| author | |
| committer | |
| log | 4aed7ea6f89a091aede10ccf0fb45b3ce12c710d |
| tree | 1e29f13ad17bfc841c33f6ac3d0ccb092404f409 |
| parent | 48cd808185f54e935714539d101585a9a0a41673 |
868 files changed, 37862 insertions(+), 10297 deletions(-)
CMakeLists.txt+99-56| ... | @@ -64,97 +64,118 @@ else() | ... | @@ -64,97 +64,118 @@ else() |
| 64 | include_directories(${LLVM_INCLUDE_DIRS}) | 64 | include_directories(${LLVM_INCLUDE_DIRS}) |
| 65 | include_directories(${CLANG_INCLUDE_DIRS}) | 65 | include_directories(${CLANG_INCLUDE_DIRS}) |
| 66 | set(EMBEDDED_LLD_LIB_SOURCES | 66 | set(EMBEDDED_LLD_LIB_SOURCES |
| 67 | "${CMAKE_SOURCE_DIR}/deps/lld/Common/Args.cpp" | ||
| 68 | "${CMAKE_SOURCE_DIR}/deps/lld/Common/ErrorHandler.cpp" | ||
| 69 | "${CMAKE_SOURCE_DIR}/deps/lld/Common/Memory.cpp" | ||
| 70 | "${CMAKE_SOURCE_DIR}/deps/lld/Common/Reproduce.cpp" | ||
| 71 | "${CMAKE_SOURCE_DIR}/deps/lld/Common/Strings.cpp" | ||
| 72 | "${CMAKE_SOURCE_DIR}/deps/lld/Common/TargetOptionsCommandFlags.cpp" | ||
| 73 | "${CMAKE_SOURCE_DIR}/deps/lld/Common/Threads.cpp" | ||
| 74 | "${CMAKE_SOURCE_DIR}/deps/lld/Common/Version.cpp" | ||
| 75 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/DefinedAtom.cpp" | ||
| 76 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Error.cpp" | ||
| 77 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/File.cpp" | ||
| 78 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/LinkingContext.cpp" | ||
| 79 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Reader.cpp" | ||
| 80 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Resolver.cpp" | ||
| 81 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/SymbolTable.cpp" | ||
| 82 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Writer.cpp" | ||
| 67 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Driver/DarwinLdDriver.cpp" | 83 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Driver/DarwinLdDriver.cpp" |
| 68 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Config/Version.cpp" | 84 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/FileArchive.cpp" |
| 69 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp" | ||
| 70 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/LayoutPass.cpp" | ||
| 71 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler.cpp" | 85 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler.cpp" |
| 86 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp" | ||
| 72 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp" | 87 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp" |
| 73 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ObjCPass.cpp" | ||
| 74 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp" | ||
| 75 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp" | ||
| 76 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp" | ||
| 77 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/TLVPass.cpp" | ||
| 78 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp" | ||
| 79 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/GOTPass.cpp" | ||
| 80 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp" | 88 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp" |
| 81 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp" | ||
| 82 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp" | 89 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp" |
| 90 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp" | ||
| 91 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/GOTPass.cpp" | ||
| 92 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/LayoutPass.cpp" | ||
| 83 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp" | 93 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp" |
| 94 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp" | ||
| 95 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp" | ||
| 96 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp" | ||
| 97 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp" | ||
| 98 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp" | ||
| 99 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ObjCPass.cpp" | ||
| 84 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ShimPass.cpp" | 100 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ShimPass.cpp" |
| 85 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/WriterMachO.cpp" | ||
| 86 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/StubsPass.cpp" | 101 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/StubsPass.cpp" |
| 87 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp" | 102 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/TLVPass.cpp" |
| 88 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp" | 103 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/WriterMachO.cpp" |
| 89 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/FileArchive.cpp" | 104 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp" |
| 90 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/TargetOptionsCommandFlags.cpp" | ||
| 91 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/File.cpp" | ||
| 92 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Error.cpp" | ||
| 93 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/SymbolTable.cpp" | ||
| 94 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Reader.cpp" | ||
| 95 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Reproduce.cpp" | ||
| 96 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Writer.cpp" | ||
| 97 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/LinkingContext.cpp" | ||
| 98 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/Resolver.cpp" | ||
| 99 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/Core/DefinedAtom.cpp" | ||
| 100 | ) | 105 | ) |
| 101 | set(EMBEDDED_LLD_ELF_SOURCES | 106 | set(EMBEDDED_LLD_ELF_SOURCES |
| 102 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ScriptLexer.cpp" | 107 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/AArch64ErrataFix.cpp" |
| 108 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/AArch64.cpp" | ||
| 103 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/AMDGPU.cpp" | 109 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/AMDGPU.cpp" |
| 104 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/PPC.cpp" | ||
| 105 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/ARM.cpp" | 110 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/ARM.cpp" |
| 106 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/AVR.cpp" | 111 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/AVR.cpp" |
| 107 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/SPARCV9.cpp" | ||
| 108 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/Mips.cpp" | 112 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/Mips.cpp" |
| 109 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/AArch64.cpp" | ||
| 110 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/X86_64.cpp" | ||
| 111 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/PPC64.cpp" | ||
| 112 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/MipsArchTree.cpp" | 113 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/MipsArchTree.cpp" |
| 114 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/PPC.cpp" | ||
| 115 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/PPC64.cpp" | ||
| 116 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/SPARCV9.cpp" | ||
| 113 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/X86.cpp" | 117 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/X86.cpp" |
| 114 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/GdbIndex.cpp" | 118 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/X86_64.cpp" |
| 115 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Driver.cpp" | 119 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Driver.cpp" |
| 116 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Relocations.cpp" | 120 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/DriverUtils.cpp" |
| 117 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Error.cpp" | ||
| 118 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/LTO.cpp" | ||
| 119 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Strings.cpp" | ||
| 120 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ScriptParser.cpp" | ||
| 121 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/MarkLive.cpp" | ||
| 122 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/SyntheticSections.cpp" | ||
| 123 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/SymbolTable.cpp" | ||
| 124 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/LinkerScript.cpp" | ||
| 125 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/EhFrame.cpp" | 121 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/EhFrame.cpp" |
| 126 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Target.cpp" | ||
| 127 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Filesystem.cpp" | 122 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Filesystem.cpp" |
| 128 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/OutputSections.cpp" | 123 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/GdbIndex.cpp" |
| 129 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Symbols.cpp" | ||
| 130 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ICF.cpp" | 124 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ICF.cpp" |
| 131 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputFiles.cpp" | 125 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputFiles.cpp" |
| 132 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Thunks.cpp" | ||
| 133 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/DriverUtils.cpp" | ||
| 134 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Writer.cpp" | ||
| 135 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputSection.cpp" | 126 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputSection.cpp" |
| 127 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/LTO.cpp" | ||
| 128 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/LinkerScript.cpp" | ||
| 136 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/MapFile.cpp" | 129 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/MapFile.cpp" |
| 130 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/MarkLive.cpp" | ||
| 131 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/OutputSections.cpp" | ||
| 132 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Relocations.cpp" | ||
| 133 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ScriptLexer.cpp" | ||
| 134 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ScriptParser.cpp" | ||
| 135 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Strings.cpp" | ||
| 136 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/SymbolTable.cpp" | ||
| 137 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Symbols.cpp" | ||
| 138 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/SyntheticSections.cpp" | ||
| 139 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Target.cpp" | ||
| 140 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Thunks.cpp" | ||
| 141 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Writer.cpp" | ||
| 137 | ) | 142 | ) |
| 143 | |||
| 138 | set(EMBEDDED_LLD_COFF_SOURCES | 144 | set(EMBEDDED_LLD_COFF_SOURCES |
| 145 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Chunks.cpp" | ||
| 139 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DLL.cpp" | 146 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DLL.cpp" |
| 140 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Driver.cpp" | 147 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Driver.cpp" |
| 141 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Chunks.cpp" | 148 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DriverUtils.cpp" |
| 142 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/PDB.cpp" | 149 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/ICF.cpp" |
| 143 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Error.cpp" | 150 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/InputFiles.cpp" |
| 144 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/LTO.cpp" | 151 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/LTO.cpp" |
| 145 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Strings.cpp" | 152 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/MapFile.cpp" |
| 146 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/MarkLive.cpp" | 153 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/MarkLive.cpp" |
| 154 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/MinGW.cpp" | ||
| 155 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/PDB.cpp" | ||
| 156 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Strings.cpp" | ||
| 147 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/SymbolTable.cpp" | 157 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/SymbolTable.cpp" |
| 148 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Symbols.cpp" | 158 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Symbols.cpp" |
| 149 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/ICF.cpp" | ||
| 150 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/InputFiles.cpp" | ||
| 151 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DriverUtils.cpp" | ||
| 152 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Writer.cpp" | 159 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Writer.cpp" |
| 153 | "${CMAKE_SOURCE_DIR}/deps/lld/COFF/MapFile.cpp" | 160 | ) |
| 161 | set(EMBEDDED_LLD_MINGW_SOURCES | ||
| 162 | "${CMAKE_SOURCE_DIR}/deps/lld/MinGW/Driver.cpp" | ||
| 163 | ) | ||
| 164 | set(EMBEDDED_LLD_WASM_SOURCES | ||
| 165 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm/Driver.cpp" | ||
| 166 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm/InputFiles.cpp" | ||
| 167 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm/InputSegment.cpp" | ||
| 168 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm/OutputSections.cpp" | ||
| 169 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm/Symbols.cpp" | ||
| 170 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm/SymbolTable.cpp" | ||
| 171 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm/Writer.cpp" | ||
| 172 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm/WriterUtils.cpp" | ||
| 154 | ) | 173 | ) |
| 155 | add_library(embedded_lld_lib ${EMBEDDED_LLD_LIB_SOURCES}) | 174 | add_library(embedded_lld_lib ${EMBEDDED_LLD_LIB_SOURCES}) |
| 156 | add_library(embedded_lld_elf ${EMBEDDED_LLD_ELF_SOURCES}) | 175 | add_library(embedded_lld_elf ${EMBEDDED_LLD_ELF_SOURCES}) |
| 157 | add_library(embedded_lld_coff ${EMBEDDED_LLD_COFF_SOURCES}) | 176 | add_library(embedded_lld_coff ${EMBEDDED_LLD_COFF_SOURCES}) |
| 177 | add_library(embedded_lld_mingw ${EMBEDDED_LLD_MINGW_SOURCES}) | ||
| 178 | add_library(embedded_lld_wasm ${EMBEDDED_LLD_WASM_SOURCES}) | ||
| 158 | if(MSVC) | 179 | if(MSVC) |
| 159 | set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w") | 180 | set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w") |
| 160 | else() | 181 | else() |
| ... | @@ -172,6 +193,14 @@ else() | ... | @@ -172,6 +193,14 @@ else() |
| 172 | COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS} | 193 | COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS} |
| 173 | LINK_FLAGS " " | 194 | LINK_FLAGS " " |
| 174 | ) | 195 | ) |
| 196 | set_target_properties(embedded_lld_mingw PROPERTIES | ||
| 197 | COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS} | ||
| 198 | LINK_FLAGS " " | ||
| 199 | ) | ||
| 200 | set_target_properties(embedded_lld_wasm PROPERTIES | ||
| 201 | COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS} | ||
| 202 | LINK_FLAGS " " | ||
| 203 | ) | ||
| 175 | target_include_directories(embedded_lld_lib PUBLIC | 204 | target_include_directories(embedded_lld_lib PUBLIC |
| 176 | "${CMAKE_SOURCE_DIR}/deps/lld/include" | 205 | "${CMAKE_SOURCE_DIR}/deps/lld/include" |
| 177 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt" | 206 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt" |
| ... | @@ -188,13 +217,27 @@ else() | ... | @@ -188,13 +217,27 @@ else() |
| 188 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt/COFF" | 217 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt/COFF" |
| 189 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt" | 218 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt" |
| 190 | ) | 219 | ) |
| 220 | target_include_directories(embedded_lld_mingw PUBLIC | ||
| 221 | "${CMAKE_SOURCE_DIR}/deps/lld/MinGW" | ||
| 222 | "${CMAKE_SOURCE_DIR}/deps/lld/include" | ||
| 223 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt/MinGW" | ||
| 224 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt" | ||
| 225 | ) | ||
| 226 | target_include_directories(embedded_lld_wasm PUBLIC | ||
| 227 | "${CMAKE_SOURCE_DIR}/deps/lld/wasm" | ||
| 228 | "${CMAKE_SOURCE_DIR}/deps/lld/include" | ||
| 229 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt/wasm" | ||
| 230 | "${CMAKE_SOURCE_DIR}/deps/lld-prebuilt" | ||
| 231 | ) | ||
| 191 | set(LLD_INCLUDE_DIRS "") | 232 | set(LLD_INCLUDE_DIRS "") |
| 192 | set(LLD_LIBRARIES | 233 | set(LLD_LIBRARIES |
| 193 | embedded_lld_elf | 234 | embedded_lld_elf |
| 194 | embedded_lld_coff | 235 | embedded_lld_coff |
| 236 | embedded_lld_mingw | ||
| 237 | embedded_lld_wasm | ||
| 195 | embedded_lld_lib | 238 | embedded_lld_lib |
| 196 | ) | 239 | ) |
| 197 | install(TARGETS embedded_lld_elf embedded_lld_coff embedded_lld_lib DESTINATION "${ZIG_CPP_LIB_DIR}") | 240 | install(TARGETS embedded_lld_elf embedded_lld_coff embedded_lld_mingw embedded_lld_wasm embedded_lld_lib DESTINATION "${ZIG_CPP_LIB_DIR}") |
| 198 | endif() | 241 | endif() |
| 199 | 242 | ||
| 200 | # No patches have been applied to SoftFloat-3d | 243 | # No patches have been applied to SoftFloat-3d |
deps/lld-prebuilt/COFF/Options.inc+61-24| ... | @@ -12,9 +12,10 @@ | ... | @@ -12,9 +12,10 @@ |
| 12 | #ifdef PREFIX | 12 | #ifdef PREFIX |
| 13 | #define COMMA , | 13 | #define COMMA , |
| 14 | PREFIX(prefix_0, {nullptr}) | 14 | PREFIX(prefix_0, {nullptr}) |
| 15 | PREFIX(prefix_3, {"--" COMMA nullptr}) | ||
| 15 | PREFIX(prefix_2, {"/" COMMA "-" COMMA nullptr}) | 16 | PREFIX(prefix_2, {"/" COMMA "-" COMMA nullptr}) |
| 16 | PREFIX(prefix_1, {"/" COMMA "-" COMMA "-?" COMMA nullptr}) | 17 | PREFIX(prefix_1, {"/" COMMA "-" COMMA "-?" COMMA nullptr}) |
| 17 | PREFIX(prefix_3, {"/?" COMMA "-?" COMMA nullptr}) | 18 | PREFIX(prefix_4, {"/?" COMMA "-?" COMMA nullptr}) |
| 18 | #undef COMMA | 19 | #undef COMMA |
| 19 | #endif // PREFIX | 20 | #endif // PREFIX |
| 20 | 21 | ||
| ... | @@ -30,19 +31,26 @@ OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullp | ... | @@ -30,19 +31,26 @@ OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullp |
| 30 | OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 31 | OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 31 | OPTION(prefix_1, "align:", align, Joined, INVALID, INVALID, nullptr, 0, 0, | 32 | OPTION(prefix_1, "align:", align, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 32 | "Section alignment", nullptr, nullptr) | 33 | "Section alignment", nullptr, nullptr) |
| 34 | OPTION(prefix_1, "aligncomm:", aligncomm, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 35 | "Set common symbol alignment", nullptr, nullptr) | ||
| 33 | OPTION(prefix_1, "allowbind:no", allowbind_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 36 | OPTION(prefix_1, "allowbind:no", allowbind_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 34 | "Disable DLL binding", nullptr, nullptr) | 37 | "Disable DLL binding", nullptr, nullptr) |
| 35 | OPTION(prefix_1, "allowbind", allowbind, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 38 | OPTION(prefix_1, "allowbind", allowbind, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 39 | "Enable DLL binding (default)", nullptr, nullptr) | ||
| 36 | OPTION(prefix_1, "allowisolation:no", allowisolation_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 40 | OPTION(prefix_1, "allowisolation:no", allowisolation_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 37 | "Set NO_ISOLATION bit", nullptr, nullptr) | 41 | "Disable DLL isolation", nullptr, nullptr) |
| 38 | OPTION(prefix_1, "allowisolation", allowisolation, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 42 | OPTION(prefix_1, "allowisolation", allowisolation, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 43 | "Enable DLL isolation (default)", nullptr, nullptr) | ||
| 39 | OPTION(prefix_1, "alternatename:", alternatename, Joined, INVALID, INVALID, nullptr, 0, 0, | 44 | OPTION(prefix_1, "alternatename:", alternatename, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 40 | "Define weak alias", nullptr, nullptr) | 45 | "Define weak alias", nullptr, nullptr) |
| 41 | OPTION(prefix_1, "appcontainer:no", appcontainer_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 46 | OPTION(prefix_1, "appcontainer:no", appcontainer_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 47 | "Image can run outside an app container (default)", nullptr, nullptr) | ||
| 48 | OPTION(prefix_1, "appcontainer", appcontainer, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 42 | "Image can only be run in an app container", nullptr, nullptr) | 49 | "Image can only be run in an app container", nullptr, nullptr) |
| 43 | OPTION(prefix_1, "appcontainer", appcontainer, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 44 | OPTION(prefix_1, "base:", base, Joined, INVALID, INVALID, nullptr, 0, 0, | 50 | OPTION(prefix_1, "base:", base, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 45 | "Base address of the program", nullptr, nullptr) | 51 | "Base address of the program", nullptr, nullptr) |
| 52 | OPTION(prefix_1, "debug:dwarf", debug_dwarf, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 53 | OPTION(prefix_1, "debug:ghash", debug_ghash, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 46 | OPTION(prefix_1, "debugtype:", debugtype, Joined, INVALID, INVALID, nullptr, 0, 0, | 54 | OPTION(prefix_1, "debugtype:", debugtype, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 47 | "Debug Info Options", nullptr, nullptr) | 55 | "Debug Info Options", nullptr, nullptr) |
| 48 | OPTION(prefix_1, "debug", debug, Flag, INVALID, INVALID, nullptr, 0, 0, | 56 | OPTION(prefix_1, "debug", debug, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -60,22 +68,25 @@ OPTION(prefix_1, "dll", dll, Flag, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -60,22 +68,25 @@ OPTION(prefix_1, "dll", dll, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 60 | OPTION(prefix_1, "driver:", driver, Joined, INVALID, INVALID, nullptr, 0, 0, | 68 | OPTION(prefix_1, "driver:", driver, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 61 | "Generate a Windows NT Kernel Mode Driver", nullptr, nullptr) | 69 | "Generate a Windows NT Kernel Mode Driver", nullptr, nullptr) |
| 62 | OPTION(prefix_1, "dynamicbase:no", dynamicbase_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 70 | OPTION(prefix_1, "dynamicbase:no", dynamicbase_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 63 | "Disable address space layout randomization", nullptr, nullptr) | 71 | "Disable ASLR (default when /fixed)", nullptr, nullptr) |
| 64 | OPTION(prefix_1, "dynamicbase", dynamicbase, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 72 | OPTION(prefix_1, "dynamicbase", dynamicbase, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 73 | "Enable ASLR (default unless /fixed)", nullptr, nullptr) | ||
| 65 | OPTION(prefix_1, "editandcontinue", editandcontinue, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 74 | OPTION(prefix_1, "editandcontinue", editandcontinue, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 66 | OPTION(prefix_1, "entry:", entry, Joined, INVALID, INVALID, nullptr, 0, 0, | 75 | OPTION(prefix_1, "entry:", entry, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 67 | "Name of entry point symbol", nullptr, nullptr) | 76 | "Name of entry point symbol", nullptr, nullptr) |
| 68 | OPTION(prefix_1, "errorlimit:", errorlimit, Joined, INVALID, INVALID, nullptr, 0, 0, | 77 | OPTION(prefix_1, "errorlimit:", errorlimit, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 69 | "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr) | 78 | "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr) |
| 70 | OPTION(prefix_1, "errorreport:", errorreport, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 79 | OPTION(prefix_1, "errorreport:", errorreport, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 80 | OPTION(prefix_1, "export-all-symbols", export_all_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 71 | OPTION(prefix_1, "export:", export, Joined, INVALID, INVALID, nullptr, 0, 0, | 81 | OPTION(prefix_1, "export:", export, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 72 | "Export a function", nullptr, nullptr) | 82 | "Export a function", nullptr, nullptr) |
| 73 | OPTION(prefix_1, "failifmismatch:", failifmismatch, Joined, INVALID, INVALID, nullptr, 0, 0, | 83 | OPTION(prefix_1, "failifmismatch:", failifmismatch, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 74 | "", nullptr, nullptr) | 84 | "", nullptr, nullptr) |
| 75 | OPTION(prefix_1, "fastfail", fastfail, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 85 | OPTION(prefix_1, "fastfail", fastfail, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 76 | OPTION(prefix_1, "fixed:no", fixed_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 86 | OPTION(prefix_1, "fixed:no", fixed_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 77 | "Enable base relocations", nullptr, nullptr) | 87 | "Enable base relocations (default)", nullptr, nullptr) |
| 78 | OPTION(prefix_1, "fixed", fixed, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 88 | OPTION(prefix_1, "fixed", fixed, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 89 | "Disable base relocations", nullptr, nullptr) | ||
| 79 | OPTION(prefix_1, "force:unresolved", force_unresolved, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 90 | OPTION(prefix_1, "force:unresolved", force_unresolved, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 80 | OPTION(prefix_1, "force", force, Flag, INVALID, INVALID, nullptr, 0, 0, | 91 | OPTION(prefix_1, "force", force, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 81 | "Allow undefined symbols when creating executables", nullptr, nullptr) | 92 | "Allow undefined symbols when creating executables", nullptr, nullptr) |
| ... | @@ -85,10 +96,12 @@ OPTION(prefix_1, "heap:", heap, Joined, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -85,10 +96,12 @@ OPTION(prefix_1, "heap:", heap, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 85 | "Size of the heap", nullptr, nullptr) | 96 | "Size of the heap", nullptr, nullptr) |
| 86 | OPTION(prefix_1, "help", help, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 97 | OPTION(prefix_1, "help", help, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 87 | OPTION(prefix_1, "highentropyva:no", highentropyva_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 98 | OPTION(prefix_1, "highentropyva:no", highentropyva_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 88 | "Set HIGH_ENTROPY_VA bit", nullptr, nullptr) | 99 | "Disable 64-bit ASLR", nullptr, nullptr) |
| 89 | OPTION(prefix_1, "highentropyva", highentropyva, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 100 | OPTION(prefix_1, "highentropyva", highentropyva, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 101 | "Enable 64-bit ASLR (default on 64-bit)", nullptr, nullptr) | ||
| 90 | OPTION(prefix_1, "idlout:", idlout, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 102 | OPTION(prefix_1, "idlout:", idlout, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 91 | OPTION(prefix_1, "ignore:", ignore, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 103 | OPTION(prefix_1, "ignore:", ignore, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 104 | "Specify warning codes to ignore", nullptr, nullptr) | ||
| 92 | OPTION(prefix_1, "ignoreidl", ignoreidl, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 105 | OPTION(prefix_1, "ignoreidl", ignoreidl, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 93 | OPTION(prefix_1, "implib:", implib, Joined, INVALID, INVALID, nullptr, 0, 0, | 106 | OPTION(prefix_1, "implib:", implib, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 94 | "Import library name", nullptr, nullptr) | 107 | "Import library name", nullptr, nullptr) |
| ... | @@ -97,14 +110,20 @@ OPTION(prefix_2, "include:", incl, Joined, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -97,14 +110,20 @@ OPTION(prefix_2, "include:", incl, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 97 | OPTION(prefix_1, "incremental:no", no_incremental, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 110 | OPTION(prefix_1, "incremental:no", no_incremental, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 98 | OPTION(prefix_1, "incremental", incremental, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 111 | OPTION(prefix_1, "incremental", incremental, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 99 | OPTION(prefix_1, "largeaddressaware:no", largeaddressaware_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 112 | OPTION(prefix_1, "largeaddressaware:no", largeaddressaware_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 100 | "Disable large addresses", nullptr, nullptr) | 113 | "Disable large addresses (default on 32-bit)", nullptr, nullptr) |
| 101 | OPTION(prefix_1, "largeaddressaware", largeaddressaware, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 114 | OPTION(prefix_1, "largeaddressaware", largeaddressaware, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 115 | "Enable large addresses (default on 64-bit)", nullptr, nullptr) | ||
| 102 | OPTION(prefix_1, "libpath:", libpath, Joined, INVALID, INVALID, nullptr, 0, 0, | 116 | OPTION(prefix_1, "libpath:", libpath, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 103 | "Additional library search path", nullptr, nullptr) | 117 | "Additional library search path", nullptr, nullptr) |
| 104 | OPTION(prefix_1, "linkrepro:", linkrepro, Joined, INVALID, INVALID, nullptr, 0, 0, | 118 | OPTION(prefix_1, "linkrepro:", linkrepro, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 105 | "Dump linker invocation and input files for debugging", nullptr, nullptr) | 119 | "Dump linker invocation and input files for debugging", nullptr, nullptr) |
| 120 | OPTION(prefix_1, "lldltocache:", lldltocache, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 121 | "Path to ThinLTO cached object file directory", nullptr, nullptr) | ||
| 122 | OPTION(prefix_1, "lldltocachepolicy:", lldltocachepolicy, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 123 | "Pruning policy for the ThinLTO cache", nullptr, nullptr) | ||
| 106 | OPTION(prefix_2, "lldmap:", lldmap_file, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 124 | OPTION(prefix_2, "lldmap:", lldmap_file, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 107 | OPTION(prefix_1, "lldmap", lldmap, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 125 | OPTION(prefix_1, "lldmap", lldmap, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 126 | OPTION(prefix_1, "lldmingw", lldmingw, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 108 | OPTION(prefix_1, "lldsavetemps", lldsavetemps, Flag, INVALID, INVALID, nullptr, 0, 0, | 127 | OPTION(prefix_1, "lldsavetemps", lldsavetemps, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 109 | "Save temporary files instead of deleting them", nullptr, nullptr) | 128 | "Save temporary files instead of deleting them", nullptr, nullptr) |
| 110 | OPTION(prefix_1, "machine:", machine, Joined, INVALID, INVALID, nullptr, 0, 0, | 129 | OPTION(prefix_1, "machine:", machine, Joined, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -126,28 +145,31 @@ OPTION(prefix_1, "merge:", merge, Joined, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -126,28 +145,31 @@ OPTION(prefix_1, "merge:", merge, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 126 | OPTION(prefix_1, "mllvm:", mllvm, Joined, INVALID, INVALID, nullptr, 0, 0, | 145 | OPTION(prefix_1, "mllvm:", mllvm, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 127 | "Options to pass to LLVM", nullptr, nullptr) | 146 | "Options to pass to LLVM", nullptr, nullptr) |
| 128 | OPTION(prefix_1, "msvclto", msvclto, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 147 | OPTION(prefix_1, "msvclto", msvclto, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 148 | OPTION(prefix_1, "natvis:", natvis, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 129 | OPTION(prefix_1, "nodefaultlib:", nodefaultlib, Joined, INVALID, INVALID, nullptr, 0, 0, | 149 | OPTION(prefix_1, "nodefaultlib:", nodefaultlib, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 130 | "Remove a default library", nullptr, nullptr) | 150 | "Remove a default library", nullptr, nullptr) |
| 131 | OPTION(prefix_1, "nodefaultlib", nodefaultlib_all, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 151 | OPTION(prefix_1, "nodefaultlib", nodefaultlib_all, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 132 | OPTION(prefix_1, "noentry", noentry, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 152 | OPTION(prefix_1, "noentry", noentry, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 133 | OPTION(prefix_1, "nologo", nologo, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 153 | OPTION(prefix_1, "nologo", nologo, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 134 | OPTION(prefix_1, "nopdb", nopdb, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 135 | "Disable PDB generation for DWARF users", nullptr, nullptr) | ||
| 136 | OPTION(prefix_1, "nosymtab", nosymtab, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 137 | OPTION(prefix_1, "nxcompat:no", nxcompat_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 154 | OPTION(prefix_1, "nxcompat:no", nxcompat_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 138 | "Disable data execution provention", nullptr, nullptr) | 155 | "Disable data execution provention", nullptr, nullptr) |
| 139 | OPTION(prefix_1, "nxcompat", nxcompat, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 156 | OPTION(prefix_1, "nxcompat", nxcompat, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 157 | "Enable data execution prevention (default)", nullptr, nullptr) | ||
| 140 | OPTION(prefix_1, "opt:", opt, Joined, INVALID, INVALID, nullptr, 0, 0, | 158 | OPTION(prefix_1, "opt:", opt, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 141 | "Control optimizations", nullptr, nullptr) | 159 | "Control optimizations", nullptr, nullptr) |
| 142 | OPTION(prefix_1, "out:", out, Joined, INVALID, INVALID, nullptr, 0, 0, | 160 | OPTION(prefix_1, "out:", out, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 143 | "Path to file to write output", nullptr, nullptr) | 161 | "Path to file to write output", nullptr, nullptr) |
| 162 | OPTION(prefix_2, "output-def:", output_def, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 144 | OPTION(prefix_1, "pdb:", pdb, Joined, INVALID, INVALID, nullptr, 0, 0, | 163 | OPTION(prefix_1, "pdb:", pdb, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 145 | "PDB file path", nullptr, nullptr) | 164 | "PDB file path", nullptr, nullptr) |
| 146 | OPTION(prefix_1, "pdbaltpath:", pdbaltpath, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 165 | OPTION(prefix_1, "pdbaltpath:", pdbaltpath, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 147 | OPTION(prefix_1, "profile", profile, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 166 | OPTION(prefix_1, "profile", profile, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 167 | OPTION(prefix_3, "rsp-quoting=", rsp_quoting, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 168 | "Quoting style for response files, 'windows' (default) or 'posix'", nullptr, nullptr) | ||
| 148 | OPTION(prefix_1, "safeseh:no", safeseh_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 169 | OPTION(prefix_1, "safeseh:no", safeseh_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 149 | "Produce an image with Safe Exception Handler", nullptr, nullptr) | 170 | "Don't produce an image with Safe Exception Handler", nullptr, nullptr) |
| 150 | OPTION(prefix_1, "safeseh", safeseh, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 171 | OPTION(prefix_1, "safeseh", safeseh, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 172 | "Produce an image with Safe Exception Handler (only for x86)", nullptr, nullptr) | ||
| 151 | OPTION(prefix_1, "section:", section, Joined, INVALID, INVALID, nullptr, 0, 0, | 173 | OPTION(prefix_1, "section:", section, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 152 | "Specify section attributes", nullptr, nullptr) | 174 | "Specify section attributes", nullptr, nullptr) |
| 153 | OPTION(prefix_1, "stack:", stack, Joined, INVALID, INVALID, nullptr, 0, 0, | 175 | OPTION(prefix_1, "stack:", stack, Joined, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -163,12 +185,27 @@ OPTION(prefix_1, "tlbid:", tlbid, Joined, INVALID, INVALID, nullptr, 0, 0, nullp | ... | @@ -163,12 +185,27 @@ OPTION(prefix_1, "tlbid:", tlbid, Joined, INVALID, INVALID, nullptr, 0, 0, nullp |
| 163 | OPTION(prefix_1, "tlbout:", tlbout, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 185 | OPTION(prefix_1, "tlbout:", tlbout, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 164 | OPTION(prefix_1, "tsaware:no", tsaware_no, Flag, INVALID, INVALID, nullptr, 0, 0, | 186 | OPTION(prefix_1, "tsaware:no", tsaware_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 165 | "Create non-Terminal Server aware executable", nullptr, nullptr) | 187 | "Create non-Terminal Server aware executable", nullptr, nullptr) |
| 166 | OPTION(prefix_1, "tsaware", tsaware, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 188 | OPTION(prefix_1, "tsaware", tsaware, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 189 | "Create Terminal Server aware executable (default)", nullptr, nullptr) | ||
| 167 | OPTION(prefix_1, "verbose:", verbose_all, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 190 | OPTION(prefix_1, "verbose:", verbose_all, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 168 | OPTION(prefix_1, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 191 | OPTION(prefix_1, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 169 | OPTION(prefix_1, "version:", version, Joined, INVALID, INVALID, nullptr, 0, 0, | 192 | OPTION(prefix_1, "version:", version, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 170 | "Specify a version number in the PE header", nullptr, nullptr) | 193 | "Specify a version number in the PE header", nullptr, nullptr) |
| 171 | OPTION(prefix_1, "wx:no", wx_no, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 194 | OPTION(prefix_3, "version", dash_dash_version, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 172 | OPTION(prefix_1, "wx", wx, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 195 | "Print version information", nullptr, nullptr) |
| 173 | OPTION(prefix_3, "", help_q, Flag, INVALID, help, nullptr, 0, 0, nullptr, nullptr, nullptr) | 196 | OPTION(prefix_1, "wholearchive:", wholearchive_file, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 197 | "Include all object files from this archive", nullptr, nullptr) | ||
| 198 | OPTION(prefix_1, "wholearchive", wholearchive_flag, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 199 | OPTION(prefix_1, "WX:no", WX_no, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 200 | "Don't treat warnings as errors", nullptr, nullptr) | ||
| 201 | OPTION(prefix_1, "WX", WX, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 202 | "Treat warnings as errors", nullptr, nullptr) | ||
| 203 | OPTION(prefix_4, "", help_q, Flag, INVALID, help, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 174 | #endif // OPTION | 204 | #endif // OPTION |
| 205 | |||
| 206 | #ifdef OPTTABLE_ARG_INIT | ||
| 207 | ////////// | ||
| 208 | // Option Values | ||
| 209 | |||
| 210 | |||
| 211 | #endif // OPTTABLE_ARG_INIT |
deps/lld-prebuilt/DarwinLdOptions.inc+7| ... | @@ -187,3 +187,10 @@ OPTION(prefix_1, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -187,3 +187,10 @@ OPTION(prefix_1, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 187 | OPTION(prefix_1, "Z", Z, Flag, INVALID, INVALID, nullptr, 0, 0, | 187 | OPTION(prefix_1, "Z", Z, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 188 | "Do not search standard directories for libraries or frameworks", nullptr, nullptr) | 188 | "Do not search standard directories for libraries or frameworks", nullptr, nullptr) |
| 189 | #endif // OPTION | 189 | #endif // OPTION |
| 190 | |||
| 191 | #ifdef OPTTABLE_ARG_INIT | ||
| 192 | ////////// | ||
| 193 | // Option Values | ||
| 194 | |||
| 195 | |||
| 196 | #endif // OPTTABLE_ARG_INIT |
deps/lld-prebuilt/ELF/Options.inc+124-46| ... | @@ -52,19 +52,23 @@ OPTION(prefix_2, "build-id", build_id, Flag, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -52,19 +52,23 @@ OPTION(prefix_2, "build-id", build_id, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 52 | "Generate build ID note", nullptr, nullptr) | 52 | "Generate build ID note", nullptr, nullptr) |
| 53 | OPTION(prefix_2, "b", alias_format_b, Separate, INVALID, format, nullptr, 0, 0, nullptr, nullptr, nullptr) | 53 | OPTION(prefix_2, "b", alias_format_b, Separate, INVALID, format, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 54 | OPTION(prefix_2, "call_shared", alias_Bdynamic_call_shared, Flag, INVALID, Bdynamic, nullptr, 0, 0, nullptr, nullptr, nullptr) | 54 | OPTION(prefix_2, "call_shared", alias_Bdynamic_call_shared, Flag, INVALID, Bdynamic, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 55 | OPTION(prefix_2, "chroot", chroot, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 55 | OPTION(prefix_2, "color-diagnostics=", color_diagnostics_eq, Joined, INVALID, INVALID, nullptr, 0, 0, | 56 | OPTION(prefix_2, "color-diagnostics=", color_diagnostics_eq, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 56 | "Use colors in diagnostics", nullptr, nullptr) | 57 | "Use colors in diagnostics", nullptr, nullptr) |
| 57 | OPTION(prefix_2, "color-diagnostics", color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, | 58 | OPTION(prefix_2, "color-diagnostics", color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 58 | "Use colors in diagnostics", nullptr, nullptr) | 59 | "Use colors in diagnostics", nullptr, nullptr) |
| 59 | OPTION(prefix_2, "compress-debug-sections=", compress_debug_sections, Joined, INVALID, INVALID, nullptr, 0, 0, | 60 | OPTION(prefix_2, "compress-debug-sections=", compress_debug_sections_eq, Joined, INVALID, compress_debug_sections, nullptr, 0, 0, |
| 60 | "Compress DWARF debug sections", nullptr, nullptr) | 61 | "Compress DWARF debug sections", nullptr, nullptr) |
| 61 | OPTION(prefix_3, "cref", cref, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 62 | OPTION(prefix_2, "compress-debug-sections", compress_debug_sections, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 63 | "Compress DWARF debug sections", nullptr, nullptr) | ||
| 64 | OPTION(prefix_2, "cref", cref, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 62 | OPTION(prefix_2, "dc", alias_define_common_dc, Flag, INVALID, define_common, nullptr, 0, 0, nullptr, nullptr, nullptr) | 65 | OPTION(prefix_2, "dc", alias_define_common_dc, Flag, INVALID, define_common, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 63 | OPTION(prefix_2, "define-common", define_common, Flag, INVALID, INVALID, nullptr, 0, 0, | 66 | OPTION(prefix_2, "define-common", define_common, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 64 | "Assign space to common symbols", nullptr, nullptr) | 67 | "Assign space to common symbols", nullptr, nullptr) |
| 65 | OPTION(prefix_2, "defsym=", defsym, Joined, INVALID, INVALID, nullptr, 0, 0, | 68 | OPTION(prefix_2, "defsym=", defsym_eq, Joined, INVALID, defsym, nullptr, 0, 0, |
| 69 | "Define a symbol alias", nullptr, nullptr) | ||
| 70 | OPTION(prefix_2, "defsym", defsym, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 66 | "Define a symbol alias", nullptr, nullptr) | 71 | "Define a symbol alias", nullptr, nullptr) |
| 67 | OPTION(prefix_2, "defsym", alias_defsym, Separate, INVALID, defsym, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 68 | OPTION(prefix_2, "demangle", demangle, Flag, INVALID, INVALID, nullptr, 0, 0, | 72 | OPTION(prefix_2, "demangle", demangle, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 69 | "Demangle symbol names", nullptr, nullptr) | 73 | "Demangle symbol names", nullptr, nullptr) |
| 70 | OPTION(prefix_2, "detect-odr-violations", detect_odr_violations, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 74 | OPTION(prefix_2, "detect-odr-violations", detect_odr_violations, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| ... | @@ -81,7 +85,8 @@ OPTION(prefix_2, "dn", alias_Bstatic_dn, Flag, INVALID, Bstatic, nullptr, 0, 0, | ... | @@ -81,7 +85,8 @@ OPTION(prefix_2, "dn", alias_Bstatic_dn, Flag, INVALID, Bstatic, nullptr, 0, 0, |
| 81 | OPTION(prefix_2, "dp", alias_define_common_dp, Flag, INVALID, define_common, nullptr, 0, 0, nullptr, nullptr, nullptr) | 85 | OPTION(prefix_2, "dp", alias_define_common_dp, Flag, INVALID, define_common, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 82 | OPTION(prefix_2, "dynamic-linker", dynamic_linker, Separate, INVALID, INVALID, nullptr, 0, 0, | 86 | OPTION(prefix_2, "dynamic-linker", dynamic_linker, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 83 | "Which dynamic linker to use", nullptr, nullptr) | 87 | "Which dynamic linker to use", nullptr, nullptr) |
| 84 | OPTION(prefix_2, "dynamic-list=", alias_dynamic_list, Joined, INVALID, dynamic_list, nullptr, 0, 0, nullptr, nullptr, nullptr) | 88 | OPTION(prefix_2, "dynamic-list=", dynamic_list_eq, Joined, INVALID, dynamic_list, nullptr, 0, 0, |
| 89 | "Read a list of dynamic symbols", nullptr, nullptr) | ||
| 85 | OPTION(prefix_2, "dynamic-list", dynamic_list, Separate, INVALID, INVALID, nullptr, 0, 0, | 90 | OPTION(prefix_2, "dynamic-list", dynamic_list, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 86 | "Read a list of dynamic symbols", nullptr, nullptr) | 91 | "Read a list of dynamic symbols", nullptr, nullptr) |
| 87 | OPTION(prefix_2, "dy", alias_Bdynamic_dy, Flag, INVALID, Bdynamic, nullptr, 0, 0, nullptr, nullptr, nullptr) | 92 | OPTION(prefix_2, "dy", alias_Bdynamic_dy, Flag, INVALID, Bdynamic, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| ... | @@ -97,18 +102,22 @@ OPTION(prefix_2, "enable-new-dtags", enable_new_dtags, Flag, INVALID, INVALID, n | ... | @@ -97,18 +102,22 @@ OPTION(prefix_2, "enable-new-dtags", enable_new_dtags, Flag, INVALID, INVALID, n |
| 97 | OPTION(prefix_2, "end-group", end_group, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 102 | OPTION(prefix_2, "end-group", end_group, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 98 | OPTION(prefix_2, "end-lib", end_lib, Flag, INVALID, INVALID, nullptr, 0, 0, | 103 | OPTION(prefix_2, "end-lib", end_lib, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 99 | "End a grouping of objects that should be treated as if they were together in an archive", nullptr, nullptr) | 104 | "End a grouping of objects that should be treated as if they were together in an archive", nullptr, nullptr) |
| 100 | OPTION(prefix_2, "entry=", alias_entry_entry, Joined, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | 105 | OPTION(prefix_2, "entry=", entry_eq, Joined, INVALID, entry, nullptr, 0, 0, |
| 106 | "Name of entry point symbol", "<entry>", nullptr) | ||
| 101 | OPTION(prefix_2, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0, | 107 | OPTION(prefix_2, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 102 | "Name of entry point symbol", "<entry>", nullptr) | 108 | "Name of entry point symbol", "<entry>", nullptr) |
| 103 | OPTION(prefix_2, "error-limit=", alias_error_limit, Joined, INVALID, error_limit, nullptr, 0, 0, nullptr, nullptr, nullptr) | 109 | OPTION(prefix_2, "error-limit=", error_limit_eq, Joined, INVALID, error_limit, nullptr, 0, 0, |
| 110 | "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr) | ||
| 104 | OPTION(prefix_2, "error-limit", error_limit, Separate, INVALID, INVALID, nullptr, 0, 0, | 111 | OPTION(prefix_2, "error-limit", error_limit, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 105 | "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr) | 112 | "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr) |
| 106 | OPTION(prefix_2, "error-unresolved-symbols", error_unresolved_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, | 113 | OPTION(prefix_2, "error-unresolved-symbols", error_unresolved_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 107 | "Report unresolved symbols as errors", nullptr, nullptr) | 114 | "Report unresolved symbols as errors", nullptr, nullptr) |
| 108 | OPTION(prefix_2, "exclude-libs=", alias_exclude_libs, Joined, INVALID, exclude_libs, nullptr, 0, 0, nullptr, nullptr, nullptr) | 115 | OPTION(prefix_2, "exclude-libs=", exclude_libs_eq, Joined, INVALID, exclude_libs, nullptr, 0, 0, |
| 116 | "Exclude static libraries from automatic export", nullptr, nullptr) | ||
| 109 | OPTION(prefix_2, "exclude-libs", exclude_libs, Separate, INVALID, INVALID, nullptr, 0, 0, | 117 | OPTION(prefix_2, "exclude-libs", exclude_libs, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 110 | "Exclude static libraries from automatic export", nullptr, nullptr) | 118 | "Exclude static libraries from automatic export", nullptr, nullptr) |
| 111 | OPTION(prefix_2, "export-dynamic-symbol=", alias_export_dynamic_symbol, Joined, INVALID, export_dynamic_symbol, nullptr, 0, 0, nullptr, nullptr, nullptr) | 119 | OPTION(prefix_2, "export-dynamic-symbol=", export_dynamic_symbol_eq, Joined, INVALID, export_dynamic_symbol, nullptr, 0, 0, |
| 120 | "Put a symbol in the dynamic symbol table", nullptr, nullptr) | ||
| 112 | OPTION(prefix_2, "export-dynamic-symbol", export_dynamic_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, | 121 | OPTION(prefix_2, "export-dynamic-symbol", export_dynamic_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 113 | "Put a symbol in the dynamic symbol table", nullptr, nullptr) | 122 | "Put a symbol in the dynamic symbol table", nullptr, nullptr) |
| 114 | OPTION(prefix_2, "export-dynamic", export_dynamic, Flag, INVALID, INVALID, nullptr, 0, 0, | 123 | OPTION(prefix_2, "export-dynamic", export_dynamic, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -117,12 +126,19 @@ OPTION(prefix_1, "E", alias_export_dynamic_E, Flag, INVALID, export_dynamic, nul | ... | @@ -117,12 +126,19 @@ OPTION(prefix_1, "E", alias_export_dynamic_E, Flag, INVALID, export_dynamic, nul |
| 117 | OPTION(prefix_1, "e", alias_entry_e, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | 126 | OPTION(prefix_1, "e", alias_entry_e, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 118 | OPTION(prefix_2, "fatal-warnings", fatal_warnings, Flag, INVALID, INVALID, nullptr, 0, 0, | 127 | OPTION(prefix_2, "fatal-warnings", fatal_warnings, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 119 | "Treat warnings as errors", nullptr, nullptr) | 128 | "Treat warnings as errors", nullptr, nullptr) |
| 120 | OPTION(prefix_2, "filter=", filter, Joined, INVALID, INVALID, nullptr, 0, 0, | 129 | OPTION(prefix_2, "filter=", filter_eq, Joined, INVALID, filter, nullptr, 0, 0, |
| 130 | "Set DT_FILTER field to the specified name", nullptr, nullptr) | ||
| 131 | OPTION(prefix_2, "filter", filter, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 121 | "Set DT_FILTER field to the specified name", nullptr, nullptr) | 132 | "Set DT_FILTER field to the specified name", nullptr, nullptr) |
| 122 | OPTION(prefix_2, "fini=", alias_fini_fini, Joined, INVALID, fini, nullptr, 0, 0, nullptr, nullptr, nullptr) | 133 | OPTION(prefix_2, "fini=", fini_eq, Joined, INVALID, fini, nullptr, 0, 0, |
| 134 | "Specify a finalizer function", "<symbol>", nullptr) | ||
| 123 | OPTION(prefix_2, "fini", fini, Separate, INVALID, INVALID, nullptr, 0, 0, | 135 | OPTION(prefix_2, "fini", fini, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 124 | "Specify a finalizer function", "<symbol>", nullptr) | 136 | "Specify a finalizer function", "<symbol>", nullptr) |
| 125 | OPTION(prefix_2, "format=", format, Joined, INVALID, INVALID, nullptr, 0, 0, | 137 | OPTION(prefix_2, "fix-cortex-a53-843419", fix_cortex_a53_843419, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 138 | "Apply fixes for AArch64 Cortex-A53 erratum 843419", nullptr, nullptr) | ||
| 139 | OPTION(prefix_2, "format=", format_eq, Joined, INVALID, format, nullptr, 0, 0, | ||
| 140 | "Change the input format of the inputs following this option", "<input-format>", nullptr) | ||
| 141 | OPTION(prefix_2, "format", format, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 126 | "Change the input format of the inputs following this option", "<input-format>", nullptr) | 142 | "Change the input format of the inputs following this option", "<input-format>", nullptr) |
| 127 | OPTION(prefix_2, "full-shutdown", full_shutdown, Flag, INVALID, INVALID, nullptr, 0, 0, | 143 | OPTION(prefix_2, "full-shutdown", full_shutdown, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 128 | "Perform a full shutdown instead of calling _exit", nullptr, nullptr) | 144 | "Perform a full shutdown instead of calling _exit", nullptr, nullptr) |
| ... | @@ -134,23 +150,36 @@ OPTION(prefix_2, "gdb-index", gdb_index, Flag, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -134,23 +150,36 @@ OPTION(prefix_2, "gdb-index", gdb_index, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 134 | "Generate .gdb_index section", nullptr, nullptr) | 150 | "Generate .gdb_index section", nullptr, nullptr) |
| 135 | OPTION(prefix_1, "G", G, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 151 | OPTION(prefix_1, "G", G, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 136 | OPTION(prefix_1, "g", g, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 152 | OPTION(prefix_1, "g", g, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 137 | OPTION(prefix_2, "hash-style=", alias_hash_style_hash_style, Joined, INVALID, hash_style, nullptr, 0, 0, nullptr, nullptr, nullptr) | 153 | OPTION(prefix_2, "hash-style=", hash_style_eq, Joined, INVALID, hash_style, nullptr, 0, 0, |
| 154 | "Specify hash style (sysv, gnu or both)", nullptr, nullptr) | ||
| 138 | OPTION(prefix_2, "hash-style", hash_style, Separate, INVALID, INVALID, nullptr, 0, 0, | 155 | OPTION(prefix_2, "hash-style", hash_style, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 139 | "Specify hash style (sysv, gnu or both)", nullptr, nullptr) | 156 | "Specify hash style (sysv, gnu or both)", nullptr, nullptr) |
| 140 | OPTION(prefix_2, "help", help, Flag, INVALID, INVALID, nullptr, 0, 0, | 157 | OPTION(prefix_2, "help", help, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 141 | "Print option help", nullptr, nullptr) | 158 | "Print option help", nullptr, nullptr) |
| 142 | OPTION(prefix_1, "h", alias_soname_h, JoinedOrSeparate, INVALID, soname, nullptr, 0, 0, nullptr, nullptr, nullptr) | 159 | OPTION(prefix_1, "h", alias_soname_h, JoinedOrSeparate, INVALID, soname, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 160 | OPTION(prefix_2, "icf-data", icf_data, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 161 | "Enable ICF to also fold identical read only data", nullptr, nullptr) | ||
| 143 | OPTION(prefix_2, "icf=all", icf_all, Flag, INVALID, INVALID, nullptr, 0, 0, | 162 | OPTION(prefix_2, "icf=all", icf_all, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 144 | "Enable identical code folding", nullptr, nullptr) | 163 | "Enable identical code folding", nullptr, nullptr) |
| 145 | OPTION(prefix_2, "icf=none", icf_none, Flag, INVALID, INVALID, nullptr, 0, 0, | 164 | OPTION(prefix_2, "icf=none", icf_none, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 146 | "Disable identical code folding", nullptr, nullptr) | 165 | "Disable identical code folding", nullptr, nullptr) |
| 147 | OPTION(prefix_2, "image-base=", image_base, Joined, INVALID, INVALID, nullptr, 0, 0, | 166 | OPTION(prefix_2, "image-base=", image_base_eq, Joined, INVALID, image_base, nullptr, 0, 0, |
| 148 | "Set the base address", nullptr, nullptr) | 167 | "Set the base address", nullptr, nullptr) |
| 149 | OPTION(prefix_2, "init=", alias_init_init, Joined, INVALID, init, nullptr, 0, 0, nullptr, nullptr, nullptr) | 168 | OPTION(prefix_2, "image-base", image_base, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 169 | "Set the base address", nullptr, nullptr) | ||
| 170 | OPTION(prefix_2, "init=", init_eq, Joined, INVALID, init, nullptr, 0, 0, | ||
| 171 | "Specify an initializer function", "<symbol>", nullptr) | ||
| 150 | OPTION(prefix_2, "init", init, Separate, INVALID, INVALID, nullptr, 0, 0, | 172 | OPTION(prefix_2, "init", init, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 151 | "Specify an initializer function", "<symbol>", nullptr) | 173 | "Specify an initializer function", "<symbol>", nullptr) |
| 152 | OPTION(prefix_2, "library-path=", alias_L__library_path, Joined, INVALID, L, nullptr, 0, 0, nullptr, nullptr, nullptr) | 174 | OPTION(prefix_2, "library-path=", library_path_eq, Joined, INVALID, library_path, nullptr, 0, 0, |
| 153 | OPTION(prefix_2, "library=", alias_l__library, Joined, INVALID, l, nullptr, 0, 0, nullptr, nullptr, nullptr) | 175 | "Add a directory to the library search path", "<dir>", nullptr) |
| 176 | OPTION(prefix_2, "library-path", library_path, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 177 | "Add a directory to the library search path", "<dir>", nullptr) | ||
| 178 | OPTION(prefix_2, "library=", library_eq, Joined, INVALID, library, nullptr, 0, 0, | ||
| 179 | "Root name of library to use", "<libName>", nullptr) | ||
| 180 | OPTION(prefix_2, "library", library, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 181 | "Root name of library to use", "<libName>", nullptr) | ||
| 182 | OPTION(prefix_2, "long-plt", long_plt, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 154 | OPTION(prefix_2, "lto-aa-pipeline=", lto_aa_pipeline, Joined, INVALID, INVALID, nullptr, 0, 0, | 183 | OPTION(prefix_2, "lto-aa-pipeline=", lto_aa_pipeline, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 155 | "AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes", nullptr, nullptr) | 184 | "AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes", nullptr, nullptr) |
| 156 | OPTION(prefix_2, "lto-newpm-passes=", lto_newpm_passes, Joined, INVALID, INVALID, nullptr, 0, 0, | 185 | OPTION(prefix_2, "lto-newpm-passes=", lto_newpm_passes, Joined, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -159,13 +188,14 @@ OPTION(prefix_2, "lto-O", lto_O, Joined, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -159,13 +188,14 @@ OPTION(prefix_2, "lto-O", lto_O, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 159 | "Optimization level for LTO", "<opt-level>", nullptr) | 188 | "Optimization level for LTO", "<opt-level>", nullptr) |
| 160 | OPTION(prefix_2, "lto-partitions=", lto_partitions, Joined, INVALID, INVALID, nullptr, 0, 0, | 189 | OPTION(prefix_2, "lto-partitions=", lto_partitions, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 161 | "Number of LTO codegen partitions", nullptr, nullptr) | 190 | "Number of LTO codegen partitions", nullptr, nullptr) |
| 162 | OPTION(prefix_1, "L", L, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | 191 | OPTION(prefix_1, "L", alias_library_path, JoinedOrSeparate, INVALID, library_path, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 163 | "Add a directory to the library search path", "<dir>", nullptr) | 192 | OPTION(prefix_1, "l", alias_library, JoinedOrSeparate, INVALID, library, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 164 | OPTION(prefix_1, "l", l, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | 193 | OPTION(prefix_2, "Map=", Map_eq, Joined, INVALID, Map, nullptr, 0, 0, |
| 165 | "Root name of library to use", "<libName>", nullptr) | ||
| 166 | OPTION(prefix_2, "Map=", alias_Map_eq, Joined, INVALID, Map, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 167 | OPTION(prefix_2, "Map", Map, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 168 | "Print a link map to the specified file", nullptr, nullptr) | 194 | "Print a link map to the specified file", nullptr, nullptr) |
| 195 | OPTION(prefix_2, "Map", Map, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 196 | "Print a link map to the specified file", nullptr, nullptr) | ||
| 197 | OPTION(prefix_2, "merge-exidx-entries", merge_exidx_entries, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 198 | "Enable merging .ARM.exidx entries", nullptr, nullptr) | ||
| 169 | OPTION(prefix_2, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 199 | OPTION(prefix_2, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 170 | OPTION(prefix_1, "M", alias_print_map_M, Flag, INVALID, print_map, nullptr, 0, 0, nullptr, nullptr, nullptr) | 200 | OPTION(prefix_1, "M", alias_print_map_M, Flag, INVALID, print_map, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 171 | OPTION(prefix_1, "m", m, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | 201 | OPTION(prefix_1, "m", m, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -176,21 +206,32 @@ OPTION(prefix_2, "no-as-needed", no_as_needed, Flag, INVALID, INVALID, nullptr, | ... | @@ -176,21 +206,32 @@ OPTION(prefix_2, "no-as-needed", no_as_needed, Flag, INVALID, INVALID, nullptr, |
| 176 | "Always DT_NEEDED for shared libraries", nullptr, nullptr) | 206 | "Always DT_NEEDED for shared libraries", nullptr, nullptr) |
| 177 | OPTION(prefix_2, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, | 207 | OPTION(prefix_2, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 178 | "Do not use colors in diagnostics", nullptr, nullptr) | 208 | "Do not use colors in diagnostics", nullptr, nullptr) |
| 179 | OPTION(prefix_2, "no-copy-dt-needed-entries", no_copy_dt_needed_entries, Flag, INVALID, no_add_needed, nullptr, 0, 0, nullptr, nullptr, nullptr) | 209 | OPTION(prefix_2, "no-copy-dt-needed-entries", no_copy_dt_needed_entries, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 210 | OPTION(prefix_2, "no-ctors-in-init-array", no_ctors_in_init_array, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 180 | OPTION(prefix_2, "no-define-common", no_define_common, Flag, INVALID, INVALID, nullptr, 0, 0, | 211 | OPTION(prefix_2, "no-define-common", no_define_common, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 181 | "Do not assign space to common symbols", nullptr, nullptr) | 212 | "Do not assign space to common symbols", nullptr, nullptr) |
| 182 | OPTION(prefix_2, "no-demangle", no_demangle, Flag, INVALID, INVALID, nullptr, 0, 0, | 213 | OPTION(prefix_2, "no-demangle", no_demangle, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 183 | "Do not demangle symbol names", nullptr, nullptr) | 214 | "Do not demangle symbol names", nullptr, nullptr) |
| 184 | OPTION(prefix_2, "no-dynamic-linker", no_dynamic_linker, Flag, INVALID, INVALID, nullptr, 0, 0, | 215 | OPTION(prefix_2, "no-dynamic-linker", no_dynamic_linker, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 185 | "Inhibit output of .interp section", nullptr, nullptr) | 216 | "Inhibit output of .interp section", nullptr, nullptr) |
| 217 | OPTION(prefix_2, "no-eh-frame-hdr", no_eh_frame_hdr, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 218 | "Do not create .eh_frame_hdr section", nullptr, nullptr) | ||
| 186 | OPTION(prefix_2, "no-export-dynamic", no_export_dynamic, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 219 | OPTION(prefix_2, "no-export-dynamic", no_export_dynamic, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 187 | OPTION(prefix_2, "no-fatal-warnings", no_fatal_warnings, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 220 | OPTION(prefix_2, "no-fatal-warnings", no_fatal_warnings, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 188 | OPTION(prefix_2, "no-gc-sections", no_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, | 221 | OPTION(prefix_2, "no-gc-sections", no_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 189 | "Disable garbage collection of unused sections", nullptr, nullptr) | 222 | "Disable garbage collection of unused sections", nullptr, nullptr) |
| 223 | OPTION(prefix_2, "no-gdb-index", no_gdb_index, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 224 | "Do not generate .gdb_index section", nullptr, nullptr) | ||
| 190 | OPTION(prefix_2, "no-gnu-unique", no_gnu_unique, Flag, INVALID, INVALID, nullptr, 0, 0, | 225 | OPTION(prefix_2, "no-gnu-unique", no_gnu_unique, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 191 | "Disable STB_GNU_UNIQUE symbol binding", nullptr, nullptr) | 226 | "Disable STB_GNU_UNIQUE symbol binding", nullptr, nullptr) |
| 192 | OPTION(prefix_2, "no-keep-memory", no_keep_memory, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 227 | OPTION(prefix_2, "no-keep-memory", no_keep_memory, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 228 | OPTION(prefix_2, "no-merge-exidx-entries", no_merge_exidx_entries, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 229 | "Disable merging .ARM.exidx entries", nullptr, nullptr) | ||
| 193 | OPTION(prefix_2, "no-mmap-output-file", no_mmap_output_file, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 230 | OPTION(prefix_2, "no-mmap-output-file", no_mmap_output_file, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 231 | OPTION(prefix_3, "no-omagic", no_omagic, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 232 | "Do not set the text data sections to be writable", "<magic>", nullptr) | ||
| 233 | OPTION(prefix_2, "no-print-gc-sections", no_print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 234 | "Do not list removed unused sections", nullptr, nullptr) | ||
| 194 | OPTION(prefix_2, "no-rosegment", no_rosegment, Flag, INVALID, INVALID, nullptr, 0, 0, | 235 | OPTION(prefix_2, "no-rosegment", no_rosegment, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 195 | "Do not put read-only non-executable sections in their own segment", nullptr, nullptr) | 236 | "Do not put read-only non-executable sections in their own segment", nullptr, nullptr) |
| 196 | OPTION(prefix_2, "no-threads", no_threads, Flag, INVALID, INVALID, nullptr, 0, 0, | 237 | OPTION(prefix_2, "no-threads", no_threads, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -219,17 +260,25 @@ OPTION(prefix_3, "opt-remarks-filename", opt_remarks_filename, Separate, INVALID | ... | @@ -219,17 +260,25 @@ OPTION(prefix_3, "opt-remarks-filename", opt_remarks_filename, Separate, INVALID |
| 219 | "YAML output file for optimization remarks", nullptr, nullptr) | 260 | "YAML output file for optimization remarks", nullptr, nullptr) |
| 220 | OPTION(prefix_3, "opt-remarks-with-hotness", opt_remarks_with_hotness, Flag, INVALID, INVALID, nullptr, 0, 0, | 261 | OPTION(prefix_3, "opt-remarks-with-hotness", opt_remarks_with_hotness, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 221 | "Include hotness informations in the optimization remarks file", nullptr, nullptr) | 262 | "Include hotness informations in the optimization remarks file", nullptr, nullptr) |
| 263 | OPTION(prefix_2, "orphan-handling=", orphan_handling_eq, Joined, INVALID, orphan_handling, nullptr, 0, 0, | ||
| 264 | "Control how orphan sections are handled when linker script used", nullptr, nullptr) | ||
| 265 | OPTION(prefix_2, "orphan-handling", orphan_handling, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 266 | "Control how orphan sections are handled when linker script used", nullptr, nullptr) | ||
| 222 | OPTION(prefix_3, "output=", alias_o_output, Joined, INVALID, o, nullptr, 0, 0, nullptr, nullptr, nullptr) | 267 | OPTION(prefix_3, "output=", alias_o_output, Joined, INVALID, o, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 223 | OPTION(prefix_3, "output", alias_o_output2, Separate, INVALID, o, nullptr, 0, 0, nullptr, nullptr, nullptr) | 268 | OPTION(prefix_3, "output", alias_o_output2, Separate, INVALID, o, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 224 | OPTION(prefix_1, "O", O, Joined, INVALID, INVALID, nullptr, 0, 0, | 269 | OPTION(prefix_1, "O", O, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, |
| 225 | "Optimize output file size", nullptr, nullptr) | 270 | "Optimize output file size", nullptr, nullptr) |
| 226 | OPTION(prefix_1, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | 271 | OPTION(prefix_1, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, |
| 227 | "Path to file to write output", "<path>", nullptr) | 272 | "Path to file to write output", "<path>", nullptr) |
| 273 | OPTION(prefix_2, "pack-dyn-relocs=", pack_dyn_relocs_eq, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 274 | "Pack dynamic relocations in the given format (none or android)", "<format>", nullptr) | ||
| 228 | OPTION(prefix_2, "pic-executable", alias_pie_pic_executable, Flag, INVALID, pie, nullptr, 0, 0, nullptr, nullptr, nullptr) | 275 | OPTION(prefix_2, "pic-executable", alias_pie_pic_executable, Flag, INVALID, pie, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 229 | OPTION(prefix_2, "pie", pie, Flag, INVALID, INVALID, nullptr, 0, 0, | 276 | OPTION(prefix_2, "pie", pie, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 230 | "Create a position independent executable", nullptr, nullptr) | 277 | "Create a position independent executable", nullptr, nullptr) |
| 231 | OPTION(prefix_2, "plugin-opt=", plugin_opt_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 278 | OPTION(prefix_2, "plugin-opt=", plugin_opt_eq, Joined, INVALID, plugin_opt, nullptr, 0, 0, |
| 232 | OPTION(prefix_2, "plugin-opt", plugin_opt, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 279 | "specifies LTO options for compatibility with GNU linkers", nullptr, nullptr) |
| 280 | OPTION(prefix_2, "plugin-opt", plugin_opt, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 281 | "specifies LTO options for compatibility with GNU linkers", nullptr, nullptr) | ||
| 233 | OPTION(prefix_2, "plugin=", plugin_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 282 | OPTION(prefix_2, "plugin=", plugin_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 234 | OPTION(prefix_2, "plugin", plugin, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 283 | OPTION(prefix_2, "plugin", plugin, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 235 | OPTION(prefix_2, "print-gc-sections", print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, | 284 | OPTION(prefix_2, "print-gc-sections", print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -240,34 +289,42 @@ OPTION(prefix_2, "Qy", Qy, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullp | ... | @@ -240,34 +289,42 @@ OPTION(prefix_2, "Qy", Qy, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullp |
| 240 | OPTION(prefix_1, "q", alias_emit_relocs, Flag, INVALID, emit_relocs, nullptr, 0, 0, nullptr, nullptr, nullptr) | 289 | OPTION(prefix_1, "q", alias_emit_relocs, Flag, INVALID, emit_relocs, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 241 | OPTION(prefix_2, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0, 0, | 290 | OPTION(prefix_2, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 242 | "Create relocatable object file", nullptr, nullptr) | 291 | "Create relocatable object file", nullptr, nullptr) |
| 243 | OPTION(prefix_2, "reproduce=", alias_reproduce_eq, Joined, INVALID, reproduce, nullptr, 0, 0, nullptr, nullptr, nullptr) | 292 | OPTION(prefix_2, "reproduce=", reproduce_eq, Joined, INVALID, reproduce, nullptr, 0, 0, |
| 293 | "Dump linker invocation and input files for debugging", nullptr, nullptr) | ||
| 244 | OPTION(prefix_2, "reproduce", reproduce, Separate, INVALID, INVALID, nullptr, 0, 0, | 294 | OPTION(prefix_2, "reproduce", reproduce, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 245 | "Dump linker invocation and input files for debugging", nullptr, nullptr) | 295 | "Dump linker invocation and input files for debugging", nullptr, nullptr) |
| 246 | OPTION(prefix_2, "retain-symbols-file=", retain_symbols_file, Joined, INVALID, INVALID, nullptr, 0, 0, | 296 | OPTION(prefix_2, "retain-symbols-file=", retain_symbols_file_eq, Joined, INVALID, retain_symbols_file, nullptr, 0, 0, |
| 297 | "Retain only the symbols listed in the file", "<file>", nullptr) | ||
| 298 | OPTION(prefix_2, "retain-symbols-file", retain_symbols_file, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 247 | "Retain only the symbols listed in the file", "<file>", nullptr) | 299 | "Retain only the symbols listed in the file", "<file>", nullptr) |
| 248 | OPTION(prefix_2, "retain-symbols-file", alias_retain_symbols_file, Separate, INVALID, retain_symbols_file, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 249 | OPTION(prefix_2, "rpath-link=", rpath_link_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 300 | OPTION(prefix_2, "rpath-link=", rpath_link_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 250 | OPTION(prefix_2, "rpath-link", rpath_link, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 301 | OPTION(prefix_2, "rpath-link", rpath_link, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 251 | OPTION(prefix_2, "rpath=", alias_rpath_rpath, Joined, INVALID, rpath, nullptr, 0, 0, nullptr, nullptr, nullptr) | 302 | OPTION(prefix_2, "rpath=", rpath_eq, Joined, INVALID, rpath, nullptr, 0, 0, |
| 303 | "Add a DT_RUNPATH to the output", nullptr, nullptr) | ||
| 252 | OPTION(prefix_2, "rpath", rpath, Separate, INVALID, INVALID, nullptr, 0, 0, | 304 | OPTION(prefix_2, "rpath", rpath, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 253 | "Add a DT_RUNPATH to the output", nullptr, nullptr) | 305 | "Add a DT_RUNPATH to the output", nullptr, nullptr) |
| 254 | OPTION(prefix_2, "rsp-quoting=", rsp_quoting, Joined, INVALID, INVALID, nullptr, 0, 0, | 306 | OPTION(prefix_2, "rsp-quoting=", rsp_quoting_eq, Joined, INVALID, rsp_quoting, nullptr, 0, 0, |
| 307 | "Quoting style for response files. Values supported: windows|posix", nullptr, nullptr) | ||
| 308 | OPTION(prefix_2, "rsp-quoting", rsp_quoting, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 255 | "Quoting style for response files. Values supported: windows|posix", nullptr, nullptr) | 309 | "Quoting style for response files. Values supported: windows|posix", nullptr, nullptr) |
| 256 | OPTION(prefix_1, "R", alias_rpath_R, JoinedOrSeparate, INVALID, rpath, nullptr, 0, 0, nullptr, nullptr, nullptr) | 310 | OPTION(prefix_1, "R", alias_rpath_R, JoinedOrSeparate, INVALID, rpath, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 257 | OPTION(prefix_1, "r", alias_relocatable_r, Flag, INVALID, relocatable, nullptr, 0, 0, nullptr, nullptr, nullptr) | 311 | OPTION(prefix_1, "r", alias_relocatable_r, Flag, INVALID, relocatable, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 258 | OPTION(prefix_2, "save-temps", save_temps, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 312 | OPTION(prefix_2, "save-temps", save_temps, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 259 | OPTION(prefix_2, "script=", alias_script, Joined, INVALID, script, nullptr, 0, 0, nullptr, nullptr, nullptr) | 313 | OPTION(prefix_2, "script=", script_eq, Joined, INVALID, script, nullptr, 0, 0, |
| 314 | "Read linker script", nullptr, nullptr) | ||
| 260 | OPTION(prefix_2, "script", script, Separate, INVALID, INVALID, nullptr, 0, 0, | 315 | OPTION(prefix_2, "script", script, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 261 | "Read linker script", nullptr, nullptr) | 316 | "Read linker script", nullptr, nullptr) |
| 262 | OPTION(prefix_2, "section-start", section_start, Separate, INVALID, INVALID, nullptr, 0, 0, | 317 | OPTION(prefix_2, "section-start", section_start, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 263 | "Set address of section", "<address>", nullptr) | 318 | "Set address of section", "<address>", nullptr) |
| 264 | OPTION(prefix_2, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0, | 319 | OPTION(prefix_2, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 265 | "Build a shared object", nullptr, nullptr) | 320 | "Build a shared object", nullptr, nullptr) |
| 266 | OPTION(prefix_2, "soname=", soname, Joined, INVALID, INVALID, nullptr, 0, 0, | 321 | OPTION(prefix_2, "soname=", soname_eq, Joined, INVALID, soname, nullptr, 0, 0, |
| 322 | "Set DT_SONAME", nullptr, nullptr) | ||
| 323 | OPTION(prefix_2, "soname", soname, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 267 | "Set DT_SONAME", nullptr, nullptr) | 324 | "Set DT_SONAME", nullptr, nullptr) |
| 268 | OPTION(prefix_2, "soname", alias_soname_soname, Separate, INVALID, soname, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 269 | OPTION(prefix_2, "sort-common", sort_common, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 325 | OPTION(prefix_2, "sort-common", sort_common, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 270 | OPTION(prefix_2, "sort-section=", alias_sort_section, Joined, INVALID, sort_section, nullptr, 0, 0, nullptr, nullptr, nullptr) | 326 | OPTION(prefix_2, "sort-section=", sort_section_eq, Joined, INVALID, sort_section, nullptr, 0, 0, |
| 327 | "Specifies sections sorting rule when linkerscript is used", nullptr, nullptr) | ||
| 271 | OPTION(prefix_2, "sort-section", sort_section, Separate, INVALID, INVALID, nullptr, 0, 0, | 328 | OPTION(prefix_2, "sort-section", sort_section, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 272 | "Specifies sections sorting rule when linkerscript is used", nullptr, nullptr) | 329 | "Specifies sections sorting rule when linkerscript is used", nullptr, nullptr) |
| 273 | OPTION(prefix_2, "start-group", start_group, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 330 | OPTION(prefix_2, "start-group", start_group, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| ... | @@ -281,7 +338,9 @@ OPTION(prefix_2, "strip-debug", strip_debug, Flag, INVALID, INVALID, nullptr, 0, | ... | @@ -281,7 +338,9 @@ OPTION(prefix_2, "strip-debug", strip_debug, Flag, INVALID, INVALID, nullptr, 0, |
| 281 | "Strip debugging information", nullptr, nullptr) | 338 | "Strip debugging information", nullptr, nullptr) |
| 282 | OPTION(prefix_2, "symbol-ordering-file", symbol_ordering_file, Separate, INVALID, INVALID, nullptr, 0, 0, | 339 | OPTION(prefix_2, "symbol-ordering-file", symbol_ordering_file, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 283 | "Layout sections in the order specified by symbol file", nullptr, nullptr) | 340 | "Layout sections in the order specified by symbol file", nullptr, nullptr) |
| 284 | OPTION(prefix_2, "sysroot=", sysroot, Joined, INVALID, INVALID, nullptr, 0, 0, | 341 | OPTION(prefix_2, "sysroot=", sysroot_eq, Joined, INVALID, sysroot, nullptr, 0, 0, |
| 342 | "Set the system root", nullptr, nullptr) | ||
| 343 | OPTION(prefix_2, "sysroot", sysroot, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 285 | "Set the system root", nullptr, nullptr) | 344 | "Set the system root", nullptr, nullptr) |
| 286 | OPTION(prefix_1, "S", alias_strip_debug_S, Flag, INVALID, strip_debug, nullptr, 0, 0, nullptr, nullptr, nullptr) | 345 | OPTION(prefix_1, "S", alias_strip_debug_S, Flag, INVALID, strip_debug, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 287 | OPTION(prefix_1, "s", alias_strip_all, Flag, INVALID, strip_all, nullptr, 0, 0, nullptr, nullptr, nullptr) | 346 | OPTION(prefix_1, "s", alias_strip_all, Flag, INVALID, strip_all, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| ... | @@ -289,12 +348,16 @@ OPTION(prefix_2, "target1-abs", target1_abs, Flag, INVALID, INVALID, nullptr, 0, | ... | @@ -289,12 +348,16 @@ OPTION(prefix_2, "target1-abs", target1_abs, Flag, INVALID, INVALID, nullptr, 0, |
| 289 | "Interpret R_ARM_TARGET1 as R_ARM_ABS32", nullptr, nullptr) | 348 | "Interpret R_ARM_TARGET1 as R_ARM_ABS32", nullptr, nullptr) |
| 290 | OPTION(prefix_2, "target1-rel", target1_rel, Flag, INVALID, INVALID, nullptr, 0, 0, | 349 | OPTION(prefix_2, "target1-rel", target1_rel, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 291 | "Interpret R_ARM_TARGET1 as R_ARM_REL32", nullptr, nullptr) | 350 | "Interpret R_ARM_TARGET1 as R_ARM_REL32", nullptr, nullptr) |
| 292 | OPTION(prefix_2, "target2=", target2, Joined, INVALID, INVALID, nullptr, 0, 0, | 351 | OPTION(prefix_2, "target2=", target2_eq, Joined, INVALID, target2, nullptr, 0, 0, |
| 352 | "Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel", "<type>", nullptr) | ||
| 353 | OPTION(prefix_2, "target2", target2, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 293 | "Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel", "<type>", nullptr) | 354 | "Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel", "<type>", nullptr) |
| 294 | OPTION(prefix_2, "Tbss=", alias_Tbss, Joined, INVALID, Tbss, nullptr, 0, 0, nullptr, nullptr, nullptr) | 355 | OPTION(prefix_2, "Tbss=", Tbss_eq, Joined, INVALID, Tbss, nullptr, 0, 0, |
| 356 | "Same as --section-start with .bss as the sectionname", nullptr, nullptr) | ||
| 295 | OPTION(prefix_2, "Tbss", Tbss, Separate, INVALID, INVALID, nullptr, 0, 0, | 357 | OPTION(prefix_2, "Tbss", Tbss, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 296 | "Same as --section-start with .bss as the sectionname", nullptr, nullptr) | 358 | "Same as --section-start with .bss as the sectionname", nullptr, nullptr) |
| 297 | OPTION(prefix_2, "Tdata=", alias_Tdata, Joined, INVALID, Tdata, nullptr, 0, 0, nullptr, nullptr, nullptr) | 359 | OPTION(prefix_2, "Tdata=", Tdata_eq, Joined, INVALID, Tdata, nullptr, 0, 0, |
| 360 | "Same as --section-start with .data as the sectionname", nullptr, nullptr) | ||
| 298 | OPTION(prefix_2, "Tdata", Tdata, Separate, INVALID, INVALID, nullptr, 0, 0, | 361 | OPTION(prefix_2, "Tdata", Tdata, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 299 | "Same as --section-start with .data as the sectionname", nullptr, nullptr) | 362 | "Same as --section-start with .data as the sectionname", nullptr, nullptr) |
| 300 | OPTION(prefix_2, "thinlto-cache-dir=", thinlto_cache_dir, Joined, INVALID, INVALID, nullptr, 0, 0, | 363 | OPTION(prefix_2, "thinlto-cache-dir=", thinlto_cache_dir, Joined, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -305,27 +368,33 @@ OPTION(prefix_2, "thinlto-jobs=", thinlto_jobs, Joined, INVALID, INVALID, nullpt | ... | @@ -305,27 +368,33 @@ OPTION(prefix_2, "thinlto-jobs=", thinlto_jobs, Joined, INVALID, INVALID, nullpt |
| 305 | "Number of ThinLTO jobs", nullptr, nullptr) | 368 | "Number of ThinLTO jobs", nullptr, nullptr) |
| 306 | OPTION(prefix_2, "threads", threads, Flag, INVALID, INVALID, nullptr, 0, 0, | 369 | OPTION(prefix_2, "threads", threads, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 307 | "Run the linker multi-threaded", nullptr, nullptr) | 370 | "Run the linker multi-threaded", nullptr, nullptr) |
| 308 | OPTION(prefix_2, "trace-symbol=", trace_trace_symbol_eq, Joined, INVALID, trace_symbol, nullptr, 0, 0, nullptr, nullptr, nullptr) | 371 | OPTION(prefix_2, "trace-symbol=", trace_symbol_eq, Joined, INVALID, trace_symbol, nullptr, 0, 0, |
| 372 | "Trace references to symbols", nullptr, nullptr) | ||
| 309 | OPTION(prefix_2, "trace-symbol", trace_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, | 373 | OPTION(prefix_2, "trace-symbol", trace_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 310 | "Trace references to symbols", nullptr, nullptr) | 374 | "Trace references to symbols", nullptr, nullptr) |
| 311 | OPTION(prefix_2, "trace", trace, Flag, INVALID, INVALID, nullptr, 0, 0, | 375 | OPTION(prefix_2, "trace", trace, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 312 | "Print the names of the input files", nullptr, nullptr) | 376 | "Print the names of the input files", nullptr, nullptr) |
| 313 | OPTION(prefix_2, "Ttext-segment=", alias_Ttext_segment_eq, Joined, INVALID, Ttext, nullptr, 0, 0, nullptr, nullptr, nullptr) | 377 | OPTION(prefix_2, "Ttext-segment=", alias_Ttext_segment_eq, Joined, INVALID, Ttext, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 314 | OPTION(prefix_2, "Ttext-segment", alias_Ttext_segment, Separate, INVALID, Ttext, nullptr, 0, 0, nullptr, nullptr, nullptr) | 378 | OPTION(prefix_2, "Ttext-segment", alias_Ttext_segment, Separate, INVALID, Ttext, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 315 | OPTION(prefix_2, "Ttext=", alias_Ttext, Joined, INVALID, Ttext, nullptr, 0, 0, nullptr, nullptr, nullptr) | 379 | OPTION(prefix_2, "Ttext=", Ttext_eq, Joined, INVALID, Ttext, nullptr, 0, 0, |
| 380 | "Same as --section-start with .text as the sectionname", nullptr, nullptr) | ||
| 316 | OPTION(prefix_2, "Ttext", Ttext, Separate, INVALID, INVALID, nullptr, 0, 0, | 381 | OPTION(prefix_2, "Ttext", Ttext, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 317 | "Same as --section-start with .text as the sectionname", nullptr, nullptr) | 382 | "Same as --section-start with .text as the sectionname", nullptr, nullptr) |
| 318 | OPTION(prefix_1, "T", alias_script_T, JoinedOrSeparate, INVALID, script, nullptr, 0, 0, nullptr, nullptr, nullptr) | 383 | OPTION(prefix_1, "T", alias_script_T, JoinedOrSeparate, INVALID, script, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 319 | OPTION(prefix_1, "t", alias_trace, Flag, INVALID, trace, nullptr, 0, 0, nullptr, nullptr, nullptr) | 384 | OPTION(prefix_1, "t", alias_trace, Flag, INVALID, trace, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 320 | OPTION(prefix_2, "undefined=", alias_undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr) | 385 | OPTION(prefix_2, "undefined=", undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0, |
| 386 | "Force undefined symbol during linking", nullptr, nullptr) | ||
| 321 | OPTION(prefix_2, "undefined", undefined, Separate, INVALID, INVALID, nullptr, 0, 0, | 387 | OPTION(prefix_2, "undefined", undefined, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 322 | "Force undefined symbol during linking", nullptr, nullptr) | 388 | "Force undefined symbol during linking", nullptr, nullptr) |
| 323 | OPTION(prefix_2, "unresolved-symbols=", unresolved_symbols, Joined, INVALID, INVALID, nullptr, 0, 0, | 389 | OPTION(prefix_2, "unresolved-symbols=", unresolved_symbols_eq, Joined, INVALID, unresolved_symbols, nullptr, 0, 0, |
| 390 | "Determine how to handle unresolved symbols", nullptr, nullptr) | ||
| 391 | OPTION(prefix_2, "unresolved-symbols", unresolved_symbols, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 324 | "Determine how to handle unresolved symbols", nullptr, nullptr) | 392 | "Determine how to handle unresolved symbols", nullptr, nullptr) |
| 325 | OPTION(prefix_1, "u", alias_undefined_u, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr) | 393 | OPTION(prefix_1, "u", alias_undefined_u, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 326 | OPTION(prefix_2, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0, | 394 | OPTION(prefix_2, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 327 | "Verbose mode", nullptr, nullptr) | 395 | "Verbose mode", nullptr, nullptr) |
| 328 | OPTION(prefix_2, "version-script=", alias_version_script_eq, Joined, INVALID, version_script, nullptr, 0, 0, nullptr, nullptr, nullptr) | 396 | OPTION(prefix_2, "version-script=", version_script_eq, Joined, INVALID, version_script, nullptr, 0, 0, |
| 397 | "Read a version script", nullptr, nullptr) | ||
| 329 | OPTION(prefix_2, "version-script", version_script, Separate, INVALID, INVALID, nullptr, 0, 0, | 398 | OPTION(prefix_2, "version-script", version_script, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 330 | "Read a version script", nullptr, nullptr) | 399 | "Read a version script", nullptr, nullptr) |
| 331 | OPTION(prefix_2, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0, | 400 | OPTION(prefix_2, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | @@ -336,12 +405,14 @@ OPTION(prefix_1, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0, | ... | @@ -336,12 +405,14 @@ OPTION(prefix_1, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 336 | OPTION(prefix_2, "warn-common", warn_common, Flag, INVALID, INVALID, nullptr, 0, 0, | 405 | OPTION(prefix_2, "warn-common", warn_common, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 337 | "Warn about duplicate common symbols", nullptr, nullptr) | 406 | "Warn about duplicate common symbols", nullptr, nullptr) |
| 338 | OPTION(prefix_2, "warn-execstack", warn_execstack, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 407 | OPTION(prefix_2, "warn-execstack", warn_execstack, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 408 | OPTION(prefix_2, "warn-once", warn_once, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 339 | OPTION(prefix_2, "warn-shared-textrel", warn_shared_textrel, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | 409 | OPTION(prefix_2, "warn-shared-textrel", warn_shared_textrel, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 340 | OPTION(prefix_2, "warn-unresolved-symbols", warn_unresolved_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, | 410 | OPTION(prefix_2, "warn-unresolved-symbols", warn_unresolved_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 341 | "Report unresolved symbols as warnings", nullptr, nullptr) | 411 | "Report unresolved symbols as warnings", nullptr, nullptr) |
| 342 | OPTION(prefix_2, "whole-archive", whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0, | 412 | OPTION(prefix_2, "whole-archive", whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 343 | "Force load of all members in a static library", nullptr, nullptr) | 413 | "Force load of all members in a static library", nullptr, nullptr) |
| 344 | OPTION(prefix_2, "wrap=", alias_wrap_wrap, Joined, INVALID, wrap, nullptr, 0, 0, nullptr, nullptr, nullptr) | 414 | OPTION(prefix_2, "wrap=", wrap_eq, Joined, INVALID, wrap, nullptr, 0, 0, |
| 415 | "Use wrapper functions for symbol", "<symbol>", nullptr) | ||
| 345 | OPTION(prefix_2, "wrap", wrap, Separate, INVALID, INVALID, nullptr, 0, 0, | 416 | OPTION(prefix_2, "wrap", wrap, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 346 | "Use wrapper functions for symbol", "<symbol>", nullptr) | 417 | "Use wrapper functions for symbol", "<symbol>", nullptr) |
| 347 | OPTION(prefix_1, "X", alias_discard_locals_X, Flag, INVALID, discard_locals, nullptr, 0, 0, nullptr, nullptr, nullptr) | 418 | OPTION(prefix_1, "X", alias_discard_locals_X, Flag, INVALID, discard_locals, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| ... | @@ -350,3 +421,10 @@ OPTION(prefix_1, "y", alias_trace_symbol_y, JoinedOrSeparate, INVALID, trace_sym | ... | @@ -350,3 +421,10 @@ OPTION(prefix_1, "y", alias_trace_symbol_y, JoinedOrSeparate, INVALID, trace_sym |
| 350 | OPTION(prefix_1, "z", z, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | 421 | OPTION(prefix_1, "z", z, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, |
| 351 | "Linker option extensions", "<option>", nullptr) | 422 | "Linker option extensions", "<option>", nullptr) |
| 352 | #endif // OPTION | 423 | #endif // OPTION |
| 424 | |||
| 425 | #ifdef OPTTABLE_ARG_INIT | ||
| 426 | ////////// | ||
| 427 | // Option Values | ||
| 428 | |||
| 429 | |||
| 430 | #endif // OPTTABLE_ARG_INIT |
deps/lld-prebuilt/MinGW/Options.inc created+114| ... | @@ -0,0 +1,114 @@ | ||
| 1 | /*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ | ||
| 2 | |* *| | ||
| 3 | |* Option Parsing Definitions *| | ||
| 4 | |* *| | ||
| 5 | |* Automatically generated file, do not edit! *| | ||
| 6 | |* *| | ||
| 7 | \*===----------------------------------------------------------------------===*/ | ||
| 8 | |||
| 9 | ///////// | ||
| 10 | // Prefixes | ||
| 11 | |||
| 12 | #ifdef PREFIX | ||
| 13 | #define COMMA , | ||
| 14 | PREFIX(prefix_0, {nullptr}) | ||
| 15 | PREFIX(prefix_1, {"-" COMMA nullptr}) | ||
| 16 | PREFIX(prefix_3, {"--" COMMA nullptr}) | ||
| 17 | PREFIX(prefix_2, {"--" COMMA "-" COMMA nullptr}) | ||
| 18 | #undef COMMA | ||
| 19 | #endif // PREFIX | ||
| 20 | |||
| 21 | ///////// | ||
| 22 | // Groups | ||
| 23 | |||
| 24 | #ifdef OPTION | ||
| 25 | |||
| 26 | ////////// | ||
| 27 | // Options | ||
| 28 | |||
| 29 | OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 30 | OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 31 | OPTION(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) | ||
| 33 | OPTION(prefix_2, "Bdynamic", Bdynamic, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 34 | "Link against shared libraries", nullptr, nullptr) | ||
| 35 | OPTION(prefix_2, "Bstatic", Bstatic, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 36 | "Do not link against shared libraries", nullptr, nullptr) | ||
| 37 | OPTION(prefix_2, "build-id", build_id, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 38 | OPTION(prefix_2, "disable-auto-image-base", disable_auto_image_base, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 39 | OPTION(prefix_2, "dynamicbase", dynamicbase, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 40 | "Enable ASLR", nullptr, nullptr) | ||
| 41 | OPTION(prefix_2, "enable-auto-image-base", enable_auto_image_base, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 42 | OPTION(prefix_2, "enable-auto-import", enable_auto_import, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 43 | OPTION(prefix_2, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 44 | "Name of entry point symbol", "<entry>", nullptr) | ||
| 45 | OPTION(prefix_2, "export-all-symbols", export_all_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 46 | "Export all symbols even if a def file or dllexport attributes are used", nullptr, nullptr) | ||
| 47 | OPTION(prefix_1, "e", alias_entry_e, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 48 | OPTION(prefix_3, "full-shutdown", full_shutdown, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 49 | OPTION(prefix_2, "gc-sections", gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 50 | "Remove unused sections", nullptr, nullptr) | ||
| 51 | OPTION(prefix_2, "high-entropy-va", high_entropy_va, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 52 | "Enable 64-bit ASLR", nullptr, nullptr) | ||
| 53 | OPTION(prefix_2, "icf=", icf, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 54 | "Identical code folding", nullptr, nullptr) | ||
| 55 | OPTION(prefix_2, "image-base", image_base, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 56 | "Base address of the program", nullptr, nullptr) | ||
| 57 | OPTION(prefix_3, "large-address-aware", large_address_aware, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 58 | "Enable large addresses", nullptr, nullptr) | ||
| 59 | OPTION(prefix_1, "L", L, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 60 | "Add a directory to the library search path", "<dir>", nullptr) | ||
| 61 | OPTION(prefix_1, "l", l, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 62 | "Root name of library to use", "<libName>", nullptr) | ||
| 63 | OPTION(prefix_2, "major-image-version", major_image_version, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 64 | OPTION(prefix_2, "minor-image-version", minor_image_version, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 65 | OPTION(prefix_2, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 66 | OPTION(prefix_1, "m", m, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 67 | "Set target emulation", nullptr, nullptr) | ||
| 68 | OPTION(prefix_2, "no-gc-sections", no_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 69 | "Don't remove unused sections", nullptr, nullptr) | ||
| 70 | OPTION(prefix_2, "no-seh", no_seh, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 71 | OPTION(prefix_2, "no-whole-archive", no_whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 72 | "No longer include all object files for following archives", nullptr, nullptr) | ||
| 73 | OPTION(prefix_2, "nxcompat", nxcompat, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 74 | "Enable data execution prevention", nullptr, nullptr) | ||
| 75 | OPTION(prefix_3, "out-implib=", out_implib_eq, Joined, INVALID, out_implib, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 76 | OPTION(prefix_3, "out-implib", out_implib, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 77 | "Import library name", nullptr, nullptr) | ||
| 78 | OPTION(prefix_2, "output-def", output_def, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 79 | "Output def file", nullptr, nullptr) | ||
| 80 | OPTION(prefix_1, "O", O, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 81 | "Optimize output file size", nullptr, nullptr) | ||
| 82 | OPTION(prefix_1, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 83 | "Path to file to write output", "<path>", nullptr) | ||
| 84 | OPTION(prefix_2, "pic-executable", pic_executable, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 85 | OPTION(prefix_2, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 86 | "Build a shared object", nullptr, nullptr) | ||
| 87 | OPTION(prefix_2, "stack", stack, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 88 | OPTION(prefix_2, "strip-all", strip_all, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 89 | "Omit all symbol information from the output binary", nullptr, nullptr) | ||
| 90 | OPTION(prefix_2, "subsystem", subs, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 91 | "Specify subsystem", nullptr, nullptr) | ||
| 92 | OPTION(prefix_2, "sysroot", sysroot, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 93 | "Sysroot", nullptr, nullptr) | ||
| 94 | OPTION(prefix_1, "s", alias_strip_s, Flag, INVALID, strip_all, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 95 | OPTION(prefix_2, "tsaware", tsaware, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 96 | "Create Terminal Server aware executable", nullptr, nullptr) | ||
| 97 | OPTION(prefix_2, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 98 | "Verbose mode", nullptr, nullptr) | ||
| 99 | OPTION(prefix_2, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 100 | "Display the version number and exit", nullptr, nullptr) | ||
| 101 | OPTION(prefix_1, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 102 | "Display the version number", nullptr, nullptr) | ||
| 103 | OPTION(prefix_2, "whole-archive", whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 104 | "Include all object files for following archives", nullptr, nullptr) | ||
| 105 | OPTION(prefix_2, "Xlink=", Xlink, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 106 | "Pass <arg> to the COFF linker", "<arg>", nullptr) | ||
| 107 | #endif // OPTION | ||
| 108 | |||
| 109 | #ifdef OPTTABLE_ARG_INIT | ||
| 110 | ////////// | ||
| 111 | // Option Values | ||
| 112 | |||
| 113 | |||
| 114 | #endif // OPTTABLE_ARG_INIT | ||
deps/lld-prebuilt/lld/Common/Version.inc created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | #define LLD_VERSION 6.0.0 | ||
| 2 | #define LLD_VERSION_STRING "6.0.0" | ||
| 3 | #define LLD_VERSION_MAJOR 6 | ||
| 4 | #define LLD_VERSION_MINOR 0 | ||
| 5 | #define LLD_REVISION_STRING "" | ||
| 6 | #define LLD_REPOSITORY_STRING "" | ||
deps/lld-prebuilt/lld/Config/Version.inc deleted-6| ... | @@ -1,6 +0,0 @@ | ||
| 1 | #define LLD_VERSION 5.0.1 | ||
| 2 | #define LLD_VERSION_STRING "5.0.1" | ||
| 3 | #define LLD_VERSION_MAJOR 5 | ||
| 4 | #define LLD_VERSION_MINOR 0 | ||
| 5 | #define LLD_REVISION_STRING "" | ||
| 6 | #define LLD_REPOSITORY_STRING "" | ||
deps/lld-prebuilt/wasm/Options.inc created+106| ... | @@ -0,0 +1,106 @@ | ||
| 1 | /*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ | ||
| 2 | |* *| | ||
| 3 | |* Option Parsing Definitions *| | ||
| 4 | |* *| | ||
| 5 | |* Automatically generated file, do not edit! *| | ||
| 6 | |* *| | ||
| 7 | \*===----------------------------------------------------------------------===*/ | ||
| 8 | |||
| 9 | ///////// | ||
| 10 | // Prefixes | ||
| 11 | |||
| 12 | #ifdef PREFIX | ||
| 13 | #define COMMA , | ||
| 14 | PREFIX(prefix_0, {nullptr}) | ||
| 15 | PREFIX(prefix_2, {"-" COMMA nullptr}) | ||
| 16 | PREFIX(prefix_1, {"--" COMMA "-" COMMA nullptr}) | ||
| 17 | #undef COMMA | ||
| 18 | #endif // PREFIX | ||
| 19 | |||
| 20 | ///////// | ||
| 21 | // Groups | ||
| 22 | |||
| 23 | #ifdef OPTION | ||
| 24 | |||
| 25 | ////////// | ||
| 26 | // Options | ||
| 27 | |||
| 28 | OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 29 | OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 30 | OPTION(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) | ||
| 32 | OPTION(prefix_2, "allow-undefined-file", allow_undefined_file_s, Separate, INVALID, allow_undefined_file, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 33 | OPTION(prefix_1, "allow-undefined", allow_undefined, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 34 | "Allow undefined symbols in linked binary", nullptr, nullptr) | ||
| 35 | OPTION(prefix_1, "check-signatures", check_signatures, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 36 | "Check function signatures", nullptr, nullptr) | ||
| 37 | OPTION(prefix_1, "color-diagnostics=", color_diagnostics_eq, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 38 | "Use colors in diagnostics", nullptr, nullptr) | ||
| 39 | OPTION(prefix_1, "color-diagnostics", color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 40 | "Use colors in diagnostics", nullptr, nullptr) | ||
| 41 | OPTION(prefix_1, "emit-relocs", emit_relocs, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 42 | "Generate relocations in output", nullptr, nullptr) | ||
| 43 | OPTION(prefix_1, "entry=", alias_entry_entry, Joined, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 44 | OPTION(prefix_1, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 45 | "Name of entry point symbol", "<entry>", nullptr) | ||
| 46 | OPTION(prefix_1, "error-limit=", error_limit, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 47 | "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr) | ||
| 48 | OPTION(prefix_2, "e", alias_entry_e, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 49 | OPTION(prefix_1, "global-base=", global_base, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 50 | "Where to start to place global data", nullptr, nullptr) | ||
| 51 | OPTION(prefix_1, "help", help, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 52 | "Print option help", nullptr, nullptr) | ||
| 53 | OPTION(prefix_1, "import-memory", import_memory, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 54 | "Import memory from the environment", nullptr, nullptr) | ||
| 55 | OPTION(prefix_1, "initial-memory=", initial_memory, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 56 | "Initial size of the linear memory", nullptr, nullptr) | ||
| 57 | OPTION(prefix_2, "i", alias_initial_memory_i, Flag, INVALID, initial_memory, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 58 | OPTION(prefix_2, "L", L, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 59 | "Add a directory to the library search path", "<dir>", nullptr) | ||
| 60 | OPTION(prefix_2, "l", l, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 61 | "Root name of library to use", "<libName>", nullptr) | ||
| 62 | OPTION(prefix_1, "max-memory=", max_memory, Joined, INVALID, INVALID, nullptr, 0, 0, | ||
| 63 | "Maximum size of the linear memory", nullptr, nullptr) | ||
| 64 | OPTION(prefix_1, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 65 | "Options to pass to LLVM", nullptr, nullptr) | ||
| 66 | OPTION(prefix_2, "m", alias_max_memory_m, Flag, INVALID, max_memory, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 67 | OPTION(prefix_1, "no-check-signatures", no_check_signatures, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 68 | "Don't check function signatures", nullptr, nullptr) | ||
| 69 | OPTION(prefix_1, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 70 | "Do not use colors in diagnostics", nullptr, nullptr) | ||
| 71 | OPTION(prefix_1, "no-entry", no_entry, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 72 | "Do not output any entry point", nullptr, nullptr) | ||
| 73 | OPTION(prefix_1, "no-threads", no_threads, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 74 | "Do not run the linker multi-threaded", nullptr, nullptr) | ||
| 75 | OPTION(prefix_2, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 76 | "Path to file to write output", "<path>", nullptr) | ||
| 77 | OPTION(prefix_1, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 78 | "Create relocatable object file", nullptr, nullptr) | ||
| 79 | OPTION(prefix_2, "r", alias_relocatable_r, Flag, INVALID, relocatable, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 80 | OPTION(prefix_1, "strip-all", strip_all, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 81 | "Strip all symbols", nullptr, nullptr) | ||
| 82 | OPTION(prefix_1, "strip-debug", strip_debug, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 83 | "Strip debugging information", nullptr, nullptr) | ||
| 84 | OPTION(prefix_1, "threads", threads, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 85 | "Run the linker multi-threaded", nullptr, nullptr) | ||
| 86 | OPTION(prefix_1, "undefined=", undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0, | ||
| 87 | "Force undefined symbol during linking", nullptr, nullptr) | ||
| 88 | OPTION(prefix_1, "undefined", undefined, Separate, INVALID, INVALID, nullptr, 0, 0, | ||
| 89 | "Force undefined symbol during linking", nullptr, nullptr) | ||
| 90 | OPTION(prefix_2, "u", alias_undefined_u, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr) | ||
| 91 | OPTION(prefix_1, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 92 | "Verbose mode", nullptr, nullptr) | ||
| 93 | OPTION(prefix_1, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 94 | "Display the version number and exit", nullptr, nullptr) | ||
| 95 | OPTION(prefix_2, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0, | ||
| 96 | "Display the version number", nullptr, nullptr) | ||
| 97 | OPTION(prefix_2, "z", z, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, | ||
| 98 | "Linker option extensions", "<option>", nullptr) | ||
| 99 | #endif // OPTION | ||
| 100 | |||
| 101 | #ifdef OPTTABLE_ARG_INIT | ||
| 102 | ////////// | ||
| 103 | // Option Values | ||
| 104 | |||
| 105 | |||
| 106 | #endif // OPTTABLE_ARG_INIT | ||
deps/lld/.arcconfig+1-1| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | { | 1 | { |
| 2 | "project_id" : "lld", | 2 | "repository.callsign" : "LLD", |
| 3 | "conduit_uri" : "https://reviews.llvm.org/" | 3 | "conduit_uri" : "https://reviews.llvm.org/" |
| 4 | } | 4 | } |
deps/lld/CMakeLists.txt+5-3| ... | @@ -160,8 +160,8 @@ endif () | ... | @@ -160,8 +160,8 @@ endif () |
| 160 | 160 | ||
| 161 | # Configure the Version.inc file. | 161 | # Configure the Version.inc file. |
| 162 | configure_file( | 162 | configure_file( |
| 163 | ${CMAKE_CURRENT_SOURCE_DIR}/include/lld/Config/Version.inc.in | 163 | ${CMAKE_CURRENT_SOURCE_DIR}/include/lld/Common/Version.inc.in |
| 164 | ${CMAKE_CURRENT_BINARY_DIR}/include/lld/Config/Version.inc) | 164 | ${CMAKE_CURRENT_BINARY_DIR}/include/lld/Common/Version.inc) |
| 165 | 165 | ||
| 166 | 166 | ||
| 167 | if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) | 167 | if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) |
| ... | @@ -210,6 +210,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) | ... | @@ -210,6 +210,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) |
| 210 | ) | 210 | ) |
| 211 | endif() | 211 | endif() |
| 212 | 212 | ||
| 213 | add_subdirectory(Common) | ||
| 213 | add_subdirectory(lib) | 214 | add_subdirectory(lib) |
| 214 | add_subdirectory(tools/lld) | 215 | add_subdirectory(tools/lld) |
| 215 | 216 | ||
| ... | @@ -221,4 +222,5 @@ endif() | ... | @@ -221,4 +222,5 @@ endif() |
| 221 | add_subdirectory(docs) | 222 | add_subdirectory(docs) |
| 222 | add_subdirectory(COFF) | 223 | add_subdirectory(COFF) |
| 223 | add_subdirectory(ELF) | 224 | add_subdirectory(ELF) |
| 224 | 225 | add_subdirectory(MinGW) | |
| 226 | add_subdirectory(wasm) |
deps/lld/CODE_OWNERS.TXT+3| ... | @@ -17,3 +17,6 @@ N: Lang Hames, Nick Kledzik | ... | @@ -17,3 +17,6 @@ N: Lang Hames, Nick Kledzik |
| 17 | E: lhames@gmail.com, kledzik@apple.com | 17 | E: lhames@gmail.com, kledzik@apple.com |
| 18 | D: Mach-O backend | 18 | D: Mach-O backend |
| 19 | 19 | ||
| 20 | N: Sam Clegg | ||
| 21 | E: sbc@chromium.org | ||
| 22 | D: WebAssembly backend (wasm/*) |
deps/lld/COFF/CMakeLists.txt+5-7| ... | @@ -11,12 +11,12 @@ add_lld_library(lldCOFF | ... | @@ -11,12 +11,12 @@ add_lld_library(lldCOFF |
| 11 | DLL.cpp | 11 | DLL.cpp |
| 12 | Driver.cpp | 12 | Driver.cpp |
| 13 | DriverUtils.cpp | 13 | DriverUtils.cpp |
| 14 | Error.cpp | ||
| 15 | ICF.cpp | 14 | ICF.cpp |
| 16 | InputFiles.cpp | 15 | InputFiles.cpp |
| 17 | LTO.cpp | 16 | LTO.cpp |
| 18 | MapFile.cpp | 17 | MapFile.cpp |
| 19 | MarkLive.cpp | 18 | MarkLive.cpp |
| 19 | MinGW.cpp | ||
| 20 | PDB.cpp | 20 | PDB.cpp |
| 21 | Strings.cpp | 21 | Strings.cpp |
| 22 | SymbolTable.cpp | 22 | SymbolTable.cpp |
| ... | @@ -26,22 +26,20 @@ add_lld_library(lldCOFF | ... | @@ -26,22 +26,20 @@ add_lld_library(lldCOFF |
| 26 | LINK_COMPONENTS | 26 | LINK_COMPONENTS |
| 27 | ${LLVM_TARGETS_TO_BUILD} | 27 | ${LLVM_TARGETS_TO_BUILD} |
| 28 | BinaryFormat | 28 | BinaryFormat |
| 29 | BitReader | ||
| 30 | Core | 29 | Core |
| 31 | DebugInfoCodeView | 30 | DebugInfoCodeView |
| 32 | DebugInfoMSF | 31 | DebugInfoMSF |
| 33 | DebugInfoPDB | 32 | DebugInfoPDB |
| 34 | LTO | ||
| 35 | LibDriver | 33 | LibDriver |
| 36 | Object | 34 | LTO |
| 37 | MC | 35 | MC |
| 38 | MCDisassembler | 36 | Object |
| 39 | Target | ||
| 40 | Option | 37 | Option |
| 41 | Support | 38 | Support |
| 39 | WindowsManifest | ||
| 42 | 40 | ||
| 43 | LINK_LIBS | 41 | LINK_LIBS |
| 44 | lldCore | 42 | lldCommon |
| 45 | ${LLVM_PTHREAD_LIB} | 43 | ${LLVM_PTHREAD_LIB} |
| 46 | 44 | ||
| 47 | DEPENDS | 45 | DEPENDS |
deps/lld/COFF/Chunks.cpp+67-32| ... | @@ -8,10 +8,10 @@ | ... | @@ -8,10 +8,10 @@ |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Chunks.h" | 10 | #include "Chunks.h" |
| 11 | #include "Error.h" | ||
| 12 | #include "InputFiles.h" | 11 | #include "InputFiles.h" |
| 13 | #include "Symbols.h" | 12 | #include "Symbols.h" |
| 14 | #include "Writer.h" | 13 | #include "Writer.h" |
| 14 | #include "lld/Common/ErrorHandler.h" | ||
| 15 | #include "llvm/ADT/Twine.h" | 15 | #include "llvm/ADT/Twine.h" |
| 16 | #include "llvm/BinaryFormat/COFF.h" | 16 | #include "llvm/BinaryFormat/COFF.h" |
| 17 | #include "llvm/Object/COFF.h" | 17 | #include "llvm/Object/COFF.h" |
| ... | @@ -29,17 +29,14 @@ using llvm::support::ulittle32_t; | ... | @@ -29,17 +29,14 @@ using llvm::support::ulittle32_t; |
| 29 | namespace lld { | 29 | namespace lld { |
| 30 | namespace coff { | 30 | namespace coff { |
| 31 | 31 | ||
| 32 | SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H) | 32 | SectionChunk::SectionChunk(ObjFile *F, const coff_section *H) |
| 33 | : Chunk(SectionKind), Repl(this), Header(H), File(F), | 33 | : Chunk(SectionKind), Repl(this), Header(H), File(F), |
| 34 | Relocs(File->getCOFFObj()->getRelocations(Header)), | 34 | Relocs(File->getCOFFObj()->getRelocations(Header)), |
| 35 | NumRelocs(std::distance(Relocs.begin(), Relocs.end())) { | 35 | NumRelocs(std::distance(Relocs.begin(), Relocs.end())) { |
| 36 | // Initialize SectionName. | 36 | // Initialize SectionName. |
| 37 | File->getCOFFObj()->getSectionName(Header, SectionName); | 37 | File->getCOFFObj()->getSectionName(Header, SectionName); |
| 38 | 38 | ||
| 39 | Align = Header->getAlignment(); | 39 | Alignment = Header->getAlignment(); |
| 40 | |||
| 41 | // Chunks may be discarded during comdat merging. | ||
| 42 | Discarded = false; | ||
| 43 | 40 | ||
| 44 | // If linker GC is disabled, every chunk starts out alive. If linker GC is | 41 | // If linker GC is disabled, every chunk starts out alive. If linker GC is |
| 45 | // enabled, treat non-comdat sections as roots. Generally optimized object | 42 | // enabled, treat non-comdat sections as roots. Generally optimized object |
| ... | @@ -62,7 +59,10 @@ static void applySecRel(const SectionChunk *Sec, uint8_t *Off, | ... | @@ -62,7 +59,10 @@ static void applySecRel(const SectionChunk *Sec, uint8_t *Off, |
| 62 | fatal("SECREL relocation cannot be applied to absolute symbols"); | 59 | fatal("SECREL relocation cannot be applied to absolute symbols"); |
| 63 | } | 60 | } |
| 64 | uint64_t SecRel = S - OS->getRVA(); | 61 | uint64_t SecRel = S - OS->getRVA(); |
| 65 | assert(SecRel < INT32_MAX && "overflow in SECREL relocation"); | 62 | if (SecRel > UINT32_MAX) { |
| 63 | error("overflow in SECREL relocation in section: " + Sec->getSectionName()); | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | add32(Off, SecRel); | 66 | add32(Off, SecRel); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| ... | @@ -119,7 +119,7 @@ static uint16_t readMOV(uint8_t *Off) { | ... | @@ -119,7 +119,7 @@ static uint16_t readMOV(uint8_t *Off) { |
| 119 | return Imm; | 119 | return Imm; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static void applyMOV32T(uint8_t *Off, uint32_t V) { | 122 | void applyMOV32T(uint8_t *Off, uint32_t V) { |
| 123 | uint16_t ImmW = readMOV(Off); // read MOVW operand | 123 | uint16_t ImmW = readMOV(Off); // read MOVW operand |
| 124 | uint16_t ImmT = readMOV(Off + 4); // read MOVT operand | 124 | uint16_t ImmT = readMOV(Off + 4); // read MOVT operand |
| 125 | uint32_t Imm = ImmW | (ImmT << 16); | 125 | uint32_t Imm = ImmW | (ImmT << 16); |
| ... | @@ -129,6 +129,8 @@ static void applyMOV32T(uint8_t *Off, uint32_t V) { | ... | @@ -129,6 +129,8 @@ static void applyMOV32T(uint8_t *Off, uint32_t V) { |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | static void applyBranch20T(uint8_t *Off, int32_t V) { | 131 | static void applyBranch20T(uint8_t *Off, int32_t V) { |
| 132 | if (!isInt<21>(V)) | ||
| 133 | fatal("relocation out of range"); | ||
| 132 | uint32_t S = V < 0 ? 1 : 0; | 134 | uint32_t S = V < 0 ? 1 : 0; |
| 133 | uint32_t J1 = (V >> 19) & 1; | 135 | uint32_t J1 = (V >> 19) & 1; |
| 134 | uint32_t J2 = (V >> 18) & 1; | 136 | uint32_t J2 = (V >> 18) & 1; |
| ... | @@ -136,7 +138,7 @@ static void applyBranch20T(uint8_t *Off, int32_t V) { | ... | @@ -136,7 +138,7 @@ static void applyBranch20T(uint8_t *Off, int32_t V) { |
| 136 | or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff)); | 138 | or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff)); |
| 137 | } | 139 | } |
| 138 | 140 | ||
| 139 | static void applyBranch24T(uint8_t *Off, int32_t V) { | 141 | void applyBranch24T(uint8_t *Off, int32_t V) { |
| 140 | if (!isInt<25>(V)) | 142 | if (!isInt<25>(V)) |
| 141 | fatal("relocation out of range"); | 143 | fatal("relocation out of range"); |
| 142 | uint32_t S = V < 0 ? 1 : 0; | 144 | uint32_t S = V < 0 ? 1 : 0; |
| ... | @@ -167,36 +169,61 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, | ... | @@ -167,36 +169,61 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, |
| 167 | } | 169 | } |
| 168 | } | 170 | } |
| 169 | 171 | ||
| 170 | static void applyArm64Addr(uint8_t *Off, uint64_t Imm) { | 172 | // Interpret the existing immediate value as a byte offset to the |
| 173 | // target symbol, then update the instruction with the immediate as | ||
| 174 | // the page offset from the current instruction to the target. | ||
| 175 | static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P) { | ||
| 176 | uint32_t Orig = read32le(Off); | ||
| 177 | uint64_t Imm = ((Orig >> 29) & 0x3) | ((Orig >> 3) & 0x1FFFFC); | ||
| 178 | S += Imm; | ||
| 179 | Imm = (S >> 12) - (P >> 12); | ||
| 171 | uint32_t ImmLo = (Imm & 0x3) << 29; | 180 | uint32_t ImmLo = (Imm & 0x3) << 29; |
| 172 | uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; | 181 | uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; |
| 173 | uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); | 182 | uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); |
| 174 | write32le(Off, (read32le(Off) & ~Mask) | ImmLo | ImmHi); | 183 | write32le(Off, (Orig & ~Mask) | ImmLo | ImmHi); |
| 175 | } | 184 | } |
| 176 | 185 | ||
| 177 | // Update the immediate field in a AARCH64 ldr, str, and add instruction. | 186 | // Update the immediate field in a AARCH64 ldr, str, and add instruction. |
| 178 | static void applyArm64Imm(uint8_t *Off, uint64_t Imm) { | 187 | // Optionally limit the range of the written immediate by one or more bits |
| 188 | // (RangeLimit). | ||
| 189 | static void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) { | ||
| 179 | uint32_t Orig = read32le(Off); | 190 | uint32_t Orig = read32le(Off); |
| 180 | Imm += (Orig >> 10) & 0xFFF; | 191 | Imm += (Orig >> 10) & 0xFFF; |
| 181 | Orig &= ~(0xFFF << 10); | 192 | Orig &= ~(0xFFF << 10); |
| 182 | write32le(Off, Orig | ((Imm & 0xFFF) << 10)); | 193 | write32le(Off, Orig | ((Imm & (0xFFF >> RangeLimit)) << 10)); |
| 183 | } | 194 | } |
| 184 | 195 | ||
| 196 | // Add the 12 bit page offset to the existing immediate. | ||
| 197 | // Ldr/str instructions store the opcode immediate scaled | ||
| 198 | // by the load/store size (giving a larger range for larger | ||
| 199 | // loads/stores). The immediate is always (both before and after | ||
| 200 | // fixing up the relocation) stored scaled similarly. | ||
| 201 | // Even if larger loads/stores have a larger range, limit the | ||
| 202 | // effective offset to 12 bit, since it is intended to be a | ||
| 203 | // page offset. | ||
| 185 | static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) { | 204 | static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) { |
| 186 | int Size = read32le(Off) >> 30; | 205 | uint32_t Orig = read32le(Off); |
| 187 | Imm >>= Size; | 206 | uint32_t Size = Orig >> 30; |
| 188 | applyArm64Imm(Off, Imm); | 207 | // 0x04000000 indicates SIMD/FP registers |
| 208 | // 0x00800000 indicates 128 bit | ||
| 209 | if ((Orig & 0x4800000) == 0x4800000) | ||
| 210 | Size += 4; | ||
| 211 | if ((Imm & ((1 << Size) - 1)) != 0) | ||
| 212 | fatal("misaligned ldr/str offset"); | ||
| 213 | applyArm64Imm(Off, Imm >> Size, Size); | ||
| 189 | } | 214 | } |
| 190 | 215 | ||
| 191 | void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, | 216 | void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, |
| 192 | uint64_t S, uint64_t P) const { | 217 | uint64_t S, uint64_t P) const { |
| 193 | switch (Type) { | 218 | switch (Type) { |
| 194 | case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, (S >> 12) - (P >> 12)); break; | 219 | case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P); break; |
| 195 | case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff); break; | 220 | case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff, 0); break; |
| 196 | case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break; | 221 | case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break; |
| 197 | case IMAGE_REL_ARM64_BRANCH26: or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break; | 222 | case IMAGE_REL_ARM64_BRANCH26: or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break; |
| 198 | case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break; | 223 | case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break; |
| 224 | case IMAGE_REL_ARM64_ADDR32NB: add32(Off, S); break; | ||
| 199 | case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break; | 225 | case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break; |
| 226 | case IMAGE_REL_ARM64_SECREL: applySecRel(this, Off, OS, S); break; | ||
| 200 | default: | 227 | default: |
| 201 | fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); | 228 | fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); |
| 202 | } | 229 | } |
| ... | @@ -224,8 +251,19 @@ void SectionChunk::writeTo(uint8_t *Buf) const { | ... | @@ -224,8 +251,19 @@ void SectionChunk::writeTo(uint8_t *Buf) const { |
| 224 | // Get the output section of the symbol for this relocation. The output | 251 | // Get the output section of the symbol for this relocation. The output |
| 225 | // section is needed to compute SECREL and SECTION relocations used in debug | 252 | // section is needed to compute SECREL and SECTION relocations used in debug |
| 226 | // info. | 253 | // info. |
| 227 | SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex); | 254 | auto *Sym = |
| 228 | Defined *Sym = cast<Defined>(Body); | 255 | dyn_cast_or_null<Defined>(File->getSymbol(Rel.SymbolTableIndex)); |
| 256 | if (!Sym) { | ||
| 257 | if (isCodeView() || isDWARF()) | ||
| 258 | continue; | ||
| 259 | // Symbols in early discarded sections are represented using null pointers, | ||
| 260 | // so we need to retrieve the name from the object file. | ||
| 261 | COFFSymbolRef Sym = | ||
| 262 | check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex)); | ||
| 263 | StringRef Name; | ||
| 264 | File->getCOFFObj()->getSymbolName(Sym, Name); | ||
| 265 | fatal("relocation against symbol in discarded section: " + Name); | ||
| 266 | } | ||
| 229 | Chunk *C = Sym->getChunk(); | 267 | Chunk *C = Sym->getChunk(); |
| 230 | OutputSection *OS = C ? C->getOutputSection() : nullptr; | 268 | OutputSection *OS = C ? C->getOutputSection() : nullptr; |
| 231 | 269 | ||
| ... | @@ -301,8 +339,8 @@ void SectionChunk::getBaserels(std::vector<Baserel> *Res) { | ... | @@ -301,8 +339,8 @@ void SectionChunk::getBaserels(std::vector<Baserel> *Res) { |
| 301 | uint8_t Ty = getBaserelType(Rel); | 339 | uint8_t Ty = getBaserelType(Rel); |
| 302 | if (Ty == IMAGE_REL_BASED_ABSOLUTE) | 340 | if (Ty == IMAGE_REL_BASED_ABSOLUTE) |
| 303 | continue; | 341 | continue; |
| 304 | SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex); | 342 | Symbol *Target = File->getSymbol(Rel.SymbolTableIndex); |
| 305 | if (isa<DefinedAbsolute>(Body)) | 343 | if (!Target || isa<DefinedAbsolute>(Target)) |
| 306 | continue; | 344 | continue; |
| 307 | Res->emplace_back(RVA + Rel.VirtualAddress, Ty); | 345 | Res->emplace_back(RVA + Rel.VirtualAddress, Ty); |
| 308 | } | 346 | } |
| ... | @@ -323,12 +361,8 @@ bool SectionChunk::isCOMDAT() const { | ... | @@ -323,12 +361,8 @@ bool SectionChunk::isCOMDAT() const { |
| 323 | void SectionChunk::printDiscardedMessage() const { | 361 | void SectionChunk::printDiscardedMessage() const { |
| 324 | // Removed by dead-stripping. If it's removed by ICF, ICF already | 362 | // Removed by dead-stripping. If it's removed by ICF, ICF already |
| 325 | // printed out the name, so don't repeat that here. | 363 | // printed out the name, so don't repeat that here. |
| 326 | if (Sym && this == Repl) { | 364 | if (Sym && this == Repl) |
| 327 | if (Discarded) | 365 | message("Discarded " + Sym->getName()); |
| 328 | message("Discarded comdat symbol " + Sym->getName()); | ||
| 329 | else if (!Live) | ||
| 330 | message("Discarded " + Sym->getName()); | ||
| 331 | } | ||
| 332 | } | 366 | } |
| 333 | 367 | ||
| 334 | StringRef SectionChunk::getDebugName() { | 368 | StringRef SectionChunk::getDebugName() { |
| ... | @@ -351,7 +385,7 @@ void SectionChunk::replace(SectionChunk *Other) { | ... | @@ -351,7 +385,7 @@ void SectionChunk::replace(SectionChunk *Other) { |
| 351 | CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) { | 385 | CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) { |
| 352 | // Common symbols are aligned on natural boundaries up to 32 bytes. | 386 | // Common symbols are aligned on natural boundaries up to 32 bytes. |
| 353 | // This is what MSVC link.exe does. | 387 | // This is what MSVC link.exe does. |
| 354 | Align = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue())); | 388 | Alignment = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue())); |
| 355 | } | 389 | } |
| 356 | 390 | ||
| 357 | uint32_t CommonChunk::getPermissions() const { | 391 | uint32_t CommonChunk::getPermissions() const { |
| ... | @@ -366,7 +400,7 @@ void StringChunk::writeTo(uint8_t *Buf) const { | ... | @@ -366,7 +400,7 @@ void StringChunk::writeTo(uint8_t *Buf) const { |
| 366 | ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) { | 400 | ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) { |
| 367 | // Intel Optimization Manual says that all branch targets | 401 | // Intel Optimization Manual says that all branch targets |
| 368 | // should be 16-byte aligned. MSVC linker does this too. | 402 | // should be 16-byte aligned. MSVC linker does this too. |
| 369 | Align = 16; | 403 | Alignment = 16; |
| 370 | } | 404 | } |
| 371 | 405 | ||
| 372 | void ImportThunkChunkX64::writeTo(uint8_t *Buf) const { | 406 | void ImportThunkChunkX64::writeTo(uint8_t *Buf) const { |
| ... | @@ -397,10 +431,9 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const { | ... | @@ -397,10 +431,9 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const { |
| 397 | } | 431 | } |
| 398 | 432 | ||
| 399 | void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const { | 433 | void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const { |
| 400 | int64_t PageOff = (ImpSymbol->getRVA() >> 12) - (RVA >> 12); | ||
| 401 | int64_t Off = ImpSymbol->getRVA() & 0xfff; | 434 | int64_t Off = ImpSymbol->getRVA() & 0xfff; |
| 402 | memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64)); | 435 | memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64)); |
| 403 | applyArm64Addr(Buf + OutputSectionOff, PageOff); | 436 | applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA); |
| 404 | applyArm64Ldr(Buf + OutputSectionOff + 4, Off); | 437 | applyArm64Ldr(Buf + OutputSectionOff + 4, Off); |
| 405 | } | 438 | } |
| 406 | 439 | ||
| ... | @@ -488,8 +521,10 @@ void BaserelChunk::writeTo(uint8_t *Buf) const { | ... | @@ -488,8 +521,10 @@ void BaserelChunk::writeTo(uint8_t *Buf) const { |
| 488 | uint8_t Baserel::getDefaultType() { | 521 | uint8_t Baserel::getDefaultType() { |
| 489 | switch (Config->Machine) { | 522 | switch (Config->Machine) { |
| 490 | case AMD64: | 523 | case AMD64: |
| 524 | case ARM64: | ||
| 491 | return IMAGE_REL_BASED_DIR64; | 525 | return IMAGE_REL_BASED_DIR64; |
| 492 | case I386: | 526 | case I386: |
| 527 | case ARMNT: | ||
| 493 | return IMAGE_REL_BASED_HIGHLOW; | 528 | return IMAGE_REL_BASED_HIGHLOW; |
| 494 | default: | 529 | default: |
| 495 | llvm_unreachable("unknown machine type"); | 530 | llvm_unreachable("unknown machine type"); |
deps/lld/COFF/Chunks.h+28-38| ... | @@ -12,7 +12,7 @@ | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | ||
| 13 | #include "Config.h" | 13 | #include "Config.h" |
| 14 | #include "InputFiles.h" | 14 | #include "InputFiles.h" |
| 15 | #include "lld/Core/LLVM.h" | 15 | #include "lld/Common/LLVM.h" |
| 16 | #include "llvm/ADT/ArrayRef.h" | 16 | #include "llvm/ADT/ArrayRef.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" |
| ... | @@ -33,9 +33,9 @@ class Baserel; | ... | @@ -33,9 +33,9 @@ class Baserel; |
| 33 | class Defined; | 33 | class Defined; |
| 34 | class DefinedImportData; | 34 | class DefinedImportData; |
| 35 | class DefinedRegular; | 35 | class DefinedRegular; |
| 36 | class ObjectFile; | 36 | class ObjFile; |
| 37 | class OutputSection; | 37 | class OutputSection; |
| 38 | class SymbolBody; | 38 | class Symbol; |
| 39 | 39 | ||
| 40 | // Mask for section types (code, data, bss, disacardable, etc.) | 40 | // Mask for section types (code, data, bss, disacardable, etc.) |
| 41 | // and permissions (writable, readable or executable). | 41 | // and permissions (writable, readable or executable). |
| ... | @@ -62,7 +62,6 @@ public: | ... | @@ -62,7 +62,6 @@ public: |
| 62 | 62 | ||
| 63 | // The writer sets and uses the addresses. | 63 | // The writer sets and uses the addresses. |
| 64 | uint64_t getRVA() const { return RVA; } | 64 | uint64_t getRVA() const { return RVA; } |
| 65 | uint32_t getAlign() const { return Align; } | ||
| 66 | void setRVA(uint64_t V) { RVA = V; } | 65 | void setRVA(uint64_t V) { RVA = V; } |
| 67 | 66 | ||
| 68 | // Returns true if this has non-zero data. BSS chunks return | 67 | // Returns true if this has non-zero data. BSS chunks return |
| ... | @@ -82,7 +81,7 @@ public: | ... | @@ -82,7 +81,7 @@ public: |
| 82 | // An output section has pointers to chunks in the section, and each | 81 | // An output section has pointers to chunks in the section, and each |
| 83 | // chunk has a back pointer to an output section. | 82 | // chunk has a back pointer to an output section. |
| 84 | void setOutputSection(OutputSection *O) { Out = O; } | 83 | void setOutputSection(OutputSection *O) { Out = O; } |
| 85 | OutputSection *getOutputSection() { return Out; } | 84 | OutputSection *getOutputSection() const { return Out; } |
| 86 | 85 | ||
| 87 | // Windows-specific. | 86 | // Windows-specific. |
| 88 | // Collect all locations that contain absolute addresses for base relocations. | 87 | // Collect all locations that contain absolute addresses for base relocations. |
| ... | @@ -92,23 +91,22 @@ public: | ... | @@ -92,23 +91,22 @@ public: |
| 92 | // bytes, so this is used only for logging or debugging. | 91 | // bytes, so this is used only for logging or debugging. |
| 93 | virtual StringRef getDebugName() { return ""; } | 92 | virtual StringRef getDebugName() { return ""; } |
| 94 | 93 | ||
| 94 | // The alignment of this chunk. The writer uses the value. | ||
| 95 | uint32_t Alignment = 1; | ||
| 96 | |||
| 95 | protected: | 97 | protected: |
| 96 | Chunk(Kind K = OtherKind) : ChunkKind(K) {} | 98 | Chunk(Kind K = OtherKind) : ChunkKind(K) {} |
| 97 | const Kind ChunkKind; | 99 | const Kind ChunkKind; |
| 98 | 100 | ||
| 99 | // The alignment of this chunk. The writer uses the value. | ||
| 100 | uint32_t Align = 1; | ||
| 101 | |||
| 102 | // The RVA of this chunk in the output. The writer sets a value. | 101 | // The RVA of this chunk in the output. The writer sets a value. |
| 103 | uint64_t RVA = 0; | 102 | uint64_t RVA = 0; |
| 104 | 103 | ||
| 104 | // The output section for this chunk. | ||
| 105 | OutputSection *Out = nullptr; | ||
| 106 | |||
| 105 | public: | 107 | public: |
| 106 | // The offset from beginning of the output section. The writer sets a value. | 108 | // The offset from beginning of the output section. The writer sets a value. |
| 107 | uint64_t OutputSectionOff = 0; | 109 | uint64_t OutputSectionOff = 0; |
| 108 | |||
| 109 | protected: | ||
| 110 | // The output section for this chunk. | ||
| 111 | OutputSection *Out = nullptr; | ||
| 112 | }; | 110 | }; |
| 113 | 111 | ||
| 114 | // A chunk corresponding a section of an input file. | 112 | // A chunk corresponding a section of an input file. |
| ... | @@ -119,23 +117,21 @@ class SectionChunk final : public Chunk { | ... | @@ -119,23 +117,21 @@ class SectionChunk final : public Chunk { |
| 119 | public: | 117 | public: |
| 120 | class symbol_iterator : public llvm::iterator_adaptor_base< | 118 | class symbol_iterator : public llvm::iterator_adaptor_base< |
| 121 | symbol_iterator, const coff_relocation *, | 119 | symbol_iterator, const coff_relocation *, |
| 122 | std::random_access_iterator_tag, SymbolBody *> { | 120 | std::random_access_iterator_tag, Symbol *> { |
| 123 | friend SectionChunk; | 121 | friend SectionChunk; |
| 124 | 122 | ||
| 125 | ObjectFile *File; | 123 | ObjFile *File; |
| 126 | 124 | ||
| 127 | symbol_iterator(ObjectFile *File, const coff_relocation *I) | 125 | symbol_iterator(ObjFile *File, const coff_relocation *I) |
| 128 | : symbol_iterator::iterator_adaptor_base(I), File(File) {} | 126 | : symbol_iterator::iterator_adaptor_base(I), File(File) {} |
| 129 | 127 | ||
| 130 | public: | 128 | public: |
| 131 | symbol_iterator() = default; | 129 | symbol_iterator() = default; |
| 132 | 130 | ||
| 133 | SymbolBody *operator*() const { | 131 | Symbol *operator*() const { return File->getSymbol(I->SymbolTableIndex); } |
| 134 | return File->getSymbolBody(I->SymbolTableIndex); | ||
| 135 | } | ||
| 136 | }; | 132 | }; |
| 137 | 133 | ||
| 138 | SectionChunk(ObjectFile *File, const coff_section *Header); | 134 | SectionChunk(ObjFile *File, const coff_section *Header); |
| 139 | static bool classof(const Chunk *C) { return C->kind() == SectionKind; } | 135 | static bool classof(const Chunk *C) { return C->kind() == SectionKind; } |
| 140 | size_t getSize() const override { return Header->SizeOfRawData; } | 136 | size_t getSize() const override { return Header->SizeOfRawData; } |
| 141 | ArrayRef<uint8_t> getContents() const; | 137 | ArrayRef<uint8_t> getContents() const; |
| ... | @@ -163,10 +159,9 @@ public: | ... | @@ -163,10 +159,9 @@ public: |
| 163 | void addAssociative(SectionChunk *Child); | 159 | void addAssociative(SectionChunk *Child); |
| 164 | 160 | ||
| 165 | StringRef getDebugName() override; | 161 | StringRef getDebugName() override; |
| 166 | void setSymbol(DefinedRegular *S) { if (!Sym) Sym = S; } | ||
| 167 | 162 | ||
| 168 | // Returns true if the chunk was not dropped by GC or COMDAT deduplication. | 163 | // Returns true if the chunk was not dropped by GC. |
| 169 | bool isLive() { return Live && !Discarded; } | 164 | bool isLive() { return Live; } |
| 170 | 165 | ||
| 171 | // Used by the garbage collector. | 166 | // Used by the garbage collector. |
| 172 | void markLive() { | 167 | void markLive() { |
| ... | @@ -175,21 +170,16 @@ public: | ... | @@ -175,21 +170,16 @@ public: |
| 175 | Live = true; | 170 | Live = true; |
| 176 | } | 171 | } |
| 177 | 172 | ||
| 178 | // Returns true if this chunk was dropped by COMDAT deduplication. | ||
| 179 | bool isDiscarded() const { return Discarded; } | ||
| 180 | |||
| 181 | // Used by the SymbolTable when discarding unused comdat sections. This is | ||
| 182 | // redundant when GC is enabled, as all comdat sections will start out dead. | ||
| 183 | void markDiscarded() { Discarded = true; } | ||
| 184 | |||
| 185 | // True if this is a codeview debug info chunk. These will not be laid out in | 173 | // True if this is a codeview debug info chunk. These will not be laid out in |
| 186 | // the image. Instead they will end up in the PDB, if one is requested. | 174 | // the image. Instead they will end up in the PDB, if one is requested. |
| 187 | bool isCodeView() const { | 175 | bool isCodeView() const { |
| 188 | return SectionName == ".debug" || SectionName.startswith(".debug$"); | 176 | return SectionName == ".debug" || SectionName.startswith(".debug$"); |
| 189 | } | 177 | } |
| 190 | 178 | ||
| 191 | // True if this is a DWARF debug info chunk. | 179 | // True if this is a DWARF debug info or exception handling chunk. |
| 192 | bool isDWARF() const { return SectionName.startswith(".debug_"); } | 180 | bool isDWARF() const { |
| 181 | return SectionName.startswith(".debug_") || SectionName == ".eh_frame"; | ||
| 182 | } | ||
| 193 | 183 | ||
| 194 | // Allow iteration over the bodies of this chunk's relocated symbols. | 184 | // Allow iteration over the bodies of this chunk's relocated symbols. |
| 195 | llvm::iterator_range<symbol_iterator> symbols() const { | 185 | llvm::iterator_range<symbol_iterator> symbols() const { |
| ... | @@ -213,7 +203,10 @@ public: | ... | @@ -213,7 +203,10 @@ public: |
| 213 | const coff_section *Header; | 203 | const coff_section *Header; |
| 214 | 204 | ||
| 215 | // The file that this chunk was created from. | 205 | // The file that this chunk was created from. |
| 216 | ObjectFile *File; | 206 | ObjFile *File; |
| 207 | |||
| 208 | // The COMDAT leader symbol if this is a COMDAT chunk. | ||
| 209 | DefinedRegular *Sym = nullptr; | ||
| 217 | 210 | ||
| 218 | private: | 211 | private: |
| 219 | StringRef SectionName; | 212 | StringRef SectionName; |
| ... | @@ -221,18 +214,12 @@ private: | ... | @@ -221,18 +214,12 @@ private: |
| 221 | llvm::iterator_range<const coff_relocation *> Relocs; | 214 | llvm::iterator_range<const coff_relocation *> Relocs; |
| 222 | size_t NumRelocs; | 215 | size_t NumRelocs; |
| 223 | 216 | ||
| 224 | // True if this chunk was discarded because it was a duplicate comdat section. | ||
| 225 | bool Discarded; | ||
| 226 | |||
| 227 | // Used by the garbage collector. | 217 | // Used by the garbage collector. |
| 228 | bool Live; | 218 | bool Live; |
| 229 | 219 | ||
| 230 | // Used for ICF (Identical COMDAT Folding) | 220 | // Used for ICF (Identical COMDAT Folding) |
| 231 | void replace(SectionChunk *Other); | 221 | void replace(SectionChunk *Other); |
| 232 | uint32_t Class[2] = {0, 0}; | 222 | uint32_t Class[2] = {0, 0}; |
| 233 | |||
| 234 | // Sym points to a section symbol if this is a COMDAT chunk. | ||
| 235 | DefinedRegular *Sym = nullptr; | ||
| 236 | }; | 223 | }; |
| 237 | 224 | ||
| 238 | // A chunk for common symbols. Common chunks don't have actual data. | 225 | // A chunk for common symbols. Common chunks don't have actual data. |
| ... | @@ -369,6 +356,9 @@ public: | ... | @@ -369,6 +356,9 @@ public: |
| 369 | uint8_t Type; | 356 | uint8_t Type; |
| 370 | }; | 357 | }; |
| 371 | 358 | ||
| 359 | void applyMOV32T(uint8_t *Off, uint32_t V); | ||
| 360 | void applyBranch24T(uint8_t *Off, int32_t V); | ||
| 361 | |||
| 372 | } // namespace coff | 362 | } // namespace coff |
| 373 | } // namespace lld | 363 | } // namespace lld |
| 374 | 364 |
deps/lld/COFF/Config.h+19-9| ... | @@ -12,6 +12,7 @@ | ... | @@ -12,6 +12,7 @@ |
| 12 | 12 | ||
| 13 | #include "llvm/ADT/StringRef.h" | 13 | #include "llvm/ADT/StringRef.h" |
| 14 | #include "llvm/Object/COFF.h" | 14 | #include "llvm/Object/COFF.h" |
| 15 | #include "llvm/Support/CachePruning.h" | ||
| 15 | #include <cstdint> | 16 | #include <cstdint> |
| 16 | #include <map> | 17 | #include <map> |
| 17 | #include <set> | 18 | #include <set> |
| ... | @@ -26,8 +27,7 @@ using llvm::StringRef; | ... | @@ -26,8 +27,7 @@ using llvm::StringRef; |
| 26 | class DefinedAbsolute; | 27 | class DefinedAbsolute; |
| 27 | class DefinedRelative; | 28 | class DefinedRelative; |
| 28 | class StringChunk; | 29 | class StringChunk; |
| 29 | struct Symbol; | 30 | class Symbol; |
| 30 | class SymbolBody; | ||
| 31 | 31 | ||
| 32 | // Short aliases. | 32 | // Short aliases. |
| 33 | static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64; | 33 | static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64; |
| ... | @@ -39,7 +39,7 @@ static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386; | ... | @@ -39,7 +39,7 @@ static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386; |
| 39 | struct Export { | 39 | struct Export { |
| 40 | StringRef Name; // N in /export:N or /export:E=N | 40 | StringRef Name; // N in /export:N or /export:E=N |
| 41 | StringRef ExtName; // E in /export:E=N | 41 | StringRef ExtName; // E in /export:E=N |
| 42 | SymbolBody *Sym = nullptr; | 42 | Symbol *Sym = nullptr; |
| 43 | uint16_t Ordinal = 0; | 43 | uint16_t Ordinal = 0; |
| 44 | bool Noname = false; | 44 | bool Noname = false; |
| 45 | bool Data = false; | 45 | bool Data = false; |
| ... | @@ -79,24 +79,23 @@ struct Configuration { | ... | @@ -79,24 +79,23 @@ struct Configuration { |
| 79 | llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN; | 79 | llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN; |
| 80 | bool Verbose = false; | 80 | bool Verbose = false; |
| 81 | WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; | 81 | WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; |
| 82 | SymbolBody *Entry = nullptr; | 82 | Symbol *Entry = nullptr; |
| 83 | bool NoEntry = false; | 83 | bool NoEntry = false; |
| 84 | std::string OutputFile; | 84 | std::string OutputFile; |
| 85 | std::string ImportName; | 85 | std::string ImportName; |
| 86 | bool ColorDiagnostics; | ||
| 87 | bool DoGC = true; | 86 | bool DoGC = true; |
| 88 | bool DoICF = true; | 87 | bool DoICF = true; |
| 89 | uint64_t ErrorLimit = 20; | ||
| 90 | bool Relocatable = true; | 88 | bool Relocatable = true; |
| 91 | bool Force = false; | 89 | bool Force = false; |
| 92 | bool Debug = false; | 90 | bool Debug = false; |
| 93 | bool WriteSymtab = true; | 91 | bool DebugDwarf = false; |
| 92 | bool DebugGHashes = false; | ||
| 94 | unsigned DebugTypes = static_cast<unsigned>(DebugType::None); | 93 | unsigned DebugTypes = static_cast<unsigned>(DebugType::None); |
| 95 | llvm::SmallString<128> PDBPath; | 94 | llvm::SmallString<128> PDBPath; |
| 96 | std::vector<llvm::StringRef> Argv; | 95 | std::vector<llvm::StringRef> Argv; |
| 97 | 96 | ||
| 98 | // Symbols in this set are considered as live by the garbage collector. | 97 | // Symbols in this set are considered as live by the garbage collector. |
| 99 | std::set<SymbolBody *> GCRoot; | 98 | std::vector<Symbol *> GCRoot; |
| 100 | 99 | ||
| 101 | std::set<StringRef> NoDefaultLibs; | 100 | std::set<StringRef> NoDefaultLibs; |
| 102 | bool NoDefaultLibAll = false; | 101 | bool NoDefaultLibAll = false; |
| ... | @@ -107,7 +106,7 @@ struct Configuration { | ... | @@ -107,7 +106,7 @@ struct Configuration { |
| 107 | std::vector<Export> Exports; | 106 | std::vector<Export> Exports; |
| 108 | std::set<std::string> DelayLoads; | 107 | std::set<std::string> DelayLoads; |
| 109 | std::map<std::string, int> DLLOrder; | 108 | std::map<std::string, int> DLLOrder; |
| 110 | SymbolBody *DelayLoadHelper = nullptr; | 109 | Symbol *DelayLoadHelper = nullptr; |
| 111 | 110 | ||
| 112 | bool SaveTemps = false; | 111 | bool SaveTemps = false; |
| 113 | 112 | ||
| ... | @@ -123,6 +122,11 @@ struct Configuration { | ... | @@ -123,6 +122,11 @@ struct Configuration { |
| 123 | // Used for /opt:lldltopartitions=N | 122 | // Used for /opt:lldltopartitions=N |
| 124 | unsigned LTOPartitions = 1; | 123 | unsigned LTOPartitions = 1; |
| 125 | 124 | ||
| 125 | // Used for /opt:lldltocache=path | ||
| 126 | StringRef LTOCache; | ||
| 127 | // Used for /opt:lldltocachepolicy=policy | ||
| 128 | llvm::CachePruningPolicy LTOCachePolicy; | ||
| 129 | |||
| 126 | // Used for /merge:from=to (e.g. /merge:.rdata=.text) | 130 | // Used for /merge:from=to (e.g. /merge:.rdata=.text) |
| 127 | std::map<StringRef, StringRef> Merge; | 131 | std::map<StringRef, StringRef> Merge; |
| 128 | 132 | ||
| ... | @@ -139,6 +143,9 @@ struct Configuration { | ... | @@ -139,6 +143,9 @@ struct Configuration { |
| 139 | StringRef ManifestUIAccess = "'false'"; | 143 | StringRef ManifestUIAccess = "'false'"; |
| 140 | StringRef ManifestFile; | 144 | StringRef ManifestFile; |
| 141 | 145 | ||
| 146 | // Used for /aligncomm. | ||
| 147 | std::map<std::string, int> AlignComm; | ||
| 148 | |||
| 142 | // Used for /failifmismatch. | 149 | // Used for /failifmismatch. |
| 143 | std::map<StringRef, StringRef> MustMatch; | 150 | std::map<StringRef, StringRef> MustMatch; |
| 144 | 151 | ||
| ... | @@ -159,12 +166,15 @@ struct Configuration { | ... | @@ -159,12 +166,15 @@ struct Configuration { |
| 159 | uint32_t MinorOSVersion = 0; | 166 | uint32_t MinorOSVersion = 0; |
| 160 | bool CanExitEarly = false; | 167 | bool CanExitEarly = false; |
| 161 | bool DynamicBase = true; | 168 | bool DynamicBase = true; |
| 169 | bool AllowBind = true; | ||
| 162 | bool NxCompat = true; | 170 | bool NxCompat = true; |
| 163 | bool AllowIsolation = true; | 171 | bool AllowIsolation = true; |
| 164 | bool TerminalServerAware = true; | 172 | bool TerminalServerAware = true; |
| 165 | bool LargeAddressAware = false; | 173 | bool LargeAddressAware = false; |
| 166 | bool HighEntropyVA = false; | 174 | bool HighEntropyVA = false; |
| 167 | bool AppContainer = false; | 175 | bool AppContainer = false; |
| 176 | bool MinGW = false; | ||
| 177 | bool WarnLocallyDefinedImported = true; | ||
| 168 | }; | 178 | }; |
| 169 | 179 | ||
| 170 | extern Configuration *Config; | 180 | extern Configuration *Config; |
deps/lld/COFF/DLL.cpp+58-9| ... | @@ -61,7 +61,7 @@ private: | ... | @@ -61,7 +61,7 @@ private: |
| 61 | // A chunk for the import descriptor table. | 61 | // A chunk for the import descriptor table. |
| 62 | class LookupChunk : public Chunk { | 62 | class LookupChunk : public Chunk { |
| 63 | public: | 63 | public: |
| 64 | explicit LookupChunk(Chunk *C) : HintName(C) {} | 64 | explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = ptrSize(); } |
| 65 | size_t getSize() const override { return ptrSize(); } | 65 | size_t getSize() const override { return ptrSize(); } |
| 66 | 66 | ||
| 67 | void writeTo(uint8_t *Buf) const override { | 67 | void writeTo(uint8_t *Buf) const override { |
| ... | @@ -76,7 +76,7 @@ public: | ... | @@ -76,7 +76,7 @@ public: |
| 76 | // See Microsoft PE/COFF spec 7.1. Import Header for details. | 76 | // See Microsoft PE/COFF spec 7.1. Import Header for details. |
| 77 | class OrdinalOnlyChunk : public Chunk { | 77 | class OrdinalOnlyChunk : public Chunk { |
| 78 | public: | 78 | public: |
| 79 | explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {} | 79 | explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { Alignment = ptrSize(); } |
| 80 | size_t getSize() const override { return ptrSize(); } | 80 | size_t getSize() const override { return ptrSize(); } |
| 81 | 81 | ||
| 82 | void writeTo(uint8_t *Buf) const override { | 82 | void writeTo(uint8_t *Buf) const override { |
| ... | @@ -117,7 +117,6 @@ public: | ... | @@ -117,7 +117,6 @@ public: |
| 117 | explicit NullChunk(size_t N) : Size(N) {} | 117 | explicit NullChunk(size_t N) : Size(N) {} |
| 118 | bool hasData() const override { return false; } | 118 | bool hasData() const override { return false; } |
| 119 | size_t getSize() const override { return Size; } | 119 | size_t getSize() const override { return Size; } |
| 120 | void setAlign(size_t N) { Align = N; } | ||
| 121 | 120 | ||
| 122 | private: | 121 | private: |
| 123 | size_t Size; | 122 | size_t Size; |
| ... | @@ -215,6 +214,22 @@ static const uint8_t ThunkX86[] = { | ... | @@ -215,6 +214,22 @@ static const uint8_t ThunkX86[] = { |
| 215 | 0xFF, 0xE0, // jmp eax | 214 | 0xFF, 0xE0, // jmp eax |
| 216 | }; | 215 | }; |
| 217 | 216 | ||
| 217 | static const uint8_t ThunkARM[] = { | ||
| 218 | 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_<FUNCNAME> | ||
| 219 | 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME> | ||
| 220 | 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr} | ||
| 221 | 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16 | ||
| 222 | 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7} | ||
| 223 | 0x61, 0x46, // mov r1, ip | ||
| 224 | 0x40, 0xf2, 0x00, 0x00, // mov.w r0, #0 DELAY_IMPORT_DESCRIPTOR | ||
| 225 | 0xc0, 0xf2, 0x00, 0x00, // mov.t r0, #0 DELAY_IMPORT_DESCRIPTOR | ||
| 226 | 0x00, 0xf0, 0x00, 0xd0, // bl #0 __delayLoadHelper2 | ||
| 227 | 0x84, 0x46, // mov ip, r0 | ||
| 228 | 0xbd, 0xec, 0x10, 0x0b, // vpop {d0, d1, d2, d3, d4, d5, d6, d7} | ||
| 229 | 0xbd, 0xe8, 0x0f, 0x48, // pop.w {r0, r1, r2, r3, r11, lr} | ||
| 230 | 0x60, 0x47, // bx ip | ||
| 231 | }; | ||
| 232 | |||
| 218 | // A chunk for the delay import thunk. | 233 | // A chunk for the delay import thunk. |
| 219 | class ThunkChunkX64 : public Chunk { | 234 | class ThunkChunkX64 : public Chunk { |
| 220 | public: | 235 | public: |
| ... | @@ -259,17 +274,45 @@ public: | ... | @@ -259,17 +274,45 @@ public: |
| 259 | Defined *Helper = nullptr; | 274 | Defined *Helper = nullptr; |
| 260 | }; | 275 | }; |
| 261 | 276 | ||
| 277 | class ThunkChunkARM : public Chunk { | ||
| 278 | public: | ||
| 279 | ThunkChunkARM(Defined *I, Chunk *D, Defined *H) | ||
| 280 | : Imp(I), Desc(D), Helper(H) {} | ||
| 281 | |||
| 282 | size_t getSize() const override { return sizeof(ThunkARM); } | ||
| 283 | |||
| 284 | void writeTo(uint8_t *Buf) const override { | ||
| 285 | memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM)); | ||
| 286 | applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase); | ||
| 287 | applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase); | ||
| 288 | applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34); | ||
| 289 | } | ||
| 290 | |||
| 291 | void getBaserels(std::vector<Baserel> *Res) override { | ||
| 292 | Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T); | ||
| 293 | Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T); | ||
| 294 | } | ||
| 295 | |||
| 296 | Defined *Imp = nullptr; | ||
| 297 | Chunk *Desc = nullptr; | ||
| 298 | Defined *Helper = nullptr; | ||
| 299 | }; | ||
| 300 | |||
| 262 | // A chunk for the import descriptor table. | 301 | // A chunk for the import descriptor table. |
| 263 | class DelayAddressChunk : public Chunk { | 302 | class DelayAddressChunk : public Chunk { |
| 264 | public: | 303 | public: |
| 265 | explicit DelayAddressChunk(Chunk *C) : Thunk(C) {} | 304 | explicit DelayAddressChunk(Chunk *C) : Thunk(C) { Alignment = ptrSize(); } |
| 266 | size_t getSize() const override { return ptrSize(); } | 305 | size_t getSize() const override { return ptrSize(); } |
| 267 | 306 | ||
| 268 | void writeTo(uint8_t *Buf) const override { | 307 | void writeTo(uint8_t *Buf) const override { |
| 269 | if (Config->is64()) { | 308 | if (Config->is64()) { |
| 270 | write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); | 309 | write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); |
| 271 | } else { | 310 | } else { |
| 272 | write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); | 311 | uint32_t Bit = 0; |
| 312 | // Pointer to thumb code must have the LSB set, so adjust it. | ||
| 313 | if (Config->Machine == ARMNT) | ||
| 314 | Bit = 1; | ||
| 315 | write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit); | ||
| 273 | } | 316 | } |
| 274 | } | 317 | } |
| 275 | 318 | ||
| ... | @@ -319,12 +362,16 @@ public: | ... | @@ -319,12 +362,16 @@ public: |
| 319 | size_t getSize() const override { return Size * 4; } | 362 | size_t getSize() const override { return Size * 4; } |
| 320 | 363 | ||
| 321 | void writeTo(uint8_t *Buf) const override { | 364 | void writeTo(uint8_t *Buf) const override { |
| 322 | for (Export &E : Config->Exports) { | 365 | for (const Export &E : Config->Exports) { |
| 323 | uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4; | 366 | uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4; |
| 367 | uint32_t Bit = 0; | ||
| 368 | // Pointer to thumb code must have the LSB set, so adjust it. | ||
| 369 | if (Config->Machine == ARMNT && !E.Data) | ||
| 370 | Bit = 1; | ||
| 324 | if (E.ForwardChunk) { | 371 | if (E.ForwardChunk) { |
| 325 | write32le(P, E.ForwardChunk->getRVA()); | 372 | write32le(P, E.ForwardChunk->getRVA() | Bit); |
| 326 | } else { | 373 | } else { |
| 327 | write32le(P, cast<Defined>(E.Sym)->getRVA()); | 374 | write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit); |
| 328 | } | 375 | } |
| 329 | } | 376 | } |
| 330 | } | 377 | } |
| ... | @@ -487,7 +534,7 @@ void DelayLoadContents::create(Defined *H) { | ... | @@ -487,7 +534,7 @@ void DelayLoadContents::create(Defined *H) { |
| 487 | for (int I = 0, E = Syms.size(); I < E; ++I) | 534 | for (int I = 0, E = Syms.size(); I < E; ++I) |
| 488 | Syms[I]->setLocation(Addresses[Base + I]); | 535 | Syms[I]->setLocation(Addresses[Base + I]); |
| 489 | auto *MH = make<NullChunk>(8); | 536 | auto *MH = make<NullChunk>(8); |
| 490 | MH->setAlign(8); | 537 | MH->Alignment = 8; |
| 491 | ModuleHandles.push_back(MH); | 538 | ModuleHandles.push_back(MH); |
| 492 | 539 | ||
| 493 | // Fill the delay import table header fields. | 540 | // Fill the delay import table header fields. |
| ... | @@ -506,6 +553,8 @@ Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { | ... | @@ -506,6 +553,8 @@ Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { |
| 506 | return make<ThunkChunkX64>(S, Dir, Helper); | 553 | return make<ThunkChunkX64>(S, Dir, Helper); |
| 507 | case I386: | 554 | case I386: |
| 508 | return make<ThunkChunkX86>(S, Dir, Helper); | 555 | return make<ThunkChunkX86>(S, Dir, Helper); |
| 556 | case ARMNT: | ||
| 557 | return make<ThunkChunkARM>(S, Dir, Helper); | ||
| 509 | default: | 558 | default: |
| 510 | llvm_unreachable("unsupported machine type"); | 559 | llvm_unreachable("unsupported machine type"); |
| 511 | } | 560 | } |
deps/lld/COFF/Driver.cpp+348-198| ... | @@ -9,13 +9,15 @@ | ... | @@ -9,13 +9,15 @@ |
| 9 | 9 | ||
| 10 | #include "Driver.h" | 10 | #include "Driver.h" |
| 11 | #include "Config.h" | 11 | #include "Config.h" |
| 12 | #include "Error.h" | ||
| 13 | #include "InputFiles.h" | 12 | #include "InputFiles.h" |
| 14 | #include "Memory.h" | 13 | #include "MinGW.h" |
| 15 | #include "SymbolTable.h" | 14 | #include "SymbolTable.h" |
| 16 | #include "Symbols.h" | 15 | #include "Symbols.h" |
| 17 | #include "Writer.h" | 16 | #include "Writer.h" |
| 18 | #include "lld/Driver/Driver.h" | 17 | #include "lld/Common/Driver.h" |
| 18 | #include "lld/Common/ErrorHandler.h" | ||
| 19 | #include "lld/Common/Memory.h" | ||
| 20 | #include "lld/Common/Version.h" | ||
| 19 | #include "llvm/ADT/Optional.h" | 21 | #include "llvm/ADT/Optional.h" |
| 20 | #include "llvm/ADT/StringSwitch.h" | 22 | #include "llvm/ADT/StringSwitch.h" |
| 21 | #include "llvm/BinaryFormat/Magic.h" | 23 | #include "llvm/BinaryFormat/Magic.h" |
| ... | @@ -48,27 +50,29 @@ namespace coff { | ... | @@ -48,27 +50,29 @@ namespace coff { |
| 48 | Configuration *Config; | 50 | Configuration *Config; |
| 49 | LinkerDriver *Driver; | 51 | LinkerDriver *Driver; |
| 50 | 52 | ||
| 51 | BumpPtrAllocator BAlloc; | ||
| 52 | StringSaver Saver{BAlloc}; | ||
| 53 | std::vector<SpecificAllocBase *> SpecificAllocBase::Instances; | ||
| 54 | |||
| 55 | bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) { | 53 | bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) { |
| 56 | ErrorCount = 0; | 54 | errorHandler().LogName = Args[0]; |
| 57 | ErrorOS = &Diag; | 55 | errorHandler().ErrorOS = &Diag; |
| 56 | errorHandler().ColorDiagnostics = Diag.has_colors(); | ||
| 57 | errorHandler().ErrorLimitExceededMsg = | ||
| 58 | "too many errors emitted, stopping now" | ||
| 59 | " (use /ERRORLIMIT:0 to see all errors)"; | ||
| 60 | errorHandler().ExitEarly = CanExitEarly; | ||
| 58 | Config = make<Configuration>(); | 61 | Config = make<Configuration>(); |
| 59 | Config->Argv = {Args.begin(), Args.end()}; | 62 | Config->Argv = {Args.begin(), Args.end()}; |
| 60 | Config->ColorDiagnostics = | ||
| 61 | (ErrorOS == &llvm::errs() && Process::StandardErrHasColors()); | ||
| 62 | Config->CanExitEarly = CanExitEarly; | 63 | Config->CanExitEarly = CanExitEarly; |
| 64 | |||
| 65 | Symtab = make<SymbolTable>(); | ||
| 66 | |||
| 63 | Driver = make<LinkerDriver>(); | 67 | Driver = make<LinkerDriver>(); |
| 64 | Driver->link(Args); | 68 | Driver->link(Args); |
| 65 | 69 | ||
| 66 | // Call exit() if we can to avoid calling destructors. | 70 | // Call exit() if we can to avoid calling destructors. |
| 67 | if (CanExitEarly) | 71 | if (CanExitEarly) |
| 68 | exitLld(ErrorCount ? 1 : 0); | 72 | exitLld(errorCount() ? 1 : 0); |
| 69 | 73 | ||
| 70 | freeArena(); | 74 | freeArena(); |
| 71 | return !ErrorCount; | 75 | return !errorCount(); |
| 72 | } | 76 | } |
| 73 | 77 | ||
| 74 | // Drop directory components and replace extension with ".exe" or ".dll". | 78 | // Drop directory components and replace extension with ".exe" or ".dll". |
| ... | @@ -114,30 +118,46 @@ MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> MB) { | ... | @@ -114,30 +118,46 @@ MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> MB) { |
| 114 | return MBRef; | 118 | return MBRef; |
| 115 | } | 119 | } |
| 116 | 120 | ||
| 117 | void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> MB) { | 121 | void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> MB, |
| 122 | bool WholeArchive) { | ||
| 118 | MemoryBufferRef MBRef = takeBuffer(std::move(MB)); | 123 | MemoryBufferRef MBRef = takeBuffer(std::move(MB)); |
| 124 | FilePaths.push_back(MBRef.getBufferIdentifier()); | ||
| 119 | 125 | ||
| 120 | // File type is detected by contents, not by file extension. | 126 | // File type is detected by contents, not by file extension. |
| 121 | file_magic Magic = identify_magic(MBRef.getBuffer()); | 127 | switch (identify_magic(MBRef.getBuffer())) { |
| 122 | if (Magic == file_magic::windows_resource) { | 128 | case file_magic::windows_resource: |
| 123 | Resources.push_back(MBRef); | 129 | Resources.push_back(MBRef); |
| 124 | return; | 130 | break; |
| 125 | } | ||
| 126 | 131 | ||
| 127 | FilePaths.push_back(MBRef.getBufferIdentifier()); | 132 | case file_magic::archive: |
| 128 | if (Magic == file_magic::archive) | 133 | if (WholeArchive) { |
| 129 | return Symtab.addFile(make<ArchiveFile>(MBRef)); | 134 | std::unique_ptr<Archive> File = |
| 130 | if (Magic == file_magic::bitcode) | 135 | CHECK(Archive::create(MBRef), |
| 131 | return Symtab.addFile(make<BitcodeFile>(MBRef)); | 136 | MBRef.getBufferIdentifier() + ": failed to parse archive"); |
| 137 | |||
| 138 | for (MemoryBufferRef M : getArchiveMembers(File.get())) | ||
| 139 | addArchiveBuffer(M, "<whole-archive>", MBRef.getBufferIdentifier()); | ||
| 140 | return; | ||
| 141 | } | ||
| 142 | Symtab->addFile(make<ArchiveFile>(MBRef)); | ||
| 143 | break; | ||
| 144 | |||
| 145 | case file_magic::bitcode: | ||
| 146 | Symtab->addFile(make<BitcodeFile>(MBRef)); | ||
| 147 | break; | ||
| 132 | 148 | ||
| 133 | if (Magic == file_magic::coff_cl_gl_object) | 149 | case file_magic::coff_cl_gl_object: |
| 134 | error(MBRef.getBufferIdentifier() + ": is not a native COFF file. " | 150 | error(MBRef.getBufferIdentifier() + ": is not a native COFF file. " |
| 135 | "Recompile without /GL"); | 151 | "Recompile without /GL"); |
| 136 | else | 152 | break; |
| 137 | Symtab.addFile(make<ObjectFile>(MBRef)); | 153 | |
| 154 | default: | ||
| 155 | Symtab->addFile(make<ObjFile>(MBRef)); | ||
| 156 | break; | ||
| 157 | } | ||
| 138 | } | 158 | } |
| 139 | 159 | ||
| 140 | void LinkerDriver::enqueuePath(StringRef Path) { | 160 | void LinkerDriver::enqueuePath(StringRef Path, bool WholeArchive) { |
| 141 | auto Future = | 161 | auto Future = |
| 142 | std::make_shared<std::future<MBErrPair>>(createFutureForFile(Path)); | 162 | std::make_shared<std::future<MBErrPair>>(createFutureForFile(Path)); |
| 143 | std::string PathStr = Path; | 163 | std::string PathStr = Path; |
| ... | @@ -146,7 +166,7 @@ void LinkerDriver::enqueuePath(StringRef Path) { | ... | @@ -146,7 +166,7 @@ void LinkerDriver::enqueuePath(StringRef Path) { |
| 146 | if (MBOrErr.second) | 166 | if (MBOrErr.second) |
| 147 | error("could not open " + PathStr + ": " + MBOrErr.second.message()); | 167 | error("could not open " + PathStr + ": " + MBOrErr.second.message()); |
| 148 | else | 168 | else |
| 149 | Driver->addBuffer(std::move(MBOrErr.first)); | 169 | Driver->addBuffer(std::move(MBOrErr.first), WholeArchive); |
| 150 | }); | 170 | }); |
| 151 | } | 171 | } |
| 152 | 172 | ||
| ... | @@ -154,13 +174,13 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName, | ... | @@ -154,13 +174,13 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName, |
| 154 | StringRef ParentName) { | 174 | StringRef ParentName) { |
| 155 | file_magic Magic = identify_magic(MB.getBuffer()); | 175 | file_magic Magic = identify_magic(MB.getBuffer()); |
| 156 | if (Magic == file_magic::coff_import_library) { | 176 | if (Magic == file_magic::coff_import_library) { |
| 157 | Symtab.addFile(make<ImportFile>(MB)); | 177 | Symtab->addFile(make<ImportFile>(MB)); |
| 158 | return; | 178 | return; |
| 159 | } | 179 | } |
| 160 | 180 | ||
| 161 | InputFile *Obj; | 181 | InputFile *Obj; |
| 162 | if (Magic == file_magic::coff_object) { | 182 | if (Magic == file_magic::coff_object) { |
| 163 | Obj = make<ObjectFile>(MB); | 183 | Obj = make<ObjFile>(MB); |
| 164 | } else if (Magic == file_magic::bitcode) { | 184 | } else if (Magic == file_magic::bitcode) { |
| 165 | Obj = make<BitcodeFile>(MB); | 185 | Obj = make<BitcodeFile>(MB); |
| 166 | } else { | 186 | } else { |
| ... | @@ -169,7 +189,7 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName, | ... | @@ -169,7 +189,7 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName, |
| 169 | } | 189 | } |
| 170 | 190 | ||
| 171 | Obj->ParentName = ParentName; | 191 | Obj->ParentName = ParentName; |
| 172 | Symtab.addFile(Obj); | 192 | Symtab->addFile(Obj); |
| 173 | log("Loaded " + toString(Obj) + " for " + SymName); | 193 | log("Loaded " + toString(Obj) + " for " + SymName); |
| 174 | } | 194 | } |
| 175 | 195 | ||
| ... | @@ -177,7 +197,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &C, | ... | @@ -177,7 +197,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &C, |
| 177 | StringRef SymName, | 197 | StringRef SymName, |
| 178 | StringRef ParentName) { | 198 | StringRef ParentName) { |
| 179 | if (!C.getParent()->isThin()) { | 199 | if (!C.getParent()->isThin()) { |
| 180 | MemoryBufferRef MB = check( | 200 | MemoryBufferRef MB = CHECK( |
| 181 | C.getMemoryBufferRef(), | 201 | C.getMemoryBufferRef(), |
| 182 | "could not get the buffer for the member defining symbol " + SymName); | 202 | "could not get the buffer for the member defining symbol " + SymName); |
| 183 | enqueueTask([=]() { Driver->addArchiveBuffer(MB, SymName, ParentName); }); | 203 | enqueueTask([=]() { Driver->addArchiveBuffer(MB, SymName, ParentName); }); |
| ... | @@ -185,39 +205,61 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &C, | ... | @@ -185,39 +205,61 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &C, |
| 185 | } | 205 | } |
| 186 | 206 | ||
| 187 | auto Future = std::make_shared<std::future<MBErrPair>>(createFutureForFile( | 207 | auto Future = std::make_shared<std::future<MBErrPair>>(createFutureForFile( |
| 188 | check(C.getFullName(), | 208 | CHECK(C.getFullName(), |
| 189 | "could not get the filename for the member defining symbol " + | 209 | "could not get the filename for the member defining symbol " + |
| 190 | SymName))); | 210 | SymName))); |
| 191 | enqueueTask([=]() { | 211 | enqueueTask([=]() { |
| 192 | auto MBOrErr = Future->get(); | 212 | auto MBOrErr = Future->get(); |
| 193 | if (MBOrErr.second) | 213 | if (MBOrErr.second) |
| 194 | fatal(MBOrErr.second, | 214 | fatal("could not get the buffer for the member defining " + SymName + |
| 195 | "could not get the buffer for the member defining " + SymName); | 215 | ": " + MBOrErr.second.message()); |
| 196 | Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName, | 216 | Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName, |
| 197 | ParentName); | 217 | ParentName); |
| 198 | }); | 218 | }); |
| 199 | } | 219 | } |
| 200 | 220 | ||
| 201 | static bool isDecorated(StringRef Sym) { | 221 | static bool isDecorated(StringRef Sym) { |
| 202 | return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?"); | 222 | return Sym.startswith("@") || Sym.contains("@@") || Sym.startswith("?") || |
| 223 | (!Config->MinGW && Sym.contains('@')); | ||
| 203 | } | 224 | } |
| 204 | 225 | ||
| 205 | // Parses .drectve section contents and returns a list of files | 226 | // Parses .drectve section contents and returns a list of files |
| 206 | // specified by /defaultlib. | 227 | // specified by /defaultlib. |
| 207 | void LinkerDriver::parseDirectives(StringRef S) { | 228 | void LinkerDriver::parseDirectives(StringRef S) { |
| 208 | opt::InputArgList Args = Parser.parse(S); | 229 | ArgParser Parser; |
| 230 | // .drectve is always tokenized using Windows shell rules. | ||
| 231 | opt::InputArgList Args = Parser.parseDirectives(S); | ||
| 209 | 232 | ||
| 210 | for (auto *Arg : Args) { | 233 | for (auto *Arg : Args) { |
| 211 | switch (Arg->getOption().getID()) { | 234 | switch (Arg->getOption().getUnaliasedOption().getID()) { |
| 235 | case OPT_aligncomm: | ||
| 236 | parseAligncomm(Arg->getValue()); | ||
| 237 | break; | ||
| 212 | case OPT_alternatename: | 238 | case OPT_alternatename: |
| 213 | parseAlternateName(Arg->getValue()); | 239 | parseAlternateName(Arg->getValue()); |
| 214 | break; | 240 | break; |
| 215 | case OPT_defaultlib: | 241 | case OPT_defaultlib: |
| 216 | if (Optional<StringRef> Path = findLib(Arg->getValue())) | 242 | if (Optional<StringRef> Path = findLib(Arg->getValue())) |
| 217 | enqueuePath(*Path); | 243 | enqueuePath(*Path, false); |
| 244 | break; | ||
| 245 | case OPT_entry: | ||
| 246 | Config->Entry = addUndefined(mangle(Arg->getValue())); | ||
| 218 | break; | 247 | break; |
| 219 | case OPT_export: { | 248 | case OPT_export: { |
| 249 | // If a common header file contains dllexported function | ||
| 250 | // declarations, many object files may end up with having the | ||
| 251 | // same /EXPORT options. In order to save cost of parsing them, | ||
| 252 | // we dedup them first. | ||
| 253 | if (!DirectivesExports.insert(Arg->getValue()).second) | ||
| 254 | break; | ||
| 255 | |||
| 220 | Export E = parseExport(Arg->getValue()); | 256 | Export E = parseExport(Arg->getValue()); |
| 257 | if (Config->Machine == I386 && Config->MinGW) { | ||
| 258 | if (!isDecorated(E.Name)) | ||
| 259 | E.Name = Saver.save("_" + E.Name); | ||
| 260 | if (!E.ExtName.empty() && !isDecorated(E.ExtName)) | ||
| 261 | E.ExtName = Saver.save("_" + E.ExtName); | ||
| 262 | } | ||
| 221 | E.Directives = true; | 263 | E.Directives = true; |
| 222 | Config->Exports.push_back(E); | 264 | Config->Exports.push_back(E); |
| 223 | break; | 265 | break; |
| ... | @@ -237,9 +279,14 @@ void LinkerDriver::parseDirectives(StringRef S) { | ... | @@ -237,9 +279,14 @@ void LinkerDriver::parseDirectives(StringRef S) { |
| 237 | case OPT_section: | 279 | case OPT_section: |
| 238 | parseSection(Arg->getValue()); | 280 | parseSection(Arg->getValue()); |
| 239 | break; | 281 | break; |
| 282 | case OPT_subsystem: | ||
| 283 | parseSubsystem(Arg->getValue(), &Config->Subsystem, | ||
| 284 | &Config->MajorOSVersion, &Config->MinorOSVersion); | ||
| 285 | break; | ||
| 240 | case OPT_editandcontinue: | 286 | case OPT_editandcontinue: |
| 241 | case OPT_fastfail: | 287 | case OPT_fastfail: |
| 242 | case OPT_guardsym: | 288 | case OPT_guardsym: |
| 289 | case OPT_natvis: | ||
| 243 | case OPT_throwingnew: | 290 | case OPT_throwingnew: |
| 244 | break; | 291 | break; |
| 245 | default: | 292 | default: |
| ... | @@ -254,7 +301,7 @@ StringRef LinkerDriver::doFindFile(StringRef Filename) { | ... | @@ -254,7 +301,7 @@ StringRef LinkerDriver::doFindFile(StringRef Filename) { |
| 254 | bool HasPathSep = (Filename.find_first_of("/\\") != StringRef::npos); | 301 | bool HasPathSep = (Filename.find_first_of("/\\") != StringRef::npos); |
| 255 | if (HasPathSep) | 302 | if (HasPathSep) |
| 256 | return Filename; | 303 | return Filename; |
| 257 | bool HasExt = (Filename.find('.') != StringRef::npos); | 304 | bool HasExt = Filename.contains('.'); |
| 258 | for (StringRef Dir : SearchPaths) { | 305 | for (StringRef Dir : SearchPaths) { |
| 259 | SmallString<128> Path = Dir; | 306 | SmallString<128> Path = Dir; |
| 260 | sys::path::append(Path, Filename); | 307 | sys::path::append(Path, Filename); |
| ... | @@ -276,13 +323,15 @@ Optional<StringRef> LinkerDriver::findFile(StringRef Filename) { | ... | @@ -276,13 +323,15 @@ Optional<StringRef> LinkerDriver::findFile(StringRef Filename) { |
| 276 | bool Seen = !VisitedFiles.insert(Path.lower()).second; | 323 | bool Seen = !VisitedFiles.insert(Path.lower()).second; |
| 277 | if (Seen) | 324 | if (Seen) |
| 278 | return None; | 325 | return None; |
| 326 | if (Path.endswith_lower(".lib")) | ||
| 327 | VisitedLibs.insert(sys::path::filename(Path)); | ||
| 279 | return Path; | 328 | return Path; |
| 280 | } | 329 | } |
| 281 | 330 | ||
| 282 | // Find library file from search path. | 331 | // Find library file from search path. |
| 283 | StringRef LinkerDriver::doFindLib(StringRef Filename) { | 332 | StringRef LinkerDriver::doFindLib(StringRef Filename) { |
| 284 | // Add ".lib" to Filename if that has no file extension. | 333 | // Add ".lib" to Filename if that has no file extension. |
| 285 | bool HasExt = (Filename.find('.') != StringRef::npos); | 334 | bool HasExt = Filename.contains('.'); |
| 286 | if (!HasExt) | 335 | if (!HasExt) |
| 287 | Filename = Saver.save(Filename + ".lib"); | 336 | Filename = Saver.save(Filename + ".lib"); |
| 288 | return doFindFile(Filename); | 337 | return doFindFile(Filename); |
| ... | @@ -317,9 +366,12 @@ void LinkerDriver::addLibSearchPaths() { | ... | @@ -317,9 +366,12 @@ void LinkerDriver::addLibSearchPaths() { |
| 317 | } | 366 | } |
| 318 | } | 367 | } |
| 319 | 368 | ||
| 320 | SymbolBody *LinkerDriver::addUndefined(StringRef Name) { | 369 | Symbol *LinkerDriver::addUndefined(StringRef Name) { |
| 321 | SymbolBody *B = Symtab.addUndefined(Name); | 370 | Symbol *B = Symtab->addUndefined(Name); |
| 322 | Config->GCRoot.insert(B); | 371 | if (!B->IsGCRoot) { |
| 372 | B->IsGCRoot = true; | ||
| 373 | Config->GCRoot.push_back(B); | ||
| 374 | } | ||
| 323 | return B; | 375 | return B; |
| 324 | } | 376 | } |
| 325 | 377 | ||
| ... | @@ -341,8 +393,8 @@ StringRef LinkerDriver::findDefaultEntry() { | ... | @@ -341,8 +393,8 @@ StringRef LinkerDriver::findDefaultEntry() { |
| 341 | {"wWinMain", "wWinMainCRTStartup"}, | 393 | {"wWinMain", "wWinMainCRTStartup"}, |
| 342 | }; | 394 | }; |
| 343 | for (auto E : Entries) { | 395 | for (auto E : Entries) { |
| 344 | StringRef Entry = Symtab.findMangle(mangle(E[0])); | 396 | StringRef Entry = Symtab->findMangle(mangle(E[0])); |
| 345 | if (!Entry.empty() && !isa<Undefined>(Symtab.find(Entry)->body())) | 397 | if (!Entry.empty() && !isa<Undefined>(Symtab->find(Entry))) |
| 346 | return mangle(E[1]); | 398 | return mangle(E[1]); |
| 347 | } | 399 | } |
| 348 | return ""; | 400 | return ""; |
| ... | @@ -351,9 +403,9 @@ StringRef LinkerDriver::findDefaultEntry() { | ... | @@ -351,9 +403,9 @@ StringRef LinkerDriver::findDefaultEntry() { |
| 351 | WindowsSubsystem LinkerDriver::inferSubsystem() { | 403 | WindowsSubsystem LinkerDriver::inferSubsystem() { |
| 352 | if (Config->DLL) | 404 | if (Config->DLL) |
| 353 | return IMAGE_SUBSYSTEM_WINDOWS_GUI; | 405 | return IMAGE_SUBSYSTEM_WINDOWS_GUI; |
| 354 | if (Symtab.findUnderscore("main") || Symtab.findUnderscore("wmain")) | 406 | if (Symtab->findUnderscore("main") || Symtab->findUnderscore("wmain")) |
| 355 | return IMAGE_SUBSYSTEM_WINDOWS_CUI; | 407 | return IMAGE_SUBSYSTEM_WINDOWS_CUI; |
| 356 | if (Symtab.findUnderscore("WinMain") || Symtab.findUnderscore("wWinMain")) | 408 | if (Symtab->findUnderscore("WinMain") || Symtab->findUnderscore("wWinMain")) |
| 357 | return IMAGE_SUBSYSTEM_WINDOWS_GUI; | 409 | return IMAGE_SUBSYSTEM_WINDOWS_GUI; |
| 358 | return IMAGE_SUBSYSTEM_UNKNOWN; | 410 | return IMAGE_SUBSYSTEM_UNKNOWN; |
| 359 | } | 411 | } |
| ... | @@ -376,9 +428,15 @@ static std::string createResponseFile(const opt::InputArgList &Args, | ... | @@ -376,9 +428,15 @@ static std::string createResponseFile(const opt::InputArgList &Args, |
| 376 | case OPT_INPUT: | 428 | case OPT_INPUT: |
| 377 | case OPT_defaultlib: | 429 | case OPT_defaultlib: |
| 378 | case OPT_libpath: | 430 | case OPT_libpath: |
| 431 | case OPT_manifest: | ||
| 432 | case OPT_manifest_colon: | ||
| 433 | case OPT_manifestdependency: | ||
| 434 | case OPT_manifestfile: | ||
| 435 | case OPT_manifestinput: | ||
| 436 | case OPT_manifestuac: | ||
| 379 | break; | 437 | break; |
| 380 | default: | 438 | default: |
| 381 | OS << toString(Arg) << "\n"; | 439 | OS << toString(*Arg) << "\n"; |
| 382 | } | 440 | } |
| 383 | } | 441 | } |
| 384 | 442 | ||
| ... | @@ -476,15 +534,17 @@ static void createImportLibrary(bool AsLib) { | ... | @@ -476,15 +534,17 @@ static void createImportLibrary(bool AsLib) { |
| 476 | Exports.push_back(E2); | 534 | Exports.push_back(E2); |
| 477 | } | 535 | } |
| 478 | 536 | ||
| 479 | writeImportLibrary(getImportName(AsLib), getImplibPath(), Exports, | 537 | auto E = writeImportLibrary(getImportName(AsLib), getImplibPath(), Exports, |
| 480 | Config->Machine, false); | 538 | Config->Machine, false); |
| 539 | handleAllErrors(std::move(E), | ||
| 540 | [&](ErrorInfoBase &EIB) { error(EIB.message()); }); | ||
| 481 | } | 541 | } |
| 482 | 542 | ||
| 483 | static void parseModuleDefs(StringRef Path) { | 543 | static void parseModuleDefs(StringRef Path) { |
| 484 | std::unique_ptr<MemoryBuffer> MB = check( | 544 | std::unique_ptr<MemoryBuffer> MB = CHECK( |
| 485 | MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); | 545 | MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); |
| 486 | COFFModuleDefinition M = | 546 | COFFModuleDefinition M = check(parseCOFFModuleDefinition( |
| 487 | check(parseCOFFModuleDefinition(MB->getMemBufferRef(), Config->Machine)); | 547 | MB->getMemBufferRef(), Config->Machine, Config->MinGW)); |
| 488 | 548 | ||
| 489 | if (Config->OutputFile.empty()) | 549 | if (Config->OutputFile.empty()) |
| 490 | Config->OutputFile = Saver.save(M.OutputFile); | 550 | Config->OutputFile = Saver.save(M.OutputFile); |
| ... | @@ -522,31 +582,12 @@ static void parseModuleDefs(StringRef Path) { | ... | @@ -522,31 +582,12 @@ static void parseModuleDefs(StringRef Path) { |
| 522 | } | 582 | } |
| 523 | } | 583 | } |
| 524 | 584 | ||
| 525 | std::vector<MemoryBufferRef> getArchiveMembers(Archive *File) { | ||
| 526 | std::vector<MemoryBufferRef> V; | ||
| 527 | Error Err = Error::success(); | ||
| 528 | for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { | ||
| 529 | Archive::Child C = | ||
| 530 | check(COrErr, | ||
| 531 | File->getFileName() + ": could not get the child of the archive"); | ||
| 532 | MemoryBufferRef MBRef = | ||
| 533 | check(C.getMemoryBufferRef(), | ||
| 534 | File->getFileName() + | ||
| 535 | ": could not get the buffer for a child of the archive"); | ||
| 536 | V.push_back(MBRef); | ||
| 537 | } | ||
| 538 | if (Err) | ||
| 539 | fatal(File->getFileName() + | ||
| 540 | ": Archive::children failed: " + toString(std::move(Err))); | ||
| 541 | return V; | ||
| 542 | } | ||
| 543 | |||
| 544 | // A helper function for filterBitcodeFiles. | 585 | // A helper function for filterBitcodeFiles. |
| 545 | static bool needsRebuilding(MemoryBufferRef MB) { | 586 | static bool needsRebuilding(MemoryBufferRef MB) { |
| 546 | // The MSVC linker doesn't support thin archives, so if it's a thin | 587 | // The MSVC linker doesn't support thin archives, so if it's a thin |
| 547 | // archive, we always need to rebuild it. | 588 | // archive, we always need to rebuild it. |
| 548 | std::unique_ptr<Archive> File = | 589 | std::unique_ptr<Archive> File = |
| 549 | check(Archive::create(MB), "Failed to read " + MB.getBufferIdentifier()); | 590 | CHECK(Archive::create(MB), "Failed to read " + MB.getBufferIdentifier()); |
| 550 | if (File->isThin()) | 591 | if (File->isThin()) |
| 551 | return true; | 592 | return true; |
| 552 | 593 | ||
| ... | @@ -567,7 +608,7 @@ static bool needsRebuilding(MemoryBufferRef MB) { | ... | @@ -567,7 +608,7 @@ static bool needsRebuilding(MemoryBufferRef MB) { |
| 567 | // its path is returned. | 608 | // its path is returned. |
| 568 | static Optional<std::string> | 609 | static Optional<std::string> |
| 569 | filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) { | 610 | filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) { |
| 570 | std::unique_ptr<MemoryBuffer> MB = check( | 611 | std::unique_ptr<MemoryBuffer> MB = CHECK( |
| 571 | MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); | 612 | MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); |
| 572 | MemoryBufferRef MBRef = MB->getMemBufferRef(); | 613 | MemoryBufferRef MBRef = MB->getMemBufferRef(); |
| 573 | file_magic Magic = identify_magic(MBRef.getBuffer()); | 614 | file_magic Magic = identify_magic(MBRef.getBuffer()); |
| ... | @@ -580,7 +621,7 @@ filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) { | ... | @@ -580,7 +621,7 @@ filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) { |
| 580 | return Path.str(); | 621 | return Path.str(); |
| 581 | 622 | ||
| 582 | std::unique_ptr<Archive> File = | 623 | std::unique_ptr<Archive> File = |
| 583 | check(Archive::create(MBRef), | 624 | CHECK(Archive::create(MBRef), |
| 584 | MBRef.getBufferIdentifier() + ": failed to parse archive"); | 625 | MBRef.getBufferIdentifier() + ": failed to parse archive"); |
| 585 | 626 | ||
| 586 | std::vector<NewArchiveMember> New; | 627 | std::vector<NewArchiveMember> New; |
| ... | @@ -596,16 +637,17 @@ filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) { | ... | @@ -596,16 +637,17 @@ filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) { |
| 596 | SmallString<128> S; | 637 | SmallString<128> S; |
| 597 | if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path), | 638 | if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path), |
| 598 | ".lib", S)) | 639 | ".lib", S)) |
| 599 | fatal(EC, "cannot create a temporary file"); | 640 | fatal("cannot create a temporary file: " + EC.message()); |
| 600 | std::string Temp = S.str(); | 641 | std::string Temp = S.str(); |
| 601 | TemporaryFiles.push_back(Temp); | 642 | TemporaryFiles.push_back(Temp); |
| 602 | 643 | ||
| 603 | std::pair<StringRef, std::error_code> Ret = | 644 | Error E = |
| 604 | llvm::writeArchive(Temp, New, /*WriteSymtab=*/true, Archive::Kind::K_GNU, | 645 | llvm::writeArchive(Temp, New, /*WriteSymtab=*/true, Archive::Kind::K_GNU, |
| 605 | /*Deterministics=*/true, | 646 | /*Deterministics=*/true, |
| 606 | /*Thin=*/false); | 647 | /*Thin=*/false); |
| 607 | if (Ret.second) | 648 | handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) { |
| 608 | error("failed to create a new archive " + S.str() + ": " + Ret.first); | 649 | error("failed to create a new archive " + S.str() + ": " + EI.message()); |
| 650 | }); | ||
| 609 | return Temp; | 651 | return Temp; |
| 610 | } | 652 | } |
| 611 | 653 | ||
| ... | @@ -617,16 +659,16 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { | ... | @@ -617,16 +659,16 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { |
| 617 | // Write out archive members that we used in symbol resolution and pass these | 659 | // Write out archive members that we used in symbol resolution and pass these |
| 618 | // to MSVC before any archives, so that MSVC uses the same objects to satisfy | 660 | // to MSVC before any archives, so that MSVC uses the same objects to satisfy |
| 619 | // references. | 661 | // references. |
| 620 | for (const auto *O : Symtab.ObjectFiles) { | 662 | for (ObjFile *Obj : ObjFile::Instances) { |
| 621 | if (O->ParentName.empty()) | 663 | if (Obj->ParentName.empty()) |
| 622 | continue; | 664 | continue; |
| 623 | SmallString<128> S; | 665 | SmallString<128> S; |
| 624 | int Fd; | 666 | int Fd; |
| 625 | if (auto EC = sys::fs::createTemporaryFile( | 667 | if (auto EC = sys::fs::createTemporaryFile( |
| 626 | "lld-" + sys::path::filename(O->ParentName), ".obj", Fd, S)) | 668 | "lld-" + sys::path::filename(Obj->ParentName), ".obj", Fd, S)) |
| 627 | fatal(EC, "cannot create a temporary file"); | 669 | fatal("cannot create a temporary file: " + EC.message()); |
| 628 | raw_fd_ostream OS(Fd, /*shouldClose*/ true); | 670 | raw_fd_ostream OS(Fd, /*shouldClose*/ true); |
| 629 | OS << O->MB.getBuffer(); | 671 | OS << Obj->MB.getBuffer(); |
| 630 | Temps.push_back(S.str()); | 672 | Temps.push_back(S.str()); |
| 631 | Rsp += quote(S) + "\n"; | 673 | Rsp += quote(S) + "\n"; |
| 632 | } | 674 | } |
| ... | @@ -642,7 +684,7 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { | ... | @@ -642,7 +684,7 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { |
| 642 | break; | 684 | break; |
| 643 | case OPT_opt: | 685 | case OPT_opt: |
| 644 | if (!StringRef(Arg->getValue()).startswith("lld")) | 686 | if (!StringRef(Arg->getValue()).startswith("lld")) |
| 645 | Rsp += toString(Arg) + " "; | 687 | Rsp += toString(*Arg) + " "; |
| 646 | break; | 688 | break; |
| 647 | case OPT_INPUT: { | 689 | case OPT_INPUT: { |
| 648 | if (Optional<StringRef> Path = doFindFile(Arg->getValue())) { | 690 | if (Optional<StringRef> Path = doFindFile(Arg->getValue())) { |
| ... | @@ -654,12 +696,12 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { | ... | @@ -654,12 +696,12 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { |
| 654 | break; | 696 | break; |
| 655 | } | 697 | } |
| 656 | default: | 698 | default: |
| 657 | Rsp += toString(Arg) + "\n"; | 699 | Rsp += toString(*Arg) + "\n"; |
| 658 | } | 700 | } |
| 659 | } | 701 | } |
| 660 | 702 | ||
| 661 | std::vector<StringRef> ObjectFiles = Symtab.compileBitcodeFiles(); | 703 | std::vector<StringRef> ObjFiles = Symtab->compileBitcodeFiles(); |
| 662 | runMSVCLinker(Rsp, ObjectFiles); | 704 | runMSVCLinker(Rsp, ObjFiles); |
| 663 | 705 | ||
| 664 | for (StringRef Path : Temps) | 706 | for (StringRef Path : Temps) |
| 665 | sys::fs::remove(Path); | 707 | sys::fs::remove(Path); |
| ... | @@ -696,6 +738,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -696,6 +738,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 696 | InitializeAllDisassemblers(); | 738 | InitializeAllDisassemblers(); |
| 697 | 739 | ||
| 698 | // Parse command line options. | 740 | // Parse command line options. |
| 741 | ArgParser Parser; | ||
| 699 | opt::InputArgList Args = Parser.parseLINK(ArgsArr.slice(1)); | 742 | opt::InputArgList Args = Parser.parseLINK(ArgsArr.slice(1)); |
| 700 | 743 | ||
| 701 | // Parse and evaluate -mllvm options. | 744 | // Parse and evaluate -mllvm options. |
| ... | @@ -711,7 +754,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -711,7 +754,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 711 | StringRef S = Arg->getValue(); | 754 | StringRef S = Arg->getValue(); |
| 712 | if (S.getAsInteger(10, N)) | 755 | if (S.getAsInteger(10, N)) |
| 713 | error(Arg->getSpelling() + " number expected, but got " + S); | 756 | error(Arg->getSpelling() + " number expected, but got " + S); |
| 714 | Config->ErrorLimit = N; | 757 | errorHandler().ErrorLimit = N; |
| 715 | } | 758 | } |
| 716 | 759 | ||
| 717 | // Handle /help | 760 | // Handle /help |
| ... | @@ -720,6 +763,18 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -720,6 +763,18 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 720 | return; | 763 | return; |
| 721 | } | 764 | } |
| 722 | 765 | ||
| 766 | // Handle --version, which is an lld extension. This option is a bit odd | ||
| 767 | // because it doesn't start with "/", but we deliberately chose "--" to | ||
| 768 | // avoid conflict with /version and for compatibility with clang-cl. | ||
| 769 | if (Args.hasArg(OPT_dash_dash_version)) { | ||
| 770 | outs() << getLLDVersion() << "\n"; | ||
| 771 | return; | ||
| 772 | } | ||
| 773 | |||
| 774 | // Handle /lldmingw early, since it can potentially affect how other | ||
| 775 | // options are handled. | ||
| 776 | Config->MinGW = Args.hasArg(OPT_lldmingw); | ||
| 777 | |||
| 723 | if (auto *Arg = Args.getLastArg(OPT_linkrepro)) { | 778 | if (auto *Arg = Args.getLastArg(OPT_linkrepro)) { |
| 724 | SmallString<64> Path = StringRef(Arg->getValue()); | 779 | SmallString<64> Path = StringRef(Arg->getValue()); |
| 725 | sys::path::append(Path, "repro.tar"); | 780 | sys::path::append(Path, "repro.tar"); |
| ... | @@ -735,8 +790,8 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -735,8 +790,8 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 735 | } | 790 | } |
| 736 | } | 791 | } |
| 737 | 792 | ||
| 738 | if (!Args.hasArgNoClaim(OPT_INPUT)) { | 793 | if (!Args.hasArg(OPT_INPUT)) { |
| 739 | if (Args.hasArgNoClaim(OPT_deffile)) | 794 | if (Args.hasArg(OPT_deffile)) |
| 740 | Config->NoEntry = true; | 795 | Config->NoEntry = true; |
| 741 | else | 796 | else |
| 742 | fatal("no input files"); | 797 | fatal("no input files"); |
| ... | @@ -748,6 +803,13 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -748,6 +803,13 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 748 | SearchPaths.push_back(Arg->getValue()); | 803 | SearchPaths.push_back(Arg->getValue()); |
| 749 | addLibSearchPaths(); | 804 | addLibSearchPaths(); |
| 750 | 805 | ||
| 806 | // Handle /ignore | ||
| 807 | for (auto *Arg : Args.filtered(OPT_ignore)) { | ||
| 808 | if (StringRef(Arg->getValue()) == "4217") | ||
| 809 | Config->WarnLocallyDefinedImported = false; | ||
| 810 | // Other warning numbers are ignored. | ||
| 811 | } | ||
| 812 | |||
| 751 | // Handle /out | 813 | // Handle /out |
| 752 | if (auto *Arg = Args.getLastArg(OPT_out)) | 814 | if (auto *Arg = Args.getLastArg(OPT_out)) |
| 753 | Config->OutputFile = Arg->getValue(); | 815 | Config->OutputFile = Arg->getValue(); |
| ... | @@ -755,23 +817,26 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -755,23 +817,26 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 755 | // Handle /verbose | 817 | // Handle /verbose |
| 756 | if (Args.hasArg(OPT_verbose)) | 818 | if (Args.hasArg(OPT_verbose)) |
| 757 | Config->Verbose = true; | 819 | Config->Verbose = true; |
| 820 | errorHandler().Verbose = Config->Verbose; | ||
| 758 | 821 | ||
| 759 | // Handle /force or /force:unresolved | 822 | // Handle /force or /force:unresolved |
| 760 | if (Args.hasArg(OPT_force) || Args.hasArg(OPT_force_unresolved)) | 823 | if (Args.hasArg(OPT_force, OPT_force_unresolved)) |
| 761 | Config->Force = true; | 824 | Config->Force = true; |
| 762 | 825 | ||
| 763 | // Handle /debug | 826 | // Handle /debug |
| 764 | if (Args.hasArg(OPT_debug)) { | 827 | if (Args.hasArg(OPT_debug, OPT_debug_dwarf, OPT_debug_ghash)) { |
| 765 | Config->Debug = true; | 828 | Config->Debug = true; |
| 766 | Config->DebugTypes = | 829 | if (auto *Arg = Args.getLastArg(OPT_debugtype)) |
| 767 | Args.hasArg(OPT_debugtype) | 830 | Config->DebugTypes = parseDebugType(Arg->getValue()); |
| 768 | ? parseDebugType(Args.getLastArg(OPT_debugtype)->getValue()) | 831 | else |
| 769 | : getDefaultDebugType(Args); | 832 | Config->DebugTypes = getDefaultDebugType(Args); |
| 770 | } | 833 | } |
| 771 | 834 | ||
| 772 | // Create a dummy PDB file to satisfy build sytem rules. | 835 | // Handle /pdb |
| 773 | if (auto *Arg = Args.getLastArg(OPT_pdb)) | 836 | bool ShouldCreatePDB = Args.hasArg(OPT_debug, OPT_debug_ghash); |
| 774 | Config->PDBPath = Arg->getValue(); | 837 | if (ShouldCreatePDB) |
| 838 | if (auto *Arg = Args.getLastArg(OPT_pdb)) | ||
| 839 | Config->PDBPath = Arg->getValue(); | ||
| 775 | 840 | ||
| 776 | // Handle /noentry | 841 | // Handle /noentry |
| 777 | if (Args.hasArg(OPT_noentry)) { | 842 | if (Args.hasArg(OPT_noentry)) { |
| ... | @@ -787,9 +852,18 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -787,9 +852,18 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 787 | Config->ManifestID = 2; | 852 | Config->ManifestID = 2; |
| 788 | } | 853 | } |
| 789 | 854 | ||
| 790 | // Handle /fixed | 855 | // Handle /dynamicbase and /fixed. We can't use hasFlag for /dynamicbase |
| 791 | if (Args.hasArg(OPT_fixed)) { | 856 | // because we need to explicitly check whether that option or its inverse was |
| 792 | if (Args.hasArg(OPT_dynamicbase)) { | 857 | // present in the argument list in order to handle /fixed. |
| 858 | auto *DynamicBaseArg = Args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no); | ||
| 859 | if (DynamicBaseArg && | ||
| 860 | DynamicBaseArg->getOption().getID() == OPT_dynamicbase_no) | ||
| 861 | Config->DynamicBase = false; | ||
| 862 | |||
| 863 | bool Fixed = Args.hasFlag(OPT_fixed, OPT_fixed_no, false); | ||
| 864 | if (Fixed) { | ||
| 865 | if (DynamicBaseArg && | ||
| 866 | DynamicBaseArg->getOption().getID() == OPT_dynamicbase) { | ||
| 793 | error("/fixed must not be specified with /dynamicbase"); | 867 | error("/fixed must not be specified with /dynamicbase"); |
| 794 | } else { | 868 | } else { |
| 795 | Config->Relocatable = false; | 869 | Config->Relocatable = false; |
| ... | @@ -797,8 +871,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -797,8 +871,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 797 | } | 871 | } |
| 798 | } | 872 | } |
| 799 | 873 | ||
| 800 | if (Args.hasArg(OPT_appcontainer)) | 874 | // Handle /appcontainer |
| 801 | Config->AppContainer = true; | 875 | Config->AppContainer = |
| 876 | Args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false); | ||
| 802 | 877 | ||
| 803 | // Handle /machine | 878 | // Handle /machine |
| 804 | if (auto *Arg = Args.getLastArg(OPT_machine)) | 879 | if (auto *Arg = Args.getLastArg(OPT_machine)) |
| ... | @@ -846,54 +921,65 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -846,54 +921,65 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 846 | if (auto *Arg = Args.getLastArg(OPT_implib)) | 921 | if (auto *Arg = Args.getLastArg(OPT_implib)) |
| 847 | Config->Implib = Arg->getValue(); | 922 | Config->Implib = Arg->getValue(); |
| 848 | 923 | ||
| 849 | // Handle /opt | 924 | // Handle /opt. |
| 925 | bool DoGC = !Args.hasArg(OPT_debug); | ||
| 926 | unsigned ICFLevel = 1; // 0: off, 1: limited, 2: on | ||
| 850 | for (auto *Arg : Args.filtered(OPT_opt)) { | 927 | for (auto *Arg : Args.filtered(OPT_opt)) { |
| 851 | std::string Str = StringRef(Arg->getValue()).lower(); | 928 | std::string Str = StringRef(Arg->getValue()).lower(); |
| 852 | SmallVector<StringRef, 1> Vec; | 929 | SmallVector<StringRef, 1> Vec; |
| 853 | StringRef(Str).split(Vec, ','); | 930 | StringRef(Str).split(Vec, ','); |
| 854 | for (StringRef S : Vec) { | 931 | for (StringRef S : Vec) { |
| 855 | if (S == "noref") { | 932 | if (S == "ref") { |
| 856 | Config->DoGC = false; | 933 | DoGC = true; |
| 857 | Config->DoICF = false; | 934 | } else if (S == "noref") { |
| 858 | continue; | 935 | DoGC = false; |
| 859 | } | 936 | } else if (S == "icf" || S.startswith("icf=")) { |
| 860 | if (S == "icf" || StringRef(S).startswith("icf=")) { | 937 | ICFLevel = 2; |
| 861 | Config->DoICF = true; | 938 | } else if (S == "noicf") { |
| 862 | continue; | 939 | ICFLevel = 0; |
| 863 | } | 940 | } else if (S.startswith("lldlto=")) { |
| 864 | if (S == "noicf") { | 941 | StringRef OptLevel = S.substr(7); |
| 865 | Config->DoICF = false; | ||
| 866 | continue; | ||
| 867 | } | ||
| 868 | if (StringRef(S).startswith("lldlto=")) { | ||
| 869 | StringRef OptLevel = StringRef(S).substr(7); | ||
| 870 | if (OptLevel.getAsInteger(10, Config->LTOOptLevel) || | 942 | if (OptLevel.getAsInteger(10, Config->LTOOptLevel) || |
| 871 | Config->LTOOptLevel > 3) | 943 | Config->LTOOptLevel > 3) |
| 872 | error("/opt:lldlto: invalid optimization level: " + OptLevel); | 944 | error("/opt:lldlto: invalid optimization level: " + OptLevel); |
| 873 | continue; | 945 | } else if (S.startswith("lldltojobs=")) { |
| 874 | } | 946 | StringRef Jobs = S.substr(11); |
| 875 | if (StringRef(S).startswith("lldltojobs=")) { | ||
| 876 | StringRef Jobs = StringRef(S).substr(11); | ||
| 877 | if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0) | 947 | if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0) |
| 878 | error("/opt:lldltojobs: invalid job count: " + Jobs); | 948 | error("/opt:lldltojobs: invalid job count: " + Jobs); |
| 879 | continue; | 949 | } else if (S.startswith("lldltopartitions=")) { |
| 880 | } | 950 | StringRef N = S.substr(17); |
| 881 | if (StringRef(S).startswith("lldltopartitions=")) { | ||
| 882 | StringRef N = StringRef(S).substr(17); | ||
| 883 | if (N.getAsInteger(10, Config->LTOPartitions) || | 951 | if (N.getAsInteger(10, Config->LTOPartitions) || |
| 884 | Config->LTOPartitions == 0) | 952 | Config->LTOPartitions == 0) |
| 885 | error("/opt:lldltopartitions: invalid partition count: " + N); | 953 | error("/opt:lldltopartitions: invalid partition count: " + N); |
| 886 | continue; | 954 | } else if (S != "lbr" && S != "nolbr") |
| 887 | } | ||
| 888 | if (S != "ref" && S != "lbr" && S != "nolbr") | ||
| 889 | error("/opt: unknown option: " + S); | 955 | error("/opt: unknown option: " + S); |
| 890 | } | 956 | } |
| 891 | } | 957 | } |
| 892 | 958 | ||
| 959 | // Limited ICF is enabled if GC is enabled and ICF was never mentioned | ||
| 960 | // explicitly. | ||
| 961 | // FIXME: LLD only implements "limited" ICF, i.e. it only merges identical | ||
| 962 | // code. If the user passes /OPT:ICF explicitly, LLD should merge identical | ||
| 963 | // comdat readonly data. | ||
| 964 | if (ICFLevel == 1 && !DoGC) | ||
| 965 | ICFLevel = 0; | ||
| 966 | Config->DoGC = DoGC; | ||
| 967 | Config->DoICF = ICFLevel > 0; | ||
| 968 | |||
| 893 | // Handle /lldsavetemps | 969 | // Handle /lldsavetemps |
| 894 | if (Args.hasArg(OPT_lldsavetemps)) | 970 | if (Args.hasArg(OPT_lldsavetemps)) |
| 895 | Config->SaveTemps = true; | 971 | Config->SaveTemps = true; |
| 896 | 972 | ||
| 973 | // Handle /lldltocache | ||
| 974 | if (auto *Arg = Args.getLastArg(OPT_lldltocache)) | ||
| 975 | Config->LTOCache = Arg->getValue(); | ||
| 976 | |||
| 977 | // Handle /lldsavecachepolicy | ||
| 978 | if (auto *Arg = Args.getLastArg(OPT_lldltocachepolicy)) | ||
| 979 | Config->LTOCachePolicy = CHECK( | ||
| 980 | parseCachePruningPolicy(Arg->getValue()), | ||
| 981 | Twine("/lldltocachepolicy: invalid cache policy: ") + Arg->getValue()); | ||
| 982 | |||
| 897 | // Handle /failifmismatch | 983 | // Handle /failifmismatch |
| 898 | for (auto *Arg : Args.filtered(OPT_failifmismatch)) | 984 | for (auto *Arg : Args.filtered(OPT_failifmismatch)) |
| 899 | checkFailIfMismatch(Arg->getValue()); | 985 | checkFailIfMismatch(Arg->getValue()); |
| ... | @@ -906,6 +992,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -906,6 +992,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 906 | for (auto *Arg : Args.filtered(OPT_section)) | 992 | for (auto *Arg : Args.filtered(OPT_section)) |
| 907 | parseSection(Arg->getValue()); | 993 | parseSection(Arg->getValue()); |
| 908 | 994 | ||
| 995 | // Handle /aligncomm | ||
| 996 | for (auto *Arg : Args.filtered(OPT_aligncomm)) | ||
| 997 | parseAligncomm(Arg->getValue()); | ||
| 998 | |||
| 909 | // Handle /manifestdependency. This enables /manifest unless /manifest:no is | 999 | // Handle /manifestdependency. This enables /manifest unless /manifest:no is |
| 910 | // also passed. | 1000 | // also passed. |
| 911 | if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) { | 1001 | if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) { |
| ... | @@ -939,35 +1029,42 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -939,35 +1029,42 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 939 | } | 1029 | } |
| 940 | 1030 | ||
| 941 | // Handle miscellaneous boolean flags. | 1031 | // Handle miscellaneous boolean flags. |
| 942 | if (Args.hasArg(OPT_allowisolation_no)) | 1032 | Config->AllowBind = Args.hasFlag(OPT_allowbind, OPT_allowbind_no, true); |
| 943 | Config->AllowIsolation = false; | 1033 | Config->AllowIsolation = |
| 944 | if (Args.hasArg(OPT_dynamicbase_no)) | 1034 | Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true); |
| 945 | Config->DynamicBase = false; | 1035 | Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true); |
| 946 | if (Args.hasArg(OPT_nxcompat_no)) | 1036 | Config->TerminalServerAware = Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true); |
| 947 | Config->NxCompat = false; | 1037 | Config->DebugDwarf = Args.hasArg(OPT_debug_dwarf); |
| 948 | if (Args.hasArg(OPT_tsaware_no)) | 1038 | Config->DebugGHashes = Args.hasArg(OPT_debug_ghash); |
| 949 | Config->TerminalServerAware = false; | ||
| 950 | if (Args.hasArg(OPT_nosymtab)) | ||
| 951 | Config->WriteSymtab = false; | ||
| 952 | 1039 | ||
| 953 | Config->MapFile = getMapFile(Args); | 1040 | Config->MapFile = getMapFile(Args); |
| 954 | 1041 | ||
| 955 | if (ErrorCount) | 1042 | if (errorCount()) |
| 956 | return; | 1043 | return; |
| 957 | 1044 | ||
| 1045 | bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag); | ||
| 958 | // Create a list of input files. Files can be given as arguments | 1046 | // Create a list of input files. Files can be given as arguments |
| 959 | // for /defaultlib option. | 1047 | // for /defaultlib option. |
| 960 | std::vector<MemoryBufferRef> MBs; | 1048 | std::vector<MemoryBufferRef> MBs; |
| 961 | for (auto *Arg : Args.filtered(OPT_INPUT)) | 1049 | for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) { |
| 962 | if (Optional<StringRef> Path = findFile(Arg->getValue())) | 1050 | switch (Arg->getOption().getID()) { |
| 963 | enqueuePath(*Path); | 1051 | case OPT_INPUT: |
| 1052 | if (Optional<StringRef> Path = findFile(Arg->getValue())) | ||
| 1053 | enqueuePath(*Path, WholeArchiveFlag); | ||
| 1054 | break; | ||
| 1055 | case OPT_wholearchive_file: | ||
| 1056 | if (Optional<StringRef> Path = findFile(Arg->getValue())) | ||
| 1057 | enqueuePath(*Path, true); | ||
| 1058 | break; | ||
| 1059 | } | ||
| 1060 | } | ||
| 964 | for (auto *Arg : Args.filtered(OPT_defaultlib)) | 1061 | for (auto *Arg : Args.filtered(OPT_defaultlib)) |
| 965 | if (Optional<StringRef> Path = findLib(Arg->getValue())) | 1062 | if (Optional<StringRef> Path = findLib(Arg->getValue())) |
| 966 | enqueuePath(*Path); | 1063 | enqueuePath(*Path, false); |
| 967 | 1064 | ||
| 968 | // Windows specific -- Create a resource file containing a manifest file. | 1065 | // Windows specific -- Create a resource file containing a manifest file. |
| 969 | if (Config->Manifest == Configuration::Embed) | 1066 | if (Config->Manifest == Configuration::Embed) |
| 970 | addBuffer(createManifestRes()); | 1067 | addBuffer(createManifestRes(), false); |
| 971 | 1068 | ||
| 972 | // Read all input files given via the command line. | 1069 | // Read all input files given via the command line. |
| 973 | run(); | 1070 | run(); |
| ... | @@ -983,7 +1080,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -983,7 +1080,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 983 | // WindowsResource to convert resource files to a regular COFF file, | 1080 | // WindowsResource to convert resource files to a regular COFF file, |
| 984 | // then link the resulting file normally. | 1081 | // then link the resulting file normally. |
| 985 | if (!Resources.empty()) | 1082 | if (!Resources.empty()) |
| 986 | addBuffer(convertResToCOFF(Resources)); | 1083 | Symtab->addFile(make<ObjFile>(convertResToCOFF(Resources))); |
| 987 | 1084 | ||
| 988 | if (Tar) | 1085 | if (Tar) |
| 989 | Tar->append("response.txt", | 1086 | Tar->append("response.txt", |
| ... | @@ -991,28 +1088,36 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -991,28 +1088,36 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 991 | ArrayRef<StringRef>(SearchPaths).slice(1))); | 1088 | ArrayRef<StringRef>(SearchPaths).slice(1))); |
| 992 | 1089 | ||
| 993 | // Handle /largeaddressaware | 1090 | // Handle /largeaddressaware |
| 994 | if (Config->is64() || Args.hasArg(OPT_largeaddressaware)) | 1091 | Config->LargeAddressAware = Args.hasFlag( |
| 995 | Config->LargeAddressAware = true; | 1092 | OPT_largeaddressaware, OPT_largeaddressaware_no, Config->is64()); |
| 996 | 1093 | ||
| 997 | // Handle /highentropyva | 1094 | // Handle /highentropyva |
| 998 | if (Config->is64() && !Args.hasArg(OPT_highentropyva_no)) | 1095 | Config->HighEntropyVA = |
| 999 | Config->HighEntropyVA = true; | 1096 | Config->is64() && |
| 1097 | Args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true); | ||
| 1098 | |||
| 1099 | if (!Config->DynamicBase && | ||
| 1100 | (Config->Machine == ARMNT || Config->Machine == ARM64)) | ||
| 1101 | error("/dynamicbase:no is not compatible with " + | ||
| 1102 | machineToStr(Config->Machine)); | ||
| 1000 | 1103 | ||
| 1001 | // Handle /entry and /dll | 1104 | // Handle /entry and /dll |
| 1002 | if (auto *Arg = Args.getLastArg(OPT_entry)) { | 1105 | if (auto *Arg = Args.getLastArg(OPT_entry)) { |
| 1003 | Config->Entry = addUndefined(mangle(Arg->getValue())); | 1106 | Config->Entry = addUndefined(mangle(Arg->getValue())); |
| 1004 | } else if (Args.hasArg(OPT_dll) && !Config->NoEntry) { | 1107 | } else if (!Config->Entry && !Config->NoEntry) { |
| 1005 | StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12" | 1108 | if (Args.hasArg(OPT_dll)) { |
| 1006 | : "_DllMainCRTStartup"; | 1109 | StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12" |
| 1007 | Config->Entry = addUndefined(S); | 1110 | : "_DllMainCRTStartup"; |
| 1008 | } else if (!Config->NoEntry) { | 1111 | Config->Entry = addUndefined(S); |
| 1009 | // Windows specific -- If entry point name is not given, we need to | 1112 | } else { |
| 1010 | // infer that from user-defined entry name. | 1113 | // Windows specific -- If entry point name is not given, we need to |
| 1011 | StringRef S = findDefaultEntry(); | 1114 | // infer that from user-defined entry name. |
| 1012 | if (S.empty()) | 1115 | StringRef S = findDefaultEntry(); |
| 1013 | fatal("entry point must be defined"); | 1116 | if (S.empty()) |
| 1014 | Config->Entry = addUndefined(S); | 1117 | fatal("entry point must be defined"); |
| 1015 | log("Entry name inferred: " + S); | 1118 | Config->Entry = addUndefined(S); |
| 1119 | log("Entry name inferred: " + S); | ||
| 1120 | } | ||
| 1016 | } | 1121 | } |
| 1017 | 1122 | ||
| 1018 | // Handle /export | 1123 | // Handle /export |
| ... | @@ -1034,7 +1139,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1034,7 +1139,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1034 | } | 1139 | } |
| 1035 | 1140 | ||
| 1036 | // Handle generation of import library from a def file. | 1141 | // Handle generation of import library from a def file. |
| 1037 | if (!Args.hasArgNoClaim(OPT_INPUT)) { | 1142 | if (!Args.hasArg(OPT_INPUT)) { |
| 1038 | fixupExports(); | 1143 | fixupExports(); |
| 1039 | createImportLibrary(/*AsLib=*/true); | 1144 | createImportLibrary(/*AsLib=*/true); |
| 1040 | return; | 1145 | return; |
| ... | @@ -1057,34 +1162,32 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1057,34 +1162,32 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1057 | } | 1162 | } |
| 1058 | 1163 | ||
| 1059 | // Put the PDB next to the image if no /pdb flag was passed. | 1164 | // Put the PDB next to the image if no /pdb flag was passed. |
| 1060 | if (Config->Debug && Config->PDBPath.empty()) { | 1165 | if (ShouldCreatePDB && Config->PDBPath.empty()) { |
| 1061 | Config->PDBPath = Config->OutputFile; | 1166 | Config->PDBPath = Config->OutputFile; |
| 1062 | sys::path::replace_extension(Config->PDBPath, ".pdb"); | 1167 | sys::path::replace_extension(Config->PDBPath, ".pdb"); |
| 1063 | } | 1168 | } |
| 1064 | 1169 | ||
| 1065 | // Disable PDB generation if the user requested it. | ||
| 1066 | if (Args.hasArg(OPT_nopdb)) | ||
| 1067 | Config->PDBPath = ""; | ||
| 1068 | |||
| 1069 | // Set default image base if /base is not given. | 1170 | // Set default image base if /base is not given. |
| 1070 | if (Config->ImageBase == uint64_t(-1)) | 1171 | if (Config->ImageBase == uint64_t(-1)) |
| 1071 | Config->ImageBase = getDefaultImageBase(); | 1172 | Config->ImageBase = getDefaultImageBase(); |
| 1072 | 1173 | ||
| 1073 | Symtab.addSynthetic(mangle("__ImageBase"), nullptr); | 1174 | Symtab->addSynthetic(mangle("__ImageBase"), nullptr); |
| 1074 | if (Config->Machine == I386) { | 1175 | if (Config->Machine == I386) { |
| 1075 | Symtab.addAbsolute("___safe_se_handler_table", 0); | 1176 | Symtab->addAbsolute("___safe_se_handler_table", 0); |
| 1076 | Symtab.addAbsolute("___safe_se_handler_count", 0); | 1177 | Symtab->addAbsolute("___safe_se_handler_count", 0); |
| 1077 | } | 1178 | } |
| 1078 | 1179 | ||
| 1079 | // We do not support /guard:cf (control flow protection) yet. | 1180 | // We do not support /guard:cf (control flow protection) yet. |
| 1080 | // Define CFG symbols anyway so that we can link MSVC 2015 CRT. | 1181 | // Define CFG symbols anyway so that we can link MSVC 2015 CRT. |
| 1081 | Symtab.addAbsolute(mangle("__guard_fids_count"), 0); | 1182 | Symtab->addAbsolute(mangle("__guard_fids_count"), 0); |
| 1082 | Symtab.addAbsolute(mangle("__guard_fids_table"), 0); | 1183 | Symtab->addAbsolute(mangle("__guard_fids_table"), 0); |
| 1083 | Symtab.addAbsolute(mangle("__guard_flags"), 0x100); | 1184 | Symtab->addAbsolute(mangle("__guard_flags"), 0x100); |
| 1084 | Symtab.addAbsolute(mangle("__guard_iat_count"), 0); | 1185 | Symtab->addAbsolute(mangle("__guard_iat_count"), 0); |
| 1085 | Symtab.addAbsolute(mangle("__guard_iat_table"), 0); | 1186 | Symtab->addAbsolute(mangle("__guard_iat_table"), 0); |
| 1086 | Symtab.addAbsolute(mangle("__guard_longjmp_count"), 0); | 1187 | Symtab->addAbsolute(mangle("__guard_longjmp_count"), 0); |
| 1087 | Symtab.addAbsolute(mangle("__guard_longjmp_table"), 0); | 1188 | Symtab->addAbsolute(mangle("__guard_longjmp_table"), 0); |
| 1189 | // Needed for MSVC 2017 15.5 CRT. | ||
| 1190 | Symtab->addAbsolute(mangle("__enclave_config"), 0); | ||
| 1088 | 1191 | ||
| 1089 | // This code may add new undefined symbols to the link, which may enqueue more | 1192 | // This code may add new undefined symbols to the link, which may enqueue more |
| 1090 | // symbol resolution tasks, so we need to continue executing tasks until we | 1193 | // symbol resolution tasks, so we need to continue executing tasks until we |
| ... | @@ -1093,7 +1196,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1093,7 +1196,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1093 | // Windows specific -- if entry point is not found, | 1196 | // Windows specific -- if entry point is not found, |
| 1094 | // search for its mangled names. | 1197 | // search for its mangled names. |
| 1095 | if (Config->Entry) | 1198 | if (Config->Entry) |
| 1096 | Symtab.mangleMaybe(Config->Entry); | 1199 | Symtab->mangleMaybe(Config->Entry); |
| 1097 | 1200 | ||
| 1098 | // Windows specific -- Make sure we resolve all dllexported symbols. | 1201 | // Windows specific -- Make sure we resolve all dllexported symbols. |
| 1099 | for (Export &E : Config->Exports) { | 1202 | for (Export &E : Config->Exports) { |
| ... | @@ -1101,7 +1204,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1101,7 +1204,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1101 | continue; | 1204 | continue; |
| 1102 | E.Sym = addUndefined(E.Name); | 1205 | E.Sym = addUndefined(E.Name); |
| 1103 | if (!E.Directives) | 1206 | if (!E.Directives) |
| 1104 | Symtab.mangleMaybe(E.Sym); | 1207 | Symtab->mangleMaybe(E.Sym); |
| 1105 | } | 1208 | } |
| 1106 | 1209 | ||
| 1107 | // Add weak aliases. Weak aliases is a mechanism to give remaining | 1210 | // Add weak aliases. Weak aliases is a mechanism to give remaining |
| ... | @@ -1109,20 +1212,20 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1109,20 +1212,20 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1109 | for (auto Pair : Config->AlternateNames) { | 1212 | for (auto Pair : Config->AlternateNames) { |
| 1110 | StringRef From = Pair.first; | 1213 | StringRef From = Pair.first; |
| 1111 | StringRef To = Pair.second; | 1214 | StringRef To = Pair.second; |
| 1112 | Symbol *Sym = Symtab.find(From); | 1215 | Symbol *Sym = Symtab->find(From); |
| 1113 | if (!Sym) | 1216 | if (!Sym) |
| 1114 | continue; | 1217 | continue; |
| 1115 | if (auto *U = dyn_cast<Undefined>(Sym->body())) | 1218 | if (auto *U = dyn_cast<Undefined>(Sym)) |
| 1116 | if (!U->WeakAlias) | 1219 | if (!U->WeakAlias) |
| 1117 | U->WeakAlias = Symtab.addUndefined(To); | 1220 | U->WeakAlias = Symtab->addUndefined(To); |
| 1118 | } | 1221 | } |
| 1119 | 1222 | ||
| 1120 | // Windows specific -- if __load_config_used can be resolved, resolve it. | 1223 | // Windows specific -- if __load_config_used can be resolved, resolve it. |
| 1121 | if (Symtab.findUnderscore("_load_config_used")) | 1224 | if (Symtab->findUnderscore("_load_config_used")) |
| 1122 | addUndefined(mangle("_load_config_used")); | 1225 | addUndefined(mangle("_load_config_used")); |
| 1123 | } while (run()); | 1226 | } while (run()); |
| 1124 | 1227 | ||
| 1125 | if (ErrorCount) | 1228 | if (errorCount()) |
| 1126 | return; | 1229 | return; |
| 1127 | 1230 | ||
| 1128 | // If /msvclto is given, we use the MSVC linker to link LTO output files. | 1231 | // If /msvclto is given, we use the MSVC linker to link LTO output files. |
| ... | @@ -1134,11 +1237,13 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1134,11 +1237,13 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1134 | 1237 | ||
| 1135 | // Do LTO by compiling bitcode input files to a set of native COFF files then | 1238 | // Do LTO by compiling bitcode input files to a set of native COFF files then |
| 1136 | // link those files. | 1239 | // link those files. |
| 1137 | Symtab.addCombinedLTOObjects(); | 1240 | Symtab->addCombinedLTOObjects(); |
| 1138 | run(); | 1241 | run(); |
| 1139 | 1242 | ||
| 1140 | // Make sure we have resolved all symbols. | 1243 | // Make sure we have resolved all symbols. |
| 1141 | Symtab.reportRemainingUndefines(); | 1244 | Symtab->reportRemainingUndefines(); |
| 1245 | if (errorCount()) | ||
| 1246 | return; | ||
| 1142 | 1247 | ||
| 1143 | // Windows specific -- if no /subsystem is given, we need to infer | 1248 | // Windows specific -- if no /subsystem is given, we need to infer |
| 1144 | // that from entry point name. | 1249 | // that from entry point name. |
| ... | @@ -1149,14 +1254,34 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1149,14 +1254,34 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1149 | } | 1254 | } |
| 1150 | 1255 | ||
| 1151 | // Handle /safeseh. | 1256 | // Handle /safeseh. |
| 1152 | if (Args.hasArg(OPT_safeseh)) { | 1257 | if (Args.hasFlag(OPT_safeseh, OPT_safeseh_no, false)) { |
| 1153 | for (ObjectFile *File : Symtab.ObjectFiles) | 1258 | for (ObjFile *File : ObjFile::Instances) |
| 1154 | if (!File->SEHCompat) | 1259 | if (!File->SEHCompat) |
| 1155 | error("/safeseh: " + File->getName() + " is not compatible with SEH"); | 1260 | error("/safeseh: " + File->getName() + " is not compatible with SEH"); |
| 1156 | if (ErrorCount) | 1261 | if (errorCount()) |
| 1157 | return; | 1262 | return; |
| 1158 | } | 1263 | } |
| 1159 | 1264 | ||
| 1265 | // In MinGW, all symbols are automatically exported if no symbols | ||
| 1266 | // are chosen to be exported. | ||
| 1267 | if (Config->DLL && ((Config->MinGW && Config->Exports.empty()) || | ||
| 1268 | Args.hasArg(OPT_export_all_symbols))) { | ||
| 1269 | AutoExporter Exporter; | ||
| 1270 | |||
| 1271 | Symtab->forEachSymbol([=](Symbol *S) { | ||
| 1272 | auto *Def = dyn_cast<Defined>(S); | ||
| 1273 | if (!Exporter.shouldExport(Def)) | ||
| 1274 | return; | ||
| 1275 | Export E; | ||
| 1276 | E.Name = Def->getName(); | ||
| 1277 | E.Sym = Def; | ||
| 1278 | if (Def->getChunk() && | ||
| 1279 | !(Def->getChunk()->getPermissions() & IMAGE_SCN_MEM_EXECUTE)) | ||
| 1280 | E.Data = true; | ||
| 1281 | Config->Exports.push_back(E); | ||
| 1282 | }); | ||
| 1283 | } | ||
| 1284 | |||
| 1160 | // Windows specific -- when we are creating a .dll file, we also | 1285 | // Windows specific -- when we are creating a .dll file, we also |
| 1161 | // need to create a .lib file. | 1286 | // need to create a .lib file. |
| 1162 | if (!Config->Exports.empty() || Config->DLL) { | 1287 | if (!Config->Exports.empty() || Config->DLL) { |
| ... | @@ -1165,20 +1290,45 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1165,20 +1290,45 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1165 | assignExportOrdinals(); | 1290 | assignExportOrdinals(); |
| 1166 | } | 1291 | } |
| 1167 | 1292 | ||
| 1293 | // Handle /output-def (MinGW specific). | ||
| 1294 | if (auto *Arg = Args.getLastArg(OPT_output_def)) | ||
| 1295 | writeDefFile(Arg->getValue()); | ||
| 1296 | |||
| 1297 | // Set extra alignment for .comm symbols | ||
| 1298 | for (auto Pair : Config->AlignComm) { | ||
| 1299 | StringRef Name = Pair.first; | ||
| 1300 | uint32_t Alignment = Pair.second; | ||
| 1301 | |||
| 1302 | Symbol *Sym = Symtab->find(Name); | ||
| 1303 | if (!Sym) { | ||
| 1304 | warn("/aligncomm symbol " + Name + " not found"); | ||
| 1305 | continue; | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | auto *DC = dyn_cast<DefinedCommon>(Sym); | ||
| 1309 | if (!DC) { | ||
| 1310 | warn("/aligncomm symbol " + Name + " of wrong kind"); | ||
| 1311 | continue; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | CommonChunk *C = DC->getChunk(); | ||
| 1315 | C->Alignment = std::max(C->Alignment, Alignment); | ||
| 1316 | } | ||
| 1317 | |||
| 1168 | // Windows specific -- Create a side-by-side manifest file. | 1318 | // Windows specific -- Create a side-by-side manifest file. |
| 1169 | if (Config->Manifest == Configuration::SideBySide) | 1319 | if (Config->Manifest == Configuration::SideBySide) |
| 1170 | createSideBySideManifest(); | 1320 | createSideBySideManifest(); |
| 1171 | 1321 | ||
| 1172 | // Identify unreferenced COMDAT sections. | 1322 | // Identify unreferenced COMDAT sections. |
| 1173 | if (Config->DoGC) | 1323 | if (Config->DoGC) |
| 1174 | markLive(Symtab.getChunks()); | 1324 | markLive(Symtab->getChunks()); |
| 1175 | 1325 | ||
| 1176 | // Identify identical COMDAT sections to merge them. | 1326 | // Identify identical COMDAT sections to merge them. |
| 1177 | if (Config->DoICF) | 1327 | if (Config->DoICF) |
| 1178 | doICF(Symtab.getChunks()); | 1328 | doICF(Symtab->getChunks()); |
| 1179 | 1329 | ||
| 1180 | // Write the result. | 1330 | // Write the result. |
| 1181 | writeResult(&Symtab); | 1331 | writeResult(); |
| 1182 | } | 1332 | } |
| 1183 | 1333 | ||
| 1184 | } // namespace coff | 1334 | } // namespace coff |
deps/lld/COFF/Driver.h+29-21| ... | @@ -12,10 +12,11 @@ | ... | @@ -12,10 +12,11 @@ |
| 12 | 12 | ||
| 13 | #include "Config.h" | 13 | #include "Config.h" |
| 14 | #include "SymbolTable.h" | 14 | #include "SymbolTable.h" |
| 15 | #include "lld/Core/LLVM.h" | 15 | #include "lld/Common/LLVM.h" |
| 16 | #include "lld/Core/Reproduce.h" | 16 | #include "lld/Common/Reproduce.h" |
| 17 | #include "llvm/ADT/Optional.h" | 17 | #include "llvm/ADT/Optional.h" |
| 18 | #include "llvm/ADT/StringRef.h" | 18 | #include "llvm/ADT/StringRef.h" |
| 19 | #include "llvm/ADT/StringSet.h" | ||
| 19 | #include "llvm/Object/Archive.h" | 20 | #include "llvm/Object/Archive.h" |
| 20 | #include "llvm/Object/COFF.h" | 21 | #include "llvm/Object/COFF.h" |
| 21 | #include "llvm/Option/Arg.h" | 22 | #include "llvm/Option/Arg.h" |
| ... | @@ -36,31 +37,39 @@ using llvm::COFF::WindowsSubsystem; | ... | @@ -36,31 +37,39 @@ using llvm::COFF::WindowsSubsystem; |
| 36 | using llvm::Optional; | 37 | using llvm::Optional; |
| 37 | 38 | ||
| 38 | // Implemented in MarkLive.cpp. | 39 | // Implemented in MarkLive.cpp. |
| 39 | void markLive(const std::vector<Chunk *> &Chunks); | 40 | void markLive(ArrayRef<Chunk *> Chunks); |
| 40 | 41 | ||
| 41 | // Implemented in ICF.cpp. | 42 | // Implemented in ICF.cpp. |
| 42 | void doICF(const std::vector<Chunk *> &Chunks); | 43 | void doICF(ArrayRef<Chunk *> Chunks); |
| 43 | 44 | ||
| 44 | class ArgParser { | 45 | class COFFOptTable : public llvm::opt::OptTable { |
| 45 | public: | 46 | public: |
| 46 | // Parses command line options. | 47 | COFFOptTable(); |
| 47 | llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args); | 48 | }; |
| 48 | 49 | ||
| 49 | // Concatenate LINK environment varirable and given arguments and parse them. | 50 | class ArgParser { |
| 51 | public: | ||
| 52 | // Concatenate LINK environment variable and given arguments and parse them. | ||
| 50 | llvm::opt::InputArgList parseLINK(std::vector<const char *> Args); | 53 | llvm::opt::InputArgList parseLINK(std::vector<const char *> Args); |
| 51 | 54 | ||
| 52 | // Tokenizes a given string and then parses as command line options. | 55 | // Tokenizes a given string and then parses as command line options. |
| 53 | llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); } | 56 | llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); } |
| 54 | 57 | ||
| 58 | // Tokenizes a given string and then parses as command line options in | ||
| 59 | // .drectve section. | ||
| 60 | llvm::opt::InputArgList parseDirectives(StringRef S); | ||
| 61 | |||
| 55 | private: | 62 | private: |
| 63 | // Parses command line options. | ||
| 64 | llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args); | ||
| 65 | |||
| 56 | std::vector<const char *> tokenize(StringRef S); | 66 | std::vector<const char *> tokenize(StringRef S); |
| 57 | 67 | ||
| 58 | std::vector<const char *> replaceResponseFiles(std::vector<const char *>); | 68 | COFFOptTable Table; |
| 59 | }; | 69 | }; |
| 60 | 70 | ||
| 61 | class LinkerDriver { | 71 | class LinkerDriver { |
| 62 | public: | 72 | public: |
| 63 | LinkerDriver() { coff::Symtab = &Symtab; } | ||
| 64 | void link(llvm::ArrayRef<const char *> Args); | 73 | void link(llvm::ArrayRef<const char *> Args); |
| 65 | 74 | ||
| 66 | // Used by the resolver to parse .drectve section contents. | 75 | // Used by the resolver to parse .drectve section contents. |
| ... | @@ -70,10 +79,9 @@ public: | ... | @@ -70,10 +79,9 @@ public: |
| 70 | void enqueueArchiveMember(const Archive::Child &C, StringRef SymName, | 79 | void enqueueArchiveMember(const Archive::Child &C, StringRef SymName, |
| 71 | StringRef ParentName); | 80 | StringRef ParentName); |
| 72 | 81 | ||
| 73 | private: | 82 | MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> MB); |
| 74 | ArgParser Parser; | ||
| 75 | SymbolTable Symtab; | ||
| 76 | 83 | ||
| 84 | private: | ||
| 77 | std::unique_ptr<llvm::TarWriter> Tar; // for /linkrepro | 85 | std::unique_ptr<llvm::TarWriter> Tar; // for /linkrepro |
| 78 | 86 | ||
| 79 | // Opens a file. Path has to be resolved already. | 87 | // Opens a file. Path has to be resolved already. |
| ... | @@ -93,7 +101,7 @@ private: | ... | @@ -93,7 +101,7 @@ private: |
| 93 | std::set<std::string> VisitedFiles; | 101 | std::set<std::string> VisitedFiles; |
| 94 | std::set<std::string> VisitedLibs; | 102 | std::set<std::string> VisitedLibs; |
| 95 | 103 | ||
| 96 | SymbolBody *addUndefined(StringRef Sym); | 104 | Symbol *addUndefined(StringRef Sym); |
| 97 | StringRef mangle(StringRef Sym); | 105 | StringRef mangle(StringRef Sym); |
| 98 | 106 | ||
| 99 | // Windows specific -- "main" is not the only main function in Windows. | 107 | // Windows specific -- "main" is not the only main function in Windows. |
| ... | @@ -108,12 +116,11 @@ private: | ... | @@ -108,12 +116,11 @@ private: |
| 108 | 116 | ||
| 109 | void invokeMSVC(llvm::opt::InputArgList &Args); | 117 | void invokeMSVC(llvm::opt::InputArgList &Args); |
| 110 | 118 | ||
| 111 | MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> MB); | 119 | void addBuffer(std::unique_ptr<MemoryBuffer> MB, bool WholeArchive); |
| 112 | void addBuffer(std::unique_ptr<MemoryBuffer> MB); | ||
| 113 | void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName, | 120 | void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName, |
| 114 | StringRef ParentName); | 121 | StringRef ParentName); |
| 115 | 122 | ||
| 116 | void enqueuePath(StringRef Path); | 123 | void enqueuePath(StringRef Path, bool WholeArchive); |
| 117 | 124 | ||
| 118 | void enqueueTask(std::function<void()> Task); | 125 | void enqueueTask(std::function<void()> Task); |
| 119 | bool run(); | 126 | bool run(); |
| ... | @@ -121,6 +128,8 @@ private: | ... | @@ -121,6 +128,8 @@ private: |
| 121 | std::list<std::function<void()>> TaskQueue; | 128 | std::list<std::function<void()>> TaskQueue; |
| 122 | std::vector<StringRef> FilePaths; | 129 | std::vector<StringRef> FilePaths; |
| 123 | std::vector<MemoryBufferRef> Resources; | 130 | std::vector<MemoryBufferRef> Resources; |
| 131 | |||
| 132 | llvm::StringSet<> DirectivesExports; | ||
| 124 | }; | 133 | }; |
| 125 | 134 | ||
| 126 | // Functions below this line are defined in DriverUtils.cpp. | 135 | // Functions below this line are defined in DriverUtils.cpp. |
| ... | @@ -145,6 +154,7 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major, | ... | @@ -145,6 +154,7 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major, |
| 145 | void parseAlternateName(StringRef); | 154 | void parseAlternateName(StringRef); |
| 146 | void parseMerge(StringRef); | 155 | void parseMerge(StringRef); |
| 147 | void parseSection(StringRef); | 156 | void parseSection(StringRef); |
| 157 | void parseAligncomm(StringRef); | ||
| 148 | 158 | ||
| 149 | // Parses a string in the form of "EMBED[,=<integer>]|NO". | 159 | // Parses a string in the form of "EMBED[,=<integer>]|NO". |
| 150 | void parseManifest(StringRef Arg); | 160 | void parseManifest(StringRef Arg); |
| ... | @@ -167,10 +177,8 @@ void assignExportOrdinals(); | ... | @@ -167,10 +177,8 @@ void assignExportOrdinals(); |
| 167 | // incompatible objects. | 177 | // incompatible objects. |
| 168 | void checkFailIfMismatch(StringRef Arg); | 178 | void checkFailIfMismatch(StringRef Arg); |
| 169 | 179 | ||
| 170 | // Convert Windows resource files (.res files) to a .obj file | 180 | // Convert Windows resource files (.res files) to a .obj file. |
| 171 | // using cvtres.exe. | 181 | MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs); |
| 172 | std::unique_ptr<MemoryBuffer> | ||
| 173 | convertResToCOFF(const std::vector<MemoryBufferRef> &MBs); | ||
| 174 | 182 | ||
| 175 | void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects); | 183 | void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects); |
| 176 | 184 |
deps/lld/COFF/DriverUtils.cpp+149-83| ... | @@ -15,9 +15,9 @@ | ... | @@ -15,9 +15,9 @@ |
| 15 | 15 | ||
| 16 | #include "Config.h" | 16 | #include "Config.h" |
| 17 | #include "Driver.h" | 17 | #include "Driver.h" |
| 18 | #include "Error.h" | ||
| 19 | #include "Memory.h" | ||
| 20 | #include "Symbols.h" | 18 | #include "Symbols.h" |
| 19 | #include "lld/Common/ErrorHandler.h" | ||
| 20 | #include "lld/Common/Memory.h" | ||
| 21 | #include "llvm/ADT/Optional.h" | 21 | #include "llvm/ADT/Optional.h" |
| 22 | #include "llvm/ADT/StringSwitch.h" | 22 | #include "llvm/ADT/StringSwitch.h" |
| 23 | #include "llvm/BinaryFormat/COFF.h" | 23 | #include "llvm/BinaryFormat/COFF.h" |
| ... | @@ -32,12 +32,11 @@ | ... | @@ -32,12 +32,11 @@ |
| 32 | #include "llvm/Support/Process.h" | 32 | #include "llvm/Support/Process.h" |
| 33 | #include "llvm/Support/Program.h" | 33 | #include "llvm/Support/Program.h" |
| 34 | #include "llvm/Support/raw_ostream.h" | 34 | #include "llvm/Support/raw_ostream.h" |
| 35 | #include "llvm/WindowsManifest/WindowsManifestMerger.h" | ||
| 35 | #include <memory> | 36 | #include <memory> |
| 36 | 37 | ||
| 37 | using namespace llvm::COFF; | 38 | using namespace llvm::COFF; |
| 38 | using namespace llvm; | 39 | using namespace llvm; |
| 39 | using llvm::cl::ExpandResponseFiles; | ||
| 40 | using llvm::cl::TokenizeWindowsCommandLine; | ||
| 41 | using llvm::sys::Process; | 40 | using llvm::sys::Process; |
| 42 | 41 | ||
| 43 | namespace lld { | 42 | namespace lld { |
| ... | @@ -58,7 +57,7 @@ public: | ... | @@ -58,7 +57,7 @@ public: |
| 58 | void run() { | 57 | void run() { |
| 59 | ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog); | 58 | ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog); |
| 60 | if (auto EC = ExeOrErr.getError()) | 59 | if (auto EC = ExeOrErr.getError()) |
| 61 | fatal(EC, "unable to find " + Prog + " in PATH: "); | 60 | fatal("unable to find " + Prog + " in PATH: " + EC.message()); |
| 62 | StringRef Exe = Saver.save(*ExeOrErr); | 61 | StringRef Exe = Saver.save(*ExeOrErr); |
| 63 | Args.insert(Args.begin(), Exe); | 62 | Args.insert(Args.begin(), Exe); |
| 64 | 63 | ||
| ... | @@ -221,6 +220,22 @@ void parseSection(StringRef S) { | ... | @@ -221,6 +220,22 @@ void parseSection(StringRef S) { |
| 221 | Config->Section[Name] = parseSectionAttributes(Attrs); | 220 | Config->Section[Name] = parseSectionAttributes(Attrs); |
| 222 | } | 221 | } |
| 223 | 222 | ||
| 223 | // Parses /aligncomm option argument. | ||
| 224 | void parseAligncomm(StringRef S) { | ||
| 225 | StringRef Name, Align; | ||
| 226 | std::tie(Name, Align) = S.split(','); | ||
| 227 | if (Name.empty() || Align.empty()) { | ||
| 228 | error("/aligncomm: invalid argument: " + S); | ||
| 229 | return; | ||
| 230 | } | ||
| 231 | int V; | ||
| 232 | if (Align.getAsInteger(0, V)) { | ||
| 233 | error("/aligncomm: invalid argument: " + S); | ||
| 234 | return; | ||
| 235 | } | ||
| 236 | Config->AlignComm[Name] = std::max(Config->AlignComm[Name], 1 << V); | ||
| 237 | } | ||
| 238 | |||
| 224 | // Parses a string in the form of "EMBED[,=<integer>]|NO". | 239 | // Parses a string in the form of "EMBED[,=<integer>]|NO". |
| 225 | // Results are directly written to Config. | 240 | // Results are directly written to Config. |
| 226 | void parseManifest(StringRef Arg) { | 241 | void parseManifest(StringRef Arg) { |
| ... | @@ -273,14 +288,14 @@ public: | ... | @@ -273,14 +288,14 @@ public: |
| 273 | TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") { | 288 | TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") { |
| 274 | SmallString<128> S; | 289 | SmallString<128> S; |
| 275 | if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S)) | 290 | if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S)) |
| 276 | fatal(EC, "cannot create a temporary file"); | 291 | fatal("cannot create a temporary file: " + EC.message()); |
| 277 | Path = S.str(); | 292 | Path = S.str(); |
| 278 | 293 | ||
| 279 | if (!Contents.empty()) { | 294 | if (!Contents.empty()) { |
| 280 | std::error_code EC; | 295 | std::error_code EC; |
| 281 | raw_fd_ostream OS(Path, EC, sys::fs::F_None); | 296 | raw_fd_ostream OS(Path, EC, sys::fs::F_None); |
| 282 | if (EC) | 297 | if (EC) |
| 283 | fatal(EC, "failed to open " + Path); | 298 | fatal("failed to open " + Path + ": " + EC.message()); |
| 284 | OS << Contents; | 299 | OS << Contents; |
| 285 | } | 300 | } |
| 286 | } | 301 | } |
| ... | @@ -302,7 +317,7 @@ public: | ... | @@ -302,7 +317,7 @@ public: |
| 302 | // is called (you cannot remove an opened file on Windows.) | 317 | // is called (you cannot remove an opened file on Windows.) |
| 303 | std::unique_ptr<MemoryBuffer> getMemoryBuffer() { | 318 | std::unique_ptr<MemoryBuffer> getMemoryBuffer() { |
| 304 | // IsVolatileSize=true forces MemoryBuffer to not use mmap(). | 319 | // IsVolatileSize=true forces MemoryBuffer to not use mmap(). |
| 305 | return check(MemoryBuffer::getFile(Path, /*FileSize=*/-1, | 320 | return CHECK(MemoryBuffer::getFile(Path, /*FileSize=*/-1, |
| 306 | /*RequiresNullTerminator=*/false, | 321 | /*RequiresNullTerminator=*/false, |
| 307 | /*IsVolatileSize=*/true), | 322 | /*IsVolatileSize=*/true), |
| 308 | "could not open " + Path); | 323 | "could not open " + Path); |
| ... | @@ -312,16 +327,9 @@ public: | ... | @@ -312,16 +327,9 @@ public: |
| 312 | }; | 327 | }; |
| 313 | } | 328 | } |
| 314 | 329 | ||
| 315 | // Create the default manifest file as a temporary file. | 330 | static std::string createDefaultXml() { |
| 316 | TemporaryFile createDefaultXml() { | 331 | std::string Ret; |
| 317 | // Create a temporary file. | 332 | raw_string_ostream OS(Ret); |
| 318 | TemporaryFile File("defaultxml", "manifest"); | ||
| 319 | |||
| 320 | // Open the temporary file for writing. | ||
| 321 | std::error_code EC; | ||
| 322 | raw_fd_ostream OS(File.Path, EC, sys::fs::F_Text); | ||
| 323 | if (EC) | ||
| 324 | fatal(EC, "failed to open " + File.Path); | ||
| 325 | 333 | ||
| 326 | // Emit the XML. Note that we do *not* verify that the XML attributes are | 334 | // Emit the XML. Note that we do *not* verify that the XML attributes are |
| 327 | // syntactically correct. This is intentional for link.exe compatibility. | 335 | // syntactically correct. This is intentional for link.exe compatibility. |
| ... | @@ -337,46 +345,77 @@ TemporaryFile createDefaultXml() { | ... | @@ -337,46 +345,77 @@ TemporaryFile createDefaultXml() { |
| 337 | << " </requestedPrivileges>\n" | 345 | << " </requestedPrivileges>\n" |
| 338 | << " </security>\n" | 346 | << " </security>\n" |
| 339 | << " </trustInfo>\n"; | 347 | << " </trustInfo>\n"; |
| 340 | if (!Config->ManifestDependency.empty()) { | 348 | } |
| 341 | OS << " <dependency>\n" | 349 | if (!Config->ManifestDependency.empty()) { |
| 342 | << " <dependentAssembly>\n" | 350 | OS << " <dependency>\n" |
| 343 | << " <assemblyIdentity " << Config->ManifestDependency << " />\n" | 351 | << " <dependentAssembly>\n" |
| 344 | << " </dependentAssembly>\n" | 352 | << " <assemblyIdentity " << Config->ManifestDependency << " />\n" |
| 345 | << " </dependency>\n"; | 353 | << " </dependentAssembly>\n" |
| 346 | } | 354 | << " </dependency>\n"; |
| 347 | } | 355 | } |
| 348 | OS << "</assembly>\n"; | 356 | OS << "</assembly>\n"; |
| 349 | OS.close(); | 357 | return OS.str(); |
| 350 | return File; | ||
| 351 | } | 358 | } |
| 352 | 359 | ||
| 353 | static std::string readFile(StringRef Path) { | 360 | static std::string createManifestXmlWithInternalMt(StringRef DefaultXml) { |
| 354 | std::unique_ptr<MemoryBuffer> MB = | 361 | std::unique_ptr<MemoryBuffer> DefaultXmlCopy = |
| 355 | check(MemoryBuffer::getFile(Path), "could not open " + Path); | 362 | MemoryBuffer::getMemBufferCopy(DefaultXml); |
| 356 | return MB->getBuffer(); | 363 | |
| 364 | windows_manifest::WindowsManifestMerger Merger; | ||
| 365 | if (auto E = Merger.merge(*DefaultXmlCopy.get())) | ||
| 366 | fatal("internal manifest tool failed on default xml: " + | ||
| 367 | toString(std::move(E))); | ||
| 368 | |||
| 369 | for (StringRef Filename : Config->ManifestInput) { | ||
| 370 | std::unique_ptr<MemoryBuffer> Manifest = | ||
| 371 | check(MemoryBuffer::getFile(Filename)); | ||
| 372 | if (auto E = Merger.merge(*Manifest.get())) | ||
| 373 | fatal("internal manifest tool failed on file " + Filename + ": " + | ||
| 374 | toString(std::move(E))); | ||
| 375 | } | ||
| 376 | |||
| 377 | return Merger.getMergedManifest().get()->getBuffer(); | ||
| 357 | } | 378 | } |
| 358 | 379 | ||
| 359 | static std::string createManifestXml() { | 380 | static std::string createManifestXmlWithExternalMt(StringRef DefaultXml) { |
| 360 | // Create the default manifest file. | 381 | // Create the default manifest file as a temporary file. |
| 361 | TemporaryFile File1 = createDefaultXml(); | 382 | TemporaryFile Default("defaultxml", "manifest"); |
| 362 | if (Config->ManifestInput.empty()) | 383 | std::error_code EC; |
| 363 | return readFile(File1.Path); | 384 | raw_fd_ostream OS(Default.Path, EC, sys::fs::F_Text); |
| 385 | if (EC) | ||
| 386 | fatal("failed to open " + Default.Path + ": " + EC.message()); | ||
| 387 | OS << DefaultXml; | ||
| 388 | OS.close(); | ||
| 364 | 389 | ||
| 365 | // If manifest files are supplied by the user using /MANIFESTINPUT | 390 | // Merge user-supplied manifests if they are given. Since libxml2 is not |
| 366 | // option, we need to merge them with the default manifest. | 391 | // enabled, we must shell out to Microsoft's mt.exe tool. |
| 367 | TemporaryFile File2("user", "manifest"); | 392 | TemporaryFile User("user", "manifest"); |
| 368 | 393 | ||
| 369 | Executor E("mt.exe"); | 394 | Executor E("mt.exe"); |
| 370 | E.add("/manifest"); | 395 | E.add("/manifest"); |
| 371 | E.add(File1.Path); | 396 | E.add(Default.Path); |
| 372 | for (StringRef Filename : Config->ManifestInput) { | 397 | for (StringRef Filename : Config->ManifestInput) { |
| 373 | E.add("/manifest"); | 398 | E.add("/manifest"); |
| 374 | E.add(Filename); | 399 | E.add(Filename); |
| 375 | } | 400 | } |
| 376 | E.add("/nologo"); | 401 | E.add("/nologo"); |
| 377 | E.add("/out:" + StringRef(File2.Path)); | 402 | E.add("/out:" + StringRef(User.Path)); |
| 378 | E.run(); | 403 | E.run(); |
| 379 | return readFile(File2.Path); | 404 | |
| 405 | return CHECK(MemoryBuffer::getFile(User.Path), "could not open " + User.Path) | ||
| 406 | .get() | ||
| 407 | ->getBuffer(); | ||
| 408 | } | ||
| 409 | |||
| 410 | static std::string createManifestXml() { | ||
| 411 | std::string DefaultXml = createDefaultXml(); | ||
| 412 | if (Config->ManifestInput.empty()) | ||
| 413 | return DefaultXml; | ||
| 414 | |||
| 415 | if (windows_manifest::isAvailable()) | ||
| 416 | return createManifestXmlWithInternalMt(DefaultXml); | ||
| 417 | |||
| 418 | return createManifestXmlWithExternalMt(DefaultXml); | ||
| 380 | } | 419 | } |
| 381 | 420 | ||
| 382 | static std::unique_ptr<MemoryBuffer> | 421 | static std::unique_ptr<MemoryBuffer> |
| ... | @@ -386,7 +425,8 @@ createMemoryBufferForManifestRes(size_t ManifestSize) { | ... | @@ -386,7 +425,8 @@ createMemoryBufferForManifestRes(size_t ManifestSize) { |
| 386 | sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) + | 425 | sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) + |
| 387 | sizeof(object::WinResHeaderSuffix) + ManifestSize, | 426 | sizeof(object::WinResHeaderSuffix) + ManifestSize, |
| 388 | object::WIN_RES_DATA_ALIGNMENT); | 427 | object::WIN_RES_DATA_ALIGNMENT); |
| 389 | return MemoryBuffer::getNewMemBuffer(ResSize); | 428 | return MemoryBuffer::getNewMemBuffer(ResSize, |
| 429 | Config->OutputFile + ".manifest.res"); | ||
| 390 | } | 430 | } |
| 391 | 431 | ||
| 392 | static void writeResFileHeader(char *&Buf) { | 432 | static void writeResFileHeader(char *&Buf) { |
| ... | @@ -444,7 +484,7 @@ void createSideBySideManifest() { | ... | @@ -444,7 +484,7 @@ void createSideBySideManifest() { |
| 444 | std::error_code EC; | 484 | std::error_code EC; |
| 445 | raw_fd_ostream Out(Path, EC, sys::fs::F_Text); | 485 | raw_fd_ostream Out(Path, EC, sys::fs::F_Text); |
| 446 | if (EC) | 486 | if (EC) |
| 447 | fatal(EC, "failed to create manifest"); | 487 | fatal("failed to create manifest: " + EC.message()); |
| 448 | Out << createManifestXml(); | 488 | Out << createManifestXml(); |
| 449 | } | 489 | } |
| 450 | 490 | ||
| ... | @@ -459,12 +499,12 @@ Export parseExport(StringRef Arg) { | ... | @@ -459,12 +499,12 @@ Export parseExport(StringRef Arg) { |
| 459 | if (E.Name.empty()) | 499 | if (E.Name.empty()) |
| 460 | goto err; | 500 | goto err; |
| 461 | 501 | ||
| 462 | if (E.Name.find('=') != StringRef::npos) { | 502 | if (E.Name.contains('=')) { |
| 463 | StringRef X, Y; | 503 | StringRef X, Y; |
| 464 | std::tie(X, Y) = E.Name.split("="); | 504 | std::tie(X, Y) = E.Name.split("="); |
| 465 | 505 | ||
| 466 | // If "<name>=<dllname>.<name>". | 506 | // If "<name>=<dllname>.<name>". |
| 467 | if (Y.find(".") != StringRef::npos) { | 507 | if (Y.contains(".")) { |
| 468 | E.Name = X; | 508 | E.Name = X; |
| 469 | E.ForwardTo = Y; | 509 | E.ForwardTo = Y; |
| 470 | return E; | 510 | return E; |
| ... | @@ -534,7 +574,7 @@ void fixupExports() { | ... | @@ -534,7 +574,7 @@ void fixupExports() { |
| 534 | } | 574 | } |
| 535 | 575 | ||
| 536 | for (Export &E : Config->Exports) { | 576 | for (Export &E : Config->Exports) { |
| 537 | SymbolBody *Sym = E.Sym; | 577 | Symbol *Sym = E.Sym; |
| 538 | if (!E.ForwardTo.empty() || !Sym) { | 578 | if (!E.ForwardTo.empty() || !Sym) { |
| 539 | E.SymbolName = E.Name; | 579 | E.SymbolName = E.Name; |
| 540 | } else { | 580 | } else { |
| ... | @@ -554,7 +594,7 @@ void fixupExports() { | ... | @@ -554,7 +594,7 @@ void fixupExports() { |
| 554 | } | 594 | } |
| 555 | 595 | ||
| 556 | // Uniquefy by name. | 596 | // Uniquefy by name. |
| 557 | std::map<StringRef, Export *> Map; | 597 | DenseMap<StringRef, Export *> Map(Config->Exports.size()); |
| 558 | std::vector<Export> V; | 598 | std::vector<Export> V; |
| 559 | for (Export &E : Config->Exports) { | 599 | for (Export &E : Config->Exports) { |
| 560 | auto Pair = Map.insert(std::make_pair(E.ExportName, &E)); | 600 | auto Pair = Map.insert(std::make_pair(E.ExportName, &E)); |
| ... | @@ -601,10 +641,8 @@ void checkFailIfMismatch(StringRef Arg) { | ... | @@ -601,10 +641,8 @@ void checkFailIfMismatch(StringRef Arg) { |
| 601 | Config->MustMatch[K] = V; | 641 | Config->MustMatch[K] = V; |
| 602 | } | 642 | } |
| 603 | 643 | ||
| 604 | // Convert Windows resource files (.res files) to a .obj file | 644 | // Convert Windows resource files (.res files) to a .obj file. |
| 605 | // using cvtres.exe. | 645 | MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs) { |
| 606 | std::unique_ptr<MemoryBuffer> | ||
| 607 | convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) { | ||
| 608 | object::WindowsResourceParser Parser; | 646 | object::WindowsResourceParser Parser; |
| 609 | 647 | ||
| 610 | for (MemoryBufferRef MB : MBs) { | 648 | for (MemoryBufferRef MB : MBs) { |
| ... | @@ -613,14 +651,17 @@ convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) { | ... | @@ -613,14 +651,17 @@ convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) { |
| 613 | if (!RF) | 651 | if (!RF) |
| 614 | fatal("cannot compile non-resource file as resource"); | 652 | fatal("cannot compile non-resource file as resource"); |
| 615 | if (auto EC = Parser.parse(RF)) | 653 | if (auto EC = Parser.parse(RF)) |
| 616 | fatal(EC, "failed to parse .res file"); | 654 | fatal("failed to parse .res file: " + toString(std::move(EC))); |
| 617 | } | 655 | } |
| 618 | 656 | ||
| 619 | Expected<std::unique_ptr<MemoryBuffer>> E = | 657 | Expected<std::unique_ptr<MemoryBuffer>> E = |
| 620 | llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser); | 658 | llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser); |
| 621 | if (!E) | 659 | if (!E) |
| 622 | fatal(errorToErrorCode(E.takeError()), "failed to write .res to COFF"); | 660 | fatal("failed to write .res to COFF: " + toString(E.takeError())); |
| 623 | return std::move(E.get()); | 661 | |
| 662 | MemoryBufferRef MBRef = **E; | ||
| 663 | make<std::unique_ptr<MemoryBuffer>>(std::move(*E)); // take ownership | ||
| 664 | return MBRef; | ||
| 624 | } | 665 | } |
| 625 | 666 | ||
| 626 | // Run MSVC link.exe for given in-memory object files. | 667 | // Run MSVC link.exe for given in-memory object files. |
| ... | @@ -651,7 +692,7 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects) { | ... | @@ -651,7 +692,7 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects) { |
| 651 | #undef PREFIX | 692 | #undef PREFIX |
| 652 | 693 | ||
| 653 | // Create table mapping all options defined in Options.td | 694 | // Create table mapping all options defined in Options.td |
| 654 | static const llvm::opt::OptTable::Info infoTable[] = { | 695 | static const llvm::opt::OptTable::Info InfoTable[] = { |
| 655 | #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ | 696 | #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ |
| 656 | {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \ | 697 | {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \ |
| 657 | X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, | 698 | X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, |
| ... | @@ -659,30 +700,65 @@ static const llvm::opt::OptTable::Info infoTable[] = { | ... | @@ -659,30 +700,65 @@ static const llvm::opt::OptTable::Info infoTable[] = { |
| 659 | #undef OPTION | 700 | #undef OPTION |
| 660 | }; | 701 | }; |
| 661 | 702 | ||
| 662 | class COFFOptTable : public llvm::opt::OptTable { | 703 | COFFOptTable::COFFOptTable() : OptTable(InfoTable, true) {} |
| 663 | public: | ||
| 664 | COFFOptTable() : OptTable(infoTable, true) {} | ||
| 665 | }; | ||
| 666 | 704 | ||
| 667 | // Parses a given list of options. | 705 | static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) { |
| 668 | opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) { | 706 | if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) { |
| 669 | // First, replace respnose files (@<file>-style options). | 707 | StringRef S = Arg->getValue(); |
| 670 | std::vector<const char *> Argv = replaceResponseFiles(ArgsArr); | 708 | if (S != "windows" && S != "posix") |
| 709 | error("invalid response file quoting: " + S); | ||
| 710 | if (S == "windows") | ||
| 711 | return cl::TokenizeWindowsCommandLine; | ||
| 712 | return cl::TokenizeGNUCommandLine; | ||
| 713 | } | ||
| 714 | // The COFF linker always defaults to Windows quoting. | ||
| 715 | return cl::TokenizeWindowsCommandLine; | ||
| 716 | } | ||
| 671 | 717 | ||
| 718 | // Parses a given list of options. | ||
| 719 | opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) { | ||
| 672 | // Make InputArgList from string vectors. | 720 | // Make InputArgList from string vectors. |
| 673 | COFFOptTable Table; | ||
| 674 | unsigned MissingIndex; | 721 | unsigned MissingIndex; |
| 675 | unsigned MissingCount; | 722 | unsigned MissingCount; |
| 676 | opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount); | 723 | SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); |
| 724 | |||
| 725 | // We need to get the quoting style for response files before parsing all | ||
| 726 | // options so we parse here before and ignore all the options but | ||
| 727 | // --rsp-quoting. | ||
| 728 | opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount); | ||
| 729 | |||
| 730 | // Expand response files (arguments in the form of @<filename>) | ||
| 731 | // and then parse the argument again. | ||
| 732 | cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec); | ||
| 733 | Args = Table.ParseArgs(Vec, MissingIndex, MissingCount); | ||
| 677 | 734 | ||
| 678 | // Print the real command line if response files are expanded. | 735 | // Print the real command line if response files are expanded. |
| 679 | if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) { | 736 | if (Args.hasArg(OPT_verbose) && Argv.size() != Vec.size()) { |
| 680 | std::string Msg = "Command line:"; | 737 | std::string Msg = "Command line:"; |
| 681 | for (const char *S : Argv) | 738 | for (const char *S : Vec) |
| 682 | Msg += " " + std::string(S); | 739 | Msg += " " + std::string(S); |
| 683 | message(Msg); | 740 | message(Msg); |
| 684 | } | 741 | } |
| 685 | 742 | ||
| 743 | // Handle /WX early since it converts missing argument warnings to errors. | ||
| 744 | errorHandler().FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false); | ||
| 745 | |||
| 746 | if (MissingCount) | ||
| 747 | fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); | ||
| 748 | for (auto *Arg : Args.filtered(OPT_UNKNOWN)) | ||
| 749 | warn("ignoring unknown argument: " + Arg->getSpelling()); | ||
| 750 | return Args; | ||
| 751 | } | ||
| 752 | |||
| 753 | // Tokenizes and parses a given string as command line in .drective section. | ||
| 754 | opt::InputArgList ArgParser::parseDirectives(StringRef S) { | ||
| 755 | // Make InputArgList from string vectors. | ||
| 756 | unsigned MissingIndex; | ||
| 757 | unsigned MissingCount; | ||
| 758 | |||
| 759 | opt::InputArgList Args = | ||
| 760 | Table.ParseArgs(tokenize(S), MissingIndex, MissingCount); | ||
| 761 | |||
| 686 | if (MissingCount) | 762 | if (MissingCount) |
| 687 | fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); | 763 | fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); |
| 688 | for (auto *Arg : Args.filtered(OPT_UNKNOWN)) | 764 | for (auto *Arg : Args.filtered(OPT_UNKNOWN)) |
| ... | @@ -693,17 +769,17 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) { | ... | @@ -693,17 +769,17 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) { |
| 693 | // link.exe has an interesting feature. If LINK or _LINK_ environment | 769 | // link.exe has an interesting feature. If LINK or _LINK_ environment |
| 694 | // variables exist, their contents are handled as command line strings. | 770 | // variables exist, their contents are handled as command line strings. |
| 695 | // So you can pass extra arguments using them. | 771 | // So you can pass extra arguments using them. |
| 696 | opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Args) { | 772 | opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Argv) { |
| 697 | // Concatenate LINK env and command line arguments, and then parse them. | 773 | // Concatenate LINK env and command line arguments, and then parse them. |
| 698 | if (Optional<std::string> S = Process::GetEnv("LINK")) { | 774 | if (Optional<std::string> S = Process::GetEnv("LINK")) { |
| 699 | std::vector<const char *> V = tokenize(*S); | 775 | std::vector<const char *> V = tokenize(*S); |
| 700 | Args.insert(Args.begin(), V.begin(), V.end()); | 776 | Argv.insert(Argv.begin(), V.begin(), V.end()); |
| 701 | } | 777 | } |
| 702 | if (Optional<std::string> S = Process::GetEnv("_LINK_")) { | 778 | if (Optional<std::string> S = Process::GetEnv("_LINK_")) { |
| 703 | std::vector<const char *> V = tokenize(*S); | 779 | std::vector<const char *> V = tokenize(*S); |
| 704 | Args.insert(Args.begin(), V.begin(), V.end()); | 780 | Argv.insert(Argv.begin(), V.begin(), V.end()); |
| 705 | } | 781 | } |
| 706 | return parse(Args); | 782 | return parse(Argv); |
| 707 | } | 783 | } |
| 708 | 784 | ||
| 709 | std::vector<const char *> ArgParser::tokenize(StringRef S) { | 785 | std::vector<const char *> ArgParser::tokenize(StringRef S) { |
| ... | @@ -712,18 +788,8 @@ std::vector<const char *> ArgParser::tokenize(StringRef S) { | ... | @@ -712,18 +788,8 @@ std::vector<const char *> ArgParser::tokenize(StringRef S) { |
| 712 | return std::vector<const char *>(Tokens.begin(), Tokens.end()); | 788 | return std::vector<const char *>(Tokens.begin(), Tokens.end()); |
| 713 | } | 789 | } |
| 714 | 790 | ||
| 715 | // Creates a new command line by replacing options starting with '@' | ||
| 716 | // character. '@<filename>' is replaced by the file's contents. | ||
| 717 | std::vector<const char *> | ||
| 718 | ArgParser::replaceResponseFiles(std::vector<const char *> Argv) { | ||
| 719 | SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size()); | ||
| 720 | ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens); | ||
| 721 | return std::vector<const char *>(Tokens.begin(), Tokens.end()); | ||
| 722 | } | ||
| 723 | |||
| 724 | void printHelp(const char *Argv0) { | 791 | void printHelp(const char *Argv0) { |
| 725 | COFFOptTable Table; | 792 | COFFOptTable().PrintHelp(outs(), Argv0, "LLVM Linker", false); |
| 726 | Table.PrintHelp(outs(), Argv0, "LLVM Linker", false); | ||
| 727 | } | 793 | } |
| 728 | 794 | ||
| 729 | } // namespace coff | 795 | } // namespace coff |
deps/lld/COFF/Error.cpp deleted-115| ... | @@ -1,115 +0,0 @@ | ||
| 1 | //===- Error.cpp ----------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "Error.h" | ||
| 11 | #include "Config.h" | ||
| 12 | |||
| 13 | #include "llvm/ADT/Twine.h" | ||
| 14 | #include "llvm/Support/Error.h" | ||
| 15 | #include "llvm/Support/ManagedStatic.h" | ||
| 16 | #include "llvm/Support/Process.h" | ||
| 17 | #include "llvm/Support/raw_ostream.h" | ||
| 18 | #include <mutex> | ||
| 19 | |||
| 20 | #if !defined(_MSC_VER) && !defined(__MINGW32__) | ||
| 21 | #include <unistd.h> | ||
| 22 | #endif | ||
| 23 | |||
| 24 | using namespace llvm; | ||
| 25 | |||
| 26 | namespace lld { | ||
| 27 | // The functions defined in this file can be called from multiple threads, | ||
| 28 | // but outs() or errs() are not thread-safe. We protect them using a mutex. | ||
| 29 | static std::mutex Mu; | ||
| 30 | |||
| 31 | namespace coff { | ||
| 32 | uint64_t ErrorCount; | ||
| 33 | raw_ostream *ErrorOS; | ||
| 34 | |||
| 35 | LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) { | ||
| 36 | // Dealloc/destroy ManagedStatic variables before calling | ||
| 37 | // _exit(). In a non-LTO build, this is a nop. In an LTO | ||
| 38 | // build allows us to get the output of -time-passes. | ||
| 39 | llvm_shutdown(); | ||
| 40 | |||
| 41 | outs().flush(); | ||
| 42 | errs().flush(); | ||
| 43 | _exit(Val); | ||
| 44 | } | ||
| 45 | |||
| 46 | static void print(StringRef S, raw_ostream::Colors C) { | ||
| 47 | *ErrorOS << Config->Argv[0] << ": "; | ||
| 48 | if (Config->ColorDiagnostics) { | ||
| 49 | ErrorOS->changeColor(C, true); | ||
| 50 | *ErrorOS << S; | ||
| 51 | ErrorOS->resetColor(); | ||
| 52 | } else { | ||
| 53 | *ErrorOS << S; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | void log(const Twine &Msg) { | ||
| 58 | if (Config->Verbose) { | ||
| 59 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 60 | outs() << Config->Argv[0] << ": " << Msg << "\n"; | ||
| 61 | outs().flush(); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | void message(const Twine &Msg) { | ||
| 66 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 67 | outs() << Msg << "\n"; | ||
| 68 | outs().flush(); | ||
| 69 | } | ||
| 70 | |||
| 71 | void error(const Twine &Msg) { | ||
| 72 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 73 | |||
| 74 | if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) { | ||
| 75 | print("error: ", raw_ostream::RED); | ||
| 76 | *ErrorOS << Msg << "\n"; | ||
| 77 | } else if (ErrorCount == Config->ErrorLimit) { | ||
| 78 | print("error: ", raw_ostream::RED); | ||
| 79 | *ErrorOS << "too many errors emitted, stopping now" | ||
| 80 | << " (use /ERRORLIMIT:0 to see all errors)\n"; | ||
| 81 | if (Config->CanExitEarly) | ||
| 82 | exitLld(1); | ||
| 83 | } | ||
| 84 | |||
| 85 | ++ErrorCount; | ||
| 86 | } | ||
| 87 | |||
| 88 | void fatal(const Twine &Msg) { | ||
| 89 | if (Config->ColorDiagnostics) { | ||
| 90 | errs().changeColor(raw_ostream::RED, /*bold=*/true); | ||
| 91 | errs() << "error: "; | ||
| 92 | errs().resetColor(); | ||
| 93 | } else { | ||
| 94 | errs() << "error: "; | ||
| 95 | } | ||
| 96 | errs() << Msg << "\n"; | ||
| 97 | exitLld(1); | ||
| 98 | } | ||
| 99 | |||
| 100 | void fatal(std::error_code EC, const Twine &Msg) { | ||
| 101 | fatal(Msg + ": " + EC.message()); | ||
| 102 | } | ||
| 103 | |||
| 104 | void fatal(llvm::Error &Err, const Twine &Msg) { | ||
| 105 | fatal(errorToErrorCode(std::move(Err)), Msg); | ||
| 106 | } | ||
| 107 | |||
| 108 | void warn(const Twine &Msg) { | ||
| 109 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 110 | print("warning: ", raw_ostream::MAGENTA); | ||
| 111 | *ErrorOS << Msg << "\n"; | ||
| 112 | } | ||
| 113 | |||
| 114 | } // namespace coff | ||
| 115 | } // namespace lld | ||
deps/lld/COFF/Error.h deleted-64| ... | @@ -1,64 +0,0 @@ | ||
| 1 | //===- Error.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_COFF_ERROR_H | ||
| 11 | #define LLD_COFF_ERROR_H | ||
| 12 | |||
| 13 | #include "lld/Core/LLVM.h" | ||
| 14 | #include "llvm/Support/Error.h" | ||
| 15 | |||
| 16 | namespace lld { | ||
| 17 | namespace coff { | ||
| 18 | |||
| 19 | extern uint64_t ErrorCount; | ||
| 20 | extern llvm::raw_ostream *ErrorOS; | ||
| 21 | |||
| 22 | void log(const Twine &Msg); | ||
| 23 | void message(const Twine &Msg); | ||
| 24 | void warn(const Twine &Msg); | ||
| 25 | void error(const Twine &Msg); | ||
| 26 | LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); | ||
| 27 | LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix); | ||
| 28 | LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix); | ||
| 29 | |||
| 30 | LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); | ||
| 31 | |||
| 32 | template <class T> T check(ErrorOr<T> V, const Twine &Prefix) { | ||
| 33 | if (auto EC = V.getError()) | ||
| 34 | fatal(EC, Prefix); | ||
| 35 | return std::move(*V); | ||
| 36 | } | ||
| 37 | |||
| 38 | template <class T> T check(Expected<T> E, const Twine &Prefix) { | ||
| 39 | if (llvm::Error Err = E.takeError()) | ||
| 40 | fatal(Err, Prefix); | ||
| 41 | return std::move(*E); | ||
| 42 | } | ||
| 43 | |||
| 44 | template <class T> T check(ErrorOr<T> EO) { | ||
| 45 | if (!EO) | ||
| 46 | fatal(EO.getError().message()); | ||
| 47 | return std::move(*EO); | ||
| 48 | } | ||
| 49 | |||
| 50 | template <class T> T check(Expected<T> E) { | ||
| 51 | if (!E) { | ||
| 52 | std::string Buf; | ||
| 53 | llvm::raw_string_ostream OS(Buf); | ||
| 54 | logAllUnhandledErrors(E.takeError(), OS, ""); | ||
| 55 | OS.flush(); | ||
| 56 | fatal(Buf); | ||
| 57 | } | ||
| 58 | return std::move(*E); | ||
| 59 | } | ||
| 60 | |||
| 61 | } // namespace coff | ||
| 62 | } // namespace lld | ||
| 63 | |||
| 64 | #endif | ||
deps/lld/COFF/ICF.cpp+28-23| ... | @@ -19,8 +19,8 @@ | ... | @@ -19,8 +19,8 @@ |
| 19 | //===----------------------------------------------------------------------===// | 19 | //===----------------------------------------------------------------------===// |
| 20 | 20 | ||
| 21 | #include "Chunks.h" | 21 | #include "Chunks.h" |
| 22 | #include "Error.h" | ||
| 23 | #include "Symbols.h" | 22 | #include "Symbols.h" |
| 23 | #include "lld/Common/ErrorHandler.h" | ||
| 24 | #include "llvm/ADT/Hashing.h" | 24 | #include "llvm/ADT/Hashing.h" |
| 25 | #include "llvm/Support/Debug.h" | 25 | #include "llvm/Support/Debug.h" |
| 26 | #include "llvm/Support/Parallel.h" | 26 | #include "llvm/Support/Parallel.h" |
| ... | @@ -36,7 +36,7 @@ namespace coff { | ... | @@ -36,7 +36,7 @@ namespace coff { |
| 36 | 36 | ||
| 37 | class ICF { | 37 | class ICF { |
| 38 | public: | 38 | public: |
| 39 | void run(const std::vector<Chunk *> &V); | 39 | void run(ArrayRef<Chunk *> V); |
| 40 | 40 | ||
| 41 | private: | 41 | private: |
| 42 | void segregate(size_t Begin, size_t End, bool Constant); | 42 | void segregate(size_t Begin, size_t End, bool Constant); |
| ... | @@ -61,12 +61,9 @@ private: | ... | @@ -61,12 +61,9 @@ private: |
| 61 | 61 | ||
| 62 | // Returns a hash value for S. | 62 | // Returns a hash value for S. |
| 63 | uint32_t ICF::getHash(SectionChunk *C) { | 63 | uint32_t ICF::getHash(SectionChunk *C) { |
| 64 | return hash_combine(C->getPermissions(), | 64 | return hash_combine(C->getPermissions(), C->SectionName, C->NumRelocs, |
| 65 | hash_value(C->SectionName), | 65 | C->Alignment, uint32_t(C->Header->SizeOfRawData), |
| 66 | C->NumRelocs, | 66 | C->Checksum, C->getContents()); |
| 67 | C->getAlign(), | ||
| 68 | uint32_t(C->Header->SizeOfRawData), | ||
| 69 | C->Checksum); | ||
| 70 | } | 67 | } |
| 71 | 68 | ||
| 72 | // Returns true if section S is subject of ICF. | 69 | // Returns true if section S is subject of ICF. |
| ... | @@ -76,12 +73,21 @@ uint32_t ICF::getHash(SectionChunk *C) { | ... | @@ -76,12 +73,21 @@ uint32_t ICF::getHash(SectionChunk *C) { |
| 76 | // 2017) says that /opt:icf folds both functions and read-only data. | 73 | // 2017) says that /opt:icf folds both functions and read-only data. |
| 77 | // Despite that, the MSVC linker folds only functions. We found | 74 | // Despite that, the MSVC linker folds only functions. We found |
| 78 | // a few instances of programs that are not safe for data merging. | 75 | // a few instances of programs that are not safe for data merging. |
| 79 | // Therefore, we merge only functions just like the MSVC tool. | 76 | // Therefore, we merge only functions just like the MSVC tool. However, we merge |
| 77 | // identical .xdata sections, because the address of unwind information is | ||
| 78 | // insignificant to the user program and the Visual C++ linker does this. | ||
| 80 | bool ICF::isEligible(SectionChunk *C) { | 79 | bool ICF::isEligible(SectionChunk *C) { |
| 81 | bool Global = C->Sym && C->Sym->isExternal(); | 80 | // Non-comdat chunks, dead chunks, and writable chunks are not elegible. |
| 82 | bool Executable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE; | ||
| 83 | bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE; | 81 | bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE; |
| 84 | return C->isCOMDAT() && C->isLive() && Global && Executable && !Writable; | 82 | if (!C->isCOMDAT() || !C->isLive() || Writable) |
| 83 | return false; | ||
| 84 | |||
| 85 | // Code sections are eligible. | ||
| 86 | if (C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE) | ||
| 87 | return true; | ||
| 88 | |||
| 89 | // .xdata unwind info sections are eligble. | ||
| 90 | return C->getSectionName().split('$').first == ".xdata"; | ||
| 85 | } | 91 | } |
| 86 | 92 | ||
| 87 | // Split an equivalence class into smaller classes. | 93 | // Split an equivalence class into smaller classes. |
| ... | @@ -122,8 +128,8 @@ bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) { | ... | @@ -122,8 +128,8 @@ bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) { |
| 122 | R1.VirtualAddress != R2.VirtualAddress) { | 128 | R1.VirtualAddress != R2.VirtualAddress) { |
| 123 | return false; | 129 | return false; |
| 124 | } | 130 | } |
| 125 | SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex); | 131 | Symbol *B1 = A->File->getSymbol(R1.SymbolTableIndex); |
| 126 | SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex); | 132 | Symbol *B2 = B->File->getSymbol(R2.SymbolTableIndex); |
| 127 | if (B1 == B2) | 133 | if (B1 == B2) |
| 128 | return true; | 134 | return true; |
| 129 | if (auto *D1 = dyn_cast<DefinedRegular>(B1)) | 135 | if (auto *D1 = dyn_cast<DefinedRegular>(B1)) |
| ... | @@ -137,19 +143,17 @@ bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) { | ... | @@ -137,19 +143,17 @@ bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) { |
| 137 | 143 | ||
| 138 | // Compare section attributes and contents. | 144 | // Compare section attributes and contents. |
| 139 | return A->getPermissions() == B->getPermissions() && | 145 | return A->getPermissions() == B->getPermissions() && |
| 140 | A->SectionName == B->SectionName && | 146 | A->SectionName == B->SectionName && A->Alignment == B->Alignment && |
| 141 | A->getAlign() == B->getAlign() && | ||
| 142 | A->Header->SizeOfRawData == B->Header->SizeOfRawData && | 147 | A->Header->SizeOfRawData == B->Header->SizeOfRawData && |
| 143 | A->Checksum == B->Checksum && | 148 | A->Checksum == B->Checksum && A->getContents() == B->getContents(); |
| 144 | A->getContents() == B->getContents(); | ||
| 145 | } | 149 | } |
| 146 | 150 | ||
| 147 | // Compare "moving" part of two sections, namely relocation targets. | 151 | // Compare "moving" part of two sections, namely relocation targets. |
| 148 | bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) { | 152 | bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) { |
| 149 | // Compare relocations. | 153 | // Compare relocations. |
| 150 | auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { | 154 | auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { |
| 151 | SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex); | 155 | Symbol *B1 = A->File->getSymbol(R1.SymbolTableIndex); |
| 152 | SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex); | 156 | Symbol *B2 = B->File->getSymbol(R2.SymbolTableIndex); |
| 153 | if (B1 == B2) | 157 | if (B1 == B2) |
| 154 | return true; | 158 | return true; |
| 155 | if (auto *D1 = dyn_cast<DefinedRegular>(B1)) | 159 | if (auto *D1 = dyn_cast<DefinedRegular>(B1)) |
| ... | @@ -202,7 +206,7 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) { | ... | @@ -202,7 +206,7 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) { |
| 202 | // Merge identical COMDAT sections. | 206 | // Merge identical COMDAT sections. |
| 203 | // Two sections are considered the same if their section headers, | 207 | // Two sections are considered the same if their section headers, |
| 204 | // contents and relocations are all the same. | 208 | // contents and relocations are all the same. |
| 205 | void ICF::run(const std::vector<Chunk *> &Vec) { | 209 | void ICF::run(ArrayRef<Chunk *> Vec) { |
| 206 | // Collect only mergeable sections and group by hash value. | 210 | // Collect only mergeable sections and group by hash value. |
| 207 | uint32_t NextId = 1; | 211 | uint32_t NextId = 1; |
| 208 | for (Chunk *C : Vec) { | 212 | for (Chunk *C : Vec) { |
| ... | @@ -215,9 +219,10 @@ void ICF::run(const std::vector<Chunk *> &Vec) { | ... | @@ -215,9 +219,10 @@ void ICF::run(const std::vector<Chunk *> &Vec) { |
| 215 | } | 219 | } |
| 216 | 220 | ||
| 217 | // Initially, we use hash values to partition sections. | 221 | // Initially, we use hash values to partition sections. |
| 218 | for (SectionChunk *SC : Chunks) | 222 | for_each(parallel::par, Chunks.begin(), Chunks.end(), [&](SectionChunk *SC) { |
| 219 | // Set MSB to 1 to avoid collisions with non-hash classs. | 223 | // Set MSB to 1 to avoid collisions with non-hash classs. |
| 220 | SC->Class[0] = getHash(SC) | (1 << 31); | 224 | SC->Class[0] = getHash(SC) | (1 << 31); |
| 225 | }); | ||
| 221 | 226 | ||
| 222 | // From now on, sections in Chunks are ordered so that sections in | 227 | // From now on, sections in Chunks are ordered so that sections in |
| 223 | // the same group are consecutive in the vector. | 228 | // the same group are consecutive in the vector. |
| ... | @@ -252,7 +257,7 @@ void ICF::run(const std::vector<Chunk *> &Vec) { | ... | @@ -252,7 +257,7 @@ void ICF::run(const std::vector<Chunk *> &Vec) { |
| 252 | } | 257 | } |
| 253 | 258 | ||
| 254 | // Entry point to ICF. | 259 | // Entry point to ICF. |
| 255 | void doICF(const std::vector<Chunk *> &Chunks) { ICF().run(Chunks); } | 260 | void doICF(ArrayRef<Chunk *> Chunks) { ICF().run(Chunks); } |
| 256 | 261 | ||
| 257 | } // namespace coff | 262 | } // namespace coff |
| 258 | } // namespace lld | 263 | } // namespace lld |
deps/lld/COFF/InputFiles.cpp+244-150| ... | @@ -11,10 +11,10 @@ | ... | @@ -11,10 +11,10 @@ |
| 11 | #include "Chunks.h" | 11 | #include "Chunks.h" |
| 12 | #include "Config.h" | 12 | #include "Config.h" |
| 13 | #include "Driver.h" | 13 | #include "Driver.h" |
| 14 | #include "Error.h" | ||
| 15 | #include "Memory.h" | ||
| 16 | #include "SymbolTable.h" | 14 | #include "SymbolTable.h" |
| 17 | #include "Symbols.h" | 15 | #include "Symbols.h" |
| 16 | #include "lld/Common/ErrorHandler.h" | ||
| 17 | #include "lld/Common/Memory.h" | ||
| 18 | #include "llvm-c/lto.h" | 18 | #include "llvm-c/lto.h" |
| 19 | #include "llvm/ADT/SmallVector.h" | 19 | #include "llvm/ADT/SmallVector.h" |
| 20 | #include "llvm/ADT/Triple.h" | 20 | #include "llvm/ADT/Triple.h" |
| ... | @@ -43,14 +43,18 @@ using llvm::support::ulittle32_t; | ... | @@ -43,14 +43,18 @@ using llvm::support::ulittle32_t; |
| 43 | namespace lld { | 43 | namespace lld { |
| 44 | namespace coff { | 44 | namespace coff { |
| 45 | 45 | ||
| 46 | std::vector<ObjFile *> ObjFile::Instances; | ||
| 47 | std::vector<ImportFile *> ImportFile::Instances; | ||
| 48 | std::vector<BitcodeFile *> BitcodeFile::Instances; | ||
| 49 | |||
| 46 | /// Checks that Source is compatible with being a weak alias to Target. | 50 | /// Checks that Source is compatible with being a weak alias to Target. |
| 47 | /// If Source is Undefined and has no weak alias set, makes it a weak | 51 | /// If Source is Undefined and has no weak alias set, makes it a weak |
| 48 | /// alias to Target. | 52 | /// alias to Target. |
| 49 | static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F, | 53 | static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F, |
| 50 | SymbolBody *Source, SymbolBody *Target) { | 54 | Symbol *Source, Symbol *Target) { |
| 51 | if (auto *U = dyn_cast<Undefined>(Source)) { | 55 | if (auto *U = dyn_cast<Undefined>(Source)) { |
| 52 | if (U->WeakAlias && U->WeakAlias != Target) | 56 | if (U->WeakAlias && U->WeakAlias != Target) |
| 53 | Symtab->reportDuplicate(Source->symbol(), F); | 57 | Symtab->reportDuplicate(Source, F); |
| 54 | U->WeakAlias = Target; | 58 | U->WeakAlias = Target; |
| 55 | } | 59 | } |
| 56 | } | 60 | } |
| ... | @@ -59,7 +63,7 @@ ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} | ... | @@ -59,7 +63,7 @@ ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} |
| 59 | 63 | ||
| 60 | void ArchiveFile::parse() { | 64 | void ArchiveFile::parse() { |
| 61 | // Parse a MemoryBufferRef as an archive file. | 65 | // Parse a MemoryBufferRef as an archive file. |
| 62 | File = check(Archive::create(MB), toString(this)); | 66 | File = CHECK(Archive::create(MB), this); |
| 63 | 67 | ||
| 64 | // Read the symbol table to construct Lazy objects. | 68 | // Read the symbol table to construct Lazy objects. |
| 65 | for (const Archive::Symbol &Sym : File->symbols()) | 69 | for (const Archive::Symbol &Sym : File->symbols()) |
| ... | @@ -69,7 +73,7 @@ void ArchiveFile::parse() { | ... | @@ -69,7 +73,7 @@ void ArchiveFile::parse() { |
| 69 | // Returns a buffer pointing to a member file containing a given symbol. | 73 | // Returns a buffer pointing to a member file containing a given symbol. |
| 70 | void ArchiveFile::addMember(const Archive::Symbol *Sym) { | 74 | void ArchiveFile::addMember(const Archive::Symbol *Sym) { |
| 71 | const Archive::Child &C = | 75 | const Archive::Child &C = |
| 72 | check(Sym->getMember(), | 76 | CHECK(Sym->getMember(), |
| 73 | "could not get the member for symbol " + Sym->getName()); | 77 | "could not get the member for symbol " + Sym->getName()); |
| 74 | 78 | ||
| 75 | // Return an empty buffer if we have already returned the same buffer. | 79 | // Return an empty buffer if we have already returned the same buffer. |
| ... | @@ -79,9 +83,28 @@ void ArchiveFile::addMember(const Archive::Symbol *Sym) { | ... | @@ -79,9 +83,28 @@ void ArchiveFile::addMember(const Archive::Symbol *Sym) { |
| 79 | Driver->enqueueArchiveMember(C, Sym->getName(), getName()); | 83 | Driver->enqueueArchiveMember(C, Sym->getName(), getName()); |
| 80 | } | 84 | } |
| 81 | 85 | ||
| 82 | void ObjectFile::parse() { | 86 | std::vector<MemoryBufferRef> getArchiveMembers(Archive *File) { |
| 87 | std::vector<MemoryBufferRef> V; | ||
| 88 | Error Err = Error::success(); | ||
| 89 | for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { | ||
| 90 | Archive::Child C = | ||
| 91 | CHECK(COrErr, | ||
| 92 | File->getFileName() + ": could not get the child of the archive"); | ||
| 93 | MemoryBufferRef MBRef = | ||
| 94 | CHECK(C.getMemoryBufferRef(), | ||
| 95 | File->getFileName() + | ||
| 96 | ": could not get the buffer for a child of the archive"); | ||
| 97 | V.push_back(MBRef); | ||
| 98 | } | ||
| 99 | if (Err) | ||
| 100 | fatal(File->getFileName() + | ||
| 101 | ": Archive::children failed: " + toString(std::move(Err))); | ||
| 102 | return V; | ||
| 103 | } | ||
| 104 | |||
| 105 | void ObjFile::parse() { | ||
| 83 | // Parse a memory buffer as a COFF file. | 106 | // Parse a memory buffer as a COFF file. |
| 84 | std::unique_ptr<Binary> Bin = check(createBinary(MB), toString(this)); | 107 | std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), this); |
| 85 | 108 | ||
| 86 | if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) { | 109 | if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) { |
| 87 | Bin.release(); | 110 | Bin.release(); |
| ... | @@ -93,114 +116,184 @@ void ObjectFile::parse() { | ... | @@ -93,114 +116,184 @@ void ObjectFile::parse() { |
| 93 | // Read section and symbol tables. | 116 | // Read section and symbol tables. |
| 94 | initializeChunks(); | 117 | initializeChunks(); |
| 95 | initializeSymbols(); | 118 | initializeSymbols(); |
| 96 | initializeSEH(); | ||
| 97 | } | 119 | } |
| 98 | 120 | ||
| 99 | void ObjectFile::initializeChunks() { | 121 | // We set SectionChunk pointers in the SparseChunks vector to this value |
| 122 | // temporarily to mark comdat sections as having an unknown resolution. As we | ||
| 123 | // walk the object file's symbol table, once we visit either a leader symbol or | ||
| 124 | // an associative section definition together with the parent comdat's leader, | ||
| 125 | // we set the pointer to either nullptr (to mark the section as discarded) or a | ||
| 126 | // valid SectionChunk for that section. | ||
| 127 | static SectionChunk *const PendingComdat = reinterpret_cast<SectionChunk *>(1); | ||
| 128 | |||
| 129 | void ObjFile::initializeChunks() { | ||
| 100 | uint32_t NumSections = COFFObj->getNumberOfSections(); | 130 | uint32_t NumSections = COFFObj->getNumberOfSections(); |
| 101 | Chunks.reserve(NumSections); | 131 | Chunks.reserve(NumSections); |
| 102 | SparseChunks.resize(NumSections + 1); | 132 | SparseChunks.resize(NumSections + 1); |
| 103 | for (uint32_t I = 1; I < NumSections + 1; ++I) { | 133 | for (uint32_t I = 1; I < NumSections + 1; ++I) { |
| 104 | const coff_section *Sec; | 134 | const coff_section *Sec; |
| 105 | StringRef Name; | ||
| 106 | if (auto EC = COFFObj->getSection(I, Sec)) | 135 | if (auto EC = COFFObj->getSection(I, Sec)) |
| 107 | fatal(EC, "getSection failed: #" + Twine(I)); | 136 | fatal("getSection failed: #" + Twine(I) + ": " + EC.message()); |
| 108 | if (auto EC = COFFObj->getSectionName(Sec, Name)) | ||
| 109 | fatal(EC, "getSectionName failed: #" + Twine(I)); | ||
| 110 | if (Name == ".sxdata") { | ||
| 111 | SXData = Sec; | ||
| 112 | continue; | ||
| 113 | } | ||
| 114 | if (Name == ".drectve") { | ||
| 115 | ArrayRef<uint8_t> Data; | ||
| 116 | COFFObj->getSectionContents(Sec, Data); | ||
| 117 | Directives = std::string((const char *)Data.data(), Data.size()); | ||
| 118 | continue; | ||
| 119 | } | ||
| 120 | 137 | ||
| 121 | // Object files may have DWARF debug info or MS CodeView debug info | 138 | if (Sec->Characteristics & IMAGE_SCN_LNK_COMDAT) |
| 122 | // (or both). | 139 | SparseChunks[I] = PendingComdat; |
| 123 | // | ||
| 124 | // DWARF sections don't need any special handling from the perspective | ||
| 125 | // of the linker; they are just a data section containing relocations. | ||
| 126 | // We can just link them to complete debug info. | ||
| 127 | // | ||
| 128 | // CodeView needs a linker support. We need to interpret and debug | ||
| 129 | // info, and then write it to a separate .pdb file. | ||
| 130 | |||
| 131 | // Ignore debug info unless /debug is given. | ||
| 132 | if (!Config->Debug && Name.startswith(".debug")) | ||
| 133 | continue; | ||
| 134 | |||
| 135 | if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) | ||
| 136 | continue; | ||
| 137 | auto *C = make<SectionChunk>(this, Sec); | ||
| 138 | |||
| 139 | // CodeView sections are stored to a different vector because they are not | ||
| 140 | // linked in the regular manner. | ||
| 141 | if (C->isCodeView()) | ||
| 142 | DebugChunks.push_back(C); | ||
| 143 | else | 140 | else |
| 144 | Chunks.push_back(C); | 141 | SparseChunks[I] = readSection(I, nullptr); |
| 142 | } | ||
| 143 | } | ||
| 145 | 144 | ||
| 146 | SparseChunks[I] = C; | 145 | SectionChunk *ObjFile::readSection(uint32_t SectionNumber, |
| 146 | const coff_aux_section_definition *Def) { | ||
| 147 | const coff_section *Sec; | ||
| 148 | StringRef Name; | ||
| 149 | if (auto EC = COFFObj->getSection(SectionNumber, Sec)) | ||
| 150 | fatal("getSection failed: #" + Twine(SectionNumber) + ": " + EC.message()); | ||
| 151 | if (auto EC = COFFObj->getSectionName(Sec, Name)) | ||
| 152 | fatal("getSectionName failed: #" + Twine(SectionNumber) + ": " + | ||
| 153 | EC.message()); | ||
| 154 | if (Name == ".sxdata") { | ||
| 155 | ArrayRef<uint8_t> Data; | ||
| 156 | COFFObj->getSectionContents(Sec, Data); | ||
| 157 | if (Data.size() % 4 != 0) | ||
| 158 | fatal(".sxdata must be an array of symbol table indices"); | ||
| 159 | SXData = {reinterpret_cast<const ulittle32_t *>(Data.data()), | ||
| 160 | Data.size() / 4}; | ||
| 161 | return nullptr; | ||
| 162 | } | ||
| 163 | if (Name == ".drectve") { | ||
| 164 | ArrayRef<uint8_t> Data; | ||
| 165 | COFFObj->getSectionContents(Sec, Data); | ||
| 166 | Directives = std::string((const char *)Data.data(), Data.size()); | ||
| 167 | return nullptr; | ||
| 147 | } | 168 | } |
| 169 | |||
| 170 | // Object files may have DWARF debug info or MS CodeView debug info | ||
| 171 | // (or both). | ||
| 172 | // | ||
| 173 | // DWARF sections don't need any special handling from the perspective | ||
| 174 | // of the linker; they are just a data section containing relocations. | ||
| 175 | // We can just link them to complete debug info. | ||
| 176 | // | ||
| 177 | // CodeView needs a linker support. We need to interpret and debug | ||
| 178 | // info, and then write it to a separate .pdb file. | ||
| 179 | |||
| 180 | // Ignore debug info unless /debug is given. | ||
| 181 | if (!Config->Debug && Name.startswith(".debug")) | ||
| 182 | return nullptr; | ||
| 183 | |||
| 184 | if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) | ||
| 185 | return nullptr; | ||
| 186 | auto *C = make<SectionChunk>(this, Sec); | ||
| 187 | if (Def) | ||
| 188 | C->Checksum = Def->CheckSum; | ||
| 189 | |||
| 190 | // CodeView sections are stored to a different vector because they are not | ||
| 191 | // linked in the regular manner. | ||
| 192 | if (C->isCodeView()) | ||
| 193 | DebugChunks.push_back(C); | ||
| 194 | else | ||
| 195 | Chunks.push_back(C); | ||
| 196 | |||
| 197 | return C; | ||
| 148 | } | 198 | } |
| 149 | 199 | ||
| 150 | void ObjectFile::initializeSymbols() { | 200 | void ObjFile::readAssociativeDefinition( |
| 201 | COFFSymbolRef Sym, const coff_aux_section_definition *Def) { | ||
| 202 | SectionChunk *Parent = SparseChunks[Def->getNumber(Sym.isBigObj())]; | ||
| 203 | |||
| 204 | // If the parent is pending, it probably means that its section definition | ||
| 205 | // appears after us in the symbol table. Leave the associated section as | ||
| 206 | // pending; we will handle it during the second pass in initializeSymbols(). | ||
| 207 | if (Parent == PendingComdat) | ||
| 208 | return; | ||
| 209 | |||
| 210 | // Check whether the parent is prevailing. If it is, so are we, and we read | ||
| 211 | // the section; otherwise mark it as discarded. | ||
| 212 | int32_t SectionNumber = Sym.getSectionNumber(); | ||
| 213 | if (Parent) { | ||
| 214 | SparseChunks[SectionNumber] = readSection(SectionNumber, Def); | ||
| 215 | if (SparseChunks[SectionNumber]) | ||
| 216 | Parent->addAssociative(SparseChunks[SectionNumber]); | ||
| 217 | } else { | ||
| 218 | SparseChunks[SectionNumber] = nullptr; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | Symbol *ObjFile::createRegular(COFFSymbolRef Sym) { | ||
| 223 | SectionChunk *SC = SparseChunks[Sym.getSectionNumber()]; | ||
| 224 | if (Sym.isExternal()) { | ||
| 225 | StringRef Name; | ||
| 226 | COFFObj->getSymbolName(Sym, Name); | ||
| 227 | if (SC) | ||
| 228 | return Symtab->addRegular(this, Name, Sym.getGeneric(), SC); | ||
| 229 | return Symtab->addUndefined(Name, this, false); | ||
| 230 | } | ||
| 231 | if (SC) | ||
| 232 | return make<DefinedRegular>(this, /*Name*/ "", false, | ||
| 233 | /*IsExternal*/ false, Sym.getGeneric(), SC); | ||
| 234 | return nullptr; | ||
| 235 | } | ||
| 236 | |||
| 237 | void ObjFile::initializeSymbols() { | ||
| 151 | uint32_t NumSymbols = COFFObj->getNumberOfSymbols(); | 238 | uint32_t NumSymbols = COFFObj->getNumberOfSymbols(); |
| 152 | SymbolBodies.reserve(NumSymbols); | 239 | Symbols.resize(NumSymbols); |
| 153 | SparseSymbolBodies.resize(NumSymbols); | ||
| 154 | 240 | ||
| 155 | SmallVector<std::pair<SymbolBody *, uint32_t>, 8> WeakAliases; | 241 | SmallVector<std::pair<Symbol *, uint32_t>, 8> WeakAliases; |
| 156 | int32_t LastSectionNumber = 0; | 242 | std::vector<uint32_t> PendingIndexes; |
| 243 | PendingIndexes.reserve(NumSymbols); | ||
| 244 | |||
| 245 | std::vector<const coff_aux_section_definition *> ComdatDefs( | ||
| 246 | COFFObj->getNumberOfSections() + 1); | ||
| 157 | 247 | ||
| 158 | for (uint32_t I = 0; I < NumSymbols; ++I) { | 248 | for (uint32_t I = 0; I < NumSymbols; ++I) { |
| 159 | // Get a COFFSymbolRef object. | 249 | COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I)); |
| 160 | ErrorOr<COFFSymbolRef> SymOrErr = COFFObj->getSymbol(I); | 250 | if (COFFSym.isUndefined()) { |
| 161 | if (!SymOrErr) | 251 | Symbols[I] = createUndefined(COFFSym); |
| 162 | fatal(SymOrErr.getError(), "broken object file: " + toString(this)); | 252 | } else if (COFFSym.isWeakExternal()) { |
| 163 | COFFSymbolRef Sym = *SymOrErr; | 253 | Symbols[I] = createUndefined(COFFSym); |
| 164 | 254 | uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex; | |
| 165 | const void *AuxP = nullptr; | 255 | WeakAliases.emplace_back(Symbols[I], TagIndex); |
| 166 | if (Sym.getNumberOfAuxSymbols()) | 256 | } else if (Optional<Symbol *> OptSym = createDefined(COFFSym, ComdatDefs)) { |
| 167 | AuxP = COFFObj->getSymbol(I + 1)->getRawPtr(); | 257 | Symbols[I] = *OptSym; |
| 168 | bool IsFirst = (LastSectionNumber != Sym.getSectionNumber()); | ||
| 169 | |||
| 170 | SymbolBody *Body = nullptr; | ||
| 171 | if (Sym.isUndefined()) { | ||
| 172 | Body = createUndefined(Sym); | ||
| 173 | } else if (Sym.isWeakExternal()) { | ||
| 174 | Body = createUndefined(Sym); | ||
| 175 | uint32_t TagIndex = | ||
| 176 | static_cast<const coff_aux_weak_external *>(AuxP)->TagIndex; | ||
| 177 | WeakAliases.emplace_back(Body, TagIndex); | ||
| 178 | } else { | 258 | } else { |
| 179 | Body = createDefined(Sym, AuxP, IsFirst); | 259 | // createDefined() returns None if a symbol belongs to a section that |
| 180 | } | 260 | // was pending at the point when the symbol was read. This can happen in |
| 181 | if (Body) { | 261 | // two cases: |
| 182 | SymbolBodies.push_back(Body); | 262 | // 1) section definition symbol for a comdat leader; |
| 183 | SparseSymbolBodies[I] = Body; | 263 | // 2) symbol belongs to a comdat section associated with a section whose |
| 264 | // section definition symbol appears later in the symbol table. | ||
| 265 | // In both of these cases, we can expect the section to be resolved by | ||
| 266 | // the time we finish visiting the remaining symbols in the symbol | ||
| 267 | // table. So we postpone the handling of this symbol until that time. | ||
| 268 | PendingIndexes.push_back(I); | ||
| 184 | } | 269 | } |
| 185 | I += Sym.getNumberOfAuxSymbols(); | 270 | I += COFFSym.getNumberOfAuxSymbols(); |
| 186 | LastSectionNumber = Sym.getSectionNumber(); | 271 | } |
| 272 | |||
| 273 | for (uint32_t I : PendingIndexes) { | ||
| 274 | COFFSymbolRef Sym = check(COFFObj->getSymbol(I)); | ||
| 275 | if (auto *Def = Sym.getSectionDefinition()) | ||
| 276 | if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) | ||
| 277 | readAssociativeDefinition(Sym, Def); | ||
| 278 | Symbols[I] = createRegular(Sym); | ||
| 187 | } | 279 | } |
| 188 | 280 | ||
| 189 | for (auto &KV : WeakAliases) { | 281 | for (auto &KV : WeakAliases) { |
| 190 | SymbolBody *Sym = KV.first; | 282 | Symbol *Sym = KV.first; |
| 191 | uint32_t Idx = KV.second; | 283 | uint32_t Idx = KV.second; |
| 192 | checkAndSetWeakAlias(Symtab, this, Sym, SparseSymbolBodies[Idx]); | 284 | checkAndSetWeakAlias(Symtab, this, Sym, Symbols[Idx]); |
| 193 | } | 285 | } |
| 194 | } | 286 | } |
| 195 | 287 | ||
| 196 | SymbolBody *ObjectFile::createUndefined(COFFSymbolRef Sym) { | 288 | Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) { |
| 197 | StringRef Name; | 289 | StringRef Name; |
| 198 | COFFObj->getSymbolName(Sym, Name); | 290 | COFFObj->getSymbolName(Sym, Name); |
| 199 | return Symtab->addUndefined(Name, this, Sym.isWeakExternal())->body(); | 291 | return Symtab->addUndefined(Name, this, Sym.isWeakExternal()); |
| 200 | } | 292 | } |
| 201 | 293 | ||
| 202 | SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, | 294 | Optional<Symbol *> ObjFile::createDefined( |
| 203 | bool IsFirst) { | 295 | COFFSymbolRef Sym, |
| 296 | std::vector<const coff_aux_section_definition *> &ComdatDefs) { | ||
| 204 | StringRef Name; | 297 | StringRef Name; |
| 205 | if (Sym.isCommon()) { | 298 | if (Sym.isCommon()) { |
| 206 | auto *C = make<CommonChunk>(Sym); | 299 | auto *C = make<CommonChunk>(Sym); |
| ... | @@ -208,7 +301,7 @@ SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, | ... | @@ -208,7 +301,7 @@ SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, |
| 208 | COFFObj->getSymbolName(Sym, Name); | 301 | COFFObj->getSymbolName(Sym, Name); |
| 209 | Symbol *S = | 302 | Symbol *S = |
| 210 | Symtab->addCommon(this, Name, Sym.getValue(), Sym.getGeneric(), C); | 303 | Symtab->addCommon(this, Name, Sym.getValue(), Sym.getGeneric(), C); |
| 211 | return S->body(); | 304 | return S; |
| 212 | } | 305 | } |
| 213 | if (Sym.isAbsolute()) { | 306 | if (Sym.isAbsolute()) { |
| 214 | COFFObj->getSymbolName(Sym, Name); | 307 | COFFObj->getSymbolName(Sym, Name); |
| ... | @@ -222,7 +315,7 @@ SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, | ... | @@ -222,7 +315,7 @@ SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, |
| 222 | return nullptr; | 315 | return nullptr; |
| 223 | } | 316 | } |
| 224 | if (Sym.isExternal()) | 317 | if (Sym.isExternal()) |
| 225 | return Symtab->addAbsolute(Name, Sym)->body(); | 318 | return Symtab->addAbsolute(Name, Sym); |
| 226 | else | 319 | else |
| 227 | return make<DefinedAbsolute>(Name, Sym); | 320 | return make<DefinedAbsolute>(Name, Sym); |
| 228 | } | 321 | } |
| ... | @@ -239,54 +332,49 @@ SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, | ... | @@ -239,54 +332,49 @@ SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, |
| 239 | if ((uint32_t)SectionNumber >= SparseChunks.size()) | 332 | if ((uint32_t)SectionNumber >= SparseChunks.size()) |
| 240 | fatal("broken object file: " + toString(this)); | 333 | fatal("broken object file: " + toString(this)); |
| 241 | 334 | ||
| 242 | // Nothing else to do without a section chunk. | 335 | // Handle comdat leader symbols. |
| 243 | auto *SC = cast_or_null<SectionChunk>(SparseChunks[SectionNumber]); | 336 | if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) { |
| 244 | if (!SC) | 337 | ComdatDefs[SectionNumber] = nullptr; |
| 245 | return nullptr; | 338 | Symbol *Leader; |
| 246 | 339 | bool Prevailing; | |
| 247 | // Handle section definitions | 340 | if (Sym.isExternal()) { |
| 248 | if (IsFirst && AuxP) { | 341 | COFFObj->getSymbolName(Sym, Name); |
| 249 | auto *Aux = reinterpret_cast<const coff_aux_section_definition *>(AuxP); | 342 | std::tie(Leader, Prevailing) = |
| 250 | if (Aux->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) | 343 | Symtab->addComdat(this, Name, Sym.getGeneric()); |
| 251 | if (auto *ParentSC = cast_or_null<SectionChunk>( | 344 | } else { |
| 252 | SparseChunks[Aux->getNumber(Sym.isBigObj())])) { | 345 | Leader = make<DefinedRegular>(this, /*Name*/ "", false, |
| 253 | ParentSC->addAssociative(SC); | 346 | /*IsExternal*/ false, Sym.getGeneric()); |
| 254 | // If we already discarded the parent, discard the child. | 347 | Prevailing = true; |
| 255 | if (ParentSC->isDiscarded()) | 348 | } |
| 256 | SC->markDiscarded(); | 349 | if (Prevailing) { |
| 257 | } | 350 | SectionChunk *C = readSection(SectionNumber, Def); |
| 258 | SC->Checksum = Aux->CheckSum; | 351 | SparseChunks[SectionNumber] = C; |
| 352 | C->Sym = cast<DefinedRegular>(Leader); | ||
| 353 | cast<DefinedRegular>(Leader)->Data = &C->Repl; | ||
| 354 | } else { | ||
| 355 | SparseChunks[SectionNumber] = nullptr; | ||
| 356 | } | ||
| 357 | return Leader; | ||
| 259 | } | 358 | } |
| 260 | 359 | ||
| 261 | DefinedRegular *B; | 360 | // Read associative section definitions and prepare to handle the comdat |
| 262 | if (Sym.isExternal()) { | 361 | // leader symbol by setting the section's ComdatDefs pointer if we encounter a |
| 263 | COFFObj->getSymbolName(Sym, Name); | 362 | // non-associative comdat. |
| 264 | Symbol *S = | 363 | if (SparseChunks[SectionNumber] == PendingComdat) { |
| 265 | Symtab->addRegular(this, Name, SC->isCOMDAT(), Sym.getGeneric(), SC); | 364 | if (auto *Def = Sym.getSectionDefinition()) { |
| 266 | B = cast<DefinedRegular>(S->body()); | 365 | if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) |
| 267 | } else | 366 | readAssociativeDefinition(Sym, Def); |
| 268 | B = make<DefinedRegular>(this, /*Name*/ "", SC->isCOMDAT(), | 367 | else |
| 269 | /*IsExternal*/ false, Sym.getGeneric(), SC); | 368 | ComdatDefs[SectionNumber] = Def; |
| 270 | if (SC->isCOMDAT() && Sym.getValue() == 0 && !AuxP) | 369 | } |
| 271 | SC->setSymbol(B); | 370 | } |
| 272 | |||
| 273 | return B; | ||
| 274 | } | ||
| 275 | 371 | ||
| 276 | void ObjectFile::initializeSEH() { | 372 | if (SparseChunks[SectionNumber] == PendingComdat) |
| 277 | if (!SEHCompat || !SXData) | 373 | return None; |
| 278 | return; | 374 | return createRegular(Sym); |
| 279 | ArrayRef<uint8_t> A; | ||
| 280 | COFFObj->getSectionContents(SXData, A); | ||
| 281 | if (A.size() % 4 != 0) | ||
| 282 | fatal(".sxdata must be an array of symbol table indices"); | ||
| 283 | auto *I = reinterpret_cast<const ulittle32_t *>(A.data()); | ||
| 284 | auto *E = reinterpret_cast<const ulittle32_t *>(A.data() + A.size()); | ||
| 285 | for (; I != E; ++I) | ||
| 286 | SEHandlers.insert(SparseSymbolBodies[*I]); | ||
| 287 | } | 375 | } |
| 288 | 376 | ||
| 289 | MachineTypes ObjectFile::getMachineType() { | 377 | MachineTypes ObjFile::getMachineType() { |
| 290 | if (COFFObj) | 378 | if (COFFObj) |
| 291 | return static_cast<MachineTypes>(COFFObj->getMachine()); | 379 | return static_cast<MachineTypes>(COFFObj->getMachine()); |
| 292 | return IMAGE_FILE_MACHINE_UNKNOWN; | 380 | return IMAGE_FILE_MACHINE_UNKNOWN; |
| ... | @@ -332,26 +420,27 @@ void ImportFile::parse() { | ... | @@ -332,26 +420,27 @@ void ImportFile::parse() { |
| 332 | this->Hdr = Hdr; | 420 | this->Hdr = Hdr; |
| 333 | ExternalName = ExtName; | 421 | ExternalName = ExtName; |
| 334 | 422 | ||
| 335 | ImpSym = cast<DefinedImportData>( | 423 | ImpSym = Symtab->addImportData(ImpName, this); |
| 336 | Symtab->addImportData(ImpName, this)->body()); | 424 | |
| 337 | if (Hdr->getType() == llvm::COFF::IMPORT_CONST) | 425 | if (Hdr->getType() == llvm::COFF::IMPORT_CONST) |
| 338 | ConstSym = | 426 | static_cast<void>(Symtab->addImportData(Name, this)); |
| 339 | cast<DefinedImportData>(Symtab->addImportData(Name, this)->body()); | ||
| 340 | 427 | ||
| 341 | // If type is function, we need to create a thunk which jump to an | 428 | // If type is function, we need to create a thunk which jump to an |
| 342 | // address pointed by the __imp_ symbol. (This allows you to call | 429 | // address pointed by the __imp_ symbol. (This allows you to call |
| 343 | // DLL functions just like regular non-DLL functions.) | 430 | // DLL functions just like regular non-DLL functions.) |
| 344 | if (Hdr->getType() != llvm::COFF::IMPORT_CODE) | 431 | if (Hdr->getType() == llvm::COFF::IMPORT_CODE) |
| 345 | return; | 432 | ThunkSym = Symtab->addImportThunk(Name, ImpSym, Hdr->Machine); |
| 346 | ThunkSym = cast<DefinedImportThunk>( | ||
| 347 | Symtab->addImportThunk(Name, ImpSym, Hdr->Machine)->body()); | ||
| 348 | } | 433 | } |
| 349 | 434 | ||
| 350 | void BitcodeFile::parse() { | 435 | void BitcodeFile::parse() { |
| 351 | Obj = check(lto::InputFile::create(MemoryBufferRef( | 436 | Obj = check(lto::InputFile::create(MemoryBufferRef( |
| 352 | MB.getBuffer(), Saver.save(ParentName + MB.getBufferIdentifier())))); | 437 | MB.getBuffer(), Saver.save(ParentName + MB.getBufferIdentifier())))); |
| 438 | std::vector<std::pair<Symbol *, bool>> Comdat(Obj->getComdatTable().size()); | ||
| 439 | for (size_t I = 0; I != Obj->getComdatTable().size(); ++I) | ||
| 440 | Comdat[I] = Symtab->addComdat(this, Saver.save(Obj->getComdatTable()[I])); | ||
| 353 | for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) { | 441 | for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) { |
| 354 | StringRef SymName = Saver.save(ObjSym.getName()); | 442 | StringRef SymName = Saver.save(ObjSym.getName()); |
| 443 | int ComdatIndex = ObjSym.getComdatIndex(); | ||
| 355 | Symbol *Sym; | 444 | Symbol *Sym; |
| 356 | if (ObjSym.isUndefined()) { | 445 | if (ObjSym.isUndefined()) { |
| 357 | Sym = Symtab->addUndefined(SymName, this, false); | 446 | Sym = Symtab->addUndefined(SymName, this, false); |
| ... | @@ -361,13 +450,19 @@ void BitcodeFile::parse() { | ... | @@ -361,13 +450,19 @@ void BitcodeFile::parse() { |
| 361 | // Weak external. | 450 | // Weak external. |
| 362 | Sym = Symtab->addUndefined(SymName, this, true); | 451 | Sym = Symtab->addUndefined(SymName, this, true); |
| 363 | std::string Fallback = ObjSym.getCOFFWeakExternalFallback(); | 452 | std::string Fallback = ObjSym.getCOFFWeakExternalFallback(); |
| 364 | SymbolBody *Alias = Symtab->addUndefined(Saver.save(Fallback)); | 453 | Symbol *Alias = Symtab->addUndefined(Saver.save(Fallback)); |
| 365 | checkAndSetWeakAlias(Symtab, this, Sym->body(), Alias); | 454 | checkAndSetWeakAlias(Symtab, this, Sym, Alias); |
| 455 | } else if (ComdatIndex != -1) { | ||
| 456 | if (SymName == Obj->getComdatTable()[ComdatIndex]) | ||
| 457 | Sym = Comdat[ComdatIndex].first; | ||
| 458 | else if (Comdat[ComdatIndex].second) | ||
| 459 | Sym = Symtab->addRegular(this, SymName); | ||
| 460 | else | ||
| 461 | Sym = Symtab->addUndefined(SymName, this, false); | ||
| 366 | } else { | 462 | } else { |
| 367 | bool IsCOMDAT = ObjSym.getComdatIndex() != -1; | 463 | Sym = Symtab->addRegular(this, SymName); |
| 368 | Sym = Symtab->addRegular(this, SymName, IsCOMDAT); | ||
| 369 | } | 464 | } |
| 370 | SymbolBodies.push_back(Sym->body()); | 465 | SymbolBodies.push_back(Sym); |
| 371 | } | 466 | } |
| 372 | Directives = Obj->getCOFFLinkerOpts(); | 467 | Directives = Obj->getCOFFLinkerOpts(); |
| 373 | } | 468 | } |
| ... | @@ -398,14 +493,13 @@ static StringRef getBasename(StringRef Path) { | ... | @@ -398,14 +493,13 @@ static StringRef getBasename(StringRef Path) { |
| 398 | } | 493 | } |
| 399 | 494 | ||
| 400 | // Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)". | 495 | // Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)". |
| 401 | std::string lld::toString(coff::InputFile *File) { | 496 | std::string lld::toString(const coff::InputFile *File) { |
| 402 | if (!File) | 497 | if (!File) |
| 403 | return "(internal)"; | 498 | return "<internal>"; |
| 404 | if (File->ParentName.empty()) | 499 | if (File->ParentName.empty()) |
| 405 | return File->getName().lower(); | 500 | return File->getName(); |
| 406 | 501 | ||
| 407 | std::string Res = | 502 | return (getBasename(File->ParentName) + "(" + getBasename(File->getName()) + |
| 408 | (getBasename(File->ParentName) + "(" + getBasename(File->getName()) + ")") | 503 | ")") |
| 409 | .str(); | 504 | .str(); |
| 410 | return StringRef(Res).lower(); | ||
| 411 | } | 505 | } |
deps/lld/COFF/InputFiles.h+41-29| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | #define LLD_COFF_INPUT_FILES_H | 11 | #define LLD_COFF_INPUT_FILES_H |
| 12 | 12 | ||
| 13 | #include "Config.h" | 13 | #include "Config.h" |
| 14 | #include "lld/Core/LLVM.h" | 14 | #include "lld/Common/LLVM.h" |
| 15 | #include "llvm/ADT/ArrayRef.h" | 15 | #include "llvm/ADT/ArrayRef.h" |
| 16 | #include "llvm/ADT/DenseSet.h" | 16 | #include "llvm/ADT/DenseSet.h" |
| 17 | #include "llvm/LTO/LTO.h" | 17 | #include "llvm/LTO/LTO.h" |
| ... | @@ -31,6 +31,8 @@ class DbiModuleDescriptorBuilder; | ... | @@ -31,6 +31,8 @@ class DbiModuleDescriptorBuilder; |
| 31 | namespace lld { | 31 | namespace lld { |
| 32 | namespace coff { | 32 | namespace coff { |
| 33 | 33 | ||
| 34 | std::vector<MemoryBufferRef> getArchiveMembers(llvm::object::Archive *File); | ||
| 35 | |||
| 34 | using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; | 36 | using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; |
| 35 | using llvm::COFF::MachineTypes; | 37 | using llvm::COFF::MachineTypes; |
| 36 | using llvm::object::Archive; | 38 | using llvm::object::Archive; |
| ... | @@ -45,8 +47,7 @@ class DefinedImportData; | ... | @@ -45,8 +47,7 @@ class DefinedImportData; |
| 45 | class DefinedImportThunk; | 47 | class DefinedImportThunk; |
| 46 | class Lazy; | 48 | class Lazy; |
| 47 | class SectionChunk; | 49 | class SectionChunk; |
| 48 | struct Symbol; | 50 | class Symbol; |
| 49 | class SymbolBody; | ||
| 50 | class Undefined; | 51 | class Undefined; |
| 51 | 52 | ||
| 52 | // The root class of input files. | 53 | // The root class of input files. |
| ... | @@ -57,7 +58,7 @@ public: | ... | @@ -57,7 +58,7 @@ public: |
| 57 | virtual ~InputFile() {} | 58 | virtual ~InputFile() {} |
| 58 | 59 | ||
| 59 | // Returns the filename. | 60 | // Returns the filename. |
| 60 | StringRef getName() { return MB.getBufferIdentifier(); } | 61 | StringRef getName() const { return MB.getBufferIdentifier(); } |
| 61 | 62 | ||
| 62 | // Reads a file (the constructor doesn't do that). | 63 | // Reads a file (the constructor doesn't do that). |
| 63 | virtual void parse() = 0; | 64 | virtual void parse() = 0; |
| ... | @@ -101,32 +102,34 @@ private: | ... | @@ -101,32 +102,34 @@ private: |
| 101 | }; | 102 | }; |
| 102 | 103 | ||
| 103 | // .obj or .o file. This may be a member of an archive file. | 104 | // .obj or .o file. This may be a member of an archive file. |
| 104 | class ObjectFile : public InputFile { | 105 | class ObjFile : public InputFile { |
| 105 | public: | 106 | public: |
| 106 | explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {} | 107 | explicit ObjFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {} |
| 107 | static bool classof(const InputFile *F) { return F->kind() == ObjectKind; } | 108 | static bool classof(const InputFile *F) { return F->kind() == ObjectKind; } |
| 108 | void parse() override; | 109 | void parse() override; |
| 109 | MachineTypes getMachineType() override; | 110 | MachineTypes getMachineType() override; |
| 110 | std::vector<Chunk *> &getChunks() { return Chunks; } | 111 | ArrayRef<Chunk *> getChunks() { return Chunks; } |
| 111 | std::vector<SectionChunk *> &getDebugChunks() { return DebugChunks; } | 112 | ArrayRef<SectionChunk *> getDebugChunks() { return DebugChunks; } |
| 112 | std::vector<SymbolBody *> &getSymbols() { return SymbolBodies; } | 113 | ArrayRef<Symbol *> getSymbols() { return Symbols; } |
| 113 | 114 | ||
| 114 | // Returns a SymbolBody object for the SymbolIndex'th symbol in the | 115 | // Returns a Symbol object for the SymbolIndex'th symbol in the |
| 115 | // underlying object file. | 116 | // underlying object file. |
| 116 | SymbolBody *getSymbolBody(uint32_t SymbolIndex) { | 117 | Symbol *getSymbol(uint32_t SymbolIndex) { |
| 117 | return SparseSymbolBodies[SymbolIndex]; | 118 | return Symbols[SymbolIndex]; |
| 118 | } | 119 | } |
| 119 | 120 | ||
| 120 | // Returns the underying COFF file. | 121 | // Returns the underying COFF file. |
| 121 | COFFObjectFile *getCOFFObj() { return COFFObj.get(); } | 122 | COFFObjectFile *getCOFFObj() { return COFFObj.get(); } |
| 122 | 123 | ||
| 124 | static std::vector<ObjFile *> Instances; | ||
| 125 | |||
| 123 | // True if this object file is compatible with SEH. | 126 | // True if this object file is compatible with SEH. |
| 124 | // COFF-specific and x86-only. | 127 | // COFF-specific and x86-only. |
| 125 | bool SEHCompat = false; | 128 | bool SEHCompat = false; |
| 126 | 129 | ||
| 127 | // The list of safe exception handlers listed in .sxdata section. | 130 | // The symbol table indexes of the safe exception handlers. |
| 128 | // COFF-specific and x86-only. | 131 | // COFF-specific and x86-only. |
| 129 | std::set<SymbolBody *> SEHandlers; | 132 | ArrayRef<llvm::support::ulittle32_t> SXData; |
| 130 | 133 | ||
| 131 | // Pointer to the PDB module descriptor builder. Various debug info records | 134 | // Pointer to the PDB module descriptor builder. Various debug info records |
| 132 | // will reference object files by "module index", which is here. Things like | 135 | // will reference object files by "module index", which is here. Things like |
| ... | @@ -137,13 +140,23 @@ public: | ... | @@ -137,13 +140,23 @@ public: |
| 137 | private: | 140 | private: |
| 138 | void initializeChunks(); | 141 | void initializeChunks(); |
| 139 | void initializeSymbols(); | 142 | void initializeSymbols(); |
| 140 | void initializeSEH(); | ||
| 141 | 143 | ||
| 142 | SymbolBody *createDefined(COFFSymbolRef Sym, const void *Aux, bool IsFirst); | 144 | SectionChunk * |
| 143 | SymbolBody *createUndefined(COFFSymbolRef Sym); | 145 | readSection(uint32_t SectionNumber, |
| 146 | const llvm::object::coff_aux_section_definition *Def); | ||
| 147 | |||
| 148 | void readAssociativeDefinition( | ||
| 149 | COFFSymbolRef COFFSym, | ||
| 150 | const llvm::object::coff_aux_section_definition *Def); | ||
| 151 | |||
| 152 | llvm::Optional<Symbol *> | ||
| 153 | createDefined(COFFSymbolRef Sym, | ||
| 154 | std::vector<const llvm::object::coff_aux_section_definition *> | ||
| 155 | &ComdatDefs); | ||
| 156 | Symbol *createRegular(COFFSymbolRef Sym); | ||
| 157 | Symbol *createUndefined(COFFSymbolRef Sym); | ||
| 144 | 158 | ||
| 145 | std::unique_ptr<COFFObjectFile> COFFObj; | 159 | std::unique_ptr<COFFObjectFile> COFFObj; |
| 146 | const coff_section *SXData = nullptr; | ||
| 147 | 160 | ||
| 148 | // List of all chunks defined by this file. This includes both section | 161 | // List of all chunks defined by this file. This includes both section |
| 149 | // chunks and non-section chunks for common symbols. | 162 | // chunks and non-section chunks for common symbols. |
| ... | @@ -157,16 +170,13 @@ private: | ... | @@ -157,16 +170,13 @@ private: |
| 157 | // Nonexistent section indices are filled with null pointers. | 170 | // Nonexistent section indices are filled with null pointers. |
| 158 | // (Because section number is 1-based, the first slot is always a | 171 | // (Because section number is 1-based, the first slot is always a |
| 159 | // null pointer.) | 172 | // null pointer.) |
| 160 | std::vector<Chunk *> SparseChunks; | 173 | std::vector<SectionChunk *> SparseChunks; |
| 161 | |||
| 162 | // List of all symbols referenced or defined by this file. | ||
| 163 | std::vector<SymbolBody *> SymbolBodies; | ||
| 164 | 174 | ||
| 165 | // This vector contains the same symbols as SymbolBodies, but they | 175 | // This vector contains a list of all symbols defined or referenced by this |
| 166 | // are indexed such that you can get a SymbolBody by symbol | 176 | // file. They are indexed such that you can get a Symbol by symbol |
| 167 | // index. Nonexistent indices (which are occupied by auxiliary | 177 | // index. Nonexistent indices (which are occupied by auxiliary |
| 168 | // symbols in the real symbol table) are filled with null pointers. | 178 | // symbols in the real symbol table) are filled with null pointers. |
| 169 | std::vector<SymbolBody *> SparseSymbolBodies; | 179 | std::vector<Symbol *> Symbols; |
| 170 | }; | 180 | }; |
| 171 | 181 | ||
| 172 | // This type represents import library members that contain DLL names | 182 | // This type represents import library members that contain DLL names |
| ... | @@ -179,8 +189,9 @@ public: | ... | @@ -179,8 +189,9 @@ public: |
| 179 | 189 | ||
| 180 | static bool classof(const InputFile *F) { return F->kind() == ImportKind; } | 190 | static bool classof(const InputFile *F) { return F->kind() == ImportKind; } |
| 181 | 191 | ||
| 192 | static std::vector<ImportFile *> Instances; | ||
| 193 | |||
| 182 | DefinedImportData *ImpSym = nullptr; | 194 | DefinedImportData *ImpSym = nullptr; |
| 183 | DefinedImportData *ConstSym = nullptr; | ||
| 184 | DefinedImportThunk *ThunkSym = nullptr; | 195 | DefinedImportThunk *ThunkSym = nullptr; |
| 185 | std::string DLLName; | 196 | std::string DLLName; |
| 186 | 197 | ||
| ... | @@ -206,18 +217,19 @@ class BitcodeFile : public InputFile { | ... | @@ -206,18 +217,19 @@ class BitcodeFile : public InputFile { |
| 206 | public: | 217 | public: |
| 207 | explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {} | 218 | explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {} |
| 208 | static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } | 219 | static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } |
| 209 | std::vector<SymbolBody *> &getSymbols() { return SymbolBodies; } | 220 | ArrayRef<Symbol *> getSymbols() { return SymbolBodies; } |
| 210 | MachineTypes getMachineType() override; | 221 | MachineTypes getMachineType() override; |
| 222 | static std::vector<BitcodeFile *> Instances; | ||
| 211 | std::unique_ptr<llvm::lto::InputFile> Obj; | 223 | std::unique_ptr<llvm::lto::InputFile> Obj; |
| 212 | 224 | ||
| 213 | private: | 225 | private: |
| 214 | void parse() override; | 226 | void parse() override; |
| 215 | 227 | ||
| 216 | std::vector<SymbolBody *> SymbolBodies; | 228 | std::vector<Symbol *> SymbolBodies; |
| 217 | }; | 229 | }; |
| 218 | } // namespace coff | 230 | } // namespace coff |
| 219 | 231 | ||
| 220 | std::string toString(coff::InputFile *File); | 232 | std::string toString(const coff::InputFile *File); |
| 221 | } // namespace lld | 233 | } // namespace lld |
| 222 | 234 | ||
| 223 | #endif | 235 | #endif |
deps/lld/COFF/LTO.cpp+42-19| ... | @@ -9,15 +9,16 @@ | ... | @@ -9,15 +9,16 @@ |
| 9 | 9 | ||
| 10 | #include "LTO.h" | 10 | #include "LTO.h" |
| 11 | #include "Config.h" | 11 | #include "Config.h" |
| 12 | #include "Error.h" | ||
| 13 | #include "InputFiles.h" | 12 | #include "InputFiles.h" |
| 14 | #include "Symbols.h" | 13 | #include "Symbols.h" |
| 15 | #include "lld/Core/TargetOptionsCommandFlags.h" | 14 | #include "lld/Common/ErrorHandler.h" |
| 15 | #include "lld/Common/TargetOptionsCommandFlags.h" | ||
| 16 | #include "llvm/ADT/STLExtras.h" | 16 | #include "llvm/ADT/STLExtras.h" |
| 17 | #include "llvm/ADT/SmallString.h" | 17 | #include "llvm/ADT/SmallString.h" |
| 18 | #include "llvm/ADT/StringRef.h" | 18 | #include "llvm/ADT/StringRef.h" |
| 19 | #include "llvm/ADT/Twine.h" | 19 | #include "llvm/ADT/Twine.h" |
| 20 | #include "llvm/IR/DiagnosticPrinter.h" | 20 | #include "llvm/IR/DiagnosticPrinter.h" |
| 21 | #include "llvm/LTO/Caching.h" | ||
| 21 | #include "llvm/LTO/Config.h" | 22 | #include "llvm/LTO/Config.h" |
| 22 | #include "llvm/LTO/LTO.h" | 23 | #include "llvm/LTO/LTO.h" |
| 23 | #include "llvm/Object/SymbolicFile.h" | 24 | #include "llvm/Object/SymbolicFile.h" |
| ... | @@ -48,10 +49,8 @@ static void diagnosticHandler(const DiagnosticInfo &DI) { | ... | @@ -48,10 +49,8 @@ static void diagnosticHandler(const DiagnosticInfo &DI) { |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | static void checkError(Error E) { | 51 | static void checkError(Error E) { |
| 51 | handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) -> Error { | 52 | handleAllErrors(std::move(E), |
| 52 | error(EIB.message()); | 53 | [&](ErrorInfoBase &EIB) { error(EIB.message()); }); |
| 53 | return Error::success(); | ||
| 54 | }); | ||
| 55 | } | 54 | } |
| 56 | 55 | ||
| 57 | static void saveBuffer(StringRef Buffer, const Twine &Path) { | 56 | static void saveBuffer(StringRef Buffer, const Twine &Path) { |
| ... | @@ -65,7 +64,13 @@ static void saveBuffer(StringRef Buffer, const Twine &Path) { | ... | @@ -65,7 +64,13 @@ static void saveBuffer(StringRef Buffer, const Twine &Path) { |
| 65 | static std::unique_ptr<lto::LTO> createLTO() { | 64 | static std::unique_ptr<lto::LTO> createLTO() { |
| 66 | lto::Config Conf; | 65 | lto::Config Conf; |
| 67 | Conf.Options = InitTargetOptionsFromCodeGenFlags(); | 66 | Conf.Options = InitTargetOptionsFromCodeGenFlags(); |
| 68 | Conf.RelocModel = Reloc::PIC_; | 67 | // Use static reloc model on 32-bit x86 because it usually results in more |
| 68 | // compact code, and because there are also known code generation bugs when | ||
| 69 | // using the PIC model (see PR34306). | ||
| 70 | if (Config->Machine == COFF::IMAGE_FILE_MACHINE_I386) | ||
| 71 | Conf.RelocModel = Reloc::Static; | ||
| 72 | else | ||
| 73 | Conf.RelocModel = Reloc::PIC_; | ||
| 69 | Conf.DisableVerify = true; | 74 | Conf.DisableVerify = true; |
| 70 | Conf.DiagHandler = diagnosticHandler; | 75 | Conf.DiagHandler = diagnosticHandler; |
| 71 | Conf.OptLevel = Config->LTOOptLevel; | 76 | Conf.OptLevel = Config->LTOOptLevel; |
| ... | @@ -83,20 +88,17 @@ BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} | ... | @@ -83,20 +88,17 @@ BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} |
| 83 | 88 | ||
| 84 | BitcodeCompiler::~BitcodeCompiler() = default; | 89 | BitcodeCompiler::~BitcodeCompiler() = default; |
| 85 | 90 | ||
| 86 | static void undefine(Symbol *S) { | 91 | static void undefine(Symbol *S) { replaceSymbol<Undefined>(S, S->getName()); } |
| 87 | replaceBody<Undefined>(S, S->body()->getName()); | ||
| 88 | } | ||
| 89 | 92 | ||
| 90 | void BitcodeCompiler::add(BitcodeFile &F) { | 93 | void BitcodeCompiler::add(BitcodeFile &F) { |
| 91 | lto::InputFile &Obj = *F.Obj; | 94 | lto::InputFile &Obj = *F.Obj; |
| 92 | unsigned SymNum = 0; | 95 | unsigned SymNum = 0; |
| 93 | std::vector<SymbolBody *> SymBodies = F.getSymbols(); | 96 | std::vector<Symbol *> SymBodies = F.getSymbols(); |
| 94 | std::vector<lto::SymbolResolution> Resols(SymBodies.size()); | 97 | std::vector<lto::SymbolResolution> Resols(SymBodies.size()); |
| 95 | 98 | ||
| 96 | // Provide a resolution to the LTO API for each symbol. | 99 | // Provide a resolution to the LTO API for each symbol. |
| 97 | for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { | 100 | for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { |
| 98 | SymbolBody *B = SymBodies[SymNum]; | 101 | Symbol *Sym = SymBodies[SymNum]; |
| 99 | Symbol *Sym = B->symbol(); | ||
| 100 | lto::SymbolResolution &R = Resols[SymNum]; | 102 | lto::SymbolResolution &R = Resols[SymNum]; |
| 101 | ++SymNum; | 103 | ++SymNum; |
| 102 | 104 | ||
| ... | @@ -105,7 +107,7 @@ void BitcodeCompiler::add(BitcodeFile &F) { | ... | @@ -105,7 +107,7 @@ void BitcodeCompiler::add(BitcodeFile &F) { |
| 105 | // flags an undefined in IR with a definition in ASM as prevailing. | 107 | // flags an undefined in IR with a definition in ASM as prevailing. |
| 106 | // Once IRObjectFile is fixed to report only one symbol this hack can | 108 | // Once IRObjectFile is fixed to report only one symbol this hack can |
| 107 | // be removed. | 109 | // be removed. |
| 108 | R.Prevailing = !ObjSym.isUndefined() && B->getFile() == &F; | 110 | R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F; |
| 109 | R.VisibleToRegularObj = Sym->IsUsedInRegularObj; | 111 | R.VisibleToRegularObj = Sym->IsUsedInRegularObj; |
| 110 | if (R.Prevailing) | 112 | if (R.Prevailing) |
| 111 | undefine(Sym); | 113 | undefine(Sym); |
| ... | @@ -118,11 +120,27 @@ void BitcodeCompiler::add(BitcodeFile &F) { | ... | @@ -118,11 +120,27 @@ void BitcodeCompiler::add(BitcodeFile &F) { |
| 118 | std::vector<StringRef> BitcodeCompiler::compile() { | 120 | std::vector<StringRef> BitcodeCompiler::compile() { |
| 119 | unsigned MaxTasks = LTOObj->getMaxTasks(); | 121 | unsigned MaxTasks = LTOObj->getMaxTasks(); |
| 120 | Buff.resize(MaxTasks); | 122 | Buff.resize(MaxTasks); |
| 121 | 123 | Files.resize(MaxTasks); | |
| 122 | checkError(LTOObj->run([&](size_t Task) { | 124 | |
| 123 | return llvm::make_unique<lto::NativeObjectStream>( | 125 | // The /lldltocache option specifies the path to a directory in which to cache |
| 124 | llvm::make_unique<raw_svector_ostream>(Buff[Task])); | 126 | // native object files for ThinLTO incremental builds. If a path was |
| 125 | })); | 127 | // specified, configure LTO to use it as the cache directory. |
| 128 | lto::NativeObjectCache Cache; | ||
| 129 | if (!Config->LTOCache.empty()) | ||
| 130 | Cache = check( | ||
| 131 | lto::localCache(Config->LTOCache, | ||
| 132 | [&](size_t Task, std::unique_ptr<MemoryBuffer> MB, | ||
| 133 | StringRef Path) { Files[Task] = std::move(MB); })); | ||
| 134 | |||
| 135 | checkError(LTOObj->run( | ||
| 136 | [&](size_t Task) { | ||
| 137 | return llvm::make_unique<lto::NativeObjectStream>( | ||
| 138 | llvm::make_unique<raw_svector_ostream>(Buff[Task])); | ||
| 139 | }, | ||
| 140 | Cache)); | ||
| 141 | |||
| 142 | if (!Config->LTOCache.empty()) | ||
| 143 | pruneCache(Config->LTOCache, Config->LTOCachePolicy); | ||
| 126 | 144 | ||
| 127 | std::vector<StringRef> Ret; | 145 | std::vector<StringRef> Ret; |
| 128 | for (unsigned I = 0; I != MaxTasks; ++I) { | 146 | for (unsigned I = 0; I != MaxTasks; ++I) { |
| ... | @@ -136,5 +154,10 @@ std::vector<StringRef> BitcodeCompiler::compile() { | ... | @@ -136,5 +154,10 @@ std::vector<StringRef> BitcodeCompiler::compile() { |
| 136 | } | 154 | } |
| 137 | Ret.emplace_back(Buff[I].data(), Buff[I].size()); | 155 | Ret.emplace_back(Buff[I].data(), Buff[I].size()); |
| 138 | } | 156 | } |
| 157 | |||
| 158 | for (std::unique_ptr<MemoryBuffer> &File : Files) | ||
| 159 | if (File) | ||
| 160 | Ret.push_back(File->getBuffer()); | ||
| 161 | |||
| 139 | return Ret; | 162 | return Ret; |
| 140 | } | 163 | } |
deps/lld/COFF/LTO.h+2-1| ... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
| 21 | #ifndef LLD_COFF_LTO_H | 21 | #ifndef LLD_COFF_LTO_H |
| 22 | #define LLD_COFF_LTO_H | 22 | #define LLD_COFF_LTO_H |
| 23 | 23 | ||
| 24 | #include "lld/Core/LLVM.h" | 24 | #include "lld/Common/LLVM.h" |
| 25 | #include "llvm/ADT/SmallString.h" | 25 | #include "llvm/ADT/SmallString.h" |
| 26 | #include <memory> | 26 | #include <memory> |
| 27 | #include <vector> | 27 | #include <vector> |
| ... | @@ -49,6 +49,7 @@ public: | ... | @@ -49,6 +49,7 @@ public: |
| 49 | private: | 49 | private: |
| 50 | std::unique_ptr<llvm::lto::LTO> LTOObj; | 50 | std::unique_ptr<llvm::lto::LTO> LTOObj; |
| 51 | std::vector<SmallString<0>> Buff; | 51 | std::vector<SmallString<0>> Buff; |
| 52 | std::vector<std::unique_ptr<MemoryBuffer>> Files; | ||
| 52 | }; | 53 | }; |
| 53 | } | 54 | } |
| 54 | } | 55 | } |
deps/lld/COFF/MapFile.cpp+5-5| ... | @@ -20,11 +20,11 @@ | ... | @@ -20,11 +20,11 @@ |
| 20 | //===----------------------------------------------------------------------===// | 20 | //===----------------------------------------------------------------------===// |
| 21 | 21 | ||
| 22 | #include "MapFile.h" | 22 | #include "MapFile.h" |
| 23 | #include "Error.h" | ||
| 24 | #include "SymbolTable.h" | 23 | #include "SymbolTable.h" |
| 25 | #include "Symbols.h" | 24 | #include "Symbols.h" |
| 26 | #include "Writer.h" | 25 | #include "Writer.h" |
| 27 | 26 | ||
| 27 | #include "lld/Common/ErrorHandler.h" | ||
| 28 | #include "llvm/Support/Parallel.h" | 28 | #include "llvm/Support/Parallel.h" |
| 29 | #include "llvm/Support/raw_ostream.h" | 29 | #include "llvm/Support/raw_ostream.h" |
| 30 | 30 | ||
| ... | @@ -48,9 +48,9 @@ static std::string indent(int Depth) { return std::string(Depth * 8, ' '); } | ... | @@ -48,9 +48,9 @@ static std::string indent(int Depth) { return std::string(Depth * 8, ' '); } |
| 48 | // Returns a list of all symbols that we want to print out. | 48 | // Returns a list of all symbols that we want to print out. |
| 49 | static std::vector<DefinedRegular *> getSymbols() { | 49 | static std::vector<DefinedRegular *> getSymbols() { |
| 50 | std::vector<DefinedRegular *> V; | 50 | std::vector<DefinedRegular *> V; |
| 51 | for (coff::ObjectFile *File : Symtab->ObjectFiles) | 51 | for (ObjFile *File : ObjFile::Instances) |
| 52 | for (SymbolBody *B : File->getSymbols()) | 52 | for (Symbol *B : File->getSymbols()) |
| 53 | if (auto *Sym = dyn_cast<DefinedRegular>(B)) | 53 | if (auto *Sym = dyn_cast_or_null<DefinedRegular>(B)) |
| 54 | if (Sym && !Sym->getCOFFSymbol().isSectionDefinition()) | 54 | if (Sym && !Sym->getCOFFSymbol().isSectionDefinition()) |
| 55 | V.push_back(Sym); | 55 | V.push_back(Sym); |
| 56 | return V; | 56 | return V; |
| ... | @@ -115,7 +115,7 @@ void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) { | ... | @@ -115,7 +115,7 @@ void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) { |
| 115 | if (!SC) | 115 | if (!SC) |
| 116 | continue; | 116 | continue; |
| 117 | 117 | ||
| 118 | writeHeader(OS, SC->getRVA(), SC->getSize(), SC->getAlign()); | 118 | writeHeader(OS, SC->getRVA(), SC->getSize(), SC->Alignment); |
| 119 | OS << indent(1) << SC->File->getName() << ":(" << SC->getSectionName() | 119 | OS << indent(1) << SC->File->getName() << ":(" << SC->getSectionName() |
| 120 | << ")\n"; | 120 | << ")\n"; |
| 121 | for (DefinedRegular *Sym : SectionSyms[SC]) | 121 | for (DefinedRegular *Sym : SectionSyms[SC]) |
deps/lld/COFF/MarkLive.cpp+6-12| ... | @@ -18,7 +18,7 @@ namespace coff { | ... | @@ -18,7 +18,7 @@ namespace coff { |
| 18 | // Set live bit on for each reachable chunk. Unmarked (unreachable) | 18 | // Set live bit on for each reachable chunk. Unmarked (unreachable) |
| 19 | // COMDAT chunks will be ignored by Writer, so they will be excluded | 19 | // COMDAT chunks will be ignored by Writer, so they will be excluded |
| 20 | // from the final output. | 20 | // from the final output. |
| 21 | void markLive(const std::vector<Chunk *> &Chunks) { | 21 | void markLive(ArrayRef<Chunk *> Chunks) { |
| 22 | // We build up a worklist of sections which have been marked as live. We only | 22 | // We build up a worklist of sections which have been marked as live. We only |
| 23 | // push into the worklist when we discover an unmarked section, and we mark | 23 | // push into the worklist when we discover an unmarked section, and we mark |
| 24 | // as we push, so sections never appear twice in the list. | 24 | // as we push, so sections never appear twice in the list. |
| ... | @@ -37,7 +37,7 @@ void markLive(const std::vector<Chunk *> &Chunks) { | ... | @@ -37,7 +37,7 @@ void markLive(const std::vector<Chunk *> &Chunks) { |
| 37 | Worklist.push_back(C); | 37 | Worklist.push_back(C); |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | auto AddSym = [&](SymbolBody *B) { | 40 | auto AddSym = [&](Symbol *B) { |
| 41 | if (auto *Sym = dyn_cast<DefinedRegular>(B)) | 41 | if (auto *Sym = dyn_cast<DefinedRegular>(B)) |
| 42 | Enqueue(Sym->getChunk()); | 42 | Enqueue(Sym->getChunk()); |
| 43 | else if (auto *Sym = dyn_cast<DefinedImportData>(B)) | 43 | else if (auto *Sym = dyn_cast<DefinedImportData>(B)) |
| ... | @@ -47,23 +47,17 @@ void markLive(const std::vector<Chunk *> &Chunks) { | ... | @@ -47,23 +47,17 @@ void markLive(const std::vector<Chunk *> &Chunks) { |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | // Add GC root chunks. | 49 | // Add GC root chunks. |
| 50 | for (SymbolBody *B : Config->GCRoot) | 50 | for (Symbol *B : Config->GCRoot) |
| 51 | AddSym(B); | 51 | AddSym(B); |
| 52 | 52 | ||
| 53 | while (!Worklist.empty()) { | 53 | while (!Worklist.empty()) { |
| 54 | SectionChunk *SC = Worklist.pop_back_val(); | 54 | SectionChunk *SC = Worklist.pop_back_val(); |
| 55 | |||
| 56 | // If this section was discarded, there are relocations referring to | ||
| 57 | // discarded sections. Ignore these sections to avoid crashing. They will be | ||
| 58 | // diagnosed during relocation processing. | ||
| 59 | if (SC->isDiscarded()) | ||
| 60 | continue; | ||
| 61 | |||
| 62 | assert(SC->isLive() && "We mark as live when pushing onto the worklist!"); | 55 | assert(SC->isLive() && "We mark as live when pushing onto the worklist!"); |
| 63 | 56 | ||
| 64 | // Mark all symbols listed in the relocation table for this section. | 57 | // Mark all symbols listed in the relocation table for this section. |
| 65 | for (SymbolBody *B : SC->symbols()) | 58 | for (Symbol *B : SC->symbols()) |
| 66 | AddSym(B); | 59 | if (B) |
| 60 | AddSym(B); | ||
| 67 | 61 | ||
| 68 | // Mark associative sections if any. | 62 | // Mark associative sections if any. |
| 69 | for (SectionChunk *C : SC->children()) | 63 | for (SectionChunk *C : SC->children()) |
deps/lld/COFF/Memory.h deleted-52| ... | @@ -1,52 +0,0 @@ | ||
| 1 | //===- Memory.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 | // See ELF/Memory.h | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #ifndef LLD_COFF_MEMORY_H | ||
| 15 | #define LLD_COFF_MEMORY_H | ||
| 16 | |||
| 17 | #include "llvm/Support/Allocator.h" | ||
| 18 | #include "llvm/Support/StringSaver.h" | ||
| 19 | #include <vector> | ||
| 20 | |||
| 21 | namespace lld { | ||
| 22 | namespace coff { | ||
| 23 | |||
| 24 | extern llvm::BumpPtrAllocator BAlloc; | ||
| 25 | extern llvm::StringSaver Saver; | ||
| 26 | |||
| 27 | struct SpecificAllocBase { | ||
| 28 | SpecificAllocBase() { Instances.push_back(this); } | ||
| 29 | virtual ~SpecificAllocBase() = default; | ||
| 30 | virtual void reset() = 0; | ||
| 31 | static std::vector<SpecificAllocBase *> Instances; | ||
| 32 | }; | ||
| 33 | |||
| 34 | template <class T> struct SpecificAlloc : public SpecificAllocBase { | ||
| 35 | void reset() override { Alloc.DestroyAll(); } | ||
| 36 | llvm::SpecificBumpPtrAllocator<T> Alloc; | ||
| 37 | }; | ||
| 38 | |||
| 39 | template <typename T, typename... U> T *make(U &&... Args) { | ||
| 40 | static SpecificAlloc<T> Alloc; | ||
| 41 | return new (Alloc.Alloc.Allocate()) T(std::forward<U>(Args)...); | ||
| 42 | } | ||
| 43 | |||
| 44 | inline void freeArena() { | ||
| 45 | for (SpecificAllocBase *Alloc : SpecificAllocBase::Instances) | ||
| 46 | Alloc->reset(); | ||
| 47 | BAlloc.Reset(); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | #endif | ||
deps/lld/COFF/MinGW.cpp created+146| ... | @@ -0,0 +1,146 @@ | ||
| 1 | //===- MinGW.cpp ----------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "MinGW.h" | ||
| 11 | #include "SymbolTable.h" | ||
| 12 | #include "lld/Common/ErrorHandler.h" | ||
| 13 | #include "llvm/Object/COFF.h" | ||
| 14 | #include "llvm/Support/Path.h" | ||
| 15 | #include "llvm/Support/raw_ostream.h" | ||
| 16 | |||
| 17 | using namespace lld; | ||
| 18 | using namespace lld::coff; | ||
| 19 | using namespace llvm; | ||
| 20 | using namespace llvm::COFF; | ||
| 21 | |||
| 22 | AutoExporter::AutoExporter() { | ||
| 23 | if (Config->Machine == I386) { | ||
| 24 | ExcludeSymbols = { | ||
| 25 | "__NULL_IMPORT_DESCRIPTOR", | ||
| 26 | "__pei386_runtime_relocator", | ||
| 27 | "_do_pseudo_reloc", | ||
| 28 | "_impure_ptr", | ||
| 29 | "__impure_ptr", | ||
| 30 | "__fmode", | ||
| 31 | "_environ", | ||
| 32 | "___dso_handle", | ||
| 33 | // These are the MinGW names that differ from the standard | ||
| 34 | // ones (lacking an extra underscore). | ||
| 35 | "_DllMain@12", | ||
| 36 | "_DllEntryPoint@12", | ||
| 37 | "_DllMainCRTStartup@12", | ||
| 38 | }; | ||
| 39 | } else { | ||
| 40 | ExcludeSymbols = { | ||
| 41 | "_NULL_IMPORT_DESCRIPTOR", | ||
| 42 | "_pei386_runtime_relocator", | ||
| 43 | "do_pseudo_reloc", | ||
| 44 | "impure_ptr", | ||
| 45 | "_impure_ptr", | ||
| 46 | "_fmode", | ||
| 47 | "environ", | ||
| 48 | "__dso_handle", | ||
| 49 | // These are the MinGW names that differ from the standard | ||
| 50 | // ones (lacking an extra underscore). | ||
| 51 | "DllMain", | ||
| 52 | "DllEntryPoint", | ||
| 53 | "DllMainCRTStartup", | ||
| 54 | }; | ||
| 55 | } | ||
| 56 | |||
| 57 | ExcludeLibs = { | ||
| 58 | "libgcc", | ||
| 59 | "libgcc_s", | ||
| 60 | "libstdc++", | ||
| 61 | "libmingw32", | ||
| 62 | "libmingwex", | ||
| 63 | "libg2c", | ||
| 64 | "libsupc++", | ||
| 65 | "libobjc", | ||
| 66 | "libgcj", | ||
| 67 | "libclang_rt.builtins-aarch64", | ||
| 68 | "libclang_rt.builtins-arm", | ||
| 69 | "libclang_rt.builtins-i386", | ||
| 70 | "libclang_rt.builtins-x86_64", | ||
| 71 | "libc++", | ||
| 72 | "libc++abi", | ||
| 73 | "libunwind", | ||
| 74 | "libmsvcrt", | ||
| 75 | "libucrtbase", | ||
| 76 | }; | ||
| 77 | ExcludeObjects = { | ||
| 78 | "crt0.o", | ||
| 79 | "crt1.o", | ||
| 80 | "crt1u.o", | ||
| 81 | "crt2.o", | ||
| 82 | "crt2u.o", | ||
| 83 | "dllcrt1.o", | ||
| 84 | "dllcrt2.o", | ||
| 85 | "gcrt0.o", | ||
| 86 | "gcrt1.o", | ||
| 87 | "gcrt2.o", | ||
| 88 | "crtbegin.o", | ||
| 89 | "crtend.o", | ||
| 90 | }; | ||
| 91 | } | ||
| 92 | |||
| 93 | bool AutoExporter::shouldExport(Defined *Sym) const { | ||
| 94 | if (!Sym || !Sym->isLive() || !Sym->getChunk()) | ||
| 95 | return false; | ||
| 96 | |||
| 97 | // Only allow the symbol kinds that make sense to export; in particular, | ||
| 98 | // disallow import symbols. | ||
| 99 | if (!isa<DefinedRegular>(Sym) && !isa<DefinedCommon>(Sym)) | ||
| 100 | return false; | ||
| 101 | if (ExcludeSymbols.count(Sym->getName())) | ||
| 102 | return false; | ||
| 103 | |||
| 104 | // Don't export anything that looks like an import symbol (which also can be | ||
| 105 | // a manually defined data symbol with such a name). | ||
| 106 | if (Sym->getName().startswith("__imp_")) | ||
| 107 | return false; | ||
| 108 | |||
| 109 | // If a corresponding __imp_ symbol exists and is defined, don't export it. | ||
| 110 | if (Symtab->find(("__imp_" + Sym->getName()).str())) | ||
| 111 | return false; | ||
| 112 | |||
| 113 | // Check that file is non-null before dereferencing it, symbols not | ||
| 114 | // originating in regular object files probably shouldn't be exported. | ||
| 115 | if (!Sym->getFile()) | ||
| 116 | return false; | ||
| 117 | |||
| 118 | StringRef LibName = sys::path::filename(Sym->getFile()->ParentName); | ||
| 119 | |||
| 120 | // Drop the file extension. | ||
| 121 | LibName = LibName.substr(0, LibName.rfind('.')); | ||
| 122 | if (!LibName.empty()) | ||
| 123 | return !ExcludeLibs.count(LibName); | ||
| 124 | |||
| 125 | StringRef FileName = sys::path::filename(Sym->getFile()->getName()); | ||
| 126 | return !ExcludeObjects.count(FileName); | ||
| 127 | } | ||
| 128 | |||
| 129 | void coff::writeDefFile(StringRef Name) { | ||
| 130 | std::error_code EC; | ||
| 131 | raw_fd_ostream OS(Name, EC, sys::fs::F_None); | ||
| 132 | if (EC) | ||
| 133 | fatal("cannot open " + Name + ": " + EC.message()); | ||
| 134 | |||
| 135 | OS << "EXPORTS\n"; | ||
| 136 | for (Export &E : Config->Exports) { | ||
| 137 | OS << " " << E.ExportName << " " | ||
| 138 | << "@" << E.Ordinal; | ||
| 139 | if (auto *Def = dyn_cast_or_null<Defined>(E.Sym)) { | ||
| 140 | if (Def && Def->getChunk() && | ||
| 141 | !(Def->getChunk()->getPermissions() & IMAGE_SCN_MEM_EXECUTE)) | ||
| 142 | OS << " DATA"; | ||
| 143 | } | ||
| 144 | OS << "\n"; | ||
| 145 | } | ||
| 146 | } | ||
deps/lld/COFF/MinGW.h created+38| ... | @@ -0,0 +1,38 @@ | ||
| 1 | //===- MinGW.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_COFF_MINGW_H | ||
| 11 | #define LLD_COFF_MINGW_H | ||
| 12 | |||
| 13 | #include "Config.h" | ||
| 14 | #include "Symbols.h" | ||
| 15 | #include "lld/Common/LLVM.h" | ||
| 16 | |||
| 17 | namespace lld { | ||
| 18 | namespace coff { | ||
| 19 | |||
| 20 | // Logic for deciding what symbols to export, when exporting all | ||
| 21 | // symbols for MinGW. | ||
| 22 | class AutoExporter { | ||
| 23 | public: | ||
| 24 | AutoExporter(); | ||
| 25 | |||
| 26 | llvm::StringSet<> ExcludeSymbols; | ||
| 27 | llvm::StringSet<> ExcludeLibs; | ||
| 28 | llvm::StringSet<> ExcludeObjects; | ||
| 29 | |||
| 30 | bool shouldExport(Defined *Sym) const; | ||
| 31 | }; | ||
| 32 | |||
| 33 | void writeDefFile(StringRef Name); | ||
| 34 | |||
| 35 | } // namespace coff | ||
| 36 | } // namespace lld | ||
| 37 | |||
| 38 | #endif | ||
deps/lld/COFF/Options.td+46-20| ... | @@ -9,13 +9,15 @@ class F<string name> : Flag<["/", "-", "-?"], name>; | ... | @@ -9,13 +9,15 @@ class F<string name> : Flag<["/", "-", "-?"], name>; |
| 9 | class P<string name, string help> : | 9 | class P<string name, string help> : |
| 10 | Joined<["/", "-", "-?"], name#":">, HelpText<help>; | 10 | Joined<["/", "-", "-?"], name#":">, HelpText<help>; |
| 11 | 11 | ||
| 12 | // Boolean flag suffixed by ":no". | 12 | // Boolean flag which can be suffixed by ":no". Using it unsuffixed turns the |
| 13 | multiclass B<string name, string help> { | 13 | // flag on and using it suffixed by ":no" turns it off. |
| 14 | def "" : F<name>; | 14 | multiclass B<string name, string help_on, string help_off> { |
| 15 | def _no : F<name#":no">, HelpText<help>; | 15 | def "" : F<name>, HelpText<help_on>; |
| 16 | def _no : F<name#":no">, HelpText<help_off>; | ||
| 16 | } | 17 | } |
| 17 | 18 | ||
| 18 | def align : P<"align", "Section alignment">; | 19 | def align : P<"align", "Section alignment">; |
| 20 | def aligncomm : P<"aligncomm", "Set common symbol alignment">; | ||
| 19 | def alternatename : P<"alternatename", "Define weak alias">; | 21 | def alternatename : P<"alternatename", "Define weak alias">; |
| 20 | def base : P<"base", "Base address of the program">; | 22 | def base : P<"base", "Base address of the program">; |
| 21 | def defaultlib : P<"defaultlib", "Add the library to the list of input files">; | 23 | def defaultlib : P<"defaultlib", "Add the library to the list of input files">; |
| ... | @@ -27,9 +29,12 @@ def export : P<"export", "Export a function">; | ... | @@ -27,9 +29,12 @@ def export : P<"export", "Export a function">; |
| 27 | // No help text because /failifmismatch is not intended to be used by the user. | 29 | // No help text because /failifmismatch is not intended to be used by the user. |
| 28 | def failifmismatch : P<"failifmismatch", "">; | 30 | def failifmismatch : P<"failifmismatch", "">; |
| 29 | def heap : P<"heap", "Size of the heap">; | 31 | def heap : P<"heap", "Size of the heap">; |
| 32 | def ignore : P<"ignore", "Specify warning codes to ignore">; | ||
| 30 | def implib : P<"implib", "Import library name">; | 33 | def implib : P<"implib", "Import library name">; |
| 31 | def libpath : P<"libpath", "Additional library search path">; | 34 | def libpath : P<"libpath", "Additional library search path">; |
| 32 | def linkrepro : P<"linkrepro", "Dump linker invocation and input files for debugging">; | 35 | def linkrepro : P<"linkrepro", "Dump linker invocation and input files for debugging">; |
| 36 | def lldltocache : P<"lldltocache", "Path to ThinLTO cached object file directory">; | ||
| 37 | def lldltocachepolicy : P<"lldltocachepolicy", "Pruning policy for the ThinLTO cache">; | ||
| 33 | def lldsavetemps : F<"lldsavetemps">, | 38 | def lldsavetemps : F<"lldsavetemps">, |
| 34 | HelpText<"Save temporary files instead of deleting them">; | 39 | HelpText<"Save temporary files instead of deleting them">; |
| 35 | def machine : P<"machine", "Specify target platform">; | 40 | def machine : P<"machine", "Specify target platform">; |
| ... | @@ -44,6 +49,7 @@ def stack : P<"stack", "Size of the stack">; | ... | @@ -44,6 +49,7 @@ def stack : P<"stack", "Size of the stack">; |
| 44 | def stub : P<"stub", "Specify DOS stub file">; | 49 | def stub : P<"stub", "Specify DOS stub file">; |
| 45 | def subsystem : P<"subsystem", "Specify subsystem">; | 50 | def subsystem : P<"subsystem", "Specify subsystem">; |
| 46 | def version : P<"version", "Specify a version number in the PE header">; | 51 | def version : P<"version", "Specify a version number in the PE header">; |
| 52 | def wholearchive_file : P<"wholearchive", "Include all object files from this archive">; | ||
| 47 | 53 | ||
| 48 | def disallowlib : Joined<["/", "-", "-?"], "disallowlib:">, Alias<nodefaultlib>; | 54 | def disallowlib : Joined<["/", "-", "-?"], "disallowlib:">, Alias<nodefaultlib>; |
| 49 | 55 | ||
| ... | @@ -75,31 +81,53 @@ def profile : F<"profile">; | ... | @@ -75,31 +81,53 @@ def profile : F<"profile">; |
| 75 | def swaprun_cd : F<"swaprun:cd">; | 81 | def swaprun_cd : F<"swaprun:cd">; |
| 76 | def swaprun_net : F<"swaprun:net">; | 82 | def swaprun_net : F<"swaprun:net">; |
| 77 | def verbose : F<"verbose">; | 83 | def verbose : F<"verbose">; |
| 84 | def wholearchive_flag : F<"wholearchive">; | ||
| 78 | 85 | ||
| 79 | def force : F<"force">, | 86 | def force : F<"force">, |
| 80 | HelpText<"Allow undefined symbols when creating executables">; | 87 | HelpText<"Allow undefined symbols when creating executables">; |
| 81 | def force_unresolved : F<"force:unresolved">; | 88 | def force_unresolved : F<"force:unresolved">; |
| 89 | defm WX : B<"WX", "Treat warnings as errors", "Don't treat warnings as errors">; | ||
| 82 | 90 | ||
| 83 | defm allowbind: B<"allowbind", "Disable DLL binding">; | 91 | defm allowbind : B<"allowbind", "Enable DLL binding (default)", |
| 84 | defm allowisolation : B<"allowisolation", "Set NO_ISOLATION bit">; | 92 | "Disable DLL binding">; |
| 93 | defm allowisolation : B<"allowisolation", "Enable DLL isolation (default)", | ||
| 94 | "Disable DLL isolation">; | ||
| 85 | defm appcontainer : B<"appcontainer", | 95 | defm appcontainer : B<"appcontainer", |
| 86 | "Image can only be run in an app container">; | 96 | "Image can only be run in an app container", |
| 87 | defm dynamicbase : B<"dynamicbase", | 97 | "Image can run outside an app container (default)">; |
| 88 | "Disable address space layout randomization">; | 98 | defm dynamicbase : B<"dynamicbase", "Enable ASLR (default unless /fixed)", |
| 89 | defm fixed : B<"fixed", "Enable base relocations">; | 99 | "Disable ASLR (default when /fixed)">; |
| 90 | defm highentropyva : B<"highentropyva", "Set HIGH_ENTROPY_VA bit">; | 100 | defm fixed : B<"fixed", "Disable base relocations", |
| 91 | defm largeaddressaware : B<"largeaddressaware", "Disable large addresses">; | 101 | "Enable base relocations (default)">; |
| 92 | defm nxcompat : B<"nxcompat", "Disable data execution provention">; | 102 | defm highentropyva : B<"highentropyva", |
| 93 | defm safeseh : B<"safeseh", "Produce an image with Safe Exception Handler">; | 103 | "Enable 64-bit ASLR (default on 64-bit)", |
| 94 | defm tsaware : B<"tsaware", "Create non-Terminal Server aware executable">; | 104 | "Disable 64-bit ASLR">; |
| 105 | defm largeaddressaware : B<"largeaddressaware", | ||
| 106 | "Enable large addresses (default on 64-bit)", | ||
| 107 | "Disable large addresses (default on 32-bit)">; | ||
| 108 | defm nxcompat : B<"nxcompat", "Enable data execution prevention (default)", | ||
| 109 | "Disable data execution provention">; | ||
| 110 | defm safeseh : B<"safeseh", | ||
| 111 | "Produce an image with Safe Exception Handler (only for x86)", | ||
| 112 | "Don't produce an image with Safe Exception Handler">; | ||
| 113 | defm tsaware : B<"tsaware", | ||
| 114 | "Create Terminal Server aware executable (default)", | ||
| 115 | "Create non-Terminal Server aware executable">; | ||
| 95 | 116 | ||
| 96 | def help : F<"help">; | 117 | def help : F<"help">; |
| 97 | def help_q : Flag<["/?", "-?"], "">, Alias<help>; | 118 | def help_q : Flag<["/?", "-?"], "">, Alias<help>; |
| 98 | 119 | ||
| 99 | // LLD extensions | 120 | // LLD extensions |
| 100 | def nopdb : F<"nopdb">, HelpText<"Disable PDB generation for DWARF users">; | 121 | def debug_ghash : F<"debug:ghash">; |
| 101 | def nosymtab : F<"nosymtab">; | 122 | def debug_dwarf : F<"debug:dwarf">; |
| 123 | def export_all_symbols : F<"export-all-symbols">; | ||
| 124 | def lldmingw : F<"lldmingw">; | ||
| 102 | def msvclto : F<"msvclto">; | 125 | def msvclto : F<"msvclto">; |
| 126 | def output_def : Joined<["/", "-"], "output-def:">; | ||
| 127 | def rsp_quoting : Joined<["--"], "rsp-quoting=">, | ||
| 128 | HelpText<"Quoting style for response files, 'windows' (default) or 'posix'">; | ||
| 129 | def dash_dash_version : Flag<["--"], "version">, | ||
| 130 | HelpText<"Print version information">; | ||
| 103 | 131 | ||
| 104 | // Flags for debugging | 132 | // Flags for debugging |
| 105 | def lldmap : F<"lldmap">; | 133 | def lldmap : F<"lldmap">; |
| ... | @@ -128,12 +156,10 @@ def fastfail : F<"fastfail">; | ... | @@ -128,12 +156,10 @@ def fastfail : F<"fastfail">; |
| 128 | def delay : QF<"delay">; | 156 | def delay : QF<"delay">; |
| 129 | def errorreport : QF<"errorreport">; | 157 | def errorreport : QF<"errorreport">; |
| 130 | def idlout : QF<"idlout">; | 158 | def idlout : QF<"idlout">; |
| 131 | def ignore : QF<"ignore">; | ||
| 132 | def maxilksize : QF<"maxilksize">; | 159 | def maxilksize : QF<"maxilksize">; |
| 160 | def natvis : QF<"natvis">; | ||
| 133 | def pdbaltpath : QF<"pdbaltpath">; | 161 | def pdbaltpath : QF<"pdbaltpath">; |
| 134 | def tlbid : QF<"tlbid">; | 162 | def tlbid : QF<"tlbid">; |
| 135 | def tlbout : QF<"tlbout">; | 163 | def tlbout : QF<"tlbout">; |
| 136 | def verbose_all : QF<"verbose">; | 164 | def verbose_all : QF<"verbose">; |
| 137 | def guardsym : QF<"guardsym">; | 165 | def guardsym : QF<"guardsym">; |
| 138 | |||
| 139 | defm wx : QB<"wx">; |
deps/lld/COFF/PDB.cpp+439-114| ... | @@ -10,37 +10,44 @@ | ... | @@ -10,37 +10,44 @@ |
| 10 | #include "PDB.h" | 10 | #include "PDB.h" |
| 11 | #include "Chunks.h" | 11 | #include "Chunks.h" |
| 12 | #include "Config.h" | 12 | #include "Config.h" |
| 13 | #include "Error.h" | 13 | #include "Driver.h" |
| 14 | #include "SymbolTable.h" | 14 | #include "SymbolTable.h" |
| 15 | #include "Symbols.h" | 15 | #include "Symbols.h" |
| 16 | #include "Writer.h" | ||
| 17 | #include "lld/Common/ErrorHandler.h" | ||
| 16 | #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" | 18 | #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" |
| 17 | #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" | 19 | #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" |
| 20 | #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" | ||
| 18 | #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" | 21 | #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" |
| 22 | #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" | ||
| 23 | #include "llvm/DebugInfo/CodeView/RecordName.h" | ||
| 24 | #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" | ||
| 19 | #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" | 25 | #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" |
| 20 | #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" | 26 | #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" |
| 21 | #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" | 27 | #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" |
| 22 | #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" | 28 | #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" |
| 23 | #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" | 29 | #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" |
| 24 | #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" | ||
| 25 | #include "llvm/DebugInfo/MSF/MSFBuilder.h" | 30 | #include "llvm/DebugInfo/MSF/MSFBuilder.h" |
| 26 | #include "llvm/DebugInfo/MSF/MSFCommon.h" | 31 | #include "llvm/DebugInfo/MSF/MSFCommon.h" |
| 27 | #include "llvm/DebugInfo/PDB/GenericError.h" | 32 | #include "llvm/DebugInfo/PDB/GenericError.h" |
| 28 | #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" | 33 | #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" |
| 29 | #include "llvm/DebugInfo/PDB/Native/DbiStream.h" | 34 | #include "llvm/DebugInfo/PDB/Native/DbiStream.h" |
| 30 | #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" | 35 | #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" |
| 36 | #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" | ||
| 31 | #include "llvm/DebugInfo/PDB/Native/InfoStream.h" | 37 | #include "llvm/DebugInfo/PDB/Native/InfoStream.h" |
| 32 | #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" | 38 | #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" |
| 33 | #include "llvm/DebugInfo/PDB/Native/NativeSession.h" | 39 | #include "llvm/DebugInfo/PDB/Native/NativeSession.h" |
| 34 | #include "llvm/DebugInfo/PDB/Native/PDBFile.h" | 40 | #include "llvm/DebugInfo/PDB/Native/PDBFile.h" |
| 35 | #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" | 41 | #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" |
| 36 | #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" | 42 | #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" |
| 43 | #include "llvm/DebugInfo/PDB/Native/TpiHashing.h" | ||
| 37 | #include "llvm/DebugInfo/PDB/Native/TpiStream.h" | 44 | #include "llvm/DebugInfo/PDB/Native/TpiStream.h" |
| 38 | #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" | 45 | #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" |
| 39 | #include "llvm/DebugInfo/PDB/PDB.h" | 46 | #include "llvm/DebugInfo/PDB/PDB.h" |
| 40 | #include "llvm/Object/COFF.h" | 47 | #include "llvm/Object/COFF.h" |
| 41 | #include "llvm/Support/BinaryByteStream.h" | 48 | #include "llvm/Support/BinaryByteStream.h" |
| 42 | #include "llvm/Support/Endian.h" | 49 | #include "llvm/Support/Endian.h" |
| 43 | #include "llvm/Support/FileOutputBuffer.h" | 50 | #include "llvm/Support/JamCRC.h" |
| 44 | #include "llvm/Support/Path.h" | 51 | #include "llvm/Support/Path.h" |
| 45 | #include "llvm/Support/ScopedPrinter.h" | 52 | #include "llvm/Support/ScopedPrinter.h" |
| 46 | #include <memory> | 53 | #include <memory> |
| ... | @@ -67,16 +74,16 @@ class PDBLinker { | ... | @@ -67,16 +74,16 @@ class PDBLinker { |
| 67 | public: | 74 | public: |
| 68 | PDBLinker(SymbolTable *Symtab) | 75 | PDBLinker(SymbolTable *Symtab) |
| 69 | : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc), | 76 | : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc), |
| 70 | IDTable(Alloc) {} | 77 | IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) {} |
| 71 | 78 | ||
| 72 | /// Emit the basic PDB structure: initial streams, headers, etc. | 79 | /// Emit the basic PDB structure: initial streams, headers, etc. |
| 73 | void initialize(const llvm::codeview::DebugInfo *DI); | 80 | void initialize(const llvm::codeview::DebugInfo &BuildId); |
| 74 | 81 | ||
| 75 | /// Link CodeView from each object file in the symbol table into the PDB. | 82 | /// Link CodeView from each object file in the symbol table into the PDB. |
| 76 | void addObjectsToPDB(); | 83 | void addObjectsToPDB(); |
| 77 | 84 | ||
| 78 | /// Link CodeView from a single object file into the PDB. | 85 | /// Link CodeView from a single object file into the PDB. |
| 79 | void addObjectFile(ObjectFile *File); | 86 | void addObjFile(ObjFile *File); |
| 80 | 87 | ||
| 81 | /// Produce a mapping from the type and item indices used in the object | 88 | /// Produce a mapping from the type and item indices used in the object |
| 82 | /// file to those in the destination PDB. | 89 | /// file to those in the destination PDB. |
| ... | @@ -89,13 +96,17 @@ public: | ... | @@ -89,13 +96,17 @@ public: |
| 89 | /// If the object does not use a type server PDB (compiled with /Z7), we merge | 96 | /// If the object does not use a type server PDB (compiled with /Z7), we merge |
| 90 | /// all the type and item records from the .debug$S stream and fill in the | 97 | /// all the type and item records from the .debug$S stream and fill in the |
| 91 | /// caller-provided ObjectIndexMap. | 98 | /// caller-provided ObjectIndexMap. |
| 92 | const CVIndexMap &mergeDebugT(ObjectFile *File, CVIndexMap &ObjectIndexMap); | 99 | const CVIndexMap &mergeDebugT(ObjFile *File, CVIndexMap &ObjectIndexMap); |
| 93 | 100 | ||
| 94 | const CVIndexMap &maybeMergeTypeServerPDB(ObjectFile *File, | 101 | const CVIndexMap &maybeMergeTypeServerPDB(ObjFile *File, |
| 95 | TypeServer2Record &TS); | 102 | TypeServer2Record &TS); |
| 96 | 103 | ||
| 97 | /// Add the section map and section contributions to the PDB. | 104 | /// Add the section map and section contributions to the PDB. |
| 98 | void addSections(ArrayRef<uint8_t> SectionTable); | 105 | void addSections(ArrayRef<OutputSection *> OutputSections, |
| 106 | ArrayRef<uint8_t> SectionTable); | ||
| 107 | |||
| 108 | void addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule, | ||
| 109 | OutputSection *OS, Chunk *C); | ||
| 99 | 110 | ||
| 100 | /// Write the PDB to disk. | 111 | /// Write the PDB to disk. |
| 101 | void commit(); | 112 | void commit(); |
| ... | @@ -108,10 +119,16 @@ private: | ... | @@ -108,10 +119,16 @@ private: |
| 108 | pdb::PDBFileBuilder Builder; | 119 | pdb::PDBFileBuilder Builder; |
| 109 | 120 | ||
| 110 | /// Type records that will go into the PDB TPI stream. | 121 | /// Type records that will go into the PDB TPI stream. |
| 111 | TypeTableBuilder TypeTable; | 122 | MergingTypeTableBuilder TypeTable; |
| 112 | 123 | ||
| 113 | /// Item records that will go into the PDB IPI stream. | 124 | /// Item records that will go into the PDB IPI stream. |
| 114 | TypeTableBuilder IDTable; | 125 | MergingTypeTableBuilder IDTable; |
| 126 | |||
| 127 | /// Type records that will go into the PDB TPI stream (for /DEBUG:GHASH) | ||
| 128 | GlobalTypeTableBuilder GlobalTypeTable; | ||
| 129 | |||
| 130 | /// Item records that will go into the PDB IPI stream (for /DEBUG:GHASH) | ||
| 131 | GlobalTypeTableBuilder GlobalIDTable; | ||
| 115 | 132 | ||
| 116 | /// PDBs use a single global string table for filenames in the file checksum | 133 | /// PDBs use a single global string table for filenames in the file checksum |
| 117 | /// table. | 134 | /// table. |
| ... | @@ -126,15 +143,7 @@ private: | ... | @@ -126,15 +143,7 @@ private: |
| 126 | }; | 143 | }; |
| 127 | } | 144 | } |
| 128 | 145 | ||
| 129 | // Returns a list of all SectionChunks. | 146 | static SectionChunk *findByName(ArrayRef<SectionChunk *> Sections, |
| 130 | static void addSectionContribs(SymbolTable *Symtab, | ||
| 131 | pdb::DbiStreamBuilder &DbiBuilder) { | ||
| 132 | for (Chunk *C : Symtab->getChunks()) | ||
| 133 | if (auto *SC = dyn_cast<SectionChunk>(C)) | ||
| 134 | DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header); | ||
| 135 | } | ||
| 136 | |||
| 137 | static SectionChunk *findByName(std::vector<SectionChunk *> &Sections, | ||
| 138 | StringRef Name) { | 147 | StringRef Name) { |
| 139 | for (SectionChunk *C : Sections) | 148 | for (SectionChunk *C : Sections) |
| 140 | if (C->getSectionName() == Name) | 149 | if (C->getSectionName() == Name) |
| ... | @@ -152,21 +161,58 @@ static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> Data, | ... | @@ -152,21 +161,58 @@ static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> Data, |
| 152 | return Data.slice(4); | 161 | return Data.slice(4); |
| 153 | } | 162 | } |
| 154 | 163 | ||
| 155 | static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) { | 164 | static ArrayRef<uint8_t> getDebugSection(ObjFile *File, StringRef SecName) { |
| 156 | if (SectionChunk *Sec = findByName(File->getDebugChunks(), SecName)) | 165 | if (SectionChunk *Sec = findByName(File->getDebugChunks(), SecName)) |
| 157 | return consumeDebugMagic(Sec->getContents(), SecName); | 166 | return consumeDebugMagic(Sec->getContents(), SecName); |
| 158 | return {}; | 167 | return {}; |
| 159 | } | 168 | } |
| 160 | 169 | ||
| 170 | // A COFF .debug$H section is currently a clang extension. This function checks | ||
| 171 | // if a .debug$H section is in a format that we expect / understand, so that we | ||
| 172 | // can ignore any sections which are coincidentally also named .debug$H but do | ||
| 173 | // not contain a format we recognize. | ||
| 174 | static bool canUseDebugH(ArrayRef<uint8_t> DebugH) { | ||
| 175 | if (DebugH.size() < sizeof(object::debug_h_header)) | ||
| 176 | return false; | ||
| 177 | auto *Header = | ||
| 178 | reinterpret_cast<const object::debug_h_header *>(DebugH.data()); | ||
| 179 | DebugH = DebugH.drop_front(sizeof(object::debug_h_header)); | ||
| 180 | return Header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC && | ||
| 181 | Header->Version == 0 && | ||
| 182 | Header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1) && | ||
| 183 | (DebugH.size() % 20 == 0); | ||
| 184 | } | ||
| 185 | |||
| 186 | static Optional<ArrayRef<uint8_t>> getDebugH(ObjFile *File) { | ||
| 187 | SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$H"); | ||
| 188 | if (!Sec) | ||
| 189 | return llvm::None; | ||
| 190 | ArrayRef<uint8_t> Contents = Sec->getContents(); | ||
| 191 | if (!canUseDebugH(Contents)) | ||
| 192 | return None; | ||
| 193 | return Contents; | ||
| 194 | } | ||
| 195 | |||
| 196 | static ArrayRef<GloballyHashedType> | ||
| 197 | getHashesFromDebugH(ArrayRef<uint8_t> DebugH) { | ||
| 198 | assert(canUseDebugH(DebugH)); | ||
| 199 | |||
| 200 | DebugH = DebugH.drop_front(sizeof(object::debug_h_header)); | ||
| 201 | uint32_t Count = DebugH.size() / sizeof(GloballyHashedType); | ||
| 202 | return {reinterpret_cast<const GloballyHashedType *>(DebugH.data()), Count}; | ||
| 203 | } | ||
| 204 | |||
| 161 | static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, | 205 | static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, |
| 162 | TypeTableBuilder &TypeTable) { | 206 | TypeCollection &TypeTable) { |
| 163 | // Start the TPI or IPI stream header. | 207 | // Start the TPI or IPI stream header. |
| 164 | TpiBuilder.setVersionHeader(pdb::PdbTpiV80); | 208 | TpiBuilder.setVersionHeader(pdb::PdbTpiV80); |
| 165 | 209 | ||
| 166 | // Flatten the in memory type table. | 210 | // Flatten the in memory type table and hash each type. |
| 167 | TypeTable.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) { | 211 | TypeTable.ForEachRecord([&](TypeIndex TI, const CVType &Type) { |
| 168 | // FIXME: Hash types. | 212 | auto Hash = pdb::hashTypeRecord(Type); |
| 169 | TpiBuilder.addTypeRecord(Rec, None); | 213 | if (auto E = Hash.takeError()) |
| 214 | fatal("type hashing error"); | ||
| 215 | TpiBuilder.addTypeRecord(Type.RecordData, *Hash); | ||
| 170 | }); | 216 | }); |
| 171 | } | 217 | } |
| 172 | 218 | ||
| ... | @@ -180,11 +226,11 @@ maybeReadTypeServerRecord(CVTypeArray &Types) { | ... | @@ -180,11 +226,11 @@ maybeReadTypeServerRecord(CVTypeArray &Types) { |
| 180 | return None; | 226 | return None; |
| 181 | TypeServer2Record TS; | 227 | TypeServer2Record TS; |
| 182 | if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS)) | 228 | if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS)) |
| 183 | fatal(EC, "error reading type server record"); | 229 | fatal("error reading type server record: " + toString(std::move(EC))); |
| 184 | return std::move(TS); | 230 | return std::move(TS); |
| 185 | } | 231 | } |
| 186 | 232 | ||
| 187 | const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File, | 233 | const CVIndexMap &PDBLinker::mergeDebugT(ObjFile *File, |
| 188 | CVIndexMap &ObjectIndexMap) { | 234 | CVIndexMap &ObjectIndexMap) { |
| 189 | ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); | 235 | ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); |
| 190 | if (Data.empty()) | 236 | if (Data.empty()) |
| ... | @@ -194,7 +240,7 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File, | ... | @@ -194,7 +240,7 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File, |
| 194 | CVTypeArray Types; | 240 | CVTypeArray Types; |
| 195 | BinaryStreamReader Reader(Stream); | 241 | BinaryStreamReader Reader(Stream); |
| 196 | if (auto EC = Reader.readArray(Types, Reader.getLength())) | 242 | if (auto EC = Reader.readArray(Types, Reader.getLength())) |
| 197 | fatal(EC, "Reader::readArray failed"); | 243 | fatal("Reader::readArray failed: " + toString(std::move(EC))); |
| 198 | 244 | ||
| 199 | // Look through type servers. If we've already seen this type server, don't | 245 | // Look through type servers. If we've already seen this type server, don't |
| 200 | // merge any type information. | 246 | // merge any type information. |
| ... | @@ -203,17 +249,41 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File, | ... | @@ -203,17 +249,41 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File, |
| 203 | 249 | ||
| 204 | // This is a /Z7 object. Fill in the temporary, caller-provided | 250 | // This is a /Z7 object. Fill in the temporary, caller-provided |
| 205 | // ObjectIndexMap. | 251 | // ObjectIndexMap. |
| 206 | if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, | 252 | if (Config->DebugGHashes) { |
| 207 | ObjectIndexMap.TPIMap, Types)) | 253 | ArrayRef<GloballyHashedType> Hashes; |
| 208 | fatal(Err, "codeview::mergeTypeAndIdRecords failed"); | 254 | std::vector<GloballyHashedType> OwnedHashes; |
| 255 | if (Optional<ArrayRef<uint8_t>> DebugH = getDebugH(File)) | ||
| 256 | Hashes = getHashesFromDebugH(*DebugH); | ||
| 257 | else { | ||
| 258 | OwnedHashes = GloballyHashedType::hashTypes(Types); | ||
| 259 | Hashes = OwnedHashes; | ||
| 260 | } | ||
| 261 | |||
| 262 | if (auto Err = mergeTypeAndIdRecords(GlobalIDTable, GlobalTypeTable, | ||
| 263 | ObjectIndexMap.TPIMap, Types, Hashes)) | ||
| 264 | fatal("codeview::mergeTypeAndIdRecords failed: " + | ||
| 265 | toString(std::move(Err))); | ||
| 266 | } else { | ||
| 267 | if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, | ||
| 268 | ObjectIndexMap.TPIMap, Types)) | ||
| 269 | fatal("codeview::mergeTypeAndIdRecords failed: " + | ||
| 270 | toString(std::move(Err))); | ||
| 271 | } | ||
| 209 | return ObjectIndexMap; | 272 | return ObjectIndexMap; |
| 210 | } | 273 | } |
| 211 | 274 | ||
| 212 | static Expected<std::unique_ptr<pdb::NativeSession>> | 275 | static Expected<std::unique_ptr<pdb::NativeSession>> |
| 213 | tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) { | 276 | tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) { |
| 277 | ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile( | ||
| 278 | TSPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false); | ||
| 279 | if (!MBOrErr) | ||
| 280 | return errorCodeToError(MBOrErr.getError()); | ||
| 281 | |||
| 214 | std::unique_ptr<pdb::IPDBSession> ThisSession; | 282 | std::unique_ptr<pdb::IPDBSession> ThisSession; |
| 215 | if (auto EC = | 283 | if (auto EC = pdb::NativeSession::createFromPdb( |
| 216 | pdb::loadDataForPDB(pdb::PDB_ReaderType::Native, TSPath, ThisSession)) | 284 | MemoryBuffer::getMemBuffer(Driver->takeBuffer(std::move(*MBOrErr)), |
| 285 | /*RequiresNullTerminator=*/false), | ||
| 286 | ThisSession)) | ||
| 217 | return std::move(EC); | 287 | return std::move(EC); |
| 218 | 288 | ||
| 219 | std::unique_ptr<pdb::NativeSession> NS( | 289 | std::unique_ptr<pdb::NativeSession> NS( |
| ... | @@ -234,7 +304,7 @@ tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) { | ... | @@ -234,7 +304,7 @@ tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) { |
| 234 | return std::move(NS); | 304 | return std::move(NS); |
| 235 | } | 305 | } |
| 236 | 306 | ||
| 237 | const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjectFile *File, | 307 | const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, |
| 238 | TypeServer2Record &TS) { | 308 | TypeServer2Record &TS) { |
| 239 | // First, check if we already loaded a PDB with this GUID. Return the type | 309 | // First, check if we already loaded a PDB with this GUID. Return the type |
| 240 | // index mapping if we have it. | 310 | // index mapping if we have it. |
| ... | @@ -260,23 +330,46 @@ const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjectFile *File, | ... | @@ -260,23 +330,46 @@ const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjectFile *File, |
| 260 | ExpectedSession = tryToLoadPDB(TS.getGuid(), Path); | 330 | ExpectedSession = tryToLoadPDB(TS.getGuid(), Path); |
| 261 | } | 331 | } |
| 262 | if (auto E = ExpectedSession.takeError()) | 332 | if (auto E = ExpectedSession.takeError()) |
| 263 | fatal(E, "Type server PDB was not found"); | 333 | fatal("Type server PDB was not found: " + toString(std::move(E))); |
| 264 | 334 | ||
| 265 | // Merge TPI first, because the IPI stream will reference type indices. | ||
| 266 | auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream(); | 335 | auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream(); |
| 267 | if (auto E = ExpectedTpi.takeError()) | 336 | if (auto E = ExpectedTpi.takeError()) |
| 268 | fatal(E, "Type server does not have TPI stream"); | 337 | fatal("Type server does not have TPI stream: " + toString(std::move(E))); |
| 269 | if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap, | ||
| 270 | ExpectedTpi->typeArray())) | ||
| 271 | fatal(Err, "codeview::mergeTypeRecords failed"); | ||
| 272 | |||
| 273 | // Merge IPI. | ||
| 274 | auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream(); | 338 | auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream(); |
| 275 | if (auto E = ExpectedIpi.takeError()) | 339 | if (auto E = ExpectedIpi.takeError()) |
| 276 | fatal(E, "Type server does not have TPI stream"); | 340 | fatal("Type server does not have TPI stream: " + toString(std::move(E))); |
| 277 | if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap, | 341 | |
| 278 | ExpectedIpi->typeArray())) | 342 | if (Config->DebugGHashes) { |
| 279 | fatal(Err, "codeview::mergeIdRecords failed"); | 343 | // PDBs do not actually store global hashes, so when merging a type server |
| 344 | // PDB we have to synthesize global hashes. To do this, we first synthesize | ||
| 345 | // global hashes for the TPI stream, since it is independent, then we | ||
| 346 | // synthesize hashes for the IPI stream, using the hashes for the TPI stream | ||
| 347 | // as inputs. | ||
| 348 | auto TpiHashes = GloballyHashedType::hashTypes(ExpectedTpi->typeArray()); | ||
| 349 | auto IpiHashes = | ||
| 350 | GloballyHashedType::hashIds(ExpectedIpi->typeArray(), TpiHashes); | ||
| 351 | |||
| 352 | // Merge TPI first, because the IPI stream will reference type indices. | ||
| 353 | if (auto Err = mergeTypeRecords(GlobalTypeTable, IndexMap.TPIMap, | ||
| 354 | ExpectedTpi->typeArray(), TpiHashes)) | ||
| 355 | fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err))); | ||
| 356 | |||
| 357 | // Merge IPI. | ||
| 358 | if (auto Err = | ||
| 359 | mergeIdRecords(GlobalIDTable, IndexMap.TPIMap, IndexMap.IPIMap, | ||
| 360 | ExpectedIpi->typeArray(), IpiHashes)) | ||
| 361 | fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err))); | ||
| 362 | } else { | ||
| 363 | // Merge TPI first, because the IPI stream will reference type indices. | ||
| 364 | if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap, | ||
| 365 | ExpectedTpi->typeArray())) | ||
| 366 | fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err))); | ||
| 367 | |||
| 368 | // Merge IPI. | ||
| 369 | if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap, | ||
| 370 | ExpectedIpi->typeArray())) | ||
| 371 | fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err))); | ||
| 372 | } | ||
| 280 | 373 | ||
| 281 | return IndexMap; | 374 | return IndexMap; |
| 282 | } | 375 | } |
| ... | @@ -290,7 +383,7 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) { | ... | @@ -290,7 +383,7 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) { |
| 290 | return true; | 383 | return true; |
| 291 | } | 384 | } |
| 292 | 385 | ||
| 293 | static void remapTypesInSymbolRecord(ObjectFile *File, | 386 | static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind, |
| 294 | MutableArrayRef<uint8_t> Contents, | 387 | MutableArrayRef<uint8_t> Contents, |
| 295 | const CVIndexMap &IndexMap, | 388 | const CVIndexMap &IndexMap, |
| 296 | ArrayRef<TiReference> TypeRefs) { | 389 | ArrayRef<TiReference> TypeRefs) { |
| ... | @@ -301,27 +394,73 @@ static void remapTypesInSymbolRecord(ObjectFile *File, | ... | @@ -301,27 +394,73 @@ static void remapTypesInSymbolRecord(ObjectFile *File, |
| 301 | 394 | ||
| 302 | // This can be an item index or a type index. Choose the appropriate map. | 395 | // This can be an item index or a type index. Choose the appropriate map. |
| 303 | ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap; | 396 | ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap; |
| 304 | if (Ref.Kind == TiRefKind::IndexRef && IndexMap.IsTypeServerMap) | 397 | bool IsItemIndex = Ref.Kind == TiRefKind::IndexRef; |
| 398 | if (IsItemIndex && IndexMap.IsTypeServerMap) | ||
| 305 | TypeOrItemMap = IndexMap.IPIMap; | 399 | TypeOrItemMap = IndexMap.IPIMap; |
| 306 | 400 | ||
| 307 | MutableArrayRef<TypeIndex> TIs( | 401 | MutableArrayRef<TypeIndex> TIs( |
| 308 | reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count); | 402 | reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count); |
| 309 | for (TypeIndex &TI : TIs) { | 403 | for (TypeIndex &TI : TIs) { |
| 310 | if (!remapTypeIndex(TI, TypeOrItemMap)) { | 404 | if (!remapTypeIndex(TI, TypeOrItemMap)) { |
| 405 | log("ignoring symbol record of kind 0x" + utohexstr(SymKind) + " in " + | ||
| 406 | File->getName() + " with bad " + (IsItemIndex ? "item" : "type") + | ||
| 407 | " index 0x" + utohexstr(TI.getIndex())); | ||
| 311 | TI = TypeIndex(SimpleTypeKind::NotTranslated); | 408 | TI = TypeIndex(SimpleTypeKind::NotTranslated); |
| 312 | log("ignoring symbol record in " + File->getName() + | ||
| 313 | " with bad type index 0x" + utohexstr(TI.getIndex())); | ||
| 314 | continue; | 409 | continue; |
| 315 | } | 410 | } |
| 316 | } | 411 | } |
| 317 | } | 412 | } |
| 318 | } | 413 | } |
| 319 | 414 | ||
| 320 | /// MSVC translates S_PROC_ID_END to S_END. | 415 | static SymbolKind symbolKind(ArrayRef<uint8_t> RecordData) { |
| 321 | uint16_t canonicalizeSymbolKind(SymbolKind Kind) { | 416 | const RecordPrefix *Prefix = |
| 322 | if (Kind == SymbolKind::S_PROC_ID_END) | 417 | reinterpret_cast<const RecordPrefix *>(RecordData.data()); |
| 323 | return SymbolKind::S_END; | 418 | return static_cast<SymbolKind>(uint16_t(Prefix->RecordKind)); |
| 324 | return Kind; | 419 | } |
| 420 | |||
| 421 | /// MSVC translates S_PROC_ID_END to S_END, and S_[LG]PROC32_ID to S_[LG]PROC32 | ||
| 422 | static void translateIdSymbols(MutableArrayRef<uint8_t> &RecordData, | ||
| 423 | TypeCollection &IDTable) { | ||
| 424 | RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(RecordData.data()); | ||
| 425 | |||
| 426 | SymbolKind Kind = symbolKind(RecordData); | ||
| 427 | |||
| 428 | if (Kind == SymbolKind::S_PROC_ID_END) { | ||
| 429 | Prefix->RecordKind = SymbolKind::S_END; | ||
| 430 | return; | ||
| 431 | } | ||
| 432 | |||
| 433 | // In an object file, GPROC32_ID has an embedded reference which refers to the | ||
| 434 | // single object file type index namespace. This has already been translated | ||
| 435 | // to the PDB file's ID stream index space, but we need to convert this to a | ||
| 436 | // symbol that refers to the type stream index space. So we remap again from | ||
| 437 | // ID index space to type index space. | ||
| 438 | if (Kind == SymbolKind::S_GPROC32_ID || Kind == SymbolKind::S_LPROC32_ID) { | ||
| 439 | SmallVector<TiReference, 1> Refs; | ||
| 440 | auto Content = RecordData.drop_front(sizeof(RecordPrefix)); | ||
| 441 | CVSymbol Sym(Kind, RecordData); | ||
| 442 | discoverTypeIndicesInSymbol(Sym, Refs); | ||
| 443 | assert(Refs.size() == 1); | ||
| 444 | assert(Refs.front().Count == 1); | ||
| 445 | |||
| 446 | TypeIndex *TI = | ||
| 447 | reinterpret_cast<TypeIndex *>(Content.data() + Refs[0].Offset); | ||
| 448 | // `TI` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in | ||
| 449 | // the IPI stream, whose `FunctionType` member refers to the TPI stream. | ||
| 450 | // Note that LF_FUNC_ID and LF_MEMFUNC_ID have the same record layout, and | ||
| 451 | // in both cases we just need the second type index. | ||
| 452 | if (!TI->isSimple() && !TI->isNoneType()) { | ||
| 453 | CVType FuncIdData = IDTable.getType(*TI); | ||
| 454 | SmallVector<TypeIndex, 2> Indices; | ||
| 455 | discoverTypeIndices(FuncIdData, Indices); | ||
| 456 | assert(Indices.size() == 2); | ||
| 457 | *TI = Indices[1]; | ||
| 458 | } | ||
| 459 | |||
| 460 | Kind = (Kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32 | ||
| 461 | : SymbolKind::S_LPROC32; | ||
| 462 | Prefix->RecordKind = uint16_t(Kind); | ||
| 463 | } | ||
| 325 | } | 464 | } |
| 326 | 465 | ||
| 327 | /// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned. | 466 | /// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned. |
| ... | @@ -339,10 +478,8 @@ static MutableArrayRef<uint8_t> copySymbolForPdb(const CVSymbol &Sym, | ... | @@ -339,10 +478,8 @@ static MutableArrayRef<uint8_t> copySymbolForPdb(const CVSymbol &Sym, |
| 339 | memset(NewData.data() + Sym.length(), 0, Size - Sym.length()); | 478 | memset(NewData.data() + Sym.length(), 0, Size - Sym.length()); |
| 340 | 479 | ||
| 341 | // Update the record prefix length. It should point to the beginning of the | 480 | // Update the record prefix length. It should point to the beginning of the |
| 342 | // next record. MSVC does some canonicalization of the record kind, so we do | 481 | // next record. |
| 343 | // that as well. | ||
| 344 | auto *Prefix = reinterpret_cast<RecordPrefix *>(Mem); | 482 | auto *Prefix = reinterpret_cast<RecordPrefix *>(Mem); |
| 345 | Prefix->RecordKind = canonicalizeSymbolKind(Sym.kind()); | ||
| 346 | Prefix->RecordLen = Size - 2; | 483 | Prefix->RecordLen = Size - 2; |
| 347 | return NewData; | 484 | return NewData; |
| 348 | } | 485 | } |
| ... | @@ -402,7 +539,7 @@ static void scopeStackOpen(SmallVectorImpl<SymbolScope> &Stack, | ... | @@ -402,7 +539,7 @@ static void scopeStackOpen(SmallVectorImpl<SymbolScope> &Stack, |
| 402 | } | 539 | } |
| 403 | 540 | ||
| 404 | static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack, | 541 | static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack, |
| 405 | uint32_t CurOffset, ObjectFile *File) { | 542 | uint32_t CurOffset, ObjFile *File) { |
| 406 | if (Stack.empty()) { | 543 | if (Stack.empty()) { |
| 407 | warn("symbol scopes are not balanced in " + File->getName()); | 544 | warn("symbol scopes are not balanced in " + File->getName()); |
| 408 | return; | 545 | return; |
| ... | @@ -411,8 +548,86 @@ static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack, | ... | @@ -411,8 +548,86 @@ static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack, |
| 411 | S.OpeningRecord->PtrEnd = CurOffset; | 548 | S.OpeningRecord->PtrEnd = CurOffset; |
| 412 | } | 549 | } |
| 413 | 550 | ||
| 414 | static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, | 551 | static bool symbolGoesInModuleStream(const CVSymbol &Sym) { |
| 552 | switch (Sym.kind()) { | ||
| 553 | case SymbolKind::S_GDATA32: | ||
| 554 | case SymbolKind::S_CONSTANT: | ||
| 555 | case SymbolKind::S_UDT: | ||
| 556 | // We really should not be seeing S_PROCREF and S_LPROCREF in the first place | ||
| 557 | // since they are synthesized by the linker in response to S_GPROC32 and | ||
| 558 | // S_LPROC32, but if we do see them, don't put them in the module stream I | ||
| 559 | // guess. | ||
| 560 | case SymbolKind::S_PROCREF: | ||
| 561 | case SymbolKind::S_LPROCREF: | ||
| 562 | return false; | ||
| 563 | // S_GDATA32 does not go in the module stream, but S_LDATA32 does. | ||
| 564 | case SymbolKind::S_LDATA32: | ||
| 565 | default: | ||
| 566 | return true; | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | static bool symbolGoesInGlobalsStream(const CVSymbol &Sym) { | ||
| 571 | switch (Sym.kind()) { | ||
| 572 | case SymbolKind::S_CONSTANT: | ||
| 573 | case SymbolKind::S_GDATA32: | ||
| 574 | // S_LDATA32 goes in both the module stream and the globals stream. | ||
| 575 | case SymbolKind::S_LDATA32: | ||
| 576 | case SymbolKind::S_GPROC32: | ||
| 577 | case SymbolKind::S_LPROC32: | ||
| 578 | // We really should not be seeing S_PROCREF and S_LPROCREF in the first place | ||
| 579 | // since they are synthesized by the linker in response to S_GPROC32 and | ||
| 580 | // S_LPROC32, but if we do see them, copy them straight through. | ||
| 581 | case SymbolKind::S_PROCREF: | ||
| 582 | case SymbolKind::S_LPROCREF: | ||
| 583 | return true; | ||
| 584 | // FIXME: For now, we drop all S_UDT symbols (i.e. they don't go in the | ||
| 585 | // globals stream or the modules stream). These have special handling which | ||
| 586 | // needs more investigation before we can get right, but by putting them all | ||
| 587 | // into the globals stream WinDbg fails to display local variables of class | ||
| 588 | // types saying that it cannot find the type Foo *. So as a stopgap just to | ||
| 589 | // keep things working, we drop them. | ||
| 590 | case SymbolKind::S_UDT: | ||
| 591 | default: | ||
| 592 | return false; | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, ObjFile &File, | ||
| 597 | const CVSymbol &Sym) { | ||
| 598 | switch (Sym.kind()) { | ||
| 599 | case SymbolKind::S_CONSTANT: | ||
| 600 | case SymbolKind::S_UDT: | ||
| 601 | case SymbolKind::S_GDATA32: | ||
| 602 | case SymbolKind::S_LDATA32: | ||
| 603 | case SymbolKind::S_PROCREF: | ||
| 604 | case SymbolKind::S_LPROCREF: | ||
| 605 | Builder.addGlobalSymbol(Sym); | ||
| 606 | break; | ||
| 607 | case SymbolKind::S_GPROC32: | ||
| 608 | case SymbolKind::S_LPROC32: { | ||
| 609 | SymbolRecordKind K = SymbolRecordKind::ProcRefSym; | ||
| 610 | if (Sym.kind() == SymbolKind::S_LPROC32) | ||
| 611 | K = SymbolRecordKind::LocalProcRef; | ||
| 612 | ProcRefSym PS(K); | ||
| 613 | PS.Module = static_cast<uint16_t>(File.ModuleDBI->getModuleIndex()); | ||
| 614 | // For some reason, MSVC seems to add one to this value. | ||
| 615 | ++PS.Module; | ||
| 616 | PS.Name = getSymbolName(Sym); | ||
| 617 | PS.SumName = 0; | ||
| 618 | PS.SymOffset = File.ModuleDBI->getNextSymbolOffset(); | ||
| 619 | Builder.addGlobalSymbol(PS); | ||
| 620 | break; | ||
| 621 | } | ||
| 622 | default: | ||
| 623 | llvm_unreachable("Invalid symbol kind!"); | ||
| 624 | } | ||
| 625 | } | ||
| 626 | |||
| 627 | static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjFile *File, | ||
| 628 | pdb::GSIStreamBuilder &GsiBuilder, | ||
| 415 | const CVIndexMap &IndexMap, | 629 | const CVIndexMap &IndexMap, |
| 630 | TypeCollection &IDTable, | ||
| 416 | BinaryStreamRef SymData) { | 631 | BinaryStreamRef SymData) { |
| 417 | // FIXME: Improve error recovery by warning and skipping records when | 632 | // FIXME: Improve error recovery by warning and skipping records when |
| 418 | // possible. | 633 | // possible. |
| ... | @@ -420,11 +635,11 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, | ... | @@ -420,11 +635,11 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, |
| 420 | BinaryStreamReader Reader(SymData); | 635 | BinaryStreamReader Reader(SymData); |
| 421 | ExitOnErr(Reader.readArray(Syms, Reader.getLength())); | 636 | ExitOnErr(Reader.readArray(Syms, Reader.getLength())); |
| 422 | SmallVector<SymbolScope, 4> Scopes; | 637 | SmallVector<SymbolScope, 4> Scopes; |
| 423 | for (const CVSymbol &Sym : Syms) { | 638 | for (CVSymbol Sym : Syms) { |
| 424 | // Discover type index references in the record. Skip it if we don't know | 639 | // Discover type index references in the record. Skip it if we don't know |
| 425 | // where they are. | 640 | // where they are. |
| 426 | SmallVector<TiReference, 32> TypeRefs; | 641 | SmallVector<TiReference, 32> TypeRefs; |
| 427 | if (!discoverTypeIndices(Sym, TypeRefs)) { | 642 | if (!discoverTypeIndicesInSymbol(Sym, TypeRefs)) { |
| 428 | log("ignoring unknown symbol record with kind 0x" + utohexstr(Sym.kind())); | 643 | log("ignoring unknown symbol record with kind 0x" + utohexstr(Sym.kind())); |
| 429 | continue; | 644 | continue; |
| 430 | } | 645 | } |
| ... | @@ -435,17 +650,30 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, | ... | @@ -435,17 +650,30 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, |
| 435 | // Re-map all the type index references. | 650 | // Re-map all the type index references. |
| 436 | MutableArrayRef<uint8_t> Contents = | 651 | MutableArrayRef<uint8_t> Contents = |
| 437 | NewData.drop_front(sizeof(RecordPrefix)); | 652 | NewData.drop_front(sizeof(RecordPrefix)); |
| 438 | remapTypesInSymbolRecord(File, Contents, IndexMap, TypeRefs); | 653 | remapTypesInSymbolRecord(File, Sym.kind(), Contents, IndexMap, TypeRefs); |
| 654 | |||
| 655 | // An object file may have S_xxx_ID symbols, but these get converted to | ||
| 656 | // "real" symbols in a PDB. | ||
| 657 | translateIdSymbols(NewData, IDTable); | ||
| 658 | |||
| 659 | SymbolKind NewKind = symbolKind(NewData); | ||
| 439 | 660 | ||
| 440 | // Fill in "Parent" and "End" fields by maintaining a stack of scopes. | 661 | // Fill in "Parent" and "End" fields by maintaining a stack of scopes. |
| 441 | CVSymbol NewSym(Sym.kind(), NewData); | 662 | CVSymbol NewSym(NewKind, NewData); |
| 442 | if (symbolOpensScope(Sym.kind())) | 663 | if (symbolOpensScope(NewKind)) |
| 443 | scopeStackOpen(Scopes, File->ModuleDBI->getNextSymbolOffset(), NewSym); | 664 | scopeStackOpen(Scopes, File->ModuleDBI->getNextSymbolOffset(), NewSym); |
| 444 | else if (symbolEndsScope(Sym.kind())) | 665 | else if (symbolEndsScope(NewKind)) |
| 445 | scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File); | 666 | scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File); |
| 446 | 667 | ||
| 668 | // Add the symbol to the globals stream if necessary. Do this before adding | ||
| 669 | // the symbol to the module since we may need to get the next symbol offset, | ||
| 670 | // and writing to the module's symbol stream will update that offset. | ||
| 671 | if (symbolGoesInGlobalsStream(NewSym)) | ||
| 672 | addGlobalSymbol(GsiBuilder, *File, NewSym); | ||
| 673 | |||
| 447 | // Add the symbol to the module. | 674 | // Add the symbol to the module. |
| 448 | File->ModuleDBI->addSymbol(NewSym); | 675 | if (symbolGoesInModuleStream(NewSym)) |
| 676 | File->ModuleDBI->addSymbol(NewSym); | ||
| 449 | } | 677 | } |
| 450 | } | 678 | } |
| 451 | 679 | ||
| ... | @@ -460,7 +688,7 @@ static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc, | ... | @@ -460,7 +688,7 @@ static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc, |
| 460 | ".debug$S"); | 688 | ".debug$S"); |
| 461 | } | 689 | } |
| 462 | 690 | ||
| 463 | void PDBLinker::addObjectFile(ObjectFile *File) { | 691 | void PDBLinker::addObjFile(ObjFile *File) { |
| 464 | // Add a module descriptor for every object file. We need to put an absolute | 692 | // Add a module descriptor for every object file. We need to put an absolute |
| 465 | // path to the object into the PDB. If this is a plain object, we make its | 693 | // path to the object into the PDB. If this is a plain object, we make its |
| 466 | // path absolute. If it's an object in an archive, we make the archive path | 694 | // path absolute. If it's an object in an archive, we make the archive path |
| ... | @@ -511,7 +739,13 @@ void PDBLinker::addObjectFile(ObjectFile *File) { | ... | @@ -511,7 +739,13 @@ void PDBLinker::addObjectFile(ObjectFile *File) { |
| 511 | File->ModuleDBI->addDebugSubsection(SS); | 739 | File->ModuleDBI->addDebugSubsection(SS); |
| 512 | break; | 740 | break; |
| 513 | case DebugSubsectionKind::Symbols: | 741 | case DebugSubsectionKind::Symbols: |
| 514 | mergeSymbolRecords(Alloc, File, IndexMap, SS.getRecordData()); | 742 | if (Config->DebugGHashes) { |
| 743 | mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap, | ||
| 744 | GlobalIDTable, SS.getRecordData()); | ||
| 745 | } else { | ||
| 746 | mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap, | ||
| 747 | IDTable, SS.getRecordData()); | ||
| 748 | } | ||
| 515 | break; | 749 | break; |
| 516 | default: | 750 | default: |
| 517 | // FIXME: Process the rest of the subsections. | 751 | // FIXME: Process the rest of the subsections. |
| ... | @@ -539,45 +773,88 @@ void PDBLinker::addObjectFile(ObjectFile *File) { | ... | @@ -539,45 +773,88 @@ void PDBLinker::addObjectFile(ObjectFile *File) { |
| 539 | } | 773 | } |
| 540 | } | 774 | } |
| 541 | 775 | ||
| 776 | static PublicSym32 createPublic(Defined *Def) { | ||
| 777 | PublicSym32 Pub(SymbolKind::S_PUB32); | ||
| 778 | Pub.Name = Def->getName(); | ||
| 779 | if (auto *D = dyn_cast<DefinedCOFF>(Def)) { | ||
| 780 | if (D->getCOFFSymbol().isFunctionDefinition()) | ||
| 781 | Pub.Flags = PublicSymFlags::Function; | ||
| 782 | } else if (isa<DefinedImportThunk>(Def)) { | ||
| 783 | Pub.Flags = PublicSymFlags::Function; | ||
| 784 | } | ||
| 785 | |||
| 786 | OutputSection *OS = Def->getChunk()->getOutputSection(); | ||
| 787 | assert(OS && "all publics should be in final image"); | ||
| 788 | Pub.Offset = Def->getRVA() - OS->getRVA(); | ||
| 789 | Pub.Segment = OS->SectionIndex; | ||
| 790 | return Pub; | ||
| 791 | } | ||
| 792 | |||
| 542 | // Add all object files to the PDB. Merge .debug$T sections into IpiData and | 793 | // Add all object files to the PDB. Merge .debug$T sections into IpiData and |
| 543 | // TpiData. | 794 | // TpiData. |
| 544 | void PDBLinker::addObjectsToPDB() { | 795 | void PDBLinker::addObjectsToPDB() { |
| 545 | for (ObjectFile *File : Symtab->ObjectFiles) | 796 | for (ObjFile *File : ObjFile::Instances) |
| 546 | addObjectFile(File); | 797 | addObjFile(File); |
| 547 | 798 | ||
| 548 | Builder.getStringTableBuilder().setStrings(PDBStrTab); | 799 | Builder.getStringTableBuilder().setStrings(PDBStrTab); |
| 549 | 800 | ||
| 550 | // Construct TPI stream contents. | 801 | // Construct TPI and IPI stream contents. |
| 551 | addTypeInfo(Builder.getTpiBuilder(), TypeTable); | 802 | if (Config->DebugGHashes) { |
| 552 | 803 | addTypeInfo(Builder.getTpiBuilder(), GlobalTypeTable); | |
| 553 | // Construct IPI stream contents. | 804 | addTypeInfo(Builder.getIpiBuilder(), GlobalIDTable); |
| 554 | addTypeInfo(Builder.getIpiBuilder(), IDTable); | 805 | } else { |
| 806 | addTypeInfo(Builder.getTpiBuilder(), TypeTable); | ||
| 807 | addTypeInfo(Builder.getIpiBuilder(), IDTable); | ||
| 808 | } | ||
| 555 | 809 | ||
| 556 | // Add public and symbol records stream. | 810 | // Compute the public and global symbols. |
| 811 | auto &GsiBuilder = Builder.getGsiBuilder(); | ||
| 812 | std::vector<PublicSym32> Publics; | ||
| 813 | Symtab->forEachSymbol([&Publics](Symbol *S) { | ||
| 814 | // Only emit defined, live symbols that have a chunk. | ||
| 815 | auto *Def = dyn_cast<Defined>(S); | ||
| 816 | if (Def && Def->isLive() && Def->getChunk()) | ||
| 817 | Publics.push_back(createPublic(Def)); | ||
| 818 | }); | ||
| 557 | 819 | ||
| 558 | // For now we don't actually write any thing useful to the publics stream, but | 820 | if (!Publics.empty()) { |
| 559 | // the act of "getting" it also creates it lazily so that we write an empty | 821 | // Sort the public symbols and add them to the stream. |
| 560 | // stream. | 822 | std::sort(Publics.begin(), Publics.end(), |
| 561 | (void)Builder.getPublicsBuilder(); | 823 | [](const PublicSym32 &L, const PublicSym32 &R) { |
| 824 | return L.Name < R.Name; | ||
| 825 | }); | ||
| 826 | for (const PublicSym32 &Pub : Publics) | ||
| 827 | GsiBuilder.addPublicSymbol(Pub); | ||
| 828 | } | ||
| 562 | } | 829 | } |
| 563 | 830 | ||
| 564 | static void addLinkerModuleSymbols(StringRef Path, | 831 | static void addCommonLinkerModuleSymbols(StringRef Path, |
| 565 | pdb::DbiModuleDescriptorBuilder &Mod, | 832 | pdb::DbiModuleDescriptorBuilder &Mod, |
| 566 | BumpPtrAllocator &Allocator) { | 833 | BumpPtrAllocator &Allocator) { |
| 567 | codeview::SymbolSerializer Serializer(Allocator, CodeViewContainer::Pdb); | 834 | ObjNameSym ONS(SymbolRecordKind::ObjNameSym); |
| 568 | codeview::ObjNameSym ONS(SymbolRecordKind::ObjNameSym); | 835 | Compile3Sym CS(SymbolRecordKind::Compile3Sym); |
| 569 | codeview::Compile3Sym CS(SymbolRecordKind::Compile3Sym); | 836 | EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); |
| 570 | codeview::EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); | ||
| 571 | 837 | ||
| 572 | ONS.Name = "* Linker *"; | 838 | ONS.Name = "* Linker *"; |
| 573 | ONS.Signature = 0; | 839 | ONS.Signature = 0; |
| 574 | 840 | ||
| 575 | CS.Machine = Config->is64() ? CPUType::X64 : CPUType::Intel80386; | 841 | CS.Machine = Config->is64() ? CPUType::X64 : CPUType::Intel80386; |
| 842 | // Interestingly, if we set the string to 0.0.0.0, then when trying to view | ||
| 843 | // local variables WinDbg emits an error that private symbols are not present. | ||
| 844 | // By setting this to a valid MSVC linker version string, local variables are | ||
| 845 | // displayed properly. As such, even though it is not representative of | ||
| 846 | // LLVM's version information, we need this for compatibility. | ||
| 576 | CS.Flags = CompileSym3Flags::None; | 847 | CS.Flags = CompileSym3Flags::None; |
| 577 | CS.VersionBackendBuild = 0; | 848 | CS.VersionBackendBuild = 25019; |
| 578 | CS.VersionBackendMajor = 0; | 849 | CS.VersionBackendMajor = 14; |
| 579 | CS.VersionBackendMinor = 0; | 850 | CS.VersionBackendMinor = 10; |
| 580 | CS.VersionBackendQFE = 0; | 851 | CS.VersionBackendQFE = 0; |
| 852 | |||
| 853 | // MSVC also sets the frontend to 0.0.0.0 since this is specifically for the | ||
| 854 | // linker module (which is by definition a backend), so we don't need to do | ||
| 855 | // anything here. Also, it seems we can use "LLVM Linker" for the linker name | ||
| 856 | // without any problems. Only the backend version has to be hardcoded to a | ||
| 857 | // magic number. | ||
| 581 | CS.VersionFrontendBuild = 0; | 858 | CS.VersionFrontendBuild = 0; |
| 582 | CS.VersionFrontendMajor = 0; | 859 | CS.VersionFrontendMajor = 0; |
| 583 | CS.VersionFrontendMinor = 0; | 860 | CS.VersionFrontendMinor = 0; |
| ... | @@ -592,7 +869,9 @@ static void addLinkerModuleSymbols(StringRef Path, | ... | @@ -592,7 +869,9 @@ static void addLinkerModuleSymbols(StringRef Path, |
| 592 | sys::fs::current_path(cwd); | 869 | sys::fs::current_path(cwd); |
| 593 | EBS.Fields.push_back(cwd); | 870 | EBS.Fields.push_back(cwd); |
| 594 | EBS.Fields.push_back("exe"); | 871 | EBS.Fields.push_back("exe"); |
| 595 | EBS.Fields.push_back(Config->Argv[0]); | 872 | SmallString<64> exe = Config->Argv[0]; |
| 873 | llvm::sys::fs::make_absolute(exe); | ||
| 874 | EBS.Fields.push_back(exe); | ||
| 596 | EBS.Fields.push_back("pdb"); | 875 | EBS.Fields.push_back("pdb"); |
| 597 | EBS.Fields.push_back(Path); | 876 | EBS.Fields.push_back(Path); |
| 598 | EBS.Fields.push_back("cmd"); | 877 | EBS.Fields.push_back("cmd"); |
| ... | @@ -605,17 +884,33 @@ static void addLinkerModuleSymbols(StringRef Path, | ... | @@ -605,17 +884,33 @@ static void addLinkerModuleSymbols(StringRef Path, |
| 605 | EBS, Allocator, CodeViewContainer::Pdb)); | 884 | EBS, Allocator, CodeViewContainer::Pdb)); |
| 606 | } | 885 | } |
| 607 | 886 | ||
| 887 | static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod, | ||
| 888 | OutputSection &OS, | ||
| 889 | BumpPtrAllocator &Allocator) { | ||
| 890 | SectionSym Sym(SymbolRecordKind::SectionSym); | ||
| 891 | Sym.Alignment = 12; // 2^12 = 4KB | ||
| 892 | Sym.Characteristics = OS.getCharacteristics(); | ||
| 893 | Sym.Length = OS.getVirtualSize(); | ||
| 894 | Sym.Name = OS.getName(); | ||
| 895 | Sym.Rva = OS.getRVA(); | ||
| 896 | Sym.SectionNumber = OS.SectionIndex; | ||
| 897 | Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( | ||
| 898 | Sym, Allocator, CodeViewContainer::Pdb)); | ||
| 899 | } | ||
| 900 | |||
| 608 | // Creates a PDB file. | 901 | // Creates a PDB file. |
| 609 | void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable, | 902 | void coff::createPDB(SymbolTable *Symtab, |
| 610 | const llvm::codeview::DebugInfo *DI) { | 903 | ArrayRef<OutputSection *> OutputSections, |
| 904 | ArrayRef<uint8_t> SectionTable, | ||
| 905 | const llvm::codeview::DebugInfo &BuildId) { | ||
| 611 | PDBLinker PDB(Symtab); | 906 | PDBLinker PDB(Symtab); |
| 612 | PDB.initialize(DI); | 907 | PDB.initialize(BuildId); |
| 613 | PDB.addObjectsToPDB(); | 908 | PDB.addObjectsToPDB(); |
| 614 | PDB.addSections(SectionTable); | 909 | PDB.addSections(OutputSections, SectionTable); |
| 615 | PDB.commit(); | 910 | PDB.commit(); |
| 616 | } | 911 | } |
| 617 | 912 | ||
| 618 | void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) { | 913 | void PDBLinker::initialize(const llvm::codeview::DebugInfo &BuildId) { |
| 619 | ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize | 914 | ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize |
| 620 | 915 | ||
| 621 | // Create streams in MSF for predefined streams, namely | 916 | // Create streams in MSF for predefined streams, namely |
| ... | @@ -625,41 +920,71 @@ void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) { | ... | @@ -625,41 +920,71 @@ void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) { |
| 625 | 920 | ||
| 626 | // Add an Info stream. | 921 | // Add an Info stream. |
| 627 | auto &InfoBuilder = Builder.getInfoBuilder(); | 922 | auto &InfoBuilder = Builder.getInfoBuilder(); |
| 628 | InfoBuilder.setAge(DI ? DI->PDB70.Age : 0); | 923 | InfoBuilder.setAge(BuildId.PDB70.Age); |
| 629 | 924 | ||
| 630 | GUID uuid{}; | 925 | GUID uuid; |
| 631 | if (DI) | 926 | memcpy(&uuid, &BuildId.PDB70.Signature, sizeof(uuid)); |
| 632 | memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid)); | ||
| 633 | InfoBuilder.setGuid(uuid); | 927 | InfoBuilder.setGuid(uuid); |
| 634 | InfoBuilder.setSignature(time(nullptr)); | 928 | InfoBuilder.setSignature(time(nullptr)); |
| 635 | InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); | 929 | InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); |
| 636 | 930 | ||
| 637 | // Add an empty DBI stream. | 931 | // Add an empty DBI stream. |
| 638 | pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); | 932 | pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); |
| 933 | DbiBuilder.setAge(BuildId.PDB70.Age); | ||
| 639 | DbiBuilder.setVersionHeader(pdb::PdbDbiV70); | 934 | DbiBuilder.setVersionHeader(pdb::PdbDbiV70); |
| 640 | ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {})); | 935 | ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {})); |
| 641 | } | 936 | } |
| 642 | 937 | ||
| 643 | void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) { | 938 | void PDBLinker::addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule, |
| 644 | // Add Section Contributions. | 939 | OutputSection *OS, Chunk *C) { |
| 645 | pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); | 940 | pdb::SectionContrib SC; |
| 646 | addSectionContribs(Symtab, DbiBuilder); | 941 | memset(&SC, 0, sizeof(SC)); |
| 647 | 942 | SC.ISect = OS->SectionIndex; | |
| 648 | // Add Section Map stream. | 943 | SC.Off = C->getRVA() - OS->getRVA(); |
| 649 | ArrayRef<object::coff_section> Sections = { | 944 | SC.Size = C->getSize(); |
| 650 | (const object::coff_section *)SectionTable.data(), | 945 | if (auto *SecChunk = dyn_cast<SectionChunk>(C)) { |
| 651 | SectionTable.size() / sizeof(object::coff_section)}; | 946 | SC.Characteristics = SecChunk->Header->Characteristics; |
| 652 | SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections); | 947 | SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex(); |
| 653 | DbiBuilder.setSectionMap(SectionMap); | 948 | ArrayRef<uint8_t> Contents = SecChunk->getContents(); |
| 949 | JamCRC CRC(0); | ||
| 950 | ArrayRef<char> CharContents = makeArrayRef( | ||
| 951 | reinterpret_cast<const char *>(Contents.data()), Contents.size()); | ||
| 952 | CRC.update(CharContents); | ||
| 953 | SC.DataCrc = CRC.getCRC(); | ||
| 954 | } else { | ||
| 955 | SC.Characteristics = OS->getCharacteristics(); | ||
| 956 | // FIXME: When we start creating DBI for import libraries, use those here. | ||
| 957 | SC.Imod = LinkerModule.getModuleIndex(); | ||
| 958 | } | ||
| 959 | SC.RelocCrc = 0; // FIXME | ||
| 960 | Builder.getDbiBuilder().addSectionContrib(SC); | ||
| 961 | } | ||
| 654 | 962 | ||
| 963 | void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections, | ||
| 964 | ArrayRef<uint8_t> SectionTable) { | ||
| 655 | // It's not entirely clear what this is, but the * Linker * module uses it. | 965 | // It's not entirely clear what this is, but the * Linker * module uses it. |
| 966 | pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); | ||
| 656 | NativePath = Config->PDBPath; | 967 | NativePath = Config->PDBPath; |
| 657 | sys::fs::make_absolute(NativePath); | 968 | sys::fs::make_absolute(NativePath); |
| 658 | sys::path::native(NativePath, sys::path::Style::windows); | 969 | sys::path::native(NativePath, sys::path::Style::windows); |
| 659 | uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); | 970 | uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); |
| 660 | auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); | 971 | auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); |
| 661 | LinkerModule.setPdbFilePathNI(PdbFilePathNI); | 972 | LinkerModule.setPdbFilePathNI(PdbFilePathNI); |
| 662 | addLinkerModuleSymbols(NativePath, LinkerModule, Alloc); | 973 | addCommonLinkerModuleSymbols(NativePath, LinkerModule, Alloc); |
| 974 | |||
| 975 | // Add section contributions. They must be ordered by ascending RVA. | ||
| 976 | for (OutputSection *OS : OutputSections) { | ||
| 977 | addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc); | ||
| 978 | for (Chunk *C : OS->getChunks()) | ||
| 979 | addSectionContrib(LinkerModule, OS, C); | ||
| 980 | } | ||
| 981 | |||
| 982 | // Add Section Map stream. | ||
| 983 | ArrayRef<object::coff_section> Sections = { | ||
| 984 | (const object::coff_section *)SectionTable.data(), | ||
| 985 | SectionTable.size() / sizeof(object::coff_section)}; | ||
| 986 | SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections); | ||
| 987 | DbiBuilder.setSectionMap(SectionMap); | ||
| 663 | 988 | ||
| 664 | // Add COFF section header stream. | 989 | // Add COFF section header stream. |
| 665 | ExitOnErr( | 990 | ExitOnErr( |
deps/lld/COFF/PDB.h+5-2| ... | @@ -21,10 +21,13 @@ union DebugInfo; | ... | @@ -21,10 +21,13 @@ union DebugInfo; |
| 21 | 21 | ||
| 22 | namespace lld { | 22 | namespace lld { |
| 23 | namespace coff { | 23 | namespace coff { |
| 24 | class OutputSection; | ||
| 24 | class SymbolTable; | 25 | class SymbolTable; |
| 25 | 26 | ||
| 26 | void createPDB(SymbolTable *Symtab, llvm::ArrayRef<uint8_t> SectionTable, | 27 | void createPDB(SymbolTable *Symtab, |
| 27 | const llvm::codeview::DebugInfo *DI); | 28 | llvm::ArrayRef<OutputSection *> OutputSections, |
| 29 | llvm::ArrayRef<uint8_t> SectionTable, | ||
| 30 | const llvm::codeview::DebugInfo &BuildId); | ||
| 28 | } | 31 | } |
| 29 | } | 32 | } |
| 30 | 33 |
deps/lld/COFF/Strings.cpp+1-1| ... | @@ -20,7 +20,7 @@ using namespace lld; | ... | @@ -20,7 +20,7 @@ using namespace lld; |
| 20 | using namespace lld::coff; | 20 | using namespace lld::coff; |
| 21 | using namespace llvm; | 21 | using namespace llvm; |
| 22 | 22 | ||
| 23 | Optional<std::string> coff::demangle(StringRef S) { | 23 | Optional<std::string> coff::demangleMSVC(StringRef S) { |
| 24 | #if defined(_MSC_VER) | 24 | #if defined(_MSC_VER) |
| 25 | // UnDecorateSymbolName is not thread-safe, so we need a mutex. | 25 | // UnDecorateSymbolName is not thread-safe, so we need a mutex. |
| 26 | static std::mutex Mu; | 26 | static std::mutex Mu; |
deps/lld/COFF/Strings.h+1-1| ... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | ||
| 17 | namespace lld { | 17 | namespace lld { |
| 18 | namespace coff { | 18 | namespace coff { |
| 19 | llvm::Optional<std::string> demangle(llvm::StringRef S); | 19 | llvm::Optional<std::string> demangleMSVC(llvm::StringRef S); |
| 20 | } | 20 | } |
| 21 | } | 21 | } |
| 22 | 22 |
deps/lld/COFF/SymbolTable.cpp+148-128| ... | @@ -10,10 +10,10 @@ | ... | @@ -10,10 +10,10 @@ |
| 10 | #include "SymbolTable.h" | 10 | #include "SymbolTable.h" |
| 11 | #include "Config.h" | 11 | #include "Config.h" |
| 12 | #include "Driver.h" | 12 | #include "Driver.h" |
| 13 | #include "Error.h" | ||
| 14 | #include "LTO.h" | 13 | #include "LTO.h" |
| 15 | #include "Memory.h" | ||
| 16 | #include "Symbols.h" | 14 | #include "Symbols.h" |
| 15 | #include "lld/Common/ErrorHandler.h" | ||
| 16 | #include "lld/Common/Memory.h" | ||
| 17 | #include "llvm/IR/LLVMContext.h" | 17 | #include "llvm/IR/LLVMContext.h" |
| 18 | #include "llvm/Support/Debug.h" | 18 | #include "llvm/Support/Debug.h" |
| 19 | #include "llvm/Support/raw_ostream.h" | 19 | #include "llvm/Support/raw_ostream.h" |
| ... | @@ -24,36 +24,6 @@ using namespace llvm; | ... | @@ -24,36 +24,6 @@ using namespace llvm; |
| 24 | namespace lld { | 24 | namespace lld { |
| 25 | namespace coff { | 25 | namespace coff { |
| 26 | 26 | ||
| 27 | enum SymbolPreference { | ||
| 28 | SP_EXISTING = -1, | ||
| 29 | SP_CONFLICT = 0, | ||
| 30 | SP_NEW = 1, | ||
| 31 | }; | ||
| 32 | |||
| 33 | /// Checks if an existing symbol S should be kept or replaced by a new symbol. | ||
| 34 | /// Returns SP_EXISTING when S should be kept, SP_NEW when the new symbol | ||
| 35 | /// should be kept, and SP_CONFLICT if no valid resolution exists. | ||
| 36 | static SymbolPreference compareDefined(Symbol *S, bool WasInserted, | ||
| 37 | bool NewIsCOMDAT) { | ||
| 38 | // If the symbol wasn't previously known, the new symbol wins by default. | ||
| 39 | if (WasInserted || !isa<Defined>(S->body())) | ||
| 40 | return SP_NEW; | ||
| 41 | |||
| 42 | // If the existing symbol is a DefinedRegular, both it and the new symbol | ||
| 43 | // must be comdats. In that case, we have no reason to prefer one symbol | ||
| 44 | // over the other, and we keep the existing one. If one of the symbols | ||
| 45 | // is not a comdat, we report a conflict. | ||
| 46 | if (auto *R = dyn_cast<DefinedRegular>(S->body())) { | ||
| 47 | if (NewIsCOMDAT && R->isCOMDAT()) | ||
| 48 | return SP_EXISTING; | ||
| 49 | else | ||
| 50 | return SP_CONFLICT; | ||
| 51 | } | ||
| 52 | |||
| 53 | // Existing symbol is not a DefinedRegular; new symbol wins. | ||
| 54 | return SP_NEW; | ||
| 55 | } | ||
| 56 | |||
| 57 | SymbolTable *Symtab; | 27 | SymbolTable *Symtab; |
| 58 | 28 | ||
| 59 | void SymbolTable::addFile(InputFile *File) { | 29 | void SymbolTable::addFile(InputFile *File) { |
| ... | @@ -68,12 +38,12 @@ void SymbolTable::addFile(InputFile *File) { | ... | @@ -68,12 +38,12 @@ void SymbolTable::addFile(InputFile *File) { |
| 68 | " conflicts with " + machineToStr(Config->Machine)); | 38 | " conflicts with " + machineToStr(Config->Machine)); |
| 69 | } | 39 | } |
| 70 | 40 | ||
| 71 | if (auto *F = dyn_cast<ObjectFile>(File)) { | 41 | if (auto *F = dyn_cast<ObjFile>(File)) { |
| 72 | ObjectFiles.push_back(F); | 42 | ObjFile::Instances.push_back(F); |
| 73 | } else if (auto *F = dyn_cast<BitcodeFile>(File)) { | 43 | } else if (auto *F = dyn_cast<BitcodeFile>(File)) { |
| 74 | BitcodeFiles.push_back(F); | 44 | BitcodeFile::Instances.push_back(F); |
| 75 | } else if (auto *F = dyn_cast<ImportFile>(File)) { | 45 | } else if (auto *F = dyn_cast<ImportFile>(File)) { |
| 76 | ImportFiles.push_back(F); | 46 | ImportFile::Instances.push_back(F); |
| 77 | } | 47 | } |
| 78 | 48 | ||
| 79 | StringRef S = File->getDirectives(); | 49 | StringRef S = File->getDirectives(); |
| ... | @@ -84,70 +54,95 @@ void SymbolTable::addFile(InputFile *File) { | ... | @@ -84,70 +54,95 @@ void SymbolTable::addFile(InputFile *File) { |
| 84 | Driver->parseDirectives(S); | 54 | Driver->parseDirectives(S); |
| 85 | } | 55 | } |
| 86 | 56 | ||
| 57 | static void errorOrWarn(const Twine &S) { | ||
| 58 | if (Config->Force) | ||
| 59 | warn(S); | ||
| 60 | else | ||
| 61 | error(S); | ||
| 62 | } | ||
| 63 | |||
| 87 | void SymbolTable::reportRemainingUndefines() { | 64 | void SymbolTable::reportRemainingUndefines() { |
| 88 | SmallPtrSet<SymbolBody *, 8> Undefs; | 65 | SmallPtrSet<Symbol *, 8> Undefs; |
| 89 | for (auto &I : Symtab) { | 66 | DenseMap<Symbol *, Symbol *> LocalImports; |
| 67 | |||
| 68 | for (auto &I : SymMap) { | ||
| 90 | Symbol *Sym = I.second; | 69 | Symbol *Sym = I.second; |
| 91 | auto *Undef = dyn_cast<Undefined>(Sym->body()); | 70 | auto *Undef = dyn_cast<Undefined>(Sym); |
| 92 | if (!Undef) | 71 | if (!Undef) |
| 93 | continue; | 72 | continue; |
| 94 | if (!Sym->IsUsedInRegularObj) | 73 | if (!Sym->IsUsedInRegularObj) |
| 95 | continue; | 74 | continue; |
| 75 | |||
| 96 | StringRef Name = Undef->getName(); | 76 | StringRef Name = Undef->getName(); |
| 77 | |||
| 97 | // A weak alias may have been resolved, so check for that. | 78 | // A weak alias may have been resolved, so check for that. |
| 98 | if (Defined *D = Undef->getWeakAlias()) { | 79 | if (Defined *D = Undef->getWeakAlias()) { |
| 99 | // We resolve weak aliases by replacing the alias's SymbolBody with the | 80 | // We want to replace Sym with D. However, we can't just blindly |
| 100 | // target's SymbolBody. This causes all SymbolBody pointers referring to | 81 | // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an |
| 101 | // the old symbol to instead refer to the new symbol. However, we can't | 82 | // internal symbol, and internal symbols are stored as "unparented" |
| 102 | // just blindly copy sizeof(Symbol::Body) bytes from D to Sym->Body | 83 | // Symbols. For that reason we need to check which type of symbol we |
| 103 | // because D may be an internal symbol, and internal symbols are stored as | 84 | // are dealing with and copy the correct number of bytes. |
| 104 | // "unparented" SymbolBodies. For that reason we need to check which type | ||
| 105 | // of symbol we are dealing with and copy the correct number of bytes. | ||
| 106 | if (isa<DefinedRegular>(D)) | 85 | if (isa<DefinedRegular>(D)) |
| 107 | memcpy(Sym->Body.buffer, D, sizeof(DefinedRegular)); | 86 | memcpy(Sym, D, sizeof(DefinedRegular)); |
| 108 | else if (isa<DefinedAbsolute>(D)) | 87 | else if (isa<DefinedAbsolute>(D)) |
| 109 | memcpy(Sym->Body.buffer, D, sizeof(DefinedAbsolute)); | 88 | memcpy(Sym, D, sizeof(DefinedAbsolute)); |
| 110 | else | 89 | else |
| 111 | // No other internal symbols are possible. | 90 | memcpy(Sym, D, sizeof(SymbolUnion)); |
| 112 | Sym->Body = D->symbol()->Body; | ||
| 113 | continue; | 91 | continue; |
| 114 | } | 92 | } |
| 93 | |||
| 115 | // If we can resolve a symbol by removing __imp_ prefix, do that. | 94 | // If we can resolve a symbol by removing __imp_ prefix, do that. |
| 116 | // This odd rule is for compatibility with MSVC linker. | 95 | // This odd rule is for compatibility with MSVC linker. |
| 117 | if (Name.startswith("__imp_")) { | 96 | if (Name.startswith("__imp_")) { |
| 118 | Symbol *Imp = find(Name.substr(strlen("__imp_"))); | 97 | Symbol *Imp = find(Name.substr(strlen("__imp_"))); |
| 119 | if (Imp && isa<Defined>(Imp->body())) { | 98 | if (Imp && isa<Defined>(Imp)) { |
| 120 | auto *D = cast<Defined>(Imp->body()); | 99 | auto *D = cast<Defined>(Imp); |
| 121 | replaceBody<DefinedLocalImport>(Sym, Name, D); | 100 | replaceSymbol<DefinedLocalImport>(Sym, Name, D); |
| 122 | LocalImportChunks.push_back( | 101 | LocalImportChunks.push_back(cast<DefinedLocalImport>(Sym)->getChunk()); |
| 123 | cast<DefinedLocalImport>(Sym->body())->getChunk()); | 102 | LocalImports[Sym] = D; |
| 124 | continue; | 103 | continue; |
| 125 | } | 104 | } |
| 126 | } | 105 | } |
| 106 | |||
| 127 | // Remaining undefined symbols are not fatal if /force is specified. | 107 | // Remaining undefined symbols are not fatal if /force is specified. |
| 128 | // They are replaced with dummy defined symbols. | 108 | // They are replaced with dummy defined symbols. |
| 129 | if (Config->Force) | 109 | if (Config->Force) |
| 130 | replaceBody<DefinedAbsolute>(Sym, Name, 0); | 110 | replaceSymbol<DefinedAbsolute>(Sym, Name, 0); |
| 131 | Undefs.insert(Sym->body()); | 111 | Undefs.insert(Sym); |
| 132 | } | 112 | } |
| 133 | if (Undefs.empty()) | 113 | |
| 114 | if (Undefs.empty() && LocalImports.empty()) | ||
| 134 | return; | 115 | return; |
| 135 | for (SymbolBody *B : Config->GCRoot) | 116 | |
| 117 | for (Symbol *B : Config->GCRoot) { | ||
| 136 | if (Undefs.count(B)) | 118 | if (Undefs.count(B)) |
| 137 | warn("<root>: undefined symbol: " + B->getName()); | 119 | errorOrWarn("<root>: undefined symbol: " + B->getName()); |
| 138 | for (ObjectFile *File : ObjectFiles) | 120 | if (Config->WarnLocallyDefinedImported) |
| 139 | for (SymbolBody *Sym : File->getSymbols()) | 121 | if (Symbol *Imp = LocalImports.lookup(B)) |
| 122 | warn("<root>: locally defined symbol imported: " + Imp->getName() + | ||
| 123 | " (defined in " + toString(Imp->getFile()) + ")"); | ||
| 124 | } | ||
| 125 | |||
| 126 | for (ObjFile *File : ObjFile::Instances) { | ||
| 127 | for (Symbol *Sym : File->getSymbols()) { | ||
| 128 | if (!Sym) | ||
| 129 | continue; | ||
| 140 | if (Undefs.count(Sym)) | 130 | if (Undefs.count(Sym)) |
| 141 | warn(toString(File) + ": undefined symbol: " + Sym->getName()); | 131 | errorOrWarn(toString(File) + ": undefined symbol: " + Sym->getName()); |
| 142 | if (!Config->Force) | 132 | if (Config->WarnLocallyDefinedImported) |
| 143 | fatal("link failed"); | 133 | if (Symbol *Imp = LocalImports.lookup(Sym)) |
| 134 | warn(toString(File) + ": locally defined symbol imported: " + | ||
| 135 | Imp->getName() + " (defined in " + toString(Imp->getFile()) + | ||
| 136 | ")"); | ||
| 137 | } | ||
| 138 | } | ||
| 144 | } | 139 | } |
| 145 | 140 | ||
| 146 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { | 141 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { |
| 147 | Symbol *&Sym = Symtab[CachedHashStringRef(Name)]; | 142 | Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; |
| 148 | if (Sym) | 143 | if (Sym) |
| 149 | return {Sym, false}; | 144 | return {Sym, false}; |
| 150 | Sym = make<Symbol>(); | 145 | Sym = (Symbol *)make<SymbolUnion>(); |
| 151 | Sym->IsUsedInRegularObj = false; | 146 | Sym->IsUsedInRegularObj = false; |
| 152 | Sym->PendingArchiveLoad = false; | 147 | Sym->PendingArchiveLoad = false; |
| 153 | return {Sym, true}; | 148 | return {Sym, true}; |
| ... | @@ -160,11 +155,11 @@ Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F, | ... | @@ -160,11 +155,11 @@ Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F, |
| 160 | std::tie(S, WasInserted) = insert(Name); | 155 | std::tie(S, WasInserted) = insert(Name); |
| 161 | if (!F || !isa<BitcodeFile>(F)) | 156 | if (!F || !isa<BitcodeFile>(F)) |
| 162 | S->IsUsedInRegularObj = true; | 157 | S->IsUsedInRegularObj = true; |
| 163 | if (WasInserted || (isa<Lazy>(S->body()) && IsWeakAlias)) { | 158 | if (WasInserted || (isa<Lazy>(S) && IsWeakAlias)) { |
| 164 | replaceBody<Undefined>(S, Name); | 159 | replaceSymbol<Undefined>(S, Name); |
| 165 | return S; | 160 | return S; |
| 166 | } | 161 | } |
| 167 | if (auto *L = dyn_cast<Lazy>(S->body())) { | 162 | if (auto *L = dyn_cast<Lazy>(S)) { |
| 168 | if (!S->PendingArchiveLoad) { | 163 | if (!S->PendingArchiveLoad) { |
| 169 | S->PendingArchiveLoad = true; | 164 | S->PendingArchiveLoad = true; |
| 170 | L->File->addMember(&L->Sym); | 165 | L->File->addMember(&L->Sym); |
| ... | @@ -179,10 +174,10 @@ void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) { | ... | @@ -179,10 +174,10 @@ void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) { |
| 179 | bool WasInserted; | 174 | bool WasInserted; |
| 180 | std::tie(S, WasInserted) = insert(Name); | 175 | std::tie(S, WasInserted) = insert(Name); |
| 181 | if (WasInserted) { | 176 | if (WasInserted) { |
| 182 | replaceBody<Lazy>(S, F, Sym); | 177 | replaceSymbol<Lazy>(S, F, Sym); |
| 183 | return; | 178 | return; |
| 184 | } | 179 | } |
| 185 | auto *U = dyn_cast<Undefined>(S->body()); | 180 | auto *U = dyn_cast<Undefined>(S); |
| 186 | if (!U || U->WeakAlias || S->PendingArchiveLoad) | 181 | if (!U || U->WeakAlias || S->PendingArchiveLoad) |
| 187 | return; | 182 | return; |
| 188 | S->PendingArchiveLoad = true; | 183 | S->PendingArchiveLoad = true; |
| ... | @@ -190,9 +185,8 @@ void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) { | ... | @@ -190,9 +185,8 @@ void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) { |
| 190 | } | 185 | } |
| 191 | 186 | ||
| 192 | void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) { | 187 | void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) { |
| 193 | error("duplicate symbol: " + toString(*Existing->body()) + " in " + | 188 | error("duplicate symbol: " + toString(*Existing) + " in " + |
| 194 | toString(Existing->body()->getFile()) + " and in " + | 189 | toString(Existing->getFile()) + " and in " + toString(NewFile)); |
| 195 | (NewFile ? toString(NewFile) : "(internal)")); | ||
| 196 | } | 190 | } |
| 197 | 191 | ||
| 198 | Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) { | 192 | Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) { |
| ... | @@ -200,9 +194,9 @@ Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) { | ... | @@ -200,9 +194,9 @@ Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) { |
| 200 | bool WasInserted; | 194 | bool WasInserted; |
| 201 | std::tie(S, WasInserted) = insert(N); | 195 | std::tie(S, WasInserted) = insert(N); |
| 202 | S->IsUsedInRegularObj = true; | 196 | S->IsUsedInRegularObj = true; |
| 203 | if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body())) | 197 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) |
| 204 | replaceBody<DefinedAbsolute>(S, N, Sym); | 198 | replaceSymbol<DefinedAbsolute>(S, N, Sym); |
| 205 | else if (!isa<DefinedCOFF>(S->body())) | 199 | else if (!isa<DefinedCOFF>(S)) |
| 206 | reportDuplicate(S, nullptr); | 200 | reportDuplicate(S, nullptr); |
| 207 | return S; | 201 | return S; |
| 208 | } | 202 | } |
| ... | @@ -212,9 +206,9 @@ Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) { | ... | @@ -212,9 +206,9 @@ Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) { |
| 212 | bool WasInserted; | 206 | bool WasInserted; |
| 213 | std::tie(S, WasInserted) = insert(N); | 207 | std::tie(S, WasInserted) = insert(N); |
| 214 | S->IsUsedInRegularObj = true; | 208 | S->IsUsedInRegularObj = true; |
| 215 | if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body())) | 209 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) |
| 216 | replaceBody<DefinedAbsolute>(S, N, VA); | 210 | replaceSymbol<DefinedAbsolute>(S, N, VA); |
| 217 | else if (!isa<DefinedCOFF>(S->body())) | 211 | else if (!isa<DefinedCOFF>(S)) |
| 218 | reportDuplicate(S, nullptr); | 212 | reportDuplicate(S, nullptr); |
| 219 | return S; | 213 | return S; |
| 220 | } | 214 | } |
| ... | @@ -224,14 +218,14 @@ Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) { | ... | @@ -224,14 +218,14 @@ Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) { |
| 224 | bool WasInserted; | 218 | bool WasInserted; |
| 225 | std::tie(S, WasInserted) = insert(N); | 219 | std::tie(S, WasInserted) = insert(N); |
| 226 | S->IsUsedInRegularObj = true; | 220 | S->IsUsedInRegularObj = true; |
| 227 | if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body())) | 221 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) |
| 228 | replaceBody<DefinedSynthetic>(S, N, C); | 222 | replaceSymbol<DefinedSynthetic>(S, N, C); |
| 229 | else if (!isa<DefinedCOFF>(S->body())) | 223 | else if (!isa<DefinedCOFF>(S)) |
| 230 | reportDuplicate(S, nullptr); | 224 | reportDuplicate(S, nullptr); |
| 231 | return S; | 225 | return S; |
| 232 | } | 226 | } |
| 233 | 227 | ||
| 234 | Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, bool IsCOMDAT, | 228 | Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, |
| 235 | const coff_symbol_generic *Sym, | 229 | const coff_symbol_generic *Sym, |
| 236 | SectionChunk *C) { | 230 | SectionChunk *C) { |
| 237 | Symbol *S; | 231 | Symbol *S; |
| ... | @@ -239,21 +233,32 @@ Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, bool IsCOMDAT, | ... | @@ -239,21 +233,32 @@ Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, bool IsCOMDAT, |
| 239 | std::tie(S, WasInserted) = insert(N); | 233 | std::tie(S, WasInserted) = insert(N); |
| 240 | if (!isa<BitcodeFile>(F)) | 234 | if (!isa<BitcodeFile>(F)) |
| 241 | S->IsUsedInRegularObj = true; | 235 | S->IsUsedInRegularObj = true; |
| 242 | SymbolPreference SP = compareDefined(S, WasInserted, IsCOMDAT); | 236 | if (WasInserted || !isa<DefinedRegular>(S)) |
| 243 | if (SP == SP_CONFLICT) { | 237 | replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ false, |
| 238 | /*IsExternal*/ true, Sym, C); | ||
| 239 | else | ||
| 244 | reportDuplicate(S, F); | 240 | reportDuplicate(S, F); |
| 245 | } else if (SP == SP_NEW) { | ||
| 246 | replaceBody<DefinedRegular>(S, F, N, IsCOMDAT, /*IsExternal*/ true, Sym, C); | ||
| 247 | } else if (SP == SP_EXISTING && IsCOMDAT && C) { | ||
| 248 | C->markDiscarded(); | ||
| 249 | // Discard associative chunks that we've parsed so far. No need to recurse | ||
| 250 | // because an associative section cannot have children. | ||
| 251 | for (SectionChunk *Child : C->children()) | ||
| 252 | Child->markDiscarded(); | ||
| 253 | } | ||
| 254 | return S; | 241 | return S; |
| 255 | } | 242 | } |
| 256 | 243 | ||
| 244 | std::pair<Symbol *, bool> | ||
| 245 | SymbolTable::addComdat(InputFile *F, StringRef N, | ||
| 246 | const coff_symbol_generic *Sym) { | ||
| 247 | Symbol *S; | ||
| 248 | bool WasInserted; | ||
| 249 | std::tie(S, WasInserted) = insert(N); | ||
| 250 | if (!isa<BitcodeFile>(F)) | ||
| 251 | S->IsUsedInRegularObj = true; | ||
| 252 | if (WasInserted || !isa<DefinedRegular>(S)) { | ||
| 253 | replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ true, | ||
| 254 | /*IsExternal*/ true, Sym, nullptr); | ||
| 255 | return {S, true}; | ||
| 256 | } | ||
| 257 | if (!cast<DefinedRegular>(S)->isCOMDAT()) | ||
| 258 | reportDuplicate(S, F); | ||
| 259 | return {S, false}; | ||
| 260 | } | ||
| 261 | |||
| 257 | Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size, | 262 | Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size, |
| 258 | const coff_symbol_generic *Sym, CommonChunk *C) { | 263 | const coff_symbol_generic *Sym, CommonChunk *C) { |
| 259 | Symbol *S; | 264 | Symbol *S; |
| ... | @@ -261,51 +266,56 @@ Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size, | ... | @@ -261,51 +266,56 @@ Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size, |
| 261 | std::tie(S, WasInserted) = insert(N); | 266 | std::tie(S, WasInserted) = insert(N); |
| 262 | if (!isa<BitcodeFile>(F)) | 267 | if (!isa<BitcodeFile>(F)) |
| 263 | S->IsUsedInRegularObj = true; | 268 | S->IsUsedInRegularObj = true; |
| 264 | if (WasInserted || !isa<DefinedCOFF>(S->body())) | 269 | if (WasInserted || !isa<DefinedCOFF>(S)) |
| 265 | replaceBody<DefinedCommon>(S, F, N, Size, Sym, C); | 270 | replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C); |
| 266 | else if (auto *DC = dyn_cast<DefinedCommon>(S->body())) | 271 | else if (auto *DC = dyn_cast<DefinedCommon>(S)) |
| 267 | if (Size > DC->getSize()) | 272 | if (Size > DC->getSize()) |
| 268 | replaceBody<DefinedCommon>(S, F, N, Size, Sym, C); | 273 | replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C); |
| 269 | return S; | 274 | return S; |
| 270 | } | 275 | } |
| 271 | 276 | ||
| 272 | Symbol *SymbolTable::addImportData(StringRef N, ImportFile *F) { | 277 | DefinedImportData *SymbolTable::addImportData(StringRef N, ImportFile *F) { |
| 273 | Symbol *S; | 278 | Symbol *S; |
| 274 | bool WasInserted; | 279 | bool WasInserted; |
| 275 | std::tie(S, WasInserted) = insert(N); | 280 | std::tie(S, WasInserted) = insert(N); |
| 276 | S->IsUsedInRegularObj = true; | 281 | S->IsUsedInRegularObj = true; |
| 277 | if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body())) | 282 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) { |
| 278 | replaceBody<DefinedImportData>(S, N, F); | 283 | replaceSymbol<DefinedImportData>(S, N, F); |
| 279 | else if (!isa<DefinedCOFF>(S->body())) | 284 | return cast<DefinedImportData>(S); |
| 280 | reportDuplicate(S, nullptr); | 285 | } |
| 281 | return S; | 286 | |
| 287 | reportDuplicate(S, F); | ||
| 288 | return nullptr; | ||
| 282 | } | 289 | } |
| 283 | 290 | ||
| 284 | Symbol *SymbolTable::addImportThunk(StringRef Name, DefinedImportData *ID, | 291 | DefinedImportThunk *SymbolTable::addImportThunk(StringRef Name, |
| 285 | uint16_t Machine) { | 292 | DefinedImportData *ID, |
| 293 | uint16_t Machine) { | ||
| 286 | Symbol *S; | 294 | Symbol *S; |
| 287 | bool WasInserted; | 295 | bool WasInserted; |
| 288 | std::tie(S, WasInserted) = insert(Name); | 296 | std::tie(S, WasInserted) = insert(Name); |
| 289 | S->IsUsedInRegularObj = true; | 297 | S->IsUsedInRegularObj = true; |
| 290 | if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body())) | 298 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) { |
| 291 | replaceBody<DefinedImportThunk>(S, Name, ID, Machine); | 299 | replaceSymbol<DefinedImportThunk>(S, Name, ID, Machine); |
| 292 | else if (!isa<DefinedCOFF>(S->body())) | 300 | return cast<DefinedImportThunk>(S); |
| 293 | reportDuplicate(S, nullptr); | 301 | } |
| 294 | return S; | 302 | |
| 303 | reportDuplicate(S, ID->File); | ||
| 304 | return nullptr; | ||
| 295 | } | 305 | } |
| 296 | 306 | ||
| 297 | std::vector<Chunk *> SymbolTable::getChunks() { | 307 | std::vector<Chunk *> SymbolTable::getChunks() { |
| 298 | std::vector<Chunk *> Res; | 308 | std::vector<Chunk *> Res; |
| 299 | for (ObjectFile *File : ObjectFiles) { | 309 | for (ObjFile *File : ObjFile::Instances) { |
| 300 | std::vector<Chunk *> &V = File->getChunks(); | 310 | ArrayRef<Chunk *> V = File->getChunks(); |
| 301 | Res.insert(Res.end(), V.begin(), V.end()); | 311 | Res.insert(Res.end(), V.begin(), V.end()); |
| 302 | } | 312 | } |
| 303 | return Res; | 313 | return Res; |
| 304 | } | 314 | } |
| 305 | 315 | ||
| 306 | Symbol *SymbolTable::find(StringRef Name) { | 316 | Symbol *SymbolTable::find(StringRef Name) { |
| 307 | auto It = Symtab.find(CachedHashStringRef(Name)); | 317 | auto It = SymMap.find(CachedHashStringRef(Name)); |
| 308 | if (It == Symtab.end()) | 318 | if (It == SymMap.end()) |
| 309 | return nullptr; | 319 | return nullptr; |
| 310 | return It->second; | 320 | return It->second; |
| 311 | } | 321 | } |
| ... | @@ -317,7 +327,7 @@ Symbol *SymbolTable::findUnderscore(StringRef Name) { | ... | @@ -317,7 +327,7 @@ Symbol *SymbolTable::findUnderscore(StringRef Name) { |
| 317 | } | 327 | } |
| 318 | 328 | ||
| 319 | StringRef SymbolTable::findByPrefix(StringRef Prefix) { | 329 | StringRef SymbolTable::findByPrefix(StringRef Prefix) { |
| 320 | for (auto Pair : Symtab) { | 330 | for (auto Pair : SymMap) { |
| 321 | StringRef Name = Pair.first.val(); | 331 | StringRef Name = Pair.first.val(); |
| 322 | if (Name.startswith(Prefix)) | 332 | if (Name.startswith(Prefix)) |
| 323 | return Name; | 333 | return Name; |
| ... | @@ -327,47 +337,57 @@ StringRef SymbolTable::findByPrefix(StringRef Prefix) { | ... | @@ -327,47 +337,57 @@ StringRef SymbolTable::findByPrefix(StringRef Prefix) { |
| 327 | 337 | ||
| 328 | StringRef SymbolTable::findMangle(StringRef Name) { | 338 | StringRef SymbolTable::findMangle(StringRef Name) { |
| 329 | if (Symbol *Sym = find(Name)) | 339 | if (Symbol *Sym = find(Name)) |
| 330 | if (!isa<Undefined>(Sym->body())) | 340 | if (!isa<Undefined>(Sym)) |
| 331 | return Name; | 341 | return Name; |
| 332 | if (Config->Machine != I386) | 342 | if (Config->Machine != I386) |
| 333 | return findByPrefix(("?" + Name + "@@Y").str()); | 343 | return findByPrefix(("?" + Name + "@@Y").str()); |
| 334 | if (!Name.startswith("_")) | 344 | if (!Name.startswith("_")) |
| 335 | return ""; | 345 | return ""; |
| 336 | // Search for x86 C function. | 346 | // Search for x86 stdcall function. |
| 337 | StringRef S = findByPrefix((Name + "@").str()); | 347 | StringRef S = findByPrefix((Name + "@").str()); |
| 348 | if (!S.empty()) | ||
| 349 | return S; | ||
| 350 | // Search for x86 fastcall function. | ||
| 351 | S = findByPrefix(("@" + Name.substr(1) + "@").str()); | ||
| 352 | if (!S.empty()) | ||
| 353 | return S; | ||
| 354 | // Search for x86 vectorcall function. | ||
| 355 | S = findByPrefix((Name.substr(1) + "@@").str()); | ||
| 338 | if (!S.empty()) | 356 | if (!S.empty()) |
| 339 | return S; | 357 | return S; |
| 340 | // Search for x86 C++ non-member function. | 358 | // Search for x86 C++ non-member function. |
| 341 | return findByPrefix(("?" + Name.substr(1) + "@@Y").str()); | 359 | return findByPrefix(("?" + Name.substr(1) + "@@Y").str()); |
| 342 | } | 360 | } |
| 343 | 361 | ||
| 344 | void SymbolTable::mangleMaybe(SymbolBody *B) { | 362 | void SymbolTable::mangleMaybe(Symbol *B) { |
| 345 | auto *U = dyn_cast<Undefined>(B); | 363 | auto *U = dyn_cast<Undefined>(B); |
| 346 | if (!U || U->WeakAlias) | 364 | if (!U || U->WeakAlias) |
| 347 | return; | 365 | return; |
| 348 | StringRef Alias = findMangle(U->getName()); | 366 | StringRef Alias = findMangle(U->getName()); |
| 349 | if (!Alias.empty()) | 367 | if (!Alias.empty()) { |
| 368 | log(U->getName() + " aliased to " + Alias); | ||
| 350 | U->WeakAlias = addUndefined(Alias); | 369 | U->WeakAlias = addUndefined(Alias); |
| 370 | } | ||
| 351 | } | 371 | } |
| 352 | 372 | ||
| 353 | SymbolBody *SymbolTable::addUndefined(StringRef Name) { | 373 | Symbol *SymbolTable::addUndefined(StringRef Name) { |
| 354 | return addUndefined(Name, nullptr, false)->body(); | 374 | return addUndefined(Name, nullptr, false); |
| 355 | } | 375 | } |
| 356 | 376 | ||
| 357 | std::vector<StringRef> SymbolTable::compileBitcodeFiles() { | 377 | std::vector<StringRef> SymbolTable::compileBitcodeFiles() { |
| 358 | LTO.reset(new BitcodeCompiler); | 378 | LTO.reset(new BitcodeCompiler); |
| 359 | for (BitcodeFile *F : BitcodeFiles) | 379 | for (BitcodeFile *F : BitcodeFile::Instances) |
| 360 | LTO->add(*F); | 380 | LTO->add(*F); |
| 361 | return LTO->compile(); | 381 | return LTO->compile(); |
| 362 | } | 382 | } |
| 363 | 383 | ||
| 364 | void SymbolTable::addCombinedLTOObjects() { | 384 | void SymbolTable::addCombinedLTOObjects() { |
| 365 | if (BitcodeFiles.empty()) | 385 | if (BitcodeFile::Instances.empty()) |
| 366 | return; | 386 | return; |
| 367 | for (StringRef Object : compileBitcodeFiles()) { | 387 | for (StringRef Object : compileBitcodeFiles()) { |
| 368 | auto *Obj = make<ObjectFile>(MemoryBufferRef(Object, "lto.tmp")); | 388 | auto *Obj = make<ObjFile>(MemoryBufferRef(Object, "lto.tmp")); |
| 369 | Obj->parse(); | 389 | Obj->parse(); |
| 370 | ObjectFiles.push_back(Obj); | 390 | ObjFile::Instances.push_back(Obj); |
| 371 | } | 391 | } |
| 372 | } | 392 | } |
| 373 | 393 |
deps/lld/COFF/SymbolTable.h+17-18| ... | @@ -31,8 +31,7 @@ class DefinedAbsolute; | ... | @@ -31,8 +31,7 @@ class DefinedAbsolute; |
| 31 | class DefinedRelative; | 31 | class DefinedRelative; |
| 32 | class Lazy; | 32 | class Lazy; |
| 33 | class SectionChunk; | 33 | class SectionChunk; |
| 34 | class SymbolBody; | 34 | class Symbol; |
| 35 | struct Symbol; | ||
| 36 | 35 | ||
| 37 | // SymbolTable is a bucket of all known symbols, including defined, | 36 | // SymbolTable is a bucket of all known symbols, including defined, |
| 38 | // undefined, or lazy symbols (the last one is symbols in archive | 37 | // undefined, or lazy symbols (the last one is symbols in archive |
| ... | @@ -66,7 +65,7 @@ public: | ... | @@ -66,7 +65,7 @@ public: |
| 66 | // mangled symbol. This function tries to find a mangled name | 65 | // mangled symbol. This function tries to find a mangled name |
| 67 | // for U from the symbol table, and if found, set the symbol as | 66 | // for U from the symbol table, and if found, set the symbol as |
| 68 | // a weak alias for U. | 67 | // a weak alias for U. |
| 69 | void mangleMaybe(SymbolBody *B); | 68 | void mangleMaybe(Symbol *B); |
| 70 | StringRef findMangle(StringRef Name); | 69 | StringRef findMangle(StringRef Name); |
| 71 | 70 | ||
| 72 | // Build a set of COFF objects representing the combined contents of | 71 | // Build a set of COFF objects representing the combined contents of |
| ... | @@ -75,15 +74,8 @@ public: | ... | @@ -75,15 +74,8 @@ public: |
| 75 | void addCombinedLTOObjects(); | 74 | void addCombinedLTOObjects(); |
| 76 | std::vector<StringRef> compileBitcodeFiles(); | 75 | std::vector<StringRef> compileBitcodeFiles(); |
| 77 | 76 | ||
| 78 | // The writer needs to handle DLL import libraries specially in | ||
| 79 | // order to create the import descriptor table. | ||
| 80 | std::vector<ImportFile *> ImportFiles; | ||
| 81 | |||
| 82 | // The writer needs to infer the machine type from the object files. | ||
| 83 | std::vector<ObjectFile *> ObjectFiles; | ||
| 84 | |||
| 85 | // Creates an Undefined symbol for a given name. | 77 | // Creates an Undefined symbol for a given name. |
| 86 | SymbolBody *addUndefined(StringRef Name); | 78 | Symbol *addUndefined(StringRef Name); |
| 87 | 79 | ||
| 88 | Symbol *addSynthetic(StringRef N, Chunk *C); | 80 | Symbol *addSynthetic(StringRef N, Chunk *C); |
| 89 | Symbol *addAbsolute(StringRef N, uint64_t VA); | 81 | Symbol *addAbsolute(StringRef N, uint64_t VA); |
| ... | @@ -91,28 +83,35 @@ public: | ... | @@ -91,28 +83,35 @@ public: |
| 91 | Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias); | 83 | Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias); |
| 92 | void addLazy(ArchiveFile *F, const Archive::Symbol Sym); | 84 | void addLazy(ArchiveFile *F, const Archive::Symbol Sym); |
| 93 | Symbol *addAbsolute(StringRef N, COFFSymbolRef S); | 85 | Symbol *addAbsolute(StringRef N, COFFSymbolRef S); |
| 94 | Symbol *addRegular(InputFile *F, StringRef N, bool IsCOMDAT, | 86 | Symbol *addRegular(InputFile *F, StringRef N, |
| 95 | const llvm::object::coff_symbol_generic *S = nullptr, | 87 | const llvm::object::coff_symbol_generic *S = nullptr, |
| 96 | SectionChunk *C = nullptr); | 88 | SectionChunk *C = nullptr); |
| 89 | std::pair<Symbol *, bool> | ||
| 90 | addComdat(InputFile *F, StringRef N, | ||
| 91 | const llvm::object::coff_symbol_generic *S = nullptr); | ||
| 97 | Symbol *addCommon(InputFile *F, StringRef N, uint64_t Size, | 92 | Symbol *addCommon(InputFile *F, StringRef N, uint64_t Size, |
| 98 | const llvm::object::coff_symbol_generic *S = nullptr, | 93 | const llvm::object::coff_symbol_generic *S = nullptr, |
| 99 | CommonChunk *C = nullptr); | 94 | CommonChunk *C = nullptr); |
| 100 | Symbol *addImportData(StringRef N, ImportFile *F); | 95 | DefinedImportData *addImportData(StringRef N, ImportFile *F); |
| 101 | Symbol *addImportThunk(StringRef Name, DefinedImportData *S, | 96 | DefinedImportThunk *addImportThunk(StringRef Name, DefinedImportData *S, |
| 102 | uint16_t Machine); | 97 | uint16_t Machine); |
| 103 | 98 | ||
| 104 | void reportDuplicate(Symbol *Existing, InputFile *NewFile); | 99 | void reportDuplicate(Symbol *Existing, InputFile *NewFile); |
| 105 | 100 | ||
| 106 | // A list of chunks which to be added to .rdata. | 101 | // A list of chunks which to be added to .rdata. |
| 107 | std::vector<Chunk *> LocalImportChunks; | 102 | std::vector<Chunk *> LocalImportChunks; |
| 108 | 103 | ||
| 104 | // Iterates symbols in non-determinstic hash table order. | ||
| 105 | template <typename T> void forEachSymbol(T Callback) { | ||
| 106 | for (auto &Pair : SymMap) | ||
| 107 | Callback(Pair.second); | ||
| 108 | } | ||
| 109 | |||
| 109 | private: | 110 | private: |
| 110 | std::pair<Symbol *, bool> insert(StringRef Name); | 111 | std::pair<Symbol *, bool> insert(StringRef Name); |
| 111 | StringRef findByPrefix(StringRef Prefix); | 112 | StringRef findByPrefix(StringRef Prefix); |
| 112 | 113 | ||
| 113 | llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> Symtab; | 114 | llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> SymMap; |
| 114 | |||
| 115 | std::vector<BitcodeFile *> BitcodeFiles; | ||
| 116 | std::unique_ptr<BitcodeCompiler> LTO; | 115 | std::unique_ptr<BitcodeCompiler> LTO; |
| 117 | }; | 116 | }; |
| 118 | 117 |
deps/lld/COFF/Symbols.cpp+20-10| ... | @@ -8,10 +8,10 @@ | ... | @@ -8,10 +8,10 @@ |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Symbols.h" | 10 | #include "Symbols.h" |
| 11 | #include "Error.h" | ||
| 12 | #include "InputFiles.h" | 11 | #include "InputFiles.h" |
| 13 | #include "Memory.h" | ||
| 14 | #include "Strings.h" | 12 | #include "Strings.h" |
| 13 | #include "lld/Common/ErrorHandler.h" | ||
| 14 | #include "lld/Common/Memory.h" | ||
| 15 | #include "llvm/ADT/STLExtras.h" | 15 | #include "llvm/ADT/STLExtras.h" |
| 16 | #include "llvm/Support/Debug.h" | 16 | #include "llvm/Support/Debug.h" |
| 17 | #include "llvm/Support/raw_ostream.h" | 17 | #include "llvm/Support/raw_ostream.h" |
| ... | @@ -20,8 +20,8 @@ using namespace llvm; | ... | @@ -20,8 +20,8 @@ using namespace llvm; |
| 20 | using namespace llvm::object; | 20 | using namespace llvm::object; |
| 21 | 21 | ||
| 22 | // Returns a symbol name for an error message. | 22 | // Returns a symbol name for an error message. |
| 23 | std::string lld::toString(coff::SymbolBody &B) { | 23 | std::string lld::toString(coff::Symbol &B) { |
| 24 | if (Optional<std::string> S = coff::demangle(B.getName())) | 24 | if (Optional<std::string> S = coff::demangleMSVC(B.getName())) |
| 25 | return ("\"" + *S + "\" (" + B.getName() + ")").str(); | 25 | return ("\"" + *S + "\" (" + B.getName() + ")").str(); |
| 26 | return B.getName(); | 26 | return B.getName(); |
| 27 | } | 27 | } |
| ... | @@ -29,7 +29,7 @@ std::string lld::toString(coff::SymbolBody &B) { | ... | @@ -29,7 +29,7 @@ std::string lld::toString(coff::SymbolBody &B) { |
| 29 | namespace lld { | 29 | namespace lld { |
| 30 | namespace coff { | 30 | namespace coff { |
| 31 | 31 | ||
| 32 | StringRef SymbolBody::getName() { | 32 | StringRef Symbol::getName() { |
| 33 | // COFF symbol names are read lazily for a performance reason. | 33 | // COFF symbol names are read lazily for a performance reason. |
| 34 | // Non-external symbol names are never used by the linker except for logging | 34 | // Non-external symbol names are never used by the linker except for logging |
| 35 | // or debugging. Their internal references are resolved not by name but by | 35 | // or debugging. Their internal references are resolved not by name but by |
| ... | @@ -39,12 +39,12 @@ StringRef SymbolBody::getName() { | ... | @@ -39,12 +39,12 @@ StringRef SymbolBody::getName() { |
| 39 | // is a waste of time. | 39 | // is a waste of time. |
| 40 | if (Name.empty()) { | 40 | if (Name.empty()) { |
| 41 | auto *D = cast<DefinedCOFF>(this); | 41 | auto *D = cast<DefinedCOFF>(this); |
| 42 | cast<ObjectFile>(D->File)->getCOFFObj()->getSymbolName(D->Sym, Name); | 42 | cast<ObjFile>(D->File)->getCOFFObj()->getSymbolName(D->Sym, Name); |
| 43 | } | 43 | } |
| 44 | return Name; | 44 | return Name; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | InputFile *SymbolBody::getFile() { | 47 | InputFile *Symbol::getFile() { |
| 48 | if (auto *Sym = dyn_cast<DefinedCOFF>(this)) | 48 | if (auto *Sym = dyn_cast<DefinedCOFF>(this)) |
| 49 | return Sym->File; | 49 | return Sym->File; |
| 50 | if (auto *Sym = dyn_cast<Lazy>(this)) | 50 | if (auto *Sym = dyn_cast<Lazy>(this)) |
| ... | @@ -52,9 +52,19 @@ InputFile *SymbolBody::getFile() { | ... | @@ -52,9 +52,19 @@ InputFile *SymbolBody::getFile() { |
| 52 | return nullptr; | 52 | return nullptr; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | bool Symbol::isLive() const { | ||
| 56 | if (auto *R = dyn_cast<DefinedRegular>(this)) | ||
| 57 | return R->getChunk()->isLive(); | ||
| 58 | if (auto *Imp = dyn_cast<DefinedImportData>(this)) | ||
| 59 | return Imp->File->Live; | ||
| 60 | if (auto *Imp = dyn_cast<DefinedImportThunk>(this)) | ||
| 61 | return Imp->WrappedSym->File->Live; | ||
| 62 | // Assume any other kind of symbol is live. | ||
| 63 | return true; | ||
| 64 | } | ||
| 65 | |||
| 55 | COFFSymbolRef DefinedCOFF::getCOFFSymbol() { | 66 | COFFSymbolRef DefinedCOFF::getCOFFSymbol() { |
| 56 | size_t SymSize = | 67 | size_t SymSize = cast<ObjFile>(File)->getCOFFObj()->getSymbolTableEntrySize(); |
| 57 | cast<ObjectFile>(File)->getCOFFObj()->getSymbolTableEntrySize(); | ||
| 58 | if (SymSize == sizeof(coff_symbol16)) | 68 | if (SymSize == sizeof(coff_symbol16)) |
| 59 | return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(Sym)); | 69 | return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(Sym)); |
| 60 | assert(SymSize == sizeof(coff_symbol32)); | 70 | assert(SymSize == sizeof(coff_symbol32)); |
| ... | @@ -81,7 +91,7 @@ DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S, | ... | @@ -81,7 +91,7 @@ DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S, |
| 81 | 91 | ||
| 82 | Defined *Undefined::getWeakAlias() { | 92 | Defined *Undefined::getWeakAlias() { |
| 83 | // A weak alias may be a weak alias to another symbol, so check recursively. | 93 | // A weak alias may be a weak alias to another symbol, so check recursively. |
| 84 | for (SymbolBody *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias) | 94 | for (Symbol *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias) |
| 85 | if (auto *D = dyn_cast<Defined>(A)) | 95 | if (auto *D = dyn_cast<Defined>(A)) |
| 86 | return D; | 96 | return D; |
| 87 | return nullptr; | 97 | return nullptr; |
deps/lld/COFF/Symbols.h+67-79| ... | @@ -12,8 +12,8 @@ | ... | @@ -12,8 +12,8 @@ |
| 12 | 12 | ||
| 13 | #include "Chunks.h" | 13 | #include "Chunks.h" |
| 14 | #include "Config.h" | 14 | #include "Config.h" |
| 15 | #include "Memory.h" | 15 | #include "lld/Common/LLVM.h" |
| 16 | #include "lld/Core/LLVM.h" | 16 | #include "lld/Common/Memory.h" |
| 17 | #include "llvm/ADT/ArrayRef.h" | 17 | #include "llvm/ADT/ArrayRef.h" |
| 18 | #include "llvm/Object/Archive.h" | 18 | #include "llvm/Object/Archive.h" |
| 19 | #include "llvm/Object/COFF.h" | 19 | #include "llvm/Object/COFF.h" |
| ... | @@ -31,12 +31,11 @@ using llvm::object::coff_symbol_generic; | ... | @@ -31,12 +31,11 @@ using llvm::object::coff_symbol_generic; |
| 31 | 31 | ||
| 32 | class ArchiveFile; | 32 | class ArchiveFile; |
| 33 | class InputFile; | 33 | class InputFile; |
| 34 | class ObjectFile; | 34 | class ObjFile; |
| 35 | struct Symbol; | ||
| 36 | class SymbolTable; | 35 | class SymbolTable; |
| 37 | 36 | ||
| 38 | // The base class for real symbol classes. | 37 | // The base class for real symbol classes. |
| 39 | class SymbolBody { | 38 | class Symbol { |
| 40 | public: | 39 | public: |
| 41 | enum Kind { | 40 | enum Kind { |
| 42 | // The order of these is significant. We start with the regular defined | 41 | // The order of these is significant. We start with the regular defined |
| ... | @@ -70,16 +69,16 @@ public: | ... | @@ -70,16 +69,16 @@ public: |
| 70 | // Returns the file from which this symbol was created. | 69 | // Returns the file from which this symbol was created. |
| 71 | InputFile *getFile(); | 70 | InputFile *getFile(); |
| 72 | 71 | ||
| 73 | Symbol *symbol(); | 72 | // Indicates that this symbol will be included in the final image. Only valid |
| 74 | const Symbol *symbol() const { | 73 | // after calling markLive. |
| 75 | return const_cast<SymbolBody *>(this)->symbol(); | 74 | bool isLive() const; |
| 76 | } | ||
| 77 | 75 | ||
| 78 | protected: | 76 | protected: |
| 79 | friend SymbolTable; | 77 | friend SymbolTable; |
| 80 | explicit SymbolBody(Kind K, StringRef N = "") | 78 | explicit Symbol(Kind K, StringRef N = "") |
| 81 | : SymbolKind(K), IsExternal(true), IsCOMDAT(false), | 79 | : SymbolKind(K), IsExternal(true), IsCOMDAT(false), |
| 82 | WrittenToSymtab(false), Name(N) {} | 80 | WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false), |
| 81 | Name(N) {} | ||
| 83 | 82 | ||
| 84 | const unsigned SymbolKind : 8; | 83 | const unsigned SymbolKind : 8; |
| 85 | unsigned IsExternal : 1; | 84 | unsigned IsExternal : 1; |
| ... | @@ -92,19 +91,28 @@ public: | ... | @@ -92,19 +91,28 @@ public: |
| 92 | // symbols from being written to the symbol table more than once. | 91 | // symbols from being written to the symbol table more than once. |
| 93 | unsigned WrittenToSymtab : 1; | 92 | unsigned WrittenToSymtab : 1; |
| 94 | 93 | ||
| 94 | // True if this symbol was referenced by a regular (non-bitcode) object. | ||
| 95 | unsigned IsUsedInRegularObj : 1; | ||
| 96 | |||
| 97 | // True if we've seen both a lazy and an undefined symbol with this symbol | ||
| 98 | // name, which means that we have enqueued an archive member load and should | ||
| 99 | // not load any more archive members to resolve the same symbol. | ||
| 100 | unsigned PendingArchiveLoad : 1; | ||
| 101 | |||
| 102 | /// True if we've already added this symbol to the list of GC roots. | ||
| 103 | unsigned IsGCRoot : 1; | ||
| 104 | |||
| 95 | protected: | 105 | protected: |
| 96 | StringRef Name; | 106 | StringRef Name; |
| 97 | }; | 107 | }; |
| 98 | 108 | ||
| 99 | // The base class for any defined symbols, including absolute symbols, | 109 | // The base class for any defined symbols, including absolute symbols, |
| 100 | // etc. | 110 | // etc. |
| 101 | class Defined : public SymbolBody { | 111 | class Defined : public Symbol { |
| 102 | public: | 112 | public: |
| 103 | Defined(Kind K, StringRef N) : SymbolBody(K, N) {} | 113 | Defined(Kind K, StringRef N) : Symbol(K, N) {} |
| 104 | 114 | ||
| 105 | static bool classof(const SymbolBody *S) { | 115 | static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; } |
| 106 | return S->kind() <= LastDefinedKind; | ||
| 107 | } | ||
| 108 | 116 | ||
| 109 | // Returns the RVA (relative virtual address) of this symbol. The | 117 | // Returns the RVA (relative virtual address) of this symbol. The |
| 110 | // writer sets and uses RVAs. | 118 | // writer sets and uses RVAs. |
| ... | @@ -120,12 +128,13 @@ public: | ... | @@ -120,12 +128,13 @@ public: |
| 120 | // loaded through that. For bitcode files, Sym is nullptr and the name is stored | 128 | // loaded through that. For bitcode files, Sym is nullptr and the name is stored |
| 121 | // as a StringRef. | 129 | // as a StringRef. |
| 122 | class DefinedCOFF : public Defined { | 130 | class DefinedCOFF : public Defined { |
| 123 | friend SymbolBody; | 131 | friend Symbol; |
| 132 | |||
| 124 | public: | 133 | public: |
| 125 | DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S) | 134 | DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S) |
| 126 | : Defined(K, N), File(F), Sym(S) {} | 135 | : Defined(K, N), File(F), Sym(S) {} |
| 127 | 136 | ||
| 128 | static bool classof(const SymbolBody *S) { | 137 | static bool classof(const Symbol *S) { |
| 129 | return S->kind() <= LastDefinedCOFFKind; | 138 | return S->kind() <= LastDefinedCOFFKind; |
| 130 | } | 139 | } |
| 131 | 140 | ||
| ... | @@ -151,16 +160,15 @@ public: | ... | @@ -151,16 +160,15 @@ public: |
| 151 | this->IsCOMDAT = IsCOMDAT; | 160 | this->IsCOMDAT = IsCOMDAT; |
| 152 | } | 161 | } |
| 153 | 162 | ||
| 154 | static bool classof(const SymbolBody *S) { | 163 | static bool classof(const Symbol *S) { |
| 155 | return S->kind() == DefinedRegularKind; | 164 | return S->kind() == DefinedRegularKind; |
| 156 | } | 165 | } |
| 157 | 166 | ||
| 158 | uint64_t getRVA() { return (*Data)->getRVA() + Sym->Value; } | 167 | uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; } |
| 159 | bool isCOMDAT() { return IsCOMDAT; } | 168 | bool isCOMDAT() const { return IsCOMDAT; } |
| 160 | SectionChunk *getChunk() { return *Data; } | 169 | SectionChunk *getChunk() const { return *Data; } |
| 161 | uint32_t getValue() { return Sym->Value; } | 170 | uint32_t getValue() const { return Sym->Value; } |
| 162 | 171 | ||
| 163 | private: | ||
| 164 | SectionChunk **Data; | 172 | SectionChunk **Data; |
| 165 | }; | 173 | }; |
| 166 | 174 | ||
| ... | @@ -173,12 +181,12 @@ public: | ... | @@ -173,12 +181,12 @@ public: |
| 173 | this->IsExternal = true; | 181 | this->IsExternal = true; |
| 174 | } | 182 | } |
| 175 | 183 | ||
| 176 | static bool classof(const SymbolBody *S) { | 184 | static bool classof(const Symbol *S) { |
| 177 | return S->kind() == DefinedCommonKind; | 185 | return S->kind() == DefinedCommonKind; |
| 178 | } | 186 | } |
| 179 | 187 | ||
| 180 | uint64_t getRVA() { return Data->getRVA(); } | 188 | uint64_t getRVA() { return Data->getRVA(); } |
| 181 | Chunk *getChunk() { return Data; } | 189 | CommonChunk *getChunk() { return Data; } |
| 182 | 190 | ||
| 183 | private: | 191 | private: |
| 184 | friend SymbolTable; | 192 | friend SymbolTable; |
| ... | @@ -198,7 +206,7 @@ public: | ... | @@ -198,7 +206,7 @@ public: |
| 198 | DefinedAbsolute(StringRef N, uint64_t V) | 206 | DefinedAbsolute(StringRef N, uint64_t V) |
| 199 | : Defined(DefinedAbsoluteKind, N), VA(V) {} | 207 | : Defined(DefinedAbsoluteKind, N), VA(V) {} |
| 200 | 208 | ||
| 201 | static bool classof(const SymbolBody *S) { | 209 | static bool classof(const Symbol *S) { |
| 202 | return S->kind() == DefinedAbsoluteKind; | 210 | return S->kind() == DefinedAbsoluteKind; |
| 203 | } | 211 | } |
| 204 | 212 | ||
| ... | @@ -222,7 +230,7 @@ public: | ... | @@ -222,7 +230,7 @@ public: |
| 222 | explicit DefinedSynthetic(StringRef Name, Chunk *C) | 230 | explicit DefinedSynthetic(StringRef Name, Chunk *C) |
| 223 | : Defined(DefinedSyntheticKind, Name), C(C) {} | 231 | : Defined(DefinedSyntheticKind, Name), C(C) {} |
| 224 | 232 | ||
| 225 | static bool classof(const SymbolBody *S) { | 233 | static bool classof(const Symbol *S) { |
| 226 | return S->kind() == DefinedSyntheticKind; | 234 | return S->kind() == DefinedSyntheticKind; |
| 227 | } | 235 | } |
| 228 | 236 | ||
| ... | @@ -240,12 +248,12 @@ private: | ... | @@ -240,12 +248,12 @@ private: |
| 240 | // object file from an archive to replace itself with a defined | 248 | // object file from an archive to replace itself with a defined |
| 241 | // symbol. If the resolver finds both Undefined and Lazy for | 249 | // symbol. If the resolver finds both Undefined and Lazy for |
| 242 | // the same name, it will ask the Lazy to load a file. | 250 | // the same name, it will ask the Lazy to load a file. |
| 243 | class Lazy : public SymbolBody { | 251 | class Lazy : public Symbol { |
| 244 | public: | 252 | public: |
| 245 | Lazy(ArchiveFile *F, const Archive::Symbol S) | 253 | Lazy(ArchiveFile *F, const Archive::Symbol S) |
| 246 | : SymbolBody(LazyKind, S.getName()), File(F), Sym(S) {} | 254 | : Symbol(LazyKind, S.getName()), File(F), Sym(S) {} |
| 247 | 255 | ||
| 248 | static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; } | 256 | static bool classof(const Symbol *S) { return S->kind() == LazyKind; } |
| 249 | 257 | ||
| 250 | ArchiveFile *File; | 258 | ArchiveFile *File; |
| 251 | 259 | ||
| ... | @@ -257,19 +265,17 @@ private: | ... | @@ -257,19 +265,17 @@ private: |
| 257 | }; | 265 | }; |
| 258 | 266 | ||
| 259 | // Undefined symbols. | 267 | // Undefined symbols. |
| 260 | class Undefined : public SymbolBody { | 268 | class Undefined : public Symbol { |
| 261 | public: | 269 | public: |
| 262 | explicit Undefined(StringRef N) : SymbolBody(UndefinedKind, N) {} | 270 | explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {} |
| 263 | 271 | ||
| 264 | static bool classof(const SymbolBody *S) { | 272 | static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; } |
| 265 | return S->kind() == UndefinedKind; | ||
| 266 | } | ||
| 267 | 273 | ||
| 268 | // An undefined symbol can have a fallback symbol which gives an | 274 | // An undefined symbol can have a fallback symbol which gives an |
| 269 | // undefined symbol a second chance if it would remain undefined. | 275 | // undefined symbol a second chance if it would remain undefined. |
| 270 | // If it remains undefined, it'll be replaced with whatever the | 276 | // If it remains undefined, it'll be replaced with whatever the |
| 271 | // Alias pointer points to. | 277 | // Alias pointer points to. |
| 272 | SymbolBody *WeakAlias = nullptr; | 278 | Symbol *WeakAlias = nullptr; |
| 273 | 279 | ||
| 274 | // If this symbol is external weak, try to resolve it to a defined | 280 | // If this symbol is external weak, try to resolve it to a defined |
| 275 | // symbol by searching the chain of fallback symbols. Returns the symbol if | 281 | // symbol by searching the chain of fallback symbols. Returns the symbol if |
| ... | @@ -289,7 +295,7 @@ public: | ... | @@ -289,7 +295,7 @@ public: |
| 289 | : Defined(DefinedImportDataKind, N), File(F) { | 295 | : Defined(DefinedImportDataKind, N), File(F) { |
| 290 | } | 296 | } |
| 291 | 297 | ||
| 292 | static bool classof(const SymbolBody *S) { | 298 | static bool classof(const Symbol *S) { |
| 293 | return S->kind() == DefinedImportDataKind; | 299 | return S->kind() == DefinedImportDataKind; |
| 294 | } | 300 | } |
| 295 | 301 | ||
| ... | @@ -313,7 +319,7 @@ class DefinedImportThunk : public Defined { | ... | @@ -313,7 +319,7 @@ class DefinedImportThunk : public Defined { |
| 313 | public: | 319 | public: |
| 314 | DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine); | 320 | DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine); |
| 315 | 321 | ||
| 316 | static bool classof(const SymbolBody *S) { | 322 | static bool classof(const Symbol *S) { |
| 317 | return S->kind() == DefinedImportThunkKind; | 323 | return S->kind() == DefinedImportThunkKind; |
| 318 | } | 324 | } |
| 319 | 325 | ||
| ... | @@ -336,7 +342,7 @@ public: | ... | @@ -336,7 +342,7 @@ public: |
| 336 | DefinedLocalImport(StringRef N, Defined *S) | 342 | DefinedLocalImport(StringRef N, Defined *S) |
| 337 | : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {} | 343 | : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {} |
| 338 | 344 | ||
| 339 | static bool classof(const SymbolBody *S) { | 345 | static bool classof(const Symbol *S) { |
| 340 | return S->kind() == DefinedLocalImportKind; | 346 | return S->kind() == DefinedLocalImportKind; |
| 341 | } | 347 | } |
| 342 | 348 | ||
| ... | @@ -393,51 +399,33 @@ inline Chunk *Defined::getChunk() { | ... | @@ -393,51 +399,33 @@ inline Chunk *Defined::getChunk() { |
| 393 | llvm_unreachable("unknown symbol kind"); | 399 | llvm_unreachable("unknown symbol kind"); |
| 394 | } | 400 | } |
| 395 | 401 | ||
| 396 | // A real symbol object, SymbolBody, is usually stored within a Symbol. There's | 402 | // A buffer class that is large enough to hold any Symbol-derived |
| 397 | // always one Symbol for each symbol name. The resolver updates the SymbolBody | 403 | // object. We allocate memory using this class and instantiate a symbol |
| 398 | // stored in the Body field of this object as it resolves symbols. Symbol also | 404 | // using the placement new. |
| 399 | // holds computed properties of symbol names. | 405 | union SymbolUnion { |
| 400 | struct Symbol { | 406 | alignas(DefinedRegular) char A[sizeof(DefinedRegular)]; |
| 401 | // True if this symbol was referenced by a regular (non-bitcode) object. | 407 | alignas(DefinedCommon) char B[sizeof(DefinedCommon)]; |
| 402 | unsigned IsUsedInRegularObj : 1; | 408 | alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)]; |
| 403 | 409 | alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)]; | |
| 404 | // True if we've seen both a lazy and an undefined symbol with this symbol | 410 | alignas(Lazy) char E[sizeof(Lazy)]; |
| 405 | // name, which means that we have enqueued an archive member load and should | 411 | alignas(Undefined) char F[sizeof(Undefined)]; |
| 406 | // not load any more archive members to resolve the same symbol. | 412 | alignas(DefinedImportData) char G[sizeof(DefinedImportData)]; |
| 407 | unsigned PendingArchiveLoad : 1; | 413 | alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)]; |
| 408 | 414 | alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)]; | |
| 409 | // This field is used to store the Symbol's SymbolBody. This instantiation of | ||
| 410 | // AlignedCharArrayUnion gives us a struct with a char array field that is | ||
| 411 | // large and aligned enough to store any derived class of SymbolBody. | ||
| 412 | llvm::AlignedCharArrayUnion< | ||
| 413 | DefinedRegular, DefinedCommon, DefinedAbsolute, DefinedSynthetic, Lazy, | ||
| 414 | Undefined, DefinedImportData, DefinedImportThunk, DefinedLocalImport> | ||
| 415 | Body; | ||
| 416 | |||
| 417 | SymbolBody *body() { | ||
| 418 | return reinterpret_cast<SymbolBody *>(Body.buffer); | ||
| 419 | } | ||
| 420 | const SymbolBody *body() const { return const_cast<Symbol *>(this)->body(); } | ||
| 421 | }; | 415 | }; |
| 422 | 416 | ||
| 423 | template <typename T, typename... ArgT> | 417 | template <typename T, typename... ArgT> |
| 424 | void replaceBody(Symbol *S, ArgT &&... Arg) { | 418 | void replaceSymbol(Symbol *S, ArgT &&... Arg) { |
| 425 | static_assert(sizeof(T) <= sizeof(S->Body), "Body too small"); | 419 | static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small"); |
| 426 | static_assert(alignof(T) <= alignof(decltype(S->Body)), | 420 | static_assert(alignof(T) <= alignof(SymbolUnion), |
| 427 | "Body not aligned enough"); | 421 | "SymbolUnion not aligned enough"); |
| 428 | assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr && | 422 | assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr && |
| 429 | "Not a SymbolBody"); | 423 | "Not a Symbol"); |
| 430 | new (S->Body.buffer) T(std::forward<ArgT>(Arg)...); | 424 | new (S) T(std::forward<ArgT>(Arg)...); |
| 431 | } | ||
| 432 | |||
| 433 | inline Symbol *SymbolBody::symbol() { | ||
| 434 | assert(isExternal()); | ||
| 435 | return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) - | ||
| 436 | offsetof(Symbol, Body)); | ||
| 437 | } | 425 | } |
| 438 | } // namespace coff | 426 | } // namespace coff |
| 439 | 427 | ||
| 440 | std::string toString(coff::SymbolBody &B); | 428 | std::string toString(coff::Symbol &B); |
| 441 | } // namespace lld | 429 | } // namespace lld |
| 442 | 430 | ||
| 443 | #endif | 431 | #endif |
deps/lld/COFF/Writer.cpp+201-130| ... | @@ -10,22 +10,22 @@ | ... | @@ -10,22 +10,22 @@ |
| 10 | #include "Writer.h" | 10 | #include "Writer.h" |
| 11 | #include "Config.h" | 11 | #include "Config.h" |
| 12 | #include "DLL.h" | 12 | #include "DLL.h" |
| 13 | #include "Error.h" | ||
| 14 | #include "InputFiles.h" | 13 | #include "InputFiles.h" |
| 15 | #include "MapFile.h" | 14 | #include "MapFile.h" |
| 16 | #include "Memory.h" | ||
| 17 | #include "PDB.h" | 15 | #include "PDB.h" |
| 18 | #include "SymbolTable.h" | 16 | #include "SymbolTable.h" |
| 19 | #include "Symbols.h" | 17 | #include "Symbols.h" |
| 18 | #include "lld/Common/ErrorHandler.h" | ||
| 19 | #include "lld/Common/Memory.h" | ||
| 20 | #include "llvm/ADT/DenseMap.h" | 20 | #include "llvm/ADT/DenseMap.h" |
| 21 | #include "llvm/ADT/STLExtras.h" | 21 | #include "llvm/ADT/STLExtras.h" |
| 22 | #include "llvm/ADT/StringSwitch.h" | 22 | #include "llvm/ADT/StringSwitch.h" |
| 23 | #include "llvm/Support/BinaryStreamReader.h" | ||
| 23 | #include "llvm/Support/Debug.h" | 24 | #include "llvm/Support/Debug.h" |
| 24 | #include "llvm/Support/Endian.h" | 25 | #include "llvm/Support/Endian.h" |
| 25 | #include "llvm/Support/FileOutputBuffer.h" | 26 | #include "llvm/Support/FileOutputBuffer.h" |
| 26 | #include "llvm/Support/Parallel.h" | 27 | #include "llvm/Support/Parallel.h" |
| 27 | #include "llvm/Support/RandomNumberGenerator.h" | 28 | #include "llvm/Support/RandomNumberGenerator.h" |
| 28 | #include "llvm/Support/raw_ostream.h" | ||
| 29 | #include <algorithm> | 29 | #include <algorithm> |
| 30 | #include <cstdio> | 30 | #include <cstdio> |
| 31 | #include <map> | 31 | #include <map> |
| ... | @@ -65,8 +65,9 @@ public: | ... | @@ -65,8 +65,9 @@ public: |
| 65 | D->Type = COFF::IMAGE_DEBUG_TYPE_CODEVIEW; | 65 | D->Type = COFF::IMAGE_DEBUG_TYPE_CODEVIEW; |
| 66 | D->SizeOfData = Record->getSize(); | 66 | D->SizeOfData = Record->getSize(); |
| 67 | D->AddressOfRawData = Record->getRVA(); | 67 | D->AddressOfRawData = Record->getRVA(); |
| 68 | // TODO(compnerd) get the file offset | 68 | OutputSection *OS = Record->getOutputSection(); |
| 69 | D->PointerToRawData = 0; | 69 | uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA()); |
| 70 | D->PointerToRawData = Offs; | ||
| 70 | 71 | ||
| 71 | ++D; | 72 | ++D; |
| 72 | } | 73 | } |
| ... | @@ -77,32 +78,37 @@ private: | ... | @@ -77,32 +78,37 @@ private: |
| 77 | }; | 78 | }; |
| 78 | 79 | ||
| 79 | class CVDebugRecordChunk : public Chunk { | 80 | class CVDebugRecordChunk : public Chunk { |
| 81 | public: | ||
| 82 | CVDebugRecordChunk() { | ||
| 83 | PDBAbsPath = Config->PDBPath; | ||
| 84 | if (!PDBAbsPath.empty()) | ||
| 85 | llvm::sys::fs::make_absolute(PDBAbsPath); | ||
| 86 | } | ||
| 87 | |||
| 80 | size_t getSize() const override { | 88 | size_t getSize() const override { |
| 81 | return sizeof(codeview::DebugInfo) + Config->PDBPath.size() + 1; | 89 | return sizeof(codeview::DebugInfo) + PDBAbsPath.size() + 1; |
| 82 | } | 90 | } |
| 83 | 91 | ||
| 84 | void writeTo(uint8_t *B) const override { | 92 | void writeTo(uint8_t *B) const override { |
| 85 | // Save off the DebugInfo entry to backfill the file signature (build id) | 93 | // Save off the DebugInfo entry to backfill the file signature (build id) |
| 86 | // in Writer::writeBuildId | 94 | // in Writer::writeBuildId |
| 87 | DI = reinterpret_cast<codeview::DebugInfo *>(B + OutputSectionOff); | 95 | BuildId = reinterpret_cast<codeview::DebugInfo *>(B + OutputSectionOff); |
| 88 | |||
| 89 | DI->Signature.CVSignature = OMF::Signature::PDB70; | ||
| 90 | 96 | ||
| 91 | // variable sized field (PDB Path) | 97 | // variable sized field (PDB Path) |
| 92 | auto *P = reinterpret_cast<char *>(B + OutputSectionOff + sizeof(*DI)); | 98 | char *P = reinterpret_cast<char *>(B + OutputSectionOff + sizeof(*BuildId)); |
| 93 | if (!Config->PDBPath.empty()) | 99 | if (!PDBAbsPath.empty()) |
| 94 | memcpy(P, Config->PDBPath.data(), Config->PDBPath.size()); | 100 | memcpy(P, PDBAbsPath.data(), PDBAbsPath.size()); |
| 95 | P[Config->PDBPath.size()] = '\0'; | 101 | P[PDBAbsPath.size()] = '\0'; |
| 96 | } | 102 | } |
| 97 | 103 | ||
| 98 | public: | 104 | SmallString<128> PDBAbsPath; |
| 99 | mutable codeview::DebugInfo *DI = nullptr; | 105 | mutable codeview::DebugInfo *BuildId = nullptr; |
| 100 | }; | 106 | }; |
| 101 | 107 | ||
| 102 | // The writer writes a SymbolTable result to a file. | 108 | // The writer writes a SymbolTable result to a file. |
| 103 | class Writer { | 109 | class Writer { |
| 104 | public: | 110 | public: |
| 105 | Writer(SymbolTable *T) : Symtab(T) {} | 111 | Writer() : Buffer(errorHandler().OutputBuffer) {} |
| 106 | void run(); | 112 | void run(); |
| 107 | 113 | ||
| 108 | private: | 114 | private: |
| ... | @@ -115,11 +121,11 @@ private: | ... | @@ -115,11 +121,11 @@ private: |
| 115 | void createSymbolAndStringTable(); | 121 | void createSymbolAndStringTable(); |
| 116 | void openFile(StringRef OutputPath); | 122 | void openFile(StringRef OutputPath); |
| 117 | template <typename PEHeaderTy> void writeHeader(); | 123 | template <typename PEHeaderTy> void writeHeader(); |
| 118 | void fixSafeSEHSymbols(); | 124 | void createSEHTable(OutputSection *RData); |
| 119 | void setSectionPermissions(); | 125 | void setSectionPermissions(); |
| 120 | void writeSections(); | 126 | void writeSections(); |
| 121 | void sortExceptionTable(); | ||
| 122 | void writeBuildId(); | 127 | void writeBuildId(); |
| 128 | void sortExceptionTable(); | ||
| 123 | 129 | ||
| 124 | llvm::Optional<coff_symbol16> createSymbol(Defined *D); | 130 | llvm::Optional<coff_symbol16> createSymbol(Defined *D); |
| 125 | size_t addEntryToStringTable(StringRef Str); | 131 | size_t addEntryToStringTable(StringRef Str); |
| ... | @@ -132,8 +138,7 @@ private: | ... | @@ -132,8 +138,7 @@ private: |
| 132 | uint32_t getSizeOfInitializedData(); | 138 | uint32_t getSizeOfInitializedData(); |
| 133 | std::map<StringRef, std::vector<DefinedImportData *>> binImports(); | 139 | std::map<StringRef, std::vector<DefinedImportData *>> binImports(); |
| 134 | 140 | ||
| 135 | SymbolTable *Symtab; | 141 | std::unique_ptr<FileOutputBuffer> &Buffer; |
| 136 | std::unique_ptr<FileOutputBuffer> Buffer; | ||
| 137 | std::vector<OutputSection *> OutputSections; | 142 | std::vector<OutputSection *> OutputSections; |
| 138 | std::vector<char> Strtab; | 143 | std::vector<char> Strtab; |
| 139 | std::vector<llvm::object::coff_symbol16> OutputSymtab; | 144 | std::vector<llvm::object::coff_symbol16> OutputSymtab; |
| ... | @@ -145,6 +150,7 @@ private: | ... | @@ -145,6 +150,7 @@ private: |
| 145 | Chunk *DebugDirectory = nullptr; | 150 | Chunk *DebugDirectory = nullptr; |
| 146 | std::vector<Chunk *> DebugRecords; | 151 | std::vector<Chunk *> DebugRecords; |
| 147 | CVDebugRecordChunk *BuildId = nullptr; | 152 | CVDebugRecordChunk *BuildId = nullptr; |
| 153 | Optional<codeview::DebugInfo> PreviousBuildId; | ||
| 148 | ArrayRef<uint8_t> SectionTable; | 154 | ArrayRef<uint8_t> SectionTable; |
| 149 | 155 | ||
| 150 | uint64_t FileSize; | 156 | uint64_t FileSize; |
| ... | @@ -157,7 +163,7 @@ private: | ... | @@ -157,7 +163,7 @@ private: |
| 157 | namespace lld { | 163 | namespace lld { |
| 158 | namespace coff { | 164 | namespace coff { |
| 159 | 165 | ||
| 160 | void writeResult(SymbolTable *T) { Writer(T).run(); } | 166 | void writeResult() { Writer().run(); } |
| 161 | 167 | ||
| 162 | void OutputSection::setRVA(uint64_t RVA) { | 168 | void OutputSection::setRVA(uint64_t RVA) { |
| 163 | Header.VirtualAddress = RVA; | 169 | Header.VirtualAddress = RVA; |
| ... | @@ -178,10 +184,12 @@ void OutputSection::addChunk(Chunk *C) { | ... | @@ -178,10 +184,12 @@ void OutputSection::addChunk(Chunk *C) { |
| 178 | Chunks.push_back(C); | 184 | Chunks.push_back(C); |
| 179 | C->setOutputSection(this); | 185 | C->setOutputSection(this); |
| 180 | uint64_t Off = Header.VirtualSize; | 186 | uint64_t Off = Header.VirtualSize; |
| 181 | Off = alignTo(Off, C->getAlign()); | 187 | Off = alignTo(Off, C->Alignment); |
| 182 | C->setRVA(Off); | 188 | C->setRVA(Off); |
| 183 | C->OutputSectionOff = Off; | 189 | C->OutputSectionOff = Off; |
| 184 | Off += C->getSize(); | 190 | Off += C->getSize(); |
| 191 | if (Off > UINT32_MAX) | ||
| 192 | error("section larger than 4 GiB: " + Name); | ||
| 185 | Header.VirtualSize = Off; | 193 | Header.VirtualSize = Off; |
| 186 | if (C->hasData()) | 194 | if (C->hasData()) |
| 187 | Header.SizeOfRawData = alignTo(Off, SectorSize); | 195 | Header.SizeOfRawData = alignTo(Off, SectorSize); |
| ... | @@ -203,7 +211,8 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) { | ... | @@ -203,7 +211,8 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) { |
| 203 | // If name is too long, write offset into the string table as a name. | 211 | // If name is too long, write offset into the string table as a name. |
| 204 | sprintf(Hdr->Name, "/%d", StringTableOff); | 212 | sprintf(Hdr->Name, "/%d", StringTableOff); |
| 205 | } else { | 213 | } else { |
| 206 | assert(!Config->Debug || Name.size() <= COFF::NameSize); | 214 | assert(!Config->Debug || Name.size() <= COFF::NameSize || |
| 215 | (Hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0); | ||
| 207 | strncpy(Hdr->Name, Name.data(), | 216 | strncpy(Hdr->Name, Name.data(), |
| 208 | std::min(Name.size(), (size_t)COFF::NameSize)); | 217 | std::min(Name.size(), (size_t)COFF::NameSize)); |
| 209 | } | 218 | } |
| ... | @@ -212,6 +221,67 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) { | ... | @@ -212,6 +221,67 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) { |
| 212 | } // namespace coff | 221 | } // namespace coff |
| 213 | } // namespace lld | 222 | } // namespace lld |
| 214 | 223 | ||
| 224 | // PDBs are matched against executables using a build id which consists of three | ||
| 225 | // components: | ||
| 226 | // 1. A 16-bit GUID | ||
| 227 | // 2. An age | ||
| 228 | // 3. A time stamp. | ||
| 229 | // | ||
| 230 | // Debuggers and symbol servers match executables against debug info by checking | ||
| 231 | // each of these components of the EXE/DLL against the corresponding value in | ||
| 232 | // the PDB and failing a match if any of the components differ. In the case of | ||
| 233 | // symbol servers, symbols are cached in a folder that is a function of the | ||
| 234 | // GUID. As a result, in order to avoid symbol cache pollution where every | ||
| 235 | // incremental build copies a new PDB to the symbol cache, we must try to re-use | ||
| 236 | // the existing GUID if one exists, but bump the age. This way the match will | ||
| 237 | // fail, so the symbol cache knows to use the new PDB, but the GUID matches, so | ||
| 238 | // it overwrites the existing item in the symbol cache rather than making a new | ||
| 239 | // one. | ||
| 240 | static Optional<codeview::DebugInfo> loadExistingBuildId(StringRef Path) { | ||
| 241 | // We don't need to incrementally update a previous build id if we're not | ||
| 242 | // writing codeview debug info. | ||
| 243 | if (!Config->Debug) | ||
| 244 | return None; | ||
| 245 | |||
| 246 | auto ExpectedBinary = llvm::object::createBinary(Path); | ||
| 247 | if (!ExpectedBinary) { | ||
| 248 | consumeError(ExpectedBinary.takeError()); | ||
| 249 | return None; | ||
| 250 | } | ||
| 251 | |||
| 252 | auto Binary = std::move(*ExpectedBinary); | ||
| 253 | if (!Binary.getBinary()->isCOFF()) | ||
| 254 | return None; | ||
| 255 | |||
| 256 | std::error_code EC; | ||
| 257 | COFFObjectFile File(Binary.getBinary()->getMemoryBufferRef(), EC); | ||
| 258 | if (EC) | ||
| 259 | return None; | ||
| 260 | |||
| 261 | // If the machine of the binary we're outputting doesn't match the machine | ||
| 262 | // of the existing binary, don't try to re-use the build id. | ||
| 263 | if (File.is64() != Config->is64() || File.getMachine() != Config->Machine) | ||
| 264 | return None; | ||
| 265 | |||
| 266 | for (const auto &DebugDir : File.debug_directories()) { | ||
| 267 | if (DebugDir.Type != IMAGE_DEBUG_TYPE_CODEVIEW) | ||
| 268 | continue; | ||
| 269 | |||
| 270 | const codeview::DebugInfo *ExistingDI = nullptr; | ||
| 271 | StringRef PDBFileName; | ||
| 272 | if (auto EC = File.getDebugPDBInfo(ExistingDI, PDBFileName)) { | ||
| 273 | (void)EC; | ||
| 274 | return None; | ||
| 275 | } | ||
| 276 | // We only support writing PDBs in v70 format. So if this is not a build | ||
| 277 | // id that we recognize / support, ignore it. | ||
| 278 | if (ExistingDI->Signature.CVSignature != OMF::Signature::PDB70) | ||
| 279 | return None; | ||
| 280 | return *ExistingDI; | ||
| 281 | } | ||
| 282 | return None; | ||
| 283 | } | ||
| 284 | |||
| 215 | // The main function of the writer. | 285 | // The main function of the writer. |
| 216 | void Writer::run() { | 286 | void Writer::run() { |
| 217 | createSections(); | 287 | createSections(); |
| ... | @@ -224,32 +294,39 @@ void Writer::run() { | ... | @@ -224,32 +294,39 @@ void Writer::run() { |
| 224 | removeEmptySections(); | 294 | removeEmptySections(); |
| 225 | setSectionPermissions(); | 295 | setSectionPermissions(); |
| 226 | createSymbolAndStringTable(); | 296 | createSymbolAndStringTable(); |
| 297 | |||
| 298 | // We must do this before opening the output file, as it depends on being able | ||
| 299 | // to read the contents of the existing output file. | ||
| 300 | PreviousBuildId = loadExistingBuildId(Config->OutputFile); | ||
| 227 | openFile(Config->OutputFile); | 301 | openFile(Config->OutputFile); |
| 228 | if (Config->is64()) { | 302 | if (Config->is64()) { |
| 229 | writeHeader<pe32plus_header>(); | 303 | writeHeader<pe32plus_header>(); |
| 230 | } else { | 304 | } else { |
| 231 | writeHeader<pe32_header>(); | 305 | writeHeader<pe32_header>(); |
| 232 | } | 306 | } |
| 233 | fixSafeSEHSymbols(); | ||
| 234 | writeSections(); | 307 | writeSections(); |
| 235 | sortExceptionTable(); | 308 | sortExceptionTable(); |
| 236 | writeBuildId(); | 309 | writeBuildId(); |
| 237 | 310 | ||
| 238 | if (!Config->PDBPath.empty() && Config->Debug) { | 311 | if (!Config->PDBPath.empty() && Config->Debug) { |
| 239 | const llvm::codeview::DebugInfo *DI = nullptr; | 312 | |
| 240 | if (Config->DebugTypes & static_cast<unsigned>(coff::DebugType::CV)) | 313 | assert(BuildId); |
| 241 | DI = BuildId->DI; | 314 | createPDB(Symtab, OutputSections, SectionTable, *BuildId->BuildId); |
| 242 | createPDB(Symtab, SectionTable, DI); | ||
| 243 | } | 315 | } |
| 244 | 316 | ||
| 245 | writeMapFile(OutputSections); | 317 | writeMapFile(OutputSections); |
| 246 | 318 | ||
| 247 | if (auto EC = Buffer->commit()) | 319 | if (auto E = Buffer->commit()) |
| 248 | fatal(EC, "failed to write the output file"); | 320 | fatal("failed to write the output file: " + toString(std::move(E))); |
| 249 | } | 321 | } |
| 250 | 322 | ||
| 251 | static StringRef getOutputSection(StringRef Name) { | 323 | static StringRef getOutputSection(StringRef Name) { |
| 252 | StringRef S = Name.split('$').first; | 324 | StringRef S = Name.split('$').first; |
| 325 | |||
| 326 | // Treat a later period as a separator for MinGW, for sections like | ||
| 327 | // ".ctors.01234". | ||
| 328 | S = S.substr(0, S.find('.', 1)); | ||
| 329 | |||
| 253 | auto It = Config->Merge.find(S); | 330 | auto It = Config->Merge.find(S); |
| 254 | if (It == Config->Merge.end()) | 331 | if (It == Config->Merge.end()) |
| 255 | return S; | 332 | return S; |
| ... | @@ -303,41 +380,20 @@ void Writer::createMiscChunks() { | ... | @@ -303,41 +380,20 @@ void Writer::createMiscChunks() { |
| 303 | if (Config->Debug) { | 380 | if (Config->Debug) { |
| 304 | DebugDirectory = make<DebugDirectoryChunk>(DebugRecords); | 381 | DebugDirectory = make<DebugDirectoryChunk>(DebugRecords); |
| 305 | 382 | ||
| 306 | // TODO(compnerd) create a coffgrp entry if DebugType::CV is not enabled | 383 | // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified. We |
| 307 | if (Config->DebugTypes & static_cast<unsigned>(coff::DebugType::CV)) { | 384 | // output a PDB no matter what, and this chunk provides the only means of |
| 308 | auto *Chunk = make<CVDebugRecordChunk>(); | 385 | // allowing a debugger to match a PDB and an executable. So we need it even |
| 309 | 386 | // if we're ultimately not going to write CodeView data to the PDB. | |
| 310 | BuildId = Chunk; | 387 | auto *CVChunk = make<CVDebugRecordChunk>(); |
| 311 | DebugRecords.push_back(Chunk); | 388 | BuildId = CVChunk; |
| 312 | } | 389 | DebugRecords.push_back(CVChunk); |
| 313 | 390 | ||
| 314 | RData->addChunk(DebugDirectory); | 391 | RData->addChunk(DebugDirectory); |
| 315 | for (Chunk *C : DebugRecords) | 392 | for (Chunk *C : DebugRecords) |
| 316 | RData->addChunk(C); | 393 | RData->addChunk(C); |
| 317 | } | 394 | } |
| 318 | 395 | ||
| 319 | // Create SEH table. x86-only. | 396 | createSEHTable(RData); |
| 320 | if (Config->Machine != I386) | ||
| 321 | return; | ||
| 322 | |||
| 323 | std::set<Defined *> Handlers; | ||
| 324 | |||
| 325 | for (lld::coff::ObjectFile *File : Symtab->ObjectFiles) { | ||
| 326 | if (!File->SEHCompat) | ||
| 327 | return; | ||
| 328 | for (SymbolBody *B : File->SEHandlers) { | ||
| 329 | // Make sure the handler is still live. Assume all handlers are regular | ||
| 330 | // symbols. | ||
| 331 | auto *D = dyn_cast<DefinedRegular>(B); | ||
| 332 | if (D && D->getChunk()->isLive()) | ||
| 333 | Handlers.insert(D); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | if (!Handlers.empty()) { | ||
| 338 | SEHTable = make<SEHTableChunk>(Handlers); | ||
| 339 | RData->addChunk(SEHTable); | ||
| 340 | } | ||
| 341 | } | 397 | } |
| 342 | 398 | ||
| 343 | // Create .idata section for the DLL-imported symbol table. | 399 | // Create .idata section for the DLL-imported symbol table. |
| ... | @@ -345,13 +401,13 @@ void Writer::createMiscChunks() { | ... | @@ -345,13 +401,13 @@ void Writer::createMiscChunks() { |
| 345 | // IdataContents class abstracted away the details for us, | 401 | // IdataContents class abstracted away the details for us, |
| 346 | // so we just let it create chunks and add them to the section. | 402 | // so we just let it create chunks and add them to the section. |
| 347 | void Writer::createImportTables() { | 403 | void Writer::createImportTables() { |
| 348 | if (Symtab->ImportFiles.empty()) | 404 | if (ImportFile::Instances.empty()) |
| 349 | return; | 405 | return; |
| 350 | 406 | ||
| 351 | // Initialize DLLOrder so that import entries are ordered in | 407 | // Initialize DLLOrder so that import entries are ordered in |
| 352 | // the same order as in the command line. (That affects DLL | 408 | // the same order as in the command line. (That affects DLL |
| 353 | // initialization order, and this ordering is MSVC-compatible.) | 409 | // initialization order, and this ordering is MSVC-compatible.) |
| 354 | for (ImportFile *File : Symtab->ImportFiles) { | 410 | for (ImportFile *File : ImportFile::Instances) { |
| 355 | if (!File->Live) | 411 | if (!File->Live) |
| 356 | continue; | 412 | continue; |
| 357 | 413 | ||
| ... | @@ -361,7 +417,7 @@ void Writer::createImportTables() { | ... | @@ -361,7 +417,7 @@ void Writer::createImportTables() { |
| 361 | } | 417 | } |
| 362 | 418 | ||
| 363 | OutputSection *Text = createSection(".text"); | 419 | OutputSection *Text = createSection(".text"); |
| 364 | for (ImportFile *File : Symtab->ImportFiles) { | 420 | for (ImportFile *File : ImportFile::Instances) { |
| 365 | if (!File->Live) | 421 | if (!File->Live) |
| 366 | continue; | 422 | continue; |
| 367 | 423 | ||
| ... | @@ -432,19 +488,12 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { | ... | @@ -432,19 +488,12 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { |
| 432 | if (isa<DefinedSynthetic>(Def)) | 488 | if (isa<DefinedSynthetic>(Def)) |
| 433 | return None; | 489 | return None; |
| 434 | 490 | ||
| 435 | if (auto *D = dyn_cast<DefinedRegular>(Def)) { | 491 | // Don't write dead symbols or symbols in codeview sections to the symbol |
| 436 | // Don't write dead symbols or symbols in codeview sections to the symbol | 492 | // table. |
| 437 | // table. | 493 | if (!Def->isLive()) |
| 438 | if (!D->getChunk()->isLive() || D->getChunk()->isCodeView()) | 494 | return None; |
| 439 | return None; | 495 | if (auto *D = dyn_cast<DefinedRegular>(Def)) |
| 440 | } | 496 | if (D->getChunk()->isCodeView()) |
| 441 | |||
| 442 | if (auto *Sym = dyn_cast<DefinedImportData>(Def)) | ||
| 443 | if (!Sym->File->Live) | ||
| 444 | return None; | ||
| 445 | |||
| 446 | if (auto *Sym = dyn_cast<DefinedImportThunk>(Def)) | ||
| 447 | if (!Sym->WrappedSym->File->Live) | ||
| 448 | return None; | 497 | return None; |
| 449 | 498 | ||
| 450 | coff_symbol16 Sym; | 499 | coff_symbol16 Sym; |
| ... | @@ -468,7 +517,7 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { | ... | @@ -468,7 +517,7 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { |
| 468 | Sym.NumberOfAuxSymbols = 0; | 517 | Sym.NumberOfAuxSymbols = 0; |
| 469 | 518 | ||
| 470 | switch (Def->kind()) { | 519 | switch (Def->kind()) { |
| 471 | case SymbolBody::DefinedAbsoluteKind: | 520 | case Symbol::DefinedAbsoluteKind: |
| 472 | Sym.Value = Def->getRVA(); | 521 | Sym.Value = Def->getRVA(); |
| 473 | Sym.SectionNumber = IMAGE_SYM_ABSOLUTE; | 522 | Sym.SectionNumber = IMAGE_SYM_ABSOLUTE; |
| 474 | break; | 523 | break; |
| ... | @@ -489,40 +538,46 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { | ... | @@ -489,40 +538,46 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { |
| 489 | } | 538 | } |
| 490 | 539 | ||
| 491 | void Writer::createSymbolAndStringTable() { | 540 | void Writer::createSymbolAndStringTable() { |
| 492 | if (!Config->Debug || !Config->WriteSymtab) | ||
| 493 | return; | ||
| 494 | |||
| 495 | // Name field in the section table is 8 byte long. Longer names need | 541 | // Name field in the section table is 8 byte long. Longer names need |
| 496 | // to be written to the string table. First, construct string table. | 542 | // to be written to the string table. First, construct string table. |
| 497 | for (OutputSection *Sec : OutputSections) { | 543 | for (OutputSection *Sec : OutputSections) { |
| 498 | StringRef Name = Sec->getName(); | 544 | StringRef Name = Sec->getName(); |
| 499 | if (Name.size() <= COFF::NameSize) | 545 | if (Name.size() <= COFF::NameSize) |
| 500 | continue; | 546 | continue; |
| 547 | // If a section isn't discardable (i.e. will be mapped at runtime), | ||
| 548 | // prefer a truncated section name over a long section name in | ||
| 549 | // the string table that is unavailable at runtime. This is different from | ||
| 550 | // what link.exe does, but finding ".eh_fram" instead of "/4" is useful | ||
| 551 | // to libunwind. | ||
| 552 | if ((Sec->getPermissions() & IMAGE_SCN_MEM_DISCARDABLE) == 0) | ||
| 553 | continue; | ||
| 501 | Sec->setStringTableOff(addEntryToStringTable(Name)); | 554 | Sec->setStringTableOff(addEntryToStringTable(Name)); |
| 502 | } | 555 | } |
| 503 | 556 | ||
| 504 | for (lld::coff::ObjectFile *File : Symtab->ObjectFiles) { | 557 | if (Config->DebugDwarf) { |
| 505 | for (SymbolBody *B : File->getSymbols()) { | 558 | for (ObjFile *File : ObjFile::Instances) { |
| 506 | auto *D = dyn_cast<Defined>(B); | 559 | for (Symbol *B : File->getSymbols()) { |
| 507 | if (!D || D->WrittenToSymtab) | 560 | auto *D = dyn_cast_or_null<Defined>(B); |
| 508 | continue; | 561 | if (!D || D->WrittenToSymtab) |
| 509 | D->WrittenToSymtab = true; | 562 | continue; |
| 563 | D->WrittenToSymtab = true; | ||
| 510 | 564 | ||
| 511 | if (Optional<coff_symbol16> Sym = createSymbol(D)) | 565 | if (Optional<coff_symbol16> Sym = createSymbol(D)) |
| 512 | OutputSymtab.push_back(*Sym); | 566 | OutputSymtab.push_back(*Sym); |
| 567 | } | ||
| 513 | } | 568 | } |
| 514 | } | 569 | } |
| 515 | 570 | ||
| 571 | if (OutputSymtab.empty() && Strtab.empty()) | ||
| 572 | return; | ||
| 573 | |||
| 516 | OutputSection *LastSection = OutputSections.back(); | 574 | OutputSection *LastSection = OutputSections.back(); |
| 517 | // We position the symbol table to be adjacent to the end of the last section. | 575 | // We position the symbol table to be adjacent to the end of the last section. |
| 518 | uint64_t FileOff = LastSection->getFileOff() + | 576 | uint64_t FileOff = LastSection->getFileOff() + |
| 519 | alignTo(LastSection->getRawSize(), SectorSize); | 577 | alignTo(LastSection->getRawSize(), SectorSize); |
| 520 | if (!OutputSymtab.empty()) { | 578 | PointerToSymbolTable = FileOff; |
| 521 | PointerToSymbolTable = FileOff; | 579 | FileOff += OutputSymtab.size() * sizeof(coff_symbol16); |
| 522 | FileOff += OutputSymtab.size() * sizeof(coff_symbol16); | 580 | FileOff += 4 + Strtab.size(); |
| 523 | } | ||
| 524 | if (!Strtab.empty()) | ||
| 525 | FileOff += Strtab.size() + 4; | ||
| 526 | FileSize = alignTo(FileOff, SectorSize); | 581 | FileSize = alignTo(FileOff, SectorSize); |
| 527 | } | 582 | } |
| 528 | 583 | ||
| ... | @@ -551,7 +606,7 @@ void Writer::assignAddresses() { | ... | @@ -551,7 +606,7 @@ void Writer::assignAddresses() { |
| 551 | RVA += alignTo(Sec->getVirtualSize(), PageSize); | 606 | RVA += alignTo(Sec->getVirtualSize(), PageSize); |
| 552 | FileSize += alignTo(Sec->getRawSize(), SectorSize); | 607 | FileSize += alignTo(Sec->getRawSize(), SectorSize); |
| 553 | } | 608 | } |
| 554 | SizeOfImage = SizeOfHeaders + alignTo(RVA - 0x1000, PageSize); | 609 | SizeOfImage = alignTo(RVA, PageSize); |
| 555 | } | 610 | } |
| 556 | 611 | ||
| 557 | template <typename PEHeaderTy> void Writer::writeHeader() { | 612 | template <typename PEHeaderTy> void Writer::writeHeader() { |
| ... | @@ -621,23 +676,21 @@ template <typename PEHeaderTy> void Writer::writeHeader() { | ... | @@ -621,23 +676,21 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 621 | PE->SizeOfStackCommit = Config->StackCommit; | 676 | PE->SizeOfStackCommit = Config->StackCommit; |
| 622 | PE->SizeOfHeapReserve = Config->HeapReserve; | 677 | PE->SizeOfHeapReserve = Config->HeapReserve; |
| 623 | PE->SizeOfHeapCommit = Config->HeapCommit; | 678 | PE->SizeOfHeapCommit = Config->HeapCommit; |
| 624 | |||
| 625 | // Import Descriptor Tables and Import Address Tables are merged | ||
| 626 | // in our output. That's not compatible with the Binding feature | ||
| 627 | // that is sort of prelinking. Setting this flag to make it clear | ||
| 628 | // that our outputs are not for the Binding. | ||
| 629 | PE->DLLCharacteristics = IMAGE_DLL_CHARACTERISTICS_NO_BIND; | ||
| 630 | |||
| 631 | if (Config->AppContainer) | 679 | if (Config->AppContainer) |
| 632 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER; | 680 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER; |
| 633 | if (Config->DynamicBase) | 681 | if (Config->DynamicBase) |
| 634 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; | 682 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; |
| 635 | if (Config->HighEntropyVA) | 683 | if (Config->HighEntropyVA) |
| 636 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA; | 684 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA; |
| 685 | if (!Config->AllowBind) | ||
| 686 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND; | ||
| 637 | if (Config->NxCompat) | 687 | if (Config->NxCompat) |
| 638 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT; | 688 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT; |
| 639 | if (!Config->AllowIsolation) | 689 | if (!Config->AllowIsolation) |
| 640 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION; | 690 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION; |
| 691 | if (Config->Machine == I386 && !SEHTable && | ||
| 692 | !Symtab->findUnderscore("_load_config_used")) | ||
| 693 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH; | ||
| 641 | if (Config->TerminalServerAware) | 694 | if (Config->TerminalServerAware) |
| 642 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE; | 695 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE; |
| 643 | PE->NumberOfRvaAndSize = NumberfOfDataDirectory; | 696 | PE->NumberOfRvaAndSize = NumberfOfDataDirectory; |
| ... | @@ -673,7 +726,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { | ... | @@ -673,7 +726,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 673 | Dir[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize(); | 726 | Dir[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize(); |
| 674 | } | 727 | } |
| 675 | if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) { | 728 | if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) { |
| 676 | if (Defined *B = dyn_cast<Defined>(Sym->body())) { | 729 | if (Defined *B = dyn_cast<Defined>(Sym)) { |
| 677 | Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA(); | 730 | Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA(); |
| 678 | Dir[TLS_TABLE].Size = Config->is64() | 731 | Dir[TLS_TABLE].Size = Config->is64() |
| 679 | ? sizeof(object::coff_tls_directory64) | 732 | ? sizeof(object::coff_tls_directory64) |
| ... | @@ -685,7 +738,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { | ... | @@ -685,7 +738,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 685 | Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize(); | 738 | Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize(); |
| 686 | } | 739 | } |
| 687 | if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) { | 740 | if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) { |
| 688 | if (auto *B = dyn_cast<DefinedRegular>(Sym->body())) { | 741 | if (auto *B = dyn_cast<DefinedRegular>(Sym)) { |
| 689 | SectionChunk *SC = B->getChunk(); | 742 | SectionChunk *SC = B->getChunk(); |
| 690 | assert(B->getRVA() >= SC->getRVA()); | 743 | assert(B->getRVA() >= SC->getRVA()); |
| 691 | uint64_t OffsetInChunk = B->getRVA() - SC->getRVA(); | 744 | uint64_t OffsetInChunk = B->getRVA() - SC->getRVA(); |
| ... | @@ -715,7 +768,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { | ... | @@ -715,7 +768,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 715 | SectionTable = ArrayRef<uint8_t>( | 768 | SectionTable = ArrayRef<uint8_t>( |
| 716 | Buf - OutputSections.size() * sizeof(coff_section), Buf); | 769 | Buf - OutputSections.size() * sizeof(coff_section), Buf); |
| 717 | 770 | ||
| 718 | if (OutputSymtab.empty()) | 771 | if (OutputSymtab.empty() && Strtab.empty()) |
| 719 | return; | 772 | return; |
| 720 | 773 | ||
| 721 | COFF->PointerToSymbolTable = PointerToSymbolTable; | 774 | COFF->PointerToSymbolTable = PointerToSymbolTable; |
| ... | @@ -734,21 +787,40 @@ template <typename PEHeaderTy> void Writer::writeHeader() { | ... | @@ -734,21 +787,40 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 734 | } | 787 | } |
| 735 | 788 | ||
| 736 | void Writer::openFile(StringRef Path) { | 789 | void Writer::openFile(StringRef Path) { |
| 737 | Buffer = check( | 790 | Buffer = CHECK( |
| 738 | FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable), | 791 | FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable), |
| 739 | "failed to open " + Path); | 792 | "failed to open " + Path); |
| 740 | } | 793 | } |
| 741 | 794 | ||
| 742 | void Writer::fixSafeSEHSymbols() { | 795 | void Writer::createSEHTable(OutputSection *RData) { |
| 743 | if (!SEHTable) | 796 | // Create SEH table. x86-only. |
| 797 | if (Config->Machine != I386) | ||
| 798 | return; | ||
| 799 | |||
| 800 | std::set<Defined *> Handlers; | ||
| 801 | |||
| 802 | for (ObjFile *File : ObjFile::Instances) { | ||
| 803 | if (!File->SEHCompat) | ||
| 804 | return; | ||
| 805 | for (uint32_t I : File->SXData) | ||
| 806 | if (Symbol *B = File->getSymbol(I)) | ||
| 807 | if (B->isLive()) | ||
| 808 | Handlers.insert(cast<Defined>(B)); | ||
| 809 | } | ||
| 810 | |||
| 811 | if (Handlers.empty()) | ||
| 744 | return; | 812 | return; |
| 813 | |||
| 814 | SEHTable = make<SEHTableChunk>(Handlers); | ||
| 815 | RData->addChunk(SEHTable); | ||
| 816 | |||
| 745 | // Replace the absolute table symbol with a synthetic symbol pointing to the | 817 | // Replace the absolute table symbol with a synthetic symbol pointing to the |
| 746 | // SEHTable chunk so that we can emit base relocations for it and resolve | 818 | // SEHTable chunk so that we can emit base relocations for it and resolve |
| 747 | // section relative relocations. | 819 | // section relative relocations. |
| 748 | Symbol *T = Symtab->find("___safe_se_handler_table"); | 820 | Symbol *T = Symtab->find("___safe_se_handler_table"); |
| 749 | Symbol *C = Symtab->find("___safe_se_handler_count"); | 821 | Symbol *C = Symtab->find("___safe_se_handler_count"); |
| 750 | replaceBody<DefinedSynthetic>(T, T->body()->getName(), SEHTable); | 822 | replaceSymbol<DefinedSynthetic>(T, T->getName(), SEHTable); |
| 751 | cast<DefinedAbsolute>(C->body())->setVA(SEHTable->getSize() / 4); | 823 | cast<DefinedAbsolute>(C)->setVA(SEHTable->getSize() / 4); |
| 752 | } | 824 | } |
| 753 | 825 | ||
| 754 | // Handles /section options to allow users to overwrite | 826 | // Handles /section options to allow users to overwrite |
| ... | @@ -781,6 +853,25 @@ void Writer::writeSections() { | ... | @@ -781,6 +853,25 @@ void Writer::writeSections() { |
| 781 | } | 853 | } |
| 782 | } | 854 | } |
| 783 | 855 | ||
| 856 | void Writer::writeBuildId() { | ||
| 857 | // If we're not writing a build id (e.g. because /debug is not specified), | ||
| 858 | // then just return; | ||
| 859 | if (!Config->Debug) | ||
| 860 | return; | ||
| 861 | |||
| 862 | assert(BuildId && "BuildId is not set!"); | ||
| 863 | |||
| 864 | if (PreviousBuildId.hasValue()) { | ||
| 865 | *BuildId->BuildId = *PreviousBuildId; | ||
| 866 | BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1; | ||
| 867 | return; | ||
| 868 | } | ||
| 869 | |||
| 870 | BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70; | ||
| 871 | BuildId->BuildId->PDB70.Age = 1; | ||
| 872 | llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16); | ||
| 873 | } | ||
| 874 | |||
| 784 | // Sort .pdata section contents according to PE/COFF spec 5.5. | 875 | // Sort .pdata section contents according to PE/COFF spec 5.5. |
| 785 | void Writer::sortExceptionTable() { | 876 | void Writer::sortExceptionTable() { |
| 786 | OutputSection *Sec = findSection(".pdata"); | 877 | OutputSection *Sec = findSection(".pdata"); |
| ... | @@ -795,7 +886,7 @@ void Writer::sortExceptionTable() { | ... | @@ -795,7 +886,7 @@ void Writer::sortExceptionTable() { |
| 795 | [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; }); | 886 | [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; }); |
| 796 | return; | 887 | return; |
| 797 | } | 888 | } |
| 798 | if (Config->Machine == ARMNT) { | 889 | if (Config->Machine == ARMNT || Config->Machine == ARM64) { |
| 799 | struct Entry { ulittle32_t Begin, Unwind; }; | 890 | struct Entry { ulittle32_t Begin, Unwind; }; |
| 800 | sort(parallel::par, (Entry *)Begin, (Entry *)End, | 891 | sort(parallel::par, (Entry *)Begin, (Entry *)End, |
| 801 | [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; }); | 892 | [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; }); |
| ... | @@ -804,26 +895,6 @@ void Writer::sortExceptionTable() { | ... | @@ -804,26 +895,6 @@ void Writer::sortExceptionTable() { |
| 804 | errs() << "warning: don't know how to handle .pdata.\n"; | 895 | errs() << "warning: don't know how to handle .pdata.\n"; |
| 805 | } | 896 | } |
| 806 | 897 | ||
| 807 | // Backfill the CVSignature in a PDB70 Debug Record. This backfilling allows us | ||
| 808 | // to get reproducible builds. | ||
| 809 | void Writer::writeBuildId() { | ||
| 810 | // There is nothing to backfill if BuildId was not setup. | ||
| 811 | if (BuildId == nullptr) | ||
| 812 | return; | ||
| 813 | |||
| 814 | assert(BuildId->DI->Signature.CVSignature == OMF::Signature::PDB70 && | ||
| 815 | "only PDB 7.0 is supported"); | ||
| 816 | assert(sizeof(BuildId->DI->PDB70.Signature) == 16 && | ||
| 817 | "signature size mismatch"); | ||
| 818 | |||
| 819 | // Compute an MD5 hash. | ||
| 820 | ArrayRef<uint8_t> Buf(Buffer->getBufferStart(), Buffer->getBufferEnd()); | ||
| 821 | memcpy(BuildId->DI->PDB70.Signature, MD5::hash(Buf).data(), 16); | ||
| 822 | |||
| 823 | // TODO(compnerd) track the Age | ||
| 824 | BuildId->DI->PDB70.Age = 1; | ||
| 825 | } | ||
| 826 | |||
| 827 | OutputSection *Writer::findSection(StringRef Name) { | 898 | OutputSection *Writer::findSection(StringRef Name) { |
| 828 | for (OutputSection *Sec : OutputSections) | 899 | for (OutputSection *Sec : OutputSections) |
| 829 | if (Sec->getName() == Name) | 900 | if (Sec->getName() == Name) |
deps/lld/COFF/Writer.h+2-4| ... | @@ -18,11 +18,9 @@ | ... | @@ -18,11 +18,9 @@ |
| 18 | 18 | ||
| 19 | namespace lld { | 19 | namespace lld { |
| 20 | namespace coff { | 20 | namespace coff { |
| 21 | class SymbolTable; | ||
| 22 | |||
| 23 | static const int PageSize = 4096; | 21 | static const int PageSize = 4096; |
| 24 | 22 | ||
| 25 | void writeResult(SymbolTable *T); | 23 | void writeResult(); |
| 26 | 24 | ||
| 27 | // OutputSection represents a section in an output file. It's a | 25 | // OutputSection represents a section in an output file. It's a |
| 28 | // container of chunks. OutputSection and Chunk are 1:N relationship. | 26 | // container of chunks. OutputSection and Chunk are 1:N relationship. |
| ... | @@ -36,7 +34,7 @@ public: | ... | @@ -36,7 +34,7 @@ public: |
| 36 | void setFileOffset(uint64_t); | 34 | void setFileOffset(uint64_t); |
| 37 | void addChunk(Chunk *C); | 35 | void addChunk(Chunk *C); |
| 38 | llvm::StringRef getName() { return Name; } | 36 | llvm::StringRef getName() { return Name; } |
| 39 | std::vector<Chunk *> &getChunks() { return Chunks; } | 37 | ArrayRef<Chunk *> getChunks() { return Chunks; } |
| 40 | void addPermissions(uint32_t C); | 38 | void addPermissions(uint32_t C); |
| 41 | void setPermissions(uint32_t C); | 39 | void setPermissions(uint32_t C); |
| 42 | uint32_t getPermissions() { return Header.Characteristics & PermMask; } | 40 | uint32_t getPermissions() { return Header.Characteristics & PermMask; } |
deps/lld/Common/Args.cpp created+62| ... | @@ -0,0 +1,62 @@ | ||
| 1 | //===- Args.cpp -----------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "lld/Common/Args.h" | ||
| 11 | #include "lld/Common/ErrorHandler.h" | ||
| 12 | #include "llvm/ADT/SmallVector.h" | ||
| 13 | #include "llvm/ADT/StringExtras.h" | ||
| 14 | #include "llvm/ADT/StringRef.h" | ||
| 15 | #include "llvm/Option/ArgList.h" | ||
| 16 | |||
| 17 | using namespace llvm; | ||
| 18 | using namespace lld; | ||
| 19 | |||
| 20 | int lld::args::getInteger(opt::InputArgList &Args, unsigned Key, int Default) { | ||
| 21 | int V = Default; | ||
| 22 | if (auto *Arg = Args.getLastArg(Key)) { | ||
| 23 | StringRef S = Arg->getValue(); | ||
| 24 | if (!to_integer(S, V, 10)) | ||
| 25 | error(Arg->getSpelling() + ": number expected, but got '" + S + "'"); | ||
| 26 | } | ||
| 27 | return V; | ||
| 28 | } | ||
| 29 | |||
| 30 | std::vector<StringRef> lld::args::getStrings(opt::InputArgList &Args, int Id) { | ||
| 31 | std::vector<StringRef> V; | ||
| 32 | for (auto *Arg : Args.filtered(Id)) | ||
| 33 | V.push_back(Arg->getValue()); | ||
| 34 | return V; | ||
| 35 | } | ||
| 36 | |||
| 37 | uint64_t lld::args::getZOptionValue(opt::InputArgList &Args, int Id, | ||
| 38 | StringRef Key, uint64_t Default) { | ||
| 39 | for (auto *Arg : Args.filtered(Id)) { | ||
| 40 | std::pair<StringRef, StringRef> KV = StringRef(Arg->getValue()).split('='); | ||
| 41 | if (KV.first == Key) { | ||
| 42 | uint64_t Result = Default; | ||
| 43 | if (!to_integer(KV.second, Result)) | ||
| 44 | error("invalid " + Key + ": " + KV.second); | ||
| 45 | return Result; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | return Default; | ||
| 49 | } | ||
| 50 | |||
| 51 | std::vector<StringRef> lld::args::getLines(MemoryBufferRef MB) { | ||
| 52 | SmallVector<StringRef, 0> Arr; | ||
| 53 | MB.getBuffer().split(Arr, '\n'); | ||
| 54 | |||
| 55 | std::vector<StringRef> Ret; | ||
| 56 | for (StringRef S : Arr) { | ||
| 57 | S = S.trim(); | ||
| 58 | if (!S.empty() && S[0] != '#') | ||
| 59 | Ret.push_back(S); | ||
| 60 | } | ||
| 61 | return Ret; | ||
| 62 | } | ||
deps/lld/Common/CMakeLists.txt created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | if(NOT LLD_BUILT_STANDALONE) | ||
| 2 | set(tablegen_deps intrinsics_gen) | ||
| 3 | endif() | ||
| 4 | |||
| 5 | add_lld_library(lldCommon | ||
| 6 | Args.cpp | ||
| 7 | ErrorHandler.cpp | ||
| 8 | Memory.cpp | ||
| 9 | Reproduce.cpp | ||
| 10 | Strings.cpp | ||
| 11 | TargetOptionsCommandFlags.cpp | ||
| 12 | Threads.cpp | ||
| 13 | Version.cpp | ||
| 14 | |||
| 15 | ADDITIONAL_HEADER_DIRS | ||
| 16 | ${LLD_INCLUDE_DIR}/lld/Common | ||
| 17 | |||
| 18 | LINK_COMPONENTS | ||
| 19 | Codegen | ||
| 20 | Core | ||
| 21 | Demangle | ||
| 22 | MC | ||
| 23 | Option | ||
| 24 | Support | ||
| 25 | Target | ||
| 26 | |||
| 27 | LINK_LIBS | ||
| 28 | ${LLVM_PTHREAD_LIB} | ||
| 29 | |||
| 30 | DEPENDS | ||
| 31 | ${tablegen_deps} | ||
| 32 | ) | ||
deps/lld/Common/ErrorHandler.cpp created+118| ... | @@ -0,0 +1,118 @@ | ||
| 1 | //===- ErrorHandler.cpp ---------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "lld/Common/ErrorHandler.h" | ||
| 11 | |||
| 12 | #include "lld/Common/Threads.h" | ||
| 13 | |||
| 14 | #include "llvm/ADT/Twine.h" | ||
| 15 | #include "llvm/Support/Error.h" | ||
| 16 | #include "llvm/Support/ManagedStatic.h" | ||
| 17 | #include "llvm/Support/raw_ostream.h" | ||
| 18 | #include <mutex> | ||
| 19 | |||
| 20 | #if !defined(_MSC_VER) && !defined(__MINGW32__) | ||
| 21 | #include <unistd.h> | ||
| 22 | #endif | ||
| 23 | |||
| 24 | using namespace llvm; | ||
| 25 | using namespace lld; | ||
| 26 | |||
| 27 | // The functions defined in this file can be called from multiple threads, | ||
| 28 | // but outs() or errs() are not thread-safe. We protect them using a mutex. | ||
| 29 | static std::mutex Mu; | ||
| 30 | |||
| 31 | // Prints "\n" or does nothing, depending on Msg contents of | ||
| 32 | // the previous call of this function. | ||
| 33 | static void newline(raw_ostream *ErrorOS, const Twine &Msg) { | ||
| 34 | // True if the previous error message contained "\n". | ||
| 35 | // We want to separate multi-line error messages with a newline. | ||
| 36 | static bool Flag; | ||
| 37 | |||
| 38 | if (Flag) | ||
| 39 | *ErrorOS << "\n"; | ||
| 40 | Flag = StringRef(Msg.str()).contains('\n'); | ||
| 41 | } | ||
| 42 | |||
| 43 | ErrorHandler &lld::errorHandler() { | ||
| 44 | static ErrorHandler Handler; | ||
| 45 | return Handler; | ||
| 46 | } | ||
| 47 | |||
| 48 | void lld::exitLld(int Val) { | ||
| 49 | // Delete the output buffer so that any tempory file is deleted. | ||
| 50 | errorHandler().OutputBuffer.reset(); | ||
| 51 | |||
| 52 | // Dealloc/destroy ManagedStatic variables before calling | ||
| 53 | // _exit(). In a non-LTO build, this is a nop. In an LTO | ||
| 54 | // build allows us to get the output of -time-passes. | ||
| 55 | llvm_shutdown(); | ||
| 56 | |||
| 57 | outs().flush(); | ||
| 58 | errs().flush(); | ||
| 59 | _exit(Val); | ||
| 60 | } | ||
| 61 | |||
| 62 | void ErrorHandler::print(StringRef S, raw_ostream::Colors C) { | ||
| 63 | *ErrorOS << LogName << ": "; | ||
| 64 | if (ColorDiagnostics) { | ||
| 65 | ErrorOS->changeColor(C, true); | ||
| 66 | *ErrorOS << S; | ||
| 67 | ErrorOS->resetColor(); | ||
| 68 | } else { | ||
| 69 | *ErrorOS << S; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | void ErrorHandler::log(const Twine &Msg) { | ||
| 74 | if (Verbose) { | ||
| 75 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 76 | *ErrorOS << LogName << ": " << Msg << "\n"; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | void ErrorHandler::message(const Twine &Msg) { | ||
| 81 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 82 | outs() << Msg << "\n"; | ||
| 83 | outs().flush(); | ||
| 84 | } | ||
| 85 | |||
| 86 | void ErrorHandler::warn(const Twine &Msg) { | ||
| 87 | if (FatalWarnings) { | ||
| 88 | error(Msg); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | |||
| 92 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 93 | newline(ErrorOS, Msg); | ||
| 94 | print("warning: ", raw_ostream::MAGENTA); | ||
| 95 | *ErrorOS << Msg << "\n"; | ||
| 96 | } | ||
| 97 | |||
| 98 | void ErrorHandler::error(const Twine &Msg) { | ||
| 99 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 100 | newline(ErrorOS, Msg); | ||
| 101 | |||
| 102 | if (ErrorLimit == 0 || ErrorCount < ErrorLimit) { | ||
| 103 | print("error: ", raw_ostream::RED); | ||
| 104 | *ErrorOS << Msg << "\n"; | ||
| 105 | } else if (ErrorCount == ErrorLimit) { | ||
| 106 | print("error: ", raw_ostream::RED); | ||
| 107 | *ErrorOS << ErrorLimitExceededMsg << "\n"; | ||
| 108 | if (ExitEarly) | ||
| 109 | exitLld(1); | ||
| 110 | } | ||
| 111 | |||
| 112 | ++ErrorCount; | ||
| 113 | } | ||
| 114 | |||
| 115 | void ErrorHandler::fatal(const Twine &Msg) { | ||
| 116 | error(Msg); | ||
| 117 | exitLld(1); | ||
| 118 | } | ||
deps/lld/Common/Memory.cpp created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | //===- Memory.cpp ---------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "lld/Common/Memory.h" | ||
| 11 | |||
| 12 | using namespace llvm; | ||
| 13 | using namespace lld; | ||
| 14 | |||
| 15 | BumpPtrAllocator lld::BAlloc; | ||
| 16 | StringSaver lld::Saver{BAlloc}; | ||
| 17 | std::vector<SpecificAllocBase *> lld::SpecificAllocBase::Instances; | ||
| 18 | |||
| 19 | void lld::freeArena() { | ||
| 20 | for (SpecificAllocBase *Alloc : SpecificAllocBase::Instances) | ||
| 21 | Alloc->reset(); | ||
| 22 | BAlloc.Reset(); | ||
| 23 | } | ||
deps/lld/Common/Reproduce.cpp created+66| ... | @@ -0,0 +1,66 @@ | ||
| 1 | //===- Reproduce.cpp - Utilities for creating reproducers -----------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "lld/Common/Reproduce.h" | ||
| 11 | #include "llvm/Option/Arg.h" | ||
| 12 | #include "llvm/Support/Error.h" | ||
| 13 | #include "llvm/Support/FileSystem.h" | ||
| 14 | #include "llvm/Support/Path.h" | ||
| 15 | |||
| 16 | using namespace lld; | ||
| 17 | using namespace llvm; | ||
| 18 | using namespace llvm::sys; | ||
| 19 | |||
| 20 | // Makes a given pathname an absolute path first, and then remove | ||
| 21 | // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", | ||
| 22 | // assuming that the current directory is "/home/john/bar". | ||
| 23 | // 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. | ||
| 25 | std::string lld::relativeToRoot(StringRef Path) { | ||
| 26 | SmallString<128> Abs = Path; | ||
| 27 | if (fs::make_absolute(Abs)) | ||
| 28 | return Path; | ||
| 29 | path::remove_dots(Abs, /*remove_dot_dot=*/true); | ||
| 30 | |||
| 31 | // 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 part | ||
| 33 | // of the result. | ||
| 34 | SmallString<128> Res; | ||
| 35 | StringRef Root = path::root_name(Abs); | ||
| 36 | if (Root.endswith(":")) | ||
| 37 | Res = Root.drop_back(); | ||
| 38 | else if (Root.startswith("//")) | ||
| 39 | Res = Root.substr(2); | ||
| 40 | |||
| 41 | path::append(Res, path::relative_path(Abs)); | ||
| 42 | return path::convert_to_slash(Res); | ||
| 43 | } | ||
| 44 | |||
| 45 | // Quote a given string if it contains a space character. | ||
| 46 | std::string lld::quote(StringRef S) { | ||
| 47 | if (S.contains(' ')) | ||
| 48 | return ("\"" + S + "\"").str(); | ||
| 49 | return S; | ||
| 50 | } | ||
| 51 | |||
| 52 | std::string lld::rewritePath(StringRef S) { | ||
| 53 | if (fs::exists(S)) | ||
| 54 | return relativeToRoot(S); | ||
| 55 | return S; | ||
| 56 | } | ||
| 57 | |||
| 58 | std::string lld::toString(const opt::Arg &Arg) { | ||
| 59 | std::string K = Arg.getSpelling(); | ||
| 60 | if (Arg.getNumValues() == 0) | ||
| 61 | return K; | ||
| 62 | std::string V = quote(Arg.getValue()); | ||
| 63 | if (Arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle) | ||
| 64 | return K + V; | ||
| 65 | return K + " " + V; | ||
| 66 | } | ||
deps/lld/Common/Strings.cpp created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | //===- Strings.cpp -------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "lld/Common/Strings.h" | ||
| 11 | #include "llvm/Demangle/Demangle.h" | ||
| 12 | |||
| 13 | using namespace llvm; | ||
| 14 | using namespace lld; | ||
| 15 | |||
| 16 | // Returns the demangled C++ symbol name for Name. | ||
| 17 | Optional<std::string> lld::demangleItanium(StringRef Name) { | ||
| 18 | // itaniumDemangle can be used to demangle strings other than symbol | ||
| 19 | // names which do not necessarily start with "_Z". Name can be | ||
| 20 | // either a C or C++ symbol. Don't call itaniumDemangle if the name | ||
| 21 | // does not look like a C++ symbol name to avoid getting unexpected | ||
| 22 | // result for a C symbol that happens to match a mangled type name. | ||
| 23 | if (!Name.startswith("_Z")) | ||
| 24 | return None; | ||
| 25 | |||
| 26 | char *Buf = itaniumDemangle(Name.str().c_str(), nullptr, nullptr, nullptr); | ||
| 27 | if (!Buf) | ||
| 28 | return None; | ||
| 29 | std::string S(Buf); | ||
| 30 | free(Buf); | ||
| 31 | return S; | ||
| 32 | } | ||
deps/lld/Common/TargetOptionsCommandFlags.cpp created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | //===-- TargetOptionsCommandFlags.cpp ---------------------------*- 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 | // This file exists as a place for global variables defined in LLVM's | ||
| 11 | // CodeGen/CommandFlags.def. By putting the resulting object file in | ||
| 12 | // an archive and linking with it, the definitions will automatically be | ||
| 13 | // included when needed and skipped when already present. | ||
| 14 | // | ||
| 15 | //===----------------------------------------------------------------------===// | ||
| 16 | |||
| 17 | #include "lld/Common/TargetOptionsCommandFlags.h" | ||
| 18 | |||
| 19 | #include "llvm/CodeGen/CommandFlags.def" | ||
| 20 | #include "llvm/Target/TargetOptions.h" | ||
| 21 | |||
| 22 | // Define an externally visible version of | ||
| 23 | // InitTargetOptionsFromCodeGenFlags, so that its functionality can be | ||
| 24 | // used without having to include llvm/CodeGen/CommandFlags.def, which | ||
| 25 | // would lead to multiple definitions of the command line flags. | ||
| 26 | llvm::TargetOptions lld::InitTargetOptionsFromCodeGenFlags() { | ||
| 27 | return ::InitTargetOptionsFromCodeGenFlags(); | ||
| 28 | } | ||
| 29 | |||
| 30 | llvm::Optional<llvm::CodeModel::Model> lld::GetCodeModelFromCMModel() { | ||
| 31 | return getCodeModel(); | ||
| 32 | } | ||
deps/lld/Common/Threads.cpp created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | //===- Threads.cpp --------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "lld/Common/Threads.h" | ||
| 11 | |||
| 12 | bool lld::ThreadsEnabled = true; | ||
deps/lld/Common/Version.cpp created+43| ... | @@ -0,0 +1,43 @@ | ||
| 1 | //===- lib/Common/Version.cpp - LLD Version Number ---------------*- C++-=====// | ||
| 2 | // | ||
| 3 | // The LLVM Compiler Infrastructure | ||
| 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 defines several version-related utility functions for LLD. | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #include "lld/Common/Version.h" | ||
| 15 | |||
| 16 | using namespace llvm; | ||
| 17 | |||
| 18 | // Returns an SVN repository path, which is usually "trunk". | ||
| 19 | static 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. | ||
| 29 | static 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 | } | ||
| 39 | |||
| 40 | // Returns a version string, e.g., "LLD 4.0 (lld/trunk 284614)". | ||
| 41 | std::string lld::getLLDVersion() { | ||
| 42 | return "LLD " + std::string(LLD_VERSION_STRING) + getRepository(); | ||
| 43 | } | ||
deps/lld/ELF/AArch64ErrataFix.cpp created+648| ... | @@ -0,0 +1,648 @@ | ||
| 1 | //===- AArch64ErrataFix.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 | // This file implements Section Patching for the purpose of working around | ||
| 10 | // errata in CPUs. The general principle is that an erratum sequence of one or | ||
| 11 | // more instructions is detected in the instruction stream, one of the | ||
| 12 | // instructions in the sequence is replaced with a branch to a patch sequence | ||
| 13 | // of replacement instructions. At the end of the replacement sequence the | ||
| 14 | // patch branches back to the instruction stream. | ||
| 15 | |||
| 16 | // This technique is only suitable for fixing an erratum when: | ||
| 17 | // - There is a set of necessary conditions required to trigger the erratum that | ||
| 18 | // can be detected at static link time. | ||
| 19 | // - There is a set of replacement instructions that can be used to remove at | ||
| 20 | // least one of the necessary conditions that trigger the erratum. | ||
| 21 | // - We can overwrite an instruction in the erratum sequence with a branch to | ||
| 22 | // the replacement sequence. | ||
| 23 | // - We can place the replacement sequence within range of the branch. | ||
| 24 | |||
| 25 | // FIXME: | ||
| 26 | // - The implementation here only supports one patch, the AArch64 Cortex-53 | ||
| 27 | // errata 843419 that affects r0p0, r0p1, r0p2 and r0p4 versions of the core. | ||
| 28 | // To keep the initial version simple there is no support for multiple | ||
| 29 | // architectures or selection of different patches. | ||
| 30 | //===----------------------------------------------------------------------===// | ||
| 31 | |||
| 32 | #include "AArch64ErrataFix.h" | ||
| 33 | #include "Config.h" | ||
| 34 | #include "LinkerScript.h" | ||
| 35 | #include "OutputSections.h" | ||
| 36 | #include "Relocations.h" | ||
| 37 | #include "Strings.h" | ||
| 38 | #include "Symbols.h" | ||
| 39 | #include "SyntheticSections.h" | ||
| 40 | #include "Target.h" | ||
| 41 | #include "lld/Common/Memory.h" | ||
| 42 | |||
| 43 | #include "llvm/Support/Endian.h" | ||
| 44 | #include "llvm/Support/raw_ostream.h" | ||
| 45 | #include <algorithm> | ||
| 46 | |||
| 47 | using namespace llvm; | ||
| 48 | using namespace llvm::ELF; | ||
| 49 | using namespace llvm::object; | ||
| 50 | using namespace llvm::support::endian; | ||
| 51 | |||
| 52 | using namespace lld; | ||
| 53 | using namespace lld::elf; | ||
| 54 | |||
| 55 | // Helper functions to identify instructions and conditions needed to trigger | ||
| 56 | // the Cortex-A53-843419 erratum. | ||
| 57 | |||
| 58 | // ADRP | ||
| 59 | // | 1 | immlo (2) | 1 | 0 0 0 0 | immhi (19) | Rd (5) | | ||
| 60 | static bool isADRP(uint32_t Instr) { | ||
| 61 | return (Instr & 0x9f000000) == 0x90000000; | ||
| 62 | } | ||
| 63 | |||
| 64 | // Load and store bit patterns from ARMv8-A ARM ARM. | ||
| 65 | // Instructions appear in order of appearance starting from table in | ||
| 66 | // C4.1.3 Loads and Stores. | ||
| 67 | |||
| 68 | // 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) | | ||
| 70 | static bool isLoadStoreClass(uint32_t Instr) { | ||
| 71 | return (Instr & 0x0a000000) == 0x08000000; | ||
| 72 | } | ||
| 73 | |||
| 74 | // LDN/STN multiple no offset | ||
| 75 | // | 0 Q 00 | 1100 | 0 L 00 | 0000 | opcode (4) | size (2) | Rn (5) | Rt (5) | | ||
| 76 | // LDN/STN multiple post-indexed | ||
| 77 | // | 0 Q 00 | 1100 | 1 L 0 | Rm (5)| opcode (4) | size (2) | Rn (5) | Rt (5) | | ||
| 78 | // L == 0 for stores. | ||
| 79 | |||
| 80 | // Utility routine to decode opcode field of LDN/STN multiple structure | ||
| 81 | // instructions to find the ST1 instructions. | ||
| 82 | // opcode == 0010 ST1 4 registers. | ||
| 83 | // opcode == 0110 ST1 3 registers. | ||
| 84 | // opcode == 0111 ST1 1 register. | ||
| 85 | // opcode == 1010 ST1 2 registers. | ||
| 86 | static bool isST1MultipleOpcode(uint32_t Instr) { | ||
| 87 | return (Instr & 0x0000f000) == 0x00002000 || | ||
| 88 | (Instr & 0x0000f000) == 0x00006000 || | ||
| 89 | (Instr & 0x0000f000) == 0x00007000 || | ||
| 90 | (Instr & 0x0000f000) == 0x0000a000; | ||
| 91 | } | ||
| 92 | |||
| 93 | static bool isST1Multiple(uint32_t Instr) { | ||
| 94 | return (Instr & 0xbfff0000) == 0x0c000000 && isST1MultipleOpcode(Instr); | ||
| 95 | } | ||
| 96 | |||
| 97 | // Writes to Rn (writeback). | ||
| 98 | static bool isST1MultiplePost(uint32_t Instr) { | ||
| 99 | return (Instr & 0xbfe00000) == 0x0c800000 && isST1MultipleOpcode(Instr); | ||
| 100 | } | ||
| 101 | |||
| 102 | // LDN/STN single no offset | ||
| 103 | // | 0 Q 00 | 1101 | 0 L R 0 | 0000 | opc (3) S | size (2) | Rn (5) | Rt (5)| | ||
| 104 | // LDN/STN single post-indexed | ||
| 105 | // | 0 Q 00 | 1101 | 1 L R | Rm (5) | opc (3) S | size (2) | Rn (5) | Rt (5)| | ||
| 106 | // L == 0 for stores | ||
| 107 | |||
| 108 | // Utility routine to decode opcode field of LDN/STN single structure | ||
| 109 | // instructions to find the ST1 instructions. | ||
| 110 | // R == 0 for ST1 and ST3, R == 1 for ST2 and ST4. | ||
| 111 | // opcode == 000 ST1 8-bit. | ||
| 112 | // opcode == 010 ST1 16-bit. | ||
| 113 | // opcode == 100 ST1 32 or 64-bit (Size determines which). | ||
| 114 | static bool isST1SingleOpcode(uint32_t Instr) { | ||
| 115 | return (Instr & 0x0040e000) == 0x00000000 || | ||
| 116 | (Instr & 0x0040e000) == 0x00004000 || | ||
| 117 | (Instr & 0x0040e000) == 0x00008000; | ||
| 118 | } | ||
| 119 | |||
| 120 | static bool isST1Single(uint32_t Instr) { | ||
| 121 | return (Instr & 0xbfff0000) == 0x0d000000 && isST1SingleOpcode(Instr); | ||
| 122 | } | ||
| 123 | |||
| 124 | // Writes to Rn (writeback). | ||
| 125 | static bool isST1SinglePost(uint32_t Instr) { | ||
| 126 | return (Instr & 0xbfe00000) == 0x0d800000 && isST1SingleOpcode(Instr); | ||
| 127 | } | ||
| 128 | |||
| 129 | static bool isST1(uint32_t Instr) { | ||
| 130 | return isST1Multiple(Instr) || isST1MultiplePost(Instr) || | ||
| 131 | isST1Single(Instr) || isST1SinglePost(Instr); | ||
| 132 | } | ||
| 133 | |||
| 134 | // Load/store exclusive | ||
| 135 | // | size (2) 00 | 1000 | o2 L o1 | Rs (5) | o0 | Rt2 (5) | Rn (5) | Rt (5) | | ||
| 136 | // L == 0 for Stores. | ||
| 137 | static bool isLoadStoreExclusive(uint32_t Instr) { | ||
| 138 | return (Instr & 0x3f000000) == 0x08000000; | ||
| 139 | } | ||
| 140 | |||
| 141 | static bool isLoadExclusive(uint32_t Instr) { | ||
| 142 | return (Instr & 0x3f400000) == 0x08400000; | ||
| 143 | } | ||
| 144 | |||
| 145 | // Load register literal | ||
| 146 | // | opc (2) 01 | 1 V 00 | imm19 | Rt (5) | | ||
| 147 | static bool isLoadLiteral(uint32_t Instr) { | ||
| 148 | return (Instr & 0x3b000000) == 0x18000000; | ||
| 149 | } | ||
| 150 | |||
| 151 | // Load/store no-allocate pair | ||
| 152 | // (offset) | ||
| 153 | // | opc (2) 10 | 1 V 00 | 0 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) | | ||
| 154 | // L == 0 for stores. | ||
| 155 | // Never writes to register | ||
| 156 | static bool isSTNP(uint32_t Instr) { | ||
| 157 | return (Instr & 0x3bc00000) == 0x28000000; | ||
| 158 | } | ||
| 159 | |||
| 160 | // Load/store register pair | ||
| 161 | // (post-indexed) | ||
| 162 | // | 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/FP | ||
| 164 | // Writes to Rn. | ||
| 165 | static bool isSTPPost(uint32_t Instr) { | ||
| 166 | return (Instr & 0x3bc00000) == 0x28800000; | ||
| 167 | } | ||
| 168 | |||
| 169 | // (offset) | ||
| 170 | // | opc (2) 10 | 1 V 01 | 0 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) | | ||
| 171 | static bool isSTPOffset(uint32_t Instr) { | ||
| 172 | return (Instr & 0x3bc00000) == 0x29000000; | ||
| 173 | } | ||
| 174 | |||
| 175 | // (pre-index) | ||
| 176 | // | opc (2) 10 | 1 V 01 | 1 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) | | ||
| 177 | // Writes to Rn. | ||
| 178 | static bool isSTPPre(uint32_t Instr) { | ||
| 179 | return (Instr & 0x3bc00000) == 0x29800000; | ||
| 180 | } | ||
| 181 | |||
| 182 | static bool isSTP(uint32_t Instr) { | ||
| 183 | return isSTPPost(Instr) || isSTPOffset(Instr) || isSTPPre(Instr); | ||
| 184 | } | ||
| 185 | |||
| 186 | // Load/store register (unscaled immediate) | ||
| 187 | // | 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. | ||
| 189 | static bool isLoadStoreUnscaled(uint32_t Instr) { | ||
| 190 | return (Instr & 0x3b000c00) == 0x38000000; | ||
| 191 | } | ||
| 192 | |||
| 193 | // Load/store register (immediate post-indexed) | ||
| 194 | // | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 01 | Rn (5) | Rt (5) | | ||
| 195 | static bool isLoadStoreImmediatePost(uint32_t Instr) { | ||
| 196 | return (Instr & 0x3b200c00) == 0x38000400; | ||
| 197 | } | ||
| 198 | |||
| 199 | // Load/store register (unprivileged) | ||
| 200 | // | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 10 | Rn (5) | Rt (5) | | ||
| 201 | static bool isLoadStoreUnpriv(uint32_t Instr) { | ||
| 202 | return (Instr & 0x3b200c00) == 0x38000800; | ||
| 203 | } | ||
| 204 | |||
| 205 | // Load/store register (immediate pre-indexed) | ||
| 206 | // | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 11 | Rn (5) | Rt (5) | | ||
| 207 | static bool isLoadStoreImmediatePre(uint32_t Instr) { | ||
| 208 | return (Instr & 0x3b200c00) == 0x38000c00; | ||
| 209 | } | ||
| 210 | |||
| 211 | // Load/store register (register offset) | ||
| 212 | // | size (2) 11 | 1 V 00 | opc (2) 1 | Rm (5) | option (3) S | 10 | Rn | Rt | | ||
| 213 | static bool isLoadStoreRegisterOff(uint32_t Instr) { | ||
| 214 | return (Instr & 0x3b200c00) == 0x38200800; | ||
| 215 | } | ||
| 216 | |||
| 217 | // Load/store register (unsigned immediate) | ||
| 218 | // | size (2) 11 | 1 V 01 | opc (2) | imm12 | Rn (5) | Rt (5) | | ||
| 219 | static bool isLoadStoreRegisterUnsigned(uint32_t Instr) { | ||
| 220 | return (Instr & 0x3b000000) == 0x39000000; | ||
| 221 | } | ||
| 222 | |||
| 223 | // Rt is always in bit position 0 - 4. | ||
| 224 | static uint32_t getRt(uint32_t Instr) { return (Instr & 0x1f); } | ||
| 225 | |||
| 226 | // Rn is always in bit position 5 - 9. | ||
| 227 | static uint32_t getRn(uint32_t Instr) { return (Instr >> 5) & 0x1f; } | ||
| 228 | |||
| 229 | // C4.1.2 Branches, Exception Generating and System instructions | ||
| 230 | // | op0 (3) 1 | 01 op1 (4) | x (22) | | ||
| 231 | // op0 == 010 101 op1 == 0xxx Conditional Branch. | ||
| 232 | // op0 == 110 101 op1 == 1xxx Unconditional Branch Register. | ||
| 233 | // op0 == x00 101 op1 == xxxx Unconditional Branch immediate. | ||
| 234 | // op0 == x01 101 op1 == 0xxx Compare and branch immediate. | ||
| 235 | // op0 == x01 101 op1 == 1xxx Test and branch immediate. | ||
| 236 | static bool isBranch(uint32_t Instr) { | ||
| 237 | return ((Instr & 0xfe000000) == 0xd6000000) || // Cond branch. | ||
| 238 | ((Instr & 0xfe000000) == 0x54000000) || // Uncond branch reg. | ||
| 239 | ((Instr & 0x7c000000) == 0x14000000) || // Uncond branch imm. | ||
| 240 | ((Instr & 0x7c000000) == 0x34000000); // Compare and test branch. | ||
| 241 | } | ||
| 242 | |||
| 243 | static bool isV8SingleRegisterNonStructureLoadStore(uint32_t Instr) { | ||
| 244 | return isLoadStoreUnscaled(Instr) || isLoadStoreImmediatePost(Instr) || | ||
| 245 | isLoadStoreUnpriv(Instr) || isLoadStoreImmediatePre(Instr) || | ||
| 246 | isLoadStoreRegisterOff(Instr) || isLoadStoreRegisterUnsigned(Instr); | ||
| 247 | } | ||
| 248 | |||
| 249 | // 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 of | ||
| 251 | // the architecture such as the Atomic memory operations introduced | ||
| 252 | // in v8.1. | ||
| 253 | static bool isV8NonStructureLoad(uint32_t Instr) { | ||
| 254 | if (isLoadExclusive(Instr)) | ||
| 255 | return true; | ||
| 256 | if (isLoadLiteral(Instr)) | ||
| 257 | return true; | ||
| 258 | else if (isV8SingleRegisterNonStructureLoadStore(Instr)) { | ||
| 259 | // For Load and Store single register, Loads are derived from a | ||
| 260 | // combination of the Size, V and Opc fields. | ||
| 261 | uint32_t Size = (Instr >> 30) & 0xff; | ||
| 262 | uint32_t V = (Instr >> 26) & 0x1; | ||
| 263 | uint32_t Opc = (Instr >> 22) & 0x3; | ||
| 264 | // For the load and store instructions that we are decoding. | ||
| 265 | // Opc == 0 are all stores. | ||
| 266 | // 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 and | ||
| 268 | // Size == 11 (3), V == 0, Opc == 10 (2) which is a prefetch. | ||
| 269 | return Opc != 0 && !(Size == 0 && V == 1 && Opc == 2) && | ||
| 270 | !(Size == 3 && V == 0 && Opc == 2); | ||
| 271 | } | ||
| 272 | return false; | ||
| 273 | } | ||
| 274 | |||
| 275 | // The following decode instructions are only complete up to the instructions | ||
| 276 | // needed for errata 843419. | ||
| 277 | |||
| 278 | // Instruction with writeback updates the index register after the load/store. | ||
| 279 | static bool hasWriteback(uint32_t Instr) { | ||
| 280 | return isLoadStoreImmediatePre(Instr) || isLoadStoreImmediatePost(Instr) || | ||
| 281 | isSTPPre(Instr) || isSTPPost(Instr) || isST1SinglePost(Instr) || | ||
| 282 | isST1MultiplePost(Instr); | ||
| 283 | } | ||
| 284 | |||
| 285 | // 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 when | ||
| 287 | // the instruction has writeback. | ||
| 288 | static bool doesLoadStoreWriteToReg(uint32_t Instr, uint32_t Reg) { | ||
| 289 | return (isV8NonStructureLoad(Instr) && getRt(Instr) == Reg) || | ||
| 290 | (hasWriteback(Instr) && getRn(Instr) == Reg); | ||
| 291 | } | ||
| 292 | |||
| 293 | // Scanner for Cortex-A53 errata 843419 | ||
| 294 | // Full details are available in the Cortex A53 MPCore revision 0 Software | ||
| 295 | // Developers Errata Notice (ARM-EPM-048406). | ||
| 296 | // | ||
| 297 | // The instruction sequence that triggers the erratum is common in compiled | ||
| 298 | // AArch64 code, however it is sensitive to the offset of the sequence within | ||
| 299 | // a 4k page. This means that by scanning and fixing the patch after we have | ||
| 300 | // assigned addresses we only need to disassemble and fix instances of the | ||
| 301 | // sequence in the range of affected offsets. | ||
| 302 | // | ||
| 303 | // In summary the erratum conditions are a series of 4 instructions: | ||
| 304 | // 1.) An ADRP instruction that writes to register Rn with low 12 bits of | ||
| 305 | // address of instruction either 0xff8 or 0xffc. | ||
| 306 | // 2.) A load or store instruction that can be: | ||
| 307 | // - A single register load or store, of either integer or vector registers. | ||
| 308 | // - An STP or STNP, of either integer or vector registers. | ||
| 309 | // - An Advanced SIMD ST1 store instruction. | ||
| 310 | // - Must not write to Rn, but may optionally read from it. | ||
| 311 | // 3.) An optional instruction that is not a branch and does not write to Rn. | ||
| 312 | // 4.) A load or store from the Load/store register (unsigned immediate) class | ||
| 313 | // that uses Rn as the base address register. | ||
| 314 | // | ||
| 315 | // Note that we do not attempt to scan for Sequence 2 as described in the | ||
| 316 | // Software Developers Errata Notice as this has been assessed to be extremely | ||
| 317 | // unlikely to occur in compiled code. This matches gold and ld.bfd behavior. | ||
| 318 | |||
| 319 | // Return true if the Instruction sequence Adrp, Instr2, and Instr4 match | ||
| 320 | // the erratum sequence. The Adrp, Instr2 and Instr4 correspond to 1.), 2.), | ||
| 321 | // and 4.) in the Scanner for Cortex-A53 errata comment above. | ||
| 322 | static bool is843419ErratumSequence(uint32_t Instr1, uint32_t Instr2, | ||
| 323 | uint32_t Instr4) { | ||
| 324 | if (!isADRP(Instr1)) | ||
| 325 | return false; | ||
| 326 | |||
| 327 | uint32_t Rn = getRt(Instr1); | ||
| 328 | return isLoadStoreClass(Instr2) && | ||
| 329 | (isLoadStoreExclusive(Instr2) || isLoadLiteral(Instr2) || | ||
| 330 | isV8SingleRegisterNonStructureLoadStore(Instr2) || isSTP(Instr2) || | ||
| 331 | isSTNP(Instr2) || isST1(Instr2)) && | ||
| 332 | !doesLoadStoreWriteToReg(Instr2, Rn) && | ||
| 333 | isLoadStoreRegisterUnsigned(Instr4) && getRn(Instr4) == Rn; | ||
| 334 | } | ||
| 335 | |||
| 336 | // Scan the instruction sequence starting at Offset Off from the base of | ||
| 337 | // InputSection IS. We update Off in this function rather than in the caller as | ||
| 338 | // we can skip ahead much further into the section when we know how many | ||
| 339 | // instructions we've scanned. | ||
| 340 | // Return the offset of the load or store instruction in IS that we want to | ||
| 341 | // patch or 0 if no patch required. | ||
| 342 | static uint64_t scanCortexA53Errata843419(InputSection *IS, uint64_t &Off, | ||
| 343 | uint64_t Limit) { | ||
| 344 | uint64_t ISAddr = IS->getParent()->Addr + IS->OutSecOff; | ||
| 345 | |||
| 346 | // Advance Off so that (ISAddr + Off) modulo 0x1000 is at least 0xff8. | ||
| 347 | uint64_t InitialPageOff = (ISAddr + Off) & 0xfff; | ||
| 348 | if (InitialPageOff < 0xff8) | ||
| 349 | Off += 0xff8 - InitialPageOff; | ||
| 350 | |||
| 351 | bool OptionalAllowed = Limit - Off > 12; | ||
| 352 | if (Off >= Limit || Limit - Off < 12) { | ||
| 353 | // Need at least 3 4-byte sized instructions to trigger erratum. | ||
| 354 | Off = Limit; | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | uint64_t PatchOff = 0; | ||
| 359 | const uint8_t *Buf = IS->Data.begin(); | ||
| 360 | const uint32_t *InstBuf = reinterpret_cast<const uint32_t *>(Buf + Off); | ||
| 361 | uint32_t Instr1 = *InstBuf++; | ||
| 362 | uint32_t Instr2 = *InstBuf++; | ||
| 363 | uint32_t Instr3 = *InstBuf++; | ||
| 364 | if (is843419ErratumSequence(Instr1, Instr2, Instr3)) { | ||
| 365 | PatchOff = Off + 8; | ||
| 366 | } else if (OptionalAllowed && !isBranch(Instr3)) { | ||
| 367 | uint32_t Instr4 = *InstBuf++; | ||
| 368 | if (is843419ErratumSequence(Instr1, Instr2, Instr4)) | ||
| 369 | PatchOff = Off + 12; | ||
| 370 | } | ||
| 371 | if (((ISAddr + Off) & 0xfff) == 0xff8) | ||
| 372 | Off += 4; | ||
| 373 | else | ||
| 374 | Off += 0xffc; | ||
| 375 | return PatchOff; | ||
| 376 | } | ||
| 377 | |||
| 378 | class lld::elf::Patch843419Section : public SyntheticSection { | ||
| 379 | public: | ||
| 380 | Patch843419Section(InputSection *P, uint64_t Off); | ||
| 381 | |||
| 382 | void writeTo(uint8_t *Buf) override; | ||
| 383 | |||
| 384 | size_t getSize() const override { return 8; } | ||
| 385 | |||
| 386 | uint64_t getLDSTAddr() const; | ||
| 387 | |||
| 388 | // The Section we are patching. | ||
| 389 | const InputSection *Patchee; | ||
| 390 | // The offset of the instruction in the Patchee section we are patching. | ||
| 391 | uint64_t PatcheeOffset; | ||
| 392 | // A label for the start of the Patch that we can use as a relocation target. | ||
| 393 | Symbol *PatchSym; | ||
| 394 | }; | ||
| 395 | |||
| 396 | lld::elf::Patch843419Section::Patch843419Section(InputSection *P, uint64_t Off) | ||
| 397 | : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4, | ||
| 398 | ".text.patch"), | ||
| 399 | Patchee(P), PatcheeOffset(Off) { | ||
| 400 | this->Parent = P->getParent(); | ||
| 401 | PatchSym = addSyntheticLocal( | ||
| 402 | Saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0, | ||
| 403 | getSize(), *this); | ||
| 404 | addSyntheticLocal(Saver.save("$x"), STT_NOTYPE, 0, 0, *this); | ||
| 405 | } | ||
| 406 | |||
| 407 | uint64_t lld::elf::Patch843419Section::getLDSTAddr() const { | ||
| 408 | return Patchee->getParent()->Addr + Patchee->OutSecOff + PatcheeOffset; | ||
| 409 | } | ||
| 410 | |||
| 411 | void lld::elf::Patch843419Section::writeTo(uint8_t *Buf) { | ||
| 412 | // Copy the instruction that we will be replacing with a branch in the | ||
| 413 | // Patchee Section. | ||
| 414 | write32le(Buf, read32le(Patchee->Data.begin() + PatcheeOffset)); | ||
| 415 | |||
| 416 | // Apply any relocation transferred from the original PatcheeSection. | ||
| 417 | // For a SyntheticSection Buf already has OutSecOff added, but relocateAlloc | ||
| 418 | // also adds OutSecOff so we need to subtract to avoid double counting. | ||
| 419 | this->relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + getSize()); | ||
| 420 | |||
| 421 | // Return address is the next instruction after the one we have just copied. | ||
| 422 | uint64_t S = getLDSTAddr() + 4; | ||
| 423 | uint64_t P = PatchSym->getVA() + 4; | ||
| 424 | Target->relocateOne(Buf + 4, R_AARCH64_JUMP26, S - P); | ||
| 425 | } | ||
| 426 | |||
| 427 | void AArch64Err843419Patcher::init() { | ||
| 428 | // 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 the | ||
| 430 | // 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. | ||
| 432 | |||
| 433 | // 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 data | ||
| 435 | // 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 by | ||
| 437 | // the mapping symbol name, $x for code, $d for data. | ||
| 438 | auto IsCodeMapSymbol = [](const Symbol *B) { | ||
| 439 | return B->getName() == "$x" || B->getName().startswith("$x."); | ||
| 440 | }; | ||
| 441 | auto IsDataMapSymbol = [](const Symbol *B) { | ||
| 442 | return B->getName() == "$d" || B->getName().startswith("$d."); | ||
| 443 | }; | ||
| 444 | |||
| 445 | // Collect mapping symbols for every executable InputSection. | ||
| 446 | for (InputFile *File : ObjectFiles) { | ||
| 447 | auto *F = cast<ObjFile<ELF64LE>>(File); | ||
| 448 | for (Symbol *B : F->getLocalSymbols()) { | ||
| 449 | auto *Def = dyn_cast<Defined>(B); | ||
| 450 | if (!Def) | ||
| 451 | continue; | ||
| 452 | if (!IsCodeMapSymbol(Def) && !IsDataMapSymbol(Def)) | ||
| 453 | continue; | ||
| 454 | if (auto *Sec = dyn_cast<InputSection>(Def->Section)) | ||
| 455 | if (Sec->Flags & SHF_EXECINSTR) | ||
| 456 | SectionMap[Sec].push_back(Def); | ||
| 457 | } | ||
| 458 | } | ||
| 459 | // For each InputSection make sure the mapping symbols are in sorted in | ||
| 460 | // 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.0 | ||
| 462 | // $d.0 $d.1 $x.1. | ||
| 463 | for (auto &KV : SectionMap) { | ||
| 464 | std::vector<const Defined *> &MapSyms = KV.second; | ||
| 465 | if (MapSyms.size() <= 1) | ||
| 466 | continue; | ||
| 467 | std::stable_sort( | ||
| 468 | MapSyms.begin(), MapSyms.end(), | ||
| 469 | [](const Defined *A, const Defined *B) { return A->Value < B->Value; }); | ||
| 470 | MapSyms.erase( | ||
| 471 | std::unique(MapSyms.begin(), MapSyms.end(), | ||
| 472 | [=](const Defined *A, const Defined *B) { | ||
| 473 | return (IsCodeMapSymbol(A) && IsCodeMapSymbol(B)) || | ||
| 474 | (IsDataMapSymbol(A) && IsDataMapSymbol(B)); | ||
| 475 | }), | ||
| 476 | MapSyms.end()); | ||
| 477 | } | ||
| 478 | Initialized = true; | ||
| 479 | } | ||
| 480 | |||
| 481 | // Insert the PatchSections we have created back into the | ||
| 482 | // InputSectionDescription. As inserting patches alters the addresses of | ||
| 483 | // InputSections that follow them, we try and place the patches after all the | ||
| 484 | // executable sections, although we may need to insert them earlier if the | ||
| 485 | // InputSectionDescription is larger than the maximum branch range. | ||
| 486 | void AArch64Err843419Patcher::insertPatches( | ||
| 487 | InputSectionDescription &ISD, std::vector<Patch843419Section *> &Patches) { | ||
| 488 | uint64_t ISLimit; | ||
| 489 | uint64_t PrevISLimit = ISD.Sections.front()->OutSecOff; | ||
| 490 | uint64_t PatchUpperBound = PrevISLimit + Target->ThunkSectionSpacing; | ||
| 491 | |||
| 492 | // Set the OutSecOff of patches to the place where we want to insert them. | ||
| 493 | // We use a similar strategy to Thunk placement. Place patches roughly | ||
| 494 | // every multiple of maximum branch range. | ||
| 495 | auto PatchIt = Patches.begin(); | ||
| 496 | auto PatchEnd = Patches.end(); | ||
| 497 | for (const InputSection *IS : ISD.Sections) { | ||
| 498 | ISLimit = IS->OutSecOff + IS->getSize(); | ||
| 499 | if (ISLimit > PatchUpperBound) { | ||
| 500 | while (PatchIt != PatchEnd) { | ||
| 501 | if ((*PatchIt)->getLDSTAddr() >= PrevISLimit) | ||
| 502 | break; | ||
| 503 | (*PatchIt)->OutSecOff = PrevISLimit; | ||
| 504 | ++PatchIt; | ||
| 505 | } | ||
| 506 | PatchUpperBound = PrevISLimit + Target->ThunkSectionSpacing; | ||
| 507 | } | ||
| 508 | PrevISLimit = ISLimit; | ||
| 509 | } | ||
| 510 | for (; PatchIt != PatchEnd; ++PatchIt) { | ||
| 511 | (*PatchIt)->OutSecOff = ISLimit; | ||
| 512 | } | ||
| 513 | |||
| 514 | // merge all patch sections. We use the OutSecOff assigned above to | ||
| 515 | // determine the insertion point. This is ok as we only merge into an | ||
| 516 | // InputSectionDescription once per pass, and at the end of the pass | ||
| 517 | // assignAddresses() will recalculate all the OutSecOff values. | ||
| 518 | std::vector<InputSection *> Tmp; | ||
| 519 | Tmp.reserve(ISD.Sections.size() + Patches.size()); | ||
| 520 | auto MergeCmp = [](const InputSection *A, const InputSection *B) { | ||
| 521 | if (A->OutSecOff < B->OutSecOff) | ||
| 522 | return true; | ||
| 523 | if (A->OutSecOff == B->OutSecOff && isa<Patch843419Section>(A) && | ||
| 524 | !isa<Patch843419Section>(B)) | ||
| 525 | return true; | ||
| 526 | return false; | ||
| 527 | }; | ||
| 528 | std::merge(ISD.Sections.begin(), ISD.Sections.end(), Patches.begin(), | ||
| 529 | Patches.end(), std::back_inserter(Tmp), MergeCmp); | ||
| 530 | ISD.Sections = std::move(Tmp); | ||
| 531 | } | ||
| 532 | |||
| 533 | // Given an erratum sequence that starts at address AdrpAddr, with an | ||
| 534 | // instruction that we need to patch at PatcheeOffset from the start of | ||
| 535 | // InputSection IS, create a Patch843419 Section and add it to the | ||
| 536 | // Patches that we need to insert. | ||
| 537 | static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset, | ||
| 538 | InputSection *IS, | ||
| 539 | std::vector<Patch843419Section *> &Patches) { | ||
| 540 | // There may be a relocation at the same offset that we are patching. There | ||
| 541 | // are three cases that we need to consider. | ||
| 542 | // Case 1: R_AARCH64_JUMP26 branch relocation. We have already patched this | ||
| 543 | // instance of the erratum on a previous patch and altered the relocation. We | ||
| 544 | // have nothing more to do. | ||
| 545 | // Case 2: A load/store register (unsigned immediate) class relocation. There | ||
| 546 | // are two of these R_AARCH_LD64_ABS_LO12_NC and R_AARCH_LD64_GOT_LO12_NC and | ||
| 547 | // they are both absolute. We need to add the same relocation to the patch, | ||
| 548 | // and replace the relocation with a R_AARCH_JUMP26 branch relocation. | ||
| 549 | // Case 3: No relocation. We must create a new R_AARCH64_JUMP26 branch | ||
| 550 | // relocation at the offset. | ||
| 551 | auto RelIt = std::find_if( | ||
| 552 | IS->Relocations.begin(), IS->Relocations.end(), | ||
| 553 | [=](const Relocation &R) { return R.Offset == PatcheeOffset; }); | ||
| 554 | if (RelIt != IS->Relocations.end() && RelIt->Type == R_AARCH64_JUMP26) | ||
| 555 | return; | ||
| 556 | |||
| 557 | if (Config->Verbose) | ||
| 558 | message("detected cortex-a53-843419 erratum sequence starting at " + | ||
| 559 | utohexstr(AdrpAddr) + " in unpatched output."); | ||
| 560 | |||
| 561 | auto *PS = make<Patch843419Section>(IS, PatcheeOffset); | ||
| 562 | Patches.push_back(PS); | ||
| 563 | |||
| 564 | auto MakeRelToPatch = [](uint64_t Offset, Symbol *PatchSym) { | ||
| 565 | return Relocation{R_PC, R_AARCH64_JUMP26, Offset, 0, PatchSym}; | ||
| 566 | }; | ||
| 567 | |||
| 568 | if (RelIt != IS->Relocations.end()) { | ||
| 569 | PS->Relocations.push_back( | ||
| 570 | {RelIt->Expr, RelIt->Type, 0, RelIt->Addend, RelIt->Sym}); | ||
| 571 | *RelIt = MakeRelToPatch(PatcheeOffset, PS->PatchSym); | ||
| 572 | } else | ||
| 573 | IS->Relocations.push_back(MakeRelToPatch(PatcheeOffset, PS->PatchSym)); | ||
| 574 | } | ||
| 575 | |||
| 576 | // Scan all the instructions in InputSectionDescription, for each instance of | ||
| 577 | // the erratum sequence create a Patch843419Section. We return the list of | ||
| 578 | // Patch843419Sections that need to be applied to ISD. | ||
| 579 | std::vector<Patch843419Section *> | ||
| 580 | AArch64Err843419Patcher::patchInputSectionDescription( | ||
| 581 | InputSectionDescription &ISD) { | ||
| 582 | std::vector<Patch843419Section *> Patches; | ||
| 583 | for (InputSection *IS : ISD.Sections) { | ||
| 584 | // LLD doesn't use the erratum sequence in SyntheticSections. | ||
| 585 | if (isa<SyntheticSection>(IS)) | ||
| 586 | continue; | ||
| 587 | // Use SectionMap to make sure we only scan code and not inline data. | ||
| 588 | // We have already sorted MapSyms in ascending order and removed consecutive | ||
| 589 | // mapping symbols of the same type. Our range of executable instructions to | ||
| 590 | // scan is therefore [CodeSym->Value, DataSym->Value) or [CodeSym->Value, | ||
| 591 | // section size). | ||
| 592 | std::vector<const Defined *> &MapSyms = SectionMap[IS]; | ||
| 593 | |||
| 594 | auto CodeSym = llvm::find_if(MapSyms, [&](const Defined *MS) { | ||
| 595 | return MS->getName().startswith("$x"); | ||
| 596 | }); | ||
| 597 | |||
| 598 | while (CodeSym != MapSyms.end()) { | ||
| 599 | auto DataSym = std::next(CodeSym); | ||
| 600 | uint64_t Off = (*CodeSym)->Value; | ||
| 601 | uint64_t Limit = | ||
| 602 | (DataSym == MapSyms.end()) ? IS->Data.size() : (*DataSym)->Value; | ||
| 603 | |||
| 604 | while (Off < Limit) { | ||
| 605 | uint64_t StartAddr = IS->getParent()->Addr + IS->OutSecOff + Off; | ||
| 606 | if (uint64_t PatcheeOffset = scanCortexA53Errata843419(IS, Off, Limit)) | ||
| 607 | implementPatch(StartAddr, PatcheeOffset, IS, Patches); | ||
| 608 | } | ||
| 609 | if (DataSym == MapSyms.end()) | ||
| 610 | break; | ||
| 611 | CodeSym = std::next(DataSym); | ||
| 612 | } | ||
| 613 | } | ||
| 614 | return Patches; | ||
| 615 | } | ||
| 616 | |||
| 617 | // For each InputSectionDescription make one pass over the executable sections | ||
| 618 | // looking for the erratum sequence; creating a synthetic Patch843419Section | ||
| 619 | // for each instance found. We insert these synthetic patch sections after the | ||
| 620 | // executable code in each InputSectionDescription. | ||
| 621 | // | ||
| 622 | // PreConditions: | ||
| 623 | // The Output and Input Sections have had their final addresses assigned. | ||
| 624 | // | ||
| 625 | // PostConditions: | ||
| 626 | // Returns true if at least one patch was added. The addresses of the | ||
| 627 | // Ouptut and Input Sections may have been changed. | ||
| 628 | // Returns false if no patches were required and no changes were made. | ||
| 629 | bool AArch64Err843419Patcher::createFixes() { | ||
| 630 | if (Initialized == false) | ||
| 631 | init(); | ||
| 632 | |||
| 633 | bool AddressesChanged = false; | ||
| 634 | for (OutputSection *OS : OutputSections) { | ||
| 635 | if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) | ||
| 636 | continue; | ||
| 637 | for (BaseCommand *BC : OS->SectionCommands) | ||
| 638 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) { | ||
| 639 | std::vector<Patch843419Section *> Patches = | ||
| 640 | patchInputSectionDescription(*ISD); | ||
| 641 | if (!Patches.empty()) { | ||
| 642 | insertPatches(*ISD, Patches); | ||
| 643 | AddressesChanged = true; | ||
| 644 | } | ||
| 645 | } | ||
| 646 | } | ||
| 647 | return AddressesChanged; | ||
| 648 | } | ||
deps/lld/ELF/AArch64ErrataFix.h created+52| ... | @@ -0,0 +1,52 @@ | ||
| 1 | //===- AArch64ErrataFix.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_AARCH64ERRATAFIX_H | ||
| 11 | #define LLD_ELF_AARCH64ERRATAFIX_H | ||
| 12 | |||
| 13 | #include "lld/Common/LLVM.h" | ||
| 14 | |||
| 15 | #include <map> | ||
| 16 | #include <vector> | ||
| 17 | |||
| 18 | namespace lld { | ||
| 19 | namespace elf { | ||
| 20 | |||
| 21 | class Defined; | ||
| 22 | class InputSection; | ||
| 23 | struct InputSectionDescription; | ||
| 24 | class OutputSection; | ||
| 25 | class Patch843419Section; | ||
| 26 | |||
| 27 | class AArch64Err843419Patcher { | ||
| 28 | public: | ||
| 29 | // return true if Patches have been added to the OutputSections. | ||
| 30 | bool createFixes(); | ||
| 31 | |||
| 32 | private: | ||
| 33 | std::vector<Patch843419Section *> | ||
| 34 | patchInputSectionDescription(InputSectionDescription &ISD); | ||
| 35 | |||
| 36 | void insertPatches(InputSectionDescription &ISD, | ||
| 37 | std::vector<Patch843419Section *> &Patches); | ||
| 38 | |||
| 39 | void init(); | ||
| 40 | |||
| 41 | // A cache of the mapping symbols defined by the InputSecion sorted in order | ||
| 42 | // of ascending value with redundant symbols removed. These describe | ||
| 43 | // the ranges of code and data in an executable InputSection. | ||
| 44 | std::map<InputSection *, std::vector<const Defined *>> SectionMap; | ||
| 45 | |||
| 46 | bool Initialized = false; | ||
| 47 | }; | ||
| 48 | |||
| 49 | } // namespace elf | ||
| 50 | } // namespace lld | ||
| 51 | |||
| 52 | #endif | ||
deps/lld/ELF/Arch/AArch64.cpp+72-22| ... | @@ -7,11 +7,11 @@ | ... | @@ -7,11 +7,11 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "Symbols.h" | 10 | #include "Symbols.h" |
| 12 | #include "SyntheticSections.h" | 11 | #include "SyntheticSections.h" |
| 13 | #include "Target.h" | 12 | #include "Target.h" |
| 14 | #include "Thunks.h" | 13 | #include "Thunks.h" |
| 14 | #include "lld/Common/ErrorHandler.h" | ||
| 15 | #include "llvm/Object/ELF.h" | 15 | #include "llvm/Object/ELF.h" |
| 16 | #include "llvm/Support/Endian.h" | 16 | #include "llvm/Support/Endian.h" |
| 17 | 17 | ||
| ... | @@ -32,20 +32,23 @@ namespace { | ... | @@ -32,20 +32,23 @@ namespace { |
| 32 | class AArch64 final : public TargetInfo { | 32 | class AArch64 final : public TargetInfo { |
| 33 | public: | 33 | public: |
| 34 | AArch64(); | 34 | AArch64(); |
| 35 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 35 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 36 | const uint8_t *Loc) const override; | 36 | const uint8_t *Loc) const override; |
| 37 | bool isPicRel(uint32_t Type) const override; | 37 | bool isPicRel(RelType Type) const override; |
| 38 | void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; | 38 | void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; |
| 39 | void writePltHeader(uint8_t *Buf) const override; | 39 | void writePltHeader(uint8_t *Buf) const override; |
| 40 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | 40 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, |
| 41 | int32_t Index, unsigned RelOff) const override; | 41 | int32_t Index, unsigned RelOff) const override; |
| 42 | bool usesOnlyLowPageBits(uint32_t Type) const override; | 42 | bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 43 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 43 | uint64_t BranchAddr, const Symbol &S) const override; |
| 44 | RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | 44 | bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; |
| 45 | bool usesOnlyLowPageBits(RelType Type) const override; | ||
| 46 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; | ||
| 47 | RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, | ||
| 45 | RelExpr Expr) const override; | 48 | RelExpr Expr) const override; |
| 46 | void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 49 | void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 47 | void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 50 | void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 48 | void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 51 | void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 49 | }; | 52 | }; |
| 50 | } // namespace | 53 | } // namespace |
| 51 | 54 | ||
| ... | @@ -66,13 +69,17 @@ AArch64::AArch64() { | ... | @@ -66,13 +69,17 @@ AArch64::AArch64() { |
| 66 | // It doesn't seem to be documented anywhere, but tls on aarch64 uses variant | 69 | // It doesn't seem to be documented anywhere, but tls on aarch64 uses variant |
| 67 | // 1 of the tls structures and the tcb size is 16. | 70 | // 1 of the tls structures and the tcb size is 16. |
| 68 | TcbSize = 16; | 71 | TcbSize = 16; |
| 72 | NeedsThunks = true; | ||
| 73 | |||
| 74 | // See comment in Arch/ARM.cpp for a more detailed explanation of | ||
| 75 | // ThunkSectionSpacing. For AArch64 the only branches we are permitted to | ||
| 76 | // Thunk have a range of +/- 128 MiB | ||
| 77 | ThunkSectionSpacing = (128 * 1024 * 1024) - 0x30000; | ||
| 69 | } | 78 | } |
| 70 | 79 | ||
| 71 | RelExpr AArch64::getRelExpr(uint32_t Type, const SymbolBody &S, | 80 | RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S, |
| 72 | const uint8_t *Loc) const { | 81 | const uint8_t *Loc) const { |
| 73 | switch (Type) { | 82 | switch (Type) { |
| 74 | default: | ||
| 75 | return R_ABS; | ||
| 76 | case R_AARCH64_TLSDESC_ADR_PAGE21: | 83 | case R_AARCH64_TLSDESC_ADR_PAGE21: |
| 77 | return R_TLSDESC_PAGE; | 84 | return R_TLSDESC_PAGE; |
| 78 | case R_AARCH64_TLSDESC_LD64_LO12: | 85 | case R_AARCH64_TLSDESC_LD64_LO12: |
| ... | @@ -92,6 +99,7 @@ RelExpr AArch64::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -92,6 +99,7 @@ RelExpr AArch64::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 92 | case R_AARCH64_PREL32: | 99 | case R_AARCH64_PREL32: |
| 93 | case R_AARCH64_PREL64: | 100 | case R_AARCH64_PREL64: |
| 94 | case R_AARCH64_ADR_PREL_LO21: | 101 | case R_AARCH64_ADR_PREL_LO21: |
| 102 | case R_AARCH64_LD_PREL_LO19: | ||
| 95 | return R_PC; | 103 | return R_PC; |
| 96 | case R_AARCH64_ADR_PREL_PG_HI21: | 104 | case R_AARCH64_ADR_PREL_PG_HI21: |
| 97 | return R_PAGE_PC; | 105 | return R_PAGE_PC; |
| ... | @@ -103,10 +111,12 @@ RelExpr AArch64::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -103,10 +111,12 @@ RelExpr AArch64::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 103 | return R_GOT_PAGE_PC; | 111 | return R_GOT_PAGE_PC; |
| 104 | case R_AARCH64_NONE: | 112 | case R_AARCH64_NONE: |
| 105 | return R_NONE; | 113 | return R_NONE; |
| 114 | default: | ||
| 115 | return R_ABS; | ||
| 106 | } | 116 | } |
| 107 | } | 117 | } |
| 108 | 118 | ||
| 109 | RelExpr AArch64::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | 119 | RelExpr AArch64::adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 110 | RelExpr Expr) const { | 120 | RelExpr Expr) const { |
| 111 | if (Expr == R_RELAX_TLS_GD_TO_IE) { | 121 | if (Expr == R_RELAX_TLS_GD_TO_IE) { |
| 112 | if (Type == R_AARCH64_TLSDESC_ADR_PAGE21) | 122 | if (Type == R_AARCH64_TLSDESC_ADR_PAGE21) |
| ... | @@ -116,7 +126,7 @@ RelExpr AArch64::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | ... | @@ -116,7 +126,7 @@ RelExpr AArch64::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, |
| 116 | return Expr; | 126 | return Expr; |
| 117 | } | 127 | } |
| 118 | 128 | ||
| 119 | bool AArch64::usesOnlyLowPageBits(uint32_t Type) const { | 129 | bool AArch64::usesOnlyLowPageBits(RelType Type) const { |
| 120 | switch (Type) { | 130 | switch (Type) { |
| 121 | default: | 131 | default: |
| 122 | return false; | 132 | return false; |
| ... | @@ -134,11 +144,11 @@ bool AArch64::usesOnlyLowPageBits(uint32_t Type) const { | ... | @@ -134,11 +144,11 @@ bool AArch64::usesOnlyLowPageBits(uint32_t Type) const { |
| 134 | } | 144 | } |
| 135 | } | 145 | } |
| 136 | 146 | ||
| 137 | bool AArch64::isPicRel(uint32_t Type) const { | 147 | bool AArch64::isPicRel(RelType Type) const { |
| 138 | return Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64; | 148 | return Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64; |
| 139 | } | 149 | } |
| 140 | 150 | ||
| 141 | void AArch64::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { | 151 | void AArch64::writeGotPlt(uint8_t *Buf, const Symbol &) const { |
| 142 | write64le(Buf, InX::Plt->getVA()); | 152 | write64le(Buf, InX::Plt->getVA()); |
| 143 | } | 153 | } |
| 144 | 154 | ||
| ... | @@ -180,6 +190,31 @@ void AArch64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ... | @@ -180,6 +190,31 @@ void AArch64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 180 | relocateOne(Buf + 8, R_AARCH64_ADD_ABS_LO12_NC, GotPltEntryAddr); | 190 | relocateOne(Buf + 8, R_AARCH64_ADD_ABS_LO12_NC, GotPltEntryAddr); |
| 181 | } | 191 | } |
| 182 | 192 | ||
| 193 | bool AArch64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, | ||
| 194 | uint64_t BranchAddr, const Symbol &S) const { | ||
| 195 | // ELF for the ARM 64-bit architecture, section Call and Jump relocations | ||
| 196 | // only permits range extension thunks for R_AARCH64_CALL26 and | ||
| 197 | // R_AARCH64_JUMP26 relocation types. | ||
| 198 | if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) | ||
| 199 | return false; | ||
| 200 | uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); | ||
| 201 | return !inBranchRange(Type, BranchAddr, Dst); | ||
| 202 | } | ||
| 203 | |||
| 204 | bool AArch64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { | ||
| 205 | if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) | ||
| 206 | return true; | ||
| 207 | // The AArch64 call and unconditional branch instructions have a range of | ||
| 208 | // +/- 128 MiB. | ||
| 209 | uint64_t Range = 128 * 1024 * 1024; | ||
| 210 | if (Dst > Src) { | ||
| 211 | // Immediate of branch is signed. | ||
| 212 | Range -= 4; | ||
| 213 | return Dst - Src <= Range; | ||
| 214 | } | ||
| 215 | return Src - Dst <= Range; | ||
| 216 | } | ||
| 217 | |||
| 183 | static void write32AArch64Addr(uint8_t *L, uint64_t Imm) { | 218 | static void write32AArch64Addr(uint8_t *L, uint64_t Imm) { |
| 184 | uint32_t ImmLo = (Imm & 0x3) << 29; | 219 | uint32_t ImmLo = (Imm & 0x3) << 29; |
| 185 | uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; | 220 | uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; |
| ... | @@ -201,7 +236,7 @@ static void or32AArch64Imm(uint8_t *L, uint64_t Imm) { | ... | @@ -201,7 +236,7 @@ static void or32AArch64Imm(uint8_t *L, uint64_t Imm) { |
| 201 | or32le(L, (Imm & 0xFFF) << 10); | 236 | or32le(L, (Imm & 0xFFF) << 10); |
| 202 | } | 237 | } |
| 203 | 238 | ||
| 204 | void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 239 | void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 205 | switch (Type) { | 240 | switch (Type) { |
| 206 | case R_AARCH64_ABS16: | 241 | case R_AARCH64_ABS16: |
| 207 | case R_AARCH64_PREL16: | 242 | case R_AARCH64_PREL16: |
| ... | @@ -232,12 +267,23 @@ void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -232,12 +267,23 @@ void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 232 | checkInt<21>(Loc, Val, Type); | 267 | checkInt<21>(Loc, Val, Type); |
| 233 | write32AArch64Addr(Loc, Val); | 268 | write32AArch64Addr(Loc, Val); |
| 234 | break; | 269 | break; |
| 235 | case R_AARCH64_CALL26: | ||
| 236 | case R_AARCH64_JUMP26: | 270 | case R_AARCH64_JUMP26: |
| 271 | // Normally we would just write the bits of the immediate field, however | ||
| 272 | // when patching instructions for the cpu errata fix -fix-cortex-a53-843419 | ||
| 273 | // we want to replace a non-branch instruction with a branch immediate | ||
| 274 | // instruction. By writing all the bits of the instruction including the | ||
| 275 | // opcode and the immediate (0 001 | 01 imm26) we can do this | ||
| 276 | // transformation by placing a R_AARCH64_JUMP26 relocation at the offset of | ||
| 277 | // the instruction we want to patch. | ||
| 278 | write32le(Loc, 0x14000000); | ||
| 279 | LLVM_FALLTHROUGH; | ||
| 280 | case R_AARCH64_CALL26: | ||
| 237 | checkInt<28>(Loc, Val, Type); | 281 | checkInt<28>(Loc, Val, Type); |
| 238 | or32le(Loc, (Val & 0x0FFFFFFC) >> 2); | 282 | or32le(Loc, (Val & 0x0FFFFFFC) >> 2); |
| 239 | break; | 283 | break; |
| 240 | case R_AARCH64_CONDBR19: | 284 | case R_AARCH64_CONDBR19: |
| 285 | case R_AARCH64_LD_PREL_LO19: | ||
| 286 | checkAlignment<4>(Loc, Val, Type); | ||
| 241 | checkInt<21>(Loc, Val, Type); | 287 | checkInt<21>(Loc, Val, Type); |
| 242 | or32le(Loc, (Val & 0x1FFFFC) << 3); | 288 | or32le(Loc, (Val & 0x1FFFFC) << 3); |
| 243 | break; | 289 | break; |
| ... | @@ -251,15 +297,19 @@ void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -251,15 +297,19 @@ void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 251 | or32AArch64Imm(Loc, getBits(Val, 0, 11)); | 297 | or32AArch64Imm(Loc, getBits(Val, 0, 11)); |
| 252 | break; | 298 | break; |
| 253 | case R_AARCH64_LDST16_ABS_LO12_NC: | 299 | case R_AARCH64_LDST16_ABS_LO12_NC: |
| 300 | checkAlignment<2>(Loc, Val, Type); | ||
| 254 | or32AArch64Imm(Loc, getBits(Val, 1, 11)); | 301 | or32AArch64Imm(Loc, getBits(Val, 1, 11)); |
| 255 | break; | 302 | break; |
| 256 | case R_AARCH64_LDST32_ABS_LO12_NC: | 303 | case R_AARCH64_LDST32_ABS_LO12_NC: |
| 304 | checkAlignment<4>(Loc, Val, Type); | ||
| 257 | or32AArch64Imm(Loc, getBits(Val, 2, 11)); | 305 | or32AArch64Imm(Loc, getBits(Val, 2, 11)); |
| 258 | break; | 306 | break; |
| 259 | case R_AARCH64_LDST64_ABS_LO12_NC: | 307 | case R_AARCH64_LDST64_ABS_LO12_NC: |
| 308 | checkAlignment<8>(Loc, Val, Type); | ||
| 260 | or32AArch64Imm(Loc, getBits(Val, 3, 11)); | 309 | or32AArch64Imm(Loc, getBits(Val, 3, 11)); |
| 261 | break; | 310 | break; |
| 262 | case R_AARCH64_LDST128_ABS_LO12_NC: | 311 | case R_AARCH64_LDST128_ABS_LO12_NC: |
| 312 | checkAlignment<16>(Loc, Val, Type); | ||
| 263 | or32AArch64Imm(Loc, getBits(Val, 4, 11)); | 313 | or32AArch64Imm(Loc, getBits(Val, 4, 11)); |
| 264 | break; | 314 | break; |
| 265 | case R_AARCH64_MOVW_UABS_G0_NC: | 315 | case R_AARCH64_MOVW_UABS_G0_NC: |
| ... | @@ -291,7 +341,7 @@ void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -291,7 +341,7 @@ void AArch64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 291 | } | 341 | } |
| 292 | } | 342 | } |
| 293 | 343 | ||
| 294 | void AArch64::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 344 | void AArch64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 295 | // TLSDESC Global-Dynamic relocation are in the form: | 345 | // TLSDESC Global-Dynamic relocation are in the form: |
| 296 | // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] | 346 | // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] |
| 297 | // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12] | 347 | // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12] |
| ... | @@ -321,7 +371,7 @@ void AArch64::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -321,7 +371,7 @@ void AArch64::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 321 | } | 371 | } |
| 322 | } | 372 | } |
| 323 | 373 | ||
| 324 | void AArch64::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 374 | void AArch64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 325 | // TLSDESC Global-Dynamic relocation are in the form: | 375 | // TLSDESC Global-Dynamic relocation are in the form: |
| 326 | // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] | 376 | // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] |
| 327 | // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12] | 377 | // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12] |
| ... | @@ -352,7 +402,7 @@ void AArch64::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -352,7 +402,7 @@ void AArch64::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 352 | } | 402 | } |
| 353 | } | 403 | } |
| 354 | 404 | ||
| 355 | void AArch64::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 405 | void AArch64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 356 | checkUInt<32>(Loc, Val, Type); | 406 | checkUInt<32>(Loc, Val, Type); |
| 357 | 407 | ||
| 358 | if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) { | 408 | if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) { |
deps/lld/ELF/Arch/AMDGPU.cpp+26-8| ... | @@ -7,10 +7,10 @@ | ... | @@ -7,10 +7,10 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "InputFiles.h" | 10 | #include "InputFiles.h" |
| 12 | #include "Symbols.h" | 11 | #include "Symbols.h" |
| 13 | #include "Target.h" | 12 | #include "Target.h" |
| 13 | #include "lld/Common/ErrorHandler.h" | ||
| 14 | #include "llvm/Object/ELF.h" | 14 | #include "llvm/Object/ELF.h" |
| 15 | #include "llvm/Support/Endian.h" | 15 | #include "llvm/Support/Endian.h" |
| 16 | 16 | ||
| ... | @@ -25,19 +25,38 @@ namespace { | ... | @@ -25,19 +25,38 @@ namespace { |
| 25 | class AMDGPU final : public TargetInfo { | 25 | class AMDGPU final : public TargetInfo { |
| 26 | public: | 26 | public: |
| 27 | AMDGPU(); | 27 | AMDGPU(); |
| 28 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 28 | uint32_t calcEFlags() const override; |
| 29 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 29 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 30 | RelExpr getRelExpr(RelType Type, const Symbol &S, | ||
| 30 | const uint8_t *Loc) const override; | 31 | const uint8_t *Loc) const override; |
| 31 | }; | 32 | }; |
| 32 | } // namespace | 33 | } // namespace |
| 33 | 34 | ||
| 34 | AMDGPU::AMDGPU() { | 35 | AMDGPU::AMDGPU() { |
| 35 | RelativeRel = R_AMDGPU_REL64; | 36 | RelativeRel = R_AMDGPU_RELATIVE64; |
| 36 | GotRel = R_AMDGPU_ABS64; | 37 | GotRel = R_AMDGPU_ABS64; |
| 37 | GotEntrySize = 8; | 38 | GotEntrySize = 8; |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | void AMDGPU::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 41 | static uint32_t getEFlags(InputFile *File) { |
| 42 | return cast<ObjFile<ELF64LE>>(File)->getObj().getHeader()->e_flags; | ||
| 43 | } | ||
| 44 | |||
| 45 | uint32_t AMDGPU::calcEFlags() const { | ||
| 46 | assert(!ObjectFiles.empty()); | ||
| 47 | uint32_t Ret = getEFlags(ObjectFiles[0]); | ||
| 48 | |||
| 49 | // Verify that all input files have the same e_flags. | ||
| 50 | for (InputFile *F : makeArrayRef(ObjectFiles).slice(1)) { | ||
| 51 | if (Ret == getEFlags(F)) | ||
| 52 | continue; | ||
| 53 | error("incompatible e_flags: " + toString(F)); | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | return Ret; | ||
| 57 | } | ||
| 58 | |||
| 59 | void AMDGPU::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { | ||
| 41 | switch (Type) { | 60 | switch (Type) { |
| 42 | case R_AMDGPU_ABS32: | 61 | case R_AMDGPU_ABS32: |
| 43 | case R_AMDGPU_GOTPCREL: | 62 | case R_AMDGPU_GOTPCREL: |
| ... | @@ -58,7 +77,7 @@ void AMDGPU::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -58,7 +77,7 @@ void AMDGPU::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 58 | } | 77 | } |
| 59 | } | 78 | } |
| 60 | 79 | ||
| 61 | RelExpr AMDGPU::getRelExpr(uint32_t Type, const SymbolBody &S, | 80 | RelExpr AMDGPU::getRelExpr(RelType Type, const Symbol &S, |
| 62 | const uint8_t *Loc) const { | 81 | const uint8_t *Loc) const { |
| 63 | switch (Type) { | 82 | switch (Type) { |
| 64 | case R_AMDGPU_ABS32: | 83 | case R_AMDGPU_ABS32: |
| ... | @@ -73,8 +92,7 @@ RelExpr AMDGPU::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -73,8 +92,7 @@ RelExpr AMDGPU::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 73 | case R_AMDGPU_GOTPCREL32_HI: | 92 | case R_AMDGPU_GOTPCREL32_HI: |
| 74 | return R_GOT_PC; | 93 | return R_GOT_PC; |
| 75 | default: | 94 | default: |
| 76 | error(toString(S.File) + ": unknown relocation type: " + toString(Type)); | 95 | return R_INVALID; |
| 77 | return R_HINT; | ||
| 78 | } | 96 | } |
| 79 | } | 97 | } |
| 80 | 98 |
deps/lld/ELF/Arch/ARM.cpp+151-48| ... | @@ -7,12 +7,12 @@ | ... | @@ -7,12 +7,12 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "InputFiles.h" | 10 | #include "InputFiles.h" |
| 12 | #include "Symbols.h" | 11 | #include "Symbols.h" |
| 13 | #include "SyntheticSections.h" | 12 | #include "SyntheticSections.h" |
| 14 | #include "Target.h" | 13 | #include "Target.h" |
| 15 | #include "Thunks.h" | 14 | #include "Thunks.h" |
| 15 | #include "lld/Common/ErrorHandler.h" | ||
| 16 | #include "llvm/Object/ELF.h" | 16 | #include "llvm/Object/ELF.h" |
| 17 | #include "llvm/Support/Endian.h" | 17 | #include "llvm/Support/Endian.h" |
| 18 | 18 | ||
| ... | @@ -26,23 +26,23 @@ namespace { | ... | @@ -26,23 +26,23 @@ namespace { |
| 26 | class ARM final : public TargetInfo { | 26 | class ARM final : public TargetInfo { |
| 27 | public: | 27 | public: |
| 28 | ARM(); | 28 | ARM(); |
| 29 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 29 | uint32_t calcEFlags() const override; |
| 30 | RelExpr getRelExpr(RelType Type, const Symbol &S, | ||
| 30 | const uint8_t *Loc) const override; | 31 | const uint8_t *Loc) const override; |
| 31 | bool isPicRel(uint32_t Type) const override; | 32 | bool isPicRel(RelType Type) const override; |
| 32 | uint32_t getDynRel(uint32_t Type) const override; | 33 | RelType getDynRel(RelType Type) const override; |
| 33 | int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; | 34 | int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; |
| 34 | void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; | 35 | void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; |
| 35 | void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override; | 36 | void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override; |
| 36 | void writePltHeader(uint8_t *Buf) const override; | 37 | void writePltHeader(uint8_t *Buf) const override; |
| 37 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | 38 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, |
| 38 | int32_t Index, unsigned RelOff) const override; | 39 | int32_t Index, unsigned RelOff) const override; |
| 39 | void addPltSymbols(InputSectionBase *IS, uint64_t Off) const override; | 40 | void addPltSymbols(InputSection &IS, uint64_t Off) const override; |
| 40 | void addPltHeaderSymbols(InputSectionBase *ISD) const override; | 41 | void addPltHeaderSymbols(InputSection &ISD) const override; |
| 41 | bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, | 42 | bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 42 | const SymbolBody &S) const override; | 43 | uint64_t BranchAddr, const Symbol &S) const override; |
| 43 | bool inBranchRange(uint32_t RelocType, uint64_t Src, | 44 | bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; |
| 44 | uint64_t Dst) const override; | 45 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 45 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | ||
| 46 | }; | 46 | }; |
| 47 | } // namespace | 47 | } // namespace |
| 48 | 48 | ||
| ... | @@ -58,18 +58,54 @@ ARM::ARM() { | ... | @@ -58,18 +58,54 @@ ARM::ARM() { |
| 58 | GotEntrySize = 4; | 58 | GotEntrySize = 4; |
| 59 | GotPltEntrySize = 4; | 59 | GotPltEntrySize = 4; |
| 60 | PltEntrySize = 16; | 60 | PltEntrySize = 16; |
| 61 | PltHeaderSize = 20; | 61 | PltHeaderSize = 32; |
| 62 | TrapInstr = 0xd4d4d4d4; | 62 | TrapInstr = 0xd4d4d4d4; |
| 63 | // ARM uses Variant 1 TLS | 63 | // ARM uses Variant 1 TLS |
| 64 | TcbSize = 8; | 64 | TcbSize = 8; |
| 65 | NeedsThunks = true; | 65 | NeedsThunks = true; |
| 66 | |||
| 67 | // The placing of pre-created ThunkSections is controlled by the | ||
| 68 | // ThunkSectionSpacing parameter. The aim is to place the | ||
| 69 | // ThunkSection such that all branches from the InputSections prior to the | ||
| 70 | // ThunkSection can reach a Thunk placed at the end of the ThunkSection. | ||
| 71 | // Graphically: | ||
| 72 | // | up to ThunkSectionSpacing .text input sections | | ||
| 73 | // | ThunkSection | | ||
| 74 | // | up to ThunkSectionSpacing .text input sections | | ||
| 75 | // | ThunkSection | | ||
| 76 | |||
| 77 | // Pre-created ThunkSections are spaced roughly 16MiB apart on ARM. This is to | ||
| 78 | // match the most common expected case of a Thumb 2 encoded BL, BLX or B.W | ||
| 79 | // ARM B, BL, BLX range +/- 32MiB | ||
| 80 | // Thumb B.W, BL, BLX range +/- 16MiB | ||
| 81 | // Thumb B<cc>.W range +/- 1MiB | ||
| 82 | // If a branch cannot reach a pre-created ThunkSection a new one will be | ||
| 83 | // created so we can handle the rare cases of a Thumb 2 conditional branch. | ||
| 84 | // We intentionally use a lower size for ThunkSectionSpacing than the maximum | ||
| 85 | // branch range so the end of the ThunkSection is more likely to be within | ||
| 86 | // range of the branch instruction that is furthest away. The value we shorten | ||
| 87 | // ThunkSectionSpacing by is set conservatively to allow us to create 16,384 | ||
| 88 | // 12 byte Thunks at any offset in a ThunkSection without risk of a branch to | ||
| 89 | // one of the Thunks going out of range. | ||
| 90 | |||
| 91 | // FIXME: lld assumes that the Thumb BL and BLX encoding permits the J1 and | ||
| 92 | // J2 bits to be used to extend the branch range. On earlier Architectures | ||
| 93 | // such as ARMv4, ARMv5 and ARMv6 (except ARMv6T2) the range is +/- 4MiB. If | ||
| 94 | // support for the earlier encodings is added then when they are used the | ||
| 95 | // ThunkSectionSpacing will need lowering. | ||
| 96 | ThunkSectionSpacing = 0x1000000 - 0x30000; | ||
| 97 | } | ||
| 98 | |||
| 99 | uint32_t ARM::calcEFlags() const { | ||
| 100 | // We don't currently use any features incompatible with EF_ARM_EABI_VER5, | ||
| 101 | // but we don't have any firm guarantees of conformance. Linux AArch64 | ||
| 102 | // kernels (as of 2016) require an EABI version to be set. | ||
| 103 | return EF_ARM_EABI_VER5; | ||
| 66 | } | 104 | } |
| 67 | 105 | ||
| 68 | RelExpr ARM::getRelExpr(uint32_t Type, const SymbolBody &S, | 106 | RelExpr ARM::getRelExpr(RelType Type, const Symbol &S, |
| 69 | const uint8_t *Loc) const { | 107 | const uint8_t *Loc) const { |
| 70 | switch (Type) { | 108 | switch (Type) { |
| 71 | default: | ||
| 72 | return R_ABS; | ||
| 73 | case R_ARM_THM_JUMP11: | 109 | case R_ARM_THM_JUMP11: |
| 74 | return R_PC; | 110 | return R_PC; |
| 75 | case R_ARM_CALL: | 111 | case R_ARM_CALL: |
| ... | @@ -120,15 +156,17 @@ RelExpr ARM::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -120,15 +156,17 @@ RelExpr ARM::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 120 | return R_NONE; | 156 | return R_NONE; |
| 121 | case R_ARM_TLS_LE32: | 157 | case R_ARM_TLS_LE32: |
| 122 | return R_TLS; | 158 | return R_TLS; |
| 159 | default: | ||
| 160 | return R_ABS; | ||
| 123 | } | 161 | } |
| 124 | } | 162 | } |
| 125 | 163 | ||
| 126 | bool ARM::isPicRel(uint32_t Type) const { | 164 | bool ARM::isPicRel(RelType Type) const { |
| 127 | return (Type == R_ARM_TARGET1 && !Config->Target1Rel) || | 165 | return (Type == R_ARM_TARGET1 && !Config->Target1Rel) || |
| 128 | (Type == R_ARM_ABS32); | 166 | (Type == R_ARM_ABS32); |
| 129 | } | 167 | } |
| 130 | 168 | ||
| 131 | uint32_t ARM::getDynRel(uint32_t Type) const { | 169 | RelType ARM::getDynRel(RelType Type) const { |
| 132 | if (Type == R_ARM_TARGET1 && !Config->Target1Rel) | 170 | if (Type == R_ARM_TARGET1 && !Config->Target1Rel) |
| 133 | return R_ARM_ABS32; | 171 | return R_ARM_ABS32; |
| 134 | if (Type == R_ARM_ABS32) | 172 | if (Type == R_ARM_ABS32) |
| ... | @@ -137,41 +175,73 @@ uint32_t ARM::getDynRel(uint32_t Type) const { | ... | @@ -137,41 +175,73 @@ uint32_t ARM::getDynRel(uint32_t Type) const { |
| 137 | return R_ARM_ABS32; | 175 | return R_ARM_ABS32; |
| 138 | } | 176 | } |
| 139 | 177 | ||
| 140 | void ARM::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { | 178 | void ARM::writeGotPlt(uint8_t *Buf, const Symbol &) const { |
| 141 | write32le(Buf, InX::Plt->getVA()); | 179 | write32le(Buf, InX::Plt->getVA()); |
| 142 | } | 180 | } |
| 143 | 181 | ||
| 144 | void ARM::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const { | 182 | void ARM::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { |
| 145 | // An ARM entry is the address of the ifunc resolver function. | 183 | // An ARM entry is the address of the ifunc resolver function. |
| 146 | write32le(Buf, S.getVA()); | 184 | write32le(Buf, S.getVA()); |
| 147 | } | 185 | } |
| 148 | 186 | ||
| 149 | void ARM::writePltHeader(uint8_t *Buf) const { | 187 | // Long form PLT Header that does not have any restrictions on the displacement |
| 188 | // of the .plt from the .plt.got. | ||
| 189 | static void writePltHeaderLong(uint8_t *Buf) { | ||
| 150 | const uint8_t PltData[] = { | 190 | const uint8_t PltData[] = { |
| 151 | 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]! | 191 | 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]! |
| 152 | 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2 | 192 | 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2 |
| 153 | 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr | 193 | 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr |
| 154 | 0x08, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #8] | 194 | 0x08, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #8] |
| 155 | 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8 | 195 | 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8 |
| 156 | }; | 196 | 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary |
| 197 | 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary | ||
| 198 | 0xd4, 0xd4, 0xd4, 0xd4}; | ||
| 157 | memcpy(Buf, PltData, sizeof(PltData)); | 199 | memcpy(Buf, PltData, sizeof(PltData)); |
| 158 | uint64_t GotPlt = InX::GotPlt->getVA(); | 200 | uint64_t GotPlt = InX::GotPlt->getVA(); |
| 159 | uint64_t L1 = InX::Plt->getVA() + 8; | 201 | uint64_t L1 = InX::Plt->getVA() + 8; |
| 160 | write32le(Buf + 16, GotPlt - L1 - 8); | 202 | write32le(Buf + 16, GotPlt - L1 - 8); |
| 161 | } | 203 | } |
| 162 | 204 | ||
| 163 | void ARM::addPltHeaderSymbols(InputSectionBase *ISD) const { | 205 | // The default PLT header requires the .plt.got to be within 128 Mb of the |
| 164 | auto *IS = cast<InputSection>(ISD); | 206 | // .plt in the positive direction. |
| 207 | void ARM::writePltHeader(uint8_t *Buf) const { | ||
| 208 | // Use a similar sequence to that in writePlt(), the difference is the calling | ||
| 209 | // conventions mean we use lr instead of ip. The PLT entry is responsible for | ||
| 210 | // saving lr on the stack, the dynamic loader is responsible for reloading | ||
| 211 | // it. | ||
| 212 | const uint32_t PltData[] = { | ||
| 213 | 0xe52de004, // L1: str lr, [sp,#-4]! | ||
| 214 | 0xe28fe600, // add lr, pc, #0x0NN00000 &(.got.plt - L1 - 4) | ||
| 215 | 0xe28eea00, // add lr, lr, #0x000NN000 &(.got.plt - L1 - 4) | ||
| 216 | 0xe5bef000, // ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4) | ||
| 217 | }; | ||
| 218 | |||
| 219 | uint64_t Offset = InX::GotPlt->getVA() - InX::Plt->getVA() - 4; | ||
| 220 | if (!llvm::isUInt<27>(Offset)) { | ||
| 221 | // We cannot encode the Offset, use the long form. | ||
| 222 | writePltHeaderLong(Buf); | ||
| 223 | return; | ||
| 224 | } | ||
| 225 | write32le(Buf + 0, PltData[0]); | ||
| 226 | write32le(Buf + 4, PltData[1] | ((Offset >> 20) & 0xff)); | ||
| 227 | write32le(Buf + 8, PltData[2] | ((Offset >> 12) & 0xff)); | ||
| 228 | write32le(Buf + 12, PltData[3] | (Offset & 0xfff)); | ||
| 229 | write32le(Buf + 16, TrapInstr); // Pad to 32-byte boundary | ||
| 230 | write32le(Buf + 20, TrapInstr); | ||
| 231 | write32le(Buf + 24, TrapInstr); | ||
| 232 | write32le(Buf + 28, TrapInstr); | ||
| 233 | } | ||
| 234 | |||
| 235 | void ARM::addPltHeaderSymbols(InputSection &IS) const { | ||
| 165 | addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS); | 236 | addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS); |
| 166 | addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS); | 237 | addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS); |
| 167 | } | 238 | } |
| 168 | 239 | ||
| 169 | void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | 240 | // Long form PLT entries that do not have any restrictions on the displacement |
| 170 | uint64_t PltEntryAddr, int32_t Index, | 241 | // of the .plt from the .plt.got. |
| 171 | unsigned RelOff) const { | 242 | static void writePltLong(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 172 | // FIXME: Using simple code sequence with simple relocations. | 243 | uint64_t PltEntryAddr, int32_t Index, |
| 173 | // There is a more optimal sequence but it requires support for the group | 244 | unsigned RelOff) { |
| 174 | // relocations. See ELF for the ARM Architecture Appendix A.3 | ||
| 175 | const uint8_t PltData[] = { | 245 | const uint8_t PltData[] = { |
| 176 | 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2 | 246 | 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2 |
| 177 | 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc | 247 | 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc |
| ... | @@ -183,24 +253,49 @@ void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ... | @@ -183,24 +253,49 @@ void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 183 | write32le(Buf + 12, GotPltEntryAddr - L1 - 8); | 253 | write32le(Buf + 12, GotPltEntryAddr - L1 - 8); |
| 184 | } | 254 | } |
| 185 | 255 | ||
| 186 | void ARM::addPltSymbols(InputSectionBase *ISD, uint64_t Off) const { | 256 | // The default PLT entries require the .plt.got to be within 128 Mb of the |
| 187 | auto *IS = cast<InputSection>(ISD); | 257 | // .plt in the positive direction. |
| 258 | void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ||
| 259 | uint64_t PltEntryAddr, int32_t Index, | ||
| 260 | unsigned RelOff) const { | ||
| 261 | // The PLT entry is similar to the example given in Appendix A of ELF for | ||
| 262 | // the Arm Architecture. Instead of using the Group Relocations to find the | ||
| 263 | // optimal rotation for the 8-bit immediate used in the add instructions we | ||
| 264 | // hard code the most compact rotations for simplicity. This saves a load | ||
| 265 | // instruction over the long plt sequences. | ||
| 266 | const uint32_t PltData[] = { | ||
| 267 | 0xe28fc600, // L1: add ip, pc, #0x0NN00000 Offset(&(.plt.got) - L1 - 8 | ||
| 268 | 0xe28cca00, // add ip, ip, #0x000NN000 Offset(&(.plt.got) - L1 - 8 | ||
| 269 | 0xe5bcf000, // ldr pc, [ip, #0x00000NNN] Offset(&(.plt.got) - L1 - 8 | ||
| 270 | }; | ||
| 271 | |||
| 272 | uint64_t Offset = GotPltEntryAddr - PltEntryAddr - 8; | ||
| 273 | if (!llvm::isUInt<27>(Offset)) { | ||
| 274 | // We cannot encode the Offset, use the long form. | ||
| 275 | writePltLong(Buf, GotPltEntryAddr, PltEntryAddr, Index, RelOff); | ||
| 276 | return; | ||
| 277 | } | ||
| 278 | write32le(Buf + 0, PltData[0] | ((Offset >> 20) & 0xff)); | ||
| 279 | write32le(Buf + 4, PltData[1] | ((Offset >> 12) & 0xff)); | ||
| 280 | write32le(Buf + 8, PltData[2] | (Offset & 0xfff)); | ||
| 281 | write32le(Buf + 12, TrapInstr); // Pad to 16-byte boundary | ||
| 282 | } | ||
| 283 | |||
| 284 | void ARM::addPltSymbols(InputSection &IS, uint64_t Off) const { | ||
| 188 | addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS); | 285 | addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS); |
| 189 | addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS); | 286 | addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS); |
| 190 | } | 287 | } |
| 191 | 288 | ||
| 192 | bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, | 289 | bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 193 | const SymbolBody &S) const { | 290 | uint64_t BranchAddr, const Symbol &S) const { |
| 194 | // If S is an undefined weak symbol in an executable we don't need a Thunk. | 291 | // If S is an undefined weak symbol and does not have a PLT entry then it |
| 195 | // In a DSO calls to undefined symbols, including weak ones get PLT entries | 292 | // will be resolved as a branch to the next instruction. |
| 196 | // which may need a thunk. | 293 | if (S.isUndefWeak() && !S.isInPlt()) |
| 197 | if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() && | ||
| 198 | !Config->Shared) | ||
| 199 | return false; | 294 | return false; |
| 200 | // A state change from ARM to Thumb and vice versa must go through an | 295 | // A state change from ARM to Thumb and vice versa must go through an |
| 201 | // interworking thunk if the relocation type is not R_ARM_CALL or | 296 | // interworking thunk if the relocation type is not R_ARM_CALL or |
| 202 | // R_ARM_THM_CALL. | 297 | // R_ARM_THM_CALL. |
| 203 | switch (RelocType) { | 298 | switch (Type) { |
| 204 | case R_ARM_PC24: | 299 | case R_ARM_PC24: |
| 205 | case R_ARM_PLT32: | 300 | case R_ARM_PLT32: |
| 206 | case R_ARM_JUMP24: | 301 | case R_ARM_JUMP24: |
| ... | @@ -208,23 +303,31 @@ bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, | ... | @@ -208,23 +303,31 @@ bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, |
| 208 | // Otherwise we need to interwork if Symbol has bit 0 set (Thumb). | 303 | // Otherwise we need to interwork if Symbol has bit 0 set (Thumb). |
| 209 | if (Expr == R_PC && ((S.getVA() & 1) == 1)) | 304 | if (Expr == R_PC && ((S.getVA() & 1) == 1)) |
| 210 | return true; | 305 | return true; |
| 211 | break; | 306 | LLVM_FALLTHROUGH; |
| 307 | case R_ARM_CALL: { | ||
| 308 | uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); | ||
| 309 | return !inBranchRange(Type, BranchAddr, Dst); | ||
| 310 | } | ||
| 212 | case R_ARM_THM_JUMP19: | 311 | case R_ARM_THM_JUMP19: |
| 213 | case R_ARM_THM_JUMP24: | 312 | case R_ARM_THM_JUMP24: |
| 214 | // Source is Thumb, all PLT entries are ARM so interworking is required. | 313 | // Source is Thumb, all PLT entries are ARM so interworking is required. |
| 215 | // Otherwise we need to interwork if Symbol has bit 0 clear (ARM). | 314 | // Otherwise we need to interwork if Symbol has bit 0 clear (ARM). |
| 216 | if (Expr == R_PLT_PC || ((S.getVA() & 1) == 0)) | 315 | if (Expr == R_PLT_PC || ((S.getVA() & 1) == 0)) |
| 217 | return true; | 316 | return true; |
| 218 | break; | 317 | LLVM_FALLTHROUGH; |
| 318 | case R_ARM_THM_CALL: { | ||
| 319 | uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); | ||
| 320 | return !inBranchRange(Type, BranchAddr, Dst); | ||
| 321 | } | ||
| 219 | } | 322 | } |
| 220 | return false; | 323 | return false; |
| 221 | } | 324 | } |
| 222 | 325 | ||
| 223 | bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const { | 326 | bool ARM::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { |
| 224 | uint64_t Range; | 327 | uint64_t Range; |
| 225 | uint64_t InstrSize; | 328 | uint64_t InstrSize; |
| 226 | 329 | ||
| 227 | switch (RelocType) { | 330 | switch (Type) { |
| 228 | case R_ARM_PC24: | 331 | case R_ARM_PC24: |
| 229 | case R_ARM_PLT32: | 332 | case R_ARM_PLT32: |
| 230 | case R_ARM_JUMP24: | 333 | case R_ARM_JUMP24: |
| ... | @@ -263,7 +366,7 @@ bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const { | ... | @@ -263,7 +366,7 @@ bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const { |
| 263 | return Distance <= Range; | 366 | return Distance <= Range; |
| 264 | } | 367 | } |
| 265 | 368 | ||
| 266 | void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 369 | void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 267 | switch (Type) { | 370 | switch (Type) { |
| 268 | case R_ARM_ABS32: | 371 | case R_ARM_ABS32: |
| 269 | case R_ARM_BASE_PREL: | 372 | case R_ARM_BASE_PREL: |
| ... | @@ -400,7 +503,7 @@ void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -400,7 +503,7 @@ void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 400 | } | 503 | } |
| 401 | } | 504 | } |
| 402 | 505 | ||
| 403 | int64_t ARM::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { | 506 | int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const { |
| 404 | switch (Type) { | 507 | switch (Type) { |
| 405 | default: | 508 | default: |
| 406 | return 0; | 509 | return 0; |
deps/lld/ELF/Arch/AVR.cpp+6-12| ... | @@ -26,10 +26,10 @@ | ... | @@ -26,10 +26,10 @@ |
| 26 | // | 26 | // |
| 27 | //===----------------------------------------------------------------------===// | 27 | //===----------------------------------------------------------------------===// |
| 28 | 28 | ||
| 29 | #include "Error.h" | ||
| 30 | #include "InputFiles.h" | 29 | #include "InputFiles.h" |
| 31 | #include "Symbols.h" | 30 | #include "Symbols.h" |
| 32 | #include "Target.h" | 31 | #include "Target.h" |
| 32 | #include "lld/Common/ErrorHandler.h" | ||
| 33 | #include "llvm/Object/ELF.h" | 33 | #include "llvm/Object/ELF.h" |
| 34 | #include "llvm/Support/Endian.h" | 34 | #include "llvm/Support/Endian.h" |
| 35 | 35 | ||
| ... | @@ -43,24 +43,18 @@ using namespace lld::elf; | ... | @@ -43,24 +43,18 @@ using namespace lld::elf; |
| 43 | namespace { | 43 | namespace { |
| 44 | class AVR final : public TargetInfo { | 44 | class AVR final : public TargetInfo { |
| 45 | public: | 45 | public: |
| 46 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 46 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 47 | const uint8_t *Loc) const override; | 47 | const uint8_t *Loc) const override; |
| 48 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 48 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 49 | }; | 49 | }; |
| 50 | } // namespace | 50 | } // namespace |
| 51 | 51 | ||
| 52 | RelExpr AVR::getRelExpr(uint32_t Type, const SymbolBody &S, | 52 | RelExpr AVR::getRelExpr(RelType Type, const Symbol &S, |
| 53 | const uint8_t *Loc) const { | 53 | const uint8_t *Loc) const { |
| 54 | switch (Type) { | 54 | return R_ABS; |
| 55 | case R_AVR_CALL: | ||
| 56 | return R_ABS; | ||
| 57 | default: | ||
| 58 | error(toString(S.File) + ": unknown relocation type: " + toString(Type)); | ||
| 59 | return R_HINT; | ||
| 60 | } | ||
| 61 | } | 55 | } |
| 62 | 56 | ||
| 63 | void AVR::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 57 | void AVR::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 64 | switch (Type) { | 58 | switch (Type) { |
| 65 | case R_AVR_CALL: { | 59 | case R_AVR_CALL: { |
| 66 | uint16_t Hi = Val >> 17; | 60 | uint16_t Hi = Val >> 17; |
deps/lld/ELF/Arch/Mips.cpp+361-102| ... | @@ -7,13 +7,13 @@ | ... | @@ -7,13 +7,13 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "InputFiles.h" | 10 | #include "InputFiles.h" |
| 12 | #include "OutputSections.h" | 11 | #include "OutputSections.h" |
| 13 | #include "Symbols.h" | 12 | #include "Symbols.h" |
| 14 | #include "SyntheticSections.h" | 13 | #include "SyntheticSections.h" |
| 15 | #include "Target.h" | 14 | #include "Target.h" |
| 16 | #include "Thunks.h" | 15 | #include "Thunks.h" |
| 16 | #include "lld/Common/ErrorHandler.h" | ||
| 17 | #include "llvm/Object/ELF.h" | 17 | #include "llvm/Object/ELF.h" |
| 18 | #include "llvm/Support/Endian.h" | 18 | #include "llvm/Support/Endian.h" |
| 19 | 19 | ||
| ... | @@ -28,19 +28,20 @@ namespace { | ... | @@ -28,19 +28,20 @@ namespace { |
| 28 | template <class ELFT> class MIPS final : public TargetInfo { | 28 | template <class ELFT> class MIPS final : public TargetInfo { |
| 29 | public: | 29 | public: |
| 30 | MIPS(); | 30 | MIPS(); |
| 31 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 31 | uint32_t calcEFlags() const override; |
| 32 | RelExpr getRelExpr(RelType Type, const Symbol &S, | ||
| 32 | const uint8_t *Loc) const override; | 33 | const uint8_t *Loc) const override; |
| 33 | int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; | 34 | int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; |
| 34 | bool isPicRel(uint32_t Type) const override; | 35 | bool isPicRel(RelType Type) const override; |
| 35 | uint32_t getDynRel(uint32_t Type) const override; | 36 | RelType getDynRel(RelType Type) const override; |
| 36 | void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; | 37 | void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; |
| 37 | void writePltHeader(uint8_t *Buf) const override; | 38 | void writePltHeader(uint8_t *Buf) const override; |
| 38 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | 39 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, |
| 39 | int32_t Index, unsigned RelOff) const override; | 40 | int32_t Index, unsigned RelOff) const override; |
| 40 | bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, | 41 | bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 41 | const SymbolBody &S) const override; | 42 | uint64_t BranchAddr, const Symbol &S) const override; |
| 42 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 43 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 43 | bool usesOnlyLowPageBits(uint32_t Type) const override; | 44 | bool usesOnlyLowPageBits(RelType Type) const override; |
| 44 | }; | 45 | }; |
| 45 | } // namespace | 46 | } // namespace |
| 46 | 47 | ||
| ... | @@ -69,24 +70,39 @@ template <class ELFT> MIPS<ELFT>::MIPS() { | ... | @@ -69,24 +70,39 @@ template <class ELFT> MIPS<ELFT>::MIPS() { |
| 69 | } | 70 | } |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 73 | template <class ELFT> uint32_t MIPS<ELFT>::calcEFlags() const { | ||
| 74 | return calcMipsEFlags<ELFT>(); | ||
| 75 | } | ||
| 76 | |||
| 72 | template <class ELFT> | 77 | template <class ELFT> |
| 73 | RelExpr MIPS<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, | 78 | RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S, |
| 74 | const uint8_t *Loc) const { | 79 | const uint8_t *Loc) const { |
| 75 | // See comment in the calculateMipsRelChain. | 80 | // See comment in the calculateMipsRelChain. |
| 76 | if (ELFT::Is64Bits || Config->MipsN32Abi) | 81 | if (ELFT::Is64Bits || Config->MipsN32Abi) |
| 77 | Type &= 0xff; | 82 | Type &= 0xff; |
| 83 | |||
| 78 | switch (Type) { | 84 | switch (Type) { |
| 79 | default: | ||
| 80 | return R_ABS; | ||
| 81 | case R_MIPS_JALR: | 85 | case R_MIPS_JALR: |
| 86 | case R_MICROMIPS_JALR: | ||
| 82 | return R_HINT; | 87 | return R_HINT; |
| 83 | case R_MIPS_GPREL16: | 88 | case R_MIPS_GPREL16: |
| 84 | case R_MIPS_GPREL32: | 89 | case R_MIPS_GPREL32: |
| 90 | case R_MICROMIPS_GPREL16: | ||
| 91 | case R_MICROMIPS_GPREL7_S2: | ||
| 85 | return R_MIPS_GOTREL; | 92 | return R_MIPS_GOTREL; |
| 86 | case R_MIPS_26: | 93 | case R_MIPS_26: |
| 94 | case R_MICROMIPS_26_S1: | ||
| 87 | return R_PLT; | 95 | return R_PLT; |
| 96 | case R_MICROMIPS_PC26_S1: | ||
| 97 | return R_PLT_PC; | ||
| 88 | case R_MIPS_HI16: | 98 | case R_MIPS_HI16: |
| 89 | case R_MIPS_LO16: | 99 | case R_MIPS_LO16: |
| 100 | case R_MIPS_HIGHER: | ||
| 101 | case R_MIPS_HIGHEST: | ||
| 102 | case R_MICROMIPS_HI16: | ||
| 103 | case R_MICROMIPS_LO16: | ||
| 104 | case R_MICROMIPS_HIGHER: | ||
| 105 | case R_MICROMIPS_HIGHEST: | ||
| 90 | // R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate | 106 | // R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate |
| 91 | // offset between start of function and 'gp' value which by default | 107 | // offset between start of function and 'gp' value which by default |
| 92 | // equal to the start of .got section. In that case we consider these | 108 | // equal to the start of .got section. In that case we consider these |
| ... | @@ -96,7 +112,24 @@ RelExpr MIPS<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -96,7 +112,24 @@ RelExpr MIPS<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 96 | if (&S == ElfSym::MipsLocalGp) | 112 | if (&S == ElfSym::MipsLocalGp) |
| 97 | return R_MIPS_GOT_GP; | 113 | return R_MIPS_GOT_GP; |
| 98 | LLVM_FALLTHROUGH; | 114 | LLVM_FALLTHROUGH; |
| 115 | case R_MIPS_32: | ||
| 116 | case R_MIPS_64: | ||
| 99 | case R_MIPS_GOT_OFST: | 117 | case R_MIPS_GOT_OFST: |
| 118 | case R_MIPS_SUB: | ||
| 119 | case R_MIPS_TLS_DTPREL_HI16: | ||
| 120 | case R_MIPS_TLS_DTPREL_LO16: | ||
| 121 | case R_MIPS_TLS_DTPREL32: | ||
| 122 | case R_MIPS_TLS_DTPREL64: | ||
| 123 | case R_MIPS_TLS_TPREL_HI16: | ||
| 124 | case R_MIPS_TLS_TPREL_LO16: | ||
| 125 | case R_MIPS_TLS_TPREL32: | ||
| 126 | case R_MIPS_TLS_TPREL64: | ||
| 127 | case R_MICROMIPS_GOT_OFST: | ||
| 128 | case R_MICROMIPS_SUB: | ||
| 129 | case R_MICROMIPS_TLS_DTPREL_HI16: | ||
| 130 | case R_MICROMIPS_TLS_DTPREL_LO16: | ||
| 131 | case R_MICROMIPS_TLS_TPREL_HI16: | ||
| 132 | case R_MICROMIPS_TLS_TPREL_LO16: | ||
| 100 | return R_ABS; | 133 | return R_ABS; |
| 101 | case R_MIPS_PC32: | 134 | case R_MIPS_PC32: |
| 102 | case R_MIPS_PC16: | 135 | case R_MIPS_PC16: |
| ... | @@ -105,111 +138,171 @@ RelExpr MIPS<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -105,111 +138,171 @@ RelExpr MIPS<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 105 | case R_MIPS_PC26_S2: | 138 | case R_MIPS_PC26_S2: |
| 106 | case R_MIPS_PCHI16: | 139 | case R_MIPS_PCHI16: |
| 107 | case R_MIPS_PCLO16: | 140 | case R_MIPS_PCLO16: |
| 141 | case R_MICROMIPS_PC7_S1: | ||
| 142 | case R_MICROMIPS_PC10_S1: | ||
| 143 | case R_MICROMIPS_PC16_S1: | ||
| 144 | case R_MICROMIPS_PC18_S3: | ||
| 145 | case R_MICROMIPS_PC19_S2: | ||
| 146 | case R_MICROMIPS_PC23_S2: | ||
| 147 | case R_MICROMIPS_PC21_S1: | ||
| 108 | return R_PC; | 148 | return R_PC; |
| 109 | case R_MIPS_GOT16: | 149 | case R_MIPS_GOT16: |
| 150 | case R_MICROMIPS_GOT16: | ||
| 110 | if (S.isLocal()) | 151 | if (S.isLocal()) |
| 111 | return R_MIPS_GOT_LOCAL_PAGE; | 152 | return R_MIPS_GOT_LOCAL_PAGE; |
| 112 | LLVM_FALLTHROUGH; | 153 | LLVM_FALLTHROUGH; |
| 113 | case R_MIPS_CALL16: | 154 | case R_MIPS_CALL16: |
| 114 | case R_MIPS_GOT_DISP: | 155 | case R_MIPS_GOT_DISP: |
| 115 | case R_MIPS_TLS_GOTTPREL: | 156 | case R_MIPS_TLS_GOTTPREL: |
| 157 | case R_MICROMIPS_CALL16: | ||
| 158 | case R_MICROMIPS_GOT_DISP: | ||
| 159 | case R_MICROMIPS_TLS_GOTTPREL: | ||
| 116 | return R_MIPS_GOT_OFF; | 160 | return R_MIPS_GOT_OFF; |
| 117 | case R_MIPS_CALL_HI16: | 161 | case R_MIPS_CALL_HI16: |
| 118 | case R_MIPS_CALL_LO16: | 162 | case R_MIPS_CALL_LO16: |
| 119 | case R_MIPS_GOT_HI16: | 163 | case R_MIPS_GOT_HI16: |
| 120 | case R_MIPS_GOT_LO16: | 164 | case R_MIPS_GOT_LO16: |
| 165 | case R_MICROMIPS_CALL_HI16: | ||
| 166 | case R_MICROMIPS_CALL_LO16: | ||
| 167 | case R_MICROMIPS_GOT_HI16: | ||
| 168 | case R_MICROMIPS_GOT_LO16: | ||
| 121 | return R_MIPS_GOT_OFF32; | 169 | return R_MIPS_GOT_OFF32; |
| 122 | case R_MIPS_GOT_PAGE: | 170 | case R_MIPS_GOT_PAGE: |
| 171 | case R_MICROMIPS_GOT_PAGE: | ||
| 123 | return R_MIPS_GOT_LOCAL_PAGE; | 172 | return R_MIPS_GOT_LOCAL_PAGE; |
| 124 | case R_MIPS_TLS_GD: | 173 | case R_MIPS_TLS_GD: |
| 174 | case R_MICROMIPS_TLS_GD: | ||
| 125 | return R_MIPS_TLSGD; | 175 | return R_MIPS_TLSGD; |
| 126 | case R_MIPS_TLS_LDM: | 176 | case R_MIPS_TLS_LDM: |
| 177 | case R_MICROMIPS_TLS_LDM: | ||
| 127 | return R_MIPS_TLSLD; | 178 | return R_MIPS_TLSLD; |
| 179 | case R_MIPS_NONE: | ||
| 180 | return R_NONE; | ||
| 181 | default: | ||
| 182 | return R_INVALID; | ||
| 128 | } | 183 | } |
| 129 | } | 184 | } |
| 130 | 185 | ||
| 131 | template <class ELFT> bool MIPS<ELFT>::isPicRel(uint32_t Type) const { | 186 | template <class ELFT> bool MIPS<ELFT>::isPicRel(RelType Type) const { |
| 132 | return Type == R_MIPS_32 || Type == R_MIPS_64; | 187 | return Type == R_MIPS_32 || Type == R_MIPS_64; |
| 133 | } | 188 | } |
| 134 | 189 | ||
| 135 | template <class ELFT> uint32_t MIPS<ELFT>::getDynRel(uint32_t Type) const { | 190 | template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType Type) const { |
| 136 | return RelativeRel; | 191 | return RelativeRel; |
| 137 | } | 192 | } |
| 138 | 193 | ||
| 139 | template <class ELFT> | 194 | template <class ELFT> |
| 140 | void MIPS<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { | 195 | void MIPS<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &) const { |
| 141 | write32<ELFT::TargetEndianness>(Buf, InX::Plt->getVA()); | 196 | uint64_t VA = InX::Plt->getVA(); |
| 142 | } | 197 | if (isMicroMips()) |
| 143 | 198 | VA |= 1; | |
| 144 | template <endianness E, uint8_t BSIZE, uint8_t SHIFT> | 199 | write32<ELFT::TargetEndianness>(Buf, VA); |
| 145 | static int64_t getPcRelocAddend(const uint8_t *Loc) { | ||
| 146 | uint32_t Instr = read32<E>(Loc); | ||
| 147 | uint32_t Mask = 0xffffffff >> (32 - BSIZE); | ||
| 148 | return SignExtend64<BSIZE + SHIFT>((Instr & Mask) << SHIFT); | ||
| 149 | } | 200 | } |
| 150 | 201 | ||
| 151 | template <endianness E, uint8_t BSIZE, uint8_t SHIFT> | 202 | template <endianness E> static uint32_t readShuffle(const uint8_t *Loc) { |
| 152 | static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t V) { | 203 | // The major opcode of a microMIPS instruction needs to appear |
| 153 | uint32_t Mask = 0xffffffff >> (32 - BSIZE); | 204 | // in the first 16-bit word (lowest address) for efficient hardware |
| 154 | uint32_t Instr = read32<E>(Loc); | 205 | // decode so that it knows if the instruction is 16-bit or 32-bit |
| 155 | if (SHIFT > 0) | 206 | // as early as possible. To do so, little-endian binaries keep 16-bit |
| 156 | checkAlignment<(1 << SHIFT)>(Loc, V, Type); | 207 | // words in a big-endian order. That is why we have to swap these |
| 157 | checkInt<BSIZE + SHIFT>(Loc, V, Type); | 208 | // words to get a correct value. |
| 158 | write32<E>(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask)); | 209 | uint32_t V = read32<E>(Loc); |
| 210 | if (E == support::little) | ||
| 211 | return (V << 16) | (V >> 16); | ||
| 212 | return V; | ||
| 159 | } | 213 | } |
| 160 | 214 | ||
| 161 | template <endianness E> static void writeMipsHi16(uint8_t *Loc, uint64_t V) { | 215 | template <endianness E> |
| 216 | static void writeRelocation(uint8_t *Loc, uint64_t V, uint8_t BitsSize, | ||
| 217 | uint8_t Shift) { | ||
| 162 | uint32_t Instr = read32<E>(Loc); | 218 | uint32_t Instr = read32<E>(Loc); |
| 163 | uint16_t Res = ((V + 0x8000) >> 16) & 0xffff; | 219 | uint32_t Mask = 0xffffffff >> (32 - BitsSize); |
| 164 | write32<E>(Loc, (Instr & 0xffff0000) | Res); | 220 | uint32_t Data = (Instr & ~Mask) | ((V >> Shift) & Mask); |
| 221 | write32<E>(Loc, Data); | ||
| 165 | } | 222 | } |
| 166 | 223 | ||
| 167 | template <endianness E> static void writeMipsHigher(uint8_t *Loc, uint64_t V) { | 224 | template <endianness E> |
| 168 | uint32_t Instr = read32<E>(Loc); | 225 | static void writeMicroRelocation32(uint8_t *Loc, uint64_t V, uint8_t BitsSize, |
| 169 | uint16_t Res = ((V + 0x80008000) >> 32) & 0xffff; | 226 | uint8_t Shift) { |
| 170 | write32<E>(Loc, (Instr & 0xffff0000) | Res); | 227 | // See comments in readShuffle for purpose of this code. |
| 171 | } | 228 | uint16_t *Words = (uint16_t *)Loc; |
| 229 | if (E == support::little) | ||
| 230 | std::swap(Words[0], Words[1]); | ||
| 172 | 231 | ||
| 173 | template <endianness E> static void writeMipsHighest(uint8_t *Loc, uint64_t V) { | 232 | writeRelocation<E>(Loc, V, BitsSize, Shift); |
| 174 | uint32_t Instr = read32<E>(Loc); | ||
| 175 | uint16_t Res = ((V + 0x800080008000) >> 48) & 0xffff; | ||
| 176 | write32<E>(Loc, (Instr & 0xffff0000) | Res); | ||
| 177 | } | ||
| 178 | 233 | ||
| 179 | template <endianness E> static void writeMipsLo16(uint8_t *Loc, uint64_t V) { | 234 | if (E == support::little) |
| 180 | uint32_t Instr = read32<E>(Loc); | 235 | std::swap(Words[0], Words[1]); |
| 181 | write32<E>(Loc, (Instr & 0xffff0000) | (V & 0xffff)); | ||
| 182 | } | 236 | } |
| 183 | 237 | ||
| 184 | template <class ELFT> static bool isMipsR6() { | 238 | template <endianness E> |
| 185 | const auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf); | 239 | static void writeMicroRelocation16(uint8_t *Loc, uint64_t V, uint8_t BitsSize, |
| 186 | uint32_t Arch = FirstObj.getObj().getHeader()->e_flags & EF_MIPS_ARCH; | 240 | uint8_t Shift) { |
| 187 | return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6; | 241 | uint16_t Instr = read16<E>(Loc); |
| 242 | uint16_t Mask = 0xffff >> (16 - BitsSize); | ||
| 243 | uint16_t Data = (Instr & ~Mask) | ((V >> Shift) & Mask); | ||
| 244 | write16<E>(Loc, Data); | ||
| 188 | } | 245 | } |
| 189 | 246 | ||
| 190 | template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *Buf) const { | 247 | template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *Buf) const { |
| 191 | const endianness E = ELFT::TargetEndianness; | 248 | const endianness E = ELFT::TargetEndianness; |
| 249 | if (isMicroMips()) { | ||
| 250 | uint64_t GotPlt = InX::GotPlt->getVA(); | ||
| 251 | uint64_t Plt = InX::Plt->getVA(); | ||
| 252 | // Overwrite trap instructions written by Writer::writeTrapInstr. | ||
| 253 | memset(Buf, 0, PltHeaderSize); | ||
| 254 | |||
| 255 | write16<E>(Buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - . | ||
| 256 | write16<E>(Buf + 4, 0xff23); // lw $25, 0($3) | ||
| 257 | write16<E>(Buf + 8, 0x0535); // subu16 $2, $2, $3 | ||
| 258 | write16<E>(Buf + 10, 0x2525); // srl16 $2, $2, 2 | ||
| 259 | write16<E>(Buf + 12, 0x3302); // addiu $24, $2, -2 | ||
| 260 | write16<E>(Buf + 14, 0xfffe); | ||
| 261 | write16<E>(Buf + 16, 0x0dff); // move $15, $31 | ||
| 262 | if (isMipsR6()) { | ||
| 263 | write16<E>(Buf + 18, 0x0f83); // move $28, $3 | ||
| 264 | write16<E>(Buf + 20, 0x472b); // jalrc $25 | ||
| 265 | write16<E>(Buf + 22, 0x0c00); // nop | ||
| 266 | relocateOne(Buf, R_MICROMIPS_PC19_S2, GotPlt - Plt); | ||
| 267 | } else { | ||
| 268 | write16<E>(Buf + 18, 0x45f9); // jalrc $25 | ||
| 269 | write16<E>(Buf + 20, 0x0f83); // move $28, $3 | ||
| 270 | write16<E>(Buf + 22, 0x0c00); // nop | ||
| 271 | relocateOne(Buf, R_MICROMIPS_PC23_S2, GotPlt - Plt); | ||
| 272 | } | ||
| 273 | return; | ||
| 274 | } | ||
| 275 | |||
| 192 | if (Config->MipsN32Abi) { | 276 | if (Config->MipsN32Abi) { |
| 193 | write32<E>(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) | 277 | write32<E>(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) |
| 194 | write32<E>(Buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) | 278 | write32<E>(Buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) |
| 195 | write32<E>(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) | 279 | write32<E>(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) |
| 196 | write32<E>(Buf + 12, 0x030ec023); // subu $24, $24, $14 | 280 | write32<E>(Buf + 12, 0x030ec023); // subu $24, $24, $14 |
| 281 | write32<E>(Buf + 16, 0x03e07825); // move $15, $31 | ||
| 282 | write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2 | ||
| 283 | } else if (ELFT::Is64Bits) { | ||
| 284 | write32<E>(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) | ||
| 285 | write32<E>(Buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14) | ||
| 286 | write32<E>(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) | ||
| 287 | write32<E>(Buf + 12, 0x030ec023); // subu $24, $24, $14 | ||
| 288 | write32<E>(Buf + 16, 0x03e07825); // move $15, $31 | ||
| 289 | write32<E>(Buf + 20, 0x0018c0c2); // srl $24, $24, 3 | ||
| 197 | } else { | 290 | } else { |
| 198 | write32<E>(Buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) | 291 | write32<E>(Buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) |
| 199 | write32<E>(Buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) | 292 | write32<E>(Buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) |
| 200 | write32<E>(Buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) | 293 | write32<E>(Buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) |
| 201 | write32<E>(Buf + 12, 0x031cc023); // subu $24, $24, $28 | 294 | write32<E>(Buf + 12, 0x031cc023); // subu $24, $24, $28 |
| 295 | write32<E>(Buf + 16, 0x03e07825); // move $15, $31 | ||
| 296 | write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2 | ||
| 202 | } | 297 | } |
| 203 | 298 | ||
| 204 | write32<E>(Buf + 16, 0x03e07825); // move $15, $31 | ||
| 205 | write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2 | ||
| 206 | write32<E>(Buf + 24, 0x0320f809); // jalr $25 | 299 | write32<E>(Buf + 24, 0x0320f809); // jalr $25 |
| 207 | write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2 | 300 | write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2 |
| 208 | 301 | ||
| 209 | uint64_t GotPlt = InX::GotPlt->getVA(); | 302 | uint64_t GotPlt = InX::GotPlt->getVA(); |
| 210 | writeMipsHi16<E>(Buf, GotPlt); | 303 | writeRelocation<E>(Buf, GotPlt + 0x8000, 16, 16); |
| 211 | writeMipsLo16<E>(Buf + 4, GotPlt); | 304 | writeRelocation<E>(Buf + 4, GotPlt, 16, 0); |
| 212 | writeMipsLo16<E>(Buf + 8, GotPlt); | 305 | writeRelocation<E>(Buf + 8, GotPlt, 16, 0); |
| 213 | } | 306 | } |
| 214 | 307 | ||
| 215 | template <class ELFT> | 308 | template <class ELFT> |
| ... | @@ -217,25 +310,45 @@ void MIPS<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ... | @@ -217,25 +310,45 @@ void MIPS<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 217 | uint64_t PltEntryAddr, int32_t Index, | 310 | uint64_t PltEntryAddr, int32_t Index, |
| 218 | unsigned RelOff) const { | 311 | unsigned RelOff) const { |
| 219 | const endianness E = ELFT::TargetEndianness; | 312 | const endianness E = ELFT::TargetEndianness; |
| 313 | if (isMicroMips()) { | ||
| 314 | // Overwrite trap instructions written by Writer::writeTrapInstr. | ||
| 315 | memset(Buf, 0, PltEntrySize); | ||
| 316 | |||
| 317 | if (isMipsR6()) { | ||
| 318 | write16<E>(Buf, 0x7840); // addiupc $2, (GOTPLT) - . | ||
| 319 | write16<E>(Buf + 4, 0xff22); // lw $25, 0($2) | ||
| 320 | write16<E>(Buf + 8, 0x0f02); // move $24, $2 | ||
| 321 | write16<E>(Buf + 10, 0x4723); // jrc $25 / jr16 $25 | ||
| 322 | relocateOne(Buf, R_MICROMIPS_PC19_S2, GotPltEntryAddr - PltEntryAddr); | ||
| 323 | } else { | ||
| 324 | write16<E>(Buf, 0x7900); // addiupc $2, (GOTPLT) - . | ||
| 325 | write16<E>(Buf + 4, 0xff22); // lw $25, 0($2) | ||
| 326 | write16<E>(Buf + 8, 0x4599); // jrc $25 / jr16 $25 | ||
| 327 | write16<E>(Buf + 10, 0x0f02); // move $24, $2 | ||
| 328 | relocateOne(Buf, R_MICROMIPS_PC23_S2, GotPltEntryAddr - PltEntryAddr); | ||
| 329 | } | ||
| 330 | return; | ||
| 331 | } | ||
| 332 | |||
| 220 | write32<E>(Buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) | 333 | write32<E>(Buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) |
| 221 | write32<E>(Buf + 4, 0x8df90000); // l[wd] $25, %lo(.got.plt entry)($15) | 334 | write32<E>(Buf + 4, 0x8df90000); // l[wd] $25, %lo(.got.plt entry)($15) |
| 222 | // jr $25 | 335 | write32<E>(Buf + 8, isMipsR6() ? 0x03200009 : 0x03200008); // jr $25 |
| 223 | write32<E>(Buf + 8, isMipsR6<ELFT>() ? 0x03200009 : 0x03200008); | ||
| 224 | write32<E>(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry) | 336 | write32<E>(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry) |
| 225 | writeMipsHi16<E>(Buf, GotPltEntryAddr); | 337 | writeRelocation<E>(Buf, GotPltEntryAddr + 0x8000, 16, 16); |
| 226 | writeMipsLo16<E>(Buf + 4, GotPltEntryAddr); | 338 | writeRelocation<E>(Buf + 4, GotPltEntryAddr, 16, 0); |
| 227 | writeMipsLo16<E>(Buf + 12, GotPltEntryAddr); | 339 | writeRelocation<E>(Buf + 12, GotPltEntryAddr, 16, 0); |
| 228 | } | 340 | } |
| 229 | 341 | ||
| 230 | template <class ELFT> | 342 | template <class ELFT> |
| 231 | bool MIPS<ELFT>::needsThunk(RelExpr Expr, uint32_t Type, const InputFile *File, | 343 | bool MIPS<ELFT>::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 232 | const SymbolBody &S) const { | 344 | uint64_t BranchAddr, const Symbol &S) const { |
| 233 | // Any MIPS PIC code function is invoked with its address in register $t9. | 345 | // Any MIPS PIC code function is invoked with its address in register $t9. |
| 234 | // So if we have a branch instruction from non-PIC code to the PIC one | 346 | // So if we have a branch instruction from non-PIC code to the PIC one |
| 235 | // we cannot make the jump directly and need to create a small stubs | 347 | // we cannot make the jump directly and need to create a small stubs |
| 236 | // to save the target function address. | 348 | // to save the target function address. |
| 237 | // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 349 | // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
| 238 | if (Type != R_MIPS_26) | 350 | if (Type != R_MIPS_26 && Type != R_MICROMIPS_26_S1 && |
| 351 | Type != R_MICROMIPS_PC26_S1) | ||
| 239 | return false; | 352 | return false; |
| 240 | auto *F = dyn_cast_or_null<ELFFileBase<ELFT>>(File); | 353 | auto *F = dyn_cast_or_null<ELFFileBase<ELFT>>(File); |
| 241 | if (!F) | 354 | if (!F) |
| ... | @@ -243,18 +356,16 @@ bool MIPS<ELFT>::needsThunk(RelExpr Expr, uint32_t Type, const InputFile *File, | ... | @@ -243,18 +356,16 @@ bool MIPS<ELFT>::needsThunk(RelExpr Expr, uint32_t Type, const InputFile *File, |
| 243 | // If current file has PIC code, LA25 stub is not required. | 356 | // If current file has PIC code, LA25 stub is not required. |
| 244 | if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC) | 357 | if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC) |
| 245 | return false; | 358 | return false; |
| 246 | auto *D = dyn_cast<DefinedRegular>(&S); | 359 | auto *D = dyn_cast<Defined>(&S); |
| 247 | // LA25 is required if target file has PIC code | 360 | // LA25 is required if target file has PIC code |
| 248 | // or target symbol is a PIC symbol. | 361 | // or target symbol is a PIC symbol. |
| 249 | return D && D->isMipsPIC<ELFT>(); | 362 | return D && isMipsPIC<ELFT>(D); |
| 250 | } | 363 | } |
| 251 | 364 | ||
| 252 | template <class ELFT> | 365 | template <class ELFT> |
| 253 | int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { | 366 | int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, RelType Type) const { |
| 254 | const endianness E = ELFT::TargetEndianness; | 367 | const endianness E = ELFT::TargetEndianness; |
| 255 | switch (Type) { | 368 | switch (Type) { |
| 256 | default: | ||
| 257 | return 0; | ||
| 258 | case R_MIPS_32: | 369 | case R_MIPS_32: |
| 259 | case R_MIPS_GPREL32: | 370 | case R_MIPS_GPREL32: |
| 260 | case R_MIPS_TLS_DTPREL32: | 371 | case R_MIPS_TLS_DTPREL32: |
| ... | @@ -264,7 +375,11 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { | ... | @@ -264,7 +375,11 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { |
| 264 | // FIXME (simon): If the relocation target symbol is not a PLT entry | 375 | // FIXME (simon): If the relocation target symbol is not a PLT entry |
| 265 | // we should use another expression for calculation: | 376 | // we should use another expression for calculation: |
| 266 | // ((A << 2) | (P & 0xf0000000)) >> 2 | 377 | // ((A << 2) | (P & 0xf0000000)) >> 2 |
| 267 | return SignExtend64<28>((read32<E>(Buf) & 0x3ffffff) << 2); | 378 | return SignExtend64<28>(read32<E>(Buf) << 2); |
| 379 | case R_MIPS_GOT16: | ||
| 380 | case R_MIPS_HI16: | ||
| 381 | case R_MIPS_PCHI16: | ||
| 382 | return SignExtend64<16>(read32<E>(Buf)) << 16; | ||
| 268 | case R_MIPS_GPREL16: | 383 | case R_MIPS_GPREL16: |
| 269 | case R_MIPS_LO16: | 384 | case R_MIPS_LO16: |
| 270 | case R_MIPS_PCLO16: | 385 | case R_MIPS_PCLO16: |
| ... | @@ -273,21 +388,53 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { | ... | @@ -273,21 +388,53 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { |
| 273 | case R_MIPS_TLS_TPREL_HI16: | 388 | case R_MIPS_TLS_TPREL_HI16: |
| 274 | case R_MIPS_TLS_TPREL_LO16: | 389 | case R_MIPS_TLS_TPREL_LO16: |
| 275 | return SignExtend64<16>(read32<E>(Buf)); | 390 | return SignExtend64<16>(read32<E>(Buf)); |
| 391 | case R_MICROMIPS_GOT16: | ||
| 392 | case R_MICROMIPS_HI16: | ||
| 393 | return SignExtend64<16>(readShuffle<E>(Buf)) << 16; | ||
| 394 | case R_MICROMIPS_GPREL16: | ||
| 395 | case R_MICROMIPS_LO16: | ||
| 396 | case R_MICROMIPS_TLS_DTPREL_HI16: | ||
| 397 | case R_MICROMIPS_TLS_DTPREL_LO16: | ||
| 398 | case R_MICROMIPS_TLS_TPREL_HI16: | ||
| 399 | case R_MICROMIPS_TLS_TPREL_LO16: | ||
| 400 | return SignExtend64<16>(readShuffle<E>(Buf)); | ||
| 401 | case R_MICROMIPS_GPREL7_S2: | ||
| 402 | return SignExtend64<9>(readShuffle<E>(Buf) << 2); | ||
| 276 | case R_MIPS_PC16: | 403 | case R_MIPS_PC16: |
| 277 | return getPcRelocAddend<E, 16, 2>(Buf); | 404 | return SignExtend64<18>(read32<E>(Buf) << 2); |
| 278 | case R_MIPS_PC19_S2: | 405 | case R_MIPS_PC19_S2: |
| 279 | return getPcRelocAddend<E, 19, 2>(Buf); | 406 | return SignExtend64<21>(read32<E>(Buf) << 2); |
| 280 | case R_MIPS_PC21_S2: | 407 | case R_MIPS_PC21_S2: |
| 281 | return getPcRelocAddend<E, 21, 2>(Buf); | 408 | return SignExtend64<23>(read32<E>(Buf) << 2); |
| 282 | case R_MIPS_PC26_S2: | 409 | case R_MIPS_PC26_S2: |
| 283 | return getPcRelocAddend<E, 26, 2>(Buf); | 410 | return SignExtend64<28>(read32<E>(Buf) << 2); |
| 284 | case R_MIPS_PC32: | 411 | case R_MIPS_PC32: |
| 285 | return getPcRelocAddend<E, 32, 0>(Buf); | 412 | return SignExtend64<32>(read32<E>(Buf)); |
| 413 | case R_MICROMIPS_26_S1: | ||
| 414 | return SignExtend64<27>(readShuffle<E>(Buf) << 1); | ||
| 415 | case R_MICROMIPS_PC7_S1: | ||
| 416 | return SignExtend64<8>(read16<E>(Buf) << 1); | ||
| 417 | case R_MICROMIPS_PC10_S1: | ||
| 418 | return SignExtend64<11>(read16<E>(Buf) << 1); | ||
| 419 | case R_MICROMIPS_PC16_S1: | ||
| 420 | return SignExtend64<17>(readShuffle<E>(Buf) << 1); | ||
| 421 | case R_MICROMIPS_PC18_S3: | ||
| 422 | return SignExtend64<21>(readShuffle<E>(Buf) << 3); | ||
| 423 | case R_MICROMIPS_PC19_S2: | ||
| 424 | return SignExtend64<21>(readShuffle<E>(Buf) << 2); | ||
| 425 | case R_MICROMIPS_PC21_S1: | ||
| 426 | return SignExtend64<22>(readShuffle<E>(Buf) << 1); | ||
| 427 | case R_MICROMIPS_PC23_S2: | ||
| 428 | return SignExtend64<25>(readShuffle<E>(Buf) << 2); | ||
| 429 | case R_MICROMIPS_PC26_S1: | ||
| 430 | return SignExtend64<27>(readShuffle<E>(Buf) << 1); | ||
| 431 | default: | ||
| 432 | return 0; | ||
| 286 | } | 433 | } |
| 287 | } | 434 | } |
| 288 | 435 | ||
| 289 | static std::pair<uint32_t, uint64_t> | 436 | static std::pair<uint32_t, uint64_t> |
| 290 | calculateMipsRelChain(uint8_t *Loc, uint32_t Type, uint64_t Val) { | 437 | calculateMipsRelChain(uint8_t *Loc, RelType Type, uint64_t Val) { |
| 291 | // MIPS N64 ABI packs multiple relocations into the single relocation | 438 | // MIPS N64 ABI packs multiple relocations into the single relocation |
| 292 | // record. In general, all up to three relocations can have arbitrary | 439 | // record. In general, all up to three relocations can have arbitrary |
| 293 | // types. In fact, Clang and GCC uses only a few combinations. For now, | 440 | // types. In fact, Clang and GCC uses only a few combinations. For now, |
| ... | @@ -300,32 +447,43 @@ calculateMipsRelChain(uint8_t *Loc, uint32_t Type, uint64_t Val) { | ... | @@ -300,32 +447,43 @@ calculateMipsRelChain(uint8_t *Loc, uint32_t Type, uint64_t Val) { |
| 300 | // relocations used to modify result of the first one: extend it to | 447 | // relocations used to modify result of the first one: extend it to |
| 301 | // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation | 448 | // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation |
| 302 | // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf | 449 | // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf |
| 303 | uint32_t Type2 = (Type >> 8) & 0xff; | 450 | RelType Type2 = (Type >> 8) & 0xff; |
| 304 | uint32_t Type3 = (Type >> 16) & 0xff; | 451 | RelType Type3 = (Type >> 16) & 0xff; |
| 305 | if (Type2 == R_MIPS_NONE && Type3 == R_MIPS_NONE) | 452 | if (Type2 == R_MIPS_NONE && Type3 == R_MIPS_NONE) |
| 306 | return std::make_pair(Type, Val); | 453 | return std::make_pair(Type, Val); |
| 307 | if (Type2 == R_MIPS_64 && Type3 == R_MIPS_NONE) | 454 | if (Type2 == R_MIPS_64 && Type3 == R_MIPS_NONE) |
| 308 | return std::make_pair(Type2, Val); | 455 | return std::make_pair(Type2, Val); |
| 309 | if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16)) | 456 | if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16)) |
| 310 | return std::make_pair(Type3, -Val); | 457 | return std::make_pair(Type3, -Val); |
| 458 | if (Type2 == R_MICROMIPS_SUB && | ||
| 459 | (Type3 == R_MICROMIPS_HI16 || Type3 == R_MICROMIPS_LO16)) | ||
| 460 | return std::make_pair(Type3, -Val); | ||
| 311 | error(getErrorLocation(Loc) + "unsupported relocations combination " + | 461 | error(getErrorLocation(Loc) + "unsupported relocations combination " + |
| 312 | Twine(Type)); | 462 | Twine(Type)); |
| 313 | return std::make_pair(Type & 0xff, Val); | 463 | return std::make_pair(Type & 0xff, Val); |
| 314 | } | 464 | } |
| 315 | 465 | ||
| 316 | template <class ELFT> | 466 | template <class ELFT> |
| 317 | void MIPS<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 467 | void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 318 | const endianness E = ELFT::TargetEndianness; | 468 | const endianness E = ELFT::TargetEndianness; |
| 469 | |||
| 319 | // Thread pointer and DRP offsets from the start of TLS data area. | 470 | // Thread pointer and DRP offsets from the start of TLS data area. |
| 320 | // https://www.linux-mips.org/wiki/NPTL | 471 | // https://www.linux-mips.org/wiki/NPTL |
| 321 | if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16 || | 472 | if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16 || |
| 322 | Type == R_MIPS_TLS_DTPREL32 || Type == R_MIPS_TLS_DTPREL64) | 473 | Type == R_MIPS_TLS_DTPREL32 || Type == R_MIPS_TLS_DTPREL64 || |
| 474 | Type == R_MICROMIPS_TLS_DTPREL_HI16 || | ||
| 475 | Type == R_MICROMIPS_TLS_DTPREL_LO16) { | ||
| 323 | Val -= 0x8000; | 476 | Val -= 0x8000; |
| 324 | else if (Type == R_MIPS_TLS_TPREL_HI16 || Type == R_MIPS_TLS_TPREL_LO16 || | 477 | } else if (Type == R_MIPS_TLS_TPREL_HI16 || Type == R_MIPS_TLS_TPREL_LO16 || |
| 325 | Type == R_MIPS_TLS_TPREL32 || Type == R_MIPS_TLS_TPREL64) | 478 | Type == R_MIPS_TLS_TPREL32 || Type == R_MIPS_TLS_TPREL64 || |
| 479 | Type == R_MICROMIPS_TLS_TPREL_HI16 || | ||
| 480 | Type == R_MICROMIPS_TLS_TPREL_LO16) { | ||
| 326 | Val -= 0x7000; | 481 | Val -= 0x7000; |
| 482 | } | ||
| 483 | |||
| 327 | if (ELFT::Is64Bits || Config->MipsN32Abi) | 484 | if (ELFT::Is64Bits || Config->MipsN32Abi) |
| 328 | std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val); | 485 | std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val); |
| 486 | |||
| 329 | switch (Type) { | 487 | switch (Type) { |
| 330 | case R_MIPS_32: | 488 | case R_MIPS_32: |
| 331 | case R_MIPS_GPREL32: | 489 | case R_MIPS_GPREL32: |
| ... | @@ -339,36 +497,65 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -339,36 +497,65 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 339 | write64<E>(Loc, Val); | 497 | write64<E>(Loc, Val); |
| 340 | break; | 498 | break; |
| 341 | case R_MIPS_26: | 499 | case R_MIPS_26: |
| 342 | write32<E>(Loc, (read32<E>(Loc) & ~0x3ffffff) | ((Val >> 2) & 0x3ffffff)); | 500 | writeRelocation<E>(Loc, Val, 26, 2); |
| 343 | break; | 501 | break; |
| 344 | case R_MIPS_GOT16: | 502 | case R_MIPS_GOT16: |
| 345 | // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode | 503 | // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode |
| 346 | // is updated addend (not a GOT index). In that case write high 16 bits | 504 | // is updated addend (not a GOT index). In that case write high 16 bits |
| 347 | // to store a correct addend value. | 505 | // to store a correct addend value. |
| 348 | if (Config->Relocatable) | 506 | if (Config->Relocatable) { |
| 349 | writeMipsHi16<E>(Loc, Val); | 507 | writeRelocation<E>(Loc, Val + 0x8000, 16, 16); |
| 350 | else { | 508 | } else { |
| 351 | checkInt<16>(Loc, Val, Type); | 509 | checkInt<16>(Loc, Val, Type); |
| 352 | writeMipsLo16<E>(Loc, Val); | 510 | writeRelocation<E>(Loc, Val, 16, 0); |
| 353 | } | 511 | } |
| 354 | break; | 512 | break; |
| 513 | case R_MICROMIPS_GOT16: | ||
| 514 | if (Config->Relocatable) { | ||
| 515 | writeMicroRelocation32<E>(Loc, Val + 0x8000, 16, 16); | ||
| 516 | } else { | ||
| 517 | checkInt<16>(Loc, Val, Type); | ||
| 518 | writeMicroRelocation32<E>(Loc, Val, 16, 0); | ||
| 519 | } | ||
| 520 | break; | ||
| 521 | case R_MIPS_CALL16: | ||
| 355 | case R_MIPS_GOT_DISP: | 522 | case R_MIPS_GOT_DISP: |
| 356 | case R_MIPS_GOT_PAGE: | 523 | case R_MIPS_GOT_PAGE: |
| 357 | case R_MIPS_GPREL16: | 524 | case R_MIPS_GPREL16: |
| 358 | case R_MIPS_TLS_GD: | 525 | case R_MIPS_TLS_GD: |
| 526 | case R_MIPS_TLS_GOTTPREL: | ||
| 359 | case R_MIPS_TLS_LDM: | 527 | case R_MIPS_TLS_LDM: |
| 360 | checkInt<16>(Loc, Val, Type); | 528 | checkInt<16>(Loc, Val, Type); |
| 361 | LLVM_FALLTHROUGH; | 529 | LLVM_FALLTHROUGH; |
| 362 | case R_MIPS_CALL16: | ||
| 363 | case R_MIPS_CALL_LO16: | 530 | case R_MIPS_CALL_LO16: |
| 364 | case R_MIPS_GOT_LO16: | 531 | case R_MIPS_GOT_LO16: |
| 365 | case R_MIPS_GOT_OFST: | 532 | case R_MIPS_GOT_OFST: |
| 366 | case R_MIPS_LO16: | 533 | case R_MIPS_LO16: |
| 367 | case R_MIPS_PCLO16: | 534 | case R_MIPS_PCLO16: |
| 368 | case R_MIPS_TLS_DTPREL_LO16: | 535 | case R_MIPS_TLS_DTPREL_LO16: |
| 369 | case R_MIPS_TLS_GOTTPREL: | ||
| 370 | case R_MIPS_TLS_TPREL_LO16: | 536 | case R_MIPS_TLS_TPREL_LO16: |
| 371 | writeMipsLo16<E>(Loc, Val); | 537 | writeRelocation<E>(Loc, Val, 16, 0); |
| 538 | break; | ||
| 539 | case R_MICROMIPS_GOT_DISP: | ||
| 540 | case R_MICROMIPS_GOT_PAGE: | ||
| 541 | case R_MICROMIPS_GPREL16: | ||
| 542 | case R_MICROMIPS_TLS_GD: | ||
| 543 | case R_MICROMIPS_TLS_LDM: | ||
| 544 | checkInt<16>(Loc, Val, Type); | ||
| 545 | writeMicroRelocation32<E>(Loc, Val, 16, 0); | ||
| 546 | break; | ||
| 547 | case R_MICROMIPS_CALL16: | ||
| 548 | case R_MICROMIPS_CALL_LO16: | ||
| 549 | case R_MICROMIPS_GOT_OFST: | ||
| 550 | case R_MICROMIPS_LO16: | ||
| 551 | case R_MICROMIPS_TLS_DTPREL_LO16: | ||
| 552 | case R_MICROMIPS_TLS_GOTTPREL: | ||
| 553 | case R_MICROMIPS_TLS_TPREL_LO16: | ||
| 554 | writeMicroRelocation32<E>(Loc, Val, 16, 0); | ||
| 555 | break; | ||
| 556 | case R_MICROMIPS_GPREL7_S2: | ||
| 557 | checkInt<7>(Loc, Val, Type); | ||
| 558 | writeMicroRelocation32<E>(Loc, Val, 7, 2); | ||
| 372 | break; | 559 | break; |
| 373 | case R_MIPS_CALL_HI16: | 560 | case R_MIPS_CALL_HI16: |
| 374 | case R_MIPS_GOT_HI16: | 561 | case R_MIPS_GOT_HI16: |
| ... | @@ -376,40 +563,107 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -376,40 +563,107 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 376 | case R_MIPS_PCHI16: | 563 | case R_MIPS_PCHI16: |
| 377 | case R_MIPS_TLS_DTPREL_HI16: | 564 | case R_MIPS_TLS_DTPREL_HI16: |
| 378 | case R_MIPS_TLS_TPREL_HI16: | 565 | case R_MIPS_TLS_TPREL_HI16: |
| 379 | writeMipsHi16<E>(Loc, Val); | 566 | writeRelocation<E>(Loc, Val + 0x8000, 16, 16); |
| 567 | break; | ||
| 568 | case R_MICROMIPS_CALL_HI16: | ||
| 569 | case R_MICROMIPS_GOT_HI16: | ||
| 570 | case R_MICROMIPS_HI16: | ||
| 571 | case R_MICROMIPS_TLS_DTPREL_HI16: | ||
| 572 | case R_MICROMIPS_TLS_TPREL_HI16: | ||
| 573 | writeMicroRelocation32<E>(Loc, Val + 0x8000, 16, 16); | ||
| 380 | break; | 574 | break; |
| 381 | case R_MIPS_HIGHER: | 575 | case R_MIPS_HIGHER: |
| 382 | writeMipsHigher<E>(Loc, Val); | 576 | writeRelocation<E>(Loc, Val + 0x80008000, 16, 32); |
| 383 | break; | 577 | break; |
| 384 | case R_MIPS_HIGHEST: | 578 | case R_MIPS_HIGHEST: |
| 385 | writeMipsHighest<E>(Loc, Val); | 579 | writeRelocation<E>(Loc, Val + 0x800080008000, 16, 48); |
| 580 | break; | ||
| 581 | case R_MICROMIPS_HIGHER: | ||
| 582 | writeMicroRelocation32<E>(Loc, Val + 0x80008000, 16, 32); | ||
| 583 | break; | ||
| 584 | case R_MICROMIPS_HIGHEST: | ||
| 585 | writeMicroRelocation32<E>(Loc, Val + 0x800080008000, 16, 48); | ||
| 386 | break; | 586 | break; |
| 387 | case R_MIPS_JALR: | 587 | case R_MIPS_JALR: |
| 588 | case R_MICROMIPS_JALR: | ||
| 388 | // Ignore this optimization relocation for now | 589 | // Ignore this optimization relocation for now |
| 389 | break; | 590 | break; |
| 390 | case R_MIPS_PC16: | 591 | case R_MIPS_PC16: |
| 391 | applyMipsPcReloc<E, 16, 2>(Loc, Type, Val); | 592 | checkAlignment<4>(Loc, Val, Type); |
| 593 | checkInt<18>(Loc, Val, Type); | ||
| 594 | writeRelocation<E>(Loc, Val, 16, 2); | ||
| 392 | break; | 595 | break; |
| 393 | case R_MIPS_PC19_S2: | 596 | case R_MIPS_PC19_S2: |
| 394 | applyMipsPcReloc<E, 19, 2>(Loc, Type, Val); | 597 | checkAlignment<4>(Loc, Val, Type); |
| 598 | checkInt<21>(Loc, Val, Type); | ||
| 599 | writeRelocation<E>(Loc, Val, 19, 2); | ||
| 395 | break; | 600 | break; |
| 396 | case R_MIPS_PC21_S2: | 601 | case R_MIPS_PC21_S2: |
| 397 | applyMipsPcReloc<E, 21, 2>(Loc, Type, Val); | 602 | checkAlignment<4>(Loc, Val, Type); |
| 603 | checkInt<23>(Loc, Val, Type); | ||
| 604 | writeRelocation<E>(Loc, Val, 21, 2); | ||
| 398 | break; | 605 | break; |
| 399 | case R_MIPS_PC26_S2: | 606 | case R_MIPS_PC26_S2: |
| 400 | applyMipsPcReloc<E, 26, 2>(Loc, Type, Val); | 607 | checkAlignment<4>(Loc, Val, Type); |
| 608 | checkInt<28>(Loc, Val, Type); | ||
| 609 | writeRelocation<E>(Loc, Val, 26, 2); | ||
| 401 | break; | 610 | break; |
| 402 | case R_MIPS_PC32: | 611 | case R_MIPS_PC32: |
| 403 | applyMipsPcReloc<E, 32, 0>(Loc, Type, Val); | 612 | writeRelocation<E>(Loc, Val, 32, 0); |
| 613 | break; | ||
| 614 | case R_MICROMIPS_26_S1: | ||
| 615 | case R_MICROMIPS_PC26_S1: | ||
| 616 | checkInt<27>(Loc, Val, Type); | ||
| 617 | writeMicroRelocation32<E>(Loc, Val, 26, 1); | ||
| 618 | break; | ||
| 619 | case R_MICROMIPS_PC7_S1: | ||
| 620 | checkInt<8>(Loc, Val, Type); | ||
| 621 | writeMicroRelocation16<E>(Loc, Val, 7, 1); | ||
| 622 | break; | ||
| 623 | case R_MICROMIPS_PC10_S1: | ||
| 624 | checkInt<11>(Loc, Val, Type); | ||
| 625 | writeMicroRelocation16<E>(Loc, Val, 10, 1); | ||
| 626 | break; | ||
| 627 | case R_MICROMIPS_PC16_S1: | ||
| 628 | checkInt<17>(Loc, Val, Type); | ||
| 629 | writeMicroRelocation32<E>(Loc, Val, 16, 1); | ||
| 630 | break; | ||
| 631 | case R_MICROMIPS_PC18_S3: | ||
| 632 | checkInt<21>(Loc, Val, Type); | ||
| 633 | writeMicroRelocation32<E>(Loc, Val, 18, 3); | ||
| 634 | break; | ||
| 635 | case R_MICROMIPS_PC19_S2: | ||
| 636 | checkInt<21>(Loc, Val, Type); | ||
| 637 | writeMicroRelocation32<E>(Loc, Val, 19, 2); | ||
| 638 | break; | ||
| 639 | case R_MICROMIPS_PC21_S1: | ||
| 640 | checkInt<22>(Loc, Val, Type); | ||
| 641 | writeMicroRelocation32<E>(Loc, Val, 21, 1); | ||
| 642 | break; | ||
| 643 | case R_MICROMIPS_PC23_S2: | ||
| 644 | checkInt<25>(Loc, Val, Type); | ||
| 645 | writeMicroRelocation32<E>(Loc, Val, 23, 2); | ||
| 404 | break; | 646 | break; |
| 405 | default: | 647 | default: |
| 406 | error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); | 648 | error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); |
| 407 | } | 649 | } |
| 408 | } | 650 | } |
| 409 | 651 | ||
| 410 | template <class ELFT> | 652 | template <class ELFT> bool MIPS<ELFT>::usesOnlyLowPageBits(RelType Type) const { |
| 411 | bool MIPS<ELFT>::usesOnlyLowPageBits(uint32_t Type) const { | 653 | return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST || |
| 412 | return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST; | 654 | Type == R_MICROMIPS_LO16 || Type == R_MICROMIPS_GOT_OFST; |
| 655 | } | ||
| 656 | |||
| 657 | // Return true if the symbol is a PIC function. | ||
| 658 | template <class ELFT> bool elf::isMipsPIC(const Defined *Sym) { | ||
| 659 | typedef typename ELFT::Ehdr Elf_Ehdr; | ||
| 660 | if (!Sym->Section || !Sym->isFunc()) | ||
| 661 | return false; | ||
| 662 | |||
| 663 | auto *Sec = cast<InputSectionBase>(Sym->Section); | ||
| 664 | const Elf_Ehdr *Hdr = Sec->template getFile<ELFT>()->getObj().getHeader(); | ||
| 665 | return (Sym->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC || | ||
| 666 | (Hdr->e_flags & EF_MIPS_PIC); | ||
| 413 | } | 667 | } |
| 414 | 668 | ||
| 415 | template <class ELFT> TargetInfo *elf::getMipsTargetInfo() { | 669 | template <class ELFT> TargetInfo *elf::getMipsTargetInfo() { |
| ... | @@ -421,3 +675,8 @@ template TargetInfo *elf::getMipsTargetInfo<ELF32LE>(); | ... | @@ -421,3 +675,8 @@ template TargetInfo *elf::getMipsTargetInfo<ELF32LE>(); |
| 421 | template TargetInfo *elf::getMipsTargetInfo<ELF32BE>(); | 675 | template TargetInfo *elf::getMipsTargetInfo<ELF32BE>(); |
| 422 | template TargetInfo *elf::getMipsTargetInfo<ELF64LE>(); | 676 | template TargetInfo *elf::getMipsTargetInfo<ELF64LE>(); |
| 423 | template TargetInfo *elf::getMipsTargetInfo<ELF64BE>(); | 677 | template TargetInfo *elf::getMipsTargetInfo<ELF64BE>(); |
| 678 | |||
| 679 | template bool elf::isMipsPIC<ELF32LE>(const Defined *); | ||
| 680 | template bool elf::isMipsPIC<ELF32BE>(const Defined *); | ||
| 681 | template bool elf::isMipsPIC<ELF64LE>(const Defined *); | ||
| 682 | template bool elf::isMipsPIC<ELF64BE>(const Defined *); |
deps/lld/ELF/Arch/MipsArchTree.cpp+34-20| ... | @@ -11,11 +11,11 @@ | ... | @@ -11,11 +11,11 @@ |
| 11 | // | 11 | // |
| 12 | //===---------------------------------------------------------------------===// | 12 | //===---------------------------------------------------------------------===// |
| 13 | 13 | ||
| 14 | #include "Error.h" | ||
| 15 | #include "InputFiles.h" | 14 | #include "InputFiles.h" |
| 16 | #include "SymbolTable.h" | 15 | #include "SymbolTable.h" |
| 17 | #include "Writer.h" | 16 | #include "Writer.h" |
| 18 | 17 | ||
| 18 | #include "lld/Common/ErrorHandler.h" | ||
| 19 | #include "llvm/BinaryFormat/ELF.h" | 19 | #include "llvm/BinaryFormat/ELF.h" |
| 20 | #include "llvm/Object/ELF.h" | 20 | #include "llvm/Object/ELF.h" |
| 21 | #include "llvm/Support/MipsABIFlags.h" | 21 | #include "llvm/Support/MipsABIFlags.h" |
| ... | @@ -34,7 +34,7 @@ struct ArchTreeEdge { | ... | @@ -34,7 +34,7 @@ struct ArchTreeEdge { |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | struct FileFlags { | 36 | struct FileFlags { |
| 37 | StringRef Filename; | 37 | InputFile *File; |
| 38 | uint32_t Flags; | 38 | uint32_t Flags; |
| 39 | }; | 39 | }; |
| 40 | } // namespace | 40 | } // namespace |
| ... | @@ -73,17 +73,17 @@ static void checkFlags(ArrayRef<FileFlags> Files) { | ... | @@ -73,17 +73,17 @@ static void checkFlags(ArrayRef<FileFlags> Files) { |
| 73 | uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2); | 73 | uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2); |
| 74 | if (ABI != ABI2) | 74 | if (ABI != ABI2) |
| 75 | error("target ABI '" + getAbiName(ABI) + "' is incompatible with '" + | 75 | error("target ABI '" + getAbiName(ABI) + "' is incompatible with '" + |
| 76 | getAbiName(ABI2) + "': " + F.Filename); | 76 | getAbiName(ABI2) + "': " + toString(F.File)); |
| 77 | 77 | ||
| 78 | bool Nan2 = F.Flags & EF_MIPS_NAN2008; | 78 | bool Nan2 = F.Flags & EF_MIPS_NAN2008; |
| 79 | if (Nan != Nan2) | 79 | if (Nan != Nan2) |
| 80 | error("target -mnan=" + getNanName(Nan) + " is incompatible with -mnan=" + | 80 | error("target -mnan=" + getNanName(Nan) + " is incompatible with -mnan=" + |
| 81 | getNanName(Nan2) + ": " + F.Filename); | 81 | getNanName(Nan2) + ": " + toString(F.File)); |
| 82 | 82 | ||
| 83 | bool Fp2 = F.Flags & EF_MIPS_FP64; | 83 | bool Fp2 = F.Flags & EF_MIPS_FP64; |
| 84 | if (Fp != Fp2) | 84 | if (Fp != Fp2) |
| 85 | error("target -mfp" + getFpName(Fp) + " is incompatible with -mfp" + | 85 | error("target -mfp" + getFpName(Fp) + " is incompatible with -mfp" + |
| 86 | getFpName(Fp2) + ": " + F.Filename); | 86 | getFpName(Fp2) + ": " + toString(F.File)); |
| 87 | } | 87 | } |
| 88 | } | 88 | } |
| 89 | 89 | ||
| ... | @@ -102,9 +102,11 @@ static uint32_t getPicFlags(ArrayRef<FileFlags> Files) { | ... | @@ -102,9 +102,11 @@ static uint32_t getPicFlags(ArrayRef<FileFlags> Files) { |
| 102 | for (const FileFlags &F : Files.slice(1)) { | 102 | for (const FileFlags &F : Files.slice(1)) { |
| 103 | bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC); | 103 | bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC); |
| 104 | if (IsPic && !IsPic2) | 104 | if (IsPic && !IsPic2) |
| 105 | warn("linking abicalls code with non-abicalls file: " + F.Filename); | 105 | warn("linking abicalls code " + toString(Files[0].File) + |
| 106 | " with non-abicalls file: " + toString(F.File)); | ||
| 106 | if (!IsPic && IsPic2) | 107 | if (!IsPic && IsPic2) |
| 107 | warn("linking non-abicalls code with abicalls file: " + F.Filename); | 108 | warn("linking non-abicalls code " + toString(Files[0].File) + |
| 109 | " with abicalls file: " + toString(F.File)); | ||
| 108 | } | 110 | } |
| 109 | 111 | ||
| 110 | // Compute the result PIC/non-PIC flag. | 112 | // Compute the result PIC/non-PIC flag. |
| ... | @@ -221,10 +223,6 @@ static StringRef getMachName(uint32_t Flags) { | ... | @@ -221,10 +223,6 @@ static StringRef getMachName(uint32_t Flags) { |
| 221 | } | 223 | } |
| 222 | 224 | ||
| 223 | static StringRef getArchName(uint32_t Flags) { | 225 | static StringRef getArchName(uint32_t Flags) { |
| 224 | StringRef S = getMachName(Flags); | ||
| 225 | if (!S.empty()) | ||
| 226 | return S; | ||
| 227 | |||
| 228 | switch (Flags & EF_MIPS_ARCH) { | 226 | switch (Flags & EF_MIPS_ARCH) { |
| 229 | case EF_MIPS_ARCH_1: | 227 | case EF_MIPS_ARCH_1: |
| 230 | return "mips1"; | 228 | return "mips1"; |
| ... | @@ -253,6 +251,14 @@ static StringRef getArchName(uint32_t Flags) { | ... | @@ -253,6 +251,14 @@ static StringRef getArchName(uint32_t Flags) { |
| 253 | } | 251 | } |
| 254 | } | 252 | } |
| 255 | 253 | ||
| 254 | static std::string getFullArchName(uint32_t Flags) { | ||
| 255 | StringRef Arch = getArchName(Flags); | ||
| 256 | StringRef Mach = getMachName(Flags); | ||
| 257 | if (Mach.empty()) | ||
| 258 | return Arch.str(); | ||
| 259 | return (Arch + " (" + Mach + ")").str(); | ||
| 260 | } | ||
| 261 | |||
| 256 | // There are (arguably too) many MIPS ISAs out there. Their relationships | 262 | // There are (arguably too) many MIPS ISAs out there. Their relationships |
| 257 | // can be represented as a forest. If all input files have ISAs which | 263 | // can be represented as a forest. If all input files have ISAs which |
| 258 | // reachable by repeated proceeding from the single child to the parent, | 264 | // reachable by repeated proceeding from the single child to the parent, |
| ... | @@ -272,8 +278,9 @@ static uint32_t getArchFlags(ArrayRef<FileFlags> Files) { | ... | @@ -272,8 +278,9 @@ static uint32_t getArchFlags(ArrayRef<FileFlags> Files) { |
| 272 | if (isArchMatched(New, Ret)) | 278 | if (isArchMatched(New, Ret)) |
| 273 | continue; | 279 | continue; |
| 274 | if (!isArchMatched(Ret, New)) { | 280 | if (!isArchMatched(Ret, New)) { |
| 275 | error("target ISA '" + getArchName(Ret) + "' is incompatible with '" + | 281 | error("incompatible target ISA:\n>>> " + toString(Files[0].File) + ": " + |
| 276 | getArchName(New) + "': " + F.Filename); | 282 | getFullArchName(Ret) + "\n>>> " + toString(F.File) + ": " + |
| 283 | getFullArchName(New)); | ||
| 277 | return 0; | 284 | return 0; |
| 278 | } | 285 | } |
| 279 | Ret = New; | 286 | Ret = New; |
| ... | @@ -281,10 +288,10 @@ static uint32_t getArchFlags(ArrayRef<FileFlags> Files) { | ... | @@ -281,10 +288,10 @@ static uint32_t getArchFlags(ArrayRef<FileFlags> Files) { |
| 281 | return Ret; | 288 | return Ret; |
| 282 | } | 289 | } |
| 283 | 290 | ||
| 284 | template <class ELFT> uint32_t elf::getMipsEFlags() { | 291 | template <class ELFT> uint32_t elf::calcMipsEFlags() { |
| 285 | std::vector<FileFlags> V; | 292 | std::vector<FileFlags> V; |
| 286 | for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) | 293 | for (InputFile *F : ObjectFiles) |
| 287 | V.push_back({F->getName(), F->getObj().getHeader()->e_flags}); | 294 | V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags}); |
| 288 | if (V.empty()) | 295 | if (V.empty()) |
| 289 | return 0; | 296 | return 0; |
| 290 | checkFlags(V); | 297 | checkFlags(V); |
| ... | @@ -363,7 +370,14 @@ bool elf::isMipsN32Abi(const InputFile *F) { | ... | @@ -363,7 +370,14 @@ bool elf::isMipsN32Abi(const InputFile *F) { |
| 363 | } | 370 | } |
| 364 | } | 371 | } |
| 365 | 372 | ||
| 366 | template uint32_t elf::getMipsEFlags<ELF32LE>(); | 373 | bool elf::isMicroMips() { return Config->EFlags & EF_MIPS_MICROMIPS; } |
| 367 | template uint32_t elf::getMipsEFlags<ELF32BE>(); | 374 | |
| 368 | template uint32_t elf::getMipsEFlags<ELF64LE>(); | 375 | bool elf::isMipsR6() { |
| 369 | template uint32_t elf::getMipsEFlags<ELF64BE>(); | 376 | uint32_t Arch = Config->EFlags & EF_MIPS_ARCH; |
| 377 | return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6; | ||
| 378 | } | ||
| 379 | |||
| 380 | template uint32_t elf::calcMipsEFlags<ELF32LE>(); | ||
| 381 | template uint32_t elf::calcMipsEFlags<ELF32BE>(); | ||
| 382 | template uint32_t elf::calcMipsEFlags<ELF64LE>(); | ||
| 383 | template uint32_t elf::calcMipsEFlags<ELF64BE>(); |
deps/lld/ELF/Arch/PPC.cpp+21-15| ... | @@ -7,9 +7,9 @@ | ... | @@ -7,9 +7,9 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "Symbols.h" | 10 | #include "Symbols.h" |
| 12 | #include "Target.h" | 11 | #include "Target.h" |
| 12 | #include "lld/Common/ErrorHandler.h" | ||
| 13 | #include "llvm/Support/Endian.h" | 13 | #include "llvm/Support/Endian.h" |
| 14 | 14 | ||
| 15 | using namespace llvm; | 15 | using namespace llvm; |
| ... | @@ -22,17 +22,33 @@ namespace { | ... | @@ -22,17 +22,33 @@ namespace { |
| 22 | class PPC final : public TargetInfo { | 22 | class PPC final : public TargetInfo { |
| 23 | public: | 23 | public: |
| 24 | PPC() { GotBaseSymOff = 0x8000; } | 24 | PPC() { GotBaseSymOff = 0x8000; } |
| 25 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 25 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 26 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 26 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 27 | const uint8_t *Loc) const override; | 27 | const uint8_t *Loc) const override; |
| 28 | }; | 28 | }; |
| 29 | } // namespace | 29 | } // namespace |
| 30 | 30 | ||
| 31 | void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 31 | RelExpr PPC::getRelExpr(RelType Type, const Symbol &S, |
| 32 | const uint8_t *Loc) const { | ||
| 33 | switch (Type) { | ||
| 34 | case R_PPC_REL24: | ||
| 35 | case R_PPC_REL32: | ||
| 36 | return R_PC; | ||
| 37 | case R_PPC_PLTREL24: | ||
| 38 | return R_PLT_PC; | ||
| 39 | default: | ||
| 40 | return R_ABS; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { | ||
| 32 | switch (Type) { | 45 | switch (Type) { |
| 33 | case R_PPC_ADDR16_HA: | 46 | case R_PPC_ADDR16_HA: |
| 34 | write16be(Loc, (Val + 0x8000) >> 16); | 47 | write16be(Loc, (Val + 0x8000) >> 16); |
| 35 | break; | 48 | break; |
| 49 | case R_PPC_ADDR16_HI: | ||
| 50 | write16be(Loc, Val >> 16); | ||
| 51 | break; | ||
| 36 | case R_PPC_ADDR16_LO: | 52 | case R_PPC_ADDR16_LO: |
| 37 | write16be(Loc, Val); | 53 | write16be(Loc, Val); |
| 38 | break; | 54 | break; |
| ... | @@ -40,6 +56,7 @@ void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -40,6 +56,7 @@ void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 40 | case R_PPC_REL32: | 56 | case R_PPC_REL32: |
| 41 | write32be(Loc, Val); | 57 | write32be(Loc, Val); |
| 42 | break; | 58 | break; |
| 59 | case R_PPC_PLTREL24: | ||
| 43 | case R_PPC_REL24: | 60 | case R_PPC_REL24: |
| 44 | write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC)); | 61 | write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC)); |
| 45 | break; | 62 | break; |
| ... | @@ -48,17 +65,6 @@ void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -48,17 +65,6 @@ void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 48 | } | 65 | } |
| 49 | } | 66 | } |
| 50 | 67 | ||
| 51 | RelExpr PPC::getRelExpr(uint32_t Type, const SymbolBody &S, | ||
| 52 | const uint8_t *Loc) const { | ||
| 53 | switch (Type) { | ||
| 54 | case R_PPC_REL24: | ||
| 55 | case R_PPC_REL32: | ||
| 56 | return R_PC; | ||
| 57 | default: | ||
| 58 | return R_ABS; | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | TargetInfo *elf::getPPCTargetInfo() { | 68 | TargetInfo *elf::getPPCTargetInfo() { |
| 63 | static PPC Target; | 69 | static PPC Target; |
| 64 | return &Target; | 70 | return &Target; |
deps/lld/ELF/Arch/PPC64.cpp+8-8| ... | @@ -7,10 +7,10 @@ | ... | @@ -7,10 +7,10 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "Symbols.h" | 10 | #include "Symbols.h" |
| 12 | #include "SyntheticSections.h" | 11 | #include "SyntheticSections.h" |
| 13 | #include "Target.h" | 12 | #include "Target.h" |
| 13 | #include "lld/Common/ErrorHandler.h" | ||
| 14 | #include "llvm/Support/Endian.h" | 14 | #include "llvm/Support/Endian.h" |
| 15 | 15 | ||
| 16 | using namespace llvm; | 16 | using namespace llvm; |
| ... | @@ -39,11 +39,11 @@ namespace { | ... | @@ -39,11 +39,11 @@ namespace { |
| 39 | class PPC64 final : public TargetInfo { | 39 | class PPC64 final : public TargetInfo { |
| 40 | public: | 40 | public: |
| 41 | PPC64(); | 41 | PPC64(); |
| 42 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 42 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 43 | const uint8_t *Loc) const override; | 43 | const uint8_t *Loc) const override; |
| 44 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | 44 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, |
| 45 | int32_t Index, unsigned RelOff) const override; | 45 | int32_t Index, unsigned RelOff) const override; |
| 46 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 46 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 47 | }; | 47 | }; |
| 48 | } // namespace | 48 | } // namespace |
| 49 | 49 | ||
| ... | @@ -82,11 +82,9 @@ PPC64::PPC64() { | ... | @@ -82,11 +82,9 @@ PPC64::PPC64() { |
| 82 | DefaultImageBase = 0x10000000; | 82 | DefaultImageBase = 0x10000000; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | RelExpr PPC64::getRelExpr(uint32_t Type, const SymbolBody &S, | 85 | RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S, |
| 86 | const uint8_t *Loc) const { | 86 | const uint8_t *Loc) const { |
| 87 | switch (Type) { | 87 | switch (Type) { |
| 88 | default: | ||
| 89 | return R_ABS; | ||
| 90 | case R_PPC64_TOC16: | 88 | case R_PPC64_TOC16: |
| 91 | case R_PPC64_TOC16_DS: | 89 | case R_PPC64_TOC16_DS: |
| 92 | case R_PPC64_TOC16_HA: | 90 | case R_PPC64_TOC16_HA: |
| ... | @@ -98,6 +96,8 @@ RelExpr PPC64::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -98,6 +96,8 @@ RelExpr PPC64::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 98 | return R_PPC_TOC; | 96 | return R_PPC_TOC; |
| 99 | case R_PPC64_REL24: | 97 | case R_PPC64_REL24: |
| 100 | return R_PPC_PLT_OPD; | 98 | return R_PPC_PLT_OPD; |
| 99 | default: | ||
| 100 | return R_ABS; | ||
| 101 | } | 101 | } |
| 102 | } | 102 | } |
| 103 | 103 | ||
| ... | @@ -122,7 +122,7 @@ void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ... | @@ -122,7 +122,7 @@ void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 122 | write32be(Buf + 28, 0x4e800420); // bctr | 122 | write32be(Buf + 28, 0x4e800420); // bctr |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static std::pair<uint32_t, uint64_t> toAddr16Rel(uint32_t Type, uint64_t Val) { | 125 | static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) { |
| 126 | uint64_t V = Val - PPC64TocOffset; | 126 | uint64_t V = Val - PPC64TocOffset; |
| 127 | switch (Type) { | 127 | switch (Type) { |
| 128 | case R_PPC64_TOC16: | 128 | case R_PPC64_TOC16: |
| ... | @@ -142,7 +142,7 @@ static std::pair<uint32_t, uint64_t> toAddr16Rel(uint32_t Type, uint64_t Val) { | ... | @@ -142,7 +142,7 @@ static std::pair<uint32_t, uint64_t> toAddr16Rel(uint32_t Type, uint64_t Val) { |
| 142 | } | 142 | } |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | void PPC64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 145 | void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 146 | // For a TOC-relative relocation, proceed in terms of the corresponding | 146 | // For a TOC-relative relocation, proceed in terms of the corresponding |
| 147 | // ADDR16 relocation type. | 147 | // ADDR16 relocation type. |
| 148 | std::tie(Type, Val) = toAddr16Rel(Type, Val); | 148 | std::tie(Type, Val) = toAddr16Rel(Type, Val); |
deps/lld/ELF/Arch/SPARCV9.cpp+6-7| ... | @@ -7,11 +7,11 @@ | ... | @@ -7,11 +7,11 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "InputFiles.h" | 10 | #include "InputFiles.h" |
| 12 | #include "Symbols.h" | 11 | #include "Symbols.h" |
| 13 | #include "SyntheticSections.h" | 12 | #include "SyntheticSections.h" |
| 14 | #include "Target.h" | 13 | #include "Target.h" |
| 14 | #include "lld/Common/ErrorHandler.h" | ||
| 15 | #include "llvm/Support/Endian.h" | 15 | #include "llvm/Support/Endian.h" |
| 16 | 16 | ||
| 17 | using namespace llvm; | 17 | using namespace llvm; |
| ... | @@ -24,11 +24,11 @@ namespace { | ... | @@ -24,11 +24,11 @@ namespace { |
| 24 | class SPARCV9 final : public TargetInfo { | 24 | class SPARCV9 final : public TargetInfo { |
| 25 | public: | 25 | public: |
| 26 | SPARCV9(); | 26 | SPARCV9(); |
| 27 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 27 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 28 | const uint8_t *Loc) const override; | 28 | const uint8_t *Loc) const override; |
| 29 | void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, | 29 | void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, |
| 30 | int32_t Index, unsigned RelOff) const override; | 30 | int32_t Index, unsigned RelOff) const override; |
| 31 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 31 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 32 | }; | 32 | }; |
| 33 | } // namespace | 33 | } // namespace |
| 34 | 34 | ||
| ... | @@ -46,7 +46,7 @@ SPARCV9::SPARCV9() { | ... | @@ -46,7 +46,7 @@ SPARCV9::SPARCV9() { |
| 46 | DefaultImageBase = 0x100000; | 46 | DefaultImageBase = 0x100000; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | RelExpr SPARCV9::getRelExpr(uint32_t Type, const SymbolBody &S, | 49 | RelExpr SPARCV9::getRelExpr(RelType Type, const Symbol &S, |
| 50 | const uint8_t *Loc) const { | 50 | const uint8_t *Loc) const { |
| 51 | switch (Type) { | 51 | switch (Type) { |
| 52 | case R_SPARC_32: | 52 | case R_SPARC_32: |
| ... | @@ -68,12 +68,11 @@ RelExpr SPARCV9::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -68,12 +68,11 @@ RelExpr SPARCV9::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 68 | case R_SPARC_NONE: | 68 | case R_SPARC_NONE: |
| 69 | return R_NONE; | 69 | return R_NONE; |
| 70 | default: | 70 | default: |
| 71 | error(toString(S.File) + ": unknown relocation type: " + toString(Type)); | 71 | return R_INVALID; |
| 72 | return R_HINT; | ||
| 73 | } | 72 | } |
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | void SPARCV9::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 75 | void SPARCV9::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 77 | switch (Type) { | 76 | switch (Type) { |
| 78 | case R_SPARC_32: | 77 | case R_SPARC_32: |
| 79 | case R_SPARC_UA32: | 78 | case R_SPARC_UA32: |
deps/lld/ELF/Arch/X86.cpp+98-57| ... | @@ -7,11 +7,11 @@ | ... | @@ -7,11 +7,11 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "InputFiles.h" | 10 | #include "InputFiles.h" |
| 12 | #include "Symbols.h" | 11 | #include "Symbols.h" |
| 13 | #include "SyntheticSections.h" | 12 | #include "SyntheticSections.h" |
| 14 | #include "Target.h" | 13 | #include "Target.h" |
| 14 | #include "lld/Common/ErrorHandler.h" | ||
| 15 | #include "llvm/Support/Endian.h" | 15 | #include "llvm/Support/Endian.h" |
| 16 | 16 | ||
| 17 | using namespace llvm; | 17 | using namespace llvm; |
| ... | @@ -24,24 +24,24 @@ namespace { | ... | @@ -24,24 +24,24 @@ namespace { |
| 24 | class X86 final : public TargetInfo { | 24 | class X86 final : public TargetInfo { |
| 25 | public: | 25 | public: |
| 26 | X86(); | 26 | X86(); |
| 27 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 27 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 28 | const uint8_t *Loc) const override; | 28 | const uint8_t *Loc) const override; |
| 29 | int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; | 29 | int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; |
| 30 | void writeGotPltHeader(uint8_t *Buf) const override; | 30 | void writeGotPltHeader(uint8_t *Buf) const override; |
| 31 | uint32_t getDynRel(uint32_t Type) const override; | 31 | RelType getDynRel(RelType Type) const override; |
| 32 | void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; | 32 | void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; |
| 33 | void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override; | 33 | void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override; |
| 34 | void writePltHeader(uint8_t *Buf) const override; | 34 | void writePltHeader(uint8_t *Buf) const override; |
| 35 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | 35 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, |
| 36 | int32_t Index, unsigned RelOff) const override; | 36 | int32_t Index, unsigned RelOff) const override; |
| 37 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 37 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 38 | 38 | ||
| 39 | RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | 39 | RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 40 | RelExpr Expr) const override; | 40 | RelExpr Expr) const override; |
| 41 | void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 41 | void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 42 | void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 42 | void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 43 | void relaxTlsIeToLe(uint8_t *Loc, uint32_t 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, uint32_t Type, uint64_t Val) const override; | 44 | void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 45 | }; | 45 | }; |
| 46 | } // namespace | 46 | } // namespace |
| 47 | 47 | ||
| ... | @@ -63,7 +63,9 @@ X86::X86() { | ... | @@ -63,7 +63,9 @@ X86::X86() { |
| 63 | TrapInstr = 0xcccccccc; // 0xcc = INT3 | 63 | TrapInstr = 0xcccccccc; // 0xcc = INT3 |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | RelExpr X86::getRelExpr(uint32_t Type, const SymbolBody &S, | 66 | static bool hasBaseReg(uint8_t ModRM) { return (ModRM & 0xc7) != 0x5; } |
| 67 | |||
| 68 | RelExpr X86::getRelExpr(RelType Type, const Symbol &S, | ||
| 67 | const uint8_t *Loc) const { | 69 | const uint8_t *Loc) const { |
| 68 | switch (Type) { | 70 | switch (Type) { |
| 69 | case R_386_8: | 71 | case R_386_8: |
| ... | @@ -87,24 +89,42 @@ RelExpr X86::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -87,24 +89,42 @@ RelExpr X86::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 87 | return R_GOT; | 89 | return R_GOT; |
| 88 | case R_386_GOT32: | 90 | case R_386_GOT32: |
| 89 | case R_386_GOT32X: | 91 | case R_386_GOT32X: |
| 90 | // These relocations can be calculated in two different ways. | 92 | // These relocations are arguably mis-designed because their calculations |
| 91 | // Usual calculation is G + A - GOT what means an offset in GOT table | 93 | // depend on the instructions they are applied to. This is bad because we |
| 92 | // (R_GOT_FROM_END). When instruction pointed by relocation has no base | 94 | // usually don't care about whether the target section contains valid |
| 93 | // register, then relocations can be used when PIC code is disabled. In that | 95 | // machine instructions or not. But this is part of the documented ABI, so |
| 94 | // case calculation is G + A, it resolves to an address of entry in GOT | 96 | // we had to implement as the standard requires. |
| 95 | // (R_GOT) and not an offset. | ||
| 96 | // | 97 | // |
| 97 | // To check that instruction has no base register we scan ModR/M byte. | 98 | // x86 does not support PC-relative data access. Therefore, in order to |
| 98 | // See "Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte" | 99 | // access GOT contents, a GOT address needs to be known at link-time |
| 99 | // (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/ | 100 | // (which means non-PIC) or compilers have to emit code to get a GOT |
| 100 | // 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf) | 101 | // address at runtime (which means code is position-independent but |
| 101 | if ((Loc[-1] & 0xc7) != 0x5) | 102 | // compilers need to emit extra code for each GOT access.) This decision |
| 102 | return R_GOT_FROM_END; | 103 | // is made at compile-time. In the latter case, compilers emit code to |
| 103 | if (Config->Pic) | 104 | // load an GOT address to a register, which is usually %ebx. |
| 104 | error(toString(S.File) + ": relocation " + toString(Type) + " against '" + | 105 | // |
| 105 | S.getName() + | 106 | // So, there are two ways to refer to symbol foo's GOT entry: foo@GOT or |
| 106 | "' without base register can not be used when PIC enabled"); | 107 | // foo@GOT(%reg). |
| 107 | return R_GOT; | 108 | // |
| 109 | // foo@GOT is not usable in PIC. If we are creating a PIC output and if we | ||
| 110 | // find such relocation, we should report an error. foo@GOT is resolved to | ||
| 111 | // an *absolute* address of foo's GOT entry, because both GOT address and | ||
| 112 | // foo's offset are known. In other words, it's G + A. | ||
| 113 | // | ||
| 114 | // foo@GOT(%reg) needs to be resolved to a *relative* offset from a GOT to | ||
| 115 | // foo's GOT entry in the table, because GOT address is not known but foo's | ||
| 116 | // offset in the table is known. It's G + A - GOT. | ||
| 117 | // | ||
| 118 | // It's unfortunate that compilers emit the same relocation for these | ||
| 119 | // different use cases. In order to distinguish them, we have to read a | ||
| 120 | // machine instruction. | ||
| 121 | // | ||
| 122 | // The following code implements it. We assume that Loc[0] is the first | ||
| 123 | // byte of a displacement or an immediate field of a valid machine | ||
| 124 | // instruction. That means a ModRM byte is at Loc[-1]. By taking a look at | ||
| 125 | // the byte, we can determine whether the instruction is register-relative | ||
| 126 | // (i.e. it was generated for foo@GOT(%reg)) or absolute (i.e. foo@GOT). | ||
| 127 | return hasBaseReg(Loc[-1]) ? R_GOT_FROM_END : R_GOT; | ||
| 108 | case R_386_TLS_GOTIE: | 128 | case R_386_TLS_GOTIE: |
| 109 | return R_GOT_FROM_END; | 129 | return R_GOT_FROM_END; |
| 110 | case R_386_GOTOFF: | 130 | case R_386_GOTOFF: |
| ... | @@ -116,12 +136,11 @@ RelExpr X86::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -116,12 +136,11 @@ RelExpr X86::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 116 | case R_386_NONE: | 136 | case R_386_NONE: |
| 117 | return R_NONE; | 137 | return R_NONE; |
| 118 | default: | 138 | default: |
| 119 | error(toString(S.File) + ": unknown relocation type: " + toString(Type)); | 139 | return R_INVALID; |
| 120 | return R_HINT; | ||
| 121 | } | 140 | } |
| 122 | } | 141 | } |
| 123 | 142 | ||
| 124 | RelExpr X86::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | 143 | RelExpr X86::adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 125 | RelExpr Expr) const { | 144 | RelExpr Expr) const { |
| 126 | switch (Expr) { | 145 | switch (Expr) { |
| 127 | default: | 146 | default: |
| ... | @@ -137,18 +156,18 @@ void X86::writeGotPltHeader(uint8_t *Buf) const { | ... | @@ -137,18 +156,18 @@ void X86::writeGotPltHeader(uint8_t *Buf) const { |
| 137 | write32le(Buf, InX::Dynamic->getVA()); | 156 | write32le(Buf, InX::Dynamic->getVA()); |
| 138 | } | 157 | } |
| 139 | 158 | ||
| 140 | void X86::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const { | 159 | void X86::writeGotPlt(uint8_t *Buf, const Symbol &S) const { |
| 141 | // Entries in .got.plt initially points back to the corresponding | 160 | // Entries in .got.plt initially points back to the corresponding |
| 142 | // PLT entries with a fixed offset to skip the first instruction. | 161 | // PLT entries with a fixed offset to skip the first instruction. |
| 143 | write32le(Buf, S.getPltVA() + 6); | 162 | write32le(Buf, S.getPltVA() + 6); |
| 144 | } | 163 | } |
| 145 | 164 | ||
| 146 | void X86::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const { | 165 | void X86::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { |
| 147 | // An x86 entry is the address of the ifunc resolver function. | 166 | // An x86 entry is the address of the ifunc resolver function. |
| 148 | write32le(Buf, S.getVA()); | 167 | write32le(Buf, S.getVA()); |
| 149 | } | 168 | } |
| 150 | 169 | ||
| 151 | uint32_t X86::getDynRel(uint32_t Type) const { | 170 | RelType X86::getDynRel(RelType Type) const { |
| 152 | if (Type == R_386_TLS_LE) | 171 | if (Type == R_386_TLS_LE) |
| 153 | return R_386_TLS_TPOFF; | 172 | return R_386_TLS_TPOFF; |
| 154 | if (Type == R_386_TLS_LE_32) | 173 | if (Type == R_386_TLS_LE_32) |
| ... | @@ -173,9 +192,9 @@ void X86::writePltHeader(uint8_t *Buf) const { | ... | @@ -173,9 +192,9 @@ void X86::writePltHeader(uint8_t *Buf) const { |
| 173 | } | 192 | } |
| 174 | 193 | ||
| 175 | const uint8_t PltData[] = { | 194 | const uint8_t PltData[] = { |
| 176 | 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushl (GOTPLT+4) | 195 | 0xff, 0x35, 0, 0, 0, 0, // pushl (GOTPLT+4) |
| 177 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *(GOTPLT+8) | 196 | 0xff, 0x25, 0, 0, 0, 0, // jmp *(GOTPLT+8) |
| 178 | 0x90, 0x90, 0x90, 0x90 // nop | 197 | 0x90, 0x90, 0x90, 0x90, // nop |
| 179 | }; | 198 | }; |
| 180 | memcpy(Buf, PltData, sizeof(PltData)); | 199 | memcpy(Buf, PltData, sizeof(PltData)); |
| 181 | uint32_t GotPlt = InX::GotPlt->getVA(); | 200 | uint32_t GotPlt = InX::GotPlt->getVA(); |
| ... | @@ -187,9 +206,9 @@ void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ... | @@ -187,9 +206,9 @@ void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 187 | uint64_t PltEntryAddr, int32_t Index, | 206 | uint64_t PltEntryAddr, int32_t Index, |
| 188 | unsigned RelOff) const { | 207 | unsigned RelOff) const { |
| 189 | const uint8_t Inst[] = { | 208 | const uint8_t Inst[] = { |
| 190 | 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // jmp *foo_in_GOT|*foo@GOT(%ebx) | 209 | 0xff, 0x00, 0, 0, 0, 0, // jmp *foo_in_GOT or jmp *foo@GOT(%ebx) |
| 191 | 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $reloc_offset | 210 | 0x68, 0, 0, 0, 0, // pushl $reloc_offset |
| 192 | 0xe9, 0x00, 0x00, 0x00, 0x00 // jmp .PLT0@PC | 211 | 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC |
| 193 | }; | 212 | }; |
| 194 | memcpy(Buf, Inst, sizeof(Inst)); | 213 | memcpy(Buf, Inst, sizeof(Inst)); |
| 195 | 214 | ||
| ... | @@ -208,10 +227,8 @@ void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ... | @@ -208,10 +227,8 @@ void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 208 | write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); | 227 | write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); |
| 209 | } | 228 | } |
| 210 | 229 | ||
| 211 | int64_t X86::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { | 230 | int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const { |
| 212 | switch (Type) { | 231 | switch (Type) { |
| 213 | default: | ||
| 214 | return 0; | ||
| 215 | case R_386_8: | 232 | case R_386_8: |
| 216 | case R_386_PC8: | 233 | case R_386_PC8: |
| 217 | return SignExtend64<8>(*Buf); | 234 | return SignExtend64<8>(*Buf); |
| ... | @@ -228,15 +245,17 @@ int64_t X86::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { | ... | @@ -228,15 +245,17 @@ int64_t X86::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { |
| 228 | case R_386_TLS_LDO_32: | 245 | case R_386_TLS_LDO_32: |
| 229 | case R_386_TLS_LE: | 246 | case R_386_TLS_LE: |
| 230 | return SignExtend64<32>(read32le(Buf)); | 247 | return SignExtend64<32>(read32le(Buf)); |
| 248 | default: | ||
| 249 | return 0; | ||
| 231 | } | 250 | } |
| 232 | } | 251 | } |
| 233 | 252 | ||
| 234 | void X86::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 253 | void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 235 | // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are | ||
| 236 | // being used for some 16-bit programs such as boot loaders, so | ||
| 237 | // we want to support them. | ||
| 238 | switch (Type) { | 254 | switch (Type) { |
| 239 | case R_386_8: | 255 | case R_386_8: |
| 256 | // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are | ||
| 257 | // being used for some 16-bit programs such as boot loaders, so | ||
| 258 | // we want to support them. | ||
| 240 | checkUInt<8>(Loc, Val, Type); | 259 | checkUInt<8>(Loc, Val, Type); |
| 241 | *Loc = Val; | 260 | *Loc = Val; |
| 242 | break; | 261 | break; |
| ... | @@ -262,13 +281,35 @@ void X86::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -262,13 +281,35 @@ void X86::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 262 | checkInt<17>(Loc, Val, Type); | 281 | checkInt<17>(Loc, Val, Type); |
| 263 | write16le(Loc, Val); | 282 | write16le(Loc, Val); |
| 264 | break; | 283 | break; |
| 265 | default: | 284 | case R_386_32: |
| 285 | case R_386_GLOB_DAT: | ||
| 286 | case R_386_GOT32: | ||
| 287 | case R_386_GOT32X: | ||
| 288 | case R_386_GOTOFF: | ||
| 289 | case R_386_GOTPC: | ||
| 290 | case R_386_PC32: | ||
| 291 | case R_386_PLT32: | ||
| 292 | case R_386_RELATIVE: | ||
| 293 | case R_386_TLS_DTPMOD32: | ||
| 294 | case R_386_TLS_DTPOFF32: | ||
| 295 | case R_386_TLS_GD: | ||
| 296 | case R_386_TLS_GOTIE: | ||
| 297 | case R_386_TLS_IE: | ||
| 298 | case R_386_TLS_LDM: | ||
| 299 | case R_386_TLS_LDO_32: | ||
| 300 | case R_386_TLS_LE: | ||
| 301 | case R_386_TLS_LE_32: | ||
| 302 | case R_386_TLS_TPOFF: | ||
| 303 | case R_386_TLS_TPOFF32: | ||
| 266 | checkInt<32>(Loc, Val, Type); | 304 | checkInt<32>(Loc, Val, Type); |
| 267 | write32le(Loc, Val); | 305 | write32le(Loc, Val); |
| 306 | break; | ||
| 307 | default: | ||
| 308 | error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); | ||
| 268 | } | 309 | } |
| 269 | } | 310 | } |
| 270 | 311 | ||
| 271 | void X86::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 312 | void X86::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 272 | // Convert | 313 | // Convert |
| 273 | // leal x@tlsgd(, %ebx, 1), | 314 | // leal x@tlsgd(, %ebx, 1), |
| 274 | // call __tls_get_addr@plt | 315 | // call __tls_get_addr@plt |
| ... | @@ -277,13 +318,13 @@ void X86::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -277,13 +318,13 @@ void X86::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 277 | // subl $x@ntpoff,%eax | 318 | // subl $x@ntpoff,%eax |
| 278 | const uint8_t Inst[] = { | 319 | const uint8_t Inst[] = { |
| 279 | 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax | 320 | 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax |
| 280 | 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax | 321 | 0x81, 0xe8, 0, 0, 0, 0, // subl Val(%ebx), %eax |
| 281 | }; | 322 | }; |
| 282 | memcpy(Loc - 3, Inst, sizeof(Inst)); | 323 | memcpy(Loc - 3, Inst, sizeof(Inst)); |
| 283 | write32le(Loc + 5, Val); | 324 | write32le(Loc + 5, Val); |
| 284 | } | 325 | } |
| 285 | 326 | ||
| 286 | void X86::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 327 | void X86::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 287 | // Convert | 328 | // Convert |
| 288 | // leal x@tlsgd(, %ebx, 1), | 329 | // leal x@tlsgd(, %ebx, 1), |
| 289 | // call __tls_get_addr@plt | 330 | // call __tls_get_addr@plt |
| ... | @@ -292,7 +333,7 @@ void X86::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -292,7 +333,7 @@ void X86::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 292 | // addl x@gotntpoff(%ebx), %eax | 333 | // addl x@gotntpoff(%ebx), %eax |
| 293 | const uint8_t Inst[] = { | 334 | const uint8_t Inst[] = { |
| 294 | 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax | 335 | 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax |
| 295 | 0x03, 0x83, 0x00, 0x00, 0x00, 0x00 // addl 0(%ebx), %eax | 336 | 0x03, 0x83, 0, 0, 0, 0, // addl Val(%ebx), %eax |
| 296 | }; | 337 | }; |
| 297 | memcpy(Loc - 3, Inst, sizeof(Inst)); | 338 | memcpy(Loc - 3, Inst, sizeof(Inst)); |
| 298 | write32le(Loc + 5, Val); | 339 | write32le(Loc + 5, Val); |
| ... | @@ -300,7 +341,7 @@ void X86::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -300,7 +341,7 @@ void X86::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 300 | 341 | ||
| 301 | // In some conditions, relocations can be optimized to avoid using GOT. | 342 | // In some conditions, relocations can be optimized to avoid using GOT. |
| 302 | // This function does that for Initial Exec to Local Exec case. | 343 | // This function does that for Initial Exec to Local Exec case. |
| 303 | void X86::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 344 | void X86::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 304 | // Ulrich's document section 6.2 says that @gotntpoff can | 345 | // Ulrich's document section 6.2 says that @gotntpoff can |
| 305 | // be used with MOVL or ADDL instructions. | 346 | // be used with MOVL or ADDL instructions. |
| 306 | // @indntpoff is similar to @gotntpoff, but for use in | 347 | // @indntpoff is similar to @gotntpoff, but for use in |
| ... | @@ -337,7 +378,7 @@ void X86::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -337,7 +378,7 @@ void X86::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 337 | write32le(Loc, Val); | 378 | write32le(Loc, Val); |
| 338 | } | 379 | } |
| 339 | 380 | ||
| 340 | void X86::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | 381 | void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 341 | if (Type == R_386_TLS_LDO_32) { | 382 | if (Type == R_386_TLS_LDO_32) { |
| 342 | write32le(Loc, Val); | 383 | write32le(Loc, Val); |
| 343 | return; | 384 | return; |
| ... | @@ -353,7 +394,7 @@ void X86::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { | ... | @@ -353,7 +394,7 @@ void X86::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { |
| 353 | const uint8_t Inst[] = { | 394 | const uint8_t Inst[] = { |
| 354 | 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax | 395 | 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax |
| 355 | 0x90, // nop | 396 | 0x90, // nop |
| 356 | 0x8d, 0x74, 0x26, 0x00 // leal 0(%esi,1),%esi | 397 | 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi |
| 357 | }; | 398 | }; |
| 358 | memcpy(Loc - 2, Inst, sizeof(Inst)); | 399 | memcpy(Loc - 2, Inst, sizeof(Inst)); |
| 359 | } | 400 | } |
deps/lld/ELF/Arch/X86_64.cpp+33-35| ... | @@ -7,11 +7,11 @@ | ... | @@ -7,11 +7,11 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Error.h" | ||
| 11 | #include "InputFiles.h" | 10 | #include "InputFiles.h" |
| 12 | #include "Symbols.h" | 11 | #include "Symbols.h" |
| 13 | #include "SyntheticSections.h" | 12 | #include "SyntheticSections.h" |
| 14 | #include "Target.h" | 13 | #include "Target.h" |
| 14 | #include "lld/Common/ErrorHandler.h" | ||
| 15 | #include "llvm/Object/ELF.h" | 15 | #include "llvm/Object/ELF.h" |
| 16 | #include "llvm/Support/Endian.h" | 16 | #include "llvm/Support/Endian.h" |
| 17 | 17 | ||
| ... | @@ -26,23 +26,23 @@ namespace { | ... | @@ -26,23 +26,23 @@ namespace { |
| 26 | template <class ELFT> class X86_64 final : public TargetInfo { | 26 | template <class ELFT> class X86_64 final : public TargetInfo { |
| 27 | public: | 27 | public: |
| 28 | X86_64(); | 28 | X86_64(); |
| 29 | RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 29 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 30 | const uint8_t *Loc) const override; | 30 | const uint8_t *Loc) const override; |
| 31 | bool isPicRel(uint32_t Type) const override; | 31 | bool isPicRel(RelType Type) const override; |
| 32 | void writeGotPltHeader(uint8_t *Buf) const override; | 32 | void writeGotPltHeader(uint8_t *Buf) const override; |
| 33 | void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; | 33 | void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; |
| 34 | void writePltHeader(uint8_t *Buf) const override; | 34 | void writePltHeader(uint8_t *Buf) const override; |
| 35 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | 35 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, |
| 36 | int32_t Index, unsigned RelOff) const override; | 36 | int32_t Index, unsigned RelOff) const override; |
| 37 | void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 37 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 38 | 38 | ||
| 39 | RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | 39 | RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 40 | RelExpr Expr) const override; | 40 | RelExpr Expr) const override; |
| 41 | void relaxGot(uint8_t *Loc, uint64_t Val) const override; | 41 | void relaxGot(uint8_t *Loc, uint64_t Val) const override; |
| 42 | void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 42 | void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 43 | void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 43 | void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 44 | void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 44 | void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 45 | void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; | 45 | void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 46 | 46 | ||
| 47 | private: | 47 | private: |
| 48 | void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, | 48 | void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, |
| ... | @@ -73,7 +73,7 @@ template <class ELFT> X86_64<ELFT>::X86_64() { | ... | @@ -73,7 +73,7 @@ template <class ELFT> X86_64<ELFT>::X86_64() { |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | template <class ELFT> | 75 | template <class ELFT> |
| 76 | RelExpr X86_64<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, | 76 | RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S, |
| 77 | const uint8_t *Loc) const { | 77 | const uint8_t *Loc) const { |
| 78 | switch (Type) { | 78 | switch (Type) { |
| 79 | case R_X86_64_8: | 79 | case R_X86_64_8: |
| ... | @@ -109,8 +109,7 @@ RelExpr X86_64<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, | ... | @@ -109,8 +109,7 @@ RelExpr X86_64<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, |
| 109 | case R_X86_64_NONE: | 109 | case R_X86_64_NONE: |
| 110 | return R_NONE; | 110 | return R_NONE; |
| 111 | default: | 111 | default: |
| 112 | error(toString(S.File) + ": unknown relocation type: " + toString(Type)); | 112 | return R_INVALID; |
| 113 | return R_HINT; | ||
| 114 | } | 113 | } |
| 115 | } | 114 | } |
| 116 | 115 | ||
| ... | @@ -123,16 +122,16 @@ template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const { | ... | @@ -123,16 +122,16 @@ template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const { |
| 123 | } | 122 | } |
| 124 | 123 | ||
| 125 | template <class ELFT> | 124 | template <class ELFT> |
| 126 | void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const { | 125 | void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const { |
| 127 | // See comments in X86TargetInfo::writeGotPlt. | 126 | // See comments in X86::writeGotPlt. |
| 128 | write32le(Buf, S.getPltVA() + 6); | 127 | write32le(Buf, S.getPltVA() + 6); |
| 129 | } | 128 | } |
| 130 | 129 | ||
| 131 | template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const { | 130 | template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const { |
| 132 | const uint8_t PltData[] = { | 131 | const uint8_t PltData[] = { |
| 133 | 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOTPLT+8(%rip) | 132 | 0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip) |
| 134 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOTPLT+16(%rip) | 133 | 0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip) |
| 135 | 0x0f, 0x1f, 0x40, 0x00 // nop | 134 | 0x0f, 0x1f, 0x40, 0x00, // nop |
| 136 | }; | 135 | }; |
| 137 | memcpy(Buf, PltData, sizeof(PltData)); | 136 | memcpy(Buf, PltData, sizeof(PltData)); |
| 138 | uint64_t GotPlt = InX::GotPlt->getVA(); | 137 | uint64_t GotPlt = InX::GotPlt->getVA(); |
| ... | @@ -146,9 +145,9 @@ void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ... | @@ -146,9 +145,9 @@ void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 146 | uint64_t PltEntryAddr, int32_t Index, | 145 | uint64_t PltEntryAddr, int32_t Index, |
| 147 | unsigned RelOff) const { | 146 | unsigned RelOff) const { |
| 148 | const uint8_t Inst[] = { | 147 | const uint8_t Inst[] = { |
| 149 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip) | 148 | 0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip) |
| 150 | 0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index> | 149 | 0x68, 0, 0, 0, 0, // pushq <relocation index> |
| 151 | 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0] | 150 | 0xe9, 0, 0, 0, 0, // jmpq plt[0] |
| 152 | }; | 151 | }; |
| 153 | memcpy(Buf, Inst, sizeof(Inst)); | 152 | memcpy(Buf, Inst, sizeof(Inst)); |
| 154 | 153 | ||
| ... | @@ -157,13 +156,13 @@ void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | ... | @@ -157,13 +156,13 @@ void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 157 | write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); | 156 | write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); |
| 158 | } | 157 | } |
| 159 | 158 | ||
| 160 | template <class ELFT> bool X86_64<ELFT>::isPicRel(uint32_t Type) const { | 159 | template <class ELFT> bool X86_64<ELFT>::isPicRel(RelType Type) const { |
| 161 | return Type != R_X86_64_PC32 && Type != R_X86_64_32 && | 160 | return Type != R_X86_64_PC32 && Type != R_X86_64_32 && |
| 162 | Type != R_X86_64_TPOFF32; | 161 | Type != R_X86_64_TPOFF32; |
| 163 | } | 162 | } |
| 164 | 163 | ||
| 165 | template <class ELFT> | 164 | template <class ELFT> |
| 166 | void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, | 165 | void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, RelType Type, |
| 167 | uint64_t Val) const { | 166 | uint64_t Val) const { |
| 168 | // Convert | 167 | // Convert |
| 169 | // .byte 0x66 | 168 | // .byte 0x66 |
| ... | @@ -176,7 +175,7 @@ void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, | ... | @@ -176,7 +175,7 @@ void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, |
| 176 | // lea x@tpoff,%rax | 175 | // lea x@tpoff,%rax |
| 177 | const uint8_t Inst[] = { | 176 | const uint8_t Inst[] = { |
| 178 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax | 177 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax |
| 179 | 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff,%rax | 178 | 0x48, 0x8d, 0x80, 0, 0, 0, 0, // lea x@tpoff,%rax |
| 180 | }; | 179 | }; |
| 181 | memcpy(Loc - 4, Inst, sizeof(Inst)); | 180 | memcpy(Loc - 4, Inst, sizeof(Inst)); |
| 182 | 181 | ||
| ... | @@ -186,7 +185,7 @@ void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, | ... | @@ -186,7 +185,7 @@ void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, |
| 186 | } | 185 | } |
| 187 | 186 | ||
| 188 | template <class ELFT> | 187 | template <class ELFT> |
| 189 | void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, | 188 | void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, RelType Type, |
| 190 | uint64_t Val) const { | 189 | uint64_t Val) const { |
| 191 | // Convert | 190 | // Convert |
| 192 | // .byte 0x66 | 191 | // .byte 0x66 |
| ... | @@ -199,7 +198,7 @@ void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, | ... | @@ -199,7 +198,7 @@ void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, |
| 199 | // addq x@tpoff,%rax | 198 | // addq x@tpoff,%rax |
| 200 | const uint8_t Inst[] = { | 199 | const uint8_t Inst[] = { |
| 201 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax | 200 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax |
| 202 | 0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax | 201 | 0x48, 0x03, 0x05, 0, 0, 0, 0, // addq x@tpoff,%rax |
| 203 | }; | 202 | }; |
| 204 | memcpy(Loc - 4, Inst, sizeof(Inst)); | 203 | memcpy(Loc - 4, Inst, sizeof(Inst)); |
| 205 | 204 | ||
| ... | @@ -211,7 +210,7 @@ void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, | ... | @@ -211,7 +210,7 @@ void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, |
| 211 | // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to | 210 | // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to |
| 212 | // R_X86_64_TPOFF32 so that it does not use GOT. | 211 | // R_X86_64_TPOFF32 so that it does not use GOT. |
| 213 | template <class ELFT> | 212 | template <class ELFT> |
| 214 | void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, | 213 | void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, RelType Type, |
| 215 | uint64_t Val) const { | 214 | uint64_t Val) const { |
| 216 | uint8_t *Inst = Loc - 3; | 215 | uint8_t *Inst = Loc - 3; |
| 217 | uint8_t Reg = Loc[-1] >> 3; | 216 | uint8_t Reg = Loc[-1] >> 3; |
| ... | @@ -254,7 +253,7 @@ void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, | ... | @@ -254,7 +253,7 @@ void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, |
| 254 | } | 253 | } |
| 255 | 254 | ||
| 256 | template <class ELFT> | 255 | template <class ELFT> |
| 257 | void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, | 256 | void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type, |
| 258 | uint64_t Val) const { | 257 | uint64_t Val) const { |
| 259 | // Convert | 258 | // Convert |
| 260 | // leaq bar@tlsld(%rip), %rdi | 259 | // leaq bar@tlsld(%rip), %rdi |
| ... | @@ -275,16 +274,15 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, | ... | @@ -275,16 +274,15 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, |
| 275 | } | 274 | } |
| 276 | 275 | ||
| 277 | const uint8_t Inst[] = { | 276 | const uint8_t Inst[] = { |
| 278 | 0x66, 0x66, // .word 0x6666 | 277 | 0x66, 0x66, // .word 0x6666 |
| 279 | 0x66, // .byte 0x66 | 278 | 0x66, // .byte 0x66 |
| 280 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax | 279 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax |
| 281 | }; | 280 | }; |
| 282 | memcpy(Loc - 3, Inst, sizeof(Inst)); | 281 | memcpy(Loc - 3, Inst, sizeof(Inst)); |
| 283 | } | 282 | } |
| 284 | 283 | ||
| 285 | template <class ELFT> | 284 | template <class ELFT> |
| 286 | void X86_64<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, | 285 | void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 287 | uint64_t Val) const { | ||
| 288 | switch (Type) { | 286 | switch (Type) { |
| 289 | case R_X86_64_8: | 287 | case R_X86_64_8: |
| 290 | checkUInt<8>(Loc, Val, Type); | 288 | checkUInt<8>(Loc, Val, Type); |
| ... | @@ -323,12 +321,12 @@ void X86_64<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, | ... | @@ -323,12 +321,12 @@ void X86_64<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, |
| 323 | write64le(Loc, Val); | 321 | write64le(Loc, Val); |
| 324 | break; | 322 | break; |
| 325 | default: | 323 | default: |
| 326 | llvm_unreachable("unexpected relocation"); | 324 | error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); |
| 327 | } | 325 | } |
| 328 | } | 326 | } |
| 329 | 327 | ||
| 330 | template <class ELFT> | 328 | template <class ELFT> |
| 331 | RelExpr X86_64<ELFT>::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | 329 | RelExpr X86_64<ELFT>::adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 332 | RelExpr RelExpr) const { | 330 | RelExpr RelExpr) const { |
| 333 | if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX) | 331 | if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX) |
| 334 | return RelExpr; | 332 | return RelExpr; |
deps/lld/ELF/Bits.h created+35| ... | @@ -0,0 +1,35 @@ | ||
| 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 | |||
| 16 | namespace lld { | ||
| 17 | namespace elf { | ||
| 18 | |||
| 19 | inline 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 | |||
| 25 | inline 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+3-14| ... | @@ -7,6 +7,7 @@ if(NOT LLD_BUILT_STANDALONE) | ... | @@ -7,6 +7,7 @@ if(NOT LLD_BUILT_STANDALONE) |
| 7 | endif() | 7 | endif() |
| 8 | 8 | ||
| 9 | add_lld_library(lldELF | 9 | add_lld_library(lldELF |
| 10 | AArch64ErrataFix.cpp | ||
| 10 | Arch/AArch64.cpp | 11 | Arch/AArch64.cpp |
| 11 | Arch/AMDGPU.cpp | 12 | Arch/AMDGPU.cpp |
| 12 | Arch/ARM.cpp | 13 | Arch/ARM.cpp |
| ... | @@ -21,7 +22,6 @@ add_lld_library(lldELF | ... | @@ -21,7 +22,6 @@ add_lld_library(lldELF |
| 21 | Driver.cpp | 22 | Driver.cpp |
| 22 | DriverUtils.cpp | 23 | DriverUtils.cpp |
| 23 | EhFrame.cpp | 24 | EhFrame.cpp |
| 24 | Error.cpp | ||
| 25 | Filesystem.cpp | 25 | Filesystem.cpp |
| 26 | GdbIndex.cpp | 26 | GdbIndex.cpp |
| 27 | ICF.cpp | 27 | ICF.cpp |
| ... | @@ -45,28 +45,17 @@ add_lld_library(lldELF | ... | @@ -45,28 +45,17 @@ add_lld_library(lldELF |
| 45 | 45 | ||
| 46 | LINK_COMPONENTS | 46 | LINK_COMPONENTS |
| 47 | ${LLVM_TARGETS_TO_BUILD} | 47 | ${LLVM_TARGETS_TO_BUILD} |
| 48 | Analysis | ||
| 49 | BinaryFormat | 48 | BinaryFormat |
| 50 | BitReader | ||
| 51 | BitWriter | ||
| 52 | Codegen | ||
| 53 | Core | 49 | Core |
| 54 | DebugInfoDWARF | 50 | DebugInfoDWARF |
| 55 | Demangle | ||
| 56 | IPO | ||
| 57 | Linker | ||
| 58 | LTO | 51 | LTO |
| 52 | MC | ||
| 59 | Object | 53 | Object |
| 60 | Option | 54 | Option |
| 61 | Passes | ||
| 62 | MC | ||
| 63 | Support | 55 | Support |
| 64 | Target | ||
| 65 | TransformUtils | ||
| 66 | 56 | ||
| 67 | LINK_LIBS | 57 | LINK_LIBS |
| 68 | lldConfig | 58 | lldCommon |
| 69 | lldCore | ||
| 70 | ${LLVM_PTHREAD_LIB} | 59 | ${LLVM_PTHREAD_LIB} |
| 71 | 60 | ||
| 72 | DEPENDS | 61 | DEPENDS |
deps/lld/ELF/Config.h+23-17| ... | @@ -24,7 +24,6 @@ namespace lld { | ... | @@ -24,7 +24,6 @@ namespace lld { |
| 24 | namespace elf { | 24 | namespace elf { |
| 25 | 25 | ||
| 26 | class InputFile; | 26 | class InputFile; |
| 27 | struct Symbol; | ||
| 28 | 27 | ||
| 29 | enum ELFKind { | 28 | enum ELFKind { |
| 30 | ELFNoneKind, | 29 | ELFNoneKind, |
| ... | @@ -44,7 +43,10 @@ enum class DiscardPolicy { Default, All, Locals, None }; | ... | @@ -44,7 +43,10 @@ enum class DiscardPolicy { Default, All, Locals, None }; |
| 44 | enum class StripPolicy { None, All, Debug }; | 43 | enum class StripPolicy { None, All, Debug }; |
| 45 | 44 | ||
| 46 | // For --unresolved-symbols. | 45 | // For --unresolved-symbols. |
| 47 | enum class UnresolvedPolicy { ReportError, Warn, WarnAll, Ignore, IgnoreAll }; | 46 | enum class UnresolvedPolicy { ReportError, Warn, Ignore, IgnoreAll }; |
| 47 | |||
| 48 | // For --orphan-handling. | ||
| 49 | enum class OrphanHandlingPolicy { Place, Warn, Error }; | ||
| 48 | 50 | ||
| 49 | // For --sort-section and linkerscript sorting rules. | 51 | // For --sort-section and linkerscript sorting rules. |
| 50 | enum class SortSectionPolicy { Default, None, Alignment, Name, Priority }; | 52 | enum class SortSectionPolicy { Default, None, Alignment, Name, Priority }; |
| ... | @@ -67,21 +69,15 @@ struct VersionDefinition { | ... | @@ -67,21 +69,15 @@ struct VersionDefinition { |
| 67 | size_t NameOff = 0; // Offset in the string table | 69 | size_t NameOff = 0; // Offset in the string table |
| 68 | }; | 70 | }; |
| 69 | 71 | ||
| 70 | // Structure for mapping renamed symbols | ||
| 71 | struct RenamedSymbol { | ||
| 72 | Symbol *Target; | ||
| 73 | uint8_t OriginalBinding; | ||
| 74 | }; | ||
| 75 | |||
| 76 | // This struct contains the global configuration for the linker. | 72 | // This struct contains the global configuration for the linker. |
| 77 | // Most fields are direct mapping from the command line options | 73 | // Most fields are direct mapping from the command line options |
| 78 | // and such fields have the same name as the corresponding options. | 74 | // and such fields have the same name as the corresponding options. |
| 79 | // Most fields are initialized by the driver. | 75 | // Most fields are initialized by the driver. |
| 80 | struct Configuration { | 76 | struct Configuration { |
| 81 | InputFile *FirstElf = nullptr; | ||
| 82 | uint8_t OSABI = 0; | 77 | uint8_t OSABI = 0; |
| 83 | llvm::CachePruningPolicy ThinLTOCachePolicy; | 78 | llvm::CachePruningPolicy ThinLTOCachePolicy; |
| 84 | llvm::StringMap<uint64_t> SectionStartMap; | 79 | llvm::StringMap<uint64_t> SectionStartMap; |
| 80 | llvm::StringRef Chroot; | ||
| 85 | llvm::StringRef DynamicLinker; | 81 | llvm::StringRef DynamicLinker; |
| 86 | llvm::StringRef Entry; | 82 | llvm::StringRef Entry; |
| 87 | llvm::StringRef Emulation; | 83 | llvm::StringRef Emulation; |
| ... | @@ -103,15 +99,18 @@ struct Configuration { | ... | @@ -103,15 +99,18 @@ struct Configuration { |
| 103 | std::vector<llvm::StringRef> SearchPaths; | 99 | std::vector<llvm::StringRef> SearchPaths; |
| 104 | std::vector<llvm::StringRef> SymbolOrderingFile; | 100 | std::vector<llvm::StringRef> SymbolOrderingFile; |
| 105 | std::vector<llvm::StringRef> Undefined; | 101 | std::vector<llvm::StringRef> Undefined; |
| 102 | std::vector<SymbolVersion> DynamicList; | ||
| 106 | std::vector<SymbolVersion> VersionScriptGlobals; | 103 | std::vector<SymbolVersion> VersionScriptGlobals; |
| 107 | std::vector<SymbolVersion> VersionScriptLocals; | 104 | std::vector<SymbolVersion> VersionScriptLocals; |
| 108 | std::vector<uint8_t> BuildIdVector; | 105 | std::vector<uint8_t> BuildIdVector; |
| 109 | llvm::MapVector<Symbol *, RenamedSymbol> RenamedSymbols; | ||
| 110 | bool AllowMultipleDefinition; | 106 | bool AllowMultipleDefinition; |
| 107 | bool AndroidPackDynRelocs = false; | ||
| 108 | bool ARMHasBlx = false; | ||
| 109 | bool ARMHasMovtMovw = false; | ||
| 110 | bool ARMJ1J2BranchEncoding = false; | ||
| 111 | bool AsNeeded = false; | 111 | bool AsNeeded = false; |
| 112 | bool Bsymbolic; | 112 | bool Bsymbolic; |
| 113 | bool BsymbolicFunctions; | 113 | bool BsymbolicFunctions; |
| 114 | bool ColorDiagnostics = false; | ||
| 115 | bool CompressDebugSections; | 114 | bool CompressDebugSections; |
| 116 | bool DefineCommon; | 115 | bool DefineCommon; |
| 117 | bool Demangle = true; | 116 | bool Demangle = true; |
| ... | @@ -120,14 +119,19 @@ struct Configuration { | ... | @@ -120,14 +119,19 @@ struct Configuration { |
| 120 | bool EmitRelocs; | 119 | bool EmitRelocs; |
| 121 | bool EnableNewDtags; | 120 | bool EnableNewDtags; |
| 122 | bool ExportDynamic; | 121 | bool ExportDynamic; |
| 123 | bool FatalWarnings; | 122 | bool FixCortexA53Errata843419; |
| 124 | bool GcSections; | 123 | bool GcSections; |
| 125 | bool GdbIndex; | 124 | bool GdbIndex; |
| 126 | bool GnuHash; | 125 | bool GnuHash = false; |
| 126 | bool HasDynamicList = false; | ||
| 127 | bool HasDynSymTab; | ||
| 127 | bool ICF; | 128 | bool ICF; |
| 129 | bool ICFData; | ||
| 130 | bool MergeArmExidx; | ||
| 128 | bool MipsN32Abi = false; | 131 | bool MipsN32Abi = false; |
| 129 | bool NoGnuUnique; | 132 | bool NoGnuUnique; |
| 130 | bool NoUndefinedVersion; | 133 | bool NoUndefinedVersion; |
| 134 | bool NoinhibitExec; | ||
| 131 | bool Nostdlib; | 135 | bool Nostdlib; |
| 132 | bool OFormatBinary; | 136 | bool OFormatBinary; |
| 133 | bool Omagic; | 137 | bool Omagic; |
| ... | @@ -139,9 +143,8 @@ struct Configuration { | ... | @@ -139,9 +143,8 @@ struct Configuration { |
| 139 | bool SingleRoRx; | 143 | bool SingleRoRx; |
| 140 | bool Shared; | 144 | bool Shared; |
| 141 | bool Static = false; | 145 | bool Static = false; |
| 142 | bool SysvHash; | 146 | bool SysvHash = false; |
| 143 | bool Target1Rel; | 147 | bool Target1Rel; |
| 144 | bool Threads; | ||
| 145 | bool Trace; | 148 | bool Trace; |
| 146 | bool Verbose; | 149 | bool Verbose; |
| 147 | bool WarnCommon; | 150 | bool WarnCommon; |
| ... | @@ -159,6 +162,7 @@ struct Configuration { | ... | @@ -159,6 +162,7 @@ struct Configuration { |
| 159 | bool ExitEarly; | 162 | bool ExitEarly; |
| 160 | bool ZWxneeded; | 163 | bool ZWxneeded; |
| 161 | DiscardPolicy Discard; | 164 | DiscardPolicy Discard; |
| 165 | OrphanHandlingPolicy OrphanHandling; | ||
| 162 | SortSectionPolicy SortSection; | 166 | SortSectionPolicy SortSection; |
| 163 | StripPolicy Strip; | 167 | StripPolicy Strip; |
| 164 | UnresolvedPolicy UnresolvedSymbols; | 168 | UnresolvedPolicy UnresolvedSymbols; |
| ... | @@ -167,8 +171,7 @@ struct Configuration { | ... | @@ -167,8 +171,7 @@ struct Configuration { |
| 167 | ELFKind EKind = ELFNoneKind; | 171 | ELFKind EKind = ELFNoneKind; |
| 168 | uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; | 172 | uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; |
| 169 | uint16_t EMachine = llvm::ELF::EM_NONE; | 173 | uint16_t EMachine = llvm::ELF::EM_NONE; |
| 170 | uint64_t ErrorLimit = 20; | 174 | llvm::Optional<uint64_t> ImageBase; |
| 171 | uint64_t ImageBase; | ||
| 172 | uint64_t MaxPageSize; | 175 | uint64_t MaxPageSize; |
| 173 | uint64_t ZStackSize; | 176 | uint64_t ZStackSize; |
| 174 | unsigned LTOPartitions; | 177 | unsigned LTOPartitions; |
| ... | @@ -206,6 +209,9 @@ struct Configuration { | ... | @@ -206,6 +209,9 @@ struct Configuration { |
| 206 | // if that's true.) | 209 | // if that's true.) |
| 207 | bool IsMips64EL; | 210 | bool IsMips64EL; |
| 208 | 211 | ||
| 212 | // Holds set of ELF header flags for the target. | ||
| 213 | uint32_t EFlags = 0; | ||
| 214 | |||
| 209 | // The ELF spec defines two types of relocation table entries, RELA and | 215 | // The ELF spec defines two types of relocation table entries, RELA and |
| 210 | // REL. RELA is a triplet of (offset, info, addend) while REL is a | 216 | // REL. RELA is a triplet of (offset, info, addend) while REL is a |
| 211 | // tuple of (offset, info). Addends for REL are implicit and read from | 217 | // tuple of (offset, info). Addends for REL are implicit and read from |
deps/lld/ELF/Driver.cpp+277-211| ... | @@ -25,23 +25,25 @@ | ... | @@ -25,23 +25,25 @@ |
| 25 | 25 | ||
| 26 | #include "Driver.h" | 26 | #include "Driver.h" |
| 27 | #include "Config.h" | 27 | #include "Config.h" |
| 28 | #include "Error.h" | ||
| 29 | #include "Filesystem.h" | 28 | #include "Filesystem.h" |
| 30 | #include "ICF.h" | 29 | #include "ICF.h" |
| 31 | #include "InputFiles.h" | 30 | #include "InputFiles.h" |
| 32 | #include "InputSection.h" | 31 | #include "InputSection.h" |
| 33 | #include "LinkerScript.h" | 32 | #include "LinkerScript.h" |
| 34 | #include "Memory.h" | ||
| 35 | #include "OutputSections.h" | 33 | #include "OutputSections.h" |
| 36 | #include "ScriptParser.h" | 34 | #include "ScriptParser.h" |
| 37 | #include "Strings.h" | 35 | #include "Strings.h" |
| 38 | #include "SymbolTable.h" | 36 | #include "SymbolTable.h" |
| 37 | #include "Symbols.h" | ||
| 39 | #include "SyntheticSections.h" | 38 | #include "SyntheticSections.h" |
| 40 | #include "Target.h" | 39 | #include "Target.h" |
| 41 | #include "Threads.h" | ||
| 42 | #include "Writer.h" | 40 | #include "Writer.h" |
| 43 | #include "lld/Config/Version.h" | 41 | #include "lld/Common/Args.h" |
| 44 | #include "lld/Driver/Driver.h" | 42 | #include "lld/Common/Driver.h" |
| 43 | #include "lld/Common/ErrorHandler.h" | ||
| 44 | #include "lld/Common/Memory.h" | ||
| 45 | #include "lld/Common/Threads.h" | ||
| 46 | #include "lld/Common/Version.h" | ||
| 45 | #include "llvm/ADT/StringExtras.h" | 47 | #include "llvm/ADT/StringExtras.h" |
| 46 | #include "llvm/ADT/StringSwitch.h" | 48 | #include "llvm/ADT/StringSwitch.h" |
| 47 | #include "llvm/Support/CommandLine.h" | 49 | #include "llvm/Support/CommandLine.h" |
| ... | @@ -64,27 +66,40 @@ using namespace lld::elf; | ... | @@ -64,27 +66,40 @@ using namespace lld::elf; |
| 64 | Configuration *elf::Config; | 66 | Configuration *elf::Config; |
| 65 | LinkerDriver *elf::Driver; | 67 | LinkerDriver *elf::Driver; |
| 66 | 68 | ||
| 67 | BumpPtrAllocator elf::BAlloc; | ||
| 68 | StringSaver elf::Saver{BAlloc}; | ||
| 69 | std::vector<SpecificAllocBase *> elf::SpecificAllocBase::Instances; | ||
| 70 | |||
| 71 | static void setConfigs(); | 69 | static void setConfigs(); |
| 72 | 70 | ||
| 73 | bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, | 71 | bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, |
| 74 | raw_ostream &Error) { | 72 | raw_ostream &Error) { |
| 75 | ErrorCount = 0; | 73 | errorHandler().LogName = Args[0]; |
| 76 | ErrorOS = &Error; | 74 | errorHandler().ErrorLimitExceededMsg = |
| 75 | "too many errors emitted, stopping now (use " | ||
| 76 | "-error-limit=0 to see all errors)"; | ||
| 77 | errorHandler().ErrorOS = &Error; | ||
| 78 | errorHandler().ColorDiagnostics = Error.has_colors(); | ||
| 77 | InputSections.clear(); | 79 | InputSections.clear(); |
| 80 | OutputSections.clear(); | ||
| 78 | Tar = nullptr; | 81 | Tar = nullptr; |
| 82 | BinaryFiles.clear(); | ||
| 83 | BitcodeFiles.clear(); | ||
| 84 | ObjectFiles.clear(); | ||
| 85 | SharedFiles.clear(); | ||
| 79 | 86 | ||
| 80 | Config = make<Configuration>(); | 87 | Config = make<Configuration>(); |
| 81 | Driver = make<LinkerDriver>(); | 88 | Driver = make<LinkerDriver>(); |
| 82 | Script = make<LinkerScript>(); | 89 | Script = make<LinkerScript>(); |
| 90 | Symtab = make<SymbolTable>(); | ||
| 83 | Config->Argv = {Args.begin(), Args.end()}; | 91 | Config->Argv = {Args.begin(), Args.end()}; |
| 84 | 92 | ||
| 85 | Driver->main(Args, CanExitEarly); | 93 | Driver->main(Args, CanExitEarly); |
| 94 | |||
| 95 | // Exit immediately if we don't need to return to the caller. | ||
| 96 | // This saves time because the overhead of calling destructors | ||
| 97 | // for all globally-allocated objects is not negligible. | ||
| 98 | if (Config->ExitEarly) | ||
| 99 | exitLld(errorCount() ? 1 : 0); | ||
| 100 | |||
| 86 | freeArena(); | 101 | freeArena(); |
| 87 | return !ErrorCount; | 102 | return !errorCount(); |
| 88 | } | 103 | } |
| 89 | 104 | ||
| 90 | // Parses a linker -m option. | 105 | // Parses a linker -m option. |
| ... | @@ -112,12 +127,8 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) { | ... | @@ -112,12 +127,8 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) { |
| 112 | .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) | 127 | .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) |
| 113 | .Default({ELFNoneKind, EM_NONE}); | 128 | .Default({ELFNoneKind, EM_NONE}); |
| 114 | 129 | ||
| 115 | if (Ret.first == ELFNoneKind) { | 130 | if (Ret.first == ELFNoneKind) |
| 116 | if (S == "i386pe" || S == "i386pep" || S == "thumb2pe") | 131 | error("unknown emulation: " + Emul); |
| 117 | error("Windows targets are not supported on the ELF frontend: " + Emul); | ||
| 118 | else | ||
| 119 | error("unknown emulation: " + Emul); | ||
| 120 | } | ||
| 121 | return std::make_tuple(Ret.first, Ret.second, OSABI); | 132 | return std::make_tuple(Ret.first, Ret.second, OSABI); |
| 122 | } | 133 | } |
| 123 | 134 | ||
| ... | @@ -126,19 +137,22 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) { | ... | @@ -126,19 +137,22 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) { |
| 126 | std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers( | 137 | std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers( |
| 127 | MemoryBufferRef MB) { | 138 | MemoryBufferRef MB) { |
| 128 | std::unique_ptr<Archive> File = | 139 | std::unique_ptr<Archive> File = |
| 129 | check(Archive::create(MB), | 140 | CHECK(Archive::create(MB), |
| 130 | MB.getBufferIdentifier() + ": failed to parse archive"); | 141 | MB.getBufferIdentifier() + ": failed to parse archive"); |
| 131 | 142 | ||
| 132 | std::vector<std::pair<MemoryBufferRef, uint64_t>> V; | 143 | std::vector<std::pair<MemoryBufferRef, uint64_t>> V; |
| 133 | Error Err = Error::success(); | 144 | Error Err = Error::success(); |
| 145 | bool AddToTar = File->isThin() && Tar; | ||
| 134 | for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { | 146 | for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { |
| 135 | Archive::Child C = | 147 | Archive::Child C = |
| 136 | check(COrErr, MB.getBufferIdentifier() + | 148 | CHECK(COrErr, MB.getBufferIdentifier() + |
| 137 | ": could not get the child of the archive"); | 149 | ": could not get the child of the archive"); |
| 138 | MemoryBufferRef MBRef = | 150 | MemoryBufferRef MBRef = |
| 139 | check(C.getMemoryBufferRef(), | 151 | CHECK(C.getMemoryBufferRef(), |
| 140 | MB.getBufferIdentifier() + | 152 | MB.getBufferIdentifier() + |
| 141 | ": could not get the buffer for a child of the archive"); | 153 | ": could not get the buffer for a child of the archive"); |
| 154 | if (AddToTar) | ||
| 155 | Tar->append(relativeToRoot(check(C.getFullName())), MBRef.getBuffer()); | ||
| 142 | V.push_back(std::make_pair(MBRef, C.getChildOffset())); | 156 | V.push_back(std::make_pair(MBRef, C.getChildOffset())); |
| 143 | } | 157 | } |
| 144 | if (Err) | 158 | if (Err) |
| ... | @@ -179,7 +193,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { | ... | @@ -179,7 +193,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { |
| 179 | } | 193 | } |
| 180 | 194 | ||
| 181 | std::unique_ptr<Archive> File = | 195 | std::unique_ptr<Archive> File = |
| 182 | check(Archive::create(MBRef), Path + ": failed to parse archive"); | 196 | CHECK(Archive::create(MBRef), Path + ": failed to parse archive"); |
| 183 | 197 | ||
| 184 | // If an archive file has no symbol table, it is likely that a user | 198 | // If an archive file has no symbol table, it is likely that a user |
| 185 | // is attempting LTO and using a default ar command that doesn't | 199 | // is attempting LTO and using a default ar command that doesn't |
| ... | @@ -187,7 +201,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { | ... | @@ -187,7 +201,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { |
| 187 | // we'll handle it as if it had a symbol table. | 201 | // we'll handle it as if it had a symbol table. |
| 188 | if (!File->isEmpty() && !File->hasSymbolTable()) { | 202 | if (!File->isEmpty() && !File->hasSymbolTable()) { |
| 189 | for (const auto &P : getArchiveMembers(MBRef)) | 203 | for (const auto &P : getArchiveMembers(MBRef)) |
| 190 | Files.push_back(make<LazyObjectFile>(P.first, Path, P.second)); | 204 | Files.push_back(make<LazyObjFile>(P.first, Path, P.second)); |
| 191 | return; | 205 | return; |
| 192 | } | 206 | } |
| 193 | 207 | ||
| ... | @@ -216,7 +230,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { | ... | @@ -216,7 +230,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { |
| 216 | return; | 230 | return; |
| 217 | default: | 231 | default: |
| 218 | if (InLib) | 232 | if (InLib) |
| 219 | Files.push_back(make<LazyObjectFile>(MBRef, "", 0)); | 233 | Files.push_back(make<LazyObjFile>(MBRef, "", 0)); |
| 220 | else | 234 | else |
| 221 | Files.push_back(createObjectFile(MBRef)); | 235 | Files.push_back(createObjectFile(MBRef)); |
| 222 | } | 236 | } |
| ... | @@ -256,6 +270,9 @@ static void checkOptions(opt::InputArgList &Args) { | ... | @@ -256,6 +270,9 @@ static void checkOptions(opt::InputArgList &Args) { |
| 256 | if (Config->EMachine == EM_MIPS && Config->GnuHash) | 270 | if (Config->EMachine == EM_MIPS && Config->GnuHash) |
| 257 | error("the .gnu.hash section is not compatible with the MIPS target."); | 271 | error("the .gnu.hash section is not compatible with the MIPS target."); |
| 258 | 272 | ||
| 273 | if (Config->FixCortexA53Errata843419 && Config->EMachine != EM_AARCH64) | ||
| 274 | error("--fix-cortex-a53-843419 is only supported on AArch64 targets."); | ||
| 275 | |||
| 259 | if (Config->Pie && Config->Shared) | 276 | if (Config->Pie && Config->Shared) |
| 260 | error("-shared and -pie may not be used together"); | 277 | error("-shared and -pie may not be used together"); |
| 261 | 278 | ||
| ... | @@ -265,6 +282,9 @@ static void checkOptions(opt::InputArgList &Args) { | ... | @@ -265,6 +282,9 @@ static void checkOptions(opt::InputArgList &Args) { |
| 265 | if (!Config->Shared && !Config->AuxiliaryList.empty()) | 282 | if (!Config->Shared && !Config->AuxiliaryList.empty()) |
| 266 | error("-f may not be used without -shared"); | 283 | error("-f may not be used without -shared"); |
| 267 | 284 | ||
| 285 | if (!Config->Relocatable && !Config->DefineCommon) | ||
| 286 | error("-no-define-common not supported in non relocatable output"); | ||
| 287 | |||
| 268 | if (Config->Relocatable) { | 288 | if (Config->Relocatable) { |
| 269 | if (Config->Shared) | 289 | if (Config->Shared) |
| 270 | error("-r and -shared may not be used together"); | 290 | error("-r and -shared may not be used together"); |
| ... | @@ -277,16 +297,6 @@ static void checkOptions(opt::InputArgList &Args) { | ... | @@ -277,16 +297,6 @@ static void checkOptions(opt::InputArgList &Args) { |
| 277 | } | 297 | } |
| 278 | } | 298 | } |
| 279 | 299 | ||
| 280 | static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) { | ||
| 281 | int V = Default; | ||
| 282 | if (auto *Arg = Args.getLastArg(Key)) { | ||
| 283 | StringRef S = Arg->getValue(); | ||
| 284 | if (!to_integer(S, V, 10)) | ||
| 285 | error(Arg->getSpelling() + ": number expected, but got " + S); | ||
| 286 | } | ||
| 287 | return V; | ||
| 288 | } | ||
| 289 | |||
| 290 | static const char *getReproduceOption(opt::InputArgList &Args) { | 300 | static const char *getReproduceOption(opt::InputArgList &Args) { |
| 291 | if (auto *Arg = Args.getLastArg(OPT_reproduce)) | 301 | if (auto *Arg = Args.getLastArg(OPT_reproduce)) |
| 292 | return Arg->getValue(); | 302 | return Arg->getValue(); |
| ... | @@ -300,26 +310,12 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) { | ... | @@ -300,26 +310,12 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) { |
| 300 | return false; | 310 | return false; |
| 301 | } | 311 | } |
| 302 | 312 | ||
| 303 | static uint64_t getZOptionValue(opt::InputArgList &Args, StringRef Key, | ||
| 304 | uint64_t Default) { | ||
| 305 | for (auto *Arg : Args.filtered(OPT_z)) { | ||
| 306 | std::pair<StringRef, StringRef> KV = StringRef(Arg->getValue()).split('='); | ||
| 307 | if (KV.first == Key) { | ||
| 308 | uint64_t Result = Default; | ||
| 309 | if (!to_integer(KV.second, Result)) | ||
| 310 | error("invalid " + Key + ": " + KV.second); | ||
| 311 | return Result; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | return Default; | ||
| 315 | } | ||
| 316 | |||
| 317 | void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { | 313 | void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { |
| 318 | ELFOptTable Parser; | 314 | ELFOptTable Parser; |
| 319 | opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); | 315 | opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); |
| 320 | 316 | ||
| 321 | // Interpret this flag early because error() depends on them. | 317 | // Interpret this flag early because error() depends on them. |
| 322 | Config->ErrorLimit = getInteger(Args, OPT_error_limit, 20); | 318 | errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); |
| 323 | 319 | ||
| 324 | // Handle -help | 320 | // Handle -help |
| 325 | if (Args.hasArg(OPT_help)) { | 321 | if (Args.hasArg(OPT_help)) { |
| ... | @@ -345,13 +341,15 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { | ... | @@ -345,13 +341,15 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { |
| 345 | if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) | 341 | if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) |
| 346 | message(getLLDVersion() + " (compatible with GNU linkers)"); | 342 | message(getLLDVersion() + " (compatible with GNU linkers)"); |
| 347 | 343 | ||
| 348 | // ld.bfd always exits after printing out the version string. | 344 | // The behavior of -v or --version is a bit strange, but this is |
| 349 | // ld.gold proceeds if a given option is -v. Because gold's behavior | 345 | // needed for compatibility with GNU linkers. |
| 350 | // is more permissive than ld.bfd, we chose what gold does here. | 346 | if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT)) |
| 347 | return; | ||
| 351 | if (Args.hasArg(OPT_version)) | 348 | if (Args.hasArg(OPT_version)) |
| 352 | return; | 349 | return; |
| 353 | 350 | ||
| 354 | Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown); | 351 | Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown); |
| 352 | errorHandler().ExitEarly = Config->ExitEarly; | ||
| 355 | 353 | ||
| 356 | if (const char *Path = getReproduceOption(Args)) { | 354 | if (const char *Path = getReproduceOption(Args)) { |
| 357 | // Note that --reproduce is a debug option so you can ignore it | 355 | // Note that --reproduce is a debug option so you can ignore it |
| ... | @@ -375,7 +373,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { | ... | @@ -375,7 +373,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { |
| 375 | inferMachineType(); | 373 | inferMachineType(); |
| 376 | setConfigs(); | 374 | setConfigs(); |
| 377 | checkOptions(Args); | 375 | checkOptions(Args); |
| 378 | if (ErrorCount) | 376 | if (errorCount()) |
| 379 | return; | 377 | return; |
| 380 | 378 | ||
| 381 | switch (Config->EKind) { | 379 | switch (Config->EKind) { |
| ... | @@ -396,36 +394,19 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { | ... | @@ -396,36 +394,19 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { |
| 396 | } | 394 | } |
| 397 | } | 395 | } |
| 398 | 396 | ||
| 399 | static bool getArg(opt::InputArgList &Args, unsigned K1, unsigned K2, | ||
| 400 | bool Default) { | ||
| 401 | if (auto *Arg = Args.getLastArg(K1, K2)) | ||
| 402 | return Arg->getOption().getID() == K1; | ||
| 403 | return Default; | ||
| 404 | } | ||
| 405 | |||
| 406 | static std::vector<StringRef> getArgs(opt::InputArgList &Args, int Id) { | ||
| 407 | std::vector<StringRef> V; | ||
| 408 | for (auto *Arg : Args.filtered(Id)) | ||
| 409 | V.push_back(Arg->getValue()); | ||
| 410 | return V; | ||
| 411 | } | ||
| 412 | |||
| 413 | static std::string getRpath(opt::InputArgList &Args) { | 397 | static std::string getRpath(opt::InputArgList &Args) { |
| 414 | std::vector<StringRef> V = getArgs(Args, OPT_rpath); | 398 | std::vector<StringRef> V = args::getStrings(Args, OPT_rpath); |
| 415 | return llvm::join(V.begin(), V.end(), ":"); | 399 | return llvm::join(V.begin(), V.end(), ":"); |
| 416 | } | 400 | } |
| 417 | 401 | ||
| 418 | // Determines what we should do if there are remaining unresolved | 402 | // Determines what we should do if there are remaining unresolved |
| 419 | // symbols after the name resolution. | 403 | // symbols after the name resolution. |
| 420 | static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) { | 404 | static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) { |
| 421 | // -noinhibit-exec or -r imply some default values. | ||
| 422 | if (Args.hasArg(OPT_noinhibit_exec)) | ||
| 423 | return UnresolvedPolicy::WarnAll; | ||
| 424 | if (Args.hasArg(OPT_relocatable)) | 405 | if (Args.hasArg(OPT_relocatable)) |
| 425 | return UnresolvedPolicy::IgnoreAll; | 406 | return UnresolvedPolicy::IgnoreAll; |
| 426 | 407 | ||
| 427 | UnresolvedPolicy ErrorOrWarn = getArg(Args, OPT_error_unresolved_symbols, | 408 | UnresolvedPolicy ErrorOrWarn = Args.hasFlag(OPT_error_unresolved_symbols, |
| 428 | OPT_warn_unresolved_symbols, true) | 409 | OPT_warn_unresolved_symbols, true) |
| 429 | ? UnresolvedPolicy::ReportError | 410 | ? UnresolvedPolicy::ReportError |
| 430 | : UnresolvedPolicy::Warn; | 411 | : UnresolvedPolicy::Warn; |
| 431 | 412 | ||
| ... | @@ -513,7 +494,7 @@ static StripPolicy getStrip(opt::InputArgList &Args) { | ... | @@ -513,7 +494,7 @@ static StripPolicy getStrip(opt::InputArgList &Args) { |
| 513 | return StripPolicy::Debug; | 494 | return StripPolicy::Debug; |
| 514 | } | 495 | } |
| 515 | 496 | ||
| 516 | static uint64_t parseSectionAddress(StringRef S, opt::Arg *Arg) { | 497 | static uint64_t parseSectionAddress(StringRef S, const opt::Arg &Arg) { |
| 517 | uint64_t VA = 0; | 498 | uint64_t VA = 0; |
| 518 | if (S.startswith("0x")) | 499 | if (S.startswith("0x")) |
| 519 | S = S.drop_front(2); | 500 | S = S.drop_front(2); |
| ... | @@ -528,15 +509,15 @@ static StringMap<uint64_t> getSectionStartMap(opt::InputArgList &Args) { | ... | @@ -528,15 +509,15 @@ static StringMap<uint64_t> getSectionStartMap(opt::InputArgList &Args) { |
| 528 | StringRef Name; | 509 | StringRef Name; |
| 529 | StringRef Addr; | 510 | StringRef Addr; |
| 530 | std::tie(Name, Addr) = StringRef(Arg->getValue()).split('='); | 511 | std::tie(Name, Addr) = StringRef(Arg->getValue()).split('='); |
| 531 | Ret[Name] = parseSectionAddress(Addr, Arg); | 512 | Ret[Name] = parseSectionAddress(Addr, *Arg); |
| 532 | } | 513 | } |
| 533 | 514 | ||
| 534 | if (auto *Arg = Args.getLastArg(OPT_Ttext)) | 515 | if (auto *Arg = Args.getLastArg(OPT_Ttext)) |
| 535 | Ret[".text"] = parseSectionAddress(Arg->getValue(), Arg); | 516 | Ret[".text"] = parseSectionAddress(Arg->getValue(), *Arg); |
| 536 | if (auto *Arg = Args.getLastArg(OPT_Tdata)) | 517 | if (auto *Arg = Args.getLastArg(OPT_Tdata)) |
| 537 | Ret[".data"] = parseSectionAddress(Arg->getValue(), Arg); | 518 | Ret[".data"] = parseSectionAddress(Arg->getValue(), *Arg); |
| 538 | if (auto *Arg = Args.getLastArg(OPT_Tbss)) | 519 | if (auto *Arg = Args.getLastArg(OPT_Tbss)) |
| 539 | Ret[".bss"] = parseSectionAddress(Arg->getValue(), Arg); | 520 | Ret[".bss"] = parseSectionAddress(Arg->getValue(), *Arg); |
| 540 | return Ret; | 521 | return Ret; |
| 541 | } | 522 | } |
| 542 | 523 | ||
| ... | @@ -551,15 +532,15 @@ static SortSectionPolicy getSortSection(opt::InputArgList &Args) { | ... | @@ -551,15 +532,15 @@ static SortSectionPolicy getSortSection(opt::InputArgList &Args) { |
| 551 | return SortSectionPolicy::Default; | 532 | return SortSectionPolicy::Default; |
| 552 | } | 533 | } |
| 553 | 534 | ||
| 554 | static std::pair<bool, bool> getHashStyle(opt::InputArgList &Args) { | 535 | static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &Args) { |
| 555 | StringRef S = Args.getLastArgValue(OPT_hash_style, "sysv"); | 536 | StringRef S = Args.getLastArgValue(OPT_orphan_handling, "place"); |
| 556 | if (S == "sysv") | 537 | if (S == "warn") |
| 557 | return {true, false}; | 538 | return OrphanHandlingPolicy::Warn; |
| 558 | if (S == "gnu") | 539 | if (S == "error") |
| 559 | return {false, true}; | 540 | return OrphanHandlingPolicy::Error; |
| 560 | if (S != "both") | 541 | if (S != "place") |
| 561 | error("unknown -hash-style: " + S); | 542 | error("unknown --orphan-handling mode: " + S); |
| 562 | return {true, true}; | 543 | return OrphanHandlingPolicy::Place; |
| 563 | } | 544 | } |
| 564 | 545 | ||
| 565 | // Parse --build-id or --build-id=<style>. We handle "tree" as a | 546 | // Parse --build-id or --build-id=<style>. We handle "tree" as a |
| ... | @@ -589,19 +570,6 @@ getBuildId(opt::InputArgList &Args) { | ... | @@ -589,19 +570,6 @@ getBuildId(opt::InputArgList &Args) { |
| 589 | return {BuildIdKind::None, {}}; | 570 | return {BuildIdKind::None, {}}; |
| 590 | } | 571 | } |
| 591 | 572 | ||
| 592 | static std::vector<StringRef> getLines(MemoryBufferRef MB) { | ||
| 593 | SmallVector<StringRef, 0> Arr; | ||
| 594 | MB.getBuffer().split(Arr, '\n'); | ||
| 595 | |||
| 596 | std::vector<StringRef> Ret; | ||
| 597 | for (StringRef S : Arr) { | ||
| 598 | S = S.trim(); | ||
| 599 | if (!S.empty()) | ||
| 600 | Ret.push_back(S); | ||
| 601 | } | ||
| 602 | return Ret; | ||
| 603 | } | ||
| 604 | |||
| 605 | static bool getCompressDebugSections(opt::InputArgList &Args) { | 573 | static bool getCompressDebugSections(opt::InputArgList &Args) { |
| 606 | StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none"); | 574 | StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none"); |
| 607 | if (S == "none") | 575 | if (S == "none") |
| ... | @@ -613,53 +581,70 @@ static bool getCompressDebugSections(opt::InputArgList &Args) { | ... | @@ -613,53 +581,70 @@ static bool getCompressDebugSections(opt::InputArgList &Args) { |
| 613 | return true; | 581 | return true; |
| 614 | } | 582 | } |
| 615 | 583 | ||
| 584 | static int parseInt(StringRef S, opt::Arg *Arg) { | ||
| 585 | int V = 0; | ||
| 586 | if (!to_integer(S, V, 10)) | ||
| 587 | error(Arg->getSpelling() + ": number expected, but got '" + S + "'"); | ||
| 588 | return V; | ||
| 589 | } | ||
| 590 | |||
| 616 | // Initializes Config members by the command line options. | 591 | // Initializes Config members by the command line options. |
| 617 | void LinkerDriver::readConfigs(opt::InputArgList &Args) { | 592 | void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 618 | Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition); | 593 | Config->AllowMultipleDefinition = |
| 619 | Config->AuxiliaryList = getArgs(Args, OPT_auxiliary); | 594 | Args.hasArg(OPT_allow_multiple_definition) || hasZOption(Args, "muldefs"); |
| 595 | Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary); | ||
| 620 | Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); | 596 | Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); |
| 621 | Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); | 597 | Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); |
| 598 | Config->Chroot = Args.getLastArgValue(OPT_chroot); | ||
| 622 | Config->CompressDebugSections = getCompressDebugSections(Args); | 599 | Config->CompressDebugSections = getCompressDebugSections(Args); |
| 623 | Config->DefineCommon = getArg(Args, OPT_define_common, OPT_no_define_common, | 600 | Config->DefineCommon = Args.hasFlag(OPT_define_common, OPT_no_define_common, |
| 624 | !Args.hasArg(OPT_relocatable)); | 601 | !Args.hasArg(OPT_relocatable)); |
| 625 | Config->Demangle = getArg(Args, OPT_demangle, OPT_no_demangle, true); | 602 | Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true); |
| 626 | Config->DisableVerify = Args.hasArg(OPT_disable_verify); | 603 | Config->DisableVerify = Args.hasArg(OPT_disable_verify); |
| 627 | Config->Discard = getDiscard(Args); | 604 | Config->Discard = getDiscard(Args); |
| 628 | Config->DynamicLinker = getDynamicLinker(Args); | 605 | Config->DynamicLinker = getDynamicLinker(Args); |
| 629 | Config->EhFrameHdr = Args.hasArg(OPT_eh_frame_hdr); | 606 | Config->EhFrameHdr = |
| 607 | Args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false); | ||
| 630 | Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); | 608 | Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); |
| 631 | Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags); | 609 | Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags); |
| 632 | Config->Entry = Args.getLastArgValue(OPT_entry); | 610 | Config->Entry = Args.getLastArgValue(OPT_entry); |
| 633 | Config->ExportDynamic = | 611 | Config->ExportDynamic = |
| 634 | getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false); | 612 | Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); |
| 635 | Config->FatalWarnings = | 613 | errorHandler().FatalWarnings = |
| 636 | getArg(Args, OPT_fatal_warnings, OPT_no_fatal_warnings, false); | 614 | Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); |
| 637 | Config->FilterList = getArgs(Args, OPT_filter); | 615 | Config->FilterList = args::getStrings(Args, OPT_filter); |
| 638 | Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); | 616 | Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); |
| 639 | Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false); | 617 | Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419); |
| 640 | Config->GdbIndex = Args.hasArg(OPT_gdb_index); | 618 | Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false); |
| 641 | Config->ICF = getArg(Args, OPT_icf_all, OPT_icf_none, false); | 619 | Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false); |
| 620 | Config->ICF = Args.hasFlag(OPT_icf_all, OPT_icf_none, false); | ||
| 621 | Config->ICFData = Args.hasArg(OPT_icf_data); | ||
| 642 | Config->Init = Args.getLastArgValue(OPT_init, "_init"); | 622 | Config->Init = Args.getLastArgValue(OPT_init, "_init"); |
| 643 | Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline); | 623 | Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline); |
| 644 | Config->LTONewPmPasses = Args.getLastArgValue(OPT_lto_newpm_passes); | 624 | Config->LTONewPmPasses = Args.getLastArgValue(OPT_lto_newpm_passes); |
| 645 | Config->LTOO = getInteger(Args, OPT_lto_O, 2); | 625 | Config->LTOO = args::getInteger(Args, OPT_lto_O, 2); |
| 646 | Config->LTOPartitions = getInteger(Args, OPT_lto_partitions, 1); | 626 | Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1); |
| 647 | Config->MapFile = Args.getLastArgValue(OPT_Map); | 627 | Config->MapFile = Args.getLastArgValue(OPT_Map); |
| 648 | Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); | 628 | Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); |
| 629 | Config->MergeArmExidx = | ||
| 630 | Args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true); | ||
| 649 | Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); | 631 | Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); |
| 632 | Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec); | ||
| 650 | Config->Nostdlib = Args.hasArg(OPT_nostdlib); | 633 | Config->Nostdlib = Args.hasArg(OPT_nostdlib); |
| 651 | Config->OFormatBinary = isOutputFormatBinary(Args); | 634 | Config->OFormatBinary = isOutputFormatBinary(Args); |
| 652 | Config->Omagic = Args.hasArg(OPT_omagic); | 635 | Config->Omagic = Args.hasFlag(OPT_omagic, OPT_no_omagic, false); |
| 653 | Config->OptRemarksFilename = Args.getLastArgValue(OPT_opt_remarks_filename); | 636 | Config->OptRemarksFilename = Args.getLastArgValue(OPT_opt_remarks_filename); |
| 654 | Config->OptRemarksWithHotness = Args.hasArg(OPT_opt_remarks_with_hotness); | 637 | Config->OptRemarksWithHotness = Args.hasArg(OPT_opt_remarks_with_hotness); |
| 655 | Config->Optimize = getInteger(Args, OPT_O, 1); | 638 | Config->Optimize = args::getInteger(Args, OPT_O, 1); |
| 639 | Config->OrphanHandling = getOrphanHandling(Args); | ||
| 656 | Config->OutputFile = Args.getLastArgValue(OPT_o); | 640 | Config->OutputFile = Args.getLastArgValue(OPT_o); |
| 657 | Config->Pie = getArg(Args, OPT_pie, OPT_nopie, false); | 641 | Config->Pie = Args.hasFlag(OPT_pie, OPT_nopie, false); |
| 658 | Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections); | 642 | Config->PrintGcSections = |
| 643 | Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); | ||
| 659 | Config->Rpath = getRpath(Args); | 644 | Config->Rpath = getRpath(Args); |
| 660 | Config->Relocatable = Args.hasArg(OPT_relocatable); | 645 | Config->Relocatable = Args.hasArg(OPT_relocatable); |
| 661 | Config->SaveTemps = Args.hasArg(OPT_save_temps); | 646 | Config->SaveTemps = Args.hasArg(OPT_save_temps); |
| 662 | Config->SearchPaths = getArgs(Args, OPT_L); | 647 | Config->SearchPaths = args::getStrings(Args, OPT_library_path); |
| 663 | Config->SectionStartMap = getSectionStartMap(Args); | 648 | Config->SectionStartMap = getSectionStartMap(Args); |
| 664 | Config->Shared = Args.hasArg(OPT_shared); | 649 | Config->Shared = Args.hasArg(OPT_shared); |
| 665 | Config->SingleRoRx = Args.hasArg(OPT_no_rosegment); | 650 | Config->SingleRoRx = Args.hasArg(OPT_no_rosegment); |
| ... | @@ -667,18 +652,19 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { | ... | @@ -667,18 +652,19 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 667 | Config->SortSection = getSortSection(Args); | 652 | Config->SortSection = getSortSection(Args); |
| 668 | Config->Strip = getStrip(Args); | 653 | Config->Strip = getStrip(Args); |
| 669 | Config->Sysroot = Args.getLastArgValue(OPT_sysroot); | 654 | Config->Sysroot = Args.getLastArgValue(OPT_sysroot); |
| 670 | Config->Target1Rel = getArg(Args, OPT_target1_rel, OPT_target1_abs, false); | 655 | Config->Target1Rel = Args.hasFlag(OPT_target1_rel, OPT_target1_abs, false); |
| 671 | Config->Target2 = getTarget2(Args); | 656 | Config->Target2 = getTarget2(Args); |
| 672 | Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir); | 657 | Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir); |
| 673 | Config->ThinLTOCachePolicy = check( | 658 | Config->ThinLTOCachePolicy = CHECK( |
| 674 | parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), | 659 | parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), |
| 675 | "--thinlto-cache-policy: invalid cache policy"); | 660 | "--thinlto-cache-policy: invalid cache policy"); |
| 676 | Config->ThinLTOJobs = getInteger(Args, OPT_thinlto_jobs, -1u); | 661 | Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u); |
| 677 | Config->Threads = getArg(Args, OPT_threads, OPT_no_threads, true); | 662 | ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); |
| 678 | Config->Trace = Args.hasArg(OPT_trace); | 663 | Config->Trace = Args.hasArg(OPT_trace); |
| 679 | Config->Undefined = getArgs(Args, OPT_undefined); | 664 | Config->Undefined = args::getStrings(Args, OPT_undefined); |
| 680 | Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); | 665 | Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); |
| 681 | Config->Verbose = Args.hasArg(OPT_verbose); | 666 | Config->Verbose = Args.hasArg(OPT_verbose); |
| 667 | errorHandler().Verbose = Config->Verbose; | ||
| 682 | Config->WarnCommon = Args.hasArg(OPT_warn_common); | 668 | Config->WarnCommon = Args.hasArg(OPT_warn_common); |
| 683 | Config->ZCombreloc = !hasZOption(Args, "nocombreloc"); | 669 | Config->ZCombreloc = !hasZOption(Args, "nocombreloc"); |
| 684 | Config->ZExecstack = hasZOption(Args, "execstack"); | 670 | Config->ZExecstack = hasZOption(Args, "execstack"); |
| ... | @@ -689,20 +675,39 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { | ... | @@ -689,20 +675,39 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 689 | Config->ZOrigin = hasZOption(Args, "origin"); | 675 | Config->ZOrigin = hasZOption(Args, "origin"); |
| 690 | Config->ZRelro = !hasZOption(Args, "norelro"); | 676 | Config->ZRelro = !hasZOption(Args, "norelro"); |
| 691 | Config->ZRodynamic = hasZOption(Args, "rodynamic"); | 677 | Config->ZRodynamic = hasZOption(Args, "rodynamic"); |
| 692 | Config->ZStackSize = getZOptionValue(Args, "stack-size", 0); | 678 | Config->ZStackSize = args::getZOptionValue(Args, OPT_z, "stack-size", 0); |
| 693 | Config->ZText = !hasZOption(Args, "notext"); | 679 | Config->ZText = !hasZOption(Args, "notext"); |
| 694 | Config->ZWxneeded = hasZOption(Args, "wxneeded"); | 680 | Config->ZWxneeded = hasZOption(Args, "wxneeded"); |
| 695 | 681 | ||
| 682 | // Parse LTO plugin-related options for compatibility with gold. | ||
| 683 | for (auto *Arg : Args.filtered(OPT_plugin_opt, OPT_plugin_opt_eq)) { | ||
| 684 | StringRef S = Arg->getValue(); | ||
| 685 | if (S == "disable-verify") | ||
| 686 | Config->DisableVerify = true; | ||
| 687 | else if (S == "save-temps") | ||
| 688 | Config->SaveTemps = true; | ||
| 689 | else if (S.startswith("O")) | ||
| 690 | Config->LTOO = parseInt(S.substr(1), Arg); | ||
| 691 | else if (S.startswith("lto-partitions=")) | ||
| 692 | Config->LTOPartitions = parseInt(S.substr(15), Arg); | ||
| 693 | else if (S.startswith("jobs=")) | ||
| 694 | Config->ThinLTOJobs = parseInt(S.substr(5), Arg); | ||
| 695 | else if (!S.startswith("/") && !S.startswith("-fresolution=") && | ||
| 696 | !S.startswith("-pass-through=") && !S.startswith("mcpu=") && | ||
| 697 | !S.startswith("thinlto") && S != "-function-sections" && | ||
| 698 | S != "-data-sections") | ||
| 699 | error(Arg->getSpelling() + ": unknown option: " + S); | ||
| 700 | } | ||
| 701 | |||
| 696 | if (Config->LTOO > 3) | 702 | if (Config->LTOO > 3) |
| 697 | error("invalid optimization level for LTO: " + | 703 | error("invalid optimization level for LTO: " + Twine(Config->LTOO)); |
| 698 | Args.getLastArgValue(OPT_lto_O)); | ||
| 699 | if (Config->LTOPartitions == 0) | 704 | if (Config->LTOPartitions == 0) |
| 700 | error("--lto-partitions: number of threads must be > 0"); | 705 | error("--lto-partitions: number of threads must be > 0"); |
| 701 | if (Config->ThinLTOJobs == 0) | 706 | if (Config->ThinLTOJobs == 0) |
| 702 | error("--thinlto-jobs: number of threads must be > 0"); | 707 | error("--thinlto-jobs: number of threads must be > 0"); |
| 703 | 708 | ||
| 709 | // Parse ELF{32,64}{LE,BE} and CPU type. | ||
| 704 | if (auto *Arg = Args.getLastArg(OPT_m)) { | 710 | if (auto *Arg = Args.getLastArg(OPT_m)) { |
| 705 | // Parse ELF{32,64}{LE,BE} and CPU type. | ||
| 706 | StringRef S = Arg->getValue(); | 711 | StringRef S = Arg->getValue(); |
| 707 | std::tie(Config->EKind, Config->EMachine, Config->OSABI) = | 712 | std::tie(Config->EKind, Config->EMachine, Config->OSABI) = |
| 708 | parseEmulation(S); | 713 | parseEmulation(S); |
| ... | @@ -710,6 +715,19 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { | ... | @@ -710,6 +715,19 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 710 | Config->Emulation = S; | 715 | Config->Emulation = S; |
| 711 | } | 716 | } |
| 712 | 717 | ||
| 718 | // Parse -hash-style={sysv,gnu,both}. | ||
| 719 | if (auto *Arg = Args.getLastArg(OPT_hash_style)) { | ||
| 720 | StringRef S = Arg->getValue(); | ||
| 721 | if (S == "sysv") | ||
| 722 | Config->SysvHash = true; | ||
| 723 | else if (S == "gnu") | ||
| 724 | Config->GnuHash = true; | ||
| 725 | else if (S == "both") | ||
| 726 | Config->SysvHash = Config->GnuHash = true; | ||
| 727 | else | ||
| 728 | error("unknown -hash-style: " + S); | ||
| 729 | } | ||
| 730 | |||
| 713 | if (Args.hasArg(OPT_print_map)) | 731 | if (Args.hasArg(OPT_print_map)) |
| 714 | Config->MapFile = "-"; | 732 | Config->MapFile = "-"; |
| 715 | 733 | ||
| ... | @@ -720,25 +738,32 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { | ... | @@ -720,25 +738,32 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 720 | if (Config->Omagic) | 738 | if (Config->Omagic) |
| 721 | Config->ZRelro = false; | 739 | Config->ZRelro = false; |
| 722 | 740 | ||
| 723 | std::tie(Config->SysvHash, Config->GnuHash) = getHashStyle(Args); | ||
| 724 | std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args); | 741 | std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args); |
| 725 | 742 | ||
| 743 | if (auto *Arg = Args.getLastArg(OPT_pack_dyn_relocs_eq)) { | ||
| 744 | StringRef S = Arg->getValue(); | ||
| 745 | if (S == "android") | ||
| 746 | Config->AndroidPackDynRelocs = true; | ||
| 747 | else if (S != "none") | ||
| 748 | error("unknown -pack-dyn-relocs format: " + S); | ||
| 749 | } | ||
| 750 | |||
| 726 | if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) | 751 | if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) |
| 727 | if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) | 752 | if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) |
| 728 | Config->SymbolOrderingFile = getLines(*Buffer); | 753 | Config->SymbolOrderingFile = args::getLines(*Buffer); |
| 729 | 754 | ||
| 730 | // If --retain-symbol-file is used, we'll keep only the symbols listed in | 755 | // If --retain-symbol-file is used, we'll keep only the symbols listed in |
| 731 | // the file and discard all others. | 756 | // the file and discard all others. |
| 732 | if (auto *Arg = Args.getLastArg(OPT_retain_symbols_file)) { | 757 | if (auto *Arg = Args.getLastArg(OPT_retain_symbols_file)) { |
| 733 | Config->DefaultSymbolVersion = VER_NDX_LOCAL; | 758 | Config->DefaultSymbolVersion = VER_NDX_LOCAL; |
| 734 | if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) | 759 | if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) |
| 735 | for (StringRef S : getLines(*Buffer)) | 760 | for (StringRef S : args::getLines(*Buffer)) |
| 736 | Config->VersionScriptGlobals.push_back( | 761 | Config->VersionScriptGlobals.push_back( |
| 737 | {S, /*IsExternCpp*/ false, /*HasWildcard*/ false}); | 762 | {S, /*IsExternCpp*/ false, /*HasWildcard*/ false}); |
| 738 | } | 763 | } |
| 739 | 764 | ||
| 740 | bool HasExportDynamic = | 765 | bool HasExportDynamic = |
| 741 | getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false); | 766 | Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); |
| 742 | 767 | ||
| 743 | // Parses -dynamic-list and -export-dynamic-symbol. They make some | 768 | // Parses -dynamic-list and -export-dynamic-symbol. They make some |
| 744 | // symbols private. Note that -export-dynamic takes precedence over them | 769 | // symbols private. Note that -export-dynamic takes precedence over them |
| ... | @@ -749,21 +774,11 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { | ... | @@ -749,21 +774,11 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 749 | readDynamicList(*Buffer); | 774 | readDynamicList(*Buffer); |
| 750 | 775 | ||
| 751 | for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) | 776 | for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) |
| 752 | Config->VersionScriptGlobals.push_back( | 777 | Config->DynamicList.push_back( |
| 753 | {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false}); | 778 | {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false}); |
| 754 | |||
| 755 | // Dynamic lists are a simplified linker script that doesn't need the | ||
| 756 | // "global:" and implicitly ends with a "local:*". Set the variables | ||
| 757 | // needed to simulate that. | ||
| 758 | if (Args.hasArg(OPT_dynamic_list) || | ||
| 759 | Args.hasArg(OPT_export_dynamic_symbol)) { | ||
| 760 | Config->ExportDynamic = true; | ||
| 761 | if (!Config->Shared) | ||
| 762 | Config->DefaultSymbolVersion = VER_NDX_LOCAL; | ||
| 763 | } | ||
| 764 | } | 779 | } |
| 765 | 780 | ||
| 766 | if (auto *Arg = Args.getLastArg(OPT_version_script)) | 781 | for (auto *Arg : Args.filtered(OPT_version_script)) |
| 767 | if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) | 782 | if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) |
| 768 | readVersionScript(*Buffer); | 783 | readVersionScript(*Buffer); |
| 769 | } | 784 | } |
| ... | @@ -804,17 +819,20 @@ static bool getBinaryOption(StringRef S) { | ... | @@ -804,17 +819,20 @@ static bool getBinaryOption(StringRef S) { |
| 804 | 819 | ||
| 805 | void LinkerDriver::createFiles(opt::InputArgList &Args) { | 820 | void LinkerDriver::createFiles(opt::InputArgList &Args) { |
| 806 | for (auto *Arg : Args) { | 821 | for (auto *Arg : Args) { |
| 807 | switch (Arg->getOption().getID()) { | 822 | switch (Arg->getOption().getUnaliasedOption().getID()) { |
| 808 | case OPT_l: | 823 | case OPT_library: |
| 809 | addLibrary(Arg->getValue()); | 824 | addLibrary(Arg->getValue()); |
| 810 | break; | 825 | break; |
| 811 | case OPT_INPUT: | 826 | case OPT_INPUT: |
| 812 | addFile(Arg->getValue(), /*WithLOption=*/false); | 827 | addFile(Arg->getValue(), /*WithLOption=*/false); |
| 813 | break; | 828 | break; |
| 814 | case OPT_alias_script_T: | ||
| 815 | case OPT_script: | 829 | case OPT_script: |
| 816 | if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) | 830 | if (Optional<std::string> Path = searchLinkerScript(Arg->getValue())) { |
| 817 | readLinkerScript(*MB); | 831 | if (Optional<MemoryBufferRef> MB = readFile(*Path)) |
| 832 | readLinkerScript(*MB); | ||
| 833 | break; | ||
| 834 | } | ||
| 835 | error(Twine("cannot find linker script ") + Arg->getValue()); | ||
| 818 | break; | 836 | break; |
| 819 | case OPT_as_needed: | 837 | case OPT_as_needed: |
| 820 | Config->AsNeeded = true; | 838 | Config->AsNeeded = true; |
| ... | @@ -846,7 +864,7 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) { | ... | @@ -846,7 +864,7 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) { |
| 846 | } | 864 | } |
| 847 | } | 865 | } |
| 848 | 866 | ||
| 849 | if (Files.empty() && ErrorCount == 0) | 867 | if (Files.empty() && errorCount() == 0) |
| 850 | error("no input files"); | 868 | error("no input files"); |
| 851 | } | 869 | } |
| 852 | 870 | ||
| ... | @@ -870,21 +888,20 @@ void LinkerDriver::inferMachineType() { | ... | @@ -870,21 +888,20 @@ void LinkerDriver::inferMachineType() { |
| 870 | // Parse -z max-page-size=<value>. The default value is defined by | 888 | // Parse -z max-page-size=<value>. The default value is defined by |
| 871 | // each target. | 889 | // each target. |
| 872 | static uint64_t getMaxPageSize(opt::InputArgList &Args) { | 890 | static uint64_t getMaxPageSize(opt::InputArgList &Args) { |
| 873 | uint64_t Val = | 891 | uint64_t Val = args::getZOptionValue(Args, OPT_z, "max-page-size", |
| 874 | getZOptionValue(Args, "max-page-size", Target->DefaultMaxPageSize); | 892 | Target->DefaultMaxPageSize); |
| 875 | if (!isPowerOf2_64(Val)) | 893 | if (!isPowerOf2_64(Val)) |
| 876 | error("max-page-size: value isn't a power of 2"); | 894 | error("max-page-size: value isn't a power of 2"); |
| 877 | return Val; | 895 | return Val; |
| 878 | } | 896 | } |
| 879 | 897 | ||
| 880 | // Parses -image-base option. | 898 | // Parses -image-base option. |
| 881 | static uint64_t getImageBase(opt::InputArgList &Args) { | 899 | static Optional<uint64_t> getImageBase(opt::InputArgList &Args) { |
| 882 | // Use default if no -image-base option is given. | 900 | // Because we are using "Config->MaxPageSize" here, this function has to be |
| 883 | // Because we are using "Target" here, this function | 901 | // called after the variable is initialized. |
| 884 | // has to be called after the variable is initialized. | ||
| 885 | auto *Arg = Args.getLastArg(OPT_image_base); | 902 | auto *Arg = Args.getLastArg(OPT_image_base); |
| 886 | if (!Arg) | 903 | if (!Arg) |
| 887 | return Config->Pic ? 0 : Target->DefaultImageBase; | 904 | return None; |
| 888 | 905 | ||
| 889 | StringRef S = Arg->getValue(); | 906 | StringRef S = Arg->getValue(); |
| 890 | uint64_t V; | 907 | uint64_t V; |
| ... | @@ -897,21 +914,6 @@ static uint64_t getImageBase(opt::InputArgList &Args) { | ... | @@ -897,21 +914,6 @@ static uint64_t getImageBase(opt::InputArgList &Args) { |
| 897 | return V; | 914 | return V; |
| 898 | } | 915 | } |
| 899 | 916 | ||
| 900 | // Parses --defsym=alias option. | ||
| 901 | static std::vector<std::pair<StringRef, StringRef>> | ||
| 902 | getDefsym(opt::InputArgList &Args) { | ||
| 903 | std::vector<std::pair<StringRef, StringRef>> Ret; | ||
| 904 | for (auto *Arg : Args.filtered(OPT_defsym)) { | ||
| 905 | StringRef From; | ||
| 906 | StringRef To; | ||
| 907 | std::tie(From, To) = StringRef(Arg->getValue()).split('='); | ||
| 908 | if (!isValidCIdentifier(To)) | ||
| 909 | error("--defsym: symbol name expected, but got " + To); | ||
| 910 | Ret.push_back({From, To}); | ||
| 911 | } | ||
| 912 | return Ret; | ||
| 913 | } | ||
| 914 | |||
| 915 | // Parses `--exclude-libs=lib,lib,...`. | 917 | // Parses `--exclude-libs=lib,lib,...`. |
| 916 | // The library names may be delimited by commas or colons. | 918 | // The library names may be delimited by commas or colons. |
| 917 | static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) { | 919 | static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) { |
| ... | @@ -930,33 +932,50 @@ static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) { | ... | @@ -930,33 +932,50 @@ static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) { |
| 930 | return Ret; | 932 | return Ret; |
| 931 | } | 933 | } |
| 932 | 934 | ||
| 935 | static Optional<StringRef> getArchiveName(InputFile *File) { | ||
| 936 | if (isa<ArchiveFile>(File)) | ||
| 937 | return File->getName(); | ||
| 938 | if (!File->ArchiveName.empty()) | ||
| 939 | return File->ArchiveName; | ||
| 940 | return None; | ||
| 941 | } | ||
| 942 | |||
| 933 | // Handles the -exclude-libs option. If a static library file is specified | 943 | // Handles the -exclude-libs option. If a static library file is specified |
| 934 | // by the -exclude-libs option, all public symbols from the archive become | 944 | // by the -exclude-libs option, all public symbols from the archive become |
| 935 | // private unless otherwise specified by version scripts or something. | 945 | // private unless otherwise specified by version scripts or something. |
| 936 | // A special library name "ALL" means all archive files. | 946 | // A special library name "ALL" means all archive files. |
| 937 | // | 947 | // |
| 938 | // This is not a popular option, but some programs such as bionic libc use it. | 948 | // This is not a popular option, but some programs such as bionic libc use it. |
| 949 | template <class ELFT> | ||
| 939 | static void excludeLibs(opt::InputArgList &Args, ArrayRef<InputFile *> Files) { | 950 | static void excludeLibs(opt::InputArgList &Args, ArrayRef<InputFile *> Files) { |
| 940 | DenseSet<StringRef> Libs = getExcludeLibs(Args); | 951 | DenseSet<StringRef> Libs = getExcludeLibs(Args); |
| 941 | bool All = Libs.count("ALL"); | 952 | bool All = Libs.count("ALL"); |
| 942 | 953 | ||
| 943 | for (InputFile *File : Files) | 954 | for (InputFile *File : Files) |
| 944 | if (auto *F = dyn_cast<ArchiveFile>(File)) | 955 | if (Optional<StringRef> Archive = getArchiveName(File)) |
| 945 | if (All || Libs.count(path::filename(F->getName()))) | 956 | if (All || Libs.count(path::filename(*Archive))) |
| 946 | for (Symbol *Sym : F->getSymbols()) | 957 | for (Symbol *Sym : File->getSymbols()) |
| 947 | Sym->VersionId = VER_NDX_LOCAL; | 958 | if (!Sym->isLocal()) |
| 959 | Sym->VersionId = VER_NDX_LOCAL; | ||
| 948 | } | 960 | } |
| 949 | 961 | ||
| 950 | // Do actual linking. Note that when this function is called, | 962 | // Do actual linking. Note that when this function is called, |
| 951 | // all linker scripts have already been parsed. | 963 | // all linker scripts have already been parsed. |
| 952 | template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { | 964 | template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 953 | SymbolTable<ELFT> Symtab; | ||
| 954 | elf::Symtab<ELFT>::X = &Symtab; | ||
| 955 | Target = getTarget(); | 965 | Target = getTarget(); |
| 956 | 966 | ||
| 957 | Config->MaxPageSize = getMaxPageSize(Args); | 967 | Config->MaxPageSize = getMaxPageSize(Args); |
| 958 | Config->ImageBase = getImageBase(Args); | 968 | Config->ImageBase = getImageBase(Args); |
| 959 | 969 | ||
| 970 | // If a -hash-style option was not given, set to a default value, | ||
| 971 | // which varies depending on the target. | ||
| 972 | if (!Args.hasArg(OPT_hash_style)) { | ||
| 973 | if (Config->EMachine == EM_MIPS) | ||
| 974 | Config->SysvHash = true; | ||
| 975 | else | ||
| 976 | Config->SysvHash = Config->GnuHash = true; | ||
| 977 | } | ||
| 978 | |||
| 960 | // Default output filename is "a.out" by the Unix tradition. | 979 | // Default output filename is "a.out" by the Unix tradition. |
| 961 | if (Config->OutputFile.empty()) | 980 | if (Config->OutputFile.empty()) |
| 962 | Config->OutputFile = "a.out"; | 981 | Config->OutputFile = "a.out"; |
| ... | @@ -968,7 +987,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { | ... | @@ -968,7 +987,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 968 | error("cannot open output file " + Config->OutputFile + ": " + E.message()); | 987 | error("cannot open output file " + Config->OutputFile + ": " + E.message()); |
| 969 | if (auto E = tryCreateFile(Config->MapFile)) | 988 | if (auto E = tryCreateFile(Config->MapFile)) |
| 970 | error("cannot open map file " + Config->MapFile + ": " + E.message()); | 989 | error("cannot open map file " + Config->MapFile + ": " + E.message()); |
| 971 | if (ErrorCount) | 990 | if (errorCount()) |
| 972 | return; | 991 | return; |
| 973 | 992 | ||
| 974 | // Use default entry point name if no name was given via the command | 993 | // Use default entry point name if no name was given via the command |
| ... | @@ -981,78 +1000,125 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { | ... | @@ -981,78 +1000,125 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 981 | 1000 | ||
| 982 | // Handle --trace-symbol. | 1001 | // Handle --trace-symbol. |
| 983 | for (auto *Arg : Args.filtered(OPT_trace_symbol)) | 1002 | for (auto *Arg : Args.filtered(OPT_trace_symbol)) |
| 984 | Symtab.trace(Arg->getValue()); | 1003 | Symtab->trace(Arg->getValue()); |
| 985 | 1004 | ||
| 986 | // Add all files to the symbol table. This will add almost all | 1005 | // Add all files to the symbol table. This will add almost all |
| 987 | // symbols that we need to the symbol table. | 1006 | // symbols that we need to the symbol table. |
| 988 | for (InputFile *F : Files) | 1007 | for (InputFile *F : Files) |
| 989 | Symtab.addFile(F); | 1008 | Symtab->addFile<ELFT>(F); |
| 1009 | |||
| 1010 | // Process -defsym option. | ||
| 1011 | for (auto *Arg : Args.filtered(OPT_defsym)) { | ||
| 1012 | StringRef From; | ||
| 1013 | StringRef To; | ||
| 1014 | std::tie(From, To) = StringRef(Arg->getValue()).split('='); | ||
| 1015 | readDefsym(From, MemoryBufferRef(To, "-defsym")); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | // Now that we have every file, we can decide if we will need a | ||
| 1019 | // dynamic symbol table. | ||
| 1020 | // We need one if we were asked to export dynamic symbols or if we are | ||
| 1021 | // producing a shared library. | ||
| 1022 | // We also need one if any shared libraries are used and for pie executables | ||
| 1023 | // (probably because the dynamic linker needs it). | ||
| 1024 | Config->HasDynSymTab = | ||
| 1025 | !SharedFiles.empty() || Config->Pic || Config->ExportDynamic; | ||
| 1026 | |||
| 1027 | // Some symbols (such as __ehdr_start) are defined lazily only when there | ||
| 1028 | // are undefined symbols for them, so we add these to trigger that logic. | ||
| 1029 | for (StringRef Sym : Script->ReferencedSymbols) | ||
| 1030 | Symtab->addUndefined<ELFT>(Sym); | ||
| 1031 | |||
| 1032 | // Handle the `--undefined <sym>` options. | ||
| 1033 | for (StringRef S : Config->Undefined) | ||
| 1034 | Symtab->fetchIfLazy<ELFT>(S); | ||
| 990 | 1035 | ||
| 991 | // If an entry symbol is in a static archive, pull out that file now | 1036 | // If an entry symbol is in a static archive, pull out that file now |
| 992 | // to complete the symbol table. After this, no new names except a | 1037 | // to complete the symbol table. After this, no new names except a |
| 993 | // few linker-synthesized ones will be added to the symbol table. | 1038 | // few linker-synthesized ones will be added to the symbol table. |
| 994 | if (Symtab.find(Config->Entry)) | 1039 | Symtab->fetchIfLazy<ELFT>(Config->Entry); |
| 995 | Symtab.addUndefined(Config->Entry); | ||
| 996 | 1040 | ||
| 997 | // Return if there were name resolution errors. | 1041 | // Return if there were name resolution errors. |
| 998 | if (ErrorCount) | 1042 | if (errorCount()) |
| 999 | return; | 1043 | return; |
| 1000 | 1044 | ||
| 1001 | // Handle the `--undefined <sym>` options. | ||
| 1002 | Symtab.scanUndefinedFlags(); | ||
| 1003 | |||
| 1004 | // Handle undefined symbols in DSOs. | 1045 | // Handle undefined symbols in DSOs. |
| 1005 | Symtab.scanShlibUndefined(); | 1046 | if (!Config->Shared) |
| 1047 | Symtab->scanShlibUndefined<ELFT>(); | ||
| 1006 | 1048 | ||
| 1007 | // Handle the -exclude-libs option. | 1049 | // Handle the -exclude-libs option. |
| 1008 | if (Args.hasArg(OPT_exclude_libs)) | 1050 | if (Args.hasArg(OPT_exclude_libs)) |
| 1009 | excludeLibs(Args, Files); | 1051 | excludeLibs<ELFT>(Args, Files); |
| 1052 | |||
| 1053 | // Create ElfHeader early. We need a dummy section in | ||
| 1054 | // addReservedSymbols to mark the created symbols as not absolute. | ||
| 1055 | Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC); | ||
| 1056 | Out::ElfHeader->Size = sizeof(typename ELFT::Ehdr); | ||
| 1057 | |||
| 1058 | // We need to create some reserved symbols such as _end. Create them. | ||
| 1059 | if (!Config->Relocatable) | ||
| 1060 | addReservedSymbols(); | ||
| 1010 | 1061 | ||
| 1011 | // Apply version scripts. | 1062 | // Apply version scripts. |
| 1012 | Symtab.scanVersionScript(); | 1063 | Symtab->scanVersionScript(); |
| 1013 | 1064 | ||
| 1014 | // Create wrapped symbols for -wrap option. | 1065 | // Create wrapped symbols for -wrap option. |
| 1015 | for (auto *Arg : Args.filtered(OPT_wrap)) | 1066 | for (auto *Arg : Args.filtered(OPT_wrap)) |
| 1016 | Symtab.addSymbolWrap(Arg->getValue()); | 1067 | Symtab->addSymbolWrap<ELFT>(Arg->getValue()); |
| 1017 | |||
| 1018 | // Create alias symbols for -defsym option. | ||
| 1019 | for (std::pair<StringRef, StringRef> &Def : getDefsym(Args)) | ||
| 1020 | Symtab.addSymbolAlias(Def.first, Def.second); | ||
| 1021 | 1068 | ||
| 1022 | Symtab.addCombinedLTOObject(); | 1069 | Symtab->addCombinedLTOObject<ELFT>(); |
| 1023 | if (ErrorCount) | 1070 | if (errorCount()) |
| 1024 | return; | 1071 | return; |
| 1025 | 1072 | ||
| 1026 | // Some symbols (such as __ehdr_start) are defined lazily only when there | 1073 | // Apply symbol renames for -wrap. |
| 1027 | // are undefined symbols for them, so we add these to trigger that logic. | 1074 | Symtab->applySymbolWrap(); |
| 1028 | for (StringRef Sym : Script->Opt.ReferencedSymbols) | ||
| 1029 | Symtab.addUndefined(Sym); | ||
| 1030 | |||
| 1031 | // Apply symbol renames for -wrap and -defsym | ||
| 1032 | Symtab.applySymbolRenames(); | ||
| 1033 | 1075 | ||
| 1034 | // Now that we have a complete list of input files. | 1076 | // Now that we have a complete list of input files. |
| 1035 | // Beyond this point, no new files are added. | 1077 | // Beyond this point, no new files are added. |
| 1036 | // Aggregate all input sections into one place. | 1078 | // Aggregate all input sections into one place. |
| 1037 | for (elf::ObjectFile<ELFT> *F : Symtab.getObjectFiles()) | 1079 | for (InputFile *F : ObjectFiles) |
| 1038 | for (InputSectionBase *S : F->getSections()) | 1080 | for (InputSectionBase *S : F->getSections()) |
| 1039 | if (S && S != &InputSection::Discarded) | 1081 | if (S && S != &InputSection::Discarded) |
| 1040 | InputSections.push_back(S); | 1082 | InputSections.push_back(S); |
| 1041 | for (BinaryFile *F : Symtab.getBinaryFiles()) | 1083 | for (BinaryFile *F : BinaryFiles) |
| 1042 | for (InputSectionBase *S : F->getSections()) | 1084 | for (InputSectionBase *S : F->getSections()) |
| 1043 | InputSections.push_back(cast<InputSection>(S)); | 1085 | InputSections.push_back(cast<InputSection>(S)); |
| 1044 | 1086 | ||
| 1087 | // We do not want to emit debug sections if --strip-all | ||
| 1088 | // or -strip-debug are given. | ||
| 1089 | if (Config->Strip != StripPolicy::None) | ||
| 1090 | llvm::erase_if(InputSections, [](InputSectionBase *S) { | ||
| 1091 | return S->Name.startswith(".debug") || S->Name.startswith(".zdebug"); | ||
| 1092 | }); | ||
| 1093 | |||
| 1094 | Config->EFlags = Target->calcEFlags(); | ||
| 1095 | |||
| 1096 | if (Config->EMachine == EM_ARM) { | ||
| 1097 | // FIXME: These warnings can be removed when lld only uses these features | ||
| 1098 | // when the input objects have been compiled with an architecture that | ||
| 1099 | // supports them. | ||
| 1100 | if (Config->ARMHasBlx == false) | ||
| 1101 | warn("lld uses blx instruction, no object with architecture supporting " | ||
| 1102 | "feature detected."); | ||
| 1103 | if (Config->ARMJ1J2BranchEncoding == false) | ||
| 1104 | warn("lld uses extended branch encoding, no object with architecture " | ||
| 1105 | "supporting feature detected."); | ||
| 1106 | if (Config->ARMHasMovtMovw == false) | ||
| 1107 | warn("lld may use movt/movw, no object with architecture supporting " | ||
| 1108 | "feature detected."); | ||
| 1109 | } | ||
| 1110 | |||
| 1045 | // This adds a .comment section containing a version string. We have to add it | 1111 | // This adds a .comment section containing a version string. We have to add it |
| 1046 | // before decompressAndMergeSections because the .comment section is a | 1112 | // before decompressAndMergeSections because the .comment section is a |
| 1047 | // mergeable section. | 1113 | // mergeable section. |
| 1048 | if (!Config->Relocatable) | 1114 | if (!Config->Relocatable) |
| 1049 | InputSections.push_back(createCommentSection<ELFT>()); | 1115 | InputSections.push_back(createCommentSection()); |
| 1050 | 1116 | ||
| 1051 | // Do size optimizations: garbage collection, merging of SHF_MERGE sections | 1117 | // Do size optimizations: garbage collection, merging of SHF_MERGE sections |
| 1052 | // and identical code folding. | 1118 | // and identical code folding. |
| 1053 | if (Config->GcSections) | 1119 | markLive<ELFT>(); |
| 1054 | markLive<ELFT>(); | 1120 | decompressSections(); |
| 1055 | decompressAndMergeSections(); | 1121 | mergeSections(); |
| 1056 | if (Config->ICF) | 1122 | if (Config->ICF) |
| 1057 | doIcf<ELFT>(); | 1123 | doIcf<ELFT>(); |
| 1058 | 1124 |
deps/lld/ELF/Driver.h+3-2| ... | @@ -11,8 +11,8 @@ | ... | @@ -11,8 +11,8 @@ |
| 11 | #define LLD_ELF_DRIVER_H | 11 | #define LLD_ELF_DRIVER_H |
| 12 | 12 | ||
| 13 | #include "SymbolTable.h" | 13 | #include "SymbolTable.h" |
| 14 | #include "lld/Core/LLVM.h" | 14 | #include "lld/Common/LLVM.h" |
| 15 | #include "lld/Core/Reproduce.h" | 15 | #include "lld/Common/Reproduce.h" |
| 16 | #include "llvm/ADT/Optional.h" | 16 | #include "llvm/ADT/Optional.h" |
| 17 | #include "llvm/ADT/StringRef.h" | 17 | #include "llvm/ADT/StringRef.h" |
| 18 | #include "llvm/ADT/StringSet.h" | 18 | #include "llvm/ADT/StringSet.h" |
| ... | @@ -67,6 +67,7 @@ void printHelp(const char *Argv0); | ... | @@ -67,6 +67,7 @@ void printHelp(const char *Argv0); |
| 67 | std::string createResponseFile(const llvm::opt::InputArgList &Args); | 67 | std::string createResponseFile(const llvm::opt::InputArgList &Args); |
| 68 | 68 | ||
| 69 | llvm::Optional<std::string> findFromSearchPaths(StringRef Path); | 69 | llvm::Optional<std::string> findFromSearchPaths(StringRef Path); |
| 70 | llvm::Optional<std::string> searchLinkerScript(StringRef Path); | ||
| 70 | llvm::Optional<std::string> searchLibrary(StringRef Path); | 71 | llvm::Optional<std::string> searchLibrary(StringRef Path); |
| 71 | 72 | ||
| 72 | } // namespace elf | 73 | } // namespace elf |
deps/lld/ELF/DriverUtils.cpp+39-29| ... | @@ -14,10 +14,10 @@ | ... | @@ -14,10 +14,10 @@ |
| 14 | //===----------------------------------------------------------------------===// | 14 | //===----------------------------------------------------------------------===// |
| 15 | 15 | ||
| 16 | #include "Driver.h" | 16 | #include "Driver.h" |
| 17 | #include "Error.h" | 17 | #include "lld/Common/ErrorHandler.h" |
| 18 | #include "Memory.h" | 18 | #include "lld/Common/Memory.h" |
| 19 | #include "lld/Config/Version.h" | 19 | #include "lld/Common/Reproduce.h" |
| 20 | #include "lld/Core/Reproduce.h" | 20 | #include "lld/Common/Version.h" |
| 21 | #include "llvm/ADT/Optional.h" | 21 | #include "llvm/ADT/Optional.h" |
| 22 | #include "llvm/ADT/STLExtras.h" | 22 | #include "llvm/ADT/STLExtras.h" |
| 23 | #include "llvm/ADT/Triple.h" | 23 | #include "llvm/ADT/Triple.h" |
| ... | @@ -51,25 +51,26 @@ static const opt::OptTable::Info OptInfo[] = { | ... | @@ -51,25 +51,26 @@ static const opt::OptTable::Info OptInfo[] = { |
| 51 | 51 | ||
| 52 | ELFOptTable::ELFOptTable() : OptTable(OptInfo) {} | 52 | ELFOptTable::ELFOptTable() : OptTable(OptInfo) {} |
| 53 | 53 | ||
| 54 | // Parse -color-diagnostics={auto,always,never} or -no-color-diagnostics. | 54 | // Set color diagnostics according to -color-diagnostics={auto,always,never} |
| 55 | static bool getColorDiagnostics(opt::InputArgList &Args) { | 55 | // or -no-color-diagnostics flags. |
| 56 | static void handleColorDiagnostics(opt::InputArgList &Args) { | ||
| 56 | auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, | 57 | auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, |
| 57 | OPT_no_color_diagnostics); | 58 | OPT_no_color_diagnostics); |
| 58 | if (!Arg) | 59 | if (!Arg) |
| 59 | return ErrorOS->has_colors(); | 60 | return; |
| 60 | if (Arg->getOption().getID() == OPT_color_diagnostics) | 61 | else if (Arg->getOption().getID() == OPT_color_diagnostics) |
| 61 | return true; | 62 | errorHandler().ColorDiagnostics = true; |
| 62 | if (Arg->getOption().getID() == OPT_no_color_diagnostics) | 63 | else if (Arg->getOption().getID() == OPT_no_color_diagnostics) |
| 63 | return false; | 64 | errorHandler().ColorDiagnostics = false; |
| 64 | 65 | else { | |
| 65 | StringRef S = Arg->getValue(); | 66 | StringRef S = Arg->getValue(); |
| 66 | if (S == "auto") | 67 | if (S == "always") |
| 67 | return ErrorOS->has_colors(); | 68 | errorHandler().ColorDiagnostics = true; |
| 68 | if (S == "always") | 69 | else if (S == "never") |
| 69 | return true; | 70 | errorHandler().ColorDiagnostics = false; |
| 70 | if (S != "never") | 71 | else if (S != "auto") |
| 71 | error("unknown option: -color-diagnostics=" + S); | 72 | error("unknown option: -color-diagnostics=" + S); |
| 72 | return false; | 73 | } |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) { | 76 | static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) { |
| ... | @@ -103,9 +104,7 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) { | ... | @@ -103,9 +104,7 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) { |
| 103 | cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec); | 104 | cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec); |
| 104 | Args = this->ParseArgs(Vec, MissingIndex, MissingCount); | 105 | Args = this->ParseArgs(Vec, MissingIndex, MissingCount); |
| 105 | 106 | ||
| 106 | // Interpret -color-diagnostics early so that error messages | 107 | handleColorDiagnostics(Args); |
| 107 | // for unknown flags are colored. | ||
| 108 | Config->ColorDiagnostics = getColorDiagnostics(Args); | ||
| 109 | if (MissingCount) | 108 | if (MissingCount) |
| 110 | error(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); | 109 | error(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); |
| 111 | 110 | ||
| ... | @@ -115,8 +114,8 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) { | ... | @@ -115,8 +114,8 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) { |
| 115 | } | 114 | } |
| 116 | 115 | ||
| 117 | void elf::printHelp(const char *Argv0) { | 116 | void elf::printHelp(const char *Argv0) { |
| 118 | ELFOptTable Table; | 117 | ELFOptTable().PrintHelp(outs(), Argv0, "lld", false /*ShowHidden*/, |
| 119 | Table.PrintHelp(outs(), Argv0, "lld", false); | 118 | true /*ShowAllAliases*/); |
| 120 | outs() << "\n"; | 119 | outs() << "\n"; |
| 121 | 120 | ||
| 122 | // Scripts generated by Libtool versions up to at least 2.4.6 (the most | 121 | // Scripts generated by Libtool versions up to at least 2.4.6 (the most |
| ... | @@ -138,10 +137,11 @@ void elf::printHelp(const char *Argv0) { | ... | @@ -138,10 +137,11 @@ void elf::printHelp(const char *Argv0) { |
| 138 | std::string elf::createResponseFile(const opt::InputArgList &Args) { | 137 | std::string elf::createResponseFile(const opt::InputArgList &Args) { |
| 139 | SmallString<0> Data; | 138 | SmallString<0> Data; |
| 140 | raw_svector_ostream OS(Data); | 139 | raw_svector_ostream OS(Data); |
| 140 | OS << "--chroot .\n"; | ||
| 141 | 141 | ||
| 142 | // Copy the command line to the output while rewriting paths. | 142 | // Copy the command line to the output while rewriting paths. |
| 143 | for (auto *Arg : Args) { | 143 | for (auto *Arg : Args) { |
| 144 | switch (Arg->getOption().getID()) { | 144 | switch (Arg->getOption().getUnaliasedOption().getID()) { |
| 145 | case OPT_reproduce: | 145 | case OPT_reproduce: |
| 146 | break; | 146 | break; |
| 147 | case OPT_INPUT: | 147 | case OPT_INPUT: |
| ... | @@ -154,17 +154,18 @@ std::string elf::createResponseFile(const opt::InputArgList &Args) { | ... | @@ -154,17 +154,18 @@ std::string elf::createResponseFile(const opt::InputArgList &Args) { |
| 154 | // Strip directories to prevent the issue. | 154 | // Strip directories to prevent the issue. |
| 155 | OS << "-o " << quote(sys::path::filename(Arg->getValue())) << "\n"; | 155 | OS << "-o " << quote(sys::path::filename(Arg->getValue())) << "\n"; |
| 156 | break; | 156 | break; |
| 157 | case OPT_L: | ||
| 158 | case OPT_dynamic_list: | 157 | case OPT_dynamic_list: |
| 158 | case OPT_library_path: | ||
| 159 | case OPT_rpath: | 159 | case OPT_rpath: |
| 160 | case OPT_alias_script_T: | ||
| 161 | case OPT_script: | 160 | case OPT_script: |
| 161 | case OPT_symbol_ordering_file: | ||
| 162 | case OPT_sysroot: | ||
| 162 | case OPT_version_script: | 163 | case OPT_version_script: |
| 163 | OS << Arg->getSpelling() << " " << quote(rewritePath(Arg->getValue())) | 164 | OS << Arg->getSpelling() << " " << quote(rewritePath(Arg->getValue())) |
| 164 | << "\n"; | 165 | << "\n"; |
| 165 | break; | 166 | break; |
| 166 | default: | 167 | default: |
| 167 | OS << toString(Arg) << "\n"; | 168 | OS << toString(*Arg) << "\n"; |
| 168 | } | 169 | } |
| 169 | } | 170 | } |
| 170 | return Data.str(); | 171 | return Data.str(); |
| ... | @@ -206,3 +207,12 @@ Optional<std::string> elf::searchLibrary(StringRef Name) { | ... | @@ -206,3 +207,12 @@ Optional<std::string> elf::searchLibrary(StringRef Name) { |
| 206 | } | 207 | } |
| 207 | return None; | 208 | return None; |
| 208 | } | 209 | } |
| 210 | |||
| 211 | // If a linker script doesn't exist in the current directory, we also look for | ||
| 212 | // the script in the '-L' search paths. This matches the behaviour of both '-T' | ||
| 213 | // and linker script INPUT() directives in ld.bfd. | ||
| 214 | Optional<std::string> elf::searchLinkerScript(StringRef Name) { | ||
| 215 | if (fs::exists(Name)) | ||
| 216 | return Name.str(); | ||
| 217 | return findFromSearchPaths(Name); | ||
| 218 | } |
deps/lld/ELF/EhFrame.cpp+15-27| ... | @@ -17,11 +17,12 @@ | ... | @@ -17,11 +17,12 @@ |
| 17 | //===----------------------------------------------------------------------===// | 17 | //===----------------------------------------------------------------------===// |
| 18 | 18 | ||
| 19 | #include "EhFrame.h" | 19 | #include "EhFrame.h" |
| 20 | #include "Error.h" | 20 | #include "Config.h" |
| 21 | #include "InputSection.h" | 21 | #include "InputSection.h" |
| 22 | #include "Relocations.h" | 22 | #include "Relocations.h" |
| 23 | #include "Strings.h" | 23 | #include "Strings.h" |
| 24 | 24 | ||
| 25 | #include "lld/Common/ErrorHandler.h" | ||
| 25 | #include "llvm/BinaryFormat/Dwarf.h" | 26 | #include "llvm/BinaryFormat/Dwarf.h" |
| 26 | #include "llvm/Object/ELF.h" | 27 | #include "llvm/Object/ELF.h" |
| 27 | #include "llvm/Support/Endian.h" | 28 | #include "llvm/Support/Endian.h" |
| ... | @@ -36,7 +37,7 @@ using namespace lld; | ... | @@ -36,7 +37,7 @@ using namespace lld; |
| 36 | using namespace lld::elf; | 37 | using namespace lld::elf; |
| 37 | 38 | ||
| 38 | namespace { | 39 | namespace { |
| 39 | template <class ELFT> class EhReader { | 40 | class EhReader { |
| 40 | public: | 41 | public: |
| 41 | EhReader(InputSectionBase *S, ArrayRef<uint8_t> D) : IS(S), D(D) {} | 42 | EhReader(InputSectionBase *S, ArrayRef<uint8_t> D) : IS(S), D(D) {} |
| 42 | size_t readEhRecordSize(); | 43 | size_t readEhRecordSize(); |
| ... | @@ -45,7 +46,7 @@ public: | ... | @@ -45,7 +46,7 @@ public: |
| 45 | private: | 46 | private: |
| 46 | template <class P> void failOn(const P *Loc, const Twine &Msg) { | 47 | template <class P> void failOn(const P *Loc, const Twine &Msg) { |
| 47 | fatal("corrupted .eh_frame: " + Msg + "\n>>> defined in " + | 48 | fatal("corrupted .eh_frame: " + Msg + "\n>>> defined in " + |
| 48 | IS->getObjMsg<ELFT>((const uint8_t *)Loc - IS->Data.data())); | 49 | IS->getObjMsg((const uint8_t *)Loc - IS->Data.data())); |
| 49 | } | 50 | } |
| 50 | 51 | ||
| 51 | uint8_t readByte(); | 52 | uint8_t readByte(); |
| ... | @@ -59,22 +60,20 @@ private: | ... | @@ -59,22 +60,20 @@ private: |
| 59 | }; | 60 | }; |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | template <class ELFT> | ||
| 63 | size_t elf::readEhRecordSize(InputSectionBase *S, size_t Off) { | 63 | size_t elf::readEhRecordSize(InputSectionBase *S, size_t Off) { |
| 64 | return EhReader<ELFT>(S, S->Data.slice(Off)).readEhRecordSize(); | 64 | return EhReader(S, S->Data.slice(Off)).readEhRecordSize(); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | // .eh_frame section is a sequence of records. Each record starts with | 67 | // .eh_frame section is a sequence of records. Each record starts with |
| 68 | // a 4 byte length field. This function reads the length. | 68 | // a 4 byte length field. This function reads the length. |
| 69 | template <class ELFT> size_t EhReader<ELFT>::readEhRecordSize() { | 69 | size_t EhReader::readEhRecordSize() { |
| 70 | const endianness E = ELFT::TargetEndianness; | ||
| 71 | if (D.size() < 4) | 70 | if (D.size() < 4) |
| 72 | failOn(D.data(), "CIE/FDE too small"); | 71 | failOn(D.data(), "CIE/FDE too small"); |
| 73 | 72 | ||
| 74 | // First 4 bytes of CIE/FDE is the size of the record. | 73 | // First 4 bytes of CIE/FDE is the size of the record. |
| 75 | // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead, | 74 | // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead, |
| 76 | // but we do not support that format yet. | 75 | // but we do not support that format yet. |
| 77 | uint64_t V = read32<E>(D.data()); | 76 | uint64_t V = read32(D.data(), Config->Endianness); |
| 78 | if (V == UINT32_MAX) | 77 | if (V == UINT32_MAX) |
| 79 | failOn(D.data(), "CIE/FDE too large"); | 78 | failOn(D.data(), "CIE/FDE too large"); |
| 80 | uint64_t Size = V + 4; | 79 | uint64_t Size = V + 4; |
| ... | @@ -84,7 +83,7 @@ template <class ELFT> size_t EhReader<ELFT>::readEhRecordSize() { | ... | @@ -84,7 +83,7 @@ template <class ELFT> size_t EhReader<ELFT>::readEhRecordSize() { |
| 84 | } | 83 | } |
| 85 | 84 | ||
| 86 | // Read a byte and advance D by one byte. | 85 | // Read a byte and advance D by one byte. |
| 87 | template <class ELFT> uint8_t EhReader<ELFT>::readByte() { | 86 | uint8_t EhReader::readByte() { |
| 88 | if (D.empty()) | 87 | if (D.empty()) |
| 89 | failOn(D.data(), "unexpected end of CIE"); | 88 | failOn(D.data(), "unexpected end of CIE"); |
| 90 | uint8_t B = D.front(); | 89 | uint8_t B = D.front(); |
| ... | @@ -92,14 +91,14 @@ template <class ELFT> uint8_t EhReader<ELFT>::readByte() { | ... | @@ -92,14 +91,14 @@ template <class ELFT> uint8_t EhReader<ELFT>::readByte() { |
| 92 | return B; | 91 | return B; |
| 93 | } | 92 | } |
| 94 | 93 | ||
| 95 | template <class ELFT> void EhReader<ELFT>::skipBytes(size_t Count) { | 94 | void EhReader::skipBytes(size_t Count) { |
| 96 | if (D.size() < Count) | 95 | if (D.size() < Count) |
| 97 | failOn(D.data(), "CIE is too small"); | 96 | failOn(D.data(), "CIE is too small"); |
| 98 | D = D.slice(Count); | 97 | D = D.slice(Count); |
| 99 | } | 98 | } |
| 100 | 99 | ||
| 101 | // Read a null-terminated string. | 100 | // Read a null-terminated string. |
| 102 | template <class ELFT> StringRef EhReader<ELFT>::readString() { | 101 | StringRef EhReader::readString() { |
| 103 | const uint8_t *End = std::find(D.begin(), D.end(), '\0'); | 102 | const uint8_t *End = std::find(D.begin(), D.end(), '\0'); |
| 104 | if (End == D.end()) | 103 | if (End == D.end()) |
| 105 | failOn(D.data(), "corrupted CIE (failed to read string)"); | 104 | failOn(D.data(), "corrupted CIE (failed to read string)"); |
| ... | @@ -112,7 +111,7 @@ template <class ELFT> StringRef EhReader<ELFT>::readString() { | ... | @@ -112,7 +111,7 @@ template <class ELFT> StringRef EhReader<ELFT>::readString() { |
| 112 | // Actual number is not of interest because only the runtime needs it. | 111 | // Actual number is not of interest because only the runtime needs it. |
| 113 | // But we need to be at least able to skip it so that we can read | 112 | // But we need to be at least able to skip it so that we can read |
| 114 | // the field that follows a LEB128 number. | 113 | // the field that follows a LEB128 number. |
| 115 | template <class ELFT> void EhReader<ELFT>::skipLeb128() { | 114 | void EhReader::skipLeb128() { |
| 116 | const uint8_t *ErrPos = D.data(); | 115 | const uint8_t *ErrPos = D.data(); |
| 117 | while (!D.empty()) { | 116 | while (!D.empty()) { |
| 118 | uint8_t Val = D.front(); | 117 | uint8_t Val = D.front(); |
| ... | @@ -141,7 +140,7 @@ static size_t getAugPSize(unsigned Enc) { | ... | @@ -141,7 +140,7 @@ static size_t getAugPSize(unsigned Enc) { |
| 141 | return 0; | 140 | return 0; |
| 142 | } | 141 | } |
| 143 | 142 | ||
| 144 | template <class ELFT> void EhReader<ELFT>::skipAugP() { | 143 | void EhReader::skipAugP() { |
| 145 | uint8_t Enc = readByte(); | 144 | uint8_t Enc = readByte(); |
| 146 | if ((Enc & 0xf0) == DW_EH_PE_aligned) | 145 | if ((Enc & 0xf0) == DW_EH_PE_aligned) |
| 147 | failOn(D.data() - 1, "DW_EH_PE_aligned encoding is not supported"); | 146 | failOn(D.data() - 1, "DW_EH_PE_aligned encoding is not supported"); |
| ... | @@ -153,12 +152,11 @@ template <class ELFT> void EhReader<ELFT>::skipAugP() { | ... | @@ -153,12 +152,11 @@ template <class ELFT> void EhReader<ELFT>::skipAugP() { |
| 153 | D = D.slice(Size); | 152 | D = D.slice(Size); |
| 154 | } | 153 | } |
| 155 | 154 | ||
| 156 | template <class ELFT> uint8_t elf::getFdeEncoding(EhSectionPiece *P) { | 155 | uint8_t elf::getFdeEncoding(EhSectionPiece *P) { |
| 157 | auto *IS = static_cast<InputSectionBase *>(P->ID); | 156 | return EhReader(P->Sec, P->data()).getFdeEncoding(); |
| 158 | return EhReader<ELFT>(IS, P->data()).getFdeEncoding(); | ||
| 159 | } | 157 | } |
| 160 | 158 | ||
| 161 | template <class ELFT> uint8_t EhReader<ELFT>::getFdeEncoding() { | 159 | uint8_t EhReader::getFdeEncoding() { |
| 162 | skipBytes(8); | 160 | skipBytes(8); |
| 163 | int Version = readByte(); | 161 | int Version = readByte(); |
| 164 | if (Version != 1 && Version != 3) | 162 | if (Version != 1 && Version != 3) |
| ... | @@ -200,13 +198,3 @@ template <class ELFT> uint8_t EhReader<ELFT>::getFdeEncoding() { | ... | @@ -200,13 +198,3 @@ template <class ELFT> uint8_t EhReader<ELFT>::getFdeEncoding() { |
| 200 | } | 198 | } |
| 201 | return DW_EH_PE_absptr; | 199 | return DW_EH_PE_absptr; |
| 202 | } | 200 | } |
| 203 | |||
| 204 | template size_t elf::readEhRecordSize<ELF32LE>(InputSectionBase *S, size_t Off); | ||
| 205 | template size_t elf::readEhRecordSize<ELF32BE>(InputSectionBase *S, size_t Off); | ||
| 206 | template size_t elf::readEhRecordSize<ELF64LE>(InputSectionBase *S, size_t Off); | ||
| 207 | template size_t elf::readEhRecordSize<ELF64BE>(InputSectionBase *S, size_t Off); | ||
| 208 | |||
| 209 | template uint8_t elf::getFdeEncoding<ELF32LE>(EhSectionPiece *P); | ||
| 210 | template uint8_t elf::getFdeEncoding<ELF32BE>(EhSectionPiece *P); | ||
| 211 | template uint8_t elf::getFdeEncoding<ELF64LE>(EhSectionPiece *P); | ||
| 212 | template uint8_t elf::getFdeEncoding<ELF64BE>(EhSectionPiece *P); |
deps/lld/ELF/EhFrame.h+3-3| ... | @@ -10,15 +10,15 @@ | ... | @@ -10,15 +10,15 @@ |
| 10 | #ifndef LLD_ELF_EHFRAME_H | 10 | #ifndef LLD_ELF_EHFRAME_H |
| 11 | #define LLD_ELF_EHFRAME_H | 11 | #define LLD_ELF_EHFRAME_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | 14 | ||
| 15 | namespace lld { | 15 | namespace lld { |
| 16 | namespace elf { | 16 | namespace elf { |
| 17 | class InputSectionBase; | 17 | class InputSectionBase; |
| 18 | struct EhSectionPiece; | 18 | struct EhSectionPiece; |
| 19 | 19 | ||
| 20 | template <class ELFT> size_t readEhRecordSize(InputSectionBase *S, size_t Off); | 20 | size_t readEhRecordSize(InputSectionBase *S, size_t Off); |
| 21 | template <class ELFT> uint8_t getFdeEncoding(EhSectionPiece *P); | 21 | uint8_t getFdeEncoding(EhSectionPiece *P); |
| 22 | } // namespace elf | 22 | } // namespace elf |
| 23 | } // namespace lld | 23 | } // namespace lld |
| 24 | 24 |
deps/lld/ELF/Error.cpp deleted-116| ... | @@ -1,116 +0,0 @@ | ||
| 1 | //===- Error.cpp ----------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "Error.h" | ||
| 11 | #include "Config.h" | ||
| 12 | |||
| 13 | #include "llvm/ADT/Twine.h" | ||
| 14 | #include "llvm/Support/Error.h" | ||
| 15 | #include "llvm/Support/ManagedStatic.h" | ||
| 16 | #include "llvm/Support/raw_ostream.h" | ||
| 17 | #include <mutex> | ||
| 18 | |||
| 19 | #if !defined(_MSC_VER) && !defined(__MINGW32__) | ||
| 20 | #include <unistd.h> | ||
| 21 | #endif | ||
| 22 | |||
| 23 | using namespace llvm; | ||
| 24 | |||
| 25 | using namespace lld; | ||
| 26 | using namespace lld::elf; | ||
| 27 | |||
| 28 | uint64_t elf::ErrorCount; | ||
| 29 | raw_ostream *elf::ErrorOS; | ||
| 30 | |||
| 31 | // The functions defined in this file can be called from multiple threads, | ||
| 32 | // but outs() or errs() are not thread-safe. We protect them using a mutex. | ||
| 33 | static std::mutex Mu; | ||
| 34 | |||
| 35 | // Prints "\n" or does nothing, depending on Msg contents of | ||
| 36 | // the previous call of this function. | ||
| 37 | static void newline(const Twine &Msg) { | ||
| 38 | // True if the previous error message contained "\n". | ||
| 39 | // We want to separate multi-line error messages with a newline. | ||
| 40 | static bool Flag; | ||
| 41 | |||
| 42 | if (Flag) | ||
| 43 | *ErrorOS << "\n"; | ||
| 44 | Flag = (StringRef(Msg.str()).find('\n') != StringRef::npos); | ||
| 45 | } | ||
| 46 | |||
| 47 | static void print(StringRef S, raw_ostream::Colors C) { | ||
| 48 | *ErrorOS << Config->Argv[0] << ": "; | ||
| 49 | if (Config->ColorDiagnostics) { | ||
| 50 | ErrorOS->changeColor(C, true); | ||
| 51 | *ErrorOS << S; | ||
| 52 | ErrorOS->resetColor(); | ||
| 53 | } else { | ||
| 54 | *ErrorOS << S; | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | void elf::log(const Twine &Msg) { | ||
| 59 | if (Config->Verbose) { | ||
| 60 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 61 | outs() << Config->Argv[0] << ": " << Msg << "\n"; | ||
| 62 | outs().flush(); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | void elf::message(const Twine &Msg) { | ||
| 67 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 68 | outs() << Msg << "\n"; | ||
| 69 | outs().flush(); | ||
| 70 | } | ||
| 71 | |||
| 72 | void elf::warn(const Twine &Msg) { | ||
| 73 | if (Config->FatalWarnings) { | ||
| 74 | error(Msg); | ||
| 75 | return; | ||
| 76 | } | ||
| 77 | |||
| 78 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 79 | newline(Msg); | ||
| 80 | print("warning: ", raw_ostream::MAGENTA); | ||
| 81 | *ErrorOS << Msg << "\n"; | ||
| 82 | } | ||
| 83 | |||
| 84 | void elf::error(const Twine &Msg) { | ||
| 85 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 86 | newline(Msg); | ||
| 87 | |||
| 88 | if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) { | ||
| 89 | print("error: ", raw_ostream::RED); | ||
| 90 | *ErrorOS << Msg << "\n"; | ||
| 91 | } else if (ErrorCount == Config->ErrorLimit) { | ||
| 92 | print("error: ", raw_ostream::RED); | ||
| 93 | *ErrorOS << "too many errors emitted, stopping now" | ||
| 94 | << " (use -error-limit=0 to see all errors)\n"; | ||
| 95 | if (Config->ExitEarly) | ||
| 96 | exitLld(1); | ||
| 97 | } | ||
| 98 | |||
| 99 | ++ErrorCount; | ||
| 100 | } | ||
| 101 | |||
| 102 | void elf::exitLld(int Val) { | ||
| 103 | // Dealloc/destroy ManagedStatic variables before calling | ||
| 104 | // _exit(). In a non-LTO build, this is a nop. In an LTO | ||
| 105 | // build allows us to get the output of -time-passes. | ||
| 106 | llvm_shutdown(); | ||
| 107 | |||
| 108 | outs().flush(); | ||
| 109 | errs().flush(); | ||
| 110 | _exit(Val); | ||
| 111 | } | ||
| 112 | |||
| 113 | void elf::fatal(const Twine &Msg) { | ||
| 114 | error(Msg); | ||
| 115 | exitLld(1); | ||
| 116 | } | ||
deps/lld/ELF/Error.h deleted-78| ... | @@ -1,78 +0,0 @@ | ||
| 1 | //===- Error.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 | // In LLD, we have three levels of errors: fatal, error or warn. | ||
| 11 | // | ||
| 12 | // Fatal makes the program exit immediately with an error message. | ||
| 13 | // You shouldn't use it except for reporting a corrupted input file. | ||
| 14 | // | ||
| 15 | // Error prints out an error message and increment a global variable | ||
| 16 | // ErrorCount to record the fact that we met an error condition. It does | ||
| 17 | // not exit, so it is safe for a lld-as-a-library use case. It is generally | ||
| 18 | // useful because it can report more than one error in a single run. | ||
| 19 | // | ||
| 20 | // Warn doesn't do anything but printing out a given message. | ||
| 21 | // | ||
| 22 | // It is not recommended to use llvm::outs() or llvm::errs() directly | ||
| 23 | // in LLD because they are not thread-safe. The functions declared in | ||
| 24 | // this file are mutually excluded, so you want to use them instead. | ||
| 25 | // | ||
| 26 | //===----------------------------------------------------------------------===// | ||
| 27 | |||
| 28 | #ifndef LLD_ELF_ERROR_H | ||
| 29 | #define LLD_ELF_ERROR_H | ||
| 30 | |||
| 31 | #include "lld/Core/LLVM.h" | ||
| 32 | |||
| 33 | #include "llvm/Support/Error.h" | ||
| 34 | |||
| 35 | namespace lld { | ||
| 36 | namespace elf { | ||
| 37 | |||
| 38 | extern uint64_t ErrorCount; | ||
| 39 | extern llvm::raw_ostream *ErrorOS; | ||
| 40 | |||
| 41 | void log(const Twine &Msg); | ||
| 42 | void message(const Twine &Msg); | ||
| 43 | void warn(const Twine &Msg); | ||
| 44 | void error(const Twine &Msg); | ||
| 45 | LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); | ||
| 46 | |||
| 47 | LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); | ||
| 48 | |||
| 49 | // check() functions are convenient functions to strip errors | ||
| 50 | // from error-or-value objects. | ||
| 51 | template <class T> T check(ErrorOr<T> E) { | ||
| 52 | if (auto EC = E.getError()) | ||
| 53 | fatal(EC.message()); | ||
| 54 | return std::move(*E); | ||
| 55 | } | ||
| 56 | |||
| 57 | template <class T> T check(Expected<T> E) { | ||
| 58 | if (!E) | ||
| 59 | fatal(llvm::toString(E.takeError())); | ||
| 60 | return std::move(*E); | ||
| 61 | } | ||
| 62 | |||
| 63 | template <class T> T check(ErrorOr<T> E, const Twine &Prefix) { | ||
| 64 | if (auto EC = E.getError()) | ||
| 65 | fatal(Prefix + ": " + EC.message()); | ||
| 66 | return std::move(*E); | ||
| 67 | } | ||
| 68 | |||
| 69 | template <class T> T check(Expected<T> E, const Twine &Prefix) { | ||
| 70 | if (!E) | ||
| 71 | fatal(Prefix + ": " + toString(E.takeError())); | ||
| 72 | return std::move(*E); | ||
| 73 | } | ||
| 74 | |||
| 75 | } // namespace elf | ||
| 76 | } // namespace lld | ||
| 77 | |||
| 78 | #endif | ||
deps/lld/ELF/Filesystem.cpp+27-18| ... | @@ -13,8 +13,13 @@ | ... | @@ -13,8 +13,13 @@ |
| 13 | 13 | ||
| 14 | #include "Filesystem.h" | 14 | #include "Filesystem.h" |
| 15 | #include "Config.h" | 15 | #include "Config.h" |
| 16 | #include "llvm/Support/FileSystem.h" | 16 | #include "lld/Common/Threads.h" |
| 17 | #include "llvm/Config/llvm-config.h" | ||
| 17 | #include "llvm/Support/FileOutputBuffer.h" | 18 | #include "llvm/Support/FileOutputBuffer.h" |
| 19 | #include "llvm/Support/FileSystem.h" | ||
| 20 | #if LLVM_ON_UNIX | ||
| 21 | #include <unistd.h> | ||
| 22 | #endif | ||
| 18 | #include <thread> | 23 | #include <thread> |
| 19 | 24 | ||
| 20 | using namespace llvm; | 25 | using namespace llvm; |
| ... | @@ -35,27 +40,29 @@ using namespace lld::elf; | ... | @@ -35,27 +40,29 @@ using namespace lld::elf; |
| 35 | // Since LLD can link a 1 GB binary in about 5 seconds, that waste | 40 | // Since LLD can link a 1 GB binary in about 5 seconds, that waste |
| 36 | // actually counts. | 41 | // actually counts. |
| 37 | // | 42 | // |
| 38 | // This function spawns a background thread to call unlink. | 43 | // This function spawns a background thread to remove the file. |
| 39 | // The calling thread returns almost immediately. | 44 | // The calling thread returns almost immediately. |
| 40 | void elf::unlinkAsync(StringRef Path) { | 45 | void elf::unlinkAsync(StringRef Path) { |
| 41 | if (!Config->Threads || !sys::fs::exists(Config->OutputFile) || | 46 | // Removing a file is async on windows. |
| 42 | !sys::fs::is_regular_file(Config->OutputFile)) | 47 | #if defined(LLVM_ON_WIN32) |
| 48 | sys::fs::remove(Path); | ||
| 49 | #else | ||
| 50 | if (!ThreadsEnabled || !sys::fs::exists(Path) || | ||
| 51 | !sys::fs::is_regular_file(Path)) | ||
| 43 | return; | 52 | return; |
| 44 | 53 | ||
| 45 | // First, rename Path to avoid race condition. We cannot remove | 54 | // We cannot just remove path from a different thread because we are now going |
| 46 | // Path from a different thread because we are now going to create | 55 | // to create path as a new file. |
| 47 | // Path as a new file. If we do that in a different thread, the new | 56 | // Instead we open the file and unlink it on this thread. The unlink is fast |
| 48 | // thread can remove the new file. | 57 | // since the open fd guarantees that it is not removing the last reference. |
| 49 | SmallString<128> TempPath; | 58 | int FD; |
| 50 | if (sys::fs::createUniqueFile(Path + "tmp%%%%%%%%", TempPath)) | 59 | std::error_code EC = sys::fs::openFileForRead(Path, FD); |
| 51 | return; | 60 | sys::fs::remove(Path); |
| 52 | if (sys::fs::rename(Path, TempPath)) { | ||
| 53 | sys::fs::remove(TempPath); | ||
| 54 | return; | ||
| 55 | } | ||
| 56 | 61 | ||
| 57 | // Remove TempPath in background. | 62 | // close and therefore remove TempPath in background. |
| 58 | std::thread([=] { ::remove(TempPath.str().str().c_str()); }).detach(); | 63 | if (!EC) |
| 64 | std::thread([=] { ::close(FD); }).detach(); | ||
| 65 | #endif | ||
| 59 | } | 66 | } |
| 60 | 67 | ||
| 61 | // Simulate file creation to see if Path is writable. | 68 | // Simulate file creation to see if Path is writable. |
| ... | @@ -73,5 +80,7 @@ void elf::unlinkAsync(StringRef Path) { | ... | @@ -73,5 +80,7 @@ void elf::unlinkAsync(StringRef Path) { |
| 73 | std::error_code elf::tryCreateFile(StringRef Path) { | 80 | std::error_code elf::tryCreateFile(StringRef Path) { |
| 74 | if (Path.empty()) | 81 | if (Path.empty()) |
| 75 | return std::error_code(); | 82 | return std::error_code(); |
| 76 | return FileOutputBuffer::create(Path, 1).getError(); | 83 | if (Path == "-") |
| 84 | return std::error_code(); | ||
| 85 | return errorToErrorCode(FileOutputBuffer::create(Path, 1).takeError()); | ||
| 77 | } | 86 | } |
deps/lld/ELF/Filesystem.h+2-1| ... | @@ -10,7 +10,8 @@ | ... | @@ -10,7 +10,8 @@ |
| 10 | #ifndef LLD_ELF_FILESYSTEM_H | 10 | #ifndef LLD_ELF_FILESYSTEM_H |
| 11 | #define LLD_ELF_FILESYSTEM_H | 11 | #define LLD_ELF_FILESYSTEM_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include <system_error> | ||
| 14 | 15 | ||
| 15 | namespace lld { | 16 | namespace lld { |
| 16 | namespace elf { | 17 | namespace elf { |
deps/lld/ELF/GdbIndex.cpp+70-18| ... | @@ -15,7 +15,8 @@ | ... | @@ -15,7 +15,8 @@ |
| 15 | //===----------------------------------------------------------------------===// | 15 | //===----------------------------------------------------------------------===// |
| 16 | 16 | ||
| 17 | #include "GdbIndex.h" | 17 | #include "GdbIndex.h" |
| 18 | #include "Memory.h" | 18 | #include "Symbols.h" |
| 19 | #include "lld/Common/Memory.h" | ||
| 19 | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" | 20 | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" |
| 20 | #include "llvm/Object/ELFObjectFile.h" | 21 | #include "llvm/Object/ELFObjectFile.h" |
| 21 | 22 | ||
| ... | @@ -24,26 +25,77 @@ using namespace llvm::object; | ... | @@ -24,26 +25,77 @@ using namespace llvm::object; |
| 24 | using namespace lld; | 25 | using namespace lld; |
| 25 | using namespace lld::elf; | 26 | using namespace lld::elf; |
| 26 | 27 | ||
| 27 | std::pair<bool, GdbSymbol *> GdbHashTab::add(uint32_t Hash, size_t Offset) { | 28 | template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *Obj) { |
| 28 | GdbSymbol *&Sym = Map[Offset]; | 29 | for (InputSectionBase *Sec : Obj->getSections()) { |
| 29 | if (Sym) | 30 | if (!Sec) |
| 30 | return {false, Sym}; | 31 | continue; |
| 31 | Sym = make<GdbSymbol>(Hash, Offset); | 32 | if (LLDDWARFSection *M = StringSwitch<LLDDWARFSection *>(Sec->Name) |
| 32 | return {true, Sym}; | 33 | .Case(".debug_info", &InfoSection) |
| 34 | .Case(".debug_ranges", &RangeSection) | ||
| 35 | .Case(".debug_line", &LineSection) | ||
| 36 | .Default(nullptr)) { | ||
| 37 | Sec->maybeUncompress(); | ||
| 38 | M->Data = toStringRef(Sec->Data); | ||
| 39 | M->Sec = Sec; | ||
| 40 | continue; | ||
| 41 | } | ||
| 42 | if (Sec->Name == ".debug_abbrev") | ||
| 43 | AbbrevSection = toStringRef(Sec->Data); | ||
| 44 | else if (Sec->Name == ".debug_gnu_pubnames") | ||
| 45 | GnuPubNamesSection = toStringRef(Sec->Data); | ||
| 46 | else if (Sec->Name == ".debug_gnu_pubtypes") | ||
| 47 | GnuPubTypesSection = toStringRef(Sec->Data); | ||
| 48 | else if (Sec->Name == ".debug_str") | ||
| 49 | StrSection = toStringRef(Sec->Data); | ||
| 50 | } | ||
| 33 | } | 51 | } |
| 34 | 52 | ||
| 35 | void GdbHashTab::finalizeContents() { | 53 | // Find if there is a relocation at Pos in Sec. The code is a bit |
| 36 | uint32_t Size = std::max<uint32_t>(1024, NextPowerOf2(Map.size() * 4 / 3)); | 54 | // more complicated than usual because we need to pass a section index |
| 37 | uint32_t Mask = Size - 1; | 55 | // to llvm since it has no idea about InputSection. |
| 38 | Table.resize(Size); | 56 | template <class ELFT> |
| 57 | template <class RelTy> | ||
| 58 | Optional<RelocAddrEntry> | ||
| 59 | LLDDwarfObj<ELFT>::findAux(const InputSectionBase &Sec, uint64_t Pos, | ||
| 60 | ArrayRef<RelTy> Rels) const { | ||
| 61 | auto It = std::lower_bound( | ||
| 62 | Rels.begin(), Rels.end(), Pos, | ||
| 63 | [](const RelTy &A, uint64_t B) { return A.r_offset < B; }); | ||
| 64 | if (It == Rels.end() || It->r_offset != Pos) | ||
| 65 | return None; | ||
| 66 | const RelTy &Rel = *It; | ||
| 39 | 67 | ||
| 40 | for (auto &P : Map) { | 68 | const ObjFile<ELFT> *File = Sec.getFile<ELFT>(); |
| 41 | GdbSymbol *Sym = P.second; | 69 | uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); |
| 42 | uint32_t I = Sym->NameHash & Mask; | 70 | const typename ELFT::Sym &Sym = File->getELFSyms()[SymIndex]; |
| 43 | uint32_t Step = ((Sym->NameHash * 17) & Mask) | 1; | 71 | uint32_t SecIndex = File->getSectionIndex(Sym); |
| 44 | 72 | ||
| 45 | while (Table[I]) | 73 | // Broken debug info can point to a non-Defined symbol. |
| 46 | I = (I + Step) & Mask; | 74 | auto *DR = dyn_cast<Defined>(&File->getRelocTargetSym(Rel)); |
| 47 | Table[I] = Sym; | 75 | if (!DR) { |
| 76 | error("unsupported relocation target while parsing debug info"); | ||
| 77 | return None; | ||
| 48 | } | 78 | } |
| 79 | uint64_t Val = DR->Value + getAddend<ELFT>(Rel); | ||
| 80 | |||
| 81 | // FIXME: We should be consistent about always adding the file | ||
| 82 | // offset or not. | ||
| 83 | if (DR->Section->Flags & ELF::SHF_ALLOC) | ||
| 84 | Val += cast<InputSection>(DR->Section)->getOffsetInFile(); | ||
| 85 | |||
| 86 | return RelocAddrEntry{SecIndex, Val}; | ||
| 49 | } | 87 | } |
| 88 | |||
| 89 | template <class ELFT> | ||
| 90 | Optional<RelocAddrEntry> LLDDwarfObj<ELFT>::find(const llvm::DWARFSection &S, | ||
| 91 | uint64_t Pos) const { | ||
| 92 | auto &Sec = static_cast<const LLDDWARFSection &>(S); | ||
| 93 | if (Sec.Sec->AreRelocsRela) | ||
| 94 | return findAux(*Sec.Sec, Pos, Sec.Sec->template relas<ELFT>()); | ||
| 95 | return findAux(*Sec.Sec, Pos, Sec.Sec->template rels<ELFT>()); | ||
| 96 | } | ||
| 97 | |||
| 98 | template class elf::LLDDwarfObj<ELF32LE>; | ||
| 99 | template class elf::LLDDwarfObj<ELF32BE>; | ||
| 100 | template class elf::LLDDwarfObj<ELF64LE>; | ||
| 101 | template class elf::LLDDwarfObj<ELF64BE>; |
deps/lld/ELF/GdbIndex.h+39-50| ... | @@ -19,61 +19,50 @@ namespace elf { | ... | @@ -19,61 +19,50 @@ namespace elf { |
| 19 | 19 | ||
| 20 | class InputSection; | 20 | class InputSection; |
| 21 | 21 | ||
| 22 | // Struct represents single entry of address area of gdb index. | 22 | struct LLDDWARFSection final : public llvm::DWARFSection { |
| 23 | struct AddressEntry { | 23 | InputSectionBase *Sec = nullptr; |
| 24 | InputSection *Section; | ||
| 25 | uint64_t LowAddress; | ||
| 26 | uint64_t HighAddress; | ||
| 27 | uint32_t CuIndex; | ||
| 28 | }; | 24 | }; |
| 29 | 25 | ||
| 30 | // Struct represents single entry of compilation units list area of gdb index. | 26 | template <class ELFT> class LLDDwarfObj final : public llvm::DWARFObject { |
| 31 | // It consist of CU offset in .debug_info section and it's size. | 27 | LLDDWARFSection InfoSection; |
| 32 | struct CompilationUnitEntry { | 28 | LLDDWARFSection RangeSection; |
| 33 | uint64_t CuOffset; | 29 | LLDDWARFSection LineSection; |
| 34 | uint64_t CuLength; | 30 | StringRef AbbrevSection; |
| 35 | }; | 31 | StringRef GnuPubNamesSection; |
| 36 | 32 | StringRef GnuPubTypesSection; | |
| 37 | // Represents data about symbol and type names which are used | 33 | StringRef StrSection; |
| 38 | // to build symbol table and constant pool area of gdb index. | ||
| 39 | struct NameTypeEntry { | ||
| 40 | StringRef Name; | ||
| 41 | uint8_t Type; | ||
| 42 | }; | ||
| 43 | |||
| 44 | // We fill one GdbIndexDataChunk for each object where scan of | ||
| 45 | // debug information performed. That information futher used | ||
| 46 | // for filling gdb index section areas. | ||
| 47 | struct GdbIndexChunk { | ||
| 48 | InputSection *DebugInfoSec; | ||
| 49 | std::vector<AddressEntry> AddressArea; | ||
| 50 | std::vector<CompilationUnitEntry> CompilationUnits; | ||
| 51 | std::vector<NameTypeEntry> NamesAndTypes; | ||
| 52 | }; | ||
| 53 | 34 | ||
| 54 | // Element of GdbHashTab hash table. | 35 | template <class RelTy> |
| 55 | struct GdbSymbol { | 36 | llvm::Optional<llvm::RelocAddrEntry> findAux(const InputSectionBase &Sec, |
| 56 | GdbSymbol(uint32_t Hash, size_t Offset) | 37 | uint64_t Pos, |
| 57 | : NameHash(Hash), NameOffset(Offset) {} | 38 | ArrayRef<RelTy> Rels) const; |
| 58 | uint32_t NameHash; | ||
| 59 | size_t NameOffset; | ||
| 60 | size_t CuVectorIndex; | ||
| 61 | }; | ||
| 62 | 39 | ||
| 63 | // This class manages the hashed symbol table for the .gdb_index section. | ||
| 64 | // The hash value for a table entry is computed by applying an iterative hash | ||
| 65 | // function to the symbol's name. | ||
| 66 | class GdbHashTab final { | ||
| 67 | public: | 40 | public: |
| 68 | std::pair<bool, GdbSymbol *> add(uint32_t Hash, size_t Offset); | 41 | explicit LLDDwarfObj(ObjFile<ELFT> *Obj); |
| 69 | 42 | const llvm::DWARFSection &getInfoSection() const override { | |
| 70 | void finalizeContents(); | 43 | return InfoSection; |
| 71 | size_t getCapacity() { return Table.size(); } | 44 | } |
| 72 | GdbSymbol *getSymbol(size_t I) { return Table[I]; } | 45 | const llvm::DWARFSection &getRangeSection() const override { |
| 73 | 46 | return RangeSection; | |
| 74 | private: | 47 | } |
| 75 | llvm::DenseMap<size_t, GdbSymbol *> Map; | 48 | const llvm::DWARFSection &getLineSection() const override { |
| 76 | std::vector<GdbSymbol *> Table; | 49 | return LineSection; |
| 50 | } | ||
| 51 | StringRef getFileName() const override { return ""; } | ||
| 52 | StringRef getCUIndexSection() const override { return ""; } | ||
| 53 | StringRef getAbbrevSection() const override { return AbbrevSection; } | ||
| 54 | StringRef getStringSection() const override { return StrSection; } | ||
| 55 | StringRef getGnuPubNamesSection() const override { | ||
| 56 | return GnuPubNamesSection; | ||
| 57 | } | ||
| 58 | StringRef getGnuPubTypesSection() const override { | ||
| 59 | return GnuPubTypesSection; | ||
| 60 | } | ||
| 61 | bool isLittleEndian() const override { | ||
| 62 | return ELFT::TargetEndianness == llvm::support::little; | ||
| 63 | } | ||
| 64 | llvm::Optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &Sec, | ||
| 65 | uint64_t Pos) const override; | ||
| 77 | }; | 66 | }; |
| 78 | 67 | ||
| 79 | } // namespace elf | 68 | } // namespace elf |
deps/lld/ELF/ICF.cpp+59-40| ... | @@ -76,7 +76,8 @@ | ... | @@ -76,7 +76,8 @@ |
| 76 | #include "ICF.h" | 76 | #include "ICF.h" |
| 77 | #include "Config.h" | 77 | #include "Config.h" |
| 78 | #include "SymbolTable.h" | 78 | #include "SymbolTable.h" |
| 79 | #include "Threads.h" | 79 | #include "Symbols.h" |
| 80 | #include "lld/Common/Threads.h" | ||
| 80 | #include "llvm/ADT/Hashing.h" | 81 | #include "llvm/ADT/Hashing.h" |
| 81 | #include "llvm/BinaryFormat/ELF.h" | 82 | #include "llvm/BinaryFormat/ELF.h" |
| 82 | #include "llvm/Object/ELF.h" | 83 | #include "llvm/Object/ELF.h" |
| ... | @@ -155,16 +156,20 @@ private: | ... | @@ -155,16 +156,20 @@ private: |
| 155 | // Returns a hash value for S. Note that the information about | 156 | // Returns a hash value for S. Note that the information about |
| 156 | // relocation targets is not included in the hash value. | 157 | // relocation targets is not included in the hash value. |
| 157 | template <class ELFT> static uint32_t getHash(InputSection *S) { | 158 | template <class ELFT> static uint32_t getHash(InputSection *S) { |
| 158 | return hash_combine(S->Flags, S->getSize(), S->NumRelocations); | 159 | return hash_combine(S->Flags, S->getSize(), S->NumRelocations, S->Data); |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 161 | // Returns true if section S is subject of ICF. | 162 | // Returns true if section S is subject of ICF. |
| 162 | static bool isEligible(InputSection *S) { | 163 | static bool isEligible(InputSection *S) { |
| 164 | // Don't merge read only data sections unless --icf-data was passed. | ||
| 165 | if (!(S->Flags & SHF_EXECINSTR) && !Config->ICFData) | ||
| 166 | return false; | ||
| 167 | |||
| 163 | // .init and .fini contains instructions that must be executed to | 168 | // .init and .fini contains instructions that must be executed to |
| 164 | // initialize and finalize the process. They cannot and should not | 169 | // initialize and finalize the process. They cannot and should not |
| 165 | // be merged. | 170 | // be merged. |
| 166 | return S->Live && (S->Flags & SHF_ALLOC) && (S->Flags & SHF_EXECINSTR) && | 171 | return S->Live && (S->Flags & SHF_ALLOC) && !(S->Flags & SHF_WRITE) && |
| 167 | !(S->Flags & SHF_WRITE) && S->Name != ".init" && S->Name != ".fini"; | 172 | S->Name != ".init" && S->Name != ".fini"; |
| 168 | } | 173 | } |
| 169 | 174 | ||
| 170 | // Split an equivalence class into smaller classes. | 175 | // Split an equivalence class into smaller classes. |
| ... | @@ -207,38 +212,49 @@ void ICF<ELFT>::segregate(size_t Begin, size_t End, bool Constant) { | ... | @@ -207,38 +212,49 @@ void ICF<ELFT>::segregate(size_t Begin, size_t End, bool Constant) { |
| 207 | // Compare two lists of relocations. | 212 | // Compare two lists of relocations. |
| 208 | template <class ELFT> | 213 | template <class ELFT> |
| 209 | template <class RelTy> | 214 | template <class RelTy> |
| 210 | bool ICF<ELFT>::constantEq(const InputSection *A, ArrayRef<RelTy> RelsA, | 215 | bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA, |
| 211 | const InputSection *B, ArrayRef<RelTy> RelsB) { | 216 | const InputSection *SecB, ArrayRef<RelTy> RB) { |
| 212 | auto Eq = [&](const RelTy &RA, const RelTy &RB) { | 217 | if (RA.size() != RB.size()) |
| 213 | if (RA.r_offset != RB.r_offset || | 218 | return false; |
| 214 | RA.getType(Config->IsMips64EL) != RB.getType(Config->IsMips64EL)) | 219 | |
| 220 | for (size_t I = 0; I < RA.size(); ++I) { | ||
| 221 | if (RA[I].r_offset != RB[I].r_offset || | ||
| 222 | RA[I].getType(Config->IsMips64EL) != RB[I].getType(Config->IsMips64EL)) | ||
| 215 | return false; | 223 | return false; |
| 216 | uint64_t AddA = getAddend<ELFT>(RA); | ||
| 217 | uint64_t AddB = getAddend<ELFT>(RB); | ||
| 218 | 224 | ||
| 219 | SymbolBody &SA = A->template getFile<ELFT>()->getRelocTargetSym(RA); | 225 | uint64_t AddA = getAddend<ELFT>(RA[I]); |
| 220 | SymbolBody &SB = B->template getFile<ELFT>()->getRelocTargetSym(RB); | 226 | uint64_t AddB = getAddend<ELFT>(RB[I]); |
| 221 | if (&SA == &SB) | ||
| 222 | return AddA == AddB; | ||
| 223 | 227 | ||
| 224 | auto *DA = dyn_cast<DefinedRegular>(&SA); | 228 | Symbol &SA = SecA->template getFile<ELFT>()->getRelocTargetSym(RA[I]); |
| 225 | auto *DB = dyn_cast<DefinedRegular>(&SB); | 229 | Symbol &SB = SecB->template getFile<ELFT>()->getRelocTargetSym(RB[I]); |
| 230 | if (&SA == &SB) { | ||
| 231 | if (AddA == AddB) | ||
| 232 | continue; | ||
| 233 | return false; | ||
| 234 | } | ||
| 235 | |||
| 236 | auto *DA = dyn_cast<Defined>(&SA); | ||
| 237 | auto *DB = dyn_cast<Defined>(&SB); | ||
| 226 | if (!DA || !DB) | 238 | if (!DA || !DB) |
| 227 | return false; | 239 | return false; |
| 228 | 240 | ||
| 229 | // Relocations referring to absolute symbols are constant-equal if their | 241 | // Relocations referring to absolute symbols are constant-equal if their |
| 230 | // values are equal. | 242 | // values are equal. |
| 243 | if (!DA->Section && !DB->Section && DA->Value + AddA == DB->Value + AddB) | ||
| 244 | continue; | ||
| 231 | if (!DA->Section || !DB->Section) | 245 | if (!DA->Section || !DB->Section) |
| 232 | return !DA->Section && !DB->Section && | 246 | return false; |
| 233 | DA->Value + AddA == DB->Value + AddB; | ||
| 234 | 247 | ||
| 235 | if (DA->Section->kind() != DB->Section->kind()) | 248 | if (DA->Section->kind() != DB->Section->kind()) |
| 236 | return false; | 249 | return false; |
| 237 | 250 | ||
| 238 | // Relocations referring to InputSections are constant-equal if their | 251 | // Relocations referring to InputSections are constant-equal if their |
| 239 | // section offsets are equal. | 252 | // section offsets are equal. |
| 240 | if (isa<InputSection>(DA->Section)) | 253 | if (isa<InputSection>(DA->Section)) { |
| 241 | return DA->Value + AddA == DB->Value + AddB; | 254 | if (DA->Value + AddA == DB->Value + AddB) |
| 255 | continue; | ||
| 256 | return false; | ||
| 257 | } | ||
| 242 | 258 | ||
| 243 | // Relocations referring to MergeInputSections are constant-equal if their | 259 | // Relocations referring to MergeInputSections are constant-equal if their |
| 244 | // offsets in the output section are equal. | 260 | // offsets in the output section are equal. |
| ... | @@ -253,11 +269,11 @@ bool ICF<ELFT>::constantEq(const InputSection *A, ArrayRef<RelTy> RelsA, | ... | @@ -253,11 +269,11 @@ bool ICF<ELFT>::constantEq(const InputSection *A, ArrayRef<RelTy> RelsA, |
| 253 | SA.isSection() ? X->getOffset(AddA) : X->getOffset(DA->Value) + AddA; | 269 | SA.isSection() ? X->getOffset(AddA) : X->getOffset(DA->Value) + AddA; |
| 254 | uint64_t OffsetB = | 270 | uint64_t OffsetB = |
| 255 | SB.isSection() ? Y->getOffset(AddB) : Y->getOffset(DB->Value) + AddB; | 271 | SB.isSection() ? Y->getOffset(AddB) : Y->getOffset(DB->Value) + AddB; |
| 256 | return OffsetA == OffsetB; | 272 | if (OffsetA != OffsetB) |
| 257 | }; | 273 | return false; |
| 274 | } | ||
| 258 | 275 | ||
| 259 | return RelsA.size() == RelsB.size() && | 276 | return true; |
| 260 | std::equal(RelsA.begin(), RelsA.end(), RelsB.begin(), Eq); | ||
| 261 | } | 277 | } |
| 262 | 278 | ||
| 263 | // Compare "non-moving" part of two InputSections, namely everything | 279 | // Compare "non-moving" part of two InputSections, namely everything |
| ... | @@ -278,37 +294,39 @@ bool ICF<ELFT>::equalsConstant(const InputSection *A, const InputSection *B) { | ... | @@ -278,37 +294,39 @@ bool ICF<ELFT>::equalsConstant(const InputSection *A, const InputSection *B) { |
| 278 | // relocations point to the same section in terms of ICF. | 294 | // relocations point to the same section in terms of ICF. |
| 279 | template <class ELFT> | 295 | template <class ELFT> |
| 280 | template <class RelTy> | 296 | template <class RelTy> |
| 281 | bool ICF<ELFT>::variableEq(const InputSection *A, ArrayRef<RelTy> RelsA, | 297 | bool ICF<ELFT>::variableEq(const InputSection *SecA, ArrayRef<RelTy> RA, |
| 282 | const InputSection *B, ArrayRef<RelTy> RelsB) { | 298 | const InputSection *SecB, ArrayRef<RelTy> RB) { |
| 283 | auto Eq = [&](const RelTy &RA, const RelTy &RB) { | 299 | assert(RA.size() == RB.size()); |
| 300 | |||
| 301 | for (size_t I = 0; I < RA.size(); ++I) { | ||
| 284 | // The two sections must be identical. | 302 | // The two sections must be identical. |
| 285 | SymbolBody &SA = A->template getFile<ELFT>()->getRelocTargetSym(RA); | 303 | Symbol &SA = SecA->template getFile<ELFT>()->getRelocTargetSym(RA[I]); |
| 286 | SymbolBody &SB = B->template getFile<ELFT>()->getRelocTargetSym(RB); | 304 | Symbol &SB = SecB->template getFile<ELFT>()->getRelocTargetSym(RB[I]); |
| 287 | if (&SA == &SB) | 305 | if (&SA == &SB) |
| 288 | return true; | 306 | continue; |
| 289 | 307 | ||
| 290 | auto *DA = cast<DefinedRegular>(&SA); | 308 | auto *DA = cast<Defined>(&SA); |
| 291 | auto *DB = cast<DefinedRegular>(&SB); | 309 | auto *DB = cast<Defined>(&SB); |
| 292 | 310 | ||
| 293 | // We already dealt with absolute and non-InputSection symbols in | 311 | // We already dealt with absolute and non-InputSection symbols in |
| 294 | // constantEq, and for InputSections we have already checked everything | 312 | // constantEq, and for InputSections we have already checked everything |
| 295 | // except the equivalence class. | 313 | // except the equivalence class. |
| 296 | if (!DA->Section) | 314 | if (!DA->Section) |
| 297 | return true; | 315 | continue; |
| 298 | auto *X = dyn_cast<InputSection>(DA->Section); | 316 | auto *X = dyn_cast<InputSection>(DA->Section); |
| 299 | if (!X) | 317 | if (!X) |
| 300 | return true; | 318 | continue; |
| 301 | auto *Y = cast<InputSection>(DB->Section); | 319 | auto *Y = cast<InputSection>(DB->Section); |
| 302 | 320 | ||
| 303 | // Ineligible sections are in the special equivalence class 0. | 321 | // Ineligible sections are in the special equivalence class 0. |
| 304 | // They can never be the same in terms of the equivalence class. | 322 | // They can never be the same in terms of the equivalence class. |
| 305 | if (X->Class[Current] == 0) | 323 | if (X->Class[Current] == 0) |
| 306 | return false; | 324 | return false; |
| 307 | 325 | if (X->Class[Current] != Y->Class[Current]) | |
| 308 | return X->Class[Current] == Y->Class[Current]; | 326 | return false; |
| 309 | }; | 327 | }; |
| 310 | 328 | ||
| 311 | return std::equal(RelsA.begin(), RelsA.end(), RelsB.begin(), Eq); | 329 | return true; |
| 312 | } | 330 | } |
| 313 | 331 | ||
| 314 | // Compare "moving" part of two InputSections, namely relocation targets. | 332 | // Compare "moving" part of two InputSections, namely relocation targets. |
| ... | @@ -353,7 +371,7 @@ template <class ELFT> | ... | @@ -353,7 +371,7 @@ template <class ELFT> |
| 353 | void ICF<ELFT>::forEachClass(std::function<void(size_t, size_t)> Fn) { | 371 | void ICF<ELFT>::forEachClass(std::function<void(size_t, size_t)> Fn) { |
| 354 | // If threading is disabled or the number of sections are | 372 | // If threading is disabled or the number of sections are |
| 355 | // too small to use threading, call Fn sequentially. | 373 | // too small to use threading, call Fn sequentially. |
| 356 | if (!Config->Threads || Sections.size() < 1024) { | 374 | if (!ThreadsEnabled || Sections.size() < 1024) { |
| 357 | forEachClassRange(0, Sections.size(), Fn); | 375 | forEachClassRange(0, Sections.size(), Fn); |
| 358 | ++Cnt; | 376 | ++Cnt; |
| 359 | return; | 377 | return; |
| ... | @@ -381,9 +399,10 @@ template <class ELFT> void ICF<ELFT>::run() { | ... | @@ -381,9 +399,10 @@ template <class ELFT> void ICF<ELFT>::run() { |
| 381 | Sections.push_back(S); | 399 | Sections.push_back(S); |
| 382 | 400 | ||
| 383 | // Initially, we use hash values to partition sections. | 401 | // Initially, we use hash values to partition sections. |
| 384 | for (InputSection *S : Sections) | 402 | parallelForEach(Sections, [&](InputSection *S) { |
| 385 | // Set MSB to 1 to avoid collisions with non-hash IDs. | 403 | // Set MSB to 1 to avoid collisions with non-hash IDs. |
| 386 | S->Class[0] = getHash<ELFT>(S) | (1 << 31); | 404 | S->Class[0] = getHash<ELFT>(S) | (1 << 31); |
| 405 | }); | ||
| 387 | 406 | ||
| 388 | // From now on, sections in Sections vector are ordered so that sections | 407 | // From now on, sections in Sections vector are ordered so that sections |
| 389 | // in the same equivalence class are consecutive in the vector. | 408 | // in the same equivalence class are consecutive in the vector. |
deps/lld/ELF/InputFiles.cpp+352-271| ... | @@ -8,13 +8,13 @@ | ... | @@ -8,13 +8,13 @@ |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "InputFiles.h" | 10 | #include "InputFiles.h" |
| 11 | #include "Error.h" | ||
| 12 | #include "InputSection.h" | 11 | #include "InputSection.h" |
| 13 | #include "LinkerScript.h" | 12 | #include "LinkerScript.h" |
| 14 | #include "Memory.h" | ||
| 15 | #include "SymbolTable.h" | 13 | #include "SymbolTable.h" |
| 16 | #include "Symbols.h" | 14 | #include "Symbols.h" |
| 17 | #include "SyntheticSections.h" | 15 | #include "SyntheticSections.h" |
| 16 | #include "lld/Common/ErrorHandler.h" | ||
| 17 | #include "lld/Common/Memory.h" | ||
| 18 | #include "llvm/ADT/STLExtras.h" | 18 | #include "llvm/ADT/STLExtras.h" |
| 19 | #include "llvm/CodeGen/Analysis.h" | 19 | #include "llvm/CodeGen/Analysis.h" |
| 20 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" | 20 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
| ... | @@ -23,6 +23,8 @@ | ... | @@ -23,6 +23,8 @@ |
| 23 | #include "llvm/LTO/LTO.h" | 23 | #include "llvm/LTO/LTO.h" |
| 24 | #include "llvm/MC/StringTableBuilder.h" | 24 | #include "llvm/MC/StringTableBuilder.h" |
| 25 | #include "llvm/Object/ELFObjectFile.h" | 25 | #include "llvm/Object/ELFObjectFile.h" |
| 26 | #include "llvm/Support/ARMAttributeParser.h" | ||
| 27 | #include "llvm/Support/ARMBuildAttributes.h" | ||
| 26 | #include "llvm/Support/Path.h" | 28 | #include "llvm/Support/Path.h" |
| 27 | #include "llvm/Support/TarWriter.h" | 29 | #include "llvm/Support/TarWriter.h" |
| 28 | #include "llvm/Support/raw_ostream.h" | 30 | #include "llvm/Support/raw_ostream.h" |
| ... | @@ -30,31 +32,29 @@ | ... | @@ -30,31 +32,29 @@ |
| 30 | using namespace llvm; | 32 | using namespace llvm; |
| 31 | using namespace llvm::ELF; | 33 | using namespace llvm::ELF; |
| 32 | using namespace llvm::object; | 34 | using namespace llvm::object; |
| 35 | using namespace llvm::sys; | ||
| 33 | using namespace llvm::sys::fs; | 36 | using namespace llvm::sys::fs; |
| 34 | 37 | ||
| 35 | using namespace lld; | 38 | using namespace lld; |
| 36 | using namespace lld::elf; | 39 | using namespace lld::elf; |
| 37 | 40 | ||
| 41 | std::vector<BinaryFile *> elf::BinaryFiles; | ||
| 42 | std::vector<BitcodeFile *> elf::BitcodeFiles; | ||
| 43 | std::vector<InputFile *> elf::ObjectFiles; | ||
| 44 | std::vector<InputFile *> elf::SharedFiles; | ||
| 45 | |||
| 38 | TarWriter *elf::Tar; | 46 | TarWriter *elf::Tar; |
| 39 | 47 | ||
| 40 | InputFile::InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} | 48 | InputFile::InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} |
| 41 | 49 | ||
| 42 | namespace { | ||
| 43 | // In ELF object file all section addresses are zero. If we have multiple | ||
| 44 | // .text sections (when using -ffunction-section or comdat group) then | ||
| 45 | // LLVM DWARF parser will not be able to parse .debug_line correctly, unless | ||
| 46 | // we assign each section some unique address. This callback method assigns | ||
| 47 | // each section an address equal to its offset in ELF object file. | ||
| 48 | class ObjectInfo : public LoadedObjectInfoHelper<ObjectInfo> { | ||
| 49 | public: | ||
| 50 | uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override { | ||
| 51 | return static_cast<const ELFSectionRef &>(Sec).getOffset(); | ||
| 52 | } | ||
| 53 | }; | ||
| 54 | } | ||
| 55 | |||
| 56 | Optional<MemoryBufferRef> elf::readFile(StringRef Path) { | 50 | Optional<MemoryBufferRef> elf::readFile(StringRef Path) { |
| 51 | // The --chroot option changes our virtual root directory. | ||
| 52 | // This is useful when you are dealing with files created by --reproduce. | ||
| 53 | if (!Config->Chroot.empty() && Path.startswith("/")) | ||
| 54 | Path = Saver.save(Config->Chroot + Path); | ||
| 55 | |||
| 57 | log(Path); | 56 | log(Path); |
| 57 | |||
| 58 | auto MBOrErr = MemoryBuffer::getFile(Path); | 58 | auto MBOrErr = MemoryBuffer::getFile(Path); |
| 59 | if (auto EC = MBOrErr.getError()) { | 59 | if (auto EC = MBOrErr.getError()) { |
| 60 | error("cannot open " + Path + ": " + EC.message()); | 60 | error("cannot open " + Path + ": " + EC.message()); |
| ... | @@ -70,28 +70,132 @@ Optional<MemoryBufferRef> elf::readFile(StringRef Path) { | ... | @@ -70,28 +70,132 @@ Optional<MemoryBufferRef> elf::readFile(StringRef Path) { |
| 70 | return MBRef; | 70 | return MBRef; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | template <class ELFT> void elf::ObjectFile<ELFT>::initializeDwarfLine() { | 73 | // Concatenates arguments to construct a string representing an error location. |
| 74 | std::unique_ptr<object::ObjectFile> Obj = | 74 | static std::string createFileLineMsg(StringRef Path, unsigned Line) { |
| 75 | check(object::ObjectFile::createObjectFile(this->MB), toString(this)); | 75 | std::string Filename = path::filename(Path); |
| 76 | std::string Lineno = ":" + std::to_string(Line); | ||
| 77 | if (Filename == Path) | ||
| 78 | return Filename + Lineno; | ||
| 79 | return Filename + Lineno + " (" + Path.str() + Lineno + ")"; | ||
| 80 | } | ||
| 76 | 81 | ||
| 77 | ObjectInfo ObjInfo; | 82 | template <class ELFT> |
| 78 | DWARFContextInMemory Dwarf(*Obj, &ObjInfo); | 83 | static std::string getSrcMsgAux(ObjFile<ELFT> &File, const Symbol &Sym, |
| 84 | InputSectionBase &Sec, uint64_t Offset) { | ||
| 85 | // In DWARF, functions and variables are stored to different places. | ||
| 86 | // First, lookup a function for a given offset. | ||
| 87 | if (Optional<DILineInfo> Info = File.getDILineInfo(&Sec, Offset)) | ||
| 88 | return createFileLineMsg(Info->FileName, Info->Line); | ||
| 89 | |||
| 90 | // If it failed, lookup again as a variable. | ||
| 91 | if (Optional<std::pair<std::string, unsigned>> FileLine = | ||
| 92 | File.getVariableLoc(Sym.getName())) | ||
| 93 | return createFileLineMsg(FileLine->first, FileLine->second); | ||
| 94 | |||
| 95 | // File.SourceFile contains STT_FILE symbol, and that is a last resort. | ||
| 96 | return File.SourceFile; | ||
| 97 | } | ||
| 98 | |||
| 99 | std::string InputFile::getSrcMsg(const Symbol &Sym, InputSectionBase &Sec, | ||
| 100 | uint64_t Offset) { | ||
| 101 | if (kind() != ObjKind) | ||
| 102 | return ""; | ||
| 103 | switch (Config->EKind) { | ||
| 104 | default: | ||
| 105 | llvm_unreachable("Invalid kind"); | ||
| 106 | case ELF32LEKind: | ||
| 107 | return getSrcMsgAux(cast<ObjFile<ELF32LE>>(*this), Sym, Sec, Offset); | ||
| 108 | case ELF32BEKind: | ||
| 109 | return getSrcMsgAux(cast<ObjFile<ELF32BE>>(*this), Sym, Sec, Offset); | ||
| 110 | case ELF64LEKind: | ||
| 111 | return getSrcMsgAux(cast<ObjFile<ELF64LE>>(*this), Sym, Sec, Offset); | ||
| 112 | case ELF64BEKind: | ||
| 113 | return getSrcMsgAux(cast<ObjFile<ELF64BE>>(*this), Sym, Sec, Offset); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | template <class ELFT> void ObjFile<ELFT>::initializeDwarf() { | ||
| 118 | DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(this)); | ||
| 119 | const DWARFObject &Obj = Dwarf.getDWARFObj(); | ||
| 79 | DwarfLine.reset(new DWARFDebugLine); | 120 | DwarfLine.reset(new DWARFDebugLine); |
| 80 | DWARFDataExtractor LineData(Dwarf.getLineSection(), Config->IsLE, | 121 | DWARFDataExtractor LineData(Obj, Obj.getLineSection(), Config->IsLE, |
| 81 | Config->Wordsize); | 122 | Config->Wordsize); |
| 82 | 123 | ||
| 83 | // The second parameter is offset in .debug_line section | 124 | // The second parameter is offset in .debug_line section |
| 84 | // for compilation unit (CU) of interest. We have only one | 125 | // for compilation unit (CU) of interest. We have only one |
| 85 | // CU (object file), so offset is always 0. | 126 | // CU (object file), so offset is always 0. |
| 86 | DwarfLine->getOrParseLineTable(LineData, 0); | 127 | // FIXME: Provide the associated DWARFUnit if there is one. DWARF v5 |
| 128 | // needs it in order to find indirect strings. | ||
| 129 | const DWARFDebugLine::LineTable *LT = | ||
| 130 | DwarfLine->getOrParseLineTable(LineData, 0, nullptr); | ||
| 131 | |||
| 132 | // Return if there is no debug information about CU available. | ||
| 133 | if (!Dwarf.getNumCompileUnits()) | ||
| 134 | return; | ||
| 135 | |||
| 136 | // Loop over variable records and insert them to VariableLoc. | ||
| 137 | DWARFCompileUnit *CU = Dwarf.getCompileUnitAtIndex(0); | ||
| 138 | for (const auto &Entry : CU->dies()) { | ||
| 139 | DWARFDie Die(CU, &Entry); | ||
| 140 | // Skip all tags that are not variables. | ||
| 141 | if (Die.getTag() != dwarf::DW_TAG_variable) | ||
| 142 | continue; | ||
| 143 | |||
| 144 | // Skip if a local variable because we don't need them for generating error | ||
| 145 | // messages. In general, only non-local symbols can fail to be linked. | ||
| 146 | if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0)) | ||
| 147 | continue; | ||
| 148 | |||
| 149 | // Get the source filename index for the variable. | ||
| 150 | unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0); | ||
| 151 | if (!LT->hasFileAtIndex(File)) | ||
| 152 | continue; | ||
| 153 | |||
| 154 | // Get the line number on which the variable is declared. | ||
| 155 | unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0); | ||
| 156 | |||
| 157 | // Get the name of the variable and add the collected information to | ||
| 158 | // VariableLoc. Usually Name is non-empty, but it can be empty if the input | ||
| 159 | // object file lacks some debug info. | ||
| 160 | StringRef Name = dwarf::toString(Die.find(dwarf::DW_AT_name), ""); | ||
| 161 | if (!Name.empty()) | ||
| 162 | VariableLoc.insert({Name, {File, Line}}); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | // Returns the pair of file name and line number describing location of data | ||
| 167 | // object (variable, array, etc) definition. | ||
| 168 | template <class ELFT> | ||
| 169 | Optional<std::pair<std::string, unsigned>> | ||
| 170 | ObjFile<ELFT>::getVariableLoc(StringRef Name) { | ||
| 171 | llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); }); | ||
| 172 | |||
| 173 | // There is always only one CU so it's offset is 0. | ||
| 174 | const DWARFDebugLine::LineTable *LT = DwarfLine->getLineTable(0); | ||
| 175 | if (!LT) | ||
| 176 | return None; | ||
| 177 | |||
| 178 | // Return if we have no debug information about data object. | ||
| 179 | auto It = VariableLoc.find(Name); | ||
| 180 | if (It == VariableLoc.end()) | ||
| 181 | return None; | ||
| 182 | |||
| 183 | // Take file name string from line table. | ||
| 184 | std::string FileName; | ||
| 185 | if (!LT->getFileNameByIndex( | ||
| 186 | It->second.first /* File */, nullptr, | ||
| 187 | DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName)) | ||
| 188 | return None; | ||
| 189 | |||
| 190 | return std::make_pair(FileName, It->second.second /*Line*/); | ||
| 87 | } | 191 | } |
| 88 | 192 | ||
| 89 | // Returns source line information for a given offset | 193 | // Returns source line information for a given offset |
| 90 | // using DWARF debug info. | 194 | // using DWARF debug info. |
| 91 | template <class ELFT> | 195 | template <class ELFT> |
| 92 | Optional<DILineInfo> elf::ObjectFile<ELFT>::getDILineInfo(InputSectionBase *S, | 196 | Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *S, |
| 93 | uint64_t Offset) { | 197 | uint64_t Offset) { |
| 94 | llvm::call_once(InitDwarfLine, [this]() { initializeDwarfLine(); }); | 198 | llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); }); |
| 95 | 199 | ||
| 96 | // The offset to CU is 0. | 200 | // The offset to CU is 0. |
| 97 | const DWARFDebugLine::LineTable *Tbl = DwarfLine->getLineTable(0); | 201 | const DWARFDebugLine::LineTable *Tbl = DwarfLine->getLineTable(0); |
| ... | @@ -112,8 +216,7 @@ Optional<DILineInfo> elf::ObjectFile<ELFT>::getDILineInfo(InputSectionBase *S, | ... | @@ -112,8 +216,7 @@ Optional<DILineInfo> elf::ObjectFile<ELFT>::getDILineInfo(InputSectionBase *S, |
| 112 | // Returns source line information for a given offset | 216 | // Returns source line information for a given offset |
| 113 | // using DWARF debug info. | 217 | // using DWARF debug info. |
| 114 | template <class ELFT> | 218 | template <class ELFT> |
| 115 | std::string elf::ObjectFile<ELFT>::getLineInfo(InputSectionBase *S, | 219 | std::string ObjFile<ELFT>::getLineInfo(InputSectionBase *S, uint64_t Offset) { |
| 116 | uint64_t Offset) { | ||
| 117 | if (Optional<DILineInfo> Info = getDILineInfo(S, Offset)) | 220 | if (Optional<DILineInfo> Info = getDILineInfo(S, Offset)) |
| 118 | return Info->FileName + ":" + std::to_string(Info->Line); | 221 | return Info->FileName + ":" + std::to_string(Info->Line); |
| 119 | return ""; | 222 | return ""; |
| ... | @@ -145,50 +248,41 @@ ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) { | ... | @@ -145,50 +248,41 @@ ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) { |
| 145 | } | 248 | } |
| 146 | 249 | ||
| 147 | template <class ELFT> | 250 | template <class ELFT> |
| 148 | typename ELFT::SymRange ELFFileBase<ELFT>::getGlobalSymbols() { | 251 | typename ELFT::SymRange ELFFileBase<ELFT>::getGlobalELFSyms() { |
| 149 | return makeArrayRef(Symbols.begin() + FirstNonLocal, Symbols.end()); | 252 | return makeArrayRef(ELFSyms.begin() + FirstNonLocal, ELFSyms.end()); |
| 150 | } | 253 | } |
| 151 | 254 | ||
| 152 | template <class ELFT> | 255 | template <class ELFT> |
| 153 | uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const { | 256 | uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const { |
| 154 | return check(getObj().getSectionIndex(&Sym, Symbols, SymtabSHNDX), | 257 | return CHECK(getObj().getSectionIndex(&Sym, ELFSyms, SymtabSHNDX), this); |
| 155 | toString(this)); | ||
| 156 | } | 258 | } |
| 157 | 259 | ||
| 158 | template <class ELFT> | 260 | template <class ELFT> |
| 159 | void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections, | 261 | void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections, |
| 160 | const Elf_Shdr *Symtab) { | 262 | const Elf_Shdr *Symtab) { |
| 161 | FirstNonLocal = Symtab->sh_info; | 263 | FirstNonLocal = Symtab->sh_info; |
| 162 | Symbols = check(getObj().symbols(Symtab), toString(this)); | 264 | ELFSyms = CHECK(getObj().symbols(Symtab), this); |
| 163 | if (FirstNonLocal == 0 || FirstNonLocal > Symbols.size()) | 265 | if (FirstNonLocal == 0 || FirstNonLocal > ELFSyms.size()) |
| 164 | fatal(toString(this) + ": invalid sh_info in symbol table"); | 266 | fatal(toString(this) + ": invalid sh_info in symbol table"); |
| 165 | 267 | ||
| 166 | StringTable = check(getObj().getStringTableForSymtab(*Symtab, Sections), | 268 | StringTable = |
| 167 | toString(this)); | 269 | CHECK(getObj().getStringTableForSymtab(*Symtab, Sections), this); |
| 168 | } | 270 | } |
| 169 | 271 | ||
| 170 | template <class ELFT> | 272 | template <class ELFT> |
| 171 | elf::ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M, StringRef ArchiveName) | 273 | ObjFile<ELFT>::ObjFile(MemoryBufferRef M, StringRef ArchiveName) |
| 172 | : ELFFileBase<ELFT>(Base::ObjectKind, M) { | 274 | : ELFFileBase<ELFT>(Base::ObjKind, M) { |
| 173 | this->ArchiveName = ArchiveName; | 275 | this->ArchiveName = ArchiveName; |
| 174 | } | 276 | } |
| 175 | 277 | ||
| 176 | template <class ELFT> | 278 | template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getLocalSymbols() { |
| 177 | ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getLocalSymbols() { | 279 | if (this->Symbols.empty()) |
| 178 | if (this->SymbolBodies.empty()) | 280 | return {}; |
| 179 | return this->SymbolBodies; | 281 | return makeArrayRef(this->Symbols).slice(1, this->FirstNonLocal - 1); |
| 180 | return makeArrayRef(this->SymbolBodies).slice(1, this->FirstNonLocal - 1); | ||
| 181 | } | ||
| 182 | |||
| 183 | template <class ELFT> | ||
| 184 | ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getSymbols() { | ||
| 185 | if (this->SymbolBodies.empty()) | ||
| 186 | return this->SymbolBodies; | ||
| 187 | return makeArrayRef(this->SymbolBodies).slice(1); | ||
| 188 | } | 282 | } |
| 189 | 283 | ||
| 190 | template <class ELFT> | 284 | template <class ELFT> |
| 191 | void elf::ObjectFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { | 285 | void ObjFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { |
| 192 | // Read section and symbol tables. | 286 | // Read section and symbol tables. |
| 193 | initializeSections(ComdatGroups); | 287 | initializeSections(ComdatGroups); |
| 194 | initializeSymbols(); | 288 | initializeSymbols(); |
| ... | @@ -198,19 +292,17 @@ void elf::ObjectFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { | ... | @@ -198,19 +292,17 @@ void elf::ObjectFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { |
| 198 | // They are identified and deduplicated by group name. This function | 292 | // They are identified and deduplicated by group name. This function |
| 199 | // returns a group name. | 293 | // returns a group name. |
| 200 | template <class ELFT> | 294 | template <class ELFT> |
| 201 | StringRef | 295 | StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, |
| 202 | elf::ObjectFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, | 296 | const Elf_Shdr &Sec) { |
| 203 | const Elf_Shdr &Sec) { | ||
| 204 | // Group signatures are stored as symbol names in object files. | 297 | // Group signatures are stored as symbol names in object files. |
| 205 | // sh_info contains a symbol index, so we fetch a symbol and read its name. | 298 | // sh_info contains a symbol index, so we fetch a symbol and read its name. |
| 206 | if (this->Symbols.empty()) | 299 | if (this->ELFSyms.empty()) |
| 207 | this->initSymtab( | 300 | this->initSymtab( |
| 208 | Sections, | 301 | Sections, CHECK(object::getSection<ELFT>(Sections, Sec.sh_link), this)); |
| 209 | check(object::getSection<ELFT>(Sections, Sec.sh_link), toString(this))); | ||
| 210 | 302 | ||
| 211 | const Elf_Sym *Sym = check( | 303 | const Elf_Sym *Sym = |
| 212 | object::getSymbol<ELFT>(this->Symbols, Sec.sh_info), toString(this)); | 304 | CHECK(object::getSymbol<ELFT>(this->ELFSyms, Sec.sh_info), this); |
| 213 | StringRef Signature = check(Sym->getName(this->StringTable), toString(this)); | 305 | StringRef Signature = CHECK(Sym->getName(this->StringTable), this); |
| 214 | 306 | ||
| 215 | // As a special case, if a symbol is a section symbol and has no name, | 307 | // As a special case, if a symbol is a section symbol and has no name, |
| 216 | // we use a section name as a signature. | 308 | // we use a section name as a signature. |
| ... | @@ -225,32 +317,22 @@ elf::ObjectFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, | ... | @@ -225,32 +317,22 @@ elf::ObjectFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, |
| 225 | } | 317 | } |
| 226 | 318 | ||
| 227 | template <class ELFT> | 319 | template <class ELFT> |
| 228 | ArrayRef<typename elf::ObjectFile<ELFT>::Elf_Word> | 320 | ArrayRef<typename ObjFile<ELFT>::Elf_Word> |
| 229 | elf::ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) { | 321 | ObjFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) { |
| 230 | const ELFFile<ELFT> &Obj = this->getObj(); | 322 | const ELFFile<ELFT> &Obj = this->getObj(); |
| 231 | ArrayRef<Elf_Word> Entries = check( | 323 | ArrayRef<Elf_Word> Entries = |
| 232 | Obj.template getSectionContentsAsArray<Elf_Word>(&Sec), toString(this)); | 324 | CHECK(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec), this); |
| 233 | if (Entries.empty() || Entries[0] != GRP_COMDAT) | 325 | if (Entries.empty() || Entries[0] != GRP_COMDAT) |
| 234 | fatal(toString(this) + ": unsupported SHT_GROUP format"); | 326 | fatal(toString(this) + ": unsupported SHT_GROUP format"); |
| 235 | return Entries.slice(1); | 327 | return Entries.slice(1); |
| 236 | } | 328 | } |
| 237 | 329 | ||
| 238 | template <class ELFT> | 330 | template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) { |
| 239 | bool elf::ObjectFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) { | ||
| 240 | // We don't merge sections if -O0 (default is -O1). This makes sometimes | 331 | // We don't merge sections if -O0 (default is -O1). This makes sometimes |
| 241 | // the linker significantly faster, although the output will be bigger. | 332 | // the linker significantly faster, although the output will be bigger. |
| 242 | if (Config->Optimize == 0) | 333 | if (Config->Optimize == 0) |
| 243 | return false; | 334 | return false; |
| 244 | 335 | ||
| 245 | // Do not merge sections if generating a relocatable object. It makes | ||
| 246 | // the code simpler because we do not need to update relocation addends | ||
| 247 | // to reflect changes introduced by merging. Instead of that we write | ||
| 248 | // such "merge" sections into separate OutputSections and keep SHF_MERGE | ||
| 249 | // / SHF_STRINGS flags and sh_entsize value to be able to perform merging | ||
| 250 | // later during a final linking. | ||
| 251 | if (Config->Relocatable) | ||
| 252 | return false; | ||
| 253 | |||
| 254 | // A mergeable section with size 0 is useless because they don't have | 336 | // A mergeable section with size 0 is useless because they don't have |
| 255 | // any data to merge. A mergeable string section with size 0 can be | 337 | // any data to merge. A mergeable string section with size 0 can be |
| 256 | // argued as invalid because it doesn't end with a null character. | 338 | // argued as invalid because it doesn't end with a null character. |
| ... | @@ -276,29 +358,19 @@ bool elf::ObjectFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) { | ... | @@ -276,29 +358,19 @@ bool elf::ObjectFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) { |
| 276 | if (Flags & SHF_WRITE) | 358 | if (Flags & SHF_WRITE) |
| 277 | fatal(toString(this) + ": writable SHF_MERGE section is not supported"); | 359 | fatal(toString(this) + ": writable SHF_MERGE section is not supported"); |
| 278 | 360 | ||
| 279 | // Don't try to merge if the alignment is larger than the sh_entsize and this | 361 | return true; |
| 280 | // is not SHF_STRINGS. | ||
| 281 | // | ||
| 282 | // Since this is not a SHF_STRINGS, we would need to pad after every entity. | ||
| 283 | // It would be equivalent for the producer of the .o to just set a larger | ||
| 284 | // sh_entsize. | ||
| 285 | if (Flags & SHF_STRINGS) | ||
| 286 | return true; | ||
| 287 | |||
| 288 | return Sec.sh_addralign <= EntSize; | ||
| 289 | } | 362 | } |
| 290 | 363 | ||
| 291 | template <class ELFT> | 364 | template <class ELFT> |
| 292 | void elf::ObjectFile<ELFT>::initializeSections( | 365 | void ObjFile<ELFT>::initializeSections( |
| 293 | DenseSet<CachedHashStringRef> &ComdatGroups) { | 366 | DenseSet<CachedHashStringRef> &ComdatGroups) { |
| 294 | const ELFFile<ELFT> &Obj = this->getObj(); | 367 | const ELFFile<ELFT> &Obj = this->getObj(); |
| 295 | 368 | ||
| 296 | ArrayRef<Elf_Shdr> ObjSections = | 369 | ArrayRef<Elf_Shdr> ObjSections = CHECK(this->getObj().sections(), this); |
| 297 | check(this->getObj().sections(), toString(this)); | ||
| 298 | uint64_t Size = ObjSections.size(); | 370 | uint64_t Size = ObjSections.size(); |
| 299 | this->Sections.resize(Size); | 371 | this->Sections.resize(Size); |
| 300 | this->SectionStringTable = | 372 | this->SectionStringTable = |
| 301 | check(Obj.getSectionStringTable(ObjSections), toString(this)); | 373 | CHECK(Obj.getSectionStringTable(ObjSections), this); |
| 302 | 374 | ||
| 303 | for (size_t I = 0, E = ObjSections.size(); I < E; I++) { | 375 | for (size_t I = 0, E = ObjSections.size(); I < E; I++) { |
| 304 | if (this->Sections[I] == &InputSection::Discarded) | 376 | if (this->Sections[I] == &InputSection::Discarded) |
| ... | @@ -344,8 +416,7 @@ void elf::ObjectFile<ELFT>::initializeSections( | ... | @@ -344,8 +416,7 @@ void elf::ObjectFile<ELFT>::initializeSections( |
| 344 | this->initSymtab(ObjSections, &Sec); | 416 | this->initSymtab(ObjSections, &Sec); |
| 345 | break; | 417 | break; |
| 346 | case SHT_SYMTAB_SHNDX: | 418 | case SHT_SYMTAB_SHNDX: |
| 347 | this->SymtabSHNDX = | 419 | this->SymtabSHNDX = CHECK(Obj.getSHNDXTable(Sec, ObjSections), this); |
| 348 | check(Obj.getSHNDXTable(Sec, ObjSections), toString(this)); | ||
| 349 | break; | 420 | break; |
| 350 | case SHT_STRTAB: | 421 | case SHT_STRTAB: |
| 351 | case SHT_NULL: | 422 | case SHT_NULL: |
| ... | @@ -358,16 +429,58 @@ void elf::ObjectFile<ELFT>::initializeSections( | ... | @@ -358,16 +429,58 @@ void elf::ObjectFile<ELFT>::initializeSections( |
| 358 | // have a SHF_LINK_ORDER dependency, this is identified by the sh_link. | 429 | // have a SHF_LINK_ORDER dependency, this is identified by the sh_link. |
| 359 | if (Sec.sh_flags & SHF_LINK_ORDER) { | 430 | if (Sec.sh_flags & SHF_LINK_ORDER) { |
| 360 | if (Sec.sh_link >= this->Sections.size()) | 431 | if (Sec.sh_link >= this->Sections.size()) |
| 361 | fatal(toString(this) + ": invalid sh_link index: " + | 432 | fatal(toString(this) + |
| 362 | Twine(Sec.sh_link)); | 433 | ": invalid sh_link index: " + Twine(Sec.sh_link)); |
| 363 | this->Sections[Sec.sh_link]->DependentSections.push_back( | 434 | this->Sections[Sec.sh_link]->DependentSections.push_back( |
| 364 | this->Sections[I]); | 435 | cast<InputSection>(this->Sections[I])); |
| 365 | } | 436 | } |
| 366 | } | 437 | } |
| 367 | } | 438 | } |
| 368 | 439 | ||
| 440 | // The ARM support in lld makes some use of instructions that are not available | ||
| 441 | // on all ARM architectures. Namely: | ||
| 442 | // - Use of BLX instruction for interworking between ARM and Thumb state. | ||
| 443 | // - Use of the extended Thumb branch encoding in relocation. | ||
| 444 | // - Use of the MOVT/MOVW instructions in Thumb Thunks. | ||
| 445 | // The ARM Attributes section contains information about the architecture chosen | ||
| 446 | // at compile time. We follow the convention that if at least one input object | ||
| 447 | // is compiled with an architecture that supports these features then lld is | ||
| 448 | // permitted to use them. | ||
| 449 | static void updateSupportedARMFeatures(const ARMAttributeParser &Attributes) { | ||
| 450 | if (!Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) | ||
| 451 | return; | ||
| 452 | auto Arch = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); | ||
| 453 | switch (Arch) { | ||
| 454 | case ARMBuildAttrs::Pre_v4: | ||
| 455 | case ARMBuildAttrs::v4: | ||
| 456 | case ARMBuildAttrs::v4T: | ||
| 457 | // Architectures prior to v5 do not support BLX instruction | ||
| 458 | break; | ||
| 459 | case ARMBuildAttrs::v5T: | ||
| 460 | case ARMBuildAttrs::v5TE: | ||
| 461 | case ARMBuildAttrs::v5TEJ: | ||
| 462 | case ARMBuildAttrs::v6: | ||
| 463 | case ARMBuildAttrs::v6KZ: | ||
| 464 | case ARMBuildAttrs::v6K: | ||
| 465 | Config->ARMHasBlx = true; | ||
| 466 | // Architectures used in pre-Cortex processors do not support | ||
| 467 | // The J1 = 1 J2 = 1 Thumb branch range extension, with the exception | ||
| 468 | // of Architecture v6T2 (arm1156t2-s and arm1156t2f-s) that do. | ||
| 469 | break; | ||
| 470 | default: | ||
| 471 | // All other Architectures have BLX and extended branch encoding | ||
| 472 | Config->ARMHasBlx = true; | ||
| 473 | Config->ARMJ1J2BranchEncoding = true; | ||
| 474 | if (Arch != ARMBuildAttrs::v6_M && Arch != ARMBuildAttrs::v6S_M) | ||
| 475 | // All Architectures used in Cortex processors with the exception | ||
| 476 | // of v6-M and v6S-M have the MOVT and MOVW instructions. | ||
| 477 | Config->ARMHasMovtMovw = true; | ||
| 478 | break; | ||
| 479 | } | ||
| 480 | } | ||
| 481 | |||
| 369 | template <class ELFT> | 482 | template <class ELFT> |
| 370 | InputSectionBase *elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) { | 483 | InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) { |
| 371 | uint32_t Idx = Sec.sh_info; | 484 | uint32_t Idx = Sec.sh_info; |
| 372 | if (Idx >= this->Sections.size()) | 485 | if (Idx >= this->Sections.size()) |
| 373 | fatal(toString(this) + ": invalid relocated section index: " + Twine(Idx)); | 486 | fatal(toString(this) + ": invalid relocated section index: " + Twine(Idx)); |
| ... | @@ -386,29 +499,32 @@ InputSectionBase *elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) { | ... | @@ -386,29 +499,32 @@ InputSectionBase *elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) { |
| 386 | 499 | ||
| 387 | // Create a regular InputSection class that has the same contents | 500 | // Create a regular InputSection class that has the same contents |
| 388 | // as a given section. | 501 | // as a given section. |
| 389 | InputSectionBase *toRegularSection(MergeInputSection *Sec) { | 502 | static InputSection *toRegularSection(MergeInputSection *Sec) { |
| 390 | auto *Ret = make<InputSection>(Sec->Flags, Sec->Type, Sec->Alignment, | 503 | return make<InputSection>(Sec->File, Sec->Flags, Sec->Type, Sec->Alignment, |
| 391 | Sec->Data, Sec->Name); | 504 | Sec->Data, Sec->Name); |
| 392 | Ret->File = Sec->File; | ||
| 393 | return Ret; | ||
| 394 | } | 505 | } |
| 395 | 506 | ||
| 396 | template <class ELFT> | 507 | template <class ELFT> |
| 397 | InputSectionBase * | 508 | InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 398 | elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { | ||
| 399 | StringRef Name = getSectionName(Sec); | 509 | StringRef Name = getSectionName(Sec); |
| 400 | 510 | ||
| 401 | switch (Sec.sh_type) { | 511 | switch (Sec.sh_type) { |
| 402 | case SHT_ARM_ATTRIBUTES: | 512 | case SHT_ARM_ATTRIBUTES: { |
| 403 | // FIXME: ARM meta-data section. Retain the first attribute section | 513 | if (Config->EMachine != EM_ARM) |
| 404 | // we see. The eglibc ARM dynamic loaders require the presence of an | 514 | break; |
| 405 | // attribute section for dlopen to work. | 515 | ARMAttributeParser Attributes; |
| 406 | // In a full implementation we would merge all attribute sections. | 516 | ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec)); |
| 517 | Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind); | ||
| 518 | updateSupportedARMFeatures(Attributes); | ||
| 519 | // FIXME: Retain the first attribute section we see. The eglibc ARM | ||
| 520 | // dynamic loaders require the presence of an attribute section for dlopen | ||
| 521 | // to work. In a full implementation we would merge all attribute sections. | ||
| 407 | if (InX::ARMAttributes == nullptr) { | 522 | if (InX::ARMAttributes == nullptr) { |
| 408 | InX::ARMAttributes = make<InputSection>(this, &Sec, Name); | 523 | InX::ARMAttributes = make<InputSection>(*this, Sec, Name); |
| 409 | return InX::ARMAttributes; | 524 | return InX::ARMAttributes; |
| 410 | } | 525 | } |
| 411 | return &InputSection::Discarded; | 526 | return &InputSection::Discarded; |
| 527 | } | ||
| 412 | case SHT_RELA: | 528 | case SHT_RELA: |
| 413 | case SHT_REL: { | 529 | case SHT_REL: { |
| 414 | // Find the relocation target section and associate this | 530 | // Find the relocation target section and associate this |
| ... | @@ -423,7 +539,7 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { | ... | @@ -423,7 +539,7 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 423 | // If -r is given, we do not interpret or apply relocation | 539 | // If -r is given, we do not interpret or apply relocation |
| 424 | // but just copy relocation sections to output. | 540 | // but just copy relocation sections to output. |
| 425 | if (Config->Relocatable) | 541 | if (Config->Relocatable) |
| 426 | return make<InputSection>(this, &Sec, Name); | 542 | return make<InputSection>(*this, Sec, Name); |
| 427 | 543 | ||
| 428 | if (Target->FirstRelocation) | 544 | if (Target->FirstRelocation) |
| 429 | fatal(toString(this) + | 545 | fatal(toString(this) + |
| ... | @@ -443,13 +559,12 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { | ... | @@ -443,13 +559,12 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 443 | 559 | ||
| 444 | size_t NumRelocations; | 560 | size_t NumRelocations; |
| 445 | if (Sec.sh_type == SHT_RELA) { | 561 | if (Sec.sh_type == SHT_RELA) { |
| 446 | ArrayRef<Elf_Rela> Rels = | 562 | ArrayRef<Elf_Rela> Rels = CHECK(this->getObj().relas(&Sec), this); |
| 447 | check(this->getObj().relas(&Sec), toString(this)); | ||
| 448 | Target->FirstRelocation = Rels.begin(); | 563 | Target->FirstRelocation = Rels.begin(); |
| 449 | NumRelocations = Rels.size(); | 564 | NumRelocations = Rels.size(); |
| 450 | Target->AreRelocsRela = true; | 565 | Target->AreRelocsRela = true; |
| 451 | } else { | 566 | } else { |
| 452 | ArrayRef<Elf_Rel> Rels = check(this->getObj().rels(&Sec), toString(this)); | 567 | ArrayRef<Elf_Rel> Rels = CHECK(this->getObj().rels(&Sec), this); |
| 453 | Target->FirstRelocation = Rels.begin(); | 568 | Target->FirstRelocation = Rels.begin(); |
| 454 | NumRelocations = Rels.size(); | 569 | NumRelocations = Rels.size(); |
| 455 | Target->AreRelocsRela = false; | 570 | Target->AreRelocsRela = false; |
| ... | @@ -462,7 +577,7 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { | ... | @@ -462,7 +577,7 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 462 | // However, if -emit-relocs is given, we need to leave them in the output. | 577 | // However, if -emit-relocs is given, we need to leave them in the output. |
| 463 | // (Some post link analysis tools need this information.) | 578 | // (Some post link analysis tools need this information.) |
| 464 | if (Config->EmitRelocs) { | 579 | if (Config->EmitRelocs) { |
| 465 | InputSection *RelocSec = make<InputSection>(this, &Sec, Name); | 580 | InputSection *RelocSec = make<InputSection>(*this, Sec, Name); |
| 466 | // We will not emit relocation section if target was discarded. | 581 | // We will not emit relocation section if target was discarded. |
| 467 | Target->DependentSections.push_back(RelocSec); | 582 | Target->DependentSections.push_back(RelocSec); |
| 468 | return RelocSec; | 583 | return RelocSec; |
| ... | @@ -497,18 +612,6 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { | ... | @@ -497,18 +612,6 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 497 | return &InputSection::Discarded; | 612 | return &InputSection::Discarded; |
| 498 | } | 613 | } |
| 499 | 614 | ||
| 500 | if (Config->Strip != StripPolicy::None && Name.startswith(".debug")) | ||
| 501 | return &InputSection::Discarded; | ||
| 502 | |||
| 503 | // If -gdb-index is given, LLD creates .gdb_index section, and that | ||
| 504 | // section serves the same purpose as .debug_gnu_pub{names,types} sections. | ||
| 505 | // If that's the case, we want to eliminate .debug_gnu_pub{names,types} | ||
| 506 | // because they are redundant and can waste large amount of disk space | ||
| 507 | // (for example, they are about 400 MiB in total for a clang debug build.) | ||
| 508 | if (Config->GdbIndex && | ||
| 509 | (Name == ".debug_gnu_pubnames" || Name == ".debug_gnu_pubtypes")) | ||
| 510 | return &InputSection::Discarded; | ||
| 511 | |||
| 512 | // The linkonce feature is a sort of proto-comdat. Some glibc i386 object | 615 | // The linkonce feature is a sort of proto-comdat. Some glibc i386 object |
| 513 | // files contain definitions of symbol "__x86.get_pc_thunk.bx" in linkonce | 616 | // files contain definitions of symbol "__x86.get_pc_thunk.bx" in linkonce |
| 514 | // sections. Drop those sections to avoid duplicate symbol errors. | 617 | // sections. Drop those sections to avoid duplicate symbol errors. |
| ... | @@ -521,54 +624,32 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { | ... | @@ -521,54 +624,32 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 521 | // .eh_frame_hdr section for runtime. So we handle them with a special | 624 | // .eh_frame_hdr section for runtime. So we handle them with a special |
| 522 | // class. For relocatable outputs, they are just passed through. | 625 | // class. For relocatable outputs, they are just passed through. |
| 523 | if (Name == ".eh_frame" && !Config->Relocatable) | 626 | if (Name == ".eh_frame" && !Config->Relocatable) |
| 524 | return make<EhInputSection>(this, &Sec, Name); | 627 | return make<EhInputSection>(*this, Sec, Name); |
| 525 | 628 | ||
| 526 | if (shouldMerge(Sec)) | 629 | if (shouldMerge(Sec)) |
| 527 | return make<MergeInputSection>(this, &Sec, Name); | 630 | return make<MergeInputSection>(*this, Sec, Name); |
| 528 | return make<InputSection>(this, &Sec, Name); | 631 | return make<InputSection>(*this, Sec, Name); |
| 529 | } | 632 | } |
| 530 | 633 | ||
| 531 | template <class ELFT> | 634 | template <class ELFT> |
| 532 | StringRef elf::ObjectFile<ELFT>::getSectionName(const Elf_Shdr &Sec) { | 635 | StringRef ObjFile<ELFT>::getSectionName(const Elf_Shdr &Sec) { |
| 533 | return check(this->getObj().getSectionName(&Sec, SectionStringTable), | 636 | return CHECK(this->getObj().getSectionName(&Sec, SectionStringTable), this); |
| 534 | toString(this)); | ||
| 535 | } | 637 | } |
| 536 | 638 | ||
| 537 | template <class ELFT> void elf::ObjectFile<ELFT>::initializeSymbols() { | 639 | template <class ELFT> void ObjFile<ELFT>::initializeSymbols() { |
| 538 | SymbolBodies.reserve(this->Symbols.size()); | 640 | this->Symbols.reserve(this->ELFSyms.size()); |
| 539 | for (const Elf_Sym &Sym : this->Symbols) | 641 | for (const Elf_Sym &Sym : this->ELFSyms) |
| 540 | SymbolBodies.push_back(createSymbolBody(&Sym)); | 642 | this->Symbols.push_back(createSymbol(&Sym)); |
| 541 | } | 643 | } |
| 542 | 644 | ||
| 543 | template <class ELFT> | 645 | template <class ELFT> Symbol *ObjFile<ELFT>::createSymbol(const Elf_Sym *Sym) { |
| 544 | InputSectionBase *elf::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const { | ||
| 545 | uint32_t Index = this->getSectionIndex(Sym); | ||
| 546 | if (Index >= this->Sections.size()) | ||
| 547 | fatal(toString(this) + ": invalid section index: " + Twine(Index)); | ||
| 548 | InputSectionBase *S = this->Sections[Index]; | ||
| 549 | |||
| 550 | // We found that GNU assembler 2.17.50 [FreeBSD] 2007-07-03 could | ||
| 551 | // generate broken objects. STT_SECTION/STT_NOTYPE symbols can be | ||
| 552 | // associated with SHT_REL[A]/SHT_SYMTAB/SHT_STRTAB sections. | ||
| 553 | // In this case it is fine for section to be null here as we do not | ||
| 554 | // allocate sections of these types. | ||
| 555 | if (!S) { | ||
| 556 | if (Index == 0 || Sym.getType() == STT_SECTION || | ||
| 557 | Sym.getType() == STT_NOTYPE) | ||
| 558 | return nullptr; | ||
| 559 | fatal(toString(this) + ": invalid section index: " + Twine(Index)); | ||
| 560 | } | ||
| 561 | |||
| 562 | if (S == &InputSection::Discarded) | ||
| 563 | return S; | ||
| 564 | return S->Repl; | ||
| 565 | } | ||
| 566 | |||
| 567 | template <class ELFT> | ||
| 568 | SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) { | ||
| 569 | int Binding = Sym->getBinding(); | 646 | int Binding = Sym->getBinding(); |
| 570 | InputSectionBase *Sec = getSection(*Sym); | ||
| 571 | 647 | ||
| 648 | uint32_t SecIdx = this->getSectionIndex(*Sym); | ||
| 649 | if (SecIdx >= this->Sections.size()) | ||
| 650 | fatal(toString(this) + ": invalid section index: " + Twine(SecIdx)); | ||
| 651 | |||
| 652 | InputSectionBase *Sec = this->Sections[SecIdx]; | ||
| 572 | uint8_t StOther = Sym->st_other; | 653 | uint8_t StOther = Sym->st_other; |
| 573 | uint8_t Type = Sym->getType(); | 654 | uint8_t Type = Sym->getType(); |
| 574 | uint64_t Value = Sym->st_value; | 655 | uint64_t Value = Sym->st_value; |
| ... | @@ -576,34 +657,29 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) { | ... | @@ -576,34 +657,29 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) { |
| 576 | 657 | ||
| 577 | if (Binding == STB_LOCAL) { | 658 | if (Binding == STB_LOCAL) { |
| 578 | if (Sym->getType() == STT_FILE) | 659 | if (Sym->getType() == STT_FILE) |
| 579 | SourceFile = check(Sym->getName(this->StringTable), toString(this)); | 660 | SourceFile = CHECK(Sym->getName(this->StringTable), this); |
| 580 | 661 | ||
| 581 | if (this->StringTable.size() <= Sym->st_name) | 662 | if (this->StringTable.size() <= Sym->st_name) |
| 582 | fatal(toString(this) + ": invalid symbol name offset"); | 663 | fatal(toString(this) + ": invalid symbol name offset"); |
| 583 | 664 | ||
| 584 | StringRefZ Name = this->StringTable.data() + Sym->st_name; | 665 | StringRefZ Name = this->StringTable.data() + Sym->st_name; |
| 585 | if (Sym->st_shndx == SHN_UNDEF) | 666 | if (Sym->st_shndx == SHN_UNDEF) |
| 586 | return make<Undefined>(Name, /*IsLocal=*/true, StOther, Type, this); | 667 | return make<Undefined>(this, Name, Binding, StOther, Type); |
| 587 | 668 | ||
| 588 | return make<DefinedRegular>(Name, /*IsLocal=*/true, StOther, Type, Value, | 669 | return make<Defined>(this, Name, Binding, StOther, Type, Value, Size, Sec); |
| 589 | Size, Sec, this); | ||
| 590 | } | 670 | } |
| 591 | 671 | ||
| 592 | StringRef Name = check(Sym->getName(this->StringTable), toString(this)); | 672 | StringRef Name = CHECK(Sym->getName(this->StringTable), this); |
| 593 | 673 | ||
| 594 | switch (Sym->st_shndx) { | 674 | switch (Sym->st_shndx) { |
| 595 | case SHN_UNDEF: | 675 | case SHN_UNDEF: |
| 596 | return elf::Symtab<ELFT>::X | 676 | return Symtab->addUndefined<ELFT>(Name, Binding, StOther, Type, |
| 597 | ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, | 677 | /*CanOmitFromDynSym=*/false, this); |
| 598 | /*CanOmitFromDynSym=*/false, this) | ||
| 599 | ->body(); | ||
| 600 | case SHN_COMMON: | 678 | case SHN_COMMON: |
| 601 | if (Value == 0 || Value >= UINT32_MAX) | 679 | if (Value == 0 || Value >= UINT32_MAX) |
| 602 | fatal(toString(this) + ": common symbol '" + Name + | 680 | fatal(toString(this) + ": common symbol '" + Name + |
| 603 | "' has invalid alignment: " + Twine(Value)); | 681 | "' has invalid alignment: " + Twine(Value)); |
| 604 | return elf::Symtab<ELFT>::X | 682 | return Symtab->addCommon(Name, Size, Value, Binding, StOther, Type, *this); |
| 605 | ->addCommon(Name, Size, Value, Binding, StOther, Type, this) | ||
| 606 | ->body(); | ||
| 607 | } | 683 | } |
| 608 | 684 | ||
| 609 | switch (Binding) { | 685 | switch (Binding) { |
| ... | @@ -613,13 +689,10 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) { | ... | @@ -613,13 +689,10 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) { |
| 613 | case STB_WEAK: | 689 | case STB_WEAK: |
| 614 | case STB_GNU_UNIQUE: | 690 | case STB_GNU_UNIQUE: |
| 615 | if (Sec == &InputSection::Discarded) | 691 | if (Sec == &InputSection::Discarded) |
| 616 | return elf::Symtab<ELFT>::X | 692 | return Symtab->addUndefined<ELFT>(Name, Binding, StOther, Type, |
| 617 | ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, | 693 | /*CanOmitFromDynSym=*/false, this); |
| 618 | /*CanOmitFromDynSym=*/false, this) | 694 | return Symtab->addRegular(Name, StOther, Type, Value, Size, Binding, Sec, |
| 619 | ->body(); | 695 | this); |
| 620 | return elf::Symtab<ELFT>::X | ||
| 621 | ->addRegular(Name, StOther, Type, Value, Size, Binding, Sec, this) | ||
| 622 | ->body(); | ||
| 623 | } | 696 | } |
| 624 | } | 697 | } |
| 625 | 698 | ||
| ... | @@ -630,14 +703,14 @@ ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File) | ... | @@ -630,14 +703,14 @@ ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File) |
| 630 | template <class ELFT> void ArchiveFile::parse() { | 703 | template <class ELFT> void ArchiveFile::parse() { |
| 631 | Symbols.reserve(File->getNumberOfSymbols()); | 704 | Symbols.reserve(File->getNumberOfSymbols()); |
| 632 | for (const Archive::Symbol &Sym : File->symbols()) | 705 | for (const Archive::Symbol &Sym : File->symbols()) |
| 633 | Symbols.push_back(Symtab<ELFT>::X->addLazyArchive(this, Sym)); | 706 | Symbols.push_back(Symtab->addLazyArchive<ELFT>(Sym.getName(), *this, Sym)); |
| 634 | } | 707 | } |
| 635 | 708 | ||
| 636 | // Returns a buffer pointing to a member file containing a given symbol. | 709 | // Returns a buffer pointing to a member file containing a given symbol. |
| 637 | std::pair<MemoryBufferRef, uint64_t> | 710 | std::pair<MemoryBufferRef, uint64_t> |
| 638 | ArchiveFile::getMember(const Archive::Symbol *Sym) { | 711 | ArchiveFile::getMember(const Archive::Symbol *Sym) { |
| 639 | Archive::Child C = | 712 | Archive::Child C = |
| 640 | check(Sym->getMember(), toString(this) + | 713 | CHECK(Sym->getMember(), toString(this) + |
| 641 | ": could not get the member for symbol " + | 714 | ": could not get the member for symbol " + |
| 642 | Sym->getName()); | 715 | Sym->getName()); |
| 643 | 716 | ||
| ... | @@ -645,14 +718,13 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) { | ... | @@ -645,14 +718,13 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) { |
| 645 | return {MemoryBufferRef(), 0}; | 718 | return {MemoryBufferRef(), 0}; |
| 646 | 719 | ||
| 647 | MemoryBufferRef Ret = | 720 | MemoryBufferRef Ret = |
| 648 | check(C.getMemoryBufferRef(), | 721 | CHECK(C.getMemoryBufferRef(), |
| 649 | toString(this) + | 722 | toString(this) + |
| 650 | ": could not get the buffer for the member defining symbol " + | 723 | ": could not get the buffer for the member defining symbol " + |
| 651 | Sym->getName()); | 724 | Sym->getName()); |
| 652 | 725 | ||
| 653 | if (C.getParent()->isThin() && Tar) | 726 | if (C.getParent()->isThin() && Tar) |
| 654 | Tar->append(relativeToRoot(check(C.getFullName(), toString(this))), | 727 | Tar->append(relativeToRoot(CHECK(C.getFullName(), this)), Ret.getBuffer()); |
| 655 | Ret.getBuffer()); | ||
| 656 | if (C.getParent()->isThin()) | 728 | if (C.getParent()->isThin()) |
| 657 | return {Ret, 0}; | 729 | return {Ret, 0}; |
| 658 | return {Ret, C.getChildOffset()}; | 730 | return {Ret, C.getChildOffset()}; |
| ... | @@ -661,22 +733,14 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) { | ... | @@ -661,22 +733,14 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) { |
| 661 | template <class ELFT> | 733 | template <class ELFT> |
| 662 | SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) | 734 | SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) |
| 663 | : ELFFileBase<ELFT>(Base::SharedKind, M), SoName(DefaultSoName), | 735 | : ELFFileBase<ELFT>(Base::SharedKind, M), SoName(DefaultSoName), |
| 664 | AsNeeded(Config->AsNeeded) {} | 736 | IsNeeded(!Config->AsNeeded) {} |
| 665 | |||
| 666 | template <class ELFT> | ||
| 667 | const typename ELFT::Shdr * | ||
| 668 | SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const { | ||
| 669 | return check( | ||
| 670 | this->getObj().getSection(&Sym, this->Symbols, this->SymtabSHNDX), | ||
| 671 | toString(this)); | ||
| 672 | } | ||
| 673 | 737 | ||
| 674 | // Partially parse the shared object file so that we can call | 738 | // Partially parse the shared object file so that we can call |
| 675 | // getSoName on this object. | 739 | // getSoName on this object. |
| 676 | template <class ELFT> void SharedFile<ELFT>::parseSoName() { | 740 | template <class ELFT> void SharedFile<ELFT>::parseSoName() { |
| 677 | const Elf_Shdr *DynamicSec = nullptr; | 741 | const Elf_Shdr *DynamicSec = nullptr; |
| 678 | const ELFFile<ELFT> Obj = this->getObj(); | 742 | const ELFFile<ELFT> Obj = this->getObj(); |
| 679 | ArrayRef<Elf_Shdr> Sections = check(Obj.sections(), toString(this)); | 743 | ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this); |
| 680 | 744 | ||
| 681 | // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d. | 745 | // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d. |
| 682 | for (const Elf_Shdr &Sec : Sections) { | 746 | for (const Elf_Shdr &Sec : Sections) { |
| ... | @@ -690,8 +754,7 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() { | ... | @@ -690,8 +754,7 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() { |
| 690 | DynamicSec = &Sec; | 754 | DynamicSec = &Sec; |
| 691 | break; | 755 | break; |
| 692 | case SHT_SYMTAB_SHNDX: | 756 | case SHT_SYMTAB_SHNDX: |
| 693 | this->SymtabSHNDX = | 757 | this->SymtabSHNDX = CHECK(Obj.getSHNDXTable(Sec, Sections), this); |
| 694 | check(Obj.getSHNDXTable(Sec, Sections), toString(this)); | ||
| 695 | break; | 758 | break; |
| 696 | case SHT_GNU_versym: | 759 | case SHT_GNU_versym: |
| 697 | this->VersymSec = &Sec; | 760 | this->VersymSec = &Sec; |
| ... | @@ -702,15 +765,14 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() { | ... | @@ -702,15 +765,14 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() { |
| 702 | } | 765 | } |
| 703 | } | 766 | } |
| 704 | 767 | ||
| 705 | if (this->VersymSec && this->Symbols.empty()) | 768 | if (this->VersymSec && this->ELFSyms.empty()) |
| 706 | error("SHT_GNU_versym should be associated with symbol table"); | 769 | error("SHT_GNU_versym should be associated with symbol table"); |
| 707 | 770 | ||
| 708 | // Search for a DT_SONAME tag to initialize this->SoName. | 771 | // Search for a DT_SONAME tag to initialize this->SoName. |
| 709 | if (!DynamicSec) | 772 | if (!DynamicSec) |
| 710 | return; | 773 | return; |
| 711 | ArrayRef<Elf_Dyn> Arr = | 774 | ArrayRef<Elf_Dyn> Arr = |
| 712 | check(Obj.template getSectionContentsAsArray<Elf_Dyn>(DynamicSec), | 775 | CHECK(Obj.template getSectionContentsAsArray<Elf_Dyn>(DynamicSec), this); |
| 713 | toString(this)); | ||
| 714 | for (const Elf_Dyn &Dyn : Arr) { | 776 | for (const Elf_Dyn &Dyn : Arr) { |
| 715 | if (Dyn.d_tag == DT_SONAME) { | 777 | if (Dyn.d_tag == DT_SONAME) { |
| 716 | uint64_t Val = Dyn.getVal(); | 778 | uint64_t Val = Dyn.getVal(); |
| ... | @@ -767,11 +829,14 @@ SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) { | ... | @@ -767,11 +829,14 @@ SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) { |
| 767 | template <class ELFT> void SharedFile<ELFT>::parseRest() { | 829 | template <class ELFT> void SharedFile<ELFT>::parseRest() { |
| 768 | // Create mapping from version identifiers to Elf_Verdef entries. | 830 | // Create mapping from version identifiers to Elf_Verdef entries. |
| 769 | const Elf_Versym *Versym = nullptr; | 831 | const Elf_Versym *Versym = nullptr; |
| 770 | std::vector<const Elf_Verdef *> Verdefs = parseVerdefs(Versym); | 832 | Verdefs = parseVerdefs(Versym); |
| 833 | |||
| 834 | ArrayRef<Elf_Shdr> Sections = CHECK(this->getObj().sections(), this); | ||
| 771 | 835 | ||
| 772 | Elf_Sym_Range Syms = this->getGlobalSymbols(); | 836 | // Add symbols to the symbol table. |
| 837 | Elf_Sym_Range Syms = this->getGlobalELFSyms(); | ||
| 773 | for (const Elf_Sym &Sym : Syms) { | 838 | for (const Elf_Sym &Sym : Syms) { |
| 774 | unsigned VersymIndex = 0; | 839 | unsigned VersymIndex = VER_NDX_GLOBAL; |
| 775 | if (Versym) { | 840 | if (Versym) { |
| 776 | VersymIndex = Versym->vs_index; | 841 | VersymIndex = Versym->vs_index; |
| 777 | ++Versym; | 842 | ++Versym; |
| ... | @@ -779,28 +844,54 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() { | ... | @@ -779,28 +844,54 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() { |
| 779 | bool Hidden = VersymIndex & VERSYM_HIDDEN; | 844 | bool Hidden = VersymIndex & VERSYM_HIDDEN; |
| 780 | VersymIndex = VersymIndex & ~VERSYM_HIDDEN; | 845 | VersymIndex = VersymIndex & ~VERSYM_HIDDEN; |
| 781 | 846 | ||
| 782 | StringRef Name = check(Sym.getName(this->StringTable), toString(this)); | 847 | StringRef Name = CHECK(Sym.getName(this->StringTable), this); |
| 783 | if (Sym.isUndefined()) { | 848 | if (Sym.isUndefined()) { |
| 784 | Undefs.push_back(Name); | 849 | Undefs.push_back(Name); |
| 785 | continue; | 850 | continue; |
| 786 | } | 851 | } |
| 787 | 852 | ||
| 788 | // Ignore local symbols. | 853 | if (Sym.getBinding() == STB_LOCAL) { |
| 789 | if (Versym && VersymIndex == VER_NDX_LOCAL) | 854 | warn("found local symbol '" + Name + |
| 855 | "' in global part of symbol table in file " + toString(this)); | ||
| 790 | continue; | 856 | continue; |
| 857 | } | ||
| 858 | |||
| 859 | const Elf_Verdef *Ver = nullptr; | ||
| 860 | if (VersymIndex != VER_NDX_GLOBAL) { | ||
| 861 | if (VersymIndex >= Verdefs.size() || VersymIndex == VER_NDX_LOCAL) { | ||
| 862 | error("corrupt input file: version definition index " + | ||
| 863 | Twine(VersymIndex) + " for symbol " + Name + | ||
| 864 | " is out of bounds\n>>> defined in " + toString(this)); | ||
| 865 | continue; | ||
| 866 | } | ||
| 867 | Ver = Verdefs[VersymIndex]; | ||
| 868 | } else { | ||
| 869 | VersymIndex = 0; | ||
| 870 | } | ||
| 791 | 871 | ||
| 792 | const Elf_Verdef *V = | 872 | // We do not usually care about alignments of data in shared object |
| 793 | VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex]; | 873 | // files because the loader takes care of it. However, if we promote a |
| 874 | // DSO symbol to point to .bss due to copy relocation, we need to keep | ||
| 875 | // the original alignment requirements. We infer it here. | ||
| 876 | uint64_t Alignment = 1; | ||
| 877 | if (Sym.st_value) | ||
| 878 | Alignment = 1ULL << countTrailingZeros((uint64_t)Sym.st_value); | ||
| 879 | if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) { | ||
| 880 | uint64_t SecAlign = Sections[Sym.st_shndx].sh_addralign; | ||
| 881 | Alignment = std::min(Alignment, SecAlign); | ||
| 882 | } | ||
| 883 | if (Alignment > UINT32_MAX) | ||
| 884 | error(toString(this) + ": alignment too large: " + Name); | ||
| 794 | 885 | ||
| 795 | if (!Hidden) | 886 | if (!Hidden) |
| 796 | elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V); | 887 | Symtab->addShared(Name, *this, Sym, Alignment, VersymIndex); |
| 797 | 888 | ||
| 798 | // Also add the symbol with the versioned name to handle undefined symbols | 889 | // Also add the symbol with the versioned name to handle undefined symbols |
| 799 | // with explicit versions. | 890 | // with explicit versions. |
| 800 | if (V) { | 891 | if (Ver) { |
| 801 | StringRef VerName = this->StringTable.data() + V->getAux()->vda_name; | 892 | StringRef VerName = this->StringTable.data() + Ver->getAux()->vda_name; |
| 802 | Name = Saver.save(Name + "@" + VerName); | 893 | Name = Saver.save(Name + "@" + VerName); |
| 803 | elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V); | 894 | Symtab->addShared(Name, *this, Sym, Alignment, VersymIndex); |
| 804 | } | 895 | } |
| 805 | } | 896 | } |
| 806 | } | 897 | } |
| ... | @@ -855,7 +946,7 @@ BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName, | ... | @@ -855,7 +946,7 @@ BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName, |
| 855 | MemoryBufferRef MBRef(MB.getBuffer(), | 946 | MemoryBufferRef MBRef(MB.getBuffer(), |
| 856 | Saver.save(ArchiveName + MB.getBufferIdentifier() + | 947 | Saver.save(ArchiveName + MB.getBufferIdentifier() + |
| 857 | utostr(OffsetInArchive))); | 948 | utostr(OffsetInArchive))); |
| 858 | Obj = check(lto::InputFile::create(MBRef), toString(this)); | 949 | Obj = CHECK(lto::InputFile::create(MBRef), this); |
| 859 | 950 | ||
| 860 | Triple T(Obj->getTargetTriple()); | 951 | Triple T(Obj->getTargetTriple()); |
| 861 | EKind = getBitcodeELFKind(T); | 952 | EKind = getBitcodeELFKind(T); |
| ... | @@ -877,7 +968,7 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) { | ... | @@ -877,7 +968,7 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) { |
| 877 | template <class ELFT> | 968 | template <class ELFT> |
| 878 | static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats, | 969 | static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats, |
| 879 | const lto::InputFile::Symbol &ObjSym, | 970 | const lto::InputFile::Symbol &ObjSym, |
| 880 | BitcodeFile *F) { | 971 | BitcodeFile &F) { |
| 881 | StringRef NameRef = Saver.save(ObjSym.getName()); | 972 | StringRef NameRef = Saver.save(ObjSym.getName()); |
| 882 | uint32_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL; | 973 | uint32_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL; |
| 883 | 974 | ||
| ... | @@ -887,22 +978,20 @@ static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats, | ... | @@ -887,22 +978,20 @@ static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats, |
| 887 | 978 | ||
| 888 | int C = ObjSym.getComdatIndex(); | 979 | int C = ObjSym.getComdatIndex(); |
| 889 | if (C != -1 && !KeptComdats[C]) | 980 | if (C != -1 && !KeptComdats[C]) |
| 890 | return Symtab<ELFT>::X->addUndefined(NameRef, /*IsLocal=*/false, Binding, | 981 | return Symtab->addUndefined<ELFT>(NameRef, Binding, Visibility, Type, |
| 891 | Visibility, Type, CanOmitFromDynSym, | 982 | CanOmitFromDynSym, &F); |
| 892 | F); | ||
| 893 | 983 | ||
| 894 | if (ObjSym.isUndefined()) | 984 | if (ObjSym.isUndefined()) |
| 895 | return Symtab<ELFT>::X->addUndefined(NameRef, /*IsLocal=*/false, Binding, | 985 | return Symtab->addUndefined<ELFT>(NameRef, Binding, Visibility, Type, |
| 896 | Visibility, Type, CanOmitFromDynSym, | 986 | CanOmitFromDynSym, &F); |
| 897 | F); | ||
| 898 | 987 | ||
| 899 | if (ObjSym.isCommon()) | 988 | if (ObjSym.isCommon()) |
| 900 | return Symtab<ELFT>::X->addCommon(NameRef, ObjSym.getCommonSize(), | 989 | return Symtab->addCommon(NameRef, ObjSym.getCommonSize(), |
| 901 | ObjSym.getCommonAlignment(), Binding, | 990 | ObjSym.getCommonAlignment(), Binding, Visibility, |
| 902 | Visibility, STT_OBJECT, F); | 991 | STT_OBJECT, F); |
| 903 | 992 | ||
| 904 | return Symtab<ELFT>::X->addBitcode(NameRef, Binding, Visibility, Type, | 993 | return Symtab->addBitcode(NameRef, Binding, Visibility, Type, |
| 905 | CanOmitFromDynSym, F); | 994 | CanOmitFromDynSym, F); |
| 906 | } | 995 | } |
| 907 | 996 | ||
| 908 | template <class ELFT> | 997 | template <class ELFT> |
| ... | @@ -912,7 +1001,7 @@ void BitcodeFile::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { | ... | @@ -912,7 +1001,7 @@ void BitcodeFile::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { |
| 912 | KeptComdats.push_back(ComdatGroups.insert(CachedHashStringRef(S)).second); | 1001 | KeptComdats.push_back(ComdatGroups.insert(CachedHashStringRef(S)).second); |
| 913 | 1002 | ||
| 914 | for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) | 1003 | for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) |
| 915 | Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, this)); | 1004 | Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, *this)); |
| 916 | } | 1005 | } |
| 917 | 1006 | ||
| 918 | static ELFKind getELFKind(MemoryBufferRef MB) { | 1007 | static ELFKind getELFKind(MemoryBufferRef MB) { |
| ... | @@ -935,10 +1024,10 @@ static ELFKind getELFKind(MemoryBufferRef MB) { | ... | @@ -935,10 +1024,10 @@ static ELFKind getELFKind(MemoryBufferRef MB) { |
| 935 | return (Endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind; | 1024 | return (Endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind; |
| 936 | } | 1025 | } |
| 937 | 1026 | ||
| 938 | template <class ELFT> void BinaryFile::parse() { | 1027 | void BinaryFile::parse() { |
| 939 | ArrayRef<uint8_t> Data = toArrayRef(MB.getBuffer()); | 1028 | ArrayRef<uint8_t> Data = toArrayRef(MB.getBuffer()); |
| 940 | auto *Section = | 1029 | auto *Section = make<InputSection>(nullptr, SHF_ALLOC | SHF_WRITE, |
| 941 | make<InputSection>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 8, Data, ".data"); | 1030 | SHT_PROGBITS, 8, Data, ".data"); |
| 942 | Sections.push_back(Section); | 1031 | Sections.push_back(Section); |
| 943 | 1032 | ||
| 944 | // For each input file foo that is embedded to a result as a binary | 1033 | // For each input file foo that is embedded to a result as a binary |
| ... | @@ -947,18 +1036,15 @@ template <class ELFT> void BinaryFile::parse() { | ... | @@ -947,18 +1036,15 @@ template <class ELFT> void BinaryFile::parse() { |
| 947 | // characters in a filename are replaced with underscore. | 1036 | // characters in a filename are replaced with underscore. |
| 948 | std::string S = "_binary_" + MB.getBufferIdentifier().str(); | 1037 | std::string S = "_binary_" + MB.getBufferIdentifier().str(); |
| 949 | for (size_t I = 0; I < S.size(); ++I) | 1038 | for (size_t I = 0; I < S.size(); ++I) |
| 950 | if (!isalnum(S[I])) | 1039 | if (!isAlnum(S[I])) |
| 951 | S[I] = '_'; | 1040 | S[I] = '_'; |
| 952 | 1041 | ||
| 953 | elf::Symtab<ELFT>::X->addRegular(Saver.save(S + "_start"), STV_DEFAULT, | 1042 | Symtab->addRegular(Saver.save(S + "_start"), STV_DEFAULT, STT_OBJECT, 0, 0, |
| 954 | STT_OBJECT, 0, 0, STB_GLOBAL, Section, | 1043 | STB_GLOBAL, Section, nullptr); |
| 955 | nullptr); | 1044 | Symtab->addRegular(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT, |
| 956 | elf::Symtab<ELFT>::X->addRegular(Saver.save(S + "_end"), STV_DEFAULT, | 1045 | Data.size(), 0, STB_GLOBAL, Section, nullptr); |
| 957 | STT_OBJECT, Data.size(), 0, STB_GLOBAL, | 1046 | Symtab->addRegular(Saver.save(S + "_size"), STV_DEFAULT, STT_OBJECT, |
| 958 | Section, nullptr); | 1047 | Data.size(), 0, STB_GLOBAL, nullptr, nullptr); |
| 959 | elf::Symtab<ELFT>::X->addRegular(Saver.save(S + "_size"), STV_DEFAULT, | ||
| 960 | STT_OBJECT, Data.size(), 0, STB_GLOBAL, | ||
| 961 | nullptr, nullptr); | ||
| 962 | } | 1048 | } |
| 963 | 1049 | ||
| 964 | static bool isBitcode(MemoryBufferRef MB) { | 1050 | static bool isBitcode(MemoryBufferRef MB) { |
| ... | @@ -973,13 +1059,13 @@ InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName, | ... | @@ -973,13 +1059,13 @@ InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName, |
| 973 | 1059 | ||
| 974 | switch (getELFKind(MB)) { | 1060 | switch (getELFKind(MB)) { |
| 975 | case ELF32LEKind: | 1061 | case ELF32LEKind: |
| 976 | return make<ObjectFile<ELF32LE>>(MB, ArchiveName); | 1062 | return make<ObjFile<ELF32LE>>(MB, ArchiveName); |
| 977 | case ELF32BEKind: | 1063 | case ELF32BEKind: |
| 978 | return make<ObjectFile<ELF32BE>>(MB, ArchiveName); | 1064 | return make<ObjFile<ELF32BE>>(MB, ArchiveName); |
| 979 | case ELF64LEKind: | 1065 | case ELF64LEKind: |
| 980 | return make<ObjectFile<ELF64LE>>(MB, ArchiveName); | 1066 | return make<ObjFile<ELF64LE>>(MB, ArchiveName); |
| 981 | case ELF64BEKind: | 1067 | case ELF64BEKind: |
| 982 | return make<ObjectFile<ELF64BE>>(MB, ArchiveName); | 1068 | return make<ObjFile<ELF64BE>>(MB, ArchiveName); |
| 983 | default: | 1069 | default: |
| 984 | llvm_unreachable("getELFKind"); | 1070 | llvm_unreachable("getELFKind"); |
| 985 | } | 1071 | } |
| ... | @@ -1000,53 +1086,53 @@ InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) { | ... | @@ -1000,53 +1086,53 @@ InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) { |
| 1000 | } | 1086 | } |
| 1001 | } | 1087 | } |
| 1002 | 1088 | ||
| 1003 | MemoryBufferRef LazyObjectFile::getBuffer() { | 1089 | MemoryBufferRef LazyObjFile::getBuffer() { |
| 1004 | if (Seen) | 1090 | if (Seen) |
| 1005 | return MemoryBufferRef(); | 1091 | return MemoryBufferRef(); |
| 1006 | Seen = true; | 1092 | Seen = true; |
| 1007 | return MB; | 1093 | return MB; |
| 1008 | } | 1094 | } |
| 1009 | 1095 | ||
| 1010 | InputFile *LazyObjectFile::fetch() { | 1096 | InputFile *LazyObjFile::fetch() { |
| 1011 | MemoryBufferRef MBRef = getBuffer(); | 1097 | MemoryBufferRef MBRef = getBuffer(); |
| 1012 | if (MBRef.getBuffer().empty()) | 1098 | if (MBRef.getBuffer().empty()) |
| 1013 | return nullptr; | 1099 | return nullptr; |
| 1014 | return createObjectFile(MBRef, ArchiveName, OffsetInArchive); | 1100 | return createObjectFile(MBRef, ArchiveName, OffsetInArchive); |
| 1015 | } | 1101 | } |
| 1016 | 1102 | ||
| 1017 | template <class ELFT> void LazyObjectFile::parse() { | 1103 | template <class ELFT> void LazyObjFile::parse() { |
| 1018 | for (StringRef Sym : getSymbols()) | 1104 | for (StringRef Sym : getSymbolNames()) |
| 1019 | Symtab<ELFT>::X->addLazyObject(Sym, *this); | 1105 | Symtab->addLazyObject<ELFT>(Sym, *this); |
| 1020 | } | 1106 | } |
| 1021 | 1107 | ||
| 1022 | template <class ELFT> std::vector<StringRef> LazyObjectFile::getElfSymbols() { | 1108 | template <class ELFT> std::vector<StringRef> LazyObjFile::getElfSymbols() { |
| 1023 | typedef typename ELFT::Shdr Elf_Shdr; | 1109 | typedef typename ELFT::Shdr Elf_Shdr; |
| 1024 | typedef typename ELFT::Sym Elf_Sym; | 1110 | typedef typename ELFT::Sym Elf_Sym; |
| 1025 | typedef typename ELFT::SymRange Elf_Sym_Range; | 1111 | typedef typename ELFT::SymRange Elf_Sym_Range; |
| 1026 | 1112 | ||
| 1027 | const ELFFile<ELFT> Obj(this->MB.getBuffer()); | 1113 | ELFFile<ELFT> Obj = check(ELFFile<ELFT>::create(this->MB.getBuffer())); |
| 1028 | ArrayRef<Elf_Shdr> Sections = check(Obj.sections(), toString(this)); | 1114 | ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this); |
| 1029 | for (const Elf_Shdr &Sec : Sections) { | 1115 | for (const Elf_Shdr &Sec : Sections) { |
| 1030 | if (Sec.sh_type != SHT_SYMTAB) | 1116 | if (Sec.sh_type != SHT_SYMTAB) |
| 1031 | continue; | 1117 | continue; |
| 1032 | 1118 | ||
| 1033 | Elf_Sym_Range Syms = check(Obj.symbols(&Sec), toString(this)); | 1119 | Elf_Sym_Range Syms = CHECK(Obj.symbols(&Sec), this); |
| 1034 | uint32_t FirstNonLocal = Sec.sh_info; | 1120 | uint32_t FirstNonLocal = Sec.sh_info; |
| 1035 | StringRef StringTable = | 1121 | StringRef StringTable = |
| 1036 | check(Obj.getStringTableForSymtab(Sec, Sections), toString(this)); | 1122 | CHECK(Obj.getStringTableForSymtab(Sec, Sections), this); |
| 1037 | std::vector<StringRef> V; | 1123 | std::vector<StringRef> V; |
| 1038 | 1124 | ||
| 1039 | for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal)) | 1125 | for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal)) |
| 1040 | if (Sym.st_shndx != SHN_UNDEF) | 1126 | if (Sym.st_shndx != SHN_UNDEF) |
| 1041 | V.push_back(check(Sym.getName(StringTable), toString(this))); | 1127 | V.push_back(CHECK(Sym.getName(StringTable), this)); |
| 1042 | return V; | 1128 | return V; |
| 1043 | } | 1129 | } |
| 1044 | return {}; | 1130 | return {}; |
| 1045 | } | 1131 | } |
| 1046 | 1132 | ||
| 1047 | std::vector<StringRef> LazyObjectFile::getBitcodeSymbols() { | 1133 | std::vector<StringRef> LazyObjFile::getBitcodeSymbols() { |
| 1048 | std::unique_ptr<lto::InputFile> Obj = | 1134 | std::unique_ptr<lto::InputFile> Obj = |
| 1049 | check(lto::InputFile::create(this->MB), toString(this)); | 1135 | CHECK(lto::InputFile::create(this->MB), this); |
| 1050 | std::vector<StringRef> V; | 1136 | std::vector<StringRef> V; |
| 1051 | for (const lto::InputFile::Symbol &Sym : Obj->symbols()) | 1137 | for (const lto::InputFile::Symbol &Sym : Obj->symbols()) |
| 1052 | if (!Sym.isUndefined()) | 1138 | if (!Sym.isUndefined()) |
| ... | @@ -1055,7 +1141,7 @@ std::vector<StringRef> LazyObjectFile::getBitcodeSymbols() { | ... | @@ -1055,7 +1141,7 @@ std::vector<StringRef> LazyObjectFile::getBitcodeSymbols() { |
| 1055 | } | 1141 | } |
| 1056 | 1142 | ||
| 1057 | // Returns a vector of globally-visible defined symbol names. | 1143 | // Returns a vector of globally-visible defined symbol names. |
| 1058 | std::vector<StringRef> LazyObjectFile::getSymbols() { | 1144 | std::vector<StringRef> LazyObjFile::getSymbolNames() { |
| 1059 | if (isBitcode(this->MB)) | 1145 | if (isBitcode(this->MB)) |
| 1060 | return getBitcodeSymbols(); | 1146 | return getBitcodeSymbols(); |
| 1061 | 1147 | ||
| ... | @@ -1083,27 +1169,22 @@ template void BitcodeFile::parse<ELF32BE>(DenseSet<CachedHashStringRef> &); | ... | @@ -1083,27 +1169,22 @@ template void BitcodeFile::parse<ELF32BE>(DenseSet<CachedHashStringRef> &); |
| 1083 | template void BitcodeFile::parse<ELF64LE>(DenseSet<CachedHashStringRef> &); | 1169 | template void BitcodeFile::parse<ELF64LE>(DenseSet<CachedHashStringRef> &); |
| 1084 | template void BitcodeFile::parse<ELF64BE>(DenseSet<CachedHashStringRef> &); | 1170 | template void BitcodeFile::parse<ELF64BE>(DenseSet<CachedHashStringRef> &); |
| 1085 | 1171 | ||
| 1086 | template void LazyObjectFile::parse<ELF32LE>(); | 1172 | template void LazyObjFile::parse<ELF32LE>(); |
| 1087 | template void LazyObjectFile::parse<ELF32BE>(); | 1173 | template void LazyObjFile::parse<ELF32BE>(); |
| 1088 | template void LazyObjectFile::parse<ELF64LE>(); | 1174 | template void LazyObjFile::parse<ELF64LE>(); |
| 1089 | template void LazyObjectFile::parse<ELF64BE>(); | 1175 | template void LazyObjFile::parse<ELF64BE>(); |
| 1090 | 1176 | ||
| 1091 | template class elf::ELFFileBase<ELF32LE>; | 1177 | template class elf::ELFFileBase<ELF32LE>; |
| 1092 | template class elf::ELFFileBase<ELF32BE>; | 1178 | template class elf::ELFFileBase<ELF32BE>; |
| 1093 | template class elf::ELFFileBase<ELF64LE>; | 1179 | template class elf::ELFFileBase<ELF64LE>; |
| 1094 | template class elf::ELFFileBase<ELF64BE>; | 1180 | template class elf::ELFFileBase<ELF64BE>; |
| 1095 | 1181 | ||
| 1096 | template class elf::ObjectFile<ELF32LE>; | 1182 | template class elf::ObjFile<ELF32LE>; |
| 1097 | template class elf::ObjectFile<ELF32BE>; | 1183 | template class elf::ObjFile<ELF32BE>; |
| 1098 | template class elf::ObjectFile<ELF64LE>; | 1184 | template class elf::ObjFile<ELF64LE>; |
| 1099 | template class elf::ObjectFile<ELF64BE>; | 1185 | template class elf::ObjFile<ELF64BE>; |
| 1100 | 1186 | ||
| 1101 | template class elf::SharedFile<ELF32LE>; | 1187 | template class elf::SharedFile<ELF32LE>; |
| 1102 | template class elf::SharedFile<ELF32BE>; | 1188 | template class elf::SharedFile<ELF32BE>; |
| 1103 | template class elf::SharedFile<ELF64LE>; | 1189 | template class elf::SharedFile<ELF64LE>; |
| 1104 | template class elf::SharedFile<ELF64BE>; | 1190 | template class elf::SharedFile<ELF64BE>; |
| 1105 | |||
| 1106 | template void BinaryFile::parse<ELF32LE>(); | ||
| 1107 | template void BinaryFile::parse<ELF32BE>(); | ||
| 1108 | template void BinaryFile::parse<ELF64LE>(); | ||
| 1109 | template void BinaryFile::parse<ELF64BE>(); |
deps/lld/ELF/InputFiles.h+60-58| ... | @@ -11,12 +11,10 @@ | ... | @@ -11,12 +11,10 @@ |
| 11 | #define LLD_ELF_INPUT_FILES_H | 11 | #define LLD_ELF_INPUT_FILES_H |
| 12 | 12 | ||
| 13 | #include "Config.h" | 13 | #include "Config.h" |
| 14 | #include "Error.h" | 14 | #include "lld/Common/ErrorHandler.h" |
| 15 | #include "InputSection.h" | ||
| 16 | #include "Symbols.h" | ||
| 17 | 15 | ||
| 18 | #include "lld/Core/LLVM.h" | 16 | #include "lld/Common/LLVM.h" |
| 19 | #include "lld/Core/Reproduce.h" | 17 | #include "lld/Common/Reproduce.h" |
| 20 | #include "llvm/ADT/CachedHashString.h" | 18 | #include "llvm/ADT/CachedHashString.h" |
| 21 | #include "llvm/ADT/DenseSet.h" | 19 | #include "llvm/ADT/DenseSet.h" |
| 22 | #include "llvm/ADT/STLExtras.h" | 20 | #include "llvm/ADT/STLExtras.h" |
| ... | @@ -40,9 +38,10 @@ class InputFile; | ... | @@ -40,9 +38,10 @@ class InputFile; |
| 40 | namespace lld { | 38 | namespace lld { |
| 41 | namespace elf { | 39 | namespace elf { |
| 42 | class InputFile; | 40 | class InputFile; |
| 41 | class InputSectionBase; | ||
| 43 | } | 42 | } |
| 44 | 43 | ||
| 45 | // Returns "(internal)", "foo.a(bar.o)" or "baz.o". | 44 | // Returns "<internal>", "foo.a(bar.o)" or "baz.o". |
| 46 | std::string toString(const elf::InputFile *F); | 45 | std::string toString(const elf::InputFile *F); |
| 47 | 46 | ||
| 48 | namespace elf { | 47 | namespace elf { |
| ... | @@ -50,7 +49,7 @@ namespace elf { | ... | @@ -50,7 +49,7 @@ namespace elf { |
| 50 | using llvm::object::Archive; | 49 | using llvm::object::Archive; |
| 51 | 50 | ||
| 52 | class Lazy; | 51 | class Lazy; |
| 53 | class SymbolBody; | 52 | class Symbol; |
| 54 | 53 | ||
| 55 | // If -reproduce option is given, all input files are written | 54 | // If -reproduce option is given, all input files are written |
| 56 | // to this tar archive. | 55 | // to this tar archive. |
| ... | @@ -63,9 +62,9 @@ llvm::Optional<MemoryBufferRef> readFile(StringRef Path); | ... | @@ -63,9 +62,9 @@ llvm::Optional<MemoryBufferRef> readFile(StringRef Path); |
| 63 | class InputFile { | 62 | class InputFile { |
| 64 | public: | 63 | public: |
| 65 | enum Kind { | 64 | enum Kind { |
| 66 | ObjectKind, | 65 | ObjKind, |
| 67 | SharedKind, | 66 | SharedKind, |
| 68 | LazyObjectKind, | 67 | LazyObjKind, |
| 69 | ArchiveKind, | 68 | ArchiveKind, |
| 70 | BitcodeKind, | 69 | BitcodeKind, |
| 71 | BinaryKind, | 70 | BinaryKind, |
| ... | @@ -73,16 +72,29 @@ public: | ... | @@ -73,16 +72,29 @@ public: |
| 73 | 72 | ||
| 74 | Kind kind() const { return FileKind; } | 73 | Kind kind() const { return FileKind; } |
| 75 | 74 | ||
| 75 | bool isElf() const { | ||
| 76 | Kind K = kind(); | ||
| 77 | return K == ObjKind || K == SharedKind; | ||
| 78 | } | ||
| 79 | |||
| 76 | StringRef getName() const { return MB.getBufferIdentifier(); } | 80 | StringRef getName() const { return MB.getBufferIdentifier(); } |
| 77 | MemoryBufferRef MB; | 81 | MemoryBufferRef MB; |
| 78 | 82 | ||
| 79 | // Returns sections. It is a runtime error to call this function | 83 | // Returns sections. It is a runtime error to call this function |
| 80 | // on files that don't have the notion of sections. | 84 | // on files that don't have the notion of sections. |
| 81 | ArrayRef<InputSectionBase *> getSections() const { | 85 | ArrayRef<InputSectionBase *> getSections() const { |
| 82 | assert(FileKind == ObjectKind || FileKind == BinaryKind); | 86 | assert(FileKind == ObjKind || FileKind == BinaryKind); |
| 83 | return Sections; | 87 | return Sections; |
| 84 | } | 88 | } |
| 85 | 89 | ||
| 90 | // Returns object file symbols. It is a runtime error to call this | ||
| 91 | // function on files of other types. | ||
| 92 | ArrayRef<Symbol *> getSymbols() { | ||
| 93 | assert(FileKind == ObjKind || FileKind == BitcodeKind || | ||
| 94 | FileKind == ArchiveKind); | ||
| 95 | return Symbols; | ||
| 96 | } | ||
| 97 | |||
| 86 | // Filename of .a which contained this file. If this file was | 98 | // Filename of .a which contained this file. If this file was |
| 87 | // not in an archive file, it is the empty string. We use this | 99 | // not in an archive file, it is the empty string. We use this |
| 88 | // string for creating error messages. | 100 | // string for creating error messages. |
| ... | @@ -97,9 +109,13 @@ public: | ... | @@ -97,9 +109,13 @@ public: |
| 97 | // Cache for toString(). Only toString() should use this member. | 109 | // Cache for toString(). Only toString() should use this member. |
| 98 | mutable std::string ToStringCache; | 110 | mutable std::string ToStringCache; |
| 99 | 111 | ||
| 112 | std::string getSrcMsg(const Symbol &Sym, InputSectionBase &Sec, | ||
| 113 | uint64_t Offset); | ||
| 114 | |||
| 100 | protected: | 115 | protected: |
| 101 | InputFile(Kind K, MemoryBufferRef M); | 116 | InputFile(Kind K, MemoryBufferRef M); |
| 102 | std::vector<InputSectionBase *> Sections; | 117 | std::vector<InputSectionBase *> Sections; |
| 118 | std::vector<Symbol *> Symbols; | ||
| 103 | 119 | ||
| 104 | private: | 120 | private: |
| 105 | const Kind FileKind; | 121 | const Kind FileKind; |
| ... | @@ -113,23 +129,21 @@ public: | ... | @@ -113,23 +129,21 @@ public: |
| 113 | typedef typename ELFT::SymRange Elf_Sym_Range; | 129 | typedef typename ELFT::SymRange Elf_Sym_Range; |
| 114 | 130 | ||
| 115 | ELFFileBase(Kind K, MemoryBufferRef M); | 131 | ELFFileBase(Kind K, MemoryBufferRef M); |
| 116 | static bool classof(const InputFile *F) { | 132 | static bool classof(const InputFile *F) { return F->isElf(); } |
| 117 | Kind K = F->kind(); | ||
| 118 | return K == ObjectKind || K == SharedKind; | ||
| 119 | } | ||
| 120 | 133 | ||
| 121 | llvm::object::ELFFile<ELFT> getObj() const { | 134 | llvm::object::ELFFile<ELFT> getObj() const { |
| 122 | return llvm::object::ELFFile<ELFT>(MB.getBuffer()); | 135 | return check(llvm::object::ELFFile<ELFT>::create(MB.getBuffer())); |
| 123 | } | 136 | } |
| 124 | 137 | ||
| 125 | StringRef getStringTable() const { return StringTable; } | 138 | StringRef getStringTable() const { return StringTable; } |
| 126 | 139 | ||
| 127 | uint32_t getSectionIndex(const Elf_Sym &Sym) const; | 140 | uint32_t getSectionIndex(const Elf_Sym &Sym) const; |
| 128 | 141 | ||
| 129 | Elf_Sym_Range getGlobalSymbols(); | 142 | Elf_Sym_Range getGlobalELFSyms(); |
| 143 | Elf_Sym_Range getELFSyms() const { return ELFSyms; } | ||
| 130 | 144 | ||
| 131 | protected: | 145 | protected: |
| 132 | ArrayRef<Elf_Sym> Symbols; | 146 | ArrayRef<Elf_Sym> ELFSyms; |
| 133 | uint32_t FirstNonLocal = 0; | 147 | uint32_t FirstNonLocal = 0; |
| 134 | ArrayRef<Elf_Word> SymtabSHNDX; | 148 | ArrayRef<Elf_Word> SymtabSHNDX; |
| 135 | StringRef StringTable; | 149 | StringRef StringTable; |
| ... | @@ -137,7 +151,7 @@ protected: | ... | @@ -137,7 +151,7 @@ protected: |
| 137 | }; | 151 | }; |
| 138 | 152 | ||
| 139 | // .o file. | 153 | // .o file. |
| 140 | template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> { | 154 | template <class ELFT> class ObjFile : public ELFFileBase<ELFT> { |
| 141 | typedef ELFFileBase<ELFT> Base; | 155 | typedef ELFFileBase<ELFT> Base; |
| 142 | typedef typename ELFT::Rel Elf_Rel; | 156 | typedef typename ELFT::Rel Elf_Rel; |
| 143 | typedef typename ELFT::Rela Elf_Rela; | 157 | typedef typename ELFT::Rela Elf_Rela; |
| ... | @@ -150,34 +164,29 @@ template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> { | ... | @@ -150,34 +164,29 @@ template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> { |
| 150 | ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec); | 164 | ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec); |
| 151 | 165 | ||
| 152 | public: | 166 | public: |
| 153 | static bool classof(const InputFile *F) { | 167 | static bool classof(const InputFile *F) { return F->kind() == Base::ObjKind; } |
| 154 | return F->kind() == Base::ObjectKind; | ||
| 155 | } | ||
| 156 | 168 | ||
| 157 | ArrayRef<SymbolBody *> getSymbols(); | 169 | ArrayRef<Symbol *> getLocalSymbols(); |
| 158 | ArrayRef<SymbolBody *> getLocalSymbols(); | ||
| 159 | 170 | ||
| 160 | ObjectFile(MemoryBufferRef M, StringRef ArchiveName); | 171 | ObjFile(MemoryBufferRef M, StringRef ArchiveName); |
| 161 | void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); | 172 | void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); |
| 162 | 173 | ||
| 163 | InputSectionBase *getSection(const Elf_Sym &Sym) const; | 174 | Symbol &getSymbol(uint32_t SymbolIndex) const { |
| 164 | 175 | if (SymbolIndex >= this->Symbols.size()) | |
| 165 | SymbolBody &getSymbolBody(uint32_t SymbolIndex) const { | ||
| 166 | if (SymbolIndex >= SymbolBodies.size()) | ||
| 167 | fatal(toString(this) + ": invalid symbol index"); | 176 | fatal(toString(this) + ": invalid symbol index"); |
| 168 | return *SymbolBodies[SymbolIndex]; | 177 | return *this->Symbols[SymbolIndex]; |
| 169 | } | 178 | } |
| 170 | 179 | ||
| 171 | template <typename RelT> | 180 | template <typename RelT> Symbol &getRelocTargetSym(const RelT &Rel) const { |
| 172 | SymbolBody &getRelocTargetSym(const RelT &Rel) const { | ||
| 173 | uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); | 181 | uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); |
| 174 | return getSymbolBody(SymIndex); | 182 | return getSymbol(SymIndex); |
| 175 | } | 183 | } |
| 176 | 184 | ||
| 177 | // Returns source line information for a given offset. | 185 | // Returns source line information for a given offset. |
| 178 | // If no information is available, returns "". | 186 | // If no information is available, returns "". |
| 179 | std::string getLineInfo(InputSectionBase *S, uint64_t Offset); | 187 | std::string getLineInfo(InputSectionBase *S, uint64_t Offset); |
| 180 | llvm::Optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t); | 188 | llvm::Optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t); |
| 189 | llvm::Optional<std::pair<std::string, unsigned>> getVariableLoc(StringRef Name); | ||
| 181 | 190 | ||
| 182 | // MIPS GP0 value defined by this file. This value represents the gp value | 191 | // MIPS GP0 value defined by this file. This value represents the gp value |
| 183 | // used to create the relocatable object and required to support | 192 | // used to create the relocatable object and required to support |
| ... | @@ -193,16 +202,13 @@ private: | ... | @@ -193,16 +202,13 @@ private: |
| 193 | void | 202 | void |
| 194 | initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); | 203 | initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); |
| 195 | void initializeSymbols(); | 204 | void initializeSymbols(); |
| 196 | void initializeDwarfLine(); | 205 | void initializeDwarf(); |
| 197 | InputSectionBase *getRelocTarget(const Elf_Shdr &Sec); | 206 | InputSectionBase *getRelocTarget(const Elf_Shdr &Sec); |
| 198 | InputSectionBase *createInputSection(const Elf_Shdr &Sec); | 207 | InputSectionBase *createInputSection(const Elf_Shdr &Sec); |
| 199 | StringRef getSectionName(const Elf_Shdr &Sec); | 208 | StringRef getSectionName(const Elf_Shdr &Sec); |
| 200 | 209 | ||
| 201 | bool shouldMerge(const Elf_Shdr &Sec); | 210 | bool shouldMerge(const Elf_Shdr &Sec); |
| 202 | SymbolBody *createSymbolBody(const Elf_Sym *Sym); | 211 | Symbol *createSymbol(const Elf_Sym *Sym); |
| 203 | |||
| 204 | // List of all symbols referenced or defined by this file. | ||
| 205 | std::vector<SymbolBody *> SymbolBodies; | ||
| 206 | 212 | ||
| 207 | // .shstrtab contents. | 213 | // .shstrtab contents. |
| 208 | StringRef SectionStringTable; | 214 | StringRef SectionStringTable; |
| ... | @@ -212,34 +218,33 @@ private: | ... | @@ -212,34 +218,33 @@ private: |
| 212 | // single object file, so we cache debugging information in order to | 218 | // single object file, so we cache debugging information in order to |
| 213 | // parse it only once for each object file we link. | 219 | // parse it only once for each object file we link. |
| 214 | std::unique_ptr<llvm::DWARFDebugLine> DwarfLine; | 220 | std::unique_ptr<llvm::DWARFDebugLine> DwarfLine; |
| 221 | llvm::DenseMap<StringRef, std::pair<unsigned, unsigned>> VariableLoc; | ||
| 215 | llvm::once_flag InitDwarfLine; | 222 | llvm::once_flag InitDwarfLine; |
| 216 | }; | 223 | }; |
| 217 | 224 | ||
| 218 | // LazyObjectFile is analogous to ArchiveFile in the sense that | 225 | // LazyObjFile is analogous to ArchiveFile in the sense that |
| 219 | // the file contains lazy symbols. The difference is that | 226 | // the file contains lazy symbols. The difference is that |
| 220 | // LazyObjectFile wraps a single file instead of multiple files. | 227 | // LazyObjFile wraps a single file instead of multiple files. |
| 221 | // | 228 | // |
| 222 | // This class is used for --start-lib and --end-lib options which | 229 | // This class is used for --start-lib and --end-lib options which |
| 223 | // instruct the linker to link object files between them with the | 230 | // instruct the linker to link object files between them with the |
| 224 | // archive file semantics. | 231 | // archive file semantics. |
| 225 | class LazyObjectFile : public InputFile { | 232 | class LazyObjFile : public InputFile { |
| 226 | public: | 233 | public: |
| 227 | LazyObjectFile(MemoryBufferRef M, StringRef ArchiveName, | 234 | LazyObjFile(MemoryBufferRef M, StringRef ArchiveName, |
| 228 | uint64_t OffsetInArchive) | 235 | uint64_t OffsetInArchive) |
| 229 | : InputFile(LazyObjectKind, M), OffsetInArchive(OffsetInArchive) { | 236 | : InputFile(LazyObjKind, M), OffsetInArchive(OffsetInArchive) { |
| 230 | this->ArchiveName = ArchiveName; | 237 | this->ArchiveName = ArchiveName; |
| 231 | } | 238 | } |
| 232 | 239 | ||
| 233 | static bool classof(const InputFile *F) { | 240 | static bool classof(const InputFile *F) { return F->kind() == LazyObjKind; } |
| 234 | return F->kind() == LazyObjectKind; | ||
| 235 | } | ||
| 236 | 241 | ||
| 237 | template <class ELFT> void parse(); | 242 | template <class ELFT> void parse(); |
| 238 | MemoryBufferRef getBuffer(); | 243 | MemoryBufferRef getBuffer(); |
| 239 | InputFile *fetch(); | 244 | InputFile *fetch(); |
| 240 | 245 | ||
| 241 | private: | 246 | private: |
| 242 | std::vector<StringRef> getSymbols(); | 247 | std::vector<StringRef> getSymbolNames(); |
| 243 | template <class ELFT> std::vector<StringRef> getElfSymbols(); | 248 | template <class ELFT> std::vector<StringRef> getElfSymbols(); |
| 244 | std::vector<StringRef> getBitcodeSymbols(); | 249 | std::vector<StringRef> getBitcodeSymbols(); |
| 245 | 250 | ||
| ... | @@ -253,7 +258,6 @@ public: | ... | @@ -253,7 +258,6 @@ public: |
| 253 | explicit ArchiveFile(std::unique_ptr<Archive> &&File); | 258 | explicit ArchiveFile(std::unique_ptr<Archive> &&File); |
| 254 | static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } | 259 | static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } |
| 255 | template <class ELFT> void parse(); | 260 | template <class ELFT> void parse(); |
| 256 | ArrayRef<Symbol *> getSymbols() { return Symbols; } | ||
| 257 | 261 | ||
| 258 | // Returns a memory buffer for a given symbol and the offset in the archive | 262 | // Returns a memory buffer for a given symbol and the offset in the archive |
| 259 | // for the member. An empty memory buffer and an offset of zero | 263 | // for the member. An empty memory buffer and an offset of zero |
| ... | @@ -264,7 +268,6 @@ public: | ... | @@ -264,7 +268,6 @@ public: |
| 264 | private: | 268 | private: |
| 265 | std::unique_ptr<Archive> File; | 269 | std::unique_ptr<Archive> File; |
| 266 | llvm::DenseSet<uint64_t> Seen; | 270 | llvm::DenseSet<uint64_t> Seen; |
| 267 | std::vector<Symbol *> Symbols; | ||
| 268 | }; | 271 | }; |
| 269 | 272 | ||
| 270 | class BitcodeFile : public InputFile { | 273 | class BitcodeFile : public InputFile { |
| ... | @@ -274,11 +277,7 @@ public: | ... | @@ -274,11 +277,7 @@ public: |
| 274 | static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } | 277 | static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } |
| 275 | template <class ELFT> | 278 | template <class ELFT> |
| 276 | void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); | 279 | void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); |
| 277 | ArrayRef<Symbol *> getSymbols() { return Symbols; } | ||
| 278 | std::unique_ptr<llvm::lto::InputFile> Obj; | 280 | std::unique_ptr<llvm::lto::InputFile> Obj; |
| 279 | |||
| 280 | private: | ||
| 281 | std::vector<Symbol *> Symbols; | ||
| 282 | }; | 281 | }; |
| 283 | 282 | ||
| 284 | // .so file. | 283 | // .so file. |
| ... | @@ -296,9 +295,9 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { | ... | @@ -296,9 +295,9 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { |
| 296 | const Elf_Shdr *VerdefSec = nullptr; | 295 | const Elf_Shdr *VerdefSec = nullptr; |
| 297 | 296 | ||
| 298 | public: | 297 | public: |
| 298 | std::vector<const Elf_Verdef *> Verdefs; | ||
| 299 | std::string SoName; | 299 | std::string SoName; |
| 300 | 300 | ||
| 301 | const Elf_Shdr *getSection(const Elf_Sym &Sym) const; | ||
| 302 | llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; } | 301 | llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; } |
| 303 | 302 | ||
| 304 | static bool classof(const InputFile *F) { | 303 | static bool classof(const InputFile *F) { |
| ... | @@ -324,22 +323,25 @@ public: | ... | @@ -324,22 +323,25 @@ public: |
| 324 | std::map<const Elf_Verdef *, NeededVer> VerdefMap; | 323 | std::map<const Elf_Verdef *, NeededVer> VerdefMap; |
| 325 | 324 | ||
| 326 | // Used for --as-needed | 325 | // Used for --as-needed |
| 327 | bool AsNeeded = false; | 326 | bool IsNeeded; |
| 328 | bool IsUsed = false; | ||
| 329 | bool isNeeded() const { return !AsNeeded || IsUsed; } | ||
| 330 | }; | 327 | }; |
| 331 | 328 | ||
| 332 | class BinaryFile : public InputFile { | 329 | class BinaryFile : public InputFile { |
| 333 | public: | 330 | public: |
| 334 | explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {} | 331 | explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {} |
| 335 | static bool classof(const InputFile *F) { return F->kind() == BinaryKind; } | 332 | static bool classof(const InputFile *F) { return F->kind() == BinaryKind; } |
| 336 | template <class ELFT> void parse(); | 333 | void parse(); |
| 337 | }; | 334 | }; |
| 338 | 335 | ||
| 339 | InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", | 336 | InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", |
| 340 | uint64_t OffsetInArchive = 0); | 337 | uint64_t OffsetInArchive = 0); |
| 341 | InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName); | 338 | InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName); |
| 342 | 339 | ||
| 340 | extern std::vector<BinaryFile *> BinaryFiles; | ||
| 341 | extern std::vector<BitcodeFile *> BitcodeFiles; | ||
| 342 | extern std::vector<InputFile *> ObjectFiles; | ||
| 343 | extern std::vector<InputFile *> SharedFiles; | ||
| 344 | |||
| 343 | } // namespace elf | 345 | } // namespace elf |
| 344 | } // namespace lld | 346 | } // namespace lld |
| 345 | 347 |
deps/lld/ELF/InputSection.cpp+260-276| ... | @@ -10,21 +10,22 @@ | ... | @@ -10,21 +10,22 @@ |
| 10 | #include "InputSection.h" | 10 | #include "InputSection.h" |
| 11 | #include "Config.h" | 11 | #include "Config.h" |
| 12 | #include "EhFrame.h" | 12 | #include "EhFrame.h" |
| 13 | #include "Error.h" | ||
| 14 | #include "InputFiles.h" | 13 | #include "InputFiles.h" |
| 15 | #include "LinkerScript.h" | 14 | #include "LinkerScript.h" |
| 16 | #include "Memory.h" | ||
| 17 | #include "OutputSections.h" | 15 | #include "OutputSections.h" |
| 18 | #include "Relocations.h" | 16 | #include "Relocations.h" |
| 17 | #include "Symbols.h" | ||
| 19 | #include "SyntheticSections.h" | 18 | #include "SyntheticSections.h" |
| 20 | #include "Target.h" | 19 | #include "Target.h" |
| 21 | #include "Thunks.h" | 20 | #include "Thunks.h" |
| 21 | #include "lld/Common/ErrorHandler.h" | ||
| 22 | #include "lld/Common/Memory.h" | ||
| 22 | #include "llvm/Object/Decompressor.h" | 23 | #include "llvm/Object/Decompressor.h" |
| 23 | #include "llvm/Support/Compiler.h" | 24 | #include "llvm/Support/Compiler.h" |
| 24 | #include "llvm/Support/Compression.h" | 25 | #include "llvm/Support/Compression.h" |
| 25 | #include "llvm/Support/Endian.h" | 26 | #include "llvm/Support/Endian.h" |
| 26 | #include "llvm/Support/Path.h" | ||
| 27 | #include "llvm/Support/Threading.h" | 27 | #include "llvm/Support/Threading.h" |
| 28 | #include "llvm/Support/xxhash.h" | ||
| 28 | #include <mutex> | 29 | #include <mutex> |
| 29 | 30 | ||
| 30 | using namespace llvm; | 31 | using namespace llvm; |
| ... | @@ -44,12 +45,38 @@ std::string lld::toString(const InputSectionBase *Sec) { | ... | @@ -44,12 +45,38 @@ std::string lld::toString(const InputSectionBase *Sec) { |
| 44 | return (toString(Sec->File) + ":(" + Sec->Name + ")").str(); | 45 | return (toString(Sec->File) + ":(" + Sec->Name + ")").str(); |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 48 | DenseMap<SectionBase *, int> elf::buildSectionOrder() { | ||
| 49 | DenseMap<SectionBase *, int> SectionOrder; | ||
| 50 | if (Config->SymbolOrderingFile.empty()) | ||
| 51 | return SectionOrder; | ||
| 52 | |||
| 53 | // Build a map from symbols to their priorities. Symbols that didn't | ||
| 54 | // appear in the symbol ordering file have the lowest priority 0. | ||
| 55 | // All explicitly mentioned symbols have negative (higher) priorities. | ||
| 56 | DenseMap<StringRef, int> SymbolOrder; | ||
| 57 | int Priority = -Config->SymbolOrderingFile.size(); | ||
| 58 | for (StringRef S : Config->SymbolOrderingFile) | ||
| 59 | SymbolOrder.insert({S, Priority++}); | ||
| 60 | |||
| 61 | // Build a map from sections to their priorities. | ||
| 62 | for (InputFile *File : ObjectFiles) { | ||
| 63 | for (Symbol *Sym : File->getSymbols()) { | ||
| 64 | auto *D = dyn_cast<Defined>(Sym); | ||
| 65 | if (!D || !D->Section) | ||
| 66 | continue; | ||
| 67 | int &Priority = SectionOrder[D->Section]; | ||
| 68 | Priority = std::min(Priority, SymbolOrder.lookup(D->getName())); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | return SectionOrder; | ||
| 72 | } | ||
| 73 | |||
| 47 | template <class ELFT> | 74 | template <class ELFT> |
| 48 | static ArrayRef<uint8_t> getSectionContents(elf::ObjectFile<ELFT> *File, | 75 | static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> &File, |
| 49 | const typename ELFT::Shdr *Hdr) { | 76 | const typename ELFT::Shdr &Hdr) { |
| 50 | if (!File || Hdr->sh_type == SHT_NOBITS) | 77 | if (Hdr.sh_type == SHT_NOBITS) |
| 51 | return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size); | 78 | return makeArrayRef<uint8_t>(nullptr, Hdr.sh_size); |
| 52 | return check(File->getObj().getSectionContents(Hdr)); | 79 | return check(File.getObj().getSectionContents(&Hdr)); |
| 53 | } | 80 | } |
| 54 | 81 | ||
| 55 | InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, | 82 | InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, |
| ... | @@ -59,9 +86,13 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, | ... | @@ -59,9 +86,13 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, |
| 59 | StringRef Name, Kind SectionKind) | 86 | StringRef Name, Kind SectionKind) |
| 60 | : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info, | 87 | : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info, |
| 61 | Link), | 88 | Link), |
| 62 | File(File), Data(Data), Repl(this) { | 89 | File(File), Data(Data) { |
| 63 | Live = !Config->GcSections || !(Flags & SHF_ALLOC); | 90 | // In order to reduce memory allocation, we assume that mergeable |
| 64 | Assigned = false; | 91 | // sections are smaller than 4 GiB, which is not an unreasonable |
| 92 | // assumption as of 2017. | ||
| 93 | if (SectionKind == SectionBase::Merge && Data.size() > UINT32_MAX) | ||
| 94 | error(toString(this) + ": section too large"); | ||
| 95 | |||
| 65 | NumRelocations = 0; | 96 | NumRelocations = 0; |
| 66 | AreRelocsRela = false; | 97 | AreRelocsRela = false; |
| 67 | 98 | ||
| ... | @@ -102,18 +133,18 @@ static uint64_t getType(uint64_t Type, StringRef Name) { | ... | @@ -102,18 +133,18 @@ static uint64_t getType(uint64_t Type, StringRef Name) { |
| 102 | } | 133 | } |
| 103 | 134 | ||
| 104 | template <class ELFT> | 135 | template <class ELFT> |
| 105 | InputSectionBase::InputSectionBase(elf::ObjectFile<ELFT> *File, | 136 | InputSectionBase::InputSectionBase(ObjFile<ELFT> &File, |
| 106 | const typename ELFT::Shdr *Hdr, | 137 | const typename ELFT::Shdr &Hdr, |
| 107 | StringRef Name, Kind SectionKind) | 138 | StringRef Name, Kind SectionKind) |
| 108 | : InputSectionBase(File, getFlags(Hdr->sh_flags), | 139 | : InputSectionBase(&File, getFlags(Hdr.sh_flags), |
| 109 | getType(Hdr->sh_type, Name), Hdr->sh_entsize, | 140 | getType(Hdr.sh_type, Name), Hdr.sh_entsize, Hdr.sh_link, |
| 110 | Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign, | 141 | Hdr.sh_info, Hdr.sh_addralign, |
| 111 | getSectionContents(File, Hdr), Name, SectionKind) { | 142 | getSectionContents(File, Hdr), Name, SectionKind) { |
| 112 | // We reject object files having insanely large alignments even though | 143 | // We reject object files having insanely large alignments even though |
| 113 | // they are allowed by the spec. I think 4GB is a reasonable limitation. | 144 | // they are allowed by the spec. I think 4GB is a reasonable limitation. |
| 114 | // We might want to relax this in the future. | 145 | // We might want to relax this in the future. |
| 115 | if (Hdr->sh_addralign > UINT32_MAX) | 146 | if (Hdr.sh_addralign > UINT32_MAX) |
| 116 | fatal(toString(File) + ": section sh_addralign is too large"); | 147 | fatal(toString(&File) + ": section sh_addralign is too large"); |
| 117 | } | 148 | } |
| 118 | 149 | ||
| 119 | size_t InputSectionBase::getSize() const { | 150 | size_t InputSectionBase::getSize() const { |
| ... | @@ -160,7 +191,7 @@ uint64_t SectionBase::getOffset(uint64_t Offset) const { | ... | @@ -160,7 +191,7 @@ uint64_t SectionBase::getOffset(uint64_t Offset) const { |
| 160 | OutputSection *SectionBase::getOutputSection() { | 191 | OutputSection *SectionBase::getOutputSection() { |
| 161 | InputSection *Sec; | 192 | InputSection *Sec; |
| 162 | if (auto *IS = dyn_cast<InputSection>(this)) | 193 | if (auto *IS = dyn_cast<InputSection>(this)) |
| 163 | Sec = IS; | 194 | return IS->getParent(); |
| 164 | else if (auto *MS = dyn_cast<MergeInputSection>(this)) | 195 | else if (auto *MS = dyn_cast<MergeInputSection>(this)) |
| 165 | Sec = MS->getParent(); | 196 | Sec = MS->getParent(); |
| 166 | else if (auto *EH = dyn_cast<EhInputSection>(this)) | 197 | else if (auto *EH = dyn_cast<EhInputSection>(this)) |
| ... | @@ -170,29 +201,23 @@ OutputSection *SectionBase::getOutputSection() { | ... | @@ -170,29 +201,23 @@ OutputSection *SectionBase::getOutputSection() { |
| 170 | return Sec ? Sec->getParent() : nullptr; | 201 | return Sec ? Sec->getParent() : nullptr; |
| 171 | } | 202 | } |
| 172 | 203 | ||
| 173 | // Uncompress section contents. Note that this function is called | 204 | // Uncompress section contents if required. Note that this function |
| 174 | // from parallel_for_each, so it must be thread-safe. | 205 | // is called from parallelForEach, so it must be thread-safe. |
| 175 | void InputSectionBase::uncompress() { | 206 | void InputSectionBase::maybeUncompress() { |
| 207 | if (UncompressBuf || !Decompressor::isCompressedELFSection(Flags, Name)) | ||
| 208 | return; | ||
| 209 | |||
| 176 | Decompressor Dec = check(Decompressor::create(Name, toStringRef(Data), | 210 | Decompressor Dec = check(Decompressor::create(Name, toStringRef(Data), |
| 177 | Config->IsLE, Config->Is64)); | 211 | Config->IsLE, Config->Is64)); |
| 178 | 212 | ||
| 179 | size_t Size = Dec.getDecompressedSize(); | 213 | size_t Size = Dec.getDecompressedSize(); |
| 180 | char *OutputBuf; | 214 | UncompressBuf.reset(new char[Size]()); |
| 181 | { | 215 | if (Error E = Dec.decompress({UncompressBuf.get(), Size})) |
| 182 | static std::mutex Mu; | ||
| 183 | std::lock_guard<std::mutex> Lock(Mu); | ||
| 184 | OutputBuf = BAlloc.Allocate<char>(Size); | ||
| 185 | } | ||
| 186 | |||
| 187 | if (Error E = Dec.decompress({OutputBuf, Size})) | ||
| 188 | fatal(toString(this) + | 216 | fatal(toString(this) + |
| 189 | ": decompress failed: " + llvm::toString(std::move(E))); | 217 | ": decompress failed: " + llvm::toString(std::move(E))); |
| 190 | this->Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size); | ||
| 191 | this->Flags &= ~(uint64_t)SHF_COMPRESSED; | ||
| 192 | } | ||
| 193 | 218 | ||
| 194 | uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const { | 219 | Data = makeArrayRef((uint8_t *)UncompressBuf.get(), Size); |
| 195 | return getOffset(Sym.Value); | 220 | Flags &= ~(uint64_t)SHF_COMPRESSED; |
| 196 | } | 221 | } |
| 197 | 222 | ||
| 198 | InputSection *InputSectionBase::getLinkOrderDep() const { | 223 | InputSection *InputSectionBase::getLinkOrderDep() const { |
| ... | @@ -200,9 +225,9 @@ InputSection *InputSectionBase::getLinkOrderDep() const { | ... | @@ -200,9 +225,9 @@ InputSection *InputSectionBase::getLinkOrderDep() const { |
| 200 | InputSectionBase *L = File->getSections()[Link]; | 225 | InputSectionBase *L = File->getSections()[Link]; |
| 201 | if (auto *IS = dyn_cast<InputSection>(L)) | 226 | if (auto *IS = dyn_cast<InputSection>(L)) |
| 202 | return IS; | 227 | return IS; |
| 203 | error( | 228 | error("a section with SHF_LINK_ORDER should not refer a non-regular " |
| 204 | "Merge and .eh_frame sections are not supported with SHF_LINK_ORDER " + | 229 | "section: " + |
| 205 | toString(L)); | 230 | toString(L)); |
| 206 | } | 231 | } |
| 207 | return nullptr; | 232 | return nullptr; |
| 208 | } | 233 | } |
| ... | @@ -227,8 +252,8 @@ std::string InputSectionBase::getLocation(uint64_t Offset) { | ... | @@ -227,8 +252,8 @@ std::string InputSectionBase::getLocation(uint64_t Offset) { |
| 227 | SrcFile = toString(File); | 252 | SrcFile = toString(File); |
| 228 | 253 | ||
| 229 | // Find a function symbol that encloses a given location. | 254 | // Find a function symbol that encloses a given location. |
| 230 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) | 255 | for (Symbol *B : File->getSymbols()) |
| 231 | if (auto *D = dyn_cast<DefinedRegular>(B)) | 256 | if (auto *D = dyn_cast<Defined>(B)) |
| 232 | if (D->Section == this && D->Type == STT_FUNC) | 257 | if (D->Section == this && D->Type == STT_FUNC) |
| 233 | if (D->Value <= Offset && Offset < D->Value + D->Size) | 258 | if (D->Value <= Offset && Offset < D->Value + D->Size) |
| 234 | return SrcFile + ":(function " + toString(*D) + ")"; | 259 | return SrcFile + ":(function " + toString(*D) + ")"; |
| ... | @@ -237,31 +262,17 @@ std::string InputSectionBase::getLocation(uint64_t Offset) { | ... | @@ -237,31 +262,17 @@ std::string InputSectionBase::getLocation(uint64_t Offset) { |
| 237 | return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); | 262 | return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); |
| 238 | } | 263 | } |
| 239 | 264 | ||
| 240 | // Returns a source location string. This function is intended to be | 265 | // This function is intended to be used for constructing an error message. |
| 241 | // used for constructing an error message. The returned message looks | 266 | // The returned message looks like this: |
| 242 | // like this: | ||
| 243 | // | 267 | // |
| 244 | // foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42) | 268 | // foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42) |
| 245 | // | 269 | // |
| 246 | // Returns an empty string if there's no way to get line info. | 270 | // Returns an empty string if there's no way to get line info. |
| 247 | template <class ELFT> std::string InputSectionBase::getSrcMsg(uint64_t Offset) { | 271 | std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) { |
| 248 | // Synthetic sections don't have input files. | 272 | // Synthetic sections don't have input files. |
| 249 | elf::ObjectFile<ELFT> *File = getFile<ELFT>(); | ||
| 250 | if (!File) | 273 | if (!File) |
| 251 | return ""; | 274 | return ""; |
| 252 | 275 | return File->getSrcMsg(Sym, *this, Offset); | |
| 253 | Optional<DILineInfo> Info = File->getDILineInfo(this, Offset); | ||
| 254 | |||
| 255 | // File->SourceFile contains STT_FILE symbol, and that is a last resort. | ||
| 256 | if (!Info) | ||
| 257 | return File->SourceFile; | ||
| 258 | |||
| 259 | std::string Path = Info->FileName; | ||
| 260 | std::string Filename = path::filename(Path); | ||
| 261 | std::string Lineno = ":" + std::to_string(Info->Line); | ||
| 262 | if (Filename == Path) | ||
| 263 | return Filename + Lineno; | ||
| 264 | return Filename + Lineno + " (" + Path + Lineno + ")"; | ||
| 265 | } | 276 | } |
| 266 | 277 | ||
| 267 | // Returns a filename string along with an optional section name. This | 278 | // Returns a filename string along with an optional section name. This |
| ... | @@ -273,11 +284,10 @@ template <class ELFT> std::string InputSectionBase::getSrcMsg(uint64_t Offset) { | ... | @@ -273,11 +284,10 @@ template <class ELFT> std::string InputSectionBase::getSrcMsg(uint64_t Offset) { |
| 273 | // or | 284 | // or |
| 274 | // | 285 | // |
| 275 | // path/to/foo.o:(function bar) in archive path/to/bar.a | 286 | // path/to/foo.o:(function bar) in archive path/to/bar.a |
| 276 | template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { | 287 | std::string InputSectionBase::getObjMsg(uint64_t Off) { |
| 277 | // Synthetic sections don't have input files. | 288 | // Synthetic sections don't have input files. |
| 278 | elf::ObjectFile<ELFT> *File = getFile<ELFT>(); | ||
| 279 | if (!File) | 289 | if (!File) |
| 280 | return ("(internal):(" + Name + "+0x" + utohexstr(Off) + ")").str(); | 290 | return ("<internal>:(" + Name + "+0x" + utohexstr(Off) + ")").str(); |
| 281 | std::string Filename = File->getName(); | 291 | std::string Filename = File->getName(); |
| 282 | 292 | ||
| 283 | std::string Archive; | 293 | std::string Archive; |
| ... | @@ -285,8 +295,8 @@ template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { | ... | @@ -285,8 +295,8 @@ template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { |
| 285 | Archive = (" in archive " + File->ArchiveName).str(); | 295 | Archive = (" in archive " + File->ArchiveName).str(); |
| 286 | 296 | ||
| 287 | // Find a symbol that encloses a given location. | 297 | // Find a symbol that encloses a given location. |
| 288 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) | 298 | for (Symbol *B : File->getSymbols()) |
| 289 | if (auto *D = dyn_cast<DefinedRegular>(B)) | 299 | if (auto *D = dyn_cast<Defined>(B)) |
| 290 | if (D->Section == this && D->Value <= Off && Off < D->Value + D->Size) | 300 | if (D->Section == this && D->Value <= Off && Off < D->Value + D->Size) |
| 291 | return Filename + ":(" + toString(*D) + ")" + Archive; | 301 | return Filename + ":(" + toString(*D) + ")" + Archive; |
| 292 | 302 | ||
| ... | @@ -295,17 +305,18 @@ template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { | ... | @@ -295,17 +305,18 @@ template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { |
| 295 | .str(); | 305 | .str(); |
| 296 | } | 306 | } |
| 297 | 307 | ||
| 298 | InputSectionBase InputSectionBase::Discarded; | 308 | InputSection InputSection::Discarded(nullptr, 0, 0, 0, ArrayRef<uint8_t>(), ""); |
| 299 | 309 | ||
| 300 | InputSection::InputSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, | 310 | InputSection::InputSection(InputFile *F, uint64_t Flags, uint32_t Type, |
| 301 | ArrayRef<uint8_t> Data, StringRef Name, Kind K) | 311 | uint32_t Alignment, ArrayRef<uint8_t> Data, |
| 302 | : InputSectionBase(nullptr, Flags, Type, | 312 | StringRef Name, Kind K) |
| 313 | : InputSectionBase(F, Flags, Type, | ||
| 303 | /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Alignment, Data, | 314 | /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Alignment, Data, |
| 304 | Name, K) {} | 315 | Name, K) {} |
| 305 | 316 | ||
| 306 | template <class ELFT> | 317 | template <class ELFT> |
| 307 | InputSection::InputSection(elf::ObjectFile<ELFT> *F, | 318 | InputSection::InputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header, |
| 308 | const typename ELFT::Shdr *Header, StringRef Name) | 319 | StringRef Name) |
| 309 | : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} | 320 | : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} |
| 310 | 321 | ||
| 311 | bool InputSection::classof(const SectionBase *S) { | 322 | bool InputSection::classof(const SectionBase *S) { |
| ... | @@ -313,10 +324,6 @@ bool InputSection::classof(const SectionBase *S) { | ... | @@ -313,10 +324,6 @@ bool InputSection::classof(const SectionBase *S) { |
| 313 | S->kind() == SectionBase::Synthetic; | 324 | S->kind() == SectionBase::Synthetic; |
| 314 | } | 325 | } |
| 315 | 326 | ||
| 316 | bool InputSectionBase::classof(const SectionBase *S) { | ||
| 317 | return S->kind() != Output; | ||
| 318 | } | ||
| 319 | |||
| 320 | OutputSection *InputSection::getParent() const { | 327 | OutputSection *InputSection::getParent() const { |
| 321 | return cast_or_null<OutputSection>(Parent); | 328 | return cast_or_null<OutputSection>(Parent); |
| 322 | } | 329 | } |
| ... | @@ -333,15 +340,15 @@ template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) { | ... | @@ -333,15 +340,15 @@ template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) { |
| 333 | 340 | ||
| 334 | // Adjust section numbers because section numbers in an input object | 341 | // Adjust section numbers because section numbers in an input object |
| 335 | // files are different in the output. | 342 | // files are different in the output. |
| 336 | ArrayRef<InputSectionBase *> Sections = this->File->getSections(); | 343 | ArrayRef<InputSectionBase *> Sections = File->getSections(); |
| 337 | for (uint32_t Idx : From.slice(1)) | 344 | for (uint32_t Idx : From.slice(1)) |
| 338 | *To++ = Sections[Idx]->getOutputSection()->SectionIndex; | 345 | *To++ = Sections[Idx]->getOutputSection()->SectionIndex; |
| 339 | } | 346 | } |
| 340 | 347 | ||
| 341 | InputSectionBase *InputSection::getRelocatedSection() { | 348 | InputSectionBase *InputSection::getRelocatedSection() { |
| 342 | assert(this->Type == SHT_RELA || this->Type == SHT_REL); | 349 | assert(Type == SHT_RELA || Type == SHT_REL); |
| 343 | ArrayRef<InputSectionBase *> Sections = this->File->getSections(); | 350 | ArrayRef<InputSectionBase *> Sections = File->getSections(); |
| 344 | return Sections[this->Info]; | 351 | return Sections[Info]; |
| 345 | } | 352 | } |
| 346 | 353 | ||
| 347 | // This is used for -r and --emit-relocs. We can't use memcpy to copy | 354 | // This is used for -r and --emit-relocs. We can't use memcpy to copy |
| ... | @@ -349,15 +356,11 @@ InputSectionBase *InputSection::getRelocatedSection() { | ... | @@ -349,15 +356,11 @@ InputSectionBase *InputSection::getRelocatedSection() { |
| 349 | // for each relocation. So we copy relocations one by one. | 356 | // for each relocation. So we copy relocations one by one. |
| 350 | template <class ELFT, class RelTy> | 357 | template <class ELFT, class RelTy> |
| 351 | void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 358 | void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
| 352 | InputSectionBase *RelocatedSection = getRelocatedSection(); | 359 | InputSectionBase *Sec = getRelocatedSection(); |
| 353 | 360 | ||
| 354 | // Loop is slow and have complexity O(N*M), where N - amount of | ||
| 355 | // relocations and M - amount of symbols in symbol table. | ||
| 356 | // That happens because getSymbolIndex(...) call below performs | ||
| 357 | // simple linear search. | ||
| 358 | for (const RelTy &Rel : Rels) { | 361 | for (const RelTy &Rel : Rels) { |
| 359 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 362 | RelType Type = Rel.getType(Config->IsMips64EL); |
| 360 | SymbolBody &Body = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 363 | Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel); |
| 361 | 364 | ||
| 362 | auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); | 365 | auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); |
| 363 | Buf += sizeof(RelTy); | 366 | Buf += sizeof(RelTy); |
| ... | @@ -367,12 +370,11 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { | ... | @@ -367,12 +370,11 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
| 367 | 370 | ||
| 368 | // Output section VA is zero for -r, so r_offset is an offset within the | 371 | // Output section VA is zero for -r, so r_offset is an offset within the |
| 369 | // section, but for --emit-relocs it is an virtual address. | 372 | // section, but for --emit-relocs it is an virtual address. |
| 370 | P->r_offset = RelocatedSection->getOutputSection()->Addr + | 373 | P->r_offset = Sec->getOutputSection()->Addr + Sec->getOffset(Rel.r_offset); |
| 371 | RelocatedSection->getOffset(Rel.r_offset); | 374 | P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Sym), Type, |
| 372 | P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Body), Type, | ||
| 373 | Config->IsMips64EL); | 375 | Config->IsMips64EL); |
| 374 | 376 | ||
| 375 | if (Body.Type == STT_SECTION) { | 377 | if (Sym.Type == STT_SECTION) { |
| 376 | // We combine multiple section symbols into only one per | 378 | // We combine multiple section symbols into only one per |
| 377 | // section. This means we have to update the addend. That is | 379 | // section. This means we have to update the addend. That is |
| 378 | // trivial for Elf_Rela, but for Elf_Rel we have to write to the | 380 | // trivial for Elf_Rela, but for Elf_Rel we have to write to the |
| ... | @@ -382,19 +384,25 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { | ... | @@ -382,19 +384,25 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
| 382 | // avoid having to parse and recreate .eh_frame, we just replace any | 384 | // avoid having to parse and recreate .eh_frame, we just replace any |
| 383 | // relocation in it pointing to discarded sections with R_*_NONE, which | 385 | // relocation in it pointing to discarded sections with R_*_NONE, which |
| 384 | // hopefully creates a frame that is ignored at runtime. | 386 | // hopefully creates a frame that is ignored at runtime. |
| 385 | SectionBase *Section = cast<DefinedRegular>(Body).Section; | 387 | auto *D = dyn_cast<Defined>(&Sym); |
| 388 | if (!D) { | ||
| 389 | error("STT_SECTION symbol should be defined"); | ||
| 390 | continue; | ||
| 391 | } | ||
| 392 | SectionBase *Section = D->Section; | ||
| 386 | if (Section == &InputSection::Discarded) { | 393 | if (Section == &InputSection::Discarded) { |
| 387 | P->setSymbolAndType(0, 0, false); | 394 | P->setSymbolAndType(0, 0, false); |
| 388 | continue; | 395 | continue; |
| 389 | } | 396 | } |
| 390 | 397 | ||
| 391 | if (Config->IsRela) { | 398 | if (Config->IsRela) { |
| 392 | P->r_addend += Body.getVA() - Section->getOutputSection()->Addr; | 399 | P->r_addend = |
| 400 | Sym.getVA(getAddend<ELFT>(Rel)) - Section->getOutputSection()->Addr; | ||
| 393 | } else if (Config->Relocatable) { | 401 | } else if (Config->Relocatable) { |
| 394 | const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset; | 402 | const uint8_t *BufLoc = Sec->Data.begin() + Rel.r_offset; |
| 395 | RelocatedSection->Relocations.push_back( | 403 | Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset, |
| 396 | {R_ABS, Type, Rel.r_offset, Target->getImplicitAddend(BufLoc, Type), | 404 | Target->getImplicitAddend(BufLoc, Type), |
| 397 | &Body}); | 405 | &Sym}); |
| 398 | } | 406 | } |
| 399 | } | 407 | } |
| 400 | 408 | ||
| ... | @@ -406,7 +414,7 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { | ... | @@ -406,7 +414,7 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
| 406 | // this context is the address of the place P. A further special case is that | 414 | // this context is the address of the place P. A further special case is that |
| 407 | // branch relocations to an undefined weak reference resolve to the next | 415 | // branch relocations to an undefined weak reference resolve to the next |
| 408 | // instruction. | 416 | // instruction. |
| 409 | static uint32_t getARMUndefinedRelativeWeakVA(uint32_t Type, uint32_t A, | 417 | static uint32_t getARMUndefinedRelativeWeakVA(RelType Type, uint32_t A, |
| 410 | uint32_t P) { | 418 | uint32_t P) { |
| 411 | switch (Type) { | 419 | switch (Type) { |
| 412 | // Unresolved branch relocations to weak references resolve to next | 420 | // Unresolved branch relocations to weak references resolve to next |
| ... | @@ -453,6 +461,7 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, | ... | @@ -453,6 +461,7 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, |
| 453 | case R_AARCH64_PREL32: | 461 | case R_AARCH64_PREL32: |
| 454 | case R_AARCH64_PREL64: | 462 | case R_AARCH64_PREL64: |
| 455 | case R_AARCH64_ADR_PREL_LO21: | 463 | case R_AARCH64_ADR_PREL_LO21: |
| 464 | case R_AARCH64_LD_PREL_LO19: | ||
| 456 | return P + A; | 465 | return P + A; |
| 457 | } | 466 | } |
| 458 | llvm_unreachable("AArch64 pc-relative relocation expected\n"); | 467 | llvm_unreachable("AArch64 pc-relative relocation expected\n"); |
| ... | @@ -461,53 +470,55 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, | ... | @@ -461,53 +470,55 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, |
| 461 | // ARM SBREL relocations are of the form S + A - B where B is the static base | 470 | // ARM SBREL relocations are of the form S + A - B where B is the static base |
| 462 | // The ARM ABI defines base to be "addressing origin of the output segment | 471 | // The ARM ABI defines base to be "addressing origin of the output segment |
| 463 | // defining the symbol S". We defined the "addressing origin"/static base to be | 472 | // defining the symbol S". We defined the "addressing origin"/static base to be |
| 464 | // the base of the PT_LOAD segment containing the Body. | 473 | // the base of the PT_LOAD segment containing the Sym. |
| 465 | // The procedure call standard only defines a Read Write Position Independent | 474 | // The procedure call standard only defines a Read Write Position Independent |
| 466 | // RWPI variant so in practice we should expect the static base to be the base | 475 | // RWPI variant so in practice we should expect the static base to be the base |
| 467 | // of the RW segment. | 476 | // of the RW segment. |
| 468 | static uint64_t getARMStaticBase(const SymbolBody &Body) { | 477 | static uint64_t getARMStaticBase(const Symbol &Sym) { |
| 469 | OutputSection *OS = Body.getOutputSection(); | 478 | OutputSection *OS = Sym.getOutputSection(); |
| 470 | if (!OS || !OS->FirstInPtLoad) | 479 | if (!OS || !OS->PtLoad || !OS->PtLoad->FirstSec) |
| 471 | fatal("SBREL relocation to " + Body.getName() + " without static base"); | 480 | fatal("SBREL relocation to " + Sym.getName() + " without static base"); |
| 472 | return OS->FirstInPtLoad->Addr; | 481 | return OS->PtLoad->FirstSec->Addr; |
| 473 | } | 482 | } |
| 474 | 483 | ||
| 475 | static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, | 484 | static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P, |
| 476 | const SymbolBody &Body, RelExpr Expr) { | 485 | const Symbol &Sym, RelExpr Expr) { |
| 477 | switch (Expr) { | 486 | switch (Expr) { |
| 487 | case R_INVALID: | ||
| 488 | return 0; | ||
| 478 | case R_ABS: | 489 | case R_ABS: |
| 479 | case R_RELAX_GOT_PC_NOPIC: | 490 | case R_RELAX_GOT_PC_NOPIC: |
| 480 | return Body.getVA(A); | 491 | return Sym.getVA(A); |
| 481 | case R_ARM_SBREL: | 492 | case R_ARM_SBREL: |
| 482 | return Body.getVA(A) - getARMStaticBase(Body); | 493 | return Sym.getVA(A) - getARMStaticBase(Sym); |
| 483 | case R_GOT: | 494 | case R_GOT: |
| 484 | case R_RELAX_TLS_GD_TO_IE_ABS: | 495 | case R_RELAX_TLS_GD_TO_IE_ABS: |
| 485 | return Body.getGotVA() + A; | 496 | return Sym.getGotVA() + A; |
| 486 | case R_GOTONLY_PC: | 497 | case R_GOTONLY_PC: |
| 487 | return InX::Got->getVA() + A - P; | 498 | return InX::Got->getVA() + A - P; |
| 488 | case R_GOTONLY_PC_FROM_END: | 499 | case R_GOTONLY_PC_FROM_END: |
| 489 | return InX::Got->getVA() + A - P + InX::Got->getSize(); | 500 | return InX::Got->getVA() + A - P + InX::Got->getSize(); |
| 490 | case R_GOTREL: | 501 | case R_GOTREL: |
| 491 | return Body.getVA(A) - InX::Got->getVA(); | 502 | return Sym.getVA(A) - InX::Got->getVA(); |
| 492 | case R_GOTREL_FROM_END: | 503 | case R_GOTREL_FROM_END: |
| 493 | return Body.getVA(A) - InX::Got->getVA() - InX::Got->getSize(); | 504 | return Sym.getVA(A) - InX::Got->getVA() - InX::Got->getSize(); |
| 494 | case R_GOT_FROM_END: | 505 | case R_GOT_FROM_END: |
| 495 | case R_RELAX_TLS_GD_TO_IE_END: | 506 | case R_RELAX_TLS_GD_TO_IE_END: |
| 496 | return Body.getGotOffset() + A - InX::Got->getSize(); | 507 | return Sym.getGotOffset() + A - InX::Got->getSize(); |
| 497 | case R_GOT_OFF: | 508 | case R_GOT_OFF: |
| 498 | return Body.getGotOffset() + A; | 509 | return Sym.getGotOffset() + A; |
| 499 | case R_GOT_PAGE_PC: | 510 | case R_GOT_PAGE_PC: |
| 500 | case R_RELAX_TLS_GD_TO_IE_PAGE_PC: | 511 | case R_RELAX_TLS_GD_TO_IE_PAGE_PC: |
| 501 | return getAArch64Page(Body.getGotVA() + A) - getAArch64Page(P); | 512 | return getAArch64Page(Sym.getGotVA() + A) - getAArch64Page(P); |
| 502 | case R_GOT_PC: | 513 | case R_GOT_PC: |
| 503 | case R_RELAX_TLS_GD_TO_IE: | 514 | case R_RELAX_TLS_GD_TO_IE: |
| 504 | return Body.getGotVA() + A - P; | 515 | return Sym.getGotVA() + A - P; |
| 505 | case R_HINT: | 516 | case R_HINT: |
| 506 | case R_NONE: | 517 | case R_NONE: |
| 507 | case R_TLSDESC_CALL: | 518 | case R_TLSDESC_CALL: |
| 508 | llvm_unreachable("cannot relocate hint relocs"); | 519 | llvm_unreachable("cannot relocate hint relocs"); |
| 509 | case R_MIPS_GOTREL: | 520 | case R_MIPS_GOTREL: |
| 510 | return Body.getVA(A) - InX::MipsGot->getGp(); | 521 | return Sym.getVA(A) - InX::MipsGot->getGp(); |
| 511 | case R_MIPS_GOT_GP: | 522 | case R_MIPS_GOT_GP: |
| 512 | return InX::MipsGot->getGp() + A; | 523 | return InX::MipsGot->getGp() + A; |
| 513 | case R_MIPS_GOT_GP_PC: { | 524 | case R_MIPS_GOT_GP_PC: { |
| ... | @@ -515,42 +526,47 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, | ... | @@ -515,42 +526,47 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, |
| 515 | // is _gp_disp symbol. In that case we should use the following | 526 | // is _gp_disp symbol. In that case we should use the following |
| 516 | // formula for calculation "AHL + GP - P + 4". For details see p. 4-19 at | 527 | // formula for calculation "AHL + GP - P + 4". For details see p. 4-19 at |
| 517 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 528 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
| 529 | // microMIPS variants of these relocations use slightly different | ||
| 530 | // expressions: AHL + GP - P + 3 for %lo() and AHL + GP - P - 1 for %hi() | ||
| 531 | // to correctly handle less-sugnificant bit of the microMIPS symbol. | ||
| 518 | uint64_t V = InX::MipsGot->getGp() + A - P; | 532 | uint64_t V = InX::MipsGot->getGp() + A - P; |
| 519 | if (Type == R_MIPS_LO16) | 533 | if (Type == R_MIPS_LO16 || Type == R_MICROMIPS_LO16) |
| 520 | V += 4; | 534 | V += 4; |
| 535 | if (Type == R_MICROMIPS_LO16 || Type == R_MICROMIPS_HI16) | ||
| 536 | V -= 1; | ||
| 521 | return V; | 537 | return V; |
| 522 | } | 538 | } |
| 523 | case R_MIPS_GOT_LOCAL_PAGE: | 539 | case R_MIPS_GOT_LOCAL_PAGE: |
| 524 | // If relocation against MIPS local symbol requires GOT entry, this entry | 540 | // If relocation against MIPS local symbol requires GOT entry, this entry |
| 525 | // should be initialized by 'page address'. This address is high 16-bits | 541 | // should be initialized by 'page address'. This address is high 16-bits |
| 526 | // of sum the symbol's value and the addend. | 542 | // of sum the symbol's value and the addend. |
| 527 | return InX::MipsGot->getVA() + InX::MipsGot->getPageEntryOffset(Body, A) - | 543 | return InX::MipsGot->getVA() + InX::MipsGot->getPageEntryOffset(Sym, A) - |
| 528 | InX::MipsGot->getGp(); | 544 | InX::MipsGot->getGp(); |
| 529 | case R_MIPS_GOT_OFF: | 545 | case R_MIPS_GOT_OFF: |
| 530 | case R_MIPS_GOT_OFF32: | 546 | case R_MIPS_GOT_OFF32: |
| 531 | // In case of MIPS if a GOT relocation has non-zero addend this addend | 547 | // In case of MIPS if a GOT relocation has non-zero addend this addend |
| 532 | // should be applied to the GOT entry content not to the GOT entry offset. | 548 | // should be applied to the GOT entry content not to the GOT entry offset. |
| 533 | // That is why we use separate expression type. | 549 | // That is why we use separate expression type. |
| 534 | return InX::MipsGot->getVA() + InX::MipsGot->getBodyEntryOffset(Body, A) - | 550 | return InX::MipsGot->getVA() + InX::MipsGot->getSymEntryOffset(Sym, A) - |
| 535 | InX::MipsGot->getGp(); | 551 | InX::MipsGot->getGp(); |
| 536 | case R_MIPS_TLSGD: | 552 | case R_MIPS_TLSGD: |
| 537 | return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() + | 553 | return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() + |
| 538 | InX::MipsGot->getGlobalDynOffset(Body) - InX::MipsGot->getGp(); | 554 | InX::MipsGot->getGlobalDynOffset(Sym) - InX::MipsGot->getGp(); |
| 539 | case R_MIPS_TLSLD: | 555 | case R_MIPS_TLSLD: |
| 540 | return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() + | 556 | return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() + |
| 541 | InX::MipsGot->getTlsIndexOff() - InX::MipsGot->getGp(); | 557 | InX::MipsGot->getTlsIndexOff() - InX::MipsGot->getGp(); |
| 542 | case R_PAGE_PC: | 558 | case R_PAGE_PC: |
| 543 | case R_PLT_PAGE_PC: { | 559 | case R_PLT_PAGE_PC: { |
| 544 | uint64_t Dest; | 560 | uint64_t Dest; |
| 545 | if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) | 561 | if (Sym.isUndefWeak()) |
| 546 | Dest = getAArch64Page(A); | 562 | Dest = getAArch64Page(A); |
| 547 | else | 563 | else |
| 548 | Dest = getAArch64Page(Body.getVA(A)); | 564 | Dest = getAArch64Page(Sym.getVA(A)); |
| 549 | return Dest - getAArch64Page(P); | 565 | return Dest - getAArch64Page(P); |
| 550 | } | 566 | } |
| 551 | case R_PC: { | 567 | case R_PC: { |
| 552 | uint64_t Dest; | 568 | uint64_t Dest; |
| 553 | if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) { | 569 | if (Sym.isUndefWeak()) { |
| 554 | // On ARM and AArch64 a branch to an undefined weak resolves to the | 570 | // On ARM and AArch64 a branch to an undefined weak resolves to the |
| 555 | // next instruction, otherwise the place. | 571 | // next instruction, otherwise the place. |
| 556 | if (Config->EMachine == EM_ARM) | 572 | if (Config->EMachine == EM_ARM) |
| ... | @@ -558,19 +574,19 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, | ... | @@ -558,19 +574,19 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, |
| 558 | else if (Config->EMachine == EM_AARCH64) | 574 | else if (Config->EMachine == EM_AARCH64) |
| 559 | Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P); | 575 | Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P); |
| 560 | else | 576 | else |
| 561 | Dest = Body.getVA(A); | 577 | Dest = Sym.getVA(A); |
| 562 | } else { | 578 | } else { |
| 563 | Dest = Body.getVA(A); | 579 | Dest = Sym.getVA(A); |
| 564 | } | 580 | } |
| 565 | return Dest - P; | 581 | return Dest - P; |
| 566 | } | 582 | } |
| 567 | case R_PLT: | 583 | case R_PLT: |
| 568 | return Body.getPltVA() + A; | 584 | return Sym.getPltVA() + A; |
| 569 | case R_PLT_PC: | 585 | case R_PLT_PC: |
| 570 | case R_PPC_PLT_OPD: | 586 | case R_PPC_PLT_OPD: |
| 571 | return Body.getPltVA() + A - P; | 587 | return Sym.getPltVA() + A - P; |
| 572 | case R_PPC_OPD: { | 588 | case R_PPC_OPD: { |
| 573 | uint64_t SymVA = Body.getVA(A); | 589 | uint64_t SymVA = Sym.getVA(A); |
| 574 | // If we have an undefined weak symbol, we might get here with a symbol | 590 | // If we have an undefined weak symbol, we might get here with a symbol |
| 575 | // address of zero. That could overflow, but the code must be unreachable, | 591 | // address of zero. That could overflow, but the code must be unreachable, |
| 576 | // so don't bother doing anything at all. | 592 | // so don't bother doing anything at all. |
| ... | @@ -590,7 +606,7 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, | ... | @@ -590,7 +606,7 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, |
| 590 | case R_PPC_TOC: | 606 | case R_PPC_TOC: |
| 591 | return getPPC64TocBase() + A; | 607 | return getPPC64TocBase() + A; |
| 592 | case R_RELAX_GOT_PC: | 608 | case R_RELAX_GOT_PC: |
| 593 | return Body.getVA(A) - P; | 609 | return Sym.getVA(A) - P; |
| 594 | case R_RELAX_TLS_GD_TO_LE: | 610 | case R_RELAX_TLS_GD_TO_LE: |
| 595 | case R_RELAX_TLS_IE_TO_LE: | 611 | case R_RELAX_TLS_IE_TO_LE: |
| 596 | case R_RELAX_TLS_LD_TO_LE: | 612 | case R_RELAX_TLS_LD_TO_LE: |
| ... | @@ -600,26 +616,25 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, | ... | @@ -600,26 +616,25 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, |
| 600 | // lld and .tbss is not referenced, it gets reclaimed and we don't | 616 | // lld and .tbss is not referenced, it gets reclaimed and we don't |
| 601 | // create a TLS program header. Therefore, we resolve this | 617 | // create a TLS program header. Therefore, we resolve this |
| 602 | // statically to zero. | 618 | // statically to zero. |
| 603 | if (Body.isTls() && (Body.isLazy() || Body.isUndefined()) && | 619 | if (Sym.isTls() && Sym.isUndefWeak()) |
| 604 | Body.symbol()->isWeak()) | ||
| 605 | return 0; | 620 | return 0; |
| 606 | if (Target->TcbSize) | 621 | if (Target->TcbSize) |
| 607 | return Body.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align); | 622 | return Sym.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align); |
| 608 | return Body.getVA(A) - Out::TlsPhdr->p_memsz; | 623 | return Sym.getVA(A) - Out::TlsPhdr->p_memsz; |
| 609 | case R_RELAX_TLS_GD_TO_LE_NEG: | 624 | case R_RELAX_TLS_GD_TO_LE_NEG: |
| 610 | case R_NEG_TLS: | 625 | case R_NEG_TLS: |
| 611 | return Out::TlsPhdr->p_memsz - Body.getVA(A); | 626 | return Out::TlsPhdr->p_memsz - Sym.getVA(A); |
| 612 | case R_SIZE: | 627 | case R_SIZE: |
| 613 | return A; // Body.getSize was already folded into the addend. | 628 | return A; // Sym.getSize was already folded into the addend. |
| 614 | case R_TLSDESC: | 629 | case R_TLSDESC: |
| 615 | return InX::Got->getGlobalDynAddr(Body) + A; | 630 | return InX::Got->getGlobalDynAddr(Sym) + A; |
| 616 | case R_TLSDESC_PAGE: | 631 | case R_TLSDESC_PAGE: |
| 617 | return getAArch64Page(InX::Got->getGlobalDynAddr(Body) + A) - | 632 | return getAArch64Page(InX::Got->getGlobalDynAddr(Sym) + A) - |
| 618 | getAArch64Page(P); | 633 | getAArch64Page(P); |
| 619 | case R_TLSGD: | 634 | case R_TLSGD: |
| 620 | return InX::Got->getGlobalDynOffset(Body) + A - InX::Got->getSize(); | 635 | return InX::Got->getGlobalDynOffset(Sym) + A - InX::Got->getSize(); |
| 621 | case R_TLSGD_PC: | 636 | case R_TLSGD_PC: |
| 622 | return InX::Got->getGlobalDynAddr(Body) + A - P; | 637 | return InX::Got->getGlobalDynAddr(Sym) + A - P; |
| 623 | case R_TLSLD: | 638 | case R_TLSLD: |
| 624 | return InX::Got->getTlsIndexOff() + A - InX::Got->getSize(); | 639 | return InX::Got->getTlsIndexOff() + A - InX::Got->getSize(); |
| 625 | case R_TLSLD_PC: | 640 | case R_TLSLD_PC: |
| ... | @@ -637,64 +652,62 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, | ... | @@ -637,64 +652,62 @@ static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, |
| 637 | // function as a performance optimization. | 652 | // function as a performance optimization. |
| 638 | template <class ELFT, class RelTy> | 653 | template <class ELFT, class RelTy> |
| 639 | void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 654 | void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
| 655 | const unsigned Bits = sizeof(typename ELFT::uint) * 8; | ||
| 656 | |||
| 640 | for (const RelTy &Rel : Rels) { | 657 | for (const RelTy &Rel : Rels) { |
| 641 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 658 | RelType Type = Rel.getType(Config->IsMips64EL); |
| 642 | uint64_t Offset = getOffset(Rel.r_offset); | 659 | uint64_t Offset = getOffset(Rel.r_offset); |
| 643 | uint8_t *BufLoc = Buf + Offset; | 660 | uint8_t *BufLoc = Buf + Offset; |
| 644 | int64_t Addend = getAddend<ELFT>(Rel); | 661 | int64_t Addend = getAddend<ELFT>(Rel); |
| 645 | if (!RelTy::IsRela) | 662 | if (!RelTy::IsRela) |
| 646 | Addend += Target->getImplicitAddend(BufLoc, Type); | 663 | Addend += Target->getImplicitAddend(BufLoc, Type); |
| 647 | 664 | ||
| 648 | SymbolBody &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 665 | Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel); |
| 649 | RelExpr Expr = Target->getRelExpr(Type, Sym, BufLoc); | 666 | RelExpr Expr = Target->getRelExpr(Type, Sym, BufLoc); |
| 650 | if (Expr == R_NONE) | 667 | if (Expr == R_NONE) |
| 651 | continue; | 668 | continue; |
| 652 | if (Expr != R_ABS) { | 669 | if (Expr != R_ABS) { |
| 653 | error(this->getLocation<ELFT>(Offset) + ": has non-ABS reloc"); | 670 | // GCC 8.0 or earlier have a bug that it emits R_386_GOTPC relocations |
| 671 | // against _GLOBAL_OFFSET_TABLE for .debug_info. The bug seems to have | ||
| 672 | // been fixed in 2017: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82630, | ||
| 673 | // but we need to keep this bug-compatible code for a while. | ||
| 674 | if (Config->EMachine == EM_386 && Type == R_386_GOTPC) | ||
| 675 | continue; | ||
| 676 | |||
| 677 | error(getLocation<ELFT>(Offset) + ": has non-ABS relocation " + | ||
| 678 | toString(Type) + " against symbol '" + toString(Sym) + "'"); | ||
| 654 | return; | 679 | return; |
| 655 | } | 680 | } |
| 656 | 681 | ||
| 657 | uint64_t AddrLoc = getParent()->Addr + Offset; | 682 | if (Sym.isTls() && !Out::TlsPhdr) |
| 658 | uint64_t SymVA = 0; | 683 | Target->relocateOne(BufLoc, Type, 0); |
| 659 | if (!Sym.isTls() || Out::TlsPhdr) | 684 | else |
| 660 | SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( | 685 | Target->relocateOne(BufLoc, Type, SignExtend64<Bits>(Sym.getVA(Addend))); |
| 661 | getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); | ||
| 662 | Target->relocateOne(BufLoc, Type, SymVA); | ||
| 663 | } | 686 | } |
| 664 | } | 687 | } |
| 665 | 688 | ||
| 666 | template <class ELFT> elf::ObjectFile<ELFT> *InputSectionBase::getFile() const { | ||
| 667 | return cast_or_null<elf::ObjectFile<ELFT>>(File); | ||
| 668 | } | ||
| 669 | |||
| 670 | template <class ELFT> | 689 | template <class ELFT> |
| 671 | void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { | 690 | void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { |
| 672 | if (Flags & SHF_ALLOC) | 691 | if (Flags & SHF_ALLOC) { |
| 673 | relocateAlloc(Buf, BufEnd); | 692 | relocateAlloc(Buf, BufEnd); |
| 674 | else | 693 | return; |
| 675 | relocateNonAlloc<ELFT>(Buf, BufEnd); | 694 | } |
| 676 | } | ||
| 677 | 695 | ||
| 678 | template <class ELFT> | 696 | auto *Sec = cast<InputSection>(this); |
| 679 | void InputSectionBase::relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd) { | 697 | if (Sec->AreRelocsRela) |
| 680 | // scanReloc function in Writer.cpp constructs Relocations | 698 | Sec->relocateNonAlloc<ELFT>(Buf, Sec->template relas<ELFT>()); |
| 681 | // vector only for SHF_ALLOC'ed sections. For other sections, | ||
| 682 | // we handle relocations directly here. | ||
| 683 | auto *IS = cast<InputSection>(this); | ||
| 684 | assert(!(IS->Flags & SHF_ALLOC)); | ||
| 685 | if (IS->AreRelocsRela) | ||
| 686 | IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>()); | ||
| 687 | else | 699 | else |
| 688 | IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>()); | 700 | Sec->relocateNonAlloc<ELFT>(Buf, Sec->template rels<ELFT>()); |
| 689 | } | 701 | } |
| 690 | 702 | ||
| 691 | void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { | 703 | void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { |
| 692 | assert(Flags & SHF_ALLOC); | 704 | assert(Flags & SHF_ALLOC); |
| 693 | const unsigned Bits = Config->Wordsize * 8; | 705 | const unsigned Bits = Config->Wordsize * 8; |
| 706 | |||
| 694 | for (const Relocation &Rel : Relocations) { | 707 | for (const Relocation &Rel : Relocations) { |
| 695 | uint64_t Offset = getOffset(Rel.Offset); | 708 | uint64_t Offset = getOffset(Rel.Offset); |
| 696 | uint8_t *BufLoc = Buf + Offset; | 709 | uint8_t *BufLoc = Buf + Offset; |
| 697 | uint32_t Type = Rel.Type; | 710 | RelType Type = Rel.Type; |
| 698 | 711 | ||
| 699 | uint64_t AddrLoc = getOutputSection()->Addr + Offset; | 712 | uint64_t AddrLoc = getOutputSection()->Addr + Offset; |
| 700 | RelExpr Expr = Rel.Expr; | 713 | RelExpr Expr = Rel.Expr; |
| ... | @@ -735,7 +748,7 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { | ... | @@ -735,7 +748,7 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { |
| 735 | } | 748 | } |
| 736 | 749 | ||
| 737 | template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { | 750 | template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { |
| 738 | if (this->Type == SHT_NOBITS) | 751 | if (Type == SHT_NOBITS) |
| 739 | return; | 752 | return; |
| 740 | 753 | ||
| 741 | if (auto *S = dyn_cast<SyntheticSection>(this)) { | 754 | if (auto *S = dyn_cast<SyntheticSection>(this)) { |
| ... | @@ -745,19 +758,17 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { | ... | @@ -745,19 +758,17 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { |
| 745 | 758 | ||
| 746 | // If -r or --emit-relocs is given, then an InputSection | 759 | // If -r or --emit-relocs is given, then an InputSection |
| 747 | // may be a relocation section. | 760 | // may be a relocation section. |
| 748 | if (this->Type == SHT_RELA) { | 761 | if (Type == SHT_RELA) { |
| 749 | copyRelocations<ELFT>(Buf + OutSecOff, | 762 | copyRelocations<ELFT>(Buf + OutSecOff, getDataAs<typename ELFT::Rela>()); |
| 750 | this->template getDataAs<typename ELFT::Rela>()); | ||
| 751 | return; | 763 | return; |
| 752 | } | 764 | } |
| 753 | if (this->Type == SHT_REL) { | 765 | if (Type == SHT_REL) { |
| 754 | copyRelocations<ELFT>(Buf + OutSecOff, | 766 | copyRelocations<ELFT>(Buf + OutSecOff, getDataAs<typename ELFT::Rel>()); |
| 755 | this->template getDataAs<typename ELFT::Rel>()); | ||
| 756 | return; | 767 | return; |
| 757 | } | 768 | } |
| 758 | 769 | ||
| 759 | // If -r is given, we may have a SHT_GROUP section. | 770 | // If -r is given, we may have a SHT_GROUP section. |
| 760 | if (this->Type == SHT_GROUP) { | 771 | if (Type == SHT_GROUP) { |
| 761 | copyShtGroup<ELFT>(Buf + OutSecOff); | 772 | copyShtGroup<ELFT>(Buf + OutSecOff); |
| 762 | return; | 773 | return; |
| 763 | } | 774 | } |
| ... | @@ -766,34 +777,25 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { | ... | @@ -766,34 +777,25 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { |
| 766 | // and then apply relocations. | 777 | // and then apply relocations. |
| 767 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); | 778 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); |
| 768 | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); | 779 | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); |
| 769 | this->relocate<ELFT>(Buf, BufEnd); | 780 | relocate<ELFT>(Buf, BufEnd); |
| 770 | } | 781 | } |
| 771 | 782 | ||
| 772 | void InputSection::replace(InputSection *Other) { | 783 | void InputSection::replace(InputSection *Other) { |
| 773 | this->Alignment = std::max(this->Alignment, Other->Alignment); | 784 | Alignment = std::max(Alignment, Other->Alignment); |
| 774 | Other->Repl = this->Repl; | 785 | Other->Repl = Repl; |
| 775 | Other->Live = false; | 786 | Other->Live = false; |
| 776 | } | 787 | } |
| 777 | 788 | ||
| 778 | template <class ELFT> | 789 | template <class ELFT> |
| 779 | EhInputSection::EhInputSection(elf::ObjectFile<ELFT> *F, | 790 | EhInputSection::EhInputSection(ObjFile<ELFT> &F, |
| 780 | const typename ELFT::Shdr *Header, | 791 | const typename ELFT::Shdr &Header, |
| 781 | StringRef Name) | 792 | StringRef Name) |
| 782 | : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) { | 793 | : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) {} |
| 783 | // Mark .eh_frame sections as live by default because there are | ||
| 784 | // usually no relocations that point to .eh_frames. Otherwise, | ||
| 785 | // the garbage collector would drop all .eh_frame sections. | ||
| 786 | this->Live = true; | ||
| 787 | } | ||
| 788 | 794 | ||
| 789 | SyntheticSection *EhInputSection::getParent() const { | 795 | SyntheticSection *EhInputSection::getParent() const { |
| 790 | return cast_or_null<SyntheticSection>(Parent); | 796 | return cast_or_null<SyntheticSection>(Parent); |
| 791 | } | 797 | } |
| 792 | 798 | ||
| 793 | bool EhInputSection::classof(const SectionBase *S) { | ||
| 794 | return S->kind() == InputSectionBase::EHFrame; | ||
| 795 | } | ||
| 796 | |||
| 797 | // Returns the index of the first relocation that points to a region between | 799 | // Returns the index of the first relocation that points to a region between |
| 798 | // Begin and Begin+Size. | 800 | // Begin and Begin+Size. |
| 799 | template <class IntTy, class RelTy> | 801 | template <class IntTy, class RelTy> |
| ... | @@ -817,26 +819,21 @@ static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels, | ... | @@ -817,26 +819,21 @@ static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels, |
| 817 | // This function splits an input section into records and returns them. | 819 | // This function splits an input section into records and returns them. |
| 818 | template <class ELFT> void EhInputSection::split() { | 820 | template <class ELFT> void EhInputSection::split() { |
| 819 | // Early exit if already split. | 821 | // Early exit if already split. |
| 820 | if (!this->Pieces.empty()) | 822 | if (!Pieces.empty()) |
| 821 | return; | 823 | return; |
| 822 | 824 | ||
| 823 | if (this->NumRelocations) { | 825 | if (AreRelocsRela) |
| 824 | if (this->AreRelocsRela) | 826 | split<ELFT>(relas<ELFT>()); |
| 825 | split<ELFT>(this->relas<ELFT>()); | 827 | else |
| 826 | else | 828 | split<ELFT>(rels<ELFT>()); |
| 827 | split<ELFT>(this->rels<ELFT>()); | ||
| 828 | return; | ||
| 829 | } | ||
| 830 | split<ELFT>(makeArrayRef<typename ELFT::Rela>(nullptr, nullptr)); | ||
| 831 | } | 829 | } |
| 832 | 830 | ||
| 833 | template <class ELFT, class RelTy> | 831 | template <class ELFT, class RelTy> |
| 834 | void EhInputSection::split(ArrayRef<RelTy> Rels) { | 832 | void EhInputSection::split(ArrayRef<RelTy> Rels) { |
| 835 | ArrayRef<uint8_t> Data = this->Data; | ||
| 836 | unsigned RelI = 0; | 833 | unsigned RelI = 0; |
| 837 | for (size_t Off = 0, End = Data.size(); Off != End;) { | 834 | for (size_t Off = 0, End = Data.size(); Off != End;) { |
| 838 | size_t Size = readEhRecordSize<ELFT>(this, Off); | 835 | size_t Size = readEhRecordSize(this, Off); |
| 839 | this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); | 836 | Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); |
| 840 | // The empty record is the end marker. | 837 | // The empty record is the end marker. |
| 841 | if (Size == 4) | 838 | if (Size == 4) |
| 842 | break; | 839 | break; |
| ... | @@ -844,9 +841,8 @@ void EhInputSection::split(ArrayRef<RelTy> Rels) { | ... | @@ -844,9 +841,8 @@ void EhInputSection::split(ArrayRef<RelTy> Rels) { |
| 844 | } | 841 | } |
| 845 | } | 842 | } |
| 846 | 843 | ||
| 847 | static size_t findNull(ArrayRef<uint8_t> A, size_t EntSize) { | 844 | static size_t findNull(StringRef S, size_t EntSize) { |
| 848 | // Optimize the common case. | 845 | // Optimize the common case. |
| 849 | StringRef S((const char *)A.data(), A.size()); | ||
| 850 | if (EntSize == 1) | 846 | if (EntSize == 1) |
| 851 | return S.find(0); | 847 | return S.find(0); |
| 852 | 848 | ||
| ... | @@ -866,15 +862,17 @@ SyntheticSection *MergeInputSection::getParent() const { | ... | @@ -866,15 +862,17 @@ SyntheticSection *MergeInputSection::getParent() const { |
| 866 | // null-terminated strings. | 862 | // null-terminated strings. |
| 867 | void MergeInputSection::splitStrings(ArrayRef<uint8_t> Data, size_t EntSize) { | 863 | void MergeInputSection::splitStrings(ArrayRef<uint8_t> Data, size_t EntSize) { |
| 868 | size_t Off = 0; | 864 | size_t Off = 0; |
| 869 | bool IsAlloc = this->Flags & SHF_ALLOC; | 865 | bool IsAlloc = Flags & SHF_ALLOC; |
| 870 | while (!Data.empty()) { | 866 | StringRef S = toStringRef(Data); |
| 871 | size_t End = findNull(Data, EntSize); | 867 | |
| 868 | while (!S.empty()) { | ||
| 869 | size_t End = findNull(S, EntSize); | ||
| 872 | if (End == StringRef::npos) | 870 | if (End == StringRef::npos) |
| 873 | fatal(toString(this) + ": string is not null terminated"); | 871 | fatal(toString(this) + ": string is not null terminated"); |
| 874 | size_t Size = End + EntSize; | 872 | size_t Size = End + EntSize; |
| 875 | Pieces.emplace_back(Off, !IsAlloc); | 873 | |
| 876 | Hashes.push_back(hash_value(toStringRef(Data.slice(0, Size)))); | 874 | Pieces.emplace_back(Off, xxHash64(S.substr(0, Size)), !IsAlloc); |
| 877 | Data = Data.slice(Size); | 875 | S = S.substr(Size); |
| 878 | Off += Size; | 876 | Off += Size; |
| 879 | } | 877 | } |
| 880 | } | 878 | } |
| ... | @@ -885,40 +883,42 @@ void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data, | ... | @@ -885,40 +883,42 @@ void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data, |
| 885 | size_t EntSize) { | 883 | size_t EntSize) { |
| 886 | size_t Size = Data.size(); | 884 | size_t Size = Data.size(); |
| 887 | assert((Size % EntSize) == 0); | 885 | assert((Size % EntSize) == 0); |
| 888 | bool IsAlloc = this->Flags & SHF_ALLOC; | 886 | bool IsAlloc = Flags & SHF_ALLOC; |
| 889 | for (unsigned I = 0, N = Size; I != N; I += EntSize) { | 887 | |
| 890 | Hashes.push_back(hash_value(toStringRef(Data.slice(I, EntSize)))); | 888 | for (size_t I = 0; I != Size; I += EntSize) |
| 891 | Pieces.emplace_back(I, !IsAlloc); | 889 | Pieces.emplace_back(I, xxHash64(toStringRef(Data.slice(I, EntSize))), |
| 892 | } | 890 | !IsAlloc); |
| 893 | } | 891 | } |
| 894 | 892 | ||
| 895 | template <class ELFT> | 893 | template <class ELFT> |
| 896 | MergeInputSection::MergeInputSection(elf::ObjectFile<ELFT> *F, | 894 | MergeInputSection::MergeInputSection(ObjFile<ELFT> &F, |
| 897 | const typename ELFT::Shdr *Header, | 895 | const typename ELFT::Shdr &Header, |
| 898 | StringRef Name) | 896 | StringRef Name) |
| 899 | : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} | 897 | : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} |
| 900 | 898 | ||
| 899 | MergeInputSection::MergeInputSection(uint64_t Flags, uint32_t Type, | ||
| 900 | uint64_t Entsize, ArrayRef<uint8_t> Data, | ||
| 901 | StringRef Name) | ||
| 902 | : InputSectionBase(nullptr, Flags, Type, Entsize, /*Link*/ 0, /*Info*/ 0, | ||
| 903 | /*Alignment*/ Entsize, Data, Name, SectionBase::Merge) {} | ||
| 904 | |||
| 901 | // This function is called after we obtain a complete list of input sections | 905 | // This function is called after we obtain a complete list of input sections |
| 902 | // that need to be linked. This is responsible to split section contents | 906 | // that need to be linked. This is responsible to split section contents |
| 903 | // into small chunks for further processing. | 907 | // into small chunks for further processing. |
| 904 | // | 908 | // |
| 905 | // Note that this function is called from parallel_for_each. This must be | 909 | // Note that this function is called from parallelForEach. This must be |
| 906 | // thread-safe (i.e. no memory allocation from the pools). | 910 | // thread-safe (i.e. no memory allocation from the pools). |
| 907 | void MergeInputSection::splitIntoPieces() { | 911 | void MergeInputSection::splitIntoPieces() { |
| 908 | ArrayRef<uint8_t> Data = this->Data; | 912 | assert(Pieces.empty()); |
| 909 | uint64_t EntSize = this->Entsize; | 913 | |
| 910 | if (this->Flags & SHF_STRINGS) | 914 | if (Flags & SHF_STRINGS) |
| 911 | splitStrings(Data, EntSize); | 915 | splitStrings(Data, Entsize); |
| 912 | else | 916 | else |
| 913 | splitNonStrings(Data, EntSize); | 917 | splitNonStrings(Data, Entsize); |
| 914 | 918 | ||
| 915 | if (Config->GcSections && (this->Flags & SHF_ALLOC)) | 919 | if (Config->GcSections && (Flags & SHF_ALLOC)) |
| 916 | for (uint64_t Off : LiveOffsets) | 920 | for (uint64_t Off : LiveOffsets) |
| 917 | this->getSectionPiece(Off)->Live = true; | 921 | getSectionPiece(Off)->Live = true; |
| 918 | } | ||
| 919 | |||
| 920 | bool MergeInputSection::classof(const SectionBase *S) { | ||
| 921 | return S->kind() == InputSectionBase::Merge; | ||
| 922 | } | 922 | } |
| 923 | 923 | ||
| 924 | // Do binary search to get a section piece at a given input offset. | 924 | // Do binary search to get a section piece at a given input offset. |
| ... | @@ -941,8 +941,7 @@ static It fastUpperBound(It First, It Last, const T &Value, Compare Comp) { | ... | @@ -941,8 +941,7 @@ static It fastUpperBound(It First, It Last, const T &Value, Compare Comp) { |
| 941 | } | 941 | } |
| 942 | 942 | ||
| 943 | const SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) const { | 943 | const SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) const { |
| 944 | uint64_t Size = this->Data.size(); | 944 | if (Data.size() <= Offset) |
| 945 | if (Offset >= Size) | ||
| 946 | fatal(toString(this) + ": entry is past the end of the section"); | 945 | fatal(toString(this) + ": entry is past the end of the section"); |
| 947 | 946 | ||
| 948 | // Find the element this offset points to. | 947 | // Find the element this offset points to. |
| ... | @@ -957,24 +956,24 @@ const SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) const { | ... | @@ -957,24 +956,24 @@ const SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) const { |
| 957 | // Because contents of a mergeable section is not contiguous in output, | 956 | // Because contents of a mergeable section is not contiguous in output, |
| 958 | // it is not just an addition to a base output offset. | 957 | // it is not just an addition to a base output offset. |
| 959 | uint64_t MergeInputSection::getOffset(uint64_t Offset) const { | 958 | uint64_t MergeInputSection::getOffset(uint64_t Offset) const { |
| 959 | if (!Live) | ||
| 960 | return 0; | ||
| 961 | |||
| 960 | // Initialize OffsetMap lazily. | 962 | // Initialize OffsetMap lazily. |
| 961 | llvm::call_once(InitOffsetMap, [&] { | 963 | llvm::call_once(InitOffsetMap, [&] { |
| 962 | OffsetMap.reserve(Pieces.size()); | 964 | OffsetMap.reserve(Pieces.size()); |
| 963 | for (const SectionPiece &Piece : Pieces) | 965 | for (size_t I = 0; I < Pieces.size(); ++I) |
| 964 | OffsetMap[Piece.InputOff] = Piece.OutputOff; | 966 | OffsetMap[Pieces[I].InputOff] = I; |
| 965 | }); | 967 | }); |
| 966 | 968 | ||
| 967 | // Find a string starting at a given offset. | 969 | // Find a string starting at a given offset. |
| 968 | auto It = OffsetMap.find(Offset); | 970 | auto It = OffsetMap.find(Offset); |
| 969 | if (It != OffsetMap.end()) | 971 | if (It != OffsetMap.end()) |
| 970 | return It->second; | 972 | return Pieces[It->second].OutputOff; |
| 971 | |||
| 972 | if (!this->Live) | ||
| 973 | return 0; | ||
| 974 | 973 | ||
| 975 | // If Offset is not at beginning of a section piece, it is not in the map. | 974 | // If Offset is not at beginning of a section piece, it is not in the map. |
| 976 | // In that case we need to search from the original section piece vector. | 975 | // In that case we need to search from the original section piece vector. |
| 977 | const SectionPiece &Piece = *this->getSectionPiece(Offset); | 976 | const SectionPiece &Piece = *getSectionPiece(Offset); |
| 978 | if (!Piece.Live) | 977 | if (!Piece.Live) |
| 979 | return 0; | 978 | return 0; |
| 980 | 979 | ||
| ... | @@ -982,57 +981,42 @@ uint64_t MergeInputSection::getOffset(uint64_t Offset) const { | ... | @@ -982,57 +981,42 @@ uint64_t MergeInputSection::getOffset(uint64_t Offset) const { |
| 982 | return Piece.OutputOff + Addend; | 981 | return Piece.OutputOff + Addend; |
| 983 | } | 982 | } |
| 984 | 983 | ||
| 985 | template InputSection::InputSection(elf::ObjectFile<ELF32LE> *, | 984 | template InputSection::InputSection(ObjFile<ELF32LE> &, const ELF32LE::Shdr &, |
| 986 | const ELF32LE::Shdr *, StringRef); | 985 | StringRef); |
| 987 | template InputSection::InputSection(elf::ObjectFile<ELF32BE> *, | 986 | template InputSection::InputSection(ObjFile<ELF32BE> &, const ELF32BE::Shdr &, |
| 988 | const ELF32BE::Shdr *, StringRef); | 987 | StringRef); |
| 989 | template InputSection::InputSection(elf::ObjectFile<ELF64LE> *, | 988 | template InputSection::InputSection(ObjFile<ELF64LE> &, const ELF64LE::Shdr &, |
| 990 | const ELF64LE::Shdr *, StringRef); | 989 | StringRef); |
| 991 | template InputSection::InputSection(elf::ObjectFile<ELF64BE> *, | 990 | template InputSection::InputSection(ObjFile<ELF64BE> &, const ELF64BE::Shdr &, |
| 992 | const ELF64BE::Shdr *, StringRef); | 991 | StringRef); |
| 993 | 992 | ||
| 994 | template std::string InputSectionBase::getLocation<ELF32LE>(uint64_t); | 993 | template std::string InputSectionBase::getLocation<ELF32LE>(uint64_t); |
| 995 | template std::string InputSectionBase::getLocation<ELF32BE>(uint64_t); | 994 | template std::string InputSectionBase::getLocation<ELF32BE>(uint64_t); |
| 996 | template std::string InputSectionBase::getLocation<ELF64LE>(uint64_t); | 995 | template std::string InputSectionBase::getLocation<ELF64LE>(uint64_t); |
| 997 | template std::string InputSectionBase::getLocation<ELF64BE>(uint64_t); | 996 | template std::string InputSectionBase::getLocation<ELF64BE>(uint64_t); |
| 998 | 997 | ||
| 999 | template std::string InputSectionBase::getSrcMsg<ELF32LE>(uint64_t); | ||
| 1000 | template std::string InputSectionBase::getSrcMsg<ELF32BE>(uint64_t); | ||
| 1001 | template std::string InputSectionBase::getSrcMsg<ELF64LE>(uint64_t); | ||
| 1002 | template std::string InputSectionBase::getSrcMsg<ELF64BE>(uint64_t); | ||
| 1003 | |||
| 1004 | template std::string InputSectionBase::getObjMsg<ELF32LE>(uint64_t); | ||
| 1005 | template std::string InputSectionBase::getObjMsg<ELF32BE>(uint64_t); | ||
| 1006 | template std::string InputSectionBase::getObjMsg<ELF64LE>(uint64_t); | ||
| 1007 | template std::string InputSectionBase::getObjMsg<ELF64BE>(uint64_t); | ||
| 1008 | |||
| 1009 | template void InputSection::writeTo<ELF32LE>(uint8_t *); | 998 | template void InputSection::writeTo<ELF32LE>(uint8_t *); |
| 1010 | template void InputSection::writeTo<ELF32BE>(uint8_t *); | 999 | template void InputSection::writeTo<ELF32BE>(uint8_t *); |
| 1011 | template void InputSection::writeTo<ELF64LE>(uint8_t *); | 1000 | template void InputSection::writeTo<ELF64LE>(uint8_t *); |
| 1012 | template void InputSection::writeTo<ELF64BE>(uint8_t *); | 1001 | template void InputSection::writeTo<ELF64BE>(uint8_t *); |
| 1013 | 1002 | ||
| 1014 | template elf::ObjectFile<ELF32LE> *InputSectionBase::getFile<ELF32LE>() const; | 1003 | template MergeInputSection::MergeInputSection(ObjFile<ELF32LE> &, |
| 1015 | template elf::ObjectFile<ELF32BE> *InputSectionBase::getFile<ELF32BE>() const; | 1004 | const ELF32LE::Shdr &, StringRef); |
| 1016 | template elf::ObjectFile<ELF64LE> *InputSectionBase::getFile<ELF64LE>() const; | 1005 | template MergeInputSection::MergeInputSection(ObjFile<ELF32BE> &, |
| 1017 | template elf::ObjectFile<ELF64BE> *InputSectionBase::getFile<ELF64BE>() const; | 1006 | const ELF32BE::Shdr &, StringRef); |
| 1018 | 1007 | template MergeInputSection::MergeInputSection(ObjFile<ELF64LE> &, | |
| 1019 | template MergeInputSection::MergeInputSection(elf::ObjectFile<ELF32LE> *, | 1008 | const ELF64LE::Shdr &, StringRef); |
| 1020 | const ELF32LE::Shdr *, StringRef); | 1009 | template MergeInputSection::MergeInputSection(ObjFile<ELF64BE> &, |
| 1021 | template MergeInputSection::MergeInputSection(elf::ObjectFile<ELF32BE> *, | 1010 | const ELF64BE::Shdr &, StringRef); |
| 1022 | const ELF32BE::Shdr *, StringRef); | 1011 | |
| 1023 | template MergeInputSection::MergeInputSection(elf::ObjectFile<ELF64LE> *, | 1012 | template EhInputSection::EhInputSection(ObjFile<ELF32LE> &, |
| 1024 | const ELF64LE::Shdr *, StringRef); | 1013 | const ELF32LE::Shdr &, StringRef); |
| 1025 | template MergeInputSection::MergeInputSection(elf::ObjectFile<ELF64BE> *, | 1014 | template EhInputSection::EhInputSection(ObjFile<ELF32BE> &, |
| 1026 | const ELF64BE::Shdr *, StringRef); | 1015 | const ELF32BE::Shdr &, StringRef); |
| 1027 | 1016 | template EhInputSection::EhInputSection(ObjFile<ELF64LE> &, | |
| 1028 | template EhInputSection::EhInputSection(elf::ObjectFile<ELF32LE> *, | 1017 | const ELF64LE::Shdr &, StringRef); |
| 1029 | const ELF32LE::Shdr *, StringRef); | 1018 | template EhInputSection::EhInputSection(ObjFile<ELF64BE> &, |
| 1030 | template EhInputSection::EhInputSection(elf::ObjectFile<ELF32BE> *, | 1019 | const ELF64BE::Shdr &, StringRef); |
| 1031 | const ELF32BE::Shdr *, StringRef); | ||
| 1032 | template EhInputSection::EhInputSection(elf::ObjectFile<ELF64LE> *, | ||
| 1033 | const ELF64LE::Shdr *, StringRef); | ||
| 1034 | template EhInputSection::EhInputSection(elf::ObjectFile<ELF64BE> *, | ||
| 1035 | const ELF64BE::Shdr *, StringRef); | ||
| 1036 | 1020 | ||
| 1037 | template void EhInputSection::split<ELF32LE>(); | 1021 | template void EhInputSection::split<ELF32LE>(); |
| 1038 | template void EhInputSection::split<ELF32BE>(); | 1022 | template void EhInputSection::split<ELF32BE>(); |
deps/lld/ELF/InputSection.h+109-94| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | #include "Config.h" | 13 | #include "Config.h" |
| 14 | #include "Relocations.h" | 14 | #include "Relocations.h" |
| 15 | #include "Thunks.h" | 15 | #include "Thunks.h" |
| 16 | #include "lld/Core/LLVM.h" | 16 | #include "lld/Common/LLVM.h" |
| 17 | #include "llvm/ADT/CachedHashString.h" | 17 | #include "llvm/ADT/CachedHashString.h" |
| 18 | #include "llvm/ADT/DenseSet.h" | 18 | #include "llvm/ADT/DenseSet.h" |
| 19 | #include "llvm/ADT/TinyPtrVector.h" | 19 | #include "llvm/ADT/TinyPtrVector.h" |
| ... | @@ -24,15 +24,13 @@ | ... | @@ -24,15 +24,13 @@ |
| 24 | namespace lld { | 24 | namespace lld { |
| 25 | namespace elf { | 25 | namespace elf { |
| 26 | 26 | ||
| 27 | class DefinedCommon; | 27 | class Symbol; |
| 28 | class SymbolBody; | ||
| 29 | struct SectionPiece; | 28 | struct SectionPiece; |
| 30 | 29 | ||
| 31 | class DefinedRegular; | 30 | class Defined; |
| 32 | class SyntheticSection; | 31 | class SyntheticSection; |
| 33 | template <class ELFT> class EhFrameSection; | ||
| 34 | class MergeSyntheticSection; | 32 | class MergeSyntheticSection; |
| 35 | template <class ELFT> class ObjectFile; | 33 | template <class ELFT> class ObjFile; |
| 36 | class OutputSection; | 34 | class OutputSection; |
| 37 | 35 | ||
| 38 | // This is the base class of all sections that lld handles. Some are sections in | 36 | // This is the base class of all sections that lld handles. Some are sections in |
| ... | @@ -47,6 +45,13 @@ public: | ... | @@ -47,6 +45,13 @@ public: |
| 47 | 45 | ||
| 48 | StringRef Name; | 46 | StringRef Name; |
| 49 | 47 | ||
| 48 | // This pointer points to the "real" instance of this instance. | ||
| 49 | // Usually Repl == this. However, if ICF merges two sections, | ||
| 50 | // Repl pointer of one section points to another section. So, | ||
| 51 | // if you need to get a pointer to this instance, do not use | ||
| 52 | // this but instead this->Repl. | ||
| 53 | SectionBase *Repl; | ||
| 54 | |||
| 50 | unsigned SectionKind : 3; | 55 | unsigned SectionKind : 3; |
| 51 | 56 | ||
| 52 | // The next two bit fields are only used by InputSectionBase, but we | 57 | // The next two bit fields are only used by InputSectionBase, but we |
| ... | @@ -54,12 +59,12 @@ public: | ... | @@ -54,12 +59,12 @@ public: |
| 54 | 59 | ||
| 55 | // The garbage collector sets sections' Live bits. | 60 | // The garbage collector sets sections' Live bits. |
| 56 | // If GC is disabled, all sections are considered live by default. | 61 | // If GC is disabled, all sections are considered live by default. |
| 57 | unsigned Live : 1; // for garbage collection | 62 | unsigned Live : 1; |
| 58 | unsigned Assigned : 1; // for linker script | ||
| 59 | 63 | ||
| 60 | uint32_t Alignment; | 64 | unsigned Bss : 1; |
| 61 | 65 | ||
| 62 | // These corresponds to the fields in Elf_Shdr. | 66 | // These corresponds to the fields in Elf_Shdr. |
| 67 | uint32_t Alignment; | ||
| 63 | uint64_t Flags; | 68 | uint64_t Flags; |
| 64 | uint64_t Entsize; | 69 | uint64_t Entsize; |
| 65 | uint32_t Type; | 70 | uint32_t Type; |
| ... | @@ -75,45 +80,20 @@ public: | ... | @@ -75,45 +80,20 @@ public: |
| 75 | // section. | 80 | // section. |
| 76 | uint64_t getOffset(uint64_t Offset) const; | 81 | uint64_t getOffset(uint64_t Offset) const; |
| 77 | 82 | ||
| 78 | uint64_t getOffset(const DefinedRegular &Sym) const; | ||
| 79 | |||
| 80 | protected: | 83 | protected: |
| 81 | SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags, | 84 | SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags, |
| 82 | uint64_t Entsize, uint64_t Alignment, uint32_t Type, | 85 | uint64_t Entsize, uint64_t Alignment, uint32_t Type, |
| 83 | uint32_t Info, uint32_t Link) | 86 | uint32_t Info, uint32_t Link) |
| 84 | : Name(Name), SectionKind(SectionKind), Alignment(Alignment), | 87 | : Name(Name), Repl(this), SectionKind(SectionKind), Live(false), |
| 85 | Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info) { | 88 | Bss(false), Alignment(Alignment), Flags(Flags), Entsize(Entsize), |
| 86 | Live = false; | 89 | Type(Type), Link(Link), Info(Info) {} |
| 87 | Assigned = false; | ||
| 88 | } | ||
| 89 | }; | 90 | }; |
| 90 | 91 | ||
| 91 | // This corresponds to a section of an input file. | 92 | // This corresponds to a section of an input file. |
| 92 | class InputSectionBase : public SectionBase { | 93 | class InputSectionBase : public SectionBase { |
| 93 | public: | 94 | public: |
| 94 | static bool classof(const SectionBase *S); | ||
| 95 | |||
| 96 | // The file this section is from. | ||
| 97 | InputFile *File; | ||
| 98 | |||
| 99 | ArrayRef<uint8_t> Data; | ||
| 100 | uint64_t getOffsetInFile() const; | ||
| 101 | |||
| 102 | static InputSectionBase Discarded; | ||
| 103 | |||
| 104 | InputSectionBase() | ||
| 105 | : SectionBase(Regular, "", /*Flags*/ 0, /*Entsize*/ 0, /*Alignment*/ 0, | ||
| 106 | /*Type*/ 0, | ||
| 107 | /*Info*/ 0, /*Link*/ 0), | ||
| 108 | Repl(this) { | ||
| 109 | Live = false; | ||
| 110 | Assigned = false; | ||
| 111 | NumRelocations = 0; | ||
| 112 | AreRelocsRela = false; | ||
| 113 | } | ||
| 114 | |||
| 115 | template <class ELFT> | 95 | template <class ELFT> |
| 116 | InputSectionBase(ObjectFile<ELFT> *File, const typename ELFT::Shdr *Header, | 96 | InputSectionBase(ObjFile<ELFT> &File, const typename ELFT::Shdr &Header, |
| 117 | StringRef Name, Kind SectionKind); | 97 | StringRef Name, Kind SectionKind); |
| 118 | 98 | ||
| 119 | InputSectionBase(InputFile *File, uint64_t Flags, uint32_t Type, | 99 | InputSectionBase(InputFile *File, uint64_t Flags, uint32_t Type, |
| ... | @@ -121,6 +101,33 @@ public: | ... | @@ -121,6 +101,33 @@ public: |
| 121 | uint32_t Alignment, ArrayRef<uint8_t> Data, StringRef Name, | 101 | uint32_t Alignment, ArrayRef<uint8_t> Data, StringRef Name, |
| 122 | Kind SectionKind); | 102 | Kind SectionKind); |
| 123 | 103 | ||
| 104 | static bool classof(const SectionBase *S) { return S->kind() != Output; } | ||
| 105 | |||
| 106 | // The file which contains this section. It's dynamic type is always | ||
| 107 | // ObjFile<ELFT>, but in order to avoid ELFT, we use InputFile as | ||
| 108 | // its static type. | ||
| 109 | InputFile *File; | ||
| 110 | |||
| 111 | template <class ELFT> ObjFile<ELFT> *getFile() const { | ||
| 112 | return cast_or_null<ObjFile<ELFT>>(File); | ||
| 113 | } | ||
| 114 | |||
| 115 | ArrayRef<uint8_t> Data; | ||
| 116 | uint64_t getOffsetInFile() const; | ||
| 117 | |||
| 118 | // True if this section has already been placed to a linker script | ||
| 119 | // output section. This is needed because, in a linker script, you | ||
| 120 | // can refer to the same section more than once. For example, in | ||
| 121 | // the following linker script, | ||
| 122 | // | ||
| 123 | // .foo : { *(.text) } | ||
| 124 | // .bar : { *(.text) } | ||
| 125 | // | ||
| 126 | // .foo takes all .text sections, and .bar becomes empty. To achieve | ||
| 127 | // this, we need to memorize whether a section has been placed or | ||
| 128 | // not for each input section. | ||
| 129 | bool Assigned = false; | ||
| 130 | |||
| 124 | // Input sections are part of an output section. Special sections | 131 | // Input sections are part of an output section. Special sections |
| 125 | // like .eh_frame and merge sections are first combined into a | 132 | // like .eh_frame and merge sections are first combined into a |
| 126 | // synthetic section that is then added to an output section. In all | 133 | // synthetic section that is then added to an output section. In all |
| ... | @@ -131,12 +138,14 @@ public: | ... | @@ -131,12 +138,14 @@ public: |
| 131 | const void *FirstRelocation = nullptr; | 138 | const void *FirstRelocation = nullptr; |
| 132 | unsigned NumRelocations : 31; | 139 | unsigned NumRelocations : 31; |
| 133 | unsigned AreRelocsRela : 1; | 140 | unsigned AreRelocsRela : 1; |
| 141 | |||
| 134 | template <class ELFT> ArrayRef<typename ELFT::Rel> rels() const { | 142 | template <class ELFT> ArrayRef<typename ELFT::Rel> rels() const { |
| 135 | assert(!AreRelocsRela); | 143 | assert(!AreRelocsRela); |
| 136 | return llvm::makeArrayRef( | 144 | return llvm::makeArrayRef( |
| 137 | static_cast<const typename ELFT::Rel *>(FirstRelocation), | 145 | static_cast<const typename ELFT::Rel *>(FirstRelocation), |
| 138 | NumRelocations); | 146 | NumRelocations); |
| 139 | } | 147 | } |
| 148 | |||
| 140 | template <class ELFT> ArrayRef<typename ELFT::Rela> relas() const { | 149 | template <class ELFT> ArrayRef<typename ELFT::Rela> relas() const { |
| 141 | assert(AreRelocsRela); | 150 | assert(AreRelocsRela); |
| 142 | return llvm::makeArrayRef( | 151 | return llvm::makeArrayRef( |
| ... | @@ -144,38 +153,33 @@ public: | ... | @@ -144,38 +153,33 @@ public: |
| 144 | NumRelocations); | 153 | NumRelocations); |
| 145 | } | 154 | } |
| 146 | 155 | ||
| 147 | // This pointer points to the "real" instance of this instance. | ||
| 148 | // Usually Repl == this. However, if ICF merges two sections, | ||
| 149 | // Repl pointer of one section points to another section. So, | ||
| 150 | // if you need to get a pointer to this instance, do not use | ||
| 151 | // this but instead this->Repl. | ||
| 152 | InputSectionBase *Repl; | ||
| 153 | |||
| 154 | // InputSections that are dependent on us (reverse dependency for GC) | 156 | // InputSections that are dependent on us (reverse dependency for GC) |
| 155 | llvm::TinyPtrVector<InputSectionBase *> DependentSections; | 157 | llvm::TinyPtrVector<InputSection *> DependentSections; |
| 156 | 158 | ||
| 157 | // Returns the size of this section (even if this is a common or BSS.) | 159 | // Returns the size of this section (even if this is a common or BSS.) |
| 158 | size_t getSize() const; | 160 | size_t getSize() const; |
| 159 | 161 | ||
| 160 | template <class ELFT> ObjectFile<ELFT> *getFile() const; | ||
| 161 | |||
| 162 | template <class ELFT> llvm::object::ELFFile<ELFT> getObj() const { | ||
| 163 | return getFile<ELFT>()->getObj(); | ||
| 164 | } | ||
| 165 | |||
| 166 | InputSection *getLinkOrderDep() const; | 162 | InputSection *getLinkOrderDep() const; |
| 167 | 163 | ||
| 168 | void uncompress(); | 164 | // Compilers emit zlib-compressed debug sections if the -gz option |
| 165 | // is given. This function checks if this section is compressed, and | ||
| 166 | // if so, decompress in memory. | ||
| 167 | void maybeUncompress(); | ||
| 169 | 168 | ||
| 170 | // Returns a source location string. Used to construct an error message. | 169 | // Returns a source location string. Used to construct an error message. |
| 171 | template <class ELFT> std::string getLocation(uint64_t Offset); | 170 | template <class ELFT> std::string getLocation(uint64_t Offset); |
| 172 | template <class ELFT> std::string getSrcMsg(uint64_t Offset); | 171 | std::string getSrcMsg(const Symbol &Sym, uint64_t Offset); |
| 173 | template <class ELFT> std::string getObjMsg(uint64_t Offset); | 172 | std::string getObjMsg(uint64_t Offset); |
| 174 | 173 | ||
| 174 | // Each section knows how to relocate itself. These functions apply | ||
| 175 | // relocations, assuming that Buf points to this section's copy in | ||
| 176 | // the mmap'ed output buffer. | ||
| 175 | template <class ELFT> void relocate(uint8_t *Buf, uint8_t *BufEnd); | 177 | template <class ELFT> void relocate(uint8_t *Buf, uint8_t *BufEnd); |
| 176 | void relocateAlloc(uint8_t *Buf, uint8_t *BufEnd); | 178 | void relocateAlloc(uint8_t *Buf, uint8_t *BufEnd); |
| 177 | template <class ELFT> void relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd); | ||
| 178 | 179 | ||
| 180 | // The native ELF reloc data type is not very convenient to handle. | ||
| 181 | // So we convert ELF reloc records to our own records in Relocations.cpp. | ||
| 182 | // This vector contains such "cooked" relocations. | ||
| 179 | std::vector<Relocation> Relocations; | 183 | std::vector<Relocation> Relocations; |
| 180 | 184 | ||
| 181 | template <typename T> llvm::ArrayRef<T> getDataAs() const { | 185 | template <typename T> llvm::ArrayRef<T> getDataAs() const { |
| ... | @@ -183,36 +187,46 @@ public: | ... | @@ -183,36 +187,46 @@ public: |
| 183 | assert(S % sizeof(T) == 0); | 187 | assert(S % sizeof(T) == 0); |
| 184 | return llvm::makeArrayRef<T>((const T *)Data.data(), S / sizeof(T)); | 188 | return llvm::makeArrayRef<T>((const T *)Data.data(), S / sizeof(T)); |
| 185 | } | 189 | } |
| 190 | |||
| 191 | private: | ||
| 192 | // A pointer that owns uncompressed data if a section is compressed by zlib. | ||
| 193 | // Since the feature is not used often, this is usually a nullptr. | ||
| 194 | std::unique_ptr<char[]> UncompressBuf; | ||
| 186 | }; | 195 | }; |
| 187 | 196 | ||
| 188 | // SectionPiece represents a piece of splittable section contents. | 197 | // SectionPiece represents a piece of splittable section contents. |
| 189 | // We allocate a lot of these and binary search on them. This means that they | 198 | // We allocate a lot of these and binary search on them. This means that they |
| 190 | // have to be as compact as possible, which is why we don't store the size (can | 199 | // have to be as compact as possible, which is why we don't store the size (can |
| 191 | // be found by looking at the next one) and put the hash in a side table. | 200 | // be found by looking at the next one). |
| 192 | struct SectionPiece { | 201 | struct SectionPiece { |
| 193 | SectionPiece(size_t Off, bool Live = false) | 202 | SectionPiece(size_t Off, uint32_t Hash, bool Live) |
| 194 | : InputOff(Off), OutputOff(-1), Live(Live || !Config->GcSections) {} | 203 | : InputOff(Off), Hash(Hash), OutputOff(-1), |
| 195 | 204 | Live(Live || !Config->GcSections) {} | |
| 196 | size_t InputOff; | 205 | |
| 197 | ssize_t OutputOff : 8 * sizeof(ssize_t) - 1; | 206 | uint32_t InputOff; |
| 198 | size_t Live : 1; | 207 | uint32_t Hash; |
| 208 | int64_t OutputOff : 63; | ||
| 209 | uint64_t Live : 1; | ||
| 199 | }; | 210 | }; |
| 200 | static_assert(sizeof(SectionPiece) == 2 * sizeof(size_t), | 211 | |
| 201 | "SectionPiece is too big"); | 212 | static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big"); |
| 202 | 213 | ||
| 203 | // This corresponds to a SHF_MERGE section of an input file. | 214 | // This corresponds to a SHF_MERGE section of an input file. |
| 204 | class MergeInputSection : public InputSectionBase { | 215 | class MergeInputSection : public InputSectionBase { |
| 205 | public: | 216 | public: |
| 206 | template <class ELFT> | 217 | template <class ELFT> |
| 207 | MergeInputSection(ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header, | 218 | MergeInputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header, |
| 208 | StringRef Name); | 219 | StringRef Name); |
| 209 | static bool classof(const SectionBase *S); | 220 | MergeInputSection(uint64_t Flags, uint32_t Type, uint64_t Entsize, |
| 221 | ArrayRef<uint8_t> Data, StringRef Name); | ||
| 222 | |||
| 223 | static bool classof(const SectionBase *S) { return S->kind() == Merge; } | ||
| 210 | void splitIntoPieces(); | 224 | void splitIntoPieces(); |
| 211 | 225 | ||
| 212 | // Mark the piece at a given offset live. Used by GC. | 226 | // Mark the piece at a given offset live. Used by GC. |
| 213 | void markLiveAt(uint64_t Offset) { | 227 | void markLiveAt(uint64_t Offset) { |
| 214 | assert(this->Flags & llvm::ELF::SHF_ALLOC); | 228 | if (this->Flags & llvm::ELF::SHF_ALLOC) |
| 215 | LiveOffsets.insert(Offset); | 229 | LiveOffsets.insert(Offset); |
| 216 | } | 230 | } |
| 217 | 231 | ||
| 218 | // Translate an offset in the input section to an offset | 232 | // Translate an offset in the input section to an offset |
| ... | @@ -228,14 +242,9 @@ public: | ... | @@ -228,14 +242,9 @@ public: |
| 228 | LLVM_ATTRIBUTE_ALWAYS_INLINE | 242 | LLVM_ATTRIBUTE_ALWAYS_INLINE |
| 229 | llvm::CachedHashStringRef getData(size_t I) const { | 243 | llvm::CachedHashStringRef getData(size_t I) const { |
| 230 | size_t Begin = Pieces[I].InputOff; | 244 | size_t Begin = Pieces[I].InputOff; |
| 231 | size_t End; | 245 | size_t End = |
| 232 | if (Pieces.size() - 1 == I) | 246 | (Pieces.size() - 1 == I) ? Data.size() : Pieces[I + 1].InputOff; |
| 233 | End = this->Data.size(); | 247 | return {toStringRef(Data.slice(Begin, End - Begin)), Pieces[I].Hash}; |
| 234 | else | ||
| 235 | End = Pieces[I + 1].InputOff; | ||
| 236 | |||
| 237 | StringRef S = {(const char *)(this->Data.data() + Begin), End - Begin}; | ||
| 238 | return {S, Hashes[I]}; | ||
| 239 | } | 248 | } |
| 240 | 249 | ||
| 241 | // Returns the SectionPiece at a given input section offset. | 250 | // Returns the SectionPiece at a given input section offset. |
| ... | @@ -248,24 +257,23 @@ private: | ... | @@ -248,24 +257,23 @@ private: |
| 248 | void splitStrings(ArrayRef<uint8_t> A, size_t Size); | 257 | void splitStrings(ArrayRef<uint8_t> A, size_t Size); |
| 249 | void splitNonStrings(ArrayRef<uint8_t> A, size_t Size); | 258 | void splitNonStrings(ArrayRef<uint8_t> A, size_t Size); |
| 250 | 259 | ||
| 251 | std::vector<uint32_t> Hashes; | 260 | mutable llvm::DenseMap<uint32_t, uint32_t> OffsetMap; |
| 252 | |||
| 253 | mutable llvm::DenseMap<uint64_t, uint64_t> OffsetMap; | ||
| 254 | mutable llvm::once_flag InitOffsetMap; | 261 | mutable llvm::once_flag InitOffsetMap; |
| 255 | 262 | ||
| 256 | llvm::DenseSet<uint64_t> LiveOffsets; | 263 | llvm::DenseSet<uint64_t> LiveOffsets; |
| 257 | }; | 264 | }; |
| 258 | 265 | ||
| 259 | struct EhSectionPiece : public SectionPiece { | 266 | struct EhSectionPiece { |
| 260 | EhSectionPiece(size_t Off, InputSectionBase *ID, uint32_t Size, | 267 | EhSectionPiece(size_t Off, InputSectionBase *Sec, uint32_t Size, |
| 261 | unsigned FirstRelocation) | 268 | unsigned FirstRelocation) |
| 262 | : SectionPiece(Off, false), ID(ID), Size(Size), | 269 | : InputOff(Off), Sec(Sec), Size(Size), FirstRelocation(FirstRelocation) {} |
| 263 | FirstRelocation(FirstRelocation) {} | ||
| 264 | InputSectionBase *ID; | ||
| 265 | uint32_t Size; | ||
| 266 | uint32_t size() const { return Size; } | ||
| 267 | 270 | ||
| 268 | ArrayRef<uint8_t> data() { return {ID->Data.data() + this->InputOff, Size}; } | 271 | ArrayRef<uint8_t> data() { return {Sec->Data.data() + this->InputOff, Size}; } |
| 272 | |||
| 273 | size_t InputOff; | ||
| 274 | ssize_t OutputOff = -1; | ||
| 275 | InputSectionBase *Sec; | ||
| 276 | uint32_t Size; | ||
| 269 | unsigned FirstRelocation; | 277 | unsigned FirstRelocation; |
| 270 | }; | 278 | }; |
| 271 | 279 | ||
| ... | @@ -273,9 +281,9 @@ struct EhSectionPiece : public SectionPiece { | ... | @@ -273,9 +281,9 @@ struct EhSectionPiece : public SectionPiece { |
| 273 | class EhInputSection : public InputSectionBase { | 281 | class EhInputSection : public InputSectionBase { |
| 274 | public: | 282 | public: |
| 275 | template <class ELFT> | 283 | template <class ELFT> |
| 276 | EhInputSection(ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header, | 284 | EhInputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header, |
| 277 | StringRef Name); | 285 | StringRef Name); |
| 278 | static bool classof(const SectionBase *S); | 286 | static bool classof(const SectionBase *S) { return S->kind() == EHFrame; } |
| 279 | template <class ELFT> void split(); | 287 | template <class ELFT> void split(); |
| 280 | template <class ELFT, class RelTy> void split(ArrayRef<RelTy> Rels); | 288 | template <class ELFT, class RelTy> void split(ArrayRef<RelTy> Rels); |
| 281 | 289 | ||
| ... | @@ -292,10 +300,10 @@ public: | ... | @@ -292,10 +300,10 @@ public: |
| 292 | // .eh_frame. It also includes the synthetic sections themselves. | 300 | // .eh_frame. It also includes the synthetic sections themselves. |
| 293 | class InputSection : public InputSectionBase { | 301 | class InputSection : public InputSectionBase { |
| 294 | public: | 302 | public: |
| 295 | InputSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, | 303 | InputSection(InputFile *F, uint64_t Flags, uint32_t Type, uint32_t Alignment, |
| 296 | ArrayRef<uint8_t> Data, StringRef Name, Kind K = Regular); | 304 | ArrayRef<uint8_t> Data, StringRef Name, Kind K = Regular); |
| 297 | template <class ELFT> | 305 | template <class ELFT> |
| 298 | InputSection(ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header, | 306 | InputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header, |
| 299 | StringRef Name); | 307 | StringRef Name); |
| 300 | 308 | ||
| 301 | // Write this section to a mmap'ed file, assuming Buf is pointing to | 309 | // Write this section to a mmap'ed file, assuming Buf is pointing to |
| ... | @@ -304,8 +312,10 @@ public: | ... | @@ -304,8 +312,10 @@ public: |
| 304 | 312 | ||
| 305 | OutputSection *getParent() const; | 313 | OutputSection *getParent() const; |
| 306 | 314 | ||
| 307 | // The offset from beginning of the output sections this section was assigned | 315 | // This variable has two usages. Initially, it represents an index in the |
| 308 | // to. The writer sets a value. | 316 | // OutputSection's InputSection list, and is used when ordering SHF_LINK_ORDER |
| 317 | // sections. After assignAddresses is called, it represents the offset from | ||
| 318 | // the beginning of the output section this section was assigned to. | ||
| 309 | uint64_t OutSecOff = 0; | 319 | uint64_t OutSecOff = 0; |
| 310 | 320 | ||
| 311 | static bool classof(const SectionBase *S); | 321 | static bool classof(const SectionBase *S); |
| ... | @@ -321,6 +331,8 @@ public: | ... | @@ -321,6 +331,8 @@ public: |
| 321 | // Called by ICF to merge two input sections. | 331 | // Called by ICF to merge two input sections. |
| 322 | void replace(InputSection *Other); | 332 | void replace(InputSection *Other); |
| 323 | 333 | ||
| 334 | static InputSection Discarded; | ||
| 335 | |||
| 324 | private: | 336 | private: |
| 325 | template <class ELFT, class RelTy> | 337 | template <class ELFT, class RelTy> |
| 326 | void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels); | 338 | void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels); |
| ... | @@ -331,6 +343,9 @@ private: | ... | @@ -331,6 +343,9 @@ private: |
| 331 | // The list of all input sections. | 343 | // The list of all input sections. |
| 332 | extern std::vector<InputSectionBase *> InputSections; | 344 | extern std::vector<InputSectionBase *> InputSections; |
| 333 | 345 | ||
| 346 | // Builds section order for handling --symbol-ordering-file. | ||
| 347 | llvm::DenseMap<SectionBase *, int> buildSectionOrder(); | ||
| 348 | |||
| 334 | } // namespace elf | 349 | } // namespace elf |
| 335 | 350 | ||
| 336 | std::string toString(const elf::InputSectionBase *); | 351 | std::string toString(const elf::InputSectionBase *); |
deps/lld/ELF/LTO.cpp+45-18| ... | @@ -9,10 +9,12 @@ | ... | @@ -9,10 +9,12 @@ |
| 9 | 9 | ||
| 10 | #include "LTO.h" | 10 | #include "LTO.h" |
| 11 | #include "Config.h" | 11 | #include "Config.h" |
| 12 | #include "Error.h" | ||
| 13 | #include "InputFiles.h" | 12 | #include "InputFiles.h" |
| 13 | #include "LinkerScript.h" | ||
| 14 | #include "SymbolTable.h" | ||
| 14 | #include "Symbols.h" | 15 | #include "Symbols.h" |
| 15 | #include "lld/Core/TargetOptionsCommandFlags.h" | 16 | #include "lld/Common/ErrorHandler.h" |
| 17 | #include "lld/Common/TargetOptionsCommandFlags.h" | ||
| 16 | #include "llvm/ADT/STLExtras.h" | 18 | #include "llvm/ADT/STLExtras.h" |
| 17 | #include "llvm/ADT/SmallString.h" | 19 | #include "llvm/ADT/SmallString.h" |
| 18 | #include "llvm/ADT/StringRef.h" | 20 | #include "llvm/ADT/StringRef.h" |
| ... | @@ -60,10 +62,8 @@ static void diagnosticHandler(const DiagnosticInfo &DI) { | ... | @@ -60,10 +62,8 @@ static void diagnosticHandler(const DiagnosticInfo &DI) { |
| 60 | } | 62 | } |
| 61 | 63 | ||
| 62 | static void checkError(Error E) { | 64 | static void checkError(Error E) { |
| 63 | handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) -> Error { | 65 | handleAllErrors(std::move(E), |
| 64 | error(EIB.message()); | 66 | [&](ErrorInfoBase &EIB) { error(EIB.message()); }); |
| 65 | return Error::success(); | ||
| 66 | }); | ||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static std::unique_ptr<lto::LTO> createLTO() { | 69 | static std::unique_ptr<lto::LTO> createLTO() { |
| ... | @@ -73,6 +73,10 @@ static std::unique_ptr<lto::LTO> createLTO() { | ... | @@ -73,6 +73,10 @@ static std::unique_ptr<lto::LTO> createLTO() { |
| 73 | Conf.Options = InitTargetOptionsFromCodeGenFlags(); | 73 | Conf.Options = InitTargetOptionsFromCodeGenFlags(); |
| 74 | Conf.Options.RelaxELFRelocations = true; | 74 | Conf.Options.RelaxELFRelocations = true; |
| 75 | 75 | ||
| 76 | // Always emit a section per function/datum with LTO. | ||
| 77 | Conf.Options.FunctionSections = true; | ||
| 78 | Conf.Options.DataSections = true; | ||
| 79 | |||
| 76 | if (Config->Relocatable) | 80 | if (Config->Relocatable) |
| 77 | Conf.RelocModel = None; | 81 | Conf.RelocModel = None; |
| 78 | else if (Config->Pic) | 82 | else if (Config->Pic) |
| ... | @@ -103,13 +107,20 @@ static std::unique_ptr<lto::LTO> createLTO() { | ... | @@ -103,13 +107,20 @@ static std::unique_ptr<lto::LTO> createLTO() { |
| 103 | Config->LTOPartitions); | 107 | Config->LTOPartitions); |
| 104 | } | 108 | } |
| 105 | 109 | ||
| 106 | BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} | 110 | BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) { |
| 111 | for (Symbol *Sym : Symtab->getSymbols()) { | ||
| 112 | StringRef Name = Sym->getName(); | ||
| 113 | for (StringRef Prefix : {"__start_", "__stop_"}) | ||
| 114 | if (Name.startswith(Prefix)) | ||
| 115 | UsedStartStop.insert(Name.substr(Prefix.size())); | ||
| 116 | } | ||
| 117 | } | ||
| 107 | 118 | ||
| 108 | BitcodeCompiler::~BitcodeCompiler() = default; | 119 | BitcodeCompiler::~BitcodeCompiler() = default; |
| 109 | 120 | ||
| 110 | static void undefine(Symbol *S) { | 121 | static void undefine(Symbol *S) { |
| 111 | replaceBody<Undefined>(S, S->body()->getName(), /*IsLocal=*/false, | 122 | replaceSymbol<Undefined>(S, nullptr, S->getName(), STB_GLOBAL, STV_DEFAULT, |
| 112 | STV_DEFAULT, S->body()->Type, nullptr); | 123 | S->Type); |
| 113 | } | 124 | } |
| 114 | 125 | ||
| 115 | void BitcodeCompiler::add(BitcodeFile &F) { | 126 | void BitcodeCompiler::add(BitcodeFile &F) { |
| ... | @@ -118,25 +129,42 @@ void BitcodeCompiler::add(BitcodeFile &F) { | ... | @@ -118,25 +129,42 @@ void BitcodeCompiler::add(BitcodeFile &F) { |
| 118 | std::vector<Symbol *> Syms = F.getSymbols(); | 129 | std::vector<Symbol *> Syms = F.getSymbols(); |
| 119 | std::vector<lto::SymbolResolution> Resols(Syms.size()); | 130 | std::vector<lto::SymbolResolution> Resols(Syms.size()); |
| 120 | 131 | ||
| 132 | DenseSet<StringRef> ScriptSymbols; | ||
| 133 | for (BaseCommand *Base : Script->SectionCommands) | ||
| 134 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) | ||
| 135 | ScriptSymbols.insert(Cmd->Name); | ||
| 136 | |||
| 121 | // Provide a resolution to the LTO API for each symbol. | 137 | // Provide a resolution to the LTO API for each symbol. |
| 122 | for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { | 138 | for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { |
| 123 | Symbol *Sym = Syms[SymNum]; | 139 | Symbol *Sym = Syms[SymNum]; |
| 124 | lto::SymbolResolution &R = Resols[SymNum]; | 140 | lto::SymbolResolution &R = Resols[SymNum]; |
| 125 | ++SymNum; | 141 | ++SymNum; |
| 126 | SymbolBody *B = Sym->body(); | ||
| 127 | 142 | ||
| 128 | // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile | 143 | // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile |
| 129 | // reports two symbols for module ASM defined. Without this check, lld | 144 | // reports two symbols for module ASM defined. Without this check, lld |
| 130 | // flags an undefined in IR with a definition in ASM as prevailing. | 145 | // flags an undefined in IR with a definition in ASM as prevailing. |
| 131 | // Once IRObjectFile is fixed to report only one symbol this hack can | 146 | // Once IRObjectFile is fixed to report only one symbol this hack can |
| 132 | // be removed. | 147 | // be removed. |
| 133 | R.Prevailing = !ObjSym.isUndefined() && B->File == &F; | 148 | R.Prevailing = !ObjSym.isUndefined() && Sym->File == &F; |
| 134 | 149 | ||
| 135 | R.VisibleToRegularObj = | 150 | // We ask LTO to preserve following global symbols: |
| 136 | Sym->IsUsedInRegularObj || (R.Prevailing && Sym->includeInDynsym()); | 151 | // 1) All symbols when doing relocatable link, so that them can be used |
| 152 | // for doing final link. | ||
| 153 | // 2) Symbols that are used in regular objects. | ||
| 154 | // 3) C named sections if we have corresponding __start_/__stop_ symbol. | ||
| 155 | // 4) Symbols that are defined in bitcode files and used for dynamic linking. | ||
| 156 | R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj || | ||
| 157 | (R.Prevailing && Sym->includeInDynsym()) || | ||
| 158 | UsedStartStop.count(ObjSym.getSectionName()); | ||
| 137 | if (R.Prevailing) | 159 | if (R.Prevailing) |
| 138 | undefine(Sym); | 160 | undefine(Sym); |
| 139 | R.LinkerRedefined = Config->RenamedSymbols.count(Sym); | 161 | |
| 162 | // We tell LTO to not apply interprocedural optimization for following | ||
| 163 | // symbols because otherwise LTO would inline them while their values are | ||
| 164 | // still not final: | ||
| 165 | // 1) Aliased (with --defsym) or wrapped (with --wrap) symbols. | ||
| 166 | // 2) Symbols redefined in linker script. | ||
| 167 | R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(Sym->getName()); | ||
| 140 | } | 168 | } |
| 141 | checkError(LTOObj->add(std::move(F.Obj), Resols)); | 169 | checkError(LTOObj->add(std::move(F.Obj), Resols)); |
| 142 | } | 170 | } |
| ... | @@ -156,9 +184,8 @@ std::vector<InputFile *> BitcodeCompiler::compile() { | ... | @@ -156,9 +184,8 @@ std::vector<InputFile *> BitcodeCompiler::compile() { |
| 156 | if (!Config->ThinLTOCacheDir.empty()) | 184 | if (!Config->ThinLTOCacheDir.empty()) |
| 157 | Cache = check( | 185 | Cache = check( |
| 158 | lto::localCache(Config->ThinLTOCacheDir, | 186 | lto::localCache(Config->ThinLTOCacheDir, |
| 159 | [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) { | 187 | [&](size_t Task, std::unique_ptr<MemoryBuffer> MB, |
| 160 | Files[Task] = std::move(MB); | 188 | StringRef Path) { Files[Task] = std::move(MB); })); |
| 161 | })); | ||
| 162 | 189 | ||
| 163 | checkError(LTOObj->run( | 190 | checkError(LTOObj->run( |
| 164 | [&](size_t Task) { | 191 | [&](size_t Task) { |
deps/lld/ELF/LTO.h+3-1| ... | @@ -21,7 +21,8 @@ | ... | @@ -21,7 +21,8 @@ |
| 21 | #ifndef LLD_ELF_LTO_H | 21 | #ifndef LLD_ELF_LTO_H |
| 22 | #define LLD_ELF_LTO_H | 22 | #define LLD_ELF_LTO_H |
| 23 | 23 | ||
| 24 | #include "lld/Core/LLVM.h" | 24 | #include "lld/Common/LLVM.h" |
| 25 | #include "llvm/ADT/DenseSet.h" | ||
| 25 | #include "llvm/ADT/SmallString.h" | 26 | #include "llvm/ADT/SmallString.h" |
| 26 | #include <memory> | 27 | #include <memory> |
| 27 | #include <vector> | 28 | #include <vector> |
| ... | @@ -50,6 +51,7 @@ private: | ... | @@ -50,6 +51,7 @@ private: |
| 50 | std::unique_ptr<llvm::lto::LTO> LTOObj; | 51 | std::unique_ptr<llvm::lto::LTO> LTOObj; |
| 51 | std::vector<SmallString<0>> Buff; | 52 | std::vector<SmallString<0>> Buff; |
| 52 | std::vector<std::unique_ptr<MemoryBuffer>> Files; | 53 | std::vector<std::unique_ptr<MemoryBuffer>> Files; |
| 54 | llvm::DenseSet<StringRef> UsedStartStop; | ||
| 53 | }; | 55 | }; |
| 54 | } // namespace elf | 56 | } // namespace elf |
| 55 | } // namespace lld | 57 | } // namespace lld |
deps/lld/ELF/LinkerScript.cpp+573-811| ... | @@ -14,20 +14,19 @@ | ... | @@ -14,20 +14,19 @@ |
| 14 | #include "LinkerScript.h" | 14 | #include "LinkerScript.h" |
| 15 | #include "Config.h" | 15 | #include "Config.h" |
| 16 | #include "InputSection.h" | 16 | #include "InputSection.h" |
| 17 | #include "Memory.h" | ||
| 18 | #include "OutputSections.h" | 17 | #include "OutputSections.h" |
| 19 | #include "Strings.h" | 18 | #include "Strings.h" |
| 20 | #include "SymbolTable.h" | 19 | #include "SymbolTable.h" |
| 21 | #include "Symbols.h" | 20 | #include "Symbols.h" |
| 22 | #include "SyntheticSections.h" | 21 | #include "SyntheticSections.h" |
| 23 | #include "Target.h" | 22 | #include "Target.h" |
| 24 | #include "Threads.h" | ||
| 25 | #include "Writer.h" | 23 | #include "Writer.h" |
| 24 | #include "lld/Common/Memory.h" | ||
| 25 | #include "lld/Common/Threads.h" | ||
| 26 | #include "llvm/ADT/STLExtras.h" | 26 | #include "llvm/ADT/STLExtras.h" |
| 27 | #include "llvm/ADT/StringRef.h" | 27 | #include "llvm/ADT/StringRef.h" |
| 28 | #include "llvm/BinaryFormat/ELF.h" | 28 | #include "llvm/BinaryFormat/ELF.h" |
| 29 | #include "llvm/Support/Casting.h" | 29 | #include "llvm/Support/Casting.h" |
| 30 | #include "llvm/Support/Compression.h" | ||
| 31 | #include "llvm/Support/Endian.h" | 30 | #include "llvm/Support/Endian.h" |
| 32 | #include "llvm/Support/ErrorHandling.h" | 31 | #include "llvm/Support/ErrorHandling.h" |
| 33 | #include "llvm/Support/FileSystem.h" | 32 | #include "llvm/Support/FileSystem.h" |
| ... | @@ -50,62 +49,56 @@ using namespace lld::elf; | ... | @@ -50,62 +49,56 @@ using namespace lld::elf; |
| 50 | 49 | ||
| 51 | LinkerScript *elf::Script; | 50 | LinkerScript *elf::Script; |
| 52 | 51 | ||
| 52 | static uint64_t getOutputSectionVA(SectionBase *InputSec, StringRef Loc) { | ||
| 53 | if (OutputSection *OS = InputSec->getOutputSection()) | ||
| 54 | return OS->Addr; | ||
| 55 | error(Loc + ": unable to evaluate expression: input section " + | ||
| 56 | InputSec->Name + " has no output section assigned"); | ||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 53 | uint64_t ExprValue::getValue() const { | 60 | uint64_t ExprValue::getValue() const { |
| 54 | if (Sec) { | 61 | if (Sec) |
| 55 | if (OutputSection *OS = Sec->getOutputSection()) | 62 | return alignTo(Sec->getOffset(Val) + getOutputSectionVA(Sec, Loc), |
| 56 | return alignTo(Sec->getOffset(Val) + OS->Addr, Alignment); | 63 | Alignment); |
| 57 | error(Loc + ": unable to evaluate expression: input section " + Sec->Name + | ||
| 58 | " has no output section assigned"); | ||
| 59 | } | ||
| 60 | return alignTo(Val, Alignment); | 64 | return alignTo(Val, Alignment); |
| 61 | } | 65 | } |
| 62 | 66 | ||
| 63 | uint64_t ExprValue::getSecAddr() const { | 67 | uint64_t ExprValue::getSecAddr() const { |
| 64 | if (Sec) | 68 | if (Sec) |
| 65 | return Sec->getOffset(0) + Sec->getOutputSection()->Addr; | 69 | return Sec->getOffset(0) + getOutputSectionVA(Sec, Loc); |
| 66 | return 0; | 70 | return 0; |
| 67 | } | 71 | } |
| 68 | 72 | ||
| 69 | template <class ELFT> static SymbolBody *addRegular(SymbolAssignment *Cmd) { | 73 | uint64_t ExprValue::getSectionOffset() const { |
| 70 | Symbol *Sym; | 74 | // If the alignment is trivial, we don't have to compute the full |
| 71 | uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; | 75 | // value to know the offset. This allows this function to succeed in |
| 72 | std::tie(Sym, std::ignore) = Symtab<ELFT>::X->insert( | 76 | // cases where the output section is not yet known. |
| 73 | Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, | 77 | if (Alignment == 1) |
| 74 | /*File*/ nullptr); | 78 | return Val; |
| 75 | Sym->Binding = STB_GLOBAL; | 79 | return getValue() - getSecAddr(); |
| 76 | ExprValue Value = Cmd->Expression(); | ||
| 77 | SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; | ||
| 78 | |||
| 79 | // We want to set symbol values early if we can. This allows us to use symbols | ||
| 80 | // as variables in linker scripts. Doing so allows us to write expressions | ||
| 81 | // like this: `alignment = 16; . = ALIGN(., alignment)` | ||
| 82 | uint64_t SymValue = Value.isAbsolute() ? Value.getValue() : 0; | ||
| 83 | replaceBody<DefinedRegular>(Sym, Cmd->Name, /*IsLocal=*/false, Visibility, | ||
| 84 | STT_NOTYPE, SymValue, 0, Sec, nullptr); | ||
| 85 | return Sym->body(); | ||
| 86 | } | 80 | } |
| 87 | 81 | ||
| 88 | OutputSectionCommand * | 82 | OutputSection *LinkerScript::createOutputSection(StringRef Name, |
| 89 | LinkerScript::createOutputSectionCommand(StringRef Name, StringRef Location) { | 83 | StringRef Location) { |
| 90 | OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name]; | 84 | OutputSection *&SecRef = NameToOutputSection[Name]; |
| 91 | OutputSectionCommand *Cmd; | 85 | OutputSection *Sec; |
| 92 | if (CmdRef && CmdRef->Location.empty()) { | 86 | if (SecRef && SecRef->Location.empty()) { |
| 93 | // There was a forward reference. | 87 | // There was a forward reference. |
| 94 | Cmd = CmdRef; | 88 | Sec = SecRef; |
| 95 | } else { | 89 | } else { |
| 96 | Cmd = make<OutputSectionCommand>(Name); | 90 | Sec = make<OutputSection>(Name, SHT_NOBITS, 0); |
| 97 | if (!CmdRef) | 91 | if (!SecRef) |
| 98 | CmdRef = Cmd; | 92 | SecRef = Sec; |
| 99 | } | 93 | } |
| 100 | Cmd->Location = Location; | 94 | Sec->Location = Location; |
| 101 | return Cmd; | 95 | return Sec; |
| 102 | } | 96 | } |
| 103 | 97 | ||
| 104 | OutputSectionCommand * | 98 | OutputSection *LinkerScript::getOrCreateOutputSection(StringRef Name) { |
| 105 | LinkerScript::getOrCreateOutputSectionCommand(StringRef Name) { | 99 | OutputSection *&CmdRef = NameToOutputSection[Name]; |
| 106 | OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name]; | ||
| 107 | if (!CmdRef) | 100 | if (!CmdRef) |
| 108 | CmdRef = make<OutputSectionCommand>(Name); | 101 | CmdRef = make<OutputSection>(Name, SHT_PROGBITS, 0); |
| 109 | return CmdRef; | 102 | return CmdRef; |
| 110 | } | 103 | } |
| 111 | 104 | ||
| ... | @@ -113,16 +106,56 @@ void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) { | ... | @@ -113,16 +106,56 @@ void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) { |
| 113 | uint64_t Val = E().getValue(); | 106 | uint64_t Val = E().getValue(); |
| 114 | if (Val < Dot && InSec) | 107 | if (Val < Dot && InSec) |
| 115 | error(Loc + ": unable to move location counter backward for: " + | 108 | error(Loc + ": unable to move location counter backward for: " + |
| 116 | CurAddressState->OutSec->Name); | 109 | Ctx->OutSec->Name); |
| 117 | Dot = Val; | 110 | Dot = Val; |
| 111 | |||
| 118 | // Update to location counter means update to section size. | 112 | // Update to location counter means update to section size. |
| 119 | if (InSec) | 113 | if (InSec) |
| 120 | CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr; | 114 | Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr; |
| 121 | } | 115 | } |
| 122 | 116 | ||
| 123 | // Sets value of a symbol. Two kinds of symbols are processed: synthetic | 117 | // This function is called from processSectionCommands, |
| 124 | // symbols, whose value is an offset from beginning of section and regular | 118 | // while we are fixing the output section layout. |
| 125 | // symbols whose value is absolute. | 119 | void LinkerScript::addSymbol(SymbolAssignment *Cmd) { |
| 120 | if (Cmd->Name == ".") | ||
| 121 | return; | ||
| 122 | |||
| 123 | // If a symbol was in PROVIDE(), we need to define it only when | ||
| 124 | // it is a referenced undefined symbol. | ||
| 125 | Symbol *B = Symtab->find(Cmd->Name); | ||
| 126 | if (Cmd->Provide && (!B || B->isDefined())) | ||
| 127 | return; | ||
| 128 | |||
| 129 | // Define a symbol. | ||
| 130 | Symbol *Sym; | ||
| 131 | uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; | ||
| 132 | std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, | ||
| 133 | /*CanOmitFromDynSym*/ false, | ||
| 134 | /*File*/ nullptr); | ||
| 135 | ExprValue Value = Cmd->Expression(); | ||
| 136 | SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; | ||
| 137 | |||
| 138 | // When this function is called, section addresses have not been | ||
| 139 | // fixed yet. So, we may or may not know the value of the RHS | ||
| 140 | // expression. | ||
| 141 | // | ||
| 142 | // For example, if an expression is `x = 42`, we know x is always 42. | ||
| 143 | // However, if an expression is `x = .`, there's no way to know its | ||
| 144 | // value at the moment. | ||
| 145 | // | ||
| 146 | // We want to set symbol values early if we can. This allows us to | ||
| 147 | // use symbols as variables in linker scripts. Doing so allows us to | ||
| 148 | // write expressions like this: `alignment = 16; . = ALIGN(., alignment)`. | ||
| 149 | uint64_t SymValue = Value.Sec ? 0 : Value.getValue(); | ||
| 150 | |||
| 151 | replaceSymbol<Defined>(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility, | ||
| 152 | STT_NOTYPE, SymValue, 0, Sec); | ||
| 153 | Cmd->Sym = cast<Defined>(Sym); | ||
| 154 | } | ||
| 155 | |||
| 156 | // This function is called from assignAddresses, while we are | ||
| 157 | // fixing the output section addresses. This function is supposed | ||
| 158 | // to set the final value for a given symbol assignment. | ||
| 126 | void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { | 159 | void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { |
| 127 | if (Cmd->Name == ".") { | 160 | if (Cmd->Name == ".") { |
| 128 | setDot(Cmd->Expression, Cmd->Location, InSec); | 161 | setDot(Cmd->Expression, Cmd->Location, InSec); |
| ... | @@ -132,116 +165,36 @@ void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { | ... | @@ -132,116 +165,36 @@ void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { |
| 132 | if (!Cmd->Sym) | 165 | if (!Cmd->Sym) |
| 133 | return; | 166 | return; |
| 134 | 167 | ||
| 135 | auto *Sym = cast<DefinedRegular>(Cmd->Sym); | ||
| 136 | ExprValue V = Cmd->Expression(); | 168 | ExprValue V = Cmd->Expression(); |
| 137 | if (V.isAbsolute()) { | 169 | if (V.isAbsolute()) { |
| 138 | Sym->Value = V.getValue(); | 170 | Cmd->Sym->Section = nullptr; |
| 171 | Cmd->Sym->Value = V.getValue(); | ||
| 139 | } else { | 172 | } else { |
| 140 | Sym->Section = V.Sec; | 173 | Cmd->Sym->Section = V.Sec; |
| 141 | Sym->Value = alignTo(V.Val, V.Alignment); | 174 | Cmd->Sym->Value = V.getSectionOffset(); |
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | static SymbolBody *findSymbol(StringRef S) { | ||
| 146 | switch (Config->EKind) { | ||
| 147 | case ELF32LEKind: | ||
| 148 | return Symtab<ELF32LE>::X->find(S); | ||
| 149 | case ELF32BEKind: | ||
| 150 | return Symtab<ELF32BE>::X->find(S); | ||
| 151 | case ELF64LEKind: | ||
| 152 | return Symtab<ELF64LE>::X->find(S); | ||
| 153 | case ELF64BEKind: | ||
| 154 | return Symtab<ELF64BE>::X->find(S); | ||
| 155 | default: | ||
| 156 | llvm_unreachable("unknown Config->EKind"); | ||
| 157 | } | 175 | } |
| 158 | } | 176 | } |
| 159 | 177 | ||
| 160 | static SymbolBody *addRegularSymbol(SymbolAssignment *Cmd) { | 178 | static std::string getFilename(InputFile *File) { |
| 161 | switch (Config->EKind) { | 179 | if (!File) |
| 162 | case ELF32LEKind: | 180 | return ""; |
| 163 | return addRegular<ELF32LE>(Cmd); | 181 | if (File->ArchiveName.empty()) |
| 164 | case ELF32BEKind: | 182 | return File->getName(); |
| 165 | return addRegular<ELF32BE>(Cmd); | 183 | return (File->ArchiveName + "(" + File->getName() + ")").str(); |
| 166 | case ELF64LEKind: | ||
| 167 | return addRegular<ELF64LE>(Cmd); | ||
| 168 | case ELF64BEKind: | ||
| 169 | return addRegular<ELF64BE>(Cmd); | ||
| 170 | default: | ||
| 171 | llvm_unreachable("unknown Config->EKind"); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | void LinkerScript::addSymbol(SymbolAssignment *Cmd) { | ||
| 176 | if (Cmd->Name == ".") | ||
| 177 | return; | ||
| 178 | |||
| 179 | // If a symbol was in PROVIDE(), we need to define it only when | ||
| 180 | // it is a referenced undefined symbol. | ||
| 181 | SymbolBody *B = findSymbol(Cmd->Name); | ||
| 182 | if (Cmd->Provide && (!B || B->isDefined())) | ||
| 183 | return; | ||
| 184 | |||
| 185 | Cmd->Sym = addRegularSymbol(Cmd); | ||
| 186 | } | ||
| 187 | |||
| 188 | bool SymbolAssignment::classof(const BaseCommand *C) { | ||
| 189 | return C->Kind == AssignmentKind; | ||
| 190 | } | ||
| 191 | |||
| 192 | bool OutputSectionCommand::classof(const BaseCommand *C) { | ||
| 193 | return C->Kind == OutputSectionKind; | ||
| 194 | } | ||
| 195 | |||
| 196 | // Fill [Buf, Buf + Size) with Filler. | ||
| 197 | // This is used for linker script "=fillexp" command. | ||
| 198 | static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { | ||
| 199 | size_t I = 0; | ||
| 200 | for (; I + 4 < Size; I += 4) | ||
| 201 | memcpy(Buf + I, &Filler, 4); | ||
| 202 | memcpy(Buf + I, &Filler, Size - I); | ||
| 203 | } | ||
| 204 | |||
| 205 | bool InputSectionDescription::classof(const BaseCommand *C) { | ||
| 206 | return C->Kind == InputSectionKind; | ||
| 207 | } | ||
| 208 | |||
| 209 | bool AssertCommand::classof(const BaseCommand *C) { | ||
| 210 | return C->Kind == AssertKind; | ||
| 211 | } | ||
| 212 | |||
| 213 | bool BytesDataCommand::classof(const BaseCommand *C) { | ||
| 214 | return C->Kind == BytesDataKind; | ||
| 215 | } | ||
| 216 | |||
| 217 | static StringRef basename(InputSectionBase *S) { | ||
| 218 | if (S->File) | ||
| 219 | return sys::path::filename(S->File->getName()); | ||
| 220 | return ""; | ||
| 221 | } | 184 | } |
| 222 | 185 | ||
| 223 | bool LinkerScript::shouldKeep(InputSectionBase *S) { | 186 | bool LinkerScript::shouldKeep(InputSectionBase *S) { |
| 224 | for (InputSectionDescription *ID : Opt.KeptSections) | 187 | if (KeptSections.empty()) |
| 225 | if (ID->FilePat.match(basename(S))) | 188 | return false; |
| 189 | std::string Filename = getFilename(S->File); | ||
| 190 | for (InputSectionDescription *ID : KeptSections) | ||
| 191 | if (ID->FilePat.match(Filename)) | ||
| 226 | for (SectionPattern &P : ID->SectionPatterns) | 192 | for (SectionPattern &P : ID->SectionPatterns) |
| 227 | if (P.SectionPat.match(S->Name)) | 193 | if (P.SectionPat.match(S->Name)) |
| 228 | return true; | 194 | return true; |
| 229 | return false; | 195 | return false; |
| 230 | } | 196 | } |
| 231 | 197 | ||
| 232 | // If an input string is in the form of "foo.N" where N is a number, | ||
| 233 | // return N. Otherwise, returns 65536, which is one greater than the | ||
| 234 | // lowest priority. | ||
| 235 | static int getPriority(StringRef S) { | ||
| 236 | size_t Pos = S.rfind('.'); | ||
| 237 | if (Pos == StringRef::npos) | ||
| 238 | return 65536; | ||
| 239 | int V; | ||
| 240 | if (!to_integer(S.substr(Pos + 1), V, 10)) | ||
| 241 | return 65536; | ||
| 242 | return V; | ||
| 243 | } | ||
| 244 | |||
| 245 | // A helper function for the SORT() command. | 198 | // A helper function for the SORT() command. |
| 246 | static std::function<bool(InputSectionBase *, InputSectionBase *)> | 199 | static std::function<bool(InputSectionBase *, InputSectionBase *)> |
| 247 | getComparator(SortSectionPolicy K) { | 200 | getComparator(SortSectionPolicy K) { |
| ... | @@ -267,28 +220,63 @@ getComparator(SortSectionPolicy K) { | ... | @@ -267,28 +220,63 @@ getComparator(SortSectionPolicy K) { |
| 267 | } | 220 | } |
| 268 | 221 | ||
| 269 | // A helper function for the SORT() command. | 222 | // A helper function for the SORT() command. |
| 270 | static bool matchConstraints(ArrayRef<InputSectionBase *> Sections, | 223 | static bool matchConstraints(ArrayRef<InputSection *> Sections, |
| 271 | ConstraintKind Kind) { | 224 | ConstraintKind Kind) { |
| 272 | if (Kind == ConstraintKind::NoConstraint) | 225 | if (Kind == ConstraintKind::NoConstraint) |
| 273 | return true; | 226 | return true; |
| 274 | 227 | ||
| 275 | bool IsRW = llvm::any_of(Sections, [](InputSectionBase *Sec) { | 228 | bool IsRW = llvm::any_of( |
| 276 | return static_cast<InputSectionBase *>(Sec)->Flags & SHF_WRITE; | 229 | Sections, [](InputSection *Sec) { return Sec->Flags & SHF_WRITE; }); |
| 277 | }); | ||
| 278 | 230 | ||
| 279 | return (IsRW && Kind == ConstraintKind::ReadWrite) || | 231 | return (IsRW && Kind == ConstraintKind::ReadWrite) || |
| 280 | (!IsRW && Kind == ConstraintKind::ReadOnly); | 232 | (!IsRW && Kind == ConstraintKind::ReadOnly); |
| 281 | } | 233 | } |
| 282 | 234 | ||
| 283 | static void sortSections(InputSection **Begin, InputSection **End, | 235 | static void sortSections(MutableArrayRef<InputSection *> Vec, |
| 284 | SortSectionPolicy K) { | 236 | SortSectionPolicy K) { |
| 285 | if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None) | 237 | if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None) |
| 286 | std::stable_sort(Begin, End, getComparator(K)); | 238 | std::stable_sort(Vec.begin(), Vec.end(), getComparator(K)); |
| 239 | } | ||
| 240 | |||
| 241 | // Sort sections as instructed by SORT-family commands and --sort-section | ||
| 242 | // option. Because SORT-family commands can be nested at most two depth | ||
| 243 | // (e.g. SORT_BY_NAME(SORT_BY_ALIGNMENT(.text.*))) and because the command | ||
| 244 | // line option is respected even if a SORT command is given, the exact | ||
| 245 | // behavior we have here is a bit complicated. Here are the rules. | ||
| 246 | // | ||
| 247 | // 1. If two SORT commands are given, --sort-section is ignored. | ||
| 248 | // 2. If one SORT command is given, and if it is not SORT_NONE, | ||
| 249 | // --sort-section is handled as an inner SORT command. | ||
| 250 | // 3. If one SORT command is given, and if it is SORT_NONE, don't sort. | ||
| 251 | // 4. If no SORT command is given, sort according to --sort-section. | ||
| 252 | // 5. If no SORT commands are given and --sort-section is not specified, | ||
| 253 | // apply sorting provided by --symbol-ordering-file if any exist. | ||
| 254 | static void sortInputSections( | ||
| 255 | MutableArrayRef<InputSection *> Vec, const SectionPattern &Pat, | ||
| 256 | const DenseMap<SectionBase *, int> &Order) { | ||
| 257 | if (Pat.SortOuter == SortSectionPolicy::None) | ||
| 258 | return; | ||
| 259 | |||
| 260 | if (Pat.SortOuter == SortSectionPolicy::Default && | ||
| 261 | Config->SortSection == SortSectionPolicy::Default) { | ||
| 262 | // If -symbol-ordering-file was given, sort accordingly. | ||
| 263 | // Usually, Order is empty. | ||
| 264 | if (!Order.empty()) | ||
| 265 | sortByOrder(Vec, [&](InputSectionBase *S) { return Order.lookup(S); }); | ||
| 266 | return; | ||
| 267 | } | ||
| 268 | |||
| 269 | if (Pat.SortInner == SortSectionPolicy::Default) | ||
| 270 | sortSections(Vec, Config->SortSection); | ||
| 271 | else | ||
| 272 | sortSections(Vec, Pat.SortInner); | ||
| 273 | sortSections(Vec, Pat.SortOuter); | ||
| 287 | } | 274 | } |
| 288 | 275 | ||
| 289 | // Compute and remember which sections the InputSectionDescription matches. | 276 | // Compute and remember which sections the InputSectionDescription matches. |
| 290 | std::vector<InputSection *> | 277 | std::vector<InputSection *> |
| 291 | LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { | 278 | LinkerScript::computeInputSections(const InputSectionDescription *Cmd, |
| 279 | const DenseMap<SectionBase *, int> &Order) { | ||
| 292 | std::vector<InputSection *> Ret; | 280 | std::vector<InputSection *> Ret; |
| 293 | 281 | ||
| 294 | // Collects all sections that satisfy constraints of Cmd. | 282 | // Collects all sections that satisfy constraints of Cmd. |
| ... | @@ -296,13 +284,8 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { | ... | @@ -296,13 +284,8 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { |
| 296 | size_t SizeBefore = Ret.size(); | 284 | size_t SizeBefore = Ret.size(); |
| 297 | 285 | ||
| 298 | for (InputSectionBase *Sec : InputSections) { | 286 | for (InputSectionBase *Sec : InputSections) { |
| 299 | if (Sec->Assigned) | 287 | if (!Sec->Live || Sec->Assigned) |
| 300 | continue; | ||
| 301 | |||
| 302 | if (!Sec->Live) { | ||
| 303 | reportDiscarded(Sec); | ||
| 304 | continue; | 288 | continue; |
| 305 | } | ||
| 306 | 289 | ||
| 307 | // For -emit-relocs we have to ignore entries like | 290 | // For -emit-relocs we have to ignore entries like |
| 308 | // .rela.dyn : { *(.rela.data) } | 291 | // .rela.dyn : { *(.rela.data) } |
| ... | @@ -310,67 +293,51 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { | ... | @@ -310,67 +293,51 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { |
| 310 | if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) | 293 | if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) |
| 311 | continue; | 294 | continue; |
| 312 | 295 | ||
| 313 | StringRef Filename = basename(Sec); | 296 | std::string Filename = getFilename(Sec->File); |
| 314 | if (!Cmd->FilePat.match(Filename) || | 297 | if (!Cmd->FilePat.match(Filename) || |
| 315 | Pat.ExcludedFilePat.match(Filename) || | 298 | Pat.ExcludedFilePat.match(Filename) || |
| 316 | !Pat.SectionPat.match(Sec->Name)) | 299 | !Pat.SectionPat.match(Sec->Name)) |
| 317 | continue; | 300 | continue; |
| 318 | 301 | ||
| 302 | // It is safe to assume that Sec is an InputSection | ||
| 303 | // because mergeable or EH input sections have already been | ||
| 304 | // handled and eliminated. | ||
| 319 | Ret.push_back(cast<InputSection>(Sec)); | 305 | Ret.push_back(cast<InputSection>(Sec)); |
| 320 | Sec->Assigned = true; | 306 | Sec->Assigned = true; |
| 321 | } | 307 | } |
| 322 | 308 | ||
| 323 | // Sort sections as instructed by SORT-family commands and --sort-section | 309 | sortInputSections(MutableArrayRef<InputSection *>(Ret).slice(SizeBefore), |
| 324 | // option. Because SORT-family commands can be nested at most two depth | 310 | Pat, Order); |
| 325 | // (e.g. SORT_BY_NAME(SORT_BY_ALIGNMENT(.text.*))) and because the command | ||
| 326 | // line option is respected even if a SORT command is given, the exact | ||
| 327 | // behavior we have here is a bit complicated. Here are the rules. | ||
| 328 | // | ||
| 329 | // 1. If two SORT commands are given, --sort-section is ignored. | ||
| 330 | // 2. If one SORT command is given, and if it is not SORT_NONE, | ||
| 331 | // --sort-section is handled as an inner SORT command. | ||
| 332 | // 3. If one SORT command is given, and if it is SORT_NONE, don't sort. | ||
| 333 | // 4. If no SORT command is given, sort according to --sort-section. | ||
| 334 | InputSection **Begin = Ret.data() + SizeBefore; | ||
| 335 | InputSection **End = Ret.data() + Ret.size(); | ||
| 336 | if (Pat.SortOuter != SortSectionPolicy::None) { | ||
| 337 | if (Pat.SortInner == SortSectionPolicy::Default) | ||
| 338 | sortSections(Begin, End, Config->SortSection); | ||
| 339 | else | ||
| 340 | sortSections(Begin, End, Pat.SortInner); | ||
| 341 | sortSections(Begin, End, Pat.SortOuter); | ||
| 342 | } | ||
| 343 | } | 311 | } |
| 344 | return Ret; | 312 | return Ret; |
| 345 | } | 313 | } |
| 346 | 314 | ||
| 347 | void LinkerScript::discard(ArrayRef<InputSectionBase *> V) { | 315 | void LinkerScript::discard(ArrayRef<InputSection *> V) { |
| 348 | for (InputSectionBase *S : V) { | 316 | for (InputSection *S : V) { |
| 349 | S->Live = false; | ||
| 350 | if (S == InX::ShStrTab || S == InX::Dynamic || S == InX::DynSymTab || | 317 | if (S == InX::ShStrTab || S == InX::Dynamic || S == InX::DynSymTab || |
| 351 | S == InX::DynStrTab) | 318 | S == InX::DynStrTab) |
| 352 | error("discarding " + S->Name + " section is not allowed"); | 319 | error("discarding " + S->Name + " section is not allowed"); |
| 320 | |||
| 321 | S->Assigned = false; | ||
| 322 | S->Live = false; | ||
| 353 | discard(S->DependentSections); | 323 | discard(S->DependentSections); |
| 354 | } | 324 | } |
| 355 | } | 325 | } |
| 356 | 326 | ||
| 357 | std::vector<InputSectionBase *> | 327 | std::vector<InputSection *> LinkerScript::createInputSectionList( |
| 358 | LinkerScript::createInputSectionList(OutputSectionCommand &OutCmd) { | 328 | OutputSection &OutCmd, const DenseMap<SectionBase *, int> &Order) { |
| 359 | std::vector<InputSectionBase *> Ret; | 329 | std::vector<InputSection *> Ret; |
| 360 | |||
| 361 | for (BaseCommand *Base : OutCmd.Commands) { | ||
| 362 | auto *Cmd = dyn_cast<InputSectionDescription>(Base); | ||
| 363 | if (!Cmd) | ||
| 364 | continue; | ||
| 365 | 330 | ||
| 366 | Cmd->Sections = computeInputSections(Cmd); | 331 | for (BaseCommand *Base : OutCmd.SectionCommands) { |
| 367 | Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end()); | 332 | if (auto *Cmd = dyn_cast<InputSectionDescription>(Base)) { |
| 333 | Cmd->Sections = computeInputSections(Cmd, Order); | ||
| 334 | Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end()); | ||
| 335 | } | ||
| 368 | } | 336 | } |
| 369 | |||
| 370 | return Ret; | 337 | return Ret; |
| 371 | } | 338 | } |
| 372 | 339 | ||
| 373 | void LinkerScript::processCommands(OutputSectionFactory &Factory) { | 340 | void LinkerScript::processSectionCommands() { |
| 374 | // A symbol can be assigned before any section is mentioned in the linker | 341 | // A symbol can be assigned before any section is mentioned in the linker |
| 375 | // script. In an DSO, the symbol values are addresses, so the only important | 342 | // script. In an DSO, the symbol values are addresses, so the only important |
| 376 | // section values are: | 343 | // section values are: |
| ... | @@ -382,28 +349,31 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { | ... | @@ -382,28 +349,31 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { |
| 382 | // which will map to whatever the first actual section is. | 349 | // which will map to whatever the first actual section is. |
| 383 | Aether = make<OutputSection>("", 0, SHF_ALLOC); | 350 | Aether = make<OutputSection>("", 0, SHF_ALLOC); |
| 384 | Aether->SectionIndex = 1; | 351 | Aether->SectionIndex = 1; |
| 385 | auto State = make_unique<AddressState>(Opt); | 352 | |
| 386 | // CurAddressState captures the local AddressState and makes it accessible | 353 | // Ctx captures the local AddressState and makes it accessible deliberately. |
| 387 | // deliberately. This is needed as there are some cases where we cannot just | 354 | // This is needed as there are some cases where we cannot just |
| 388 | // thread the current state through to a lambda function created by the | 355 | // thread the current state through to a lambda function created by the |
| 389 | // script parser. | 356 | // script parser. |
| 390 | CurAddressState = State.get(); | 357 | auto Deleter = make_unique<AddressState>(); |
| 391 | CurAddressState->OutSec = Aether; | 358 | Ctx = Deleter.get(); |
| 392 | Dot = 0; | 359 | Ctx->OutSec = Aether; |
| 393 | 360 | ||
| 394 | for (size_t I = 0; I < Opt.Commands.size(); ++I) { | 361 | size_t I = 0; |
| 362 | DenseMap<SectionBase *, int> Order = buildSectionOrder(); | ||
| 363 | // Add input sections to output sections. | ||
| 364 | for (BaseCommand *Base : SectionCommands) { | ||
| 395 | // Handle symbol assignments outside of any output section. | 365 | // Handle symbol assignments outside of any output section. |
| 396 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Opt.Commands[I])) { | 366 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { |
| 397 | addSymbol(Cmd); | 367 | addSymbol(Cmd); |
| 398 | continue; | 368 | continue; |
| 399 | } | 369 | } |
| 400 | 370 | ||
| 401 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I])) { | 371 | if (auto *Sec = dyn_cast<OutputSection>(Base)) { |
| 402 | std::vector<InputSectionBase *> V = createInputSectionList(*Cmd); | 372 | std::vector<InputSection *> V = createInputSectionList(*Sec, Order); |
| 403 | 373 | ||
| 404 | // The output section name `/DISCARD/' is special. | 374 | // The output section name `/DISCARD/' is special. |
| 405 | // Any input section assigned to it is discarded. | 375 | // Any input section assigned to it is discarded. |
| 406 | if (Cmd->Name == "/DISCARD/") { | 376 | if (Sec->Name == "/DISCARD/") { |
| 407 | discard(V); | 377 | discard(V); |
| 408 | continue; | 378 | continue; |
| 409 | } | 379 | } |
| ... | @@ -413,250 +383,265 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { | ... | @@ -413,250 +383,265 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { |
| 413 | // sections satisfy a given constraint. If not, a directive is handled | 383 | // sections satisfy a given constraint. If not, a directive is handled |
| 414 | // as if it wasn't present from the beginning. | 384 | // as if it wasn't present from the beginning. |
| 415 | // | 385 | // |
| 416 | // Because we'll iterate over Commands many more times, the easiest | 386 | // Because we'll iterate over SectionCommands many more times, the easy |
| 417 | // way to "make it as if it wasn't present" is to just remove it. | 387 | // way to "make it as if it wasn't present" is to make it empty. |
| 418 | if (!matchConstraints(V, Cmd->Constraint)) { | 388 | if (!matchConstraints(V, Sec->Constraint)) { |
| 419 | for (InputSectionBase *S : V) | 389 | for (InputSectionBase *S : V) |
| 420 | S->Assigned = false; | 390 | S->Assigned = false; |
| 421 | Opt.Commands.erase(Opt.Commands.begin() + I); | 391 | Sec->SectionCommands.clear(); |
| 422 | --I; | ||
| 423 | continue; | 392 | continue; |
| 424 | } | 393 | } |
| 425 | 394 | ||
| 426 | // A directive may contain symbol definitions like this: | 395 | // A directive may contain symbol definitions like this: |
| 427 | // ".foo : { ...; bar = .; }". Handle them. | 396 | // ".foo : { ...; bar = .; }". Handle them. |
| 428 | for (BaseCommand *Base : Cmd->Commands) | 397 | for (BaseCommand *Base : Sec->SectionCommands) |
| 429 | if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base)) | 398 | if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base)) |
| 430 | addSymbol(OutCmd); | 399 | addSymbol(OutCmd); |
| 431 | 400 | ||
| 432 | // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign | 401 | // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign |
| 433 | // is given, input sections are aligned to that value, whether the | 402 | // is given, input sections are aligned to that value, whether the |
| 434 | // given value is larger or smaller than the original section alignment. | 403 | // given value is larger or smaller than the original section alignment. |
| 435 | if (Cmd->SubalignExpr) { | 404 | if (Sec->SubalignExpr) { |
| 436 | uint32_t Subalign = Cmd->SubalignExpr().getValue(); | 405 | uint32_t Subalign = Sec->SubalignExpr().getValue(); |
| 437 | for (InputSectionBase *S : V) | 406 | for (InputSectionBase *S : V) |
| 438 | S->Alignment = Subalign; | 407 | S->Alignment = Subalign; |
| 439 | } | 408 | } |
| 440 | 409 | ||
| 441 | // Add input sections to an output section. | 410 | // Add input sections to an output section. |
| 442 | for (InputSectionBase *S : V) | 411 | for (InputSection *S : V) |
| 443 | Factory.addInputSec(S, Cmd->Name, Cmd->Sec); | 412 | Sec->addSection(S); |
| 444 | if (OutputSection *Sec = Cmd->Sec) { | 413 | |
| 445 | assert(Sec->SectionIndex == INT_MAX); | 414 | Sec->SectionIndex = I++; |
| 446 | Sec->SectionIndex = I; | 415 | if (Sec->Noload) |
| 447 | if (Cmd->Noload) | 416 | Sec->Type = SHT_NOBITS; |
| 448 | Sec->Type = SHT_NOBITS; | ||
| 449 | SecToCommand[Sec] = Cmd; | ||
| 450 | } | ||
| 451 | } | 417 | } |
| 452 | } | 418 | } |
| 453 | CurAddressState = nullptr; | 419 | Ctx = nullptr; |
| 454 | } | 420 | } |
| 455 | 421 | ||
| 456 | void LinkerScript::fabricateDefaultCommands() { | 422 | static OutputSection *findByName(ArrayRef<BaseCommand *> Vec, |
| 457 | std::vector<BaseCommand *> Commands; | 423 | StringRef Name) { |
| 458 | 424 | for (BaseCommand *Base : Vec) | |
| 459 | // Define start address | 425 | if (auto *Sec = dyn_cast<OutputSection>(Base)) |
| 460 | uint64_t StartAddr = -1; | 426 | if (Sec->Name == Name) |
| 461 | 427 | return Sec; | |
| 462 | // The Sections with -T<section> have been sorted in order of ascending | 428 | return nullptr; |
| 463 | // address. We must lower StartAddr if the lowest -T<section address> as | 429 | } |
| 464 | // calls to setDot() must be monotonically increasing. | ||
| 465 | for (auto &KV : Config->SectionStartMap) | ||
| 466 | StartAddr = std::min(StartAddr, KV.second); | ||
| 467 | |||
| 468 | Commands.push_back(make<SymbolAssignment>( | ||
| 469 | ".", | ||
| 470 | [=] { | ||
| 471 | return std::min(StartAddr, Config->ImageBase + elf::getHeaderSize()); | ||
| 472 | }, | ||
| 473 | "")); | ||
| 474 | 430 | ||
| 475 | // For each OutputSection that needs a VA fabricate an OutputSectionCommand | 431 | static OutputSection *createSection(InputSectionBase *IS, |
| 476 | // with an InputSectionDescription describing the InputSections | 432 | StringRef OutsecName) { |
| 477 | for (OutputSection *Sec : OutputSections) { | 433 | OutputSection *Sec = Script->createOutputSection(OutsecName, "<internal>"); |
| 478 | auto *OSCmd = createOutputSectionCommand(Sec->Name, "<internal>"); | 434 | Sec->addSection(cast<InputSection>(IS)); |
| 479 | OSCmd->Sec = Sec; | 435 | return Sec; |
| 480 | SecToCommand[Sec] = OSCmd; | 436 | } |
| 481 | 437 | ||
| 482 | Commands.push_back(OSCmd); | 438 | static OutputSection *addInputSec(StringMap<OutputSection *> &Map, |
| 483 | if (Sec->Sections.size()) { | 439 | InputSectionBase *IS, StringRef OutsecName) { |
| 484 | auto *ISD = make<InputSectionDescription>(""); | 440 | // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r |
| 485 | OSCmd->Commands.push_back(ISD); | 441 | // option is given. A section with SHT_GROUP defines a "section group", and |
| 486 | for (InputSection *ISec : Sec->Sections) { | 442 | // its members have SHF_GROUP attribute. Usually these flags have already been |
| 487 | ISD->Sections.push_back(ISec); | 443 | // stripped by InputFiles.cpp as section groups are processed and uniquified. |
| 488 | ISec->Assigned = true; | 444 | // However, for the -r option, we want to pass through all section groups |
| 489 | } | 445 | // as-is because adding/removing members or merging them with other groups |
| 446 | // change their semantics. | ||
| 447 | if (IS->Type == SHT_GROUP || (IS->Flags & SHF_GROUP)) | ||
| 448 | return createSection(IS, OutsecName); | ||
| 449 | |||
| 450 | // Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have | ||
| 451 | // relocation sections .rela.foo and .rela.bar for example. Most tools do | ||
| 452 | // not allow multiple REL[A] sections for output section. Hence we | ||
| 453 | // should combine these relocation sections into single output. | ||
| 454 | // We skip synthetic sections because it can be .rela.dyn/.rela.plt or any | ||
| 455 | // other REL[A] sections created by linker itself. | ||
| 456 | if (!isa<SyntheticSection>(IS) && | ||
| 457 | (IS->Type == SHT_REL || IS->Type == SHT_RELA)) { | ||
| 458 | auto *Sec = cast<InputSection>(IS); | ||
| 459 | OutputSection *Out = Sec->getRelocatedSection()->getOutputSection(); | ||
| 460 | |||
| 461 | if (Out->RelocationSection) { | ||
| 462 | Out->RelocationSection->addSection(Sec); | ||
| 463 | return nullptr; | ||
| 490 | } | 464 | } |
| 465 | |||
| 466 | Out->RelocationSection = createSection(IS, OutsecName); | ||
| 467 | return Out->RelocationSection; | ||
| 468 | } | ||
| 469 | |||
| 470 | // When control reaches here, mergeable sections have already been merged into | ||
| 471 | // synthetic sections. For relocatable case we want to create one output | ||
| 472 | // section per syntetic section so that they have a valid sh_entsize. | ||
| 473 | if (Config->Relocatable && (IS->Flags & SHF_MERGE)) | ||
| 474 | return createSection(IS, OutsecName); | ||
| 475 | |||
| 476 | // The ELF spec just says | ||
| 477 | // ---------------------------------------------------------------- | ||
| 478 | // In the first phase, input sections that match in name, type and | ||
| 479 | // attribute flags should be concatenated into single sections. | ||
| 480 | // ---------------------------------------------------------------- | ||
| 481 | // | ||
| 482 | // However, it is clear that at least some flags have to be ignored for | ||
| 483 | // section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be | ||
| 484 | // ignored. We should not have two output .text sections just because one was | ||
| 485 | // in a group and another was not for example. | ||
| 486 | // | ||
| 487 | // It also seems that that wording was a late addition and didn't get the | ||
| 488 | // necessary scrutiny. | ||
| 489 | // | ||
| 490 | // Merging sections with different flags is expected by some users. One | ||
| 491 | // reason is that if one file has | ||
| 492 | // | ||
| 493 | // int *const bar __attribute__((section(".foo"))) = (int *)0; | ||
| 494 | // | ||
| 495 | // gcc with -fPIC will produce a read only .foo section. But if another | ||
| 496 | // file has | ||
| 497 | // | ||
| 498 | // int zed; | ||
| 499 | // int *const bar __attribute__((section(".foo"))) = (int *)&zed; | ||
| 500 | // | ||
| 501 | // gcc with -fPIC will produce a read write section. | ||
| 502 | // | ||
| 503 | // Last but not least, when using linker script the merge rules are forced by | ||
| 504 | // the script. Unfortunately, linker scripts are name based. This means that | ||
| 505 | // expressions like *(.foo*) can refer to multiple input sections with | ||
| 506 | // different flags. We cannot put them in different output sections or we | ||
| 507 | // would produce wrong results for | ||
| 508 | // | ||
| 509 | // start = .; *(.foo.*) end = .; *(.bar) | ||
| 510 | // | ||
| 511 | // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to | ||
| 512 | // another. The problem is that there is no way to layout those output | ||
| 513 | // sections such that the .foo sections are the only thing between the start | ||
| 514 | // and end symbols. | ||
| 515 | // | ||
| 516 | // Given the above issues, we instead merge sections by name and error on | ||
| 517 | // incompatible types and flags. | ||
| 518 | OutputSection *&Sec = Map[OutsecName]; | ||
| 519 | if (Sec) { | ||
| 520 | Sec->addSection(cast<InputSection>(IS)); | ||
| 521 | return nullptr; | ||
| 491 | } | 522 | } |
| 492 | // SECTIONS commands run before other non SECTIONS commands | 523 | |
| 493 | Commands.insert(Commands.end(), Opt.Commands.begin(), Opt.Commands.end()); | 524 | Sec = createSection(IS, OutsecName); |
| 494 | Opt.Commands = std::move(Commands); | 525 | return Sec; |
| 495 | } | 526 | } |
| 496 | 527 | ||
| 497 | // Add sections that didn't match any sections command. | 528 | // Add sections that didn't match any sections command. |
| 498 | void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { | 529 | void LinkerScript::addOrphanSections() { |
| 499 | unsigned NumCommands = Opt.Commands.size(); | 530 | unsigned End = SectionCommands.size(); |
| 531 | StringMap<OutputSection *> Map; | ||
| 532 | |||
| 533 | std::vector<OutputSection *> V; | ||
| 500 | for (InputSectionBase *S : InputSections) { | 534 | for (InputSectionBase *S : InputSections) { |
| 501 | if (!S->Live || S->Parent) | 535 | if (!S->Live || S->Parent) |
| 502 | continue; | 536 | continue; |
| 503 | StringRef Name = getOutputSectionName(S->Name); | 537 | |
| 504 | auto End = Opt.Commands.begin() + NumCommands; | 538 | StringRef Name = getOutputSectionName(S); |
| 505 | auto I = std::find_if(Opt.Commands.begin(), End, [&](BaseCommand *Base) { | 539 | |
| 506 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) | 540 | if (Config->OrphanHandling == OrphanHandlingPolicy::Error) |
| 507 | return Cmd->Name == Name; | 541 | error(toString(S) + " is being placed in '" + Name + "'"); |
| 508 | return false; | 542 | else if (Config->OrphanHandling == OrphanHandlingPolicy::Warn) |
| 509 | }); | 543 | warn(toString(S) + " is being placed in '" + Name + "'"); |
| 510 | OutputSectionCommand *Cmd; | 544 | |
| 511 | if (I == End) { | 545 | if (OutputSection *Sec = |
| 512 | Factory.addInputSec(S, Name); | 546 | findByName(makeArrayRef(SectionCommands).slice(0, End), Name)) { |
| 513 | OutputSection *Sec = S->getOutputSection(); | 547 | Sec->addSection(cast<InputSection>(S)); |
| 514 | assert(Sec->SectionIndex == INT_MAX); | 548 | continue; |
| 515 | OutputSectionCommand *&CmdRef = SecToCommand[Sec]; | ||
| 516 | if (!CmdRef) { | ||
| 517 | CmdRef = createOutputSectionCommand(Sec->Name, "<internal>"); | ||
| 518 | CmdRef->Sec = Sec; | ||
| 519 | Opt.Commands.push_back(CmdRef); | ||
| 520 | } | ||
| 521 | Cmd = CmdRef; | ||
| 522 | } else { | ||
| 523 | Cmd = cast<OutputSectionCommand>(*I); | ||
| 524 | Factory.addInputSec(S, Name, Cmd->Sec); | ||
| 525 | if (OutputSection *Sec = Cmd->Sec) { | ||
| 526 | SecToCommand[Sec] = Cmd; | ||
| 527 | unsigned Index = std::distance(Opt.Commands.begin(), I); | ||
| 528 | assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index); | ||
| 529 | Sec->SectionIndex = Index; | ||
| 530 | } | ||
| 531 | } | 549 | } |
| 532 | auto *ISD = make<InputSectionDescription>(""); | 550 | |
| 533 | ISD->Sections.push_back(cast<InputSection>(S)); | 551 | if (OutputSection *OS = addInputSec(Map, S, Name)) |
| 534 | Cmd->Commands.push_back(ISD); | 552 | V.push_back(OS); |
| 553 | assert(S->getOutputSection()->SectionIndex == INT_MAX); | ||
| 535 | } | 554 | } |
| 555 | |||
| 556 | // If no SECTIONS command was given, we should insert sections commands | ||
| 557 | // before others, so that we can handle scripts which refers them, | ||
| 558 | // for example: "foo = ABSOLUTE(ADDR(.text)));". | ||
| 559 | // When SECTIONS command is present we just add all orphans to the end. | ||
| 560 | if (HasSectionsCommand) | ||
| 561 | SectionCommands.insert(SectionCommands.end(), V.begin(), V.end()); | ||
| 562 | else | ||
| 563 | SectionCommands.insert(SectionCommands.begin(), V.begin(), V.end()); | ||
| 536 | } | 564 | } |
| 537 | 565 | ||
| 538 | uint64_t LinkerScript::advance(uint64_t Size, unsigned Align) { | 566 | uint64_t LinkerScript::advance(uint64_t Size, unsigned Alignment) { |
| 539 | bool IsTbss = (CurAddressState->OutSec->Flags & SHF_TLS) && | 567 | bool IsTbss = |
| 540 | CurAddressState->OutSec->Type == SHT_NOBITS; | 568 | (Ctx->OutSec->Flags & SHF_TLS) && Ctx->OutSec->Type == SHT_NOBITS; |
| 541 | uint64_t Start = IsTbss ? Dot + CurAddressState->ThreadBssOffset : Dot; | 569 | uint64_t Start = IsTbss ? Dot + Ctx->ThreadBssOffset : Dot; |
| 542 | Start = alignTo(Start, Align); | 570 | Start = alignTo(Start, Alignment); |
| 543 | uint64_t End = Start + Size; | 571 | uint64_t End = Start + Size; |
| 544 | 572 | ||
| 545 | if (IsTbss) | 573 | if (IsTbss) |
| 546 | CurAddressState->ThreadBssOffset = End - Dot; | 574 | Ctx->ThreadBssOffset = End - Dot; |
| 547 | else | 575 | else |
| 548 | Dot = End; | 576 | Dot = End; |
| 549 | return End; | 577 | return End; |
| 550 | } | 578 | } |
| 551 | 579 | ||
| 552 | void LinkerScript::output(InputSection *S) { | 580 | void LinkerScript::output(InputSection *S) { |
| 581 | uint64_t Before = advance(0, 1); | ||
| 553 | uint64_t Pos = advance(S->getSize(), S->Alignment); | 582 | uint64_t Pos = advance(S->getSize(), S->Alignment); |
| 554 | S->OutSecOff = Pos - S->getSize() - CurAddressState->OutSec->Addr; | 583 | S->OutSecOff = Pos - S->getSize() - Ctx->OutSec->Addr; |
| 555 | 584 | ||
| 556 | // Update output section size after adding each section. This is so that | 585 | // Update output section size after adding each section. This is so that |
| 557 | // SIZEOF works correctly in the case below: | 586 | // SIZEOF works correctly in the case below: |
| 558 | // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } | 587 | // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } |
| 559 | CurAddressState->OutSec->Size = Pos - CurAddressState->OutSec->Addr; | 588 | Ctx->OutSec->Size = Pos - Ctx->OutSec->Addr; |
| 560 | 589 | ||
| 561 | // If there is a memory region associated with this input section, then | 590 | // If there is a memory region associated with this input section, then |
| 562 | // place the section in that region and update the region index. | 591 | // place the section in that region and update the region index. |
| 563 | if (CurAddressState->MemRegion) { | 592 | if (Ctx->MemRegion) { |
| 564 | uint64_t &CurOffset = | 593 | uint64_t &CurOffset = Ctx->MemRegionOffset[Ctx->MemRegion]; |
| 565 | CurAddressState->MemRegionOffset[CurAddressState->MemRegion]; | 594 | CurOffset += Pos - Before; |
| 566 | CurOffset += CurAddressState->OutSec->Size; | 595 | uint64_t CurSize = CurOffset - Ctx->MemRegion->Origin; |
| 567 | uint64_t CurSize = CurOffset - CurAddressState->MemRegion->Origin; | 596 | if (CurSize > Ctx->MemRegion->Length) { |
| 568 | if (CurSize > CurAddressState->MemRegion->Length) { | 597 | uint64_t OverflowAmt = CurSize - Ctx->MemRegion->Length; |
| 569 | uint64_t OverflowAmt = CurSize - CurAddressState->MemRegion->Length; | 598 | error("section '" + Ctx->OutSec->Name + "' will not fit in region '" + |
| 570 | error("section '" + CurAddressState->OutSec->Name + | 599 | Ctx->MemRegion->Name + "': overflowed by " + Twine(OverflowAmt) + |
| 571 | "' will not fit in region '" + CurAddressState->MemRegion->Name + | 600 | " bytes"); |
| 572 | "': overflowed by " + Twine(OverflowAmt) + " bytes"); | ||
| 573 | } | 601 | } |
| 574 | } | 602 | } |
| 575 | } | 603 | } |
| 576 | 604 | ||
| 577 | void LinkerScript::switchTo(OutputSection *Sec) { | 605 | void LinkerScript::switchTo(OutputSection *Sec) { |
| 578 | if (CurAddressState->OutSec == Sec) | 606 | if (Ctx->OutSec == Sec) |
| 579 | return; | 607 | return; |
| 580 | 608 | ||
| 581 | CurAddressState->OutSec = Sec; | 609 | Ctx->OutSec = Sec; |
| 582 | CurAddressState->OutSec->Addr = | 610 | Ctx->OutSec->Addr = advance(0, Ctx->OutSec->Alignment); |
| 583 | advance(0, CurAddressState->OutSec->Alignment); | ||
| 584 | 611 | ||
| 585 | // If neither AT nor AT> is specified for an allocatable section, the linker | 612 | // If neither AT nor AT> is specified for an allocatable section, the linker |
| 586 | // will set the LMA such that the difference between VMA and LMA for the | 613 | // will set the LMA such that the difference between VMA and LMA for the |
| 587 | // section is the same as the preceding output section in the same region | 614 | // section is the same as the preceding output section in the same region |
| 588 | // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html | 615 | // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html |
| 589 | if (CurAddressState->LMAOffset) | 616 | if (Ctx->LMAOffset) |
| 590 | CurAddressState->OutSec->LMAOffset = CurAddressState->LMAOffset(); | 617 | Ctx->OutSec->LMAOffset = Ctx->LMAOffset(); |
| 591 | } | ||
| 592 | |||
| 593 | void LinkerScript::process(BaseCommand &Base) { | ||
| 594 | // This handles the assignments to symbol or to the dot. | ||
| 595 | if (auto *Cmd = dyn_cast<SymbolAssignment>(&Base)) { | ||
| 596 | assignSymbol(Cmd, true); | ||
| 597 | return; | ||
| 598 | } | ||
| 599 | |||
| 600 | // Handle BYTE(), SHORT(), LONG(), or QUAD(). | ||
| 601 | if (auto *Cmd = dyn_cast<BytesDataCommand>(&Base)) { | ||
| 602 | Cmd->Offset = Dot - CurAddressState->OutSec->Addr; | ||
| 603 | Dot += Cmd->Size; | ||
| 604 | CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr; | ||
| 605 | return; | ||
| 606 | } | ||
| 607 | |||
| 608 | // Handle ASSERT(). | ||
| 609 | if (auto *Cmd = dyn_cast<AssertCommand>(&Base)) { | ||
| 610 | Cmd->Expression(); | ||
| 611 | return; | ||
| 612 | } | ||
| 613 | |||
| 614 | // Handle a single input section description command. | ||
| 615 | // It calculates and assigns the offsets for each section and also | ||
| 616 | // updates the output section size. | ||
| 617 | auto &Cmd = cast<InputSectionDescription>(Base); | ||
| 618 | for (InputSection *Sec : Cmd.Sections) { | ||
| 619 | // We tentatively added all synthetic sections at the beginning and removed | ||
| 620 | // empty ones afterwards (because there is no way to know whether they were | ||
| 621 | // going be empty or not other than actually running linker scripts.) | ||
| 622 | // We need to ignore remains of empty sections. | ||
| 623 | if (auto *S = dyn_cast<SyntheticSection>(Sec)) | ||
| 624 | if (S->empty()) | ||
| 625 | continue; | ||
| 626 | |||
| 627 | if (!Sec->Live) | ||
| 628 | continue; | ||
| 629 | assert(CurAddressState->OutSec == Sec->getParent()); | ||
| 630 | output(Sec); | ||
| 631 | } | ||
| 632 | } | 618 | } |
| 633 | 619 | ||
| 634 | // This function searches for a memory region to place the given output | 620 | // This function searches for a memory region to place the given output |
| 635 | // section in. If found, a pointer to the appropriate memory region is | 621 | // section in. If found, a pointer to the appropriate memory region is |
| 636 | // returned. Otherwise, a nullptr is returned. | 622 | // returned. Otherwise, a nullptr is returned. |
| 637 | MemoryRegion *LinkerScript::findMemoryRegion(OutputSectionCommand *Cmd) { | 623 | MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) { |
| 638 | // If a memory region name was specified in the output section command, | 624 | // If a memory region name was specified in the output section command, |
| 639 | // then try to find that region first. | 625 | // then try to find that region first. |
| 640 | if (!Cmd->MemoryRegionName.empty()) { | 626 | if (!Sec->MemoryRegionName.empty()) { |
| 641 | auto It = Opt.MemoryRegions.find(Cmd->MemoryRegionName); | 627 | auto It = MemoryRegions.find(Sec->MemoryRegionName); |
| 642 | if (It != Opt.MemoryRegions.end()) | 628 | if (It != MemoryRegions.end()) |
| 643 | return &It->second; | 629 | return It->second; |
| 644 | error("memory region '" + Cmd->MemoryRegionName + "' not declared"); | 630 | error("memory region '" + Sec->MemoryRegionName + "' not declared"); |
| 645 | return nullptr; | 631 | return nullptr; |
| 646 | } | 632 | } |
| 647 | 633 | ||
| 648 | // If at least one memory region is defined, all sections must | 634 | // If at least one memory region is defined, all sections must |
| 649 | // belong to some memory region. Otherwise, we don't need to do | 635 | // belong to some memory region. Otherwise, we don't need to do |
| 650 | // anything for memory regions. | 636 | // anything for memory regions. |
| 651 | if (Opt.MemoryRegions.empty()) | 637 | if (MemoryRegions.empty()) |
| 652 | return nullptr; | 638 | return nullptr; |
| 653 | 639 | ||
| 654 | OutputSection *Sec = Cmd->Sec; | ||
| 655 | // See if a region can be found by matching section flags. | 640 | // See if a region can be found by matching section flags. |
| 656 | for (auto &Pair : Opt.MemoryRegions) { | 641 | for (auto &Pair : MemoryRegions) { |
| 657 | MemoryRegion &M = Pair.second; | 642 | MemoryRegion *M = Pair.second; |
| 658 | if ((M.Flags & Sec->Flags) && (M.NegFlags & Sec->Flags) == 0) | 643 | if ((M->Flags & Sec->Flags) && (M->NegFlags & Sec->Flags) == 0) |
| 659 | return &M; | 644 | return M; |
| 660 | } | 645 | } |
| 661 | 646 | ||
| 662 | // Otherwise, no suitable region was found. | 647 | // Otherwise, no suitable region was found. |
| ... | @@ -667,33 +652,73 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSectionCommand *Cmd) { | ... | @@ -667,33 +652,73 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSectionCommand *Cmd) { |
| 667 | 652 | ||
| 668 | // This function assigns offsets to input sections and an output section | 653 | // This function assigns offsets to input sections and an output section |
| 669 | // for a single sections command (e.g. ".text { *(.text); }"). | 654 | // for a single sections command (e.g. ".text { *(.text); }"). |
| 670 | void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) { | 655 | void LinkerScript::assignOffsets(OutputSection *Sec) { |
| 671 | OutputSection *Sec = Cmd->Sec; | ||
| 672 | if (!Sec) | ||
| 673 | return; | ||
| 674 | |||
| 675 | if (!(Sec->Flags & SHF_ALLOC)) | 656 | if (!(Sec->Flags & SHF_ALLOC)) |
| 676 | Dot = 0; | 657 | Dot = 0; |
| 677 | else if (Cmd->AddrExpr) | 658 | else if (Sec->AddrExpr) |
| 678 | setDot(Cmd->AddrExpr, Cmd->Location, false); | 659 | setDot(Sec->AddrExpr, Sec->Location, false); |
| 679 | 660 | ||
| 680 | if (Cmd->LMAExpr) { | 661 | Ctx->MemRegion = Sec->MemRegion; |
| 662 | if (Ctx->MemRegion) | ||
| 663 | Dot = Ctx->MemRegionOffset[Ctx->MemRegion]; | ||
| 664 | |||
| 665 | if (Sec->LMAExpr) { | ||
| 681 | uint64_t D = Dot; | 666 | uint64_t D = Dot; |
| 682 | CurAddressState->LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; }; | 667 | Ctx->LMAOffset = [=] { return Sec->LMAExpr().getValue() - D; }; |
| 683 | } | 668 | } |
| 684 | 669 | ||
| 685 | CurAddressState->MemRegion = Cmd->MemRegion; | ||
| 686 | if (CurAddressState->MemRegion) | ||
| 687 | Dot = CurAddressState->MemRegionOffset[CurAddressState->MemRegion]; | ||
| 688 | switchTo(Sec); | 670 | switchTo(Sec); |
| 689 | 671 | ||
| 690 | // We do not support custom layout for compressed debug sectons. | 672 | // The Size previously denoted how many InputSections had been added to this |
| 691 | // At this point we already know their size and have compressed content. | 673 | // section, and was used for sorting SHF_LINK_ORDER sections. Reset it to |
| 692 | if (CurAddressState->OutSec->Flags & SHF_COMPRESSED) | 674 | // compute the actual size value. |
| 693 | return; | 675 | Sec->Size = 0; |
| 676 | |||
| 677 | // We visited SectionsCommands from processSectionCommands to | ||
| 678 | // layout sections. Now, we visit SectionsCommands again to fix | ||
| 679 | // section offsets. | ||
| 680 | for (BaseCommand *Base : Sec->SectionCommands) { | ||
| 681 | // This handles the assignments to symbol or to the dot. | ||
| 682 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { | ||
| 683 | assignSymbol(Cmd, true); | ||
| 684 | continue; | ||
| 685 | } | ||
| 686 | |||
| 687 | // Handle BYTE(), SHORT(), LONG(), or QUAD(). | ||
| 688 | if (auto *Cmd = dyn_cast<ByteCommand>(Base)) { | ||
| 689 | Cmd->Offset = Dot - Ctx->OutSec->Addr; | ||
| 690 | Dot += Cmd->Size; | ||
| 691 | if (Ctx->MemRegion) | ||
| 692 | Ctx->MemRegionOffset[Ctx->MemRegion] += Cmd->Size; | ||
| 693 | Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr; | ||
| 694 | continue; | ||
| 695 | } | ||
| 696 | |||
| 697 | // Handle ASSERT(). | ||
| 698 | if (auto *Cmd = dyn_cast<AssertCommand>(Base)) { | ||
| 699 | Cmd->Expression(); | ||
| 700 | continue; | ||
| 701 | } | ||
| 694 | 702 | ||
| 695 | for (BaseCommand *C : Cmd->Commands) | 703 | // Handle a single input section description command. |
| 696 | process(*C); | 704 | // It calculates and assigns the offsets for each section and also |
| 705 | // updates the output section size. | ||
| 706 | auto *Cmd = cast<InputSectionDescription>(Base); | ||
| 707 | for (InputSection *Sec : Cmd->Sections) { | ||
| 708 | // We tentatively added all synthetic sections at the beginning and | ||
| 709 | // removed empty ones afterwards (because there is no way to know | ||
| 710 | // whether they were going be empty or not other than actually running | ||
| 711 | // linker scripts.) We need to ignore remains of empty sections. | ||
| 712 | if (auto *S = dyn_cast<SyntheticSection>(Sec)) | ||
| 713 | if (S->empty()) | ||
| 714 | continue; | ||
| 715 | |||
| 716 | if (!Sec->Live) | ||
| 717 | continue; | ||
| 718 | assert(Ctx->OutSec == Sec->getParent()); | ||
| 719 | output(Sec); | ||
| 720 | } | ||
| 721 | } | ||
| 697 | } | 722 | } |
| 698 | 723 | ||
| 699 | void LinkerScript::removeEmptyCommands() { | 724 | void LinkerScript::removeEmptyCommands() { |
| ... | @@ -703,17 +728,15 @@ void LinkerScript::removeEmptyCommands() { | ... | @@ -703,17 +728,15 @@ void LinkerScript::removeEmptyCommands() { |
| 703 | // clutter the output. | 728 | // clutter the output. |
| 704 | // We instead remove trivially empty sections. The bfd linker seems even | 729 | // We instead remove trivially empty sections. The bfd linker seems even |
| 705 | // more aggressive at removing them. | 730 | // more aggressive at removing them. |
| 706 | auto Pos = std::remove_if( | 731 | llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { |
| 707 | Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) { | 732 | if (auto *Sec = dyn_cast<OutputSection>(Base)) |
| 708 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) | 733 | return !Sec->Live; |
| 709 | return Cmd->Sec == nullptr; | 734 | return false; |
| 710 | return false; | 735 | }); |
| 711 | }); | ||
| 712 | Opt.Commands.erase(Pos, Opt.Commands.end()); | ||
| 713 | } | 736 | } |
| 714 | 737 | ||
| 715 | static bool isAllSectionDescription(const OutputSectionCommand &Cmd) { | 738 | static bool isAllSectionDescription(const OutputSection &Cmd) { |
| 716 | for (BaseCommand *Base : Cmd.Commands) | 739 | for (BaseCommand *Base : Cmd.SectionCommands) |
| 717 | if (!isa<InputSectionDescription>(*Base)) | 740 | if (!isa<InputSectionDescription>(*Base)) |
| 718 | return false; | 741 | return false; |
| 719 | return true; | 742 | return true; |
| ... | @@ -721,38 +744,55 @@ static bool isAllSectionDescription(const OutputSectionCommand &Cmd) { | ... | @@ -721,38 +744,55 @@ static bool isAllSectionDescription(const OutputSectionCommand &Cmd) { |
| 721 | 744 | ||
| 722 | void LinkerScript::adjustSectionsBeforeSorting() { | 745 | void LinkerScript::adjustSectionsBeforeSorting() { |
| 723 | // If the output section contains only symbol assignments, create a | 746 | // If the output section contains only symbol assignments, create a |
| 724 | // corresponding output section. The bfd linker seems to only create them if | 747 | // corresponding output section. The issue is what to do with linker script |
| 725 | // '.' is assigned to, but creating these section should not have any bad | 748 | // like ".foo : { symbol = 42; }". One option would be to convert it to |
| 726 | // consequeces and gives us a section to put the symbol in. | 749 | // "symbol = 42;". That is, move the symbol out of the empty section |
| 750 | // description. That seems to be what bfd does for this simple case. The | ||
| 751 | // problem is that this is not completely general. bfd will give up and | ||
| 752 | // create a dummy section too if there is a ". = . + 1" inside the section | ||
| 753 | // for example. | ||
| 754 | // Given that we want to create the section, we have to worry what impact | ||
| 755 | // it will have on the link. For example, if we just create a section with | ||
| 756 | // 0 for flags, it would change which PT_LOADs are created. | ||
| 757 | // We could remember that that particular section is dummy and ignore it in | ||
| 758 | // other parts of the linker, but unfortunately there are quite a few places | ||
| 759 | // that would need to change: | ||
| 760 | // * The program header creation. | ||
| 761 | // * The orphan section placement. | ||
| 762 | // * The address assignment. | ||
| 763 | // The other option is to pick flags that minimize the impact the section | ||
| 764 | // will have on the rest of the linker. That is why we copy the flags from | ||
| 765 | // the previous sections. Only a few flags are needed to keep the impact low. | ||
| 727 | uint64_t Flags = SHF_ALLOC; | 766 | uint64_t Flags = SHF_ALLOC; |
| 728 | 767 | ||
| 729 | for (int I = 0, E = Opt.Commands.size(); I != E; ++I) { | 768 | for (BaseCommand *Cmd : SectionCommands) { |
| 730 | auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]); | 769 | auto *Sec = dyn_cast<OutputSection>(Cmd); |
| 731 | if (!Cmd) | 770 | if (!Sec) |
| 732 | continue; | 771 | continue; |
| 733 | if (OutputSection *Sec = Cmd->Sec) { | 772 | if (Sec->Live) { |
| 734 | Flags = Sec->Flags; | 773 | Flags = Sec->Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR); |
| 735 | continue; | 774 | continue; |
| 736 | } | 775 | } |
| 737 | 776 | ||
| 738 | if (isAllSectionDescription(*Cmd)) | 777 | if (isAllSectionDescription(*Sec)) |
| 739 | continue; | 778 | continue; |
| 740 | 779 | ||
| 741 | auto *OutSec = make<OutputSection>(Cmd->Name, SHT_PROGBITS, Flags); | 780 | Sec->Live = true; |
| 742 | OutSec->SectionIndex = I; | 781 | Sec->Flags = Flags; |
| 743 | Cmd->Sec = OutSec; | ||
| 744 | SecToCommand[OutSec] = Cmd; | ||
| 745 | } | 782 | } |
| 746 | } | 783 | } |
| 747 | 784 | ||
| 748 | void LinkerScript::adjustSectionsAfterSorting() { | 785 | void LinkerScript::adjustSectionsAfterSorting() { |
| 749 | // Try and find an appropriate memory region to assign offsets in. | 786 | // Try and find an appropriate memory region to assign offsets in. |
| 750 | for (BaseCommand *Base : Opt.Commands) { | 787 | for (BaseCommand *Base : SectionCommands) { |
| 751 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) { | 788 | if (auto *Sec = dyn_cast<OutputSection>(Base)) { |
| 752 | Cmd->MemRegion = findMemoryRegion(Cmd); | 789 | if (!Sec->Live) |
| 790 | continue; | ||
| 791 | Sec->MemRegion = findMemoryRegion(Sec); | ||
| 753 | // Handle align (e.g. ".foo : ALIGN(16) { ... }"). | 792 | // Handle align (e.g. ".foo : ALIGN(16) { ... }"). |
| 754 | if (Cmd->AlignExpr && Cmd->Sec) | 793 | if (Sec->AlignExpr) |
| 755 | Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue()); | 794 | Sec->Alignment = |
| 795 | std::max<uint32_t>(Sec->Alignment, Sec->AlignExpr().getValue()); | ||
| 756 | } | 796 | } |
| 757 | } | 797 | } |
| 758 | 798 | ||
| ... | @@ -764,108 +804,112 @@ void LinkerScript::adjustSectionsAfterSorting() { | ... | @@ -764,108 +804,112 @@ void LinkerScript::adjustSectionsAfterSorting() { |
| 764 | // SECTIONS { .aaa : { *(.aaa) } } | 804 | // SECTIONS { .aaa : { *(.aaa) } } |
| 765 | std::vector<StringRef> DefPhdrs; | 805 | std::vector<StringRef> DefPhdrs; |
| 766 | auto FirstPtLoad = | 806 | auto FirstPtLoad = |
| 767 | std::find_if(Opt.PhdrsCommands.begin(), Opt.PhdrsCommands.end(), | 807 | std::find_if(PhdrsCommands.begin(), PhdrsCommands.end(), |
| 768 | [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; }); | 808 | [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; }); |
| 769 | if (FirstPtLoad != Opt.PhdrsCommands.end()) | 809 | if (FirstPtLoad != PhdrsCommands.end()) |
| 770 | DefPhdrs.push_back(FirstPtLoad->Name); | 810 | DefPhdrs.push_back(FirstPtLoad->Name); |
| 771 | 811 | ||
| 772 | // Walk the commands and propagate the program headers to commands that don't | 812 | // Walk the commands and propagate the program headers to commands that don't |
| 773 | // explicitly specify them. | 813 | // explicitly specify them. |
| 774 | for (BaseCommand *Base : Opt.Commands) { | 814 | for (BaseCommand *Base : SectionCommands) { |
| 775 | auto *Cmd = dyn_cast<OutputSectionCommand>(Base); | 815 | auto *Sec = dyn_cast<OutputSection>(Base); |
| 776 | if (!Cmd) | 816 | if (!Sec) |
| 777 | continue; | 817 | continue; |
| 778 | 818 | ||
| 779 | if (Cmd->Phdrs.empty()) { | 819 | if (Sec->Phdrs.empty()) { |
| 780 | OutputSection *Sec = Cmd->Sec; | ||
| 781 | // To match the bfd linker script behaviour, only propagate program | 820 | // To match the bfd linker script behaviour, only propagate program |
| 782 | // headers to sections that are allocated. | 821 | // headers to sections that are allocated. |
| 783 | if (Sec && (Sec->Flags & SHF_ALLOC)) | 822 | if (Sec->Flags & SHF_ALLOC) |
| 784 | Cmd->Phdrs = DefPhdrs; | 823 | Sec->Phdrs = DefPhdrs; |
| 785 | } else { | 824 | } else { |
| 786 | DefPhdrs = Cmd->Phdrs; | 825 | DefPhdrs = Sec->Phdrs; |
| 787 | } | 826 | } |
| 788 | } | 827 | } |
| 789 | |||
| 790 | removeEmptyCommands(); | ||
| 791 | } | 828 | } |
| 792 | 829 | ||
| 793 | void LinkerScript::processNonSectionCommands() { | 830 | static OutputSection *findFirstSection(PhdrEntry *Load) { |
| 794 | for (BaseCommand *Base : Opt.Commands) { | 831 | for (OutputSection *Sec : OutputSections) |
| 795 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) | 832 | if (Sec->PtLoad == Load) |
| 796 | assignSymbol(Cmd, false); | 833 | return Sec; |
| 797 | else if (auto *Cmd = dyn_cast<AssertCommand>(Base)) | 834 | return nullptr; |
| 798 | Cmd->Expression(); | ||
| 799 | } | ||
| 800 | } | 835 | } |
| 801 | 836 | ||
| 802 | void LinkerScript::allocateHeaders(std::vector<PhdrEntry> &Phdrs) { | 837 | // Try to find an address for the file and program headers output sections, |
| 838 | // which were unconditionally added to the first PT_LOAD segment earlier. | ||
| 839 | // | ||
| 840 | // When using the default layout, we check if the headers fit below the first | ||
| 841 | // allocated section. When using a linker script, we also check if the headers | ||
| 842 | // are covered by the output section. This allows omitting the headers by not | ||
| 843 | // leaving enough space for them in the linker script; this pattern is common | ||
| 844 | // in embedded systems. | ||
| 845 | // | ||
| 846 | // If there isn't enough space for these sections, we'll remove them from the | ||
| 847 | // PT_LOAD segment, and we'll also remove the PT_PHDR segment. | ||
| 848 | void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) { | ||
| 803 | uint64_t Min = std::numeric_limits<uint64_t>::max(); | 849 | uint64_t Min = std::numeric_limits<uint64_t>::max(); |
| 804 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 850 | for (OutputSection *Sec : OutputSections) |
| 805 | OutputSection *Sec = Cmd->Sec; | ||
| 806 | if (Sec->Flags & SHF_ALLOC) | 851 | if (Sec->Flags & SHF_ALLOC) |
| 807 | Min = std::min<uint64_t>(Min, Sec->Addr); | 852 | Min = std::min<uint64_t>(Min, Sec->Addr); |
| 808 | } | ||
| 809 | 853 | ||
| 810 | auto FirstPTLoad = llvm::find_if( | 854 | auto It = llvm::find_if( |
| 811 | Phdrs, [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); | 855 | Phdrs, [](const PhdrEntry *E) { return E->p_type == PT_LOAD; }); |
| 812 | if (FirstPTLoad == Phdrs.end()) | 856 | if (It == Phdrs.end()) |
| 813 | return; | 857 | return; |
| 858 | PhdrEntry *FirstPTLoad = *It; | ||
| 814 | 859 | ||
| 815 | uint64_t HeaderSize = getHeaderSize(); | 860 | uint64_t HeaderSize = getHeaderSize(); |
| 816 | if (HeaderSize <= Min || Script->hasPhdrsCommands()) { | 861 | // When linker script with SECTIONS is being used, don't output headers |
| 862 | // unless there's a space for them. | ||
| 863 | uint64_t Base = HasSectionsCommand ? alignDown(Min, Config->MaxPageSize) : 0; | ||
| 864 | if (HeaderSize <= Min - Base || Script->hasPhdrsCommands()) { | ||
| 817 | Min = alignDown(Min - HeaderSize, Config->MaxPageSize); | 865 | Min = alignDown(Min - HeaderSize, Config->MaxPageSize); |
| 818 | Out::ElfHeader->Addr = Min; | 866 | Out::ElfHeader->Addr = Min; |
| 819 | Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size; | 867 | Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size; |
| 820 | return; | 868 | return; |
| 821 | } | 869 | } |
| 822 | 870 | ||
| 823 | assert(FirstPTLoad->First == Out::ElfHeader); | 871 | Out::ElfHeader->PtLoad = nullptr; |
| 824 | OutputSection *ActualFirst = nullptr; | 872 | Out::ProgramHeaders->PtLoad = nullptr; |
| 825 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 873 | FirstPTLoad->FirstSec = findFirstSection(FirstPTLoad); |
| 826 | OutputSection *Sec = Cmd->Sec; | ||
| 827 | if (Sec->FirstInPtLoad == Out::ElfHeader) { | ||
| 828 | ActualFirst = Sec; | ||
| 829 | break; | ||
| 830 | } | ||
| 831 | } | ||
| 832 | if (ActualFirst) { | ||
| 833 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | ||
| 834 | OutputSection *Sec = Cmd->Sec; | ||
| 835 | if (Sec->FirstInPtLoad == Out::ElfHeader) | ||
| 836 | Sec->FirstInPtLoad = ActualFirst; | ||
| 837 | } | ||
| 838 | FirstPTLoad->First = ActualFirst; | ||
| 839 | } else { | ||
| 840 | Phdrs.erase(FirstPTLoad); | ||
| 841 | } | ||
| 842 | 874 | ||
| 843 | auto PhdrI = llvm::find_if( | 875 | llvm::erase_if(Phdrs, |
| 844 | Phdrs, [](const PhdrEntry &E) { return E.p_type == PT_PHDR; }); | 876 | [](const PhdrEntry *E) { return E->p_type == PT_PHDR; }); |
| 845 | if (PhdrI != Phdrs.end()) | ||
| 846 | Phdrs.erase(PhdrI); | ||
| 847 | } | 877 | } |
| 848 | 878 | ||
| 849 | LinkerScript::AddressState::AddressState(const ScriptConfiguration &Opt) { | 879 | LinkerScript::AddressState::AddressState() { |
| 850 | for (auto &MRI : Opt.MemoryRegions) { | 880 | for (auto &MRI : Script->MemoryRegions) { |
| 851 | const MemoryRegion *MR = &MRI.second; | 881 | const MemoryRegion *MR = MRI.second; |
| 852 | MemRegionOffset[MR] = MR->Origin; | 882 | MemRegionOffset[MR] = MR->Origin; |
| 853 | } | 883 | } |
| 854 | } | 884 | } |
| 855 | 885 | ||
| 886 | static uint64_t getInitialDot() { | ||
| 887 | // By default linker scripts use an initial value of 0 for '.', | ||
| 888 | // but prefer -image-base if set. | ||
| 889 | if (Script->HasSectionsCommand) | ||
| 890 | return Config->ImageBase ? *Config->ImageBase : 0; | ||
| 891 | |||
| 892 | uint64_t StartAddr = UINT64_MAX; | ||
| 893 | // The Sections with -T<section> have been sorted in order of ascending | ||
| 894 | // address. We must lower StartAddr if the lowest -T<section address> as | ||
| 895 | // calls to setDot() must be monotonically increasing. | ||
| 896 | for (auto &KV : Config->SectionStartMap) | ||
| 897 | StartAddr = std::min(StartAddr, KV.second); | ||
| 898 | return std::min(StartAddr, Target->getImageBase() + elf::getHeaderSize()); | ||
| 899 | } | ||
| 900 | |||
| 901 | // Here we assign addresses as instructed by linker script SECTIONS | ||
| 902 | // sub-commands. Doing that allows us to use final VA values, so here | ||
| 903 | // we also handle rest commands like symbol assignments and ASSERTs. | ||
| 856 | void LinkerScript::assignAddresses() { | 904 | void LinkerScript::assignAddresses() { |
| 857 | // Assign addresses as instructed by linker script SECTIONS sub-commands. | 905 | Dot = getInitialDot(); |
| 858 | Dot = 0; | 906 | |
| 859 | auto State = make_unique<AddressState>(Opt); | 907 | auto Deleter = make_unique<AddressState>(); |
| 860 | // CurAddressState captures the local AddressState and makes it accessible | 908 | Ctx = Deleter.get(); |
| 861 | // deliberately. This is needed as there are some cases where we cannot just | ||
| 862 | // thread the current state through to a lambda function created by the | ||
| 863 | // script parser. | ||
| 864 | CurAddressState = State.get(); | ||
| 865 | ErrorOnMissingSection = true; | 909 | ErrorOnMissingSection = true; |
| 866 | switchTo(Aether); | 910 | switchTo(Aether); |
| 867 | 911 | ||
| 868 | for (BaseCommand *Base : Opt.Commands) { | 912 | for (BaseCommand *Base : SectionCommands) { |
| 869 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { | 913 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { |
| 870 | assignSymbol(Cmd, false); | 914 | assignSymbol(Cmd, false); |
| 871 | continue; | 915 | continue; |
| ... | @@ -876,380 +920,98 @@ void LinkerScript::assignAddresses() { | ... | @@ -876,380 +920,98 @@ void LinkerScript::assignAddresses() { |
| 876 | continue; | 920 | continue; |
| 877 | } | 921 | } |
| 878 | 922 | ||
| 879 | auto *Cmd = cast<OutputSectionCommand>(Base); | 923 | assignOffsets(cast<OutputSection>(Base)); |
| 880 | assignOffsets(Cmd); | ||
| 881 | } | 924 | } |
| 882 | CurAddressState = nullptr; | 925 | Ctx = nullptr; |
| 883 | } | 926 | } |
| 884 | 927 | ||
| 885 | // Creates program headers as instructed by PHDRS linker script command. | 928 | // Creates program headers as instructed by PHDRS linker script command. |
| 886 | std::vector<PhdrEntry> LinkerScript::createPhdrs() { | 929 | std::vector<PhdrEntry *> LinkerScript::createPhdrs() { |
| 887 | std::vector<PhdrEntry> Ret; | 930 | std::vector<PhdrEntry *> Ret; |
| 888 | 931 | ||
| 889 | // Process PHDRS and FILEHDR keywords because they are not | 932 | // Process PHDRS and FILEHDR keywords because they are not |
| 890 | // real output sections and cannot be added in the following loop. | 933 | // real output sections and cannot be added in the following loop. |
| 891 | for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) { | 934 | for (const PhdrsCommand &Cmd : PhdrsCommands) { |
| 892 | Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags); | 935 | PhdrEntry *Phdr = make<PhdrEntry>(Cmd.Type, Cmd.Flags ? *Cmd.Flags : PF_R); |
| 893 | PhdrEntry &Phdr = Ret.back(); | ||
| 894 | 936 | ||
| 895 | if (Cmd.HasFilehdr) | 937 | if (Cmd.HasFilehdr) |
| 896 | Phdr.add(Out::ElfHeader); | 938 | Phdr->add(Out::ElfHeader); |
| 897 | if (Cmd.HasPhdrs) | 939 | if (Cmd.HasPhdrs) |
| 898 | Phdr.add(Out::ProgramHeaders); | 940 | Phdr->add(Out::ProgramHeaders); |
| 899 | 941 | ||
| 900 | if (Cmd.LMAExpr) { | 942 | if (Cmd.LMAExpr) { |
| 901 | Phdr.p_paddr = Cmd.LMAExpr().getValue(); | 943 | Phdr->p_paddr = Cmd.LMAExpr().getValue(); |
| 902 | Phdr.HasLMA = true; | 944 | Phdr->HasLMA = true; |
| 903 | } | 945 | } |
| 946 | Ret.push_back(Phdr); | ||
| 904 | } | 947 | } |
| 905 | 948 | ||
| 906 | // Add output sections to program headers. | 949 | // Add output sections to program headers. |
| 907 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 950 | for (OutputSection *Sec : OutputSections) { |
| 908 | // Assign headers specified by linker script | 951 | // Assign headers specified by linker script |
| 909 | for (size_t Id : getPhdrIndices(Cmd)) { | 952 | for (size_t Id : getPhdrIndices(Sec)) { |
| 910 | OutputSection *Sec = Cmd->Sec; | 953 | Ret[Id]->add(Sec); |
| 911 | Ret[Id].add(Sec); | 954 | if (!PhdrsCommands[Id].Flags.hasValue()) |
| 912 | if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) | 955 | Ret[Id]->p_flags |= Sec->getPhdrFlags(); |
| 913 | Ret[Id].p_flags |= Sec->getPhdrFlags(); | ||
| 914 | } | 956 | } |
| 915 | } | 957 | } |
| 916 | return Ret; | 958 | return Ret; |
| 917 | } | 959 | } |
| 918 | 960 | ||
| 919 | bool LinkerScript::ignoreInterpSection() { | 961 | // Returns true if we should emit an .interp section. |
| 920 | // Ignore .interp section in case we have PHDRS specification | ||
| 921 | // and PT_INTERP isn't listed. | ||
| 922 | if (Opt.PhdrsCommands.empty()) | ||
| 923 | return false; | ||
| 924 | for (PhdrsCommand &Cmd : Opt.PhdrsCommands) | ||
| 925 | if (Cmd.Type == PT_INTERP) | ||
| 926 | return false; | ||
| 927 | return true; | ||
| 928 | } | ||
| 929 | |||
| 930 | OutputSectionCommand *LinkerScript::getCmd(OutputSection *Sec) const { | ||
| 931 | auto I = SecToCommand.find(Sec); | ||
| 932 | if (I == SecToCommand.end()) | ||
| 933 | return nullptr; | ||
| 934 | return I->second; | ||
| 935 | } | ||
| 936 | |||
| 937 | void OutputSectionCommand::sort(std::function<int(InputSectionBase *S)> Order) { | ||
| 938 | typedef std::pair<unsigned, InputSection *> Pair; | ||
| 939 | auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; }; | ||
| 940 | |||
| 941 | std::vector<Pair> V; | ||
| 942 | assert(Commands.size() == 1); | ||
| 943 | auto *ISD = cast<InputSectionDescription>(Commands[0]); | ||
| 944 | for (InputSection *S : ISD->Sections) | ||
| 945 | V.push_back({Order(S), S}); | ||
| 946 | std::stable_sort(V.begin(), V.end(), Comp); | ||
| 947 | ISD->Sections.clear(); | ||
| 948 | for (Pair &P : V) | ||
| 949 | ISD->Sections.push_back(P.second); | ||
| 950 | } | ||
| 951 | |||
| 952 | // Returns true if S matches /Filename.?\.o$/. | ||
| 953 | static bool isCrtBeginEnd(StringRef S, StringRef Filename) { | ||
| 954 | if (!S.endswith(".o")) | ||
| 955 | return false; | ||
| 956 | S = S.drop_back(2); | ||
| 957 | if (S.endswith(Filename)) | ||
| 958 | return true; | ||
| 959 | return !S.empty() && S.drop_back().endswith(Filename); | ||
| 960 | } | ||
| 961 | |||
| 962 | static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); } | ||
| 963 | static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); } | ||
| 964 | |||
| 965 | // .ctors and .dtors are sorted by this priority from highest to lowest. | ||
| 966 | // | ||
| 967 | // 1. The section was contained in crtbegin (crtbegin contains | ||
| 968 | // some sentinel value in its .ctors and .dtors so that the runtime | ||
| 969 | // can find the beginning of the sections.) | ||
| 970 | // | ||
| 971 | // 2. The section has an optional priority value in the form of ".ctors.N" | ||
| 972 | // or ".dtors.N" where N is a number. Unlike .{init,fini}_array, | ||
| 973 | // they are compared as string rather than number. | ||
| 974 | // | ||
| 975 | // 3. The section is just ".ctors" or ".dtors". | ||
| 976 | // | 962 | // |
| 977 | // 4. The section was contained in crtend, which contains an end marker. | 963 | // We usually do. But if PHDRS commands are given, and |
| 978 | // | 964 | // no PT_INTERP is there, there's no place to emit an |
| 979 | // In an ideal world, we don't need this function because .init_array and | 965 | // .interp, so we don't do that in that case. |
| 980 | // .ctors are duplicate features (and .init_array is newer.) However, there | 966 | bool LinkerScript::needsInterpSection() { |
| 981 | // are too many real-world use cases of .ctors, so we had no choice to | 967 | if (PhdrsCommands.empty()) |
| 982 | // support that with this rather ad-hoc semantics. | 968 | return true; |
| 983 | static bool compCtors(const InputSection *A, const InputSection *B) { | 969 | for (PhdrsCommand &Cmd : PhdrsCommands) |
| 984 | bool BeginA = isCrtbegin(A->File->getName()); | 970 | if (Cmd.Type == PT_INTERP) |
| 985 | bool BeginB = isCrtbegin(B->File->getName()); | 971 | return true; |
| 986 | if (BeginA != BeginB) | 972 | return false; |
| 987 | return BeginA; | ||
| 988 | bool EndA = isCrtend(A->File->getName()); | ||
| 989 | bool EndB = isCrtend(B->File->getName()); | ||
| 990 | if (EndA != EndB) | ||
| 991 | return EndB; | ||
| 992 | StringRef X = A->Name; | ||
| 993 | StringRef Y = B->Name; | ||
| 994 | assert(X.startswith(".ctors") || X.startswith(".dtors")); | ||
| 995 | assert(Y.startswith(".ctors") || Y.startswith(".dtors")); | ||
| 996 | X = X.substr(6); | ||
| 997 | Y = Y.substr(6); | ||
| 998 | if (X.empty() && Y.empty()) | ||
| 999 | return false; | ||
| 1000 | return X < Y; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | // Sorts input sections by the special rules for .ctors and .dtors. | ||
| 1004 | // Unfortunately, the rules are different from the one for .{init,fini}_array. | ||
| 1005 | // Read the comment above. | ||
| 1006 | void OutputSectionCommand::sortCtorsDtors() { | ||
| 1007 | assert(Commands.size() == 1); | ||
| 1008 | auto *ISD = cast<InputSectionDescription>(Commands[0]); | ||
| 1009 | std::stable_sort(ISD->Sections.begin(), ISD->Sections.end(), compCtors); | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | // Sorts input sections by section name suffixes, so that .foo.N comes | ||
| 1013 | // before .foo.M if N < M. Used to sort .{init,fini}_array.N sections. | ||
| 1014 | // We want to keep the original order if the priorities are the same | ||
| 1015 | // because the compiler keeps the original initialization order in a | ||
| 1016 | // translation unit and we need to respect that. | ||
| 1017 | // For more detail, read the section of the GCC's manual about init_priority. | ||
| 1018 | void OutputSectionCommand::sortInitFini() { | ||
| 1019 | // Sort sections by priority. | ||
| 1020 | sort([](InputSectionBase *S) { return getPriority(S->Name); }); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | uint32_t OutputSectionCommand::getFiller() { | ||
| 1024 | if (Filler) | ||
| 1025 | return *Filler; | ||
| 1026 | if (Sec->Flags & SHF_EXECINSTR) | ||
| 1027 | return Target->TrapInstr; | ||
| 1028 | return 0; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { | ||
| 1032 | if (Size == 1) | ||
| 1033 | *Buf = Data; | ||
| 1034 | else if (Size == 2) | ||
| 1035 | write16(Buf, Data, Config->Endianness); | ||
| 1036 | else if (Size == 4) | ||
| 1037 | write32(Buf, Data, Config->Endianness); | ||
| 1038 | else if (Size == 8) | ||
| 1039 | write64(Buf, Data, Config->Endianness); | ||
| 1040 | else | ||
| 1041 | llvm_unreachable("unsupported Size argument"); | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | static bool compareByFilePosition(InputSection *A, InputSection *B) { | ||
| 1045 | // Synthetic doesn't have link order dependecy, stable_sort will keep it last | ||
| 1046 | if (A->kind() == InputSectionBase::Synthetic || | ||
| 1047 | B->kind() == InputSectionBase::Synthetic) | ||
| 1048 | return false; | ||
| 1049 | InputSection *LA = A->getLinkOrderDep(); | ||
| 1050 | InputSection *LB = B->getLinkOrderDep(); | ||
| 1051 | OutputSection *AOut = LA->getParent(); | ||
| 1052 | OutputSection *BOut = LB->getParent(); | ||
| 1053 | if (AOut != BOut) | ||
| 1054 | return AOut->SectionIndex < BOut->SectionIndex; | ||
| 1055 | return LA->OutSecOff < LB->OutSecOff; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | template <class ELFT> | ||
| 1059 | static void finalizeShtGroup(OutputSection *OS, | ||
| 1060 | ArrayRef<InputSection *> Sections) { | ||
| 1061 | assert(Config->Relocatable && Sections.size() == 1); | ||
| 1062 | |||
| 1063 | // sh_link field for SHT_GROUP sections should contain the section index of | ||
| 1064 | // the symbol table. | ||
| 1065 | OS->Link = InX::SymTab->getParent()->SectionIndex; | ||
| 1066 | |||
| 1067 | // sh_info then contain index of an entry in symbol table section which | ||
| 1068 | // provides signature of the section group. | ||
| 1069 | elf::ObjectFile<ELFT> *Obj = Sections[0]->getFile<ELFT>(); | ||
| 1070 | ArrayRef<SymbolBody *> Symbols = Obj->getSymbols(); | ||
| 1071 | OS->Info = InX::SymTab->getSymbolIndex(Symbols[Sections[0]->Info - 1]); | ||
| 1072 | } | 973 | } |
| 1073 | 974 | ||
| 1074 | template <class ELFT> void OutputSectionCommand::finalize() { | 975 | ExprValue LinkerScript::getSymbolValue(StringRef Name, const Twine &Loc) { |
| 1075 | // Link order may be distributed across several InputSectionDescriptions | 976 | if (Name == ".") { |
| 1076 | // but sort must consider them all at once. | 977 | if (Ctx) |
| 1077 | std::vector<InputSection **> ScriptSections; | 978 | return {Ctx->OutSec, false, Dot - Ctx->OutSec->Addr, Loc}; |
| 1078 | std::vector<InputSection *> Sections; | 979 | error(Loc + ": unable to get location counter value"); |
| 1079 | for (BaseCommand *Base : Commands) | 980 | return 0; |
| 1080 | if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) | ||
| 1081 | for (InputSection *&IS : ISD->Sections) { | ||
| 1082 | ScriptSections.push_back(&IS); | ||
| 1083 | Sections.push_back(IS); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | if ((Sec->Flags & SHF_LINK_ORDER)) { | ||
| 1087 | std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); | ||
| 1088 | for (int I = 0, N = Sections.size(); I < N; ++I) | ||
| 1089 | *ScriptSections[I] = Sections[I]; | ||
| 1090 | |||
| 1091 | // We must preserve the link order dependency of sections with the | ||
| 1092 | // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We | ||
| 1093 | // need to translate the InputSection sh_link to the OutputSection sh_link, | ||
| 1094 | // all InputSections in the OutputSection have the same dependency. | ||
| 1095 | if (auto *D = Sections.front()->getLinkOrderDep()) | ||
| 1096 | Sec->Link = D->getParent()->SectionIndex; | ||
| 1097 | } | 981 | } |
| 1098 | 982 | ||
| 1099 | uint32_t Type = Sec->Type; | 983 | if (Symbol *Sym = Symtab->find(Name)) { |
| 1100 | if (Type == SHT_GROUP) { | 984 | if (auto *DS = dyn_cast<Defined>(Sym)) |
| 1101 | finalizeShtGroup<ELFT>(Sec, Sections); | 985 | return {DS->Section, false, DS->Value, Loc}; |
| 1102 | return; | 986 | if (auto *SS = dyn_cast<SharedSymbol>(Sym)) |
| 1103 | } | 987 | if (!ErrorOnMissingSection || SS->CopyRelSec) |
| 1104 | 988 | return {SS->CopyRelSec, false, 0, Loc}; | |
| 1105 | if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL)) | ||
| 1106 | return; | ||
| 1107 | |||
| 1108 | InputSection *First = Sections[0]; | ||
| 1109 | if (isa<SyntheticSection>(First)) | ||
| 1110 | return; | ||
| 1111 | |||
| 1112 | Sec->Link = InX::SymTab->getParent()->SectionIndex; | ||
| 1113 | // sh_info for SHT_REL[A] sections should contain the section header index of | ||
| 1114 | // the section to which the relocation applies. | ||
| 1115 | InputSectionBase *S = First->getRelocatedSection(); | ||
| 1116 | Sec->Info = S->getOutputSection()->SectionIndex; | ||
| 1117 | Sec->Flags |= SHF_INFO_LINK; | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | // Compress section contents if this section contains debug info. | ||
| 1121 | template <class ELFT> void OutputSectionCommand::maybeCompress() { | ||
| 1122 | typedef typename ELFT::Chdr Elf_Chdr; | ||
| 1123 | |||
| 1124 | // Compress only DWARF debug sections. | ||
| 1125 | if (!Config->CompressDebugSections || (Sec->Flags & SHF_ALLOC) || | ||
| 1126 | !Name.startswith(".debug_")) | ||
| 1127 | return; | ||
| 1128 | |||
| 1129 | // Create a section header. | ||
| 1130 | Sec->ZDebugHeader.resize(sizeof(Elf_Chdr)); | ||
| 1131 | auto *Hdr = reinterpret_cast<Elf_Chdr *>(Sec->ZDebugHeader.data()); | ||
| 1132 | Hdr->ch_type = ELFCOMPRESS_ZLIB; | ||
| 1133 | Hdr->ch_size = Sec->Size; | ||
| 1134 | Hdr->ch_addralign = Sec->Alignment; | ||
| 1135 | |||
| 1136 | // Write section contents to a temporary buffer and compress it. | ||
| 1137 | std::vector<uint8_t> Buf(Sec->Size); | ||
| 1138 | writeTo<ELFT>(Buf.data()); | ||
| 1139 | if (Error E = zlib::compress(toStringRef(Buf), Sec->CompressedData)) | ||
| 1140 | fatal("compress failed: " + llvm::toString(std::move(E))); | ||
| 1141 | |||
| 1142 | // Update section headers. | ||
| 1143 | Sec->Size = sizeof(Elf_Chdr) + Sec->CompressedData.size(); | ||
| 1144 | Sec->Flags |= SHF_COMPRESSED; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) { | ||
| 1148 | if (Sec->Type == SHT_NOBITS) | ||
| 1149 | return; | ||
| 1150 | |||
| 1151 | Sec->Loc = Buf; | ||
| 1152 | |||
| 1153 | // If -compress-debug-section is specified and if this is a debug seciton, | ||
| 1154 | // we've already compressed section contents. If that's the case, | ||
| 1155 | // just write it down. | ||
| 1156 | if (!Sec->CompressedData.empty()) { | ||
| 1157 | memcpy(Buf, Sec->ZDebugHeader.data(), Sec->ZDebugHeader.size()); | ||
| 1158 | memcpy(Buf + Sec->ZDebugHeader.size(), Sec->CompressedData.data(), | ||
| 1159 | Sec->CompressedData.size()); | ||
| 1160 | return; | ||
| 1161 | } | 989 | } |
| 1162 | 990 | ||
| 1163 | // Write leading padding. | 991 | error(Loc + ": symbol not found: " + Name); |
| 1164 | std::vector<InputSection *> Sections; | ||
| 1165 | for (BaseCommand *Cmd : Commands) | ||
| 1166 | if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd)) | ||
| 1167 | for (InputSection *IS : ISD->Sections) | ||
| 1168 | if (IS->Live) | ||
| 1169 | Sections.push_back(IS); | ||
| 1170 | uint32_t Filler = getFiller(); | ||
| 1171 | if (Filler) | ||
| 1172 | fill(Buf, Sections.empty() ? Sec->Size : Sections[0]->OutSecOff, Filler); | ||
| 1173 | |||
| 1174 | parallelForEachN(0, Sections.size(), [=](size_t I) { | ||
| 1175 | InputSection *IS = Sections[I]; | ||
| 1176 | IS->writeTo<ELFT>(Buf); | ||
| 1177 | |||
| 1178 | // Fill gaps between sections. | ||
| 1179 | if (Filler) { | ||
| 1180 | uint8_t *Start = Buf + IS->OutSecOff + IS->getSize(); | ||
| 1181 | uint8_t *End; | ||
| 1182 | if (I + 1 == Sections.size()) | ||
| 1183 | End = Buf + Sec->Size; | ||
| 1184 | else | ||
| 1185 | End = Buf + Sections[I + 1]->OutSecOff; | ||
| 1186 | fill(Start, End - Start, Filler); | ||
| 1187 | } | ||
| 1188 | }); | ||
| 1189 | |||
| 1190 | // Linker scripts may have BYTE()-family commands with which you | ||
| 1191 | // can write arbitrary bytes to the output. Process them if any. | ||
| 1192 | for (BaseCommand *Base : Commands) | ||
| 1193 | if (auto *Data = dyn_cast<BytesDataCommand>(Base)) | ||
| 1194 | writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) { | ||
| 1198 | if (S == ".") | ||
| 1199 | return {CurAddressState->OutSec, Dot - CurAddressState->OutSec->Addr, Loc}; | ||
| 1200 | if (SymbolBody *B = findSymbol(S)) { | ||
| 1201 | if (auto *D = dyn_cast<DefinedRegular>(B)) | ||
| 1202 | return {D->Section, D->Value, Loc}; | ||
| 1203 | if (auto *C = dyn_cast<DefinedCommon>(B)) | ||
| 1204 | return {InX::Common, C->Offset, Loc}; | ||
| 1205 | } | ||
| 1206 | error(Loc + ": symbol not found: " + S); | ||
| 1207 | return 0; | 992 | return 0; |
| 1208 | } | 993 | } |
| 1209 | 994 | ||
| 1210 | bool LinkerScript::isDefined(StringRef S) { return findSymbol(S) != nullptr; } | 995 | // Returns the index of the segment named Name. |
| 1211 | 996 | static Optional<size_t> getPhdrIndex(ArrayRef<PhdrsCommand> Vec, | |
| 1212 | static const size_t NoPhdr = -1; | 997 | StringRef Name) { |
| 998 | for (size_t I = 0; I < Vec.size(); ++I) | ||
| 999 | if (Vec[I].Name == Name) | ||
| 1000 | return I; | ||
| 1001 | return None; | ||
| 1002 | } | ||
| 1213 | 1003 | ||
| 1214 | // Returns indices of ELF headers containing specific section. Each index is a | 1004 | // Returns indices of ELF headers containing specific section. Each index is a |
| 1215 | // zero based number of ELF header listed within PHDRS {} script block. | 1005 | // zero based number of ELF header listed within PHDRS {} script block. |
| 1216 | std::vector<size_t> LinkerScript::getPhdrIndices(OutputSectionCommand *Cmd) { | 1006 | std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *Cmd) { |
| 1217 | std::vector<size_t> Ret; | 1007 | std::vector<size_t> Ret; |
| 1218 | for (StringRef PhdrName : Cmd->Phdrs) { | ||
| 1219 | size_t Index = getPhdrIndex(Cmd->Location, PhdrName); | ||
| 1220 | if (Index != NoPhdr) | ||
| 1221 | Ret.push_back(Index); | ||
| 1222 | } | ||
| 1223 | return Ret; | ||
| 1224 | } | ||
| 1225 | 1008 | ||
| 1226 | // Returns the index of the segment named PhdrName if found otherwise | 1009 | for (StringRef S : Cmd->Phdrs) { |
| 1227 | // NoPhdr. When not found, if PhdrName is not the special case value 'NONE' | 1010 | if (Optional<size_t> Idx = getPhdrIndex(PhdrsCommands, S)) |
| 1228 | // (which can be used to explicitly specify that a section isn't assigned to a | 1011 | Ret.push_back(*Idx); |
| 1229 | // segment) then error. | 1012 | else if (S != "NONE") |
| 1230 | size_t LinkerScript::getPhdrIndex(const Twine &Loc, StringRef PhdrName) { | 1013 | error(Cmd->Location + ": section header '" + S + |
| 1231 | size_t I = 0; | 1014 | "' is not listed in PHDRS"); |
| 1232 | for (PhdrsCommand &Cmd : Opt.PhdrsCommands) { | ||
| 1233 | if (Cmd.Name == PhdrName) | ||
| 1234 | return I; | ||
| 1235 | ++I; | ||
| 1236 | } | 1015 | } |
| 1237 | if (PhdrName != "NONE") | 1016 | return Ret; |
| 1238 | error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS"); | ||
| 1239 | return NoPhdr; | ||
| 1240 | } | 1017 | } |
| 1241 | |||
| 1242 | template void OutputSectionCommand::writeTo<ELF32LE>(uint8_t *Buf); | ||
| 1243 | template void OutputSectionCommand::writeTo<ELF32BE>(uint8_t *Buf); | ||
| 1244 | template void OutputSectionCommand::writeTo<ELF64LE>(uint8_t *Buf); | ||
| 1245 | template void OutputSectionCommand::writeTo<ELF64BE>(uint8_t *Buf); | ||
| 1246 | |||
| 1247 | template void OutputSectionCommand::maybeCompress<ELF32LE>(); | ||
| 1248 | template void OutputSectionCommand::maybeCompress<ELF32BE>(); | ||
| 1249 | template void OutputSectionCommand::maybeCompress<ELF64LE>(); | ||
| 1250 | template void OutputSectionCommand::maybeCompress<ELF64BE>(); | ||
| 1251 | |||
| 1252 | template void OutputSectionCommand::finalize<ELF32LE>(); | ||
| 1253 | template void OutputSectionCommand::finalize<ELF32BE>(); | ||
| 1254 | template void OutputSectionCommand::finalize<ELF64LE>(); | ||
| 1255 | template void OutputSectionCommand::finalize<ELF64BE>(); |
deps/lld/ELF/LinkerScript.h+98-113| ... | @@ -13,10 +13,11 @@ | ... | @@ -13,10 +13,11 @@ |
| 13 | #include "Config.h" | 13 | #include "Config.h" |
| 14 | #include "Strings.h" | 14 | #include "Strings.h" |
| 15 | #include "Writer.h" | 15 | #include "Writer.h" |
| 16 | #include "lld/Core/LLVM.h" | 16 | #include "lld/Common/LLVM.h" |
| 17 | #include "llvm/ADT/ArrayRef.h" | 17 | #include "llvm/ADT/ArrayRef.h" |
| 18 | #include "llvm/ADT/DenseMap.h" | 18 | #include "llvm/ADT/DenseMap.h" |
| 19 | #include "llvm/ADT/DenseSet.h" | 19 | #include "llvm/ADT/DenseSet.h" |
| 20 | #include "llvm/ADT/MapVector.h" | ||
| 20 | #include "llvm/ADT/StringRef.h" | 21 | #include "llvm/ADT/StringRef.h" |
| 21 | #include "llvm/Support/MemoryBuffer.h" | 22 | #include "llvm/Support/MemoryBuffer.h" |
| 22 | #include <cstddef> | 23 | #include <cstddef> |
| ... | @@ -28,31 +29,39 @@ | ... | @@ -28,31 +29,39 @@ |
| 28 | namespace lld { | 29 | namespace lld { |
| 29 | namespace elf { | 30 | namespace elf { |
| 30 | 31 | ||
| 31 | class DefinedCommon; | 32 | class Defined; |
| 32 | class SymbolBody; | 33 | class Symbol; |
| 33 | class InputSectionBase; | 34 | class InputSectionBase; |
| 34 | class InputSection; | 35 | class InputSection; |
| 35 | class OutputSection; | 36 | class OutputSection; |
| 36 | class OutputSectionFactory; | ||
| 37 | class InputSectionBase; | 37 | class InputSectionBase; |
| 38 | class SectionBase; | 38 | class SectionBase; |
| 39 | 39 | ||
| 40 | // This represents an r-value in the linker script. | ||
| 40 | struct ExprValue { | 41 | struct ExprValue { |
| 41 | SectionBase *Sec; | ||
| 42 | uint64_t Val; | ||
| 43 | bool ForceAbsolute; | ||
| 44 | uint64_t Alignment = 1; | ||
| 45 | std::string Loc; | ||
| 46 | |||
| 47 | ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val, | 42 | ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val, |
| 48 | const Twine &Loc) | 43 | const Twine &Loc) |
| 49 | : Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Loc(Loc.str()) {} | 44 | : Sec(Sec), ForceAbsolute(ForceAbsolute), Val(Val), Loc(Loc.str()) {} |
| 50 | ExprValue(SectionBase *Sec, uint64_t Val, const Twine &Loc) | 45 | |
| 51 | : ExprValue(Sec, false, Val, Loc) {} | 46 | ExprValue(uint64_t Val) : ExprValue(nullptr, false, Val, "") {} |
| 52 | ExprValue(uint64_t Val) : ExprValue(nullptr, Val, "") {} | 47 | |
| 53 | bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; } | 48 | bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; } |
| 54 | uint64_t getValue() const; | 49 | uint64_t getValue() const; |
| 55 | uint64_t getSecAddr() const; | 50 | uint64_t getSecAddr() const; |
| 51 | uint64_t getSectionOffset() const; | ||
| 52 | |||
| 53 | // If a value is relative to a section, it has a non-null Sec. | ||
| 54 | SectionBase *Sec; | ||
| 55 | |||
| 56 | // True if this expression is enclosed in ABSOLUTE(). | ||
| 57 | // This flag affects the return value of getValue(). | ||
| 58 | bool ForceAbsolute; | ||
| 59 | |||
| 60 | uint64_t Val; | ||
| 61 | uint64_t Alignment = 1; | ||
| 62 | |||
| 63 | // Original source location. Used for error messages. | ||
| 64 | std::string Loc; | ||
| 56 | }; | 65 | }; |
| 57 | 66 | ||
| 58 | // This represents an expression in the linker script. | 67 | // This represents an expression in the linker script. |
| ... | @@ -66,8 +75,8 @@ enum SectionsCommandKind { | ... | @@ -66,8 +75,8 @@ enum SectionsCommandKind { |
| 66 | AssignmentKind, // . = expr or <sym> = expr | 75 | AssignmentKind, // . = expr or <sym> = expr |
| 67 | OutputSectionKind, | 76 | OutputSectionKind, |
| 68 | InputSectionKind, | 77 | InputSectionKind, |
| 69 | AssertKind, // ASSERT(expr) | 78 | AssertKind, // ASSERT(expr) |
| 70 | BytesDataKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr) | 79 | ByteKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr) |
| 71 | }; | 80 | }; |
| 72 | 81 | ||
| 73 | struct BaseCommand { | 82 | struct BaseCommand { |
| ... | @@ -80,11 +89,13 @@ struct SymbolAssignment : BaseCommand { | ... | @@ -80,11 +89,13 @@ struct SymbolAssignment : BaseCommand { |
| 80 | SymbolAssignment(StringRef Name, Expr E, std::string Loc) | 89 | SymbolAssignment(StringRef Name, Expr E, std::string Loc) |
| 81 | : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {} | 90 | : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {} |
| 82 | 91 | ||
| 83 | static bool classof(const BaseCommand *C); | 92 | static bool classof(const BaseCommand *C) { |
| 93 | return C->Kind == AssignmentKind; | ||
| 94 | } | ||
| 84 | 95 | ||
| 85 | // The LHS of an expression. Name is either a symbol name or ".". | 96 | // The LHS of an expression. Name is either a symbol name or ".". |
| 86 | StringRef Name; | 97 | StringRef Name; |
| 87 | SymbolBody *Sym = nullptr; | 98 | Defined *Sym = nullptr; |
| 88 | 99 | ||
| 89 | // The RHS of an expression. | 100 | // The RHS of an expression. |
| 90 | Expr Expression; | 101 | Expr Expression; |
| ... | @@ -114,37 +125,6 @@ struct MemoryRegion { | ... | @@ -114,37 +125,6 @@ struct MemoryRegion { |
| 114 | uint32_t NegFlags; | 125 | uint32_t NegFlags; |
| 115 | }; | 126 | }; |
| 116 | 127 | ||
| 117 | struct OutputSectionCommand : BaseCommand { | ||
| 118 | OutputSectionCommand(StringRef Name) | ||
| 119 | : BaseCommand(OutputSectionKind), Name(Name) {} | ||
| 120 | |||
| 121 | static bool classof(const BaseCommand *C); | ||
| 122 | |||
| 123 | OutputSection *Sec = nullptr; | ||
| 124 | MemoryRegion *MemRegion = nullptr; | ||
| 125 | StringRef Name; | ||
| 126 | Expr AddrExpr; | ||
| 127 | Expr AlignExpr; | ||
| 128 | Expr LMAExpr; | ||
| 129 | Expr SubalignExpr; | ||
| 130 | std::vector<BaseCommand *> Commands; | ||
| 131 | std::vector<StringRef> Phdrs; | ||
| 132 | llvm::Optional<uint32_t> Filler; | ||
| 133 | ConstraintKind Constraint = ConstraintKind::NoConstraint; | ||
| 134 | std::string Location; | ||
| 135 | std::string MemoryRegionName; | ||
| 136 | bool Noload = false; | ||
| 137 | |||
| 138 | template <class ELFT> void finalize(); | ||
| 139 | template <class ELFT> void writeTo(uint8_t *Buf); | ||
| 140 | template <class ELFT> void maybeCompress(); | ||
| 141 | uint32_t getFiller(); | ||
| 142 | |||
| 143 | void sort(std::function<int(InputSectionBase *S)> Order); | ||
| 144 | void sortInitFini(); | ||
| 145 | void sortCtorsDtors(); | ||
| 146 | }; | ||
| 147 | |||
| 148 | // This struct represents one section match pattern in SECTIONS() command. | 128 | // This struct represents one section match pattern in SECTIONS() command. |
| 149 | // It can optionally have negative match pattern for EXCLUDED_FILE command. | 129 | // It can optionally have negative match pattern for EXCLUDED_FILE command. |
| 150 | // Also it may be surrounded with SORT() command, so contains sorting rules. | 130 | // Also it may be surrounded with SORT() command, so contains sorting rules. |
| ... | @@ -158,11 +138,14 @@ struct SectionPattern { | ... | @@ -158,11 +138,14 @@ struct SectionPattern { |
| 158 | SortSectionPolicy SortInner; | 138 | SortSectionPolicy SortInner; |
| 159 | }; | 139 | }; |
| 160 | 140 | ||
| 141 | class ThunkSection; | ||
| 161 | struct InputSectionDescription : BaseCommand { | 142 | struct InputSectionDescription : BaseCommand { |
| 162 | InputSectionDescription(StringRef FilePattern) | 143 | InputSectionDescription(StringRef FilePattern) |
| 163 | : BaseCommand(InputSectionKind), FilePat(FilePattern) {} | 144 | : BaseCommand(InputSectionKind), FilePat(FilePattern) {} |
| 164 | 145 | ||
| 165 | static bool classof(const BaseCommand *C); | 146 | static bool classof(const BaseCommand *C) { |
| 147 | return C->Kind == InputSectionKind; | ||
| 148 | } | ||
| 166 | 149 | ||
| 167 | StringMatcher FilePat; | 150 | StringMatcher FilePat; |
| 168 | 151 | ||
| ... | @@ -171,23 +154,28 @@ struct InputSectionDescription : BaseCommand { | ... | @@ -171,23 +154,28 @@ struct InputSectionDescription : BaseCommand { |
| 171 | std::vector<SectionPattern> SectionPatterns; | 154 | std::vector<SectionPattern> SectionPatterns; |
| 172 | 155 | ||
| 173 | std::vector<InputSection *> Sections; | 156 | std::vector<InputSection *> Sections; |
| 157 | |||
| 158 | // Temporary record of synthetic ThunkSection instances and the pass that | ||
| 159 | // they were created in. This is used to insert newly created ThunkSections | ||
| 160 | // into Sections at the end of a createThunks() pass. | ||
| 161 | std::vector<std::pair<ThunkSection *, uint32_t>> ThunkSections; | ||
| 174 | }; | 162 | }; |
| 175 | 163 | ||
| 176 | // Represents an ASSERT(). | 164 | // Represents an ASSERT(). |
| 177 | struct AssertCommand : BaseCommand { | 165 | struct AssertCommand : BaseCommand { |
| 178 | AssertCommand(Expr E) : BaseCommand(AssertKind), Expression(E) {} | 166 | AssertCommand(Expr E) : BaseCommand(AssertKind), Expression(E) {} |
| 179 | 167 | ||
| 180 | static bool classof(const BaseCommand *C); | 168 | static bool classof(const BaseCommand *C) { return C->Kind == AssertKind; } |
| 181 | 169 | ||
| 182 | Expr Expression; | 170 | Expr Expression; |
| 183 | }; | 171 | }; |
| 184 | 172 | ||
| 185 | // Represents BYTE(), SHORT(), LONG(), or QUAD(). | 173 | // Represents BYTE(), SHORT(), LONG(), or QUAD(). |
| 186 | struct BytesDataCommand : BaseCommand { | 174 | struct ByteCommand : BaseCommand { |
| 187 | BytesDataCommand(Expr E, unsigned Size) | 175 | ByteCommand(Expr E, unsigned Size) |
| 188 | : BaseCommand(BytesDataKind), Expression(E), Size(Size) {} | 176 | : BaseCommand(ByteKind), Expression(E), Size(Size) {} |
| 189 | 177 | ||
| 190 | static bool classof(const BaseCommand *C); | 178 | static bool classof(const BaseCommand *C) { return C->Kind == ByteKind; } |
| 191 | 179 | ||
| 192 | Expr Expression; | 180 | Expr Expression; |
| 193 | unsigned Offset; | 181 | unsigned Offset; |
| ... | @@ -196,106 +184,103 @@ struct BytesDataCommand : BaseCommand { | ... | @@ -196,106 +184,103 @@ struct BytesDataCommand : BaseCommand { |
| 196 | 184 | ||
| 197 | struct PhdrsCommand { | 185 | struct PhdrsCommand { |
| 198 | StringRef Name; | 186 | StringRef Name; |
| 199 | unsigned Type; | 187 | unsigned Type = llvm::ELF::PT_NULL; |
| 200 | bool HasFilehdr; | 188 | bool HasFilehdr = false; |
| 201 | bool HasPhdrs; | 189 | bool HasPhdrs = false; |
| 202 | unsigned Flags; | 190 | llvm::Optional<unsigned> Flags; |
| 203 | Expr LMAExpr; | 191 | Expr LMAExpr = nullptr; |
| 204 | }; | ||
| 205 | |||
| 206 | // ScriptConfiguration holds linker script parse results. | ||
| 207 | struct ScriptConfiguration { | ||
| 208 | // Used to assign addresses to sections. | ||
| 209 | std::vector<BaseCommand *> Commands; | ||
| 210 | |||
| 211 | // Used to assign sections to headers. | ||
| 212 | std::vector<PhdrsCommand> PhdrsCommands; | ||
| 213 | |||
| 214 | bool HasSections = false; | ||
| 215 | |||
| 216 | // List of section patterns specified with KEEP commands. They will | ||
| 217 | // be kept even if they are unused and --gc-sections is specified. | ||
| 218 | std::vector<InputSectionDescription *> KeptSections; | ||
| 219 | |||
| 220 | // A map from memory region name to a memory region descriptor. | ||
| 221 | llvm::DenseMap<llvm::StringRef, MemoryRegion> MemoryRegions; | ||
| 222 | |||
| 223 | // A list of symbols referenced by the script. | ||
| 224 | std::vector<llvm::StringRef> ReferencedSymbols; | ||
| 225 | }; | 192 | }; |
| 226 | 193 | ||
| 227 | class LinkerScript final { | 194 | class LinkerScript final { |
| 228 | // Temporary state used in processCommands() and assignAddresses() | 195 | // Temporary state used in processSectionCommands() and assignAddresses() |
| 229 | // that must be reinitialized for each call to the above functions, and must | 196 | // that must be reinitialized for each call to the above functions, and must |
| 230 | // not be used outside of the scope of a call to the above functions. | 197 | // not be used outside of the scope of a call to the above functions. |
| 231 | struct AddressState { | 198 | struct AddressState { |
| 199 | AddressState(); | ||
| 232 | uint64_t ThreadBssOffset = 0; | 200 | uint64_t ThreadBssOffset = 0; |
| 233 | OutputSection *OutSec = nullptr; | 201 | OutputSection *OutSec = nullptr; |
| 234 | MemoryRegion *MemRegion = nullptr; | 202 | MemoryRegion *MemRegion = nullptr; |
| 235 | llvm::DenseMap<const MemoryRegion *, uint64_t> MemRegionOffset; | 203 | llvm::DenseMap<const MemoryRegion *, uint64_t> MemRegionOffset; |
| 236 | std::function<uint64_t()> LMAOffset; | 204 | std::function<uint64_t()> LMAOffset; |
| 237 | AddressState(const ScriptConfiguration &Opt); | ||
| 238 | }; | 205 | }; |
| 239 | llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand; | ||
| 240 | llvm::DenseMap<StringRef, OutputSectionCommand *> NameToOutputSectionCommand; | ||
| 241 | 206 | ||
| 207 | llvm::DenseMap<StringRef, OutputSection *> NameToOutputSection; | ||
| 208 | |||
| 209 | void addSymbol(SymbolAssignment *Cmd); | ||
| 242 | void assignSymbol(SymbolAssignment *Cmd, bool InSec); | 210 | void assignSymbol(SymbolAssignment *Cmd, bool InSec); |
| 243 | void setDot(Expr E, const Twine &Loc, bool InSec); | 211 | void setDot(Expr E, const Twine &Loc, bool InSec); |
| 244 | 212 | ||
| 245 | std::vector<InputSection *> | 213 | std::vector<InputSection *> |
| 246 | computeInputSections(const InputSectionDescription *); | 214 | computeInputSections(const InputSectionDescription *, |
| 215 | const llvm::DenseMap<SectionBase *, int> &Order); | ||
| 247 | 216 | ||
| 248 | std::vector<InputSectionBase *> | 217 | std::vector<InputSection *> |
| 249 | createInputSectionList(OutputSectionCommand &Cmd); | 218 | createInputSectionList(OutputSection &Cmd, |
| 219 | const llvm::DenseMap<SectionBase *, int> &Order); | ||
| 250 | 220 | ||
| 251 | std::vector<size_t> getPhdrIndices(OutputSectionCommand *Cmd); | 221 | std::vector<size_t> getPhdrIndices(OutputSection *Sec); |
| 252 | size_t getPhdrIndex(const Twine &Loc, StringRef PhdrName); | ||
| 253 | 222 | ||
| 254 | MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd); | 223 | MemoryRegion *findMemoryRegion(OutputSection *Sec); |
| 255 | 224 | ||
| 256 | void switchTo(OutputSection *Sec); | 225 | void switchTo(OutputSection *Sec); |
| 257 | uint64_t advance(uint64_t Size, unsigned Align); | 226 | uint64_t advance(uint64_t Size, unsigned Align); |
| 258 | void output(InputSection *Sec); | 227 | void output(InputSection *Sec); |
| 259 | void process(BaseCommand &Base); | ||
| 260 | 228 | ||
| 261 | AddressState *CurAddressState = nullptr; | 229 | void assignOffsets(OutputSection *Sec); |
| 230 | |||
| 231 | // Ctx captures the local AddressState and makes it accessible | ||
| 232 | // deliberately. This is needed as there are some cases where we cannot just | ||
| 233 | // thread the current state through to a lambda function created by the | ||
| 234 | // script parser. | ||
| 235 | // This should remain a plain pointer as its lifetime is smaller than | ||
| 236 | // LinkerScript. | ||
| 237 | AddressState *Ctx = nullptr; | ||
| 238 | |||
| 262 | OutputSection *Aether; | 239 | OutputSection *Aether; |
| 263 | 240 | ||
| 264 | uint64_t Dot; | 241 | uint64_t Dot; |
| 265 | 242 | ||
| 266 | public: | 243 | public: |
| 267 | bool ErrorOnMissingSection = false; | 244 | OutputSection *createOutputSection(StringRef Name, StringRef Location); |
| 268 | OutputSectionCommand *createOutputSectionCommand(StringRef Name, | 245 | OutputSection *getOrCreateOutputSection(StringRef Name); |
| 269 | StringRef Location); | ||
| 270 | OutputSectionCommand *getOrCreateOutputSectionCommand(StringRef Name); | ||
| 271 | 246 | ||
| 272 | OutputSectionCommand *getCmd(OutputSection *Sec) const; | 247 | bool hasPhdrsCommands() { return !PhdrsCommands.empty(); } |
| 273 | bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); } | ||
| 274 | uint64_t getDot() { return Dot; } | 248 | uint64_t getDot() { return Dot; } |
| 275 | void discard(ArrayRef<InputSectionBase *> V); | 249 | void discard(ArrayRef<InputSection *> V); |
| 276 | 250 | ||
| 277 | ExprValue getSymbolValue(const Twine &Loc, StringRef S); | 251 | ExprValue getSymbolValue(StringRef Name, const Twine &Loc); |
| 278 | bool isDefined(StringRef S); | ||
| 279 | 252 | ||
| 280 | void fabricateDefaultCommands(); | 253 | void addOrphanSections(); |
| 281 | void addOrphanSections(OutputSectionFactory &Factory); | ||
| 282 | void removeEmptyCommands(); | 254 | void removeEmptyCommands(); |
| 283 | void adjustSectionsBeforeSorting(); | 255 | void adjustSectionsBeforeSorting(); |
| 284 | void adjustSectionsAfterSorting(); | 256 | void adjustSectionsAfterSorting(); |
| 285 | 257 | ||
| 286 | std::vector<PhdrEntry> createPhdrs(); | 258 | std::vector<PhdrEntry *> createPhdrs(); |
| 287 | bool ignoreInterpSection(); | 259 | bool needsInterpSection(); |
| 288 | 260 | ||
| 289 | bool shouldKeep(InputSectionBase *S); | 261 | bool shouldKeep(InputSectionBase *S); |
| 290 | void assignOffsets(OutputSectionCommand *Cmd); | ||
| 291 | void processNonSectionCommands(); | ||
| 292 | void assignAddresses(); | 262 | void assignAddresses(); |
| 293 | void allocateHeaders(std::vector<PhdrEntry> &Phdrs); | 263 | void allocateHeaders(std::vector<PhdrEntry *> &Phdrs); |
| 294 | void addSymbol(SymbolAssignment *Cmd); | 264 | void processSectionCommands(); |
| 295 | void processCommands(OutputSectionFactory &Factory); | 265 | |
| 266 | // SECTIONS command list. | ||
| 267 | std::vector<BaseCommand *> SectionCommands; | ||
| 268 | |||
| 269 | // PHDRS command list. | ||
| 270 | std::vector<PhdrsCommand> PhdrsCommands; | ||
| 271 | |||
| 272 | bool HasSectionsCommand = false; | ||
| 273 | bool ErrorOnMissingSection = false; | ||
| 296 | 274 | ||
| 297 | // Parsed linker script configurations are set to this struct. | 275 | // List of section patterns specified with KEEP commands. They will |
| 298 | ScriptConfiguration Opt; | 276 | // be kept even if they are unused and --gc-sections is specified. |
| 277 | std::vector<InputSectionDescription *> KeptSections; | ||
| 278 | |||
| 279 | // A map from memory region name to a memory region descriptor. | ||
| 280 | llvm::MapVector<llvm::StringRef, MemoryRegion *> MemoryRegions; | ||
| 281 | |||
| 282 | // A list of symbols referenced by the script. | ||
| 283 | std::vector<llvm::StringRef> ReferencedSymbols; | ||
| 299 | }; | 284 | }; |
| 300 | 285 | ||
| 301 | extern LinkerScript *Script; | 286 | extern LinkerScript *Script; |
deps/lld/ELF/MapFile.cpp+49-46| ... | @@ -25,8 +25,9 @@ | ... | @@ -25,8 +25,9 @@ |
| 25 | #include "OutputSections.h" | 25 | #include "OutputSections.h" |
| 26 | #include "Strings.h" | 26 | #include "Strings.h" |
| 27 | #include "SymbolTable.h" | 27 | #include "SymbolTable.h" |
| 28 | #include "Threads.h" | 28 | #include "Symbols.h" |
| 29 | 29 | #include "SyntheticSections.h" | |
| 30 | #include "lld/Common/Threads.h" | ||
| 30 | #include "llvm/Support/raw_ostream.h" | 31 | #include "llvm/Support/raw_ostream.h" |
| 31 | 32 | ||
| 32 | using namespace llvm; | 33 | using namespace llvm; |
| ... | @@ -35,46 +36,57 @@ using namespace llvm::object; | ... | @@ -35,46 +36,57 @@ using namespace llvm::object; |
| 35 | using namespace lld; | 36 | using namespace lld; |
| 36 | using namespace lld::elf; | 37 | using namespace lld::elf; |
| 37 | 38 | ||
| 38 | typedef DenseMap<const SectionBase *, SmallVector<DefinedRegular *, 4>> | 39 | typedef DenseMap<const SectionBase *, SmallVector<Symbol *, 4>> SymbolMapTy; |
| 39 | SymbolMapTy; | ||
| 40 | 40 | ||
| 41 | // Print out the first three columns of a line. | 41 | // Print out the first three columns of a line. |
| 42 | template <class ELFT> | ||
| 43 | static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size, | 42 | static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size, |
| 44 | uint64_t Align) { | 43 | uint64_t Align) { |
| 45 | int W = ELFT::Is64Bits ? 16 : 8; | 44 | int W = Config->Is64 ? 16 : 8; |
| 46 | OS << format("%0*llx %0*llx %5lld ", W, Addr, W, Size, Align); | 45 | OS << format("%0*llx %0*llx %5lld ", W, Addr, W, Size, Align); |
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | static std::string indent(int Depth) { return std::string(Depth * 8, ' '); } | 48 | static std::string indent(int Depth) { return std::string(Depth * 8, ' '); } |
| 50 | 49 | ||
| 51 | // Returns a list of all symbols that we want to print out. | 50 | // Returns a list of all symbols that we want to print out. |
| 52 | template <class ELFT> std::vector<DefinedRegular *> getSymbols() { | 51 | static std::vector<Symbol *> getSymbols() { |
| 53 | std::vector<DefinedRegular *> V; | 52 | std::vector<Symbol *> V; |
| 54 | for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) | 53 | for (InputFile *File : ObjectFiles) { |
| 55 | for (SymbolBody *B : File->getSymbols()) | 54 | for (Symbol *B : File->getSymbols()) { |
| 56 | if (B->File == File && !B->isSection()) | 55 | if (auto *SS = dyn_cast<SharedSymbol>(B)) |
| 57 | if (auto *Sym = dyn_cast<DefinedRegular>(B)) | 56 | if (SS->CopyRelSec || SS->NeedsPltAddr) |
| 58 | if (Sym->Section && Sym->Section->Live) | 57 | V.push_back(SS); |
| 59 | V.push_back(Sym); | 58 | if (auto *DR = dyn_cast<Defined>(B)) |
| 59 | if (DR->File == File && !DR->isSection() && DR->Section && | ||
| 60 | DR->Section->Live) | ||
| 61 | V.push_back(DR); | ||
| 62 | } | ||
| 63 | } | ||
| 60 | return V; | 64 | return V; |
| 61 | } | 65 | } |
| 62 | 66 | ||
| 63 | // Returns a map from sections to their symbols. | 67 | // Returns a map from sections to their symbols. |
| 64 | template <class ELFT> | 68 | static SymbolMapTy getSectionSyms(ArrayRef<Symbol *> Syms) { |
| 65 | SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> Syms) { | ||
| 66 | SymbolMapTy Ret; | 69 | SymbolMapTy Ret; |
| 67 | for (DefinedRegular *S : Syms) | 70 | for (Symbol *S : Syms) { |
| 68 | Ret[S->Section].push_back(S); | 71 | if (auto *DR = dyn_cast<Defined>(S)) { |
| 72 | Ret[DR->Section].push_back(S); | ||
| 73 | continue; | ||
| 74 | } | ||
| 75 | |||
| 76 | SharedSymbol *SS = cast<SharedSymbol>(S); | ||
| 77 | if (SS->CopyRelSec) | ||
| 78 | Ret[SS->CopyRelSec].push_back(S); | ||
| 79 | else | ||
| 80 | Ret[InX::Plt].push_back(S); | ||
| 81 | } | ||
| 69 | 82 | ||
| 70 | // Sort symbols by address. We want to print out symbols in the | 83 | // Sort symbols by address. We want to print out symbols in the |
| 71 | // order in the output file rather than the order they appeared | 84 | // order in the output file rather than the order they appeared |
| 72 | // in the input files. | 85 | // in the input files. |
| 73 | for (auto &It : Ret) { | 86 | for (auto &It : Ret) { |
| 74 | SmallVectorImpl<DefinedRegular *> &V = It.second; | 87 | SmallVectorImpl<Symbol *> &V = It.second; |
| 75 | std::sort(V.begin(), V.end(), [](DefinedRegular *A, DefinedRegular *B) { | 88 | std::sort(V.begin(), V.end(), |
| 76 | return A->getVA() < B->getVA(); | 89 | [](Symbol *A, Symbol *B) { return A->getVA() < B->getVA(); }); |
| 77 | }); | ||
| 78 | } | 90 | } |
| 79 | return Ret; | 91 | return Ret; |
| 80 | } | 92 | } |
| ... | @@ -82,25 +94,22 @@ SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> Syms) { | ... | @@ -82,25 +94,22 @@ SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> Syms) { |
| 82 | // Construct a map from symbols to their stringified representations. | 94 | // Construct a map from symbols to their stringified representations. |
| 83 | // Demangling symbols (which is what toString() does) is slow, so | 95 | // Demangling symbols (which is what toString() does) is slow, so |
| 84 | // we do that in batch using parallel-for. | 96 | // we do that in batch using parallel-for. |
| 85 | template <class ELFT> | 97 | static DenseMap<Symbol *, std::string> |
| 86 | DenseMap<DefinedRegular *, std::string> | 98 | getSymbolStrings(ArrayRef<Symbol *> Syms) { |
| 87 | getSymbolStrings(ArrayRef<DefinedRegular *> Syms) { | ||
| 88 | std::vector<std::string> Str(Syms.size()); | 99 | std::vector<std::string> Str(Syms.size()); |
| 89 | parallelForEachN(0, Syms.size(), [&](size_t I) { | 100 | parallelForEachN(0, Syms.size(), [&](size_t I) { |
| 90 | raw_string_ostream OS(Str[I]); | 101 | raw_string_ostream OS(Str[I]); |
| 91 | writeHeader<ELFT>(OS, Syms[I]->getVA(), Syms[I]->template getSize<ELFT>(), | 102 | writeHeader(OS, Syms[I]->getVA(), Syms[I]->getSize(), 0); |
| 92 | 0); | ||
| 93 | OS << indent(2) << toString(*Syms[I]); | 103 | OS << indent(2) << toString(*Syms[I]); |
| 94 | }); | 104 | }); |
| 95 | 105 | ||
| 96 | DenseMap<DefinedRegular *, std::string> Ret; | 106 | DenseMap<Symbol *, std::string> Ret; |
| 97 | for (size_t I = 0, E = Syms.size(); I < E; ++I) | 107 | for (size_t I = 0, E = Syms.size(); I < E; ++I) |
| 98 | Ret[Syms[I]] = std::move(Str[I]); | 108 | Ret[Syms[I]] = std::move(Str[I]); |
| 99 | return Ret; | 109 | return Ret; |
| 100 | } | 110 | } |
| 101 | 111 | ||
| 102 | template <class ELFT> | 112 | void elf::writeMapFile() { |
| 103 | void elf::writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script) { | ||
| 104 | if (Config->MapFile.empty()) | 113 | if (Config->MapFile.empty()) |
| 105 | return; | 114 | return; |
| 106 | 115 | ||
| ... | @@ -113,38 +122,32 @@ void elf::writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script) { | ... | @@ -113,38 +122,32 @@ void elf::writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script) { |
| 113 | } | 122 | } |
| 114 | 123 | ||
| 115 | // Collect symbol info that we want to print out. | 124 | // Collect symbol info that we want to print out. |
| 116 | std::vector<DefinedRegular *> Syms = getSymbols<ELFT>(); | 125 | std::vector<Symbol *> Syms = getSymbols(); |
| 117 | SymbolMapTy SectionSyms = getSectionSyms<ELFT>(Syms); | 126 | SymbolMapTy SectionSyms = getSectionSyms(Syms); |
| 118 | DenseMap<DefinedRegular *, std::string> SymStr = getSymbolStrings<ELFT>(Syms); | 127 | DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms); |
| 119 | 128 | ||
| 120 | // Print out the header line. | 129 | // Print out the header line. |
| 121 | int W = ELFT::Is64Bits ? 16 : 8; | 130 | int W = Config->Is64 ? 16 : 8; |
| 122 | OS << left_justify("Address", W) << ' ' << left_justify("Size", W) | 131 | OS << left_justify("Address", W) << ' ' << left_justify("Size", W) |
| 123 | << " Align Out In Symbol\n"; | 132 | << " Align Out In Symbol\n"; |
| 124 | 133 | ||
| 125 | // Print out file contents. | 134 | // Print out file contents. |
| 126 | for (OutputSectionCommand *Cmd : Script) { | 135 | for (OutputSection *OSec : OutputSections) { |
| 127 | OutputSection *OSec = Cmd->Sec; | 136 | writeHeader(OS, OSec->Addr, OSec->Size, OSec->Alignment); |
| 128 | writeHeader<ELFT>(OS, OSec->Addr, OSec->Size, OSec->Alignment); | ||
| 129 | OS << OSec->Name << '\n'; | 137 | OS << OSec->Name << '\n'; |
| 130 | 138 | ||
| 131 | // Dump symbols for each input section. | 139 | // Dump symbols for each input section. |
| 132 | for (BaseCommand *Base : Cmd->Commands) { | 140 | for (BaseCommand *Base : OSec->SectionCommands) { |
| 133 | auto *ISD = dyn_cast<InputSectionDescription>(Base); | 141 | auto *ISD = dyn_cast<InputSectionDescription>(Base); |
| 134 | if (!ISD) | 142 | if (!ISD) |
| 135 | continue; | 143 | continue; |
| 136 | for (InputSection *IS : ISD->Sections) { | 144 | for (InputSection *IS : ISD->Sections) { |
| 137 | writeHeader<ELFT>(OS, OSec->Addr + IS->OutSecOff, IS->getSize(), | 145 | writeHeader(OS, OSec->Addr + IS->OutSecOff, IS->getSize(), |
| 138 | IS->Alignment); | 146 | IS->Alignment); |
| 139 | OS << indent(1) << toString(IS) << '\n'; | 147 | OS << indent(1) << toString(IS) << '\n'; |
| 140 | for (DefinedRegular *Sym : SectionSyms[IS]) | 148 | for (Symbol *Sym : SectionSyms[IS]) |
| 141 | OS << SymStr[Sym] << '\n'; | 149 | OS << SymStr[Sym] << '\n'; |
| 142 | } | 150 | } |
| 143 | } | 151 | } |
| 144 | } | 152 | } |
| 145 | } | 153 | } |
| 146 | |||
| 147 | template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionCommand *>); | ||
| 148 | template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionCommand *>); | ||
| 149 | template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionCommand *>); | ||
| 150 | template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionCommand *>); |
deps/lld/ELF/MapFile.h+1-5| ... | @@ -10,13 +10,9 @@ | ... | @@ -10,13 +10,9 @@ |
| 10 | #ifndef LLD_ELF_MAPFILE_H | 10 | #ifndef LLD_ELF_MAPFILE_H |
| 11 | #define LLD_ELF_MAPFILE_H | 11 | #define LLD_ELF_MAPFILE_H |
| 12 | 12 | ||
| 13 | #include <llvm/ADT/ArrayRef.h> | ||
| 14 | |||
| 15 | namespace lld { | 13 | namespace lld { |
| 16 | namespace elf { | 14 | namespace elf { |
| 17 | struct OutputSectionCommand; | 15 | void writeMapFile(); |
| 18 | template <class ELFT> | ||
| 19 | void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script); | ||
| 20 | } // namespace elf | 16 | } // namespace elf |
| 21 | } // namespace lld | 17 | } // namespace lld |
| 22 | 18 |
deps/lld/ELF/MarkLive.cpp+119-72| ... | @@ -22,13 +22,13 @@ | ... | @@ -22,13 +22,13 @@ |
| 22 | 22 | ||
| 23 | #include "InputSection.h" | 23 | #include "InputSection.h" |
| 24 | #include "LinkerScript.h" | 24 | #include "LinkerScript.h" |
| 25 | #include "Memory.h" | ||
| 26 | #include "OutputSections.h" | 25 | #include "OutputSections.h" |
| 27 | #include "Strings.h" | 26 | #include "Strings.h" |
| 28 | #include "SymbolTable.h" | 27 | #include "SymbolTable.h" |
| 29 | #include "Symbols.h" | 28 | #include "Symbols.h" |
| 30 | #include "Target.h" | 29 | #include "Target.h" |
| 31 | #include "Writer.h" | 30 | #include "Writer.h" |
| 31 | #include "lld/Common/Memory.h" | ||
| 32 | #include "llvm/ADT/STLExtras.h" | 32 | #include "llvm/ADT/STLExtras.h" |
| 33 | #include "llvm/Object/ELF.h" | 33 | #include "llvm/Object/ELF.h" |
| 34 | #include <functional> | 34 | #include <functional> |
| ... | @@ -42,15 +42,6 @@ using namespace llvm::support::endian; | ... | @@ -42,15 +42,6 @@ using namespace llvm::support::endian; |
| 42 | using namespace lld; | 42 | using namespace lld; |
| 43 | using namespace lld::elf; | 43 | using namespace lld::elf; |
| 44 | 44 | ||
| 45 | namespace { | ||
| 46 | // A resolved relocation. The Sec and Offset fields are set if the relocation | ||
| 47 | // was resolved to an offset within a section. | ||
| 48 | struct ResolvedReloc { | ||
| 49 | InputSectionBase *Sec; | ||
| 50 | uint64_t Offset; | ||
| 51 | }; | ||
| 52 | } // end anonymous namespace | ||
| 53 | |||
| 54 | template <class ELFT> | 45 | template <class ELFT> |
| 55 | static typename ELFT::uint getAddend(InputSectionBase &Sec, | 46 | static typename ELFT::uint getAddend(InputSectionBase &Sec, |
| 56 | const typename ELFT::Rel &Rel) { | 47 | const typename ELFT::Rel &Rel) { |
| ... | @@ -70,25 +61,36 @@ static DenseMap<StringRef, std::vector<InputSectionBase *>> CNamedSections; | ... | @@ -70,25 +61,36 @@ static DenseMap<StringRef, std::vector<InputSectionBase *>> CNamedSections; |
| 70 | 61 | ||
| 71 | template <class ELFT, class RelT> | 62 | template <class ELFT, class RelT> |
| 72 | static void resolveReloc(InputSectionBase &Sec, RelT &Rel, | 63 | static void resolveReloc(InputSectionBase &Sec, RelT &Rel, |
| 73 | std::function<void(ResolvedReloc)> Fn) { | 64 | std::function<void(InputSectionBase *, uint64_t)> Fn) { |
| 74 | SymbolBody &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel); | 65 | Symbol &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel); |
| 75 | if (auto *D = dyn_cast<DefinedRegular>(&B)) { | 66 | |
| 76 | if (!D->Section) | 67 | // If a symbol is referenced in a live section, it is used. |
| 68 | B.Used = true; | ||
| 69 | if (auto *SS = dyn_cast<SharedSymbol>(&B)) | ||
| 70 | if (!SS->isWeak()) | ||
| 71 | SS->getFile<ELFT>().IsNeeded = true; | ||
| 72 | |||
| 73 | if (auto *D = dyn_cast<Defined>(&B)) { | ||
| 74 | auto *RelSec = dyn_cast_or_null<InputSectionBase>(D->Section); | ||
| 75 | if (!RelSec) | ||
| 77 | return; | 76 | return; |
| 78 | typename ELFT::uint Offset = D->Value; | 77 | uint64_t Offset = D->Value; |
| 79 | if (D->isSection()) | 78 | if (D->isSection()) |
| 80 | Offset += getAddend<ELFT>(Sec, Rel); | 79 | Offset += getAddend<ELFT>(Sec, Rel); |
| 81 | Fn({cast<InputSectionBase>(D->Section), Offset}); | 80 | Fn(RelSec, Offset); |
| 82 | } else if (auto *U = dyn_cast<Undefined>(&B)) { | 81 | return; |
| 83 | for (InputSectionBase *Sec : CNamedSections.lookup(U->getName())) | ||
| 84 | Fn({Sec, 0}); | ||
| 85 | } | 82 | } |
| 83 | |||
| 84 | if (!B.isDefined()) | ||
| 85 | for (InputSectionBase *Sec : CNamedSections.lookup(B.getName())) | ||
| 86 | Fn(Sec, 0); | ||
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | // Calls Fn for each section that Sec refers to via relocations. | 89 | // Calls Fn for each section that Sec refers to via relocations. |
| 89 | template <class ELFT> | 90 | template <class ELFT> |
| 90 | static void forEachSuccessor(InputSection &Sec, | 91 | static void |
| 91 | std::function<void(ResolvedReloc)> Fn) { | 92 | forEachSuccessor(InputSection &Sec, |
| 93 | std::function<void(InputSectionBase *, uint64_t)> Fn) { | ||
| 92 | if (Sec.AreRelocsRela) { | 94 | if (Sec.AreRelocsRela) { |
| 93 | for (const typename ELFT::Rela &Rel : Sec.template relas<ELFT>()) | 95 | for (const typename ELFT::Rela &Rel : Sec.template relas<ELFT>()) |
| 94 | resolveReloc<ELFT>(Sec, Rel, Fn); | 96 | resolveReloc<ELFT>(Sec, Rel, Fn); |
| ... | @@ -96,8 +98,9 @@ static void forEachSuccessor(InputSection &Sec, | ... | @@ -96,8 +98,9 @@ static void forEachSuccessor(InputSection &Sec, |
| 96 | for (const typename ELFT::Rel &Rel : Sec.template rels<ELFT>()) | 98 | for (const typename ELFT::Rel &Rel : Sec.template rels<ELFT>()) |
| 97 | resolveReloc<ELFT>(Sec, Rel, Fn); | 99 | resolveReloc<ELFT>(Sec, Rel, Fn); |
| 98 | } | 100 | } |
| 101 | |||
| 99 | for (InputSectionBase *IS : Sec.DependentSections) | 102 | for (InputSectionBase *IS : Sec.DependentSections) |
| 100 | Fn({IS, 0}); | 103 | Fn(IS, 0); |
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | // The .eh_frame section is an unfortunate special case. | 106 | // The .eh_frame section is an unfortunate special case. |
| ... | @@ -115,9 +118,11 @@ static void forEachSuccessor(InputSection &Sec, | ... | @@ -115,9 +118,11 @@ static void forEachSuccessor(InputSection &Sec, |
| 115 | // the gc pass. With that we would be able to also gc some sections holding | 118 | // the gc pass. With that we would be able to also gc some sections holding |
| 116 | // LSDAs and personality functions if we found that they were unused. | 119 | // LSDAs and personality functions if we found that they were unused. |
| 117 | template <class ELFT, class RelTy> | 120 | template <class ELFT, class RelTy> |
| 118 | static void scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels, | 121 | static void |
| 119 | std::function<void(ResolvedReloc)> Enqueue) { | 122 | scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels, |
| 123 | std::function<void(InputSectionBase *, uint64_t)> Fn) { | ||
| 120 | const endianness E = ELFT::TargetEndianness; | 124 | const endianness E = ELFT::TargetEndianness; |
| 125 | |||
| 121 | for (unsigned I = 0, N = EH.Pieces.size(); I < N; ++I) { | 126 | for (unsigned I = 0, N = EH.Pieces.size(); I < N; ++I) { |
| 122 | EhSectionPiece &Piece = EH.Pieces[I]; | 127 | EhSectionPiece &Piece = EH.Pieces[I]; |
| 123 | unsigned FirstRelI = Piece.FirstRelocation; | 128 | unsigned FirstRelI = Piece.FirstRelocation; |
| ... | @@ -126,31 +131,31 @@ static void scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels, | ... | @@ -126,31 +131,31 @@ static void scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels, |
| 126 | if (read32<E>(Piece.data().data() + 4) == 0) { | 131 | if (read32<E>(Piece.data().data() + 4) == 0) { |
| 127 | // This is a CIE, we only need to worry about the first relocation. It is | 132 | // This is a CIE, we only need to worry about the first relocation. It is |
| 128 | // known to point to the personality function. | 133 | // known to point to the personality function. |
| 129 | resolveReloc<ELFT>(EH, Rels[FirstRelI], Enqueue); | 134 | resolveReloc<ELFT>(EH, Rels[FirstRelI], Fn); |
| 130 | continue; | 135 | continue; |
| 131 | } | 136 | } |
| 132 | // This is a FDE. The relocations point to the described function or to | 137 | // This is a FDE. The relocations point to the described function or to |
| 133 | // a LSDA. We only need to keep the LSDA alive, so ignore anything that | 138 | // a LSDA. We only need to keep the LSDA alive, so ignore anything that |
| 134 | // points to executable sections. | 139 | // points to executable sections. |
| 135 | typename ELFT::uint PieceEnd = Piece.InputOff + Piece.size(); | 140 | typename ELFT::uint PieceEnd = Piece.InputOff + Piece.Size; |
| 136 | for (unsigned I2 = FirstRelI, N2 = Rels.size(); I2 < N2; ++I2) { | 141 | for (unsigned I2 = FirstRelI, N2 = Rels.size(); I2 < N2; ++I2) { |
| 137 | const RelTy &Rel = Rels[I2]; | 142 | const RelTy &Rel = Rels[I2]; |
| 138 | if (Rel.r_offset >= PieceEnd) | 143 | if (Rel.r_offset >= PieceEnd) |
| 139 | break; | 144 | break; |
| 140 | resolveReloc<ELFT>(EH, Rels[I2], [&](ResolvedReloc R) { | 145 | resolveReloc<ELFT>(EH, Rels[I2], |
| 141 | if (!R.Sec || R.Sec == &InputSection::Discarded) | 146 | [&](InputSectionBase *Sec, uint64_t Offset) { |
| 142 | return; | 147 | if (Sec && Sec != &InputSection::Discarded && |
| 143 | if (R.Sec->Flags & SHF_EXECINSTR) | 148 | !(Sec->Flags & SHF_EXECINSTR)) |
| 144 | return; | 149 | Fn(Sec, 0); |
| 145 | Enqueue({R.Sec, 0}); | 150 | }); |
| 146 | }); | ||
| 147 | } | 151 | } |
| 148 | } | 152 | } |
| 149 | } | 153 | } |
| 150 | 154 | ||
| 151 | template <class ELFT> | 155 | template <class ELFT> |
| 152 | static void scanEhFrameSection(EhInputSection &EH, | 156 | static void |
| 153 | std::function<void(ResolvedReloc)> Enqueue) { | 157 | scanEhFrameSection(EhInputSection &EH, |
| 158 | std::function<void(InputSectionBase *, uint64_t)> Fn) { | ||
| 154 | if (!EH.NumRelocations) | 159 | if (!EH.NumRelocations) |
| 155 | return; | 160 | return; |
| 156 | 161 | ||
| ... | @@ -159,14 +164,14 @@ static void scanEhFrameSection(EhInputSection &EH, | ... | @@ -159,14 +164,14 @@ static void scanEhFrameSection(EhInputSection &EH, |
| 159 | EH.split<ELFT>(); | 164 | EH.split<ELFT>(); |
| 160 | 165 | ||
| 161 | if (EH.AreRelocsRela) | 166 | if (EH.AreRelocsRela) |
| 162 | scanEhFrameSection<ELFT>(EH, EH.template relas<ELFT>(), Enqueue); | 167 | scanEhFrameSection<ELFT>(EH, EH.template relas<ELFT>(), Fn); |
| 163 | else | 168 | else |
| 164 | scanEhFrameSection<ELFT>(EH, EH.template rels<ELFT>(), Enqueue); | 169 | scanEhFrameSection<ELFT>(EH, EH.template rels<ELFT>(), Fn); |
| 165 | } | 170 | } |
| 166 | 171 | ||
| 167 | // We do not garbage-collect two types of sections: | 172 | // Some sections are used directly by the loader, so they should never be |
| 168 | // 1) Sections used by the loader (.init, .fini, .ctors, .dtors or .jcr) | 173 | // garbage-collected. This function returns true if a given section is such |
| 169 | // 2) Non-allocatable sections which typically contain debugging information | 174 | // section. |
| 170 | template <class ELFT> static bool isReserved(InputSectionBase *Sec) { | 175 | template <class ELFT> static bool isReserved(InputSectionBase *Sec) { |
| 171 | switch (Sec->Type) { | 176 | switch (Sec->Type) { |
| 172 | case SHT_FINI_ARRAY: | 177 | case SHT_FINI_ARRAY: |
| ... | @@ -175,9 +180,6 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) { | ... | @@ -175,9 +180,6 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) { |
| 175 | case SHT_PREINIT_ARRAY: | 180 | case SHT_PREINIT_ARRAY: |
| 176 | return true; | 181 | return true; |
| 177 | default: | 182 | default: |
| 178 | if (!(Sec->Flags & SHF_ALLOC)) | ||
| 179 | return true; | ||
| 180 | |||
| 181 | StringRef S = Sec->Name; | 183 | StringRef S = Sec->Name; |
| 182 | return S.startswith(".ctors") || S.startswith(".dtors") || | 184 | return S.startswith(".ctors") || S.startswith(".dtors") || |
| 183 | S.startswith(".init") || S.startswith(".fini") || | 185 | S.startswith(".init") || S.startswith(".fini") || |
| ... | @@ -188,72 +190,74 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) { | ... | @@ -188,72 +190,74 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) { |
| 188 | // This is the main function of the garbage collector. | 190 | // This is the main function of the garbage collector. |
| 189 | // Starting from GC-root sections, this function visits all reachable | 191 | // Starting from GC-root sections, this function visits all reachable |
| 190 | // sections to set their "Live" bits. | 192 | // sections to set their "Live" bits. |
| 191 | template <class ELFT> void elf::markLive() { | 193 | template <class ELFT> static void doGcSections() { |
| 192 | SmallVector<InputSection *, 256> Q; | 194 | SmallVector<InputSection *, 256> Q; |
| 193 | CNamedSections.clear(); | 195 | CNamedSections.clear(); |
| 194 | 196 | ||
| 195 | auto Enqueue = [&](ResolvedReloc R) { | 197 | auto Enqueue = [&](InputSectionBase *Sec, uint64_t Offset) { |
| 196 | // Skip over discarded sections. This in theory shouldn't happen, because | 198 | // Skip over discarded sections. This in theory shouldn't happen, because |
| 197 | // the ELF spec doesn't allow a relocation to point to a deduplicated | 199 | // the ELF spec doesn't allow a relocation to point to a deduplicated |
| 198 | // COMDAT section directly. Unfortunately this happens in practice (e.g. | 200 | // COMDAT section directly. Unfortunately this happens in practice (e.g. |
| 199 | // .eh_frame) so we need to add a check. | 201 | // .eh_frame) so we need to add a check. |
| 200 | if (R.Sec == &InputSection::Discarded) | 202 | if (Sec == &InputSection::Discarded) |
| 201 | return; | 203 | return; |
| 202 | 204 | ||
| 203 | // We don't gc non alloc sections. | ||
| 204 | if (!(R.Sec->Flags & SHF_ALLOC)) | ||
| 205 | return; | ||
| 206 | 205 | ||
| 207 | // Usually, a whole section is marked as live or dead, but in mergeable | 206 | // Usually, a whole section is marked as live or dead, but in mergeable |
| 208 | // (splittable) sections, each piece of data has independent liveness bit. | 207 | // (splittable) sections, each piece of data has independent liveness bit. |
| 209 | // So we explicitly tell it which offset is in use. | 208 | // So we explicitly tell it which offset is in use. |
| 210 | if (auto *MS = dyn_cast<MergeInputSection>(R.Sec)) | 209 | if (auto *MS = dyn_cast<MergeInputSection>(Sec)) |
| 211 | MS->markLiveAt(R.Offset); | 210 | MS->markLiveAt(Offset); |
| 212 | 211 | ||
| 213 | if (R.Sec->Live) | 212 | if (Sec->Live) |
| 214 | return; | 213 | return; |
| 215 | R.Sec->Live = true; | 214 | Sec->Live = true; |
| 215 | |||
| 216 | // Add input section to the queue. | 216 | // Add input section to the queue. |
| 217 | if (InputSection *S = dyn_cast<InputSection>(R.Sec)) | 217 | if (InputSection *S = dyn_cast<InputSection>(Sec)) |
| 218 | Q.push_back(S); | 218 | Q.push_back(S); |
| 219 | }; | 219 | }; |
| 220 | 220 | ||
| 221 | auto MarkSymbol = [&](const SymbolBody *Sym) { | 221 | auto MarkSymbol = [&](Symbol *Sym) { |
| 222 | if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym)) | 222 | if (auto *D = dyn_cast_or_null<Defined>(Sym)) |
| 223 | if (auto *IS = cast_or_null<InputSectionBase>(D->Section)) | 223 | if (auto *IS = dyn_cast_or_null<InputSectionBase>(D->Section)) |
| 224 | Enqueue({IS, D->Value}); | 224 | Enqueue(IS, D->Value); |
| 225 | }; | 225 | }; |
| 226 | 226 | ||
| 227 | // Add GC root symbols. | 227 | // Add GC root symbols. |
| 228 | MarkSymbol(Symtab<ELFT>::X->find(Config->Entry)); | 228 | MarkSymbol(Symtab->find(Config->Entry)); |
| 229 | MarkSymbol(Symtab<ELFT>::X->find(Config->Init)); | 229 | MarkSymbol(Symtab->find(Config->Init)); |
| 230 | MarkSymbol(Symtab<ELFT>::X->find(Config->Fini)); | 230 | MarkSymbol(Symtab->find(Config->Fini)); |
| 231 | for (StringRef S : Config->Undefined) | 231 | for (StringRef S : Config->Undefined) |
| 232 | MarkSymbol(Symtab<ELFT>::X->find(S)); | 232 | MarkSymbol(Symtab->find(S)); |
| 233 | for (StringRef S : Script->Opt.ReferencedSymbols) | 233 | for (StringRef S : Script->ReferencedSymbols) |
| 234 | MarkSymbol(Symtab<ELFT>::X->find(S)); | 234 | MarkSymbol(Symtab->find(S)); |
| 235 | 235 | ||
| 236 | // Preserve externally-visible symbols if the symbols defined by this | 236 | // Preserve externally-visible symbols if the symbols defined by this |
| 237 | // file can interrupt other ELF file's symbols at runtime. | 237 | // file can interrupt other ELF file's symbols at runtime. |
| 238 | for (const Symbol *S : Symtab<ELFT>::X->getSymbols()) | 238 | for (Symbol *S : Symtab->getSymbols()) |
| 239 | if (S->includeInDynsym()) | 239 | if (S->includeInDynsym()) |
| 240 | MarkSymbol(S->body()); | 240 | MarkSymbol(S); |
| 241 | 241 | ||
| 242 | // Preserve special sections and those which are specified in linker | 242 | // Preserve special sections and those which are specified in linker |
| 243 | // script KEEP command. | 243 | // script KEEP command. |
| 244 | for (InputSectionBase *Sec : InputSections) { | 244 | for (InputSectionBase *Sec : InputSections) { |
| 245 | // .eh_frame is always marked as live now, but also it can reference to | 245 | // Mark .eh_frame sections as live because there are usually no relocations |
| 246 | // sections that contain personality. We preserve all non-text sections | 246 | // that point to .eh_frames. Otherwise, the garbage collector would drop |
| 247 | // referred by .eh_frame here. | 247 | // all of them. We also want to preserve personality routines and LSDA |
| 248 | if (auto *EH = dyn_cast_or_null<EhInputSection>(Sec)) | 248 | // referenced by .eh_frame sections, so we scan them for that here. |
| 249 | if (auto *EH = dyn_cast<EhInputSection>(Sec)) { | ||
| 250 | EH->Live = true; | ||
| 249 | scanEhFrameSection<ELFT>(*EH, Enqueue); | 251 | scanEhFrameSection<ELFT>(*EH, Enqueue); |
| 252 | } | ||
| 253 | |||
| 250 | if (Sec->Flags & SHF_LINK_ORDER) | 254 | if (Sec->Flags & SHF_LINK_ORDER) |
| 251 | continue; | 255 | continue; |
| 252 | if (isReserved<ELFT>(Sec) || Script->shouldKeep(Sec)) | 256 | if (isReserved<ELFT>(Sec) || Script->shouldKeep(Sec)) |
| 253 | Enqueue({Sec, 0}); | 257 | Enqueue(Sec, 0); |
| 254 | else if (isValidCIdentifier(Sec->Name)) { | 258 | else if (isValidCIdentifier(Sec->Name)) { |
| 255 | CNamedSections[Saver.save("__start_" + Sec->Name)].push_back(Sec); | 259 | CNamedSections[Saver.save("__start_" + Sec->Name)].push_back(Sec); |
| 256 | CNamedSections[Saver.save("__end_" + Sec->Name)].push_back(Sec); | 260 | CNamedSections[Saver.save("__stop_" + Sec->Name)].push_back(Sec); |
| 257 | } | 261 | } |
| 258 | } | 262 | } |
| 259 | 263 | ||
| ... | @@ -262,6 +266,49 @@ template <class ELFT> void elf::markLive() { | ... | @@ -262,6 +266,49 @@ template <class ELFT> void elf::markLive() { |
| 262 | forEachSuccessor<ELFT>(*Q.pop_back_val(), Enqueue); | 266 | forEachSuccessor<ELFT>(*Q.pop_back_val(), Enqueue); |
| 263 | } | 267 | } |
| 264 | 268 | ||
| 269 | // Before calling this function, Live bits are off for all | ||
| 270 | // input sections. This function make some or all of them on | ||
| 271 | // so that they are emitted to the output file. | ||
| 272 | template <class ELFT> void elf::markLive() { | ||
| 273 | // If -gc-sections is missing, no sections are removed. | ||
| 274 | if (!Config->GcSections) { | ||
| 275 | for (InputSectionBase *Sec : InputSections) | ||
| 276 | Sec->Live = true; | ||
| 277 | return; | ||
| 278 | } | ||
| 279 | |||
| 280 | // The -gc-sections option works only for SHF_ALLOC sections | ||
| 281 | // (sections that are memory-mapped at runtime). So we can | ||
| 282 | // unconditionally make non-SHF_ALLOC sections alive. | ||
| 283 | // | ||
| 284 | // Non SHF_ALLOC sections are not removed even if they are | ||
| 285 | // unreachable through relocations because reachability is not | ||
| 286 | // a good signal whether they are garbage or not (e.g. there is | ||
| 287 | // usually no section referring to a .comment section, but we | ||
| 288 | // want to keep it.) | ||
| 289 | // | ||
| 290 | // Note on SHF_REL{,A}: Such sections reach here only when -r | ||
| 291 | // or -emit-reloc were given. And they are subject of garbage | ||
| 292 | // collection because, if we remove a text section, we also | ||
| 293 | // remove its relocation section. | ||
| 294 | for (InputSectionBase *Sec : InputSections) { | ||
| 295 | bool IsAlloc = (Sec->Flags & SHF_ALLOC); | ||
| 296 | bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA); | ||
| 297 | if (!IsAlloc && !IsRel) | ||
| 298 | Sec->Live = true; | ||
| 299 | } | ||
| 300 | |||
| 301 | // Follow the graph to mark all live sections. | ||
| 302 | doGcSections<ELFT>(); | ||
| 303 | |||
| 304 | // Report garbage-collected sections. | ||
| 305 | if (Config->PrintGcSections) | ||
| 306 | for (InputSectionBase *Sec : InputSections) | ||
| 307 | if (!Sec->Live) | ||
| 308 | message("removing unused section from '" + Sec->Name + "' in file '" + | ||
| 309 | Sec->File->getName() + "'"); | ||
| 310 | } | ||
| 311 | |||
| 265 | template void elf::markLive<ELF32LE>(); | 312 | template void elf::markLive<ELF32LE>(); |
| 266 | template void elf::markLive<ELF32BE>(); | 313 | template void elf::markLive<ELF32BE>(); |
| 267 | template void elf::markLive<ELF64LE>(); | 314 | template void elf::markLive<ELF64LE>(); |
deps/lld/ELF/Memory.h deleted-67| ... | @@ -1,67 +0,0 @@ | ||
| 1 | //===- Memory.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 | // This file defines arena allocators. | ||
| 11 | // | ||
| 12 | // Almost all large objects, such as files, sections or symbols, are | ||
| 13 | // used for the entire lifetime of the linker once they are created. | ||
| 14 | // This usage characteristic makes arena allocator an attractive choice | ||
| 15 | // where the entire linker is one arena. With an arena, newly created | ||
| 16 | // objects belong to the arena and freed all at once when everything is done. | ||
| 17 | // Arena allocators are efficient and easy to understand. | ||
| 18 | // Most objects are allocated using the arena allocators defined by this file. | ||
| 19 | // | ||
| 20 | // If you edit this file, please edit COFF/Memory.h too. | ||
| 21 | // | ||
| 22 | //===----------------------------------------------------------------------===// | ||
| 23 | |||
| 24 | #ifndef LLD_ELF_MEMORY_H | ||
| 25 | #define LLD_ELF_MEMORY_H | ||
| 26 | |||
| 27 | #include "llvm/Support/Allocator.h" | ||
| 28 | #include "llvm/Support/StringSaver.h" | ||
| 29 | #include <vector> | ||
| 30 | |||
| 31 | namespace lld { | ||
| 32 | namespace elf { | ||
| 33 | |||
| 34 | // Use this arena if your object doesn't have a destructor. | ||
| 35 | extern llvm::BumpPtrAllocator BAlloc; | ||
| 36 | extern llvm::StringSaver Saver; | ||
| 37 | |||
| 38 | // These two classes are hack to keep track of all | ||
| 39 | // SpecificBumpPtrAllocator instances. | ||
| 40 | struct SpecificAllocBase { | ||
| 41 | SpecificAllocBase() { Instances.push_back(this); } | ||
| 42 | virtual ~SpecificAllocBase() = default; | ||
| 43 | virtual void reset() = 0; | ||
| 44 | static std::vector<SpecificAllocBase *> Instances; | ||
| 45 | }; | ||
| 46 | |||
| 47 | template <class T> struct SpecificAlloc : public SpecificAllocBase { | ||
| 48 | void reset() override { Alloc.DestroyAll(); } | ||
| 49 | llvm::SpecificBumpPtrAllocator<T> Alloc; | ||
| 50 | }; | ||
| 51 | |||
| 52 | // Use this arena if your object has a destructor. | ||
| 53 | // Your destructor will be invoked from freeArena(). | ||
| 54 | template <typename T, typename... U> T *make(U &&... Args) { | ||
| 55 | static SpecificAlloc<T> Alloc; | ||
| 56 | return new (Alloc.Alloc.Allocate()) T(std::forward<U>(Args)...); | ||
| 57 | } | ||
| 58 | |||
| 59 | inline void freeArena() { | ||
| 60 | for (SpecificAllocBase *Alloc : SpecificAllocBase::Instances) | ||
| 61 | Alloc->reset(); | ||
| 62 | BAlloc.Reset(); | ||
| 63 | } | ||
| 64 | } // namespace elf | ||
| 65 | } // namespace lld | ||
| 66 | |||
| 67 | #endif | ||
deps/lld/ELF/Options.td+100-77| ... | @@ -5,7 +5,11 @@ include "llvm/Option/OptParser.td" | ... | @@ -5,7 +5,11 @@ include "llvm/Option/OptParser.td" |
| 5 | class F<string name>: Flag<["--", "-"], name>; | 5 | class F<string name>: Flag<["--", "-"], name>; |
| 6 | class J<string name>: Joined<["--", "-"], name>; | 6 | class J<string name>: Joined<["--", "-"], name>; |
| 7 | class S<string name>: Separate<["--", "-"], name>; | 7 | class S<string name>: Separate<["--", "-"], name>; |
| 8 | class JS<string name>: JoinedOrSeparate<["--", "-"], name>; | 8 | |
| 9 | multiclass Eq<string name> { | ||
| 10 | def "": Separate<["--", "-"], name>; | ||
| 11 | def _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>; | ||
| 12 | } | ||
| 9 | 13 | ||
| 10 | def auxiliary: S<"auxiliary">, HelpText<"Set DT_AUXILIARY field to the specified name">; | 14 | def auxiliary: S<"auxiliary">, HelpText<"Set DT_AUXILIARY field to the specified name">; |
| 11 | 15 | ||
| ... | @@ -22,21 +26,24 @@ def build_id: F<"build-id">, HelpText<"Generate build ID note">; | ... | @@ -22,21 +26,24 @@ def build_id: F<"build-id">, HelpText<"Generate build ID note">; |
| 22 | 26 | ||
| 23 | def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">; | 27 | def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">; |
| 24 | 28 | ||
| 25 | def compress_debug_sections : J<"compress-debug-sections=">, | 29 | defm compress_debug_sections : Eq<"compress-debug-sections">, |
| 26 | HelpText<"Compress DWARF debug sections">; | 30 | HelpText<"Compress DWARF debug sections">; |
| 27 | 31 | ||
| 28 | def defsym: J<"defsym=">, HelpText<"Define a symbol alias">; | 32 | defm defsym: Eq<"defsym">, HelpText<"Define a symbol alias">; |
| 29 | 33 | ||
| 30 | def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">, | 34 | defm library_path: Eq<"library-path">, |
| 31 | HelpText<"Add a directory to the library search path">; | 35 | HelpText<"Add a directory to the library search path">, MetaVarName<"<dir>">; |
| 32 | 36 | ||
| 33 | def O: Joined<["-"], "O">, HelpText<"Optimize output file size">; | 37 | def O: JoinedOrSeparate<["-"], "O">, HelpText<"Optimize output file size">; |
| 34 | 38 | ||
| 35 | def Tbss: S<"Tbss">, HelpText<"Same as --section-start with .bss as the sectionname">; | 39 | defm Tbss: Eq<"Tbss">, |
| 40 | HelpText<"Same as --section-start with .bss as the sectionname">; | ||
| 36 | 41 | ||
| 37 | def Tdata: S<"Tdata">, HelpText<"Same as --section-start with .data as the sectionname">; | 42 | defm Tdata: Eq<"Tdata">, |
| 43 | HelpText<"Same as --section-start with .data as the sectionname">; | ||
| 38 | 44 | ||
| 39 | def Ttext: S<"Ttext">, HelpText<"Same as --section-start with .text as the sectionname">; | 45 | defm Ttext: Eq<"Ttext">, |
| 46 | HelpText<"Same as --section-start with .text as the sectionname">; | ||
| 40 | 47 | ||
| 41 | def allow_multiple_definition: F<"allow-multiple-definition">, | 48 | def allow_multiple_definition: F<"allow-multiple-definition">, |
| 42 | HelpText<"Allow multiple definitions">; | 49 | HelpText<"Allow multiple definitions">; |
| ... | @@ -44,6 +51,9 @@ def allow_multiple_definition: F<"allow-multiple-definition">, | ... | @@ -44,6 +51,9 @@ def allow_multiple_definition: F<"allow-multiple-definition">, |
| 44 | def as_needed: F<"as-needed">, | 51 | def as_needed: F<"as-needed">, |
| 45 | HelpText<"Only set DT_NEEDED for shared libraries if used">; | 52 | HelpText<"Only set DT_NEEDED for shared libraries if used">; |
| 46 | 53 | ||
| 54 | // -chroot doesn't have a help text because it is an internal option. | ||
| 55 | def chroot: S<"chroot">; | ||
| 56 | |||
| 47 | def color_diagnostics: F<"color-diagnostics">, | 57 | def color_diagnostics: F<"color-diagnostics">, |
| 48 | HelpText<"Use colors in diagnostics">; | 58 | HelpText<"Use colors in diagnostics">; |
| 49 | 59 | ||
| ... | @@ -69,7 +79,7 @@ def discard_none: F<"discard-none">, | ... | @@ -69,7 +79,7 @@ def discard_none: F<"discard-none">, |
| 69 | def dynamic_linker: S<"dynamic-linker">, | 79 | def dynamic_linker: S<"dynamic-linker">, |
| 70 | HelpText<"Which dynamic linker to use">; | 80 | HelpText<"Which dynamic linker to use">; |
| 71 | 81 | ||
| 72 | def dynamic_list: S<"dynamic-list">, | 82 | defm dynamic_list: Eq<"dynamic-list">, |
| 73 | HelpText<"Read a list of dynamic symbols">; | 83 | HelpText<"Read a list of dynamic symbols">; |
| 74 | 84 | ||
| 75 | def eh_frame_hdr: F<"eh-frame-hdr">, | 85 | def eh_frame_hdr: F<"eh-frame-hdr">, |
| ... | @@ -83,37 +93,42 @@ def enable_new_dtags: F<"enable-new-dtags">, | ... | @@ -83,37 +93,42 @@ def enable_new_dtags: F<"enable-new-dtags">, |
| 83 | def end_lib: F<"end-lib">, | 93 | def end_lib: F<"end-lib">, |
| 84 | HelpText<"End a grouping of objects that should be treated as if they were together in an archive">; | 94 | HelpText<"End a grouping of objects that should be treated as if they were together in an archive">; |
| 85 | 95 | ||
| 86 | def entry: S<"entry">, MetaVarName<"<entry>">, | 96 | defm entry: Eq<"entry">, HelpText<"Name of entry point symbol">, |
| 87 | HelpText<"Name of entry point symbol">; | 97 | MetaVarName<"<entry>">; |
| 88 | 98 | ||
| 89 | def error_limit: S<"error-limit">, | 99 | defm error_limit: Eq<"error-limit">, |
| 90 | HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">; | 100 | HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">; |
| 91 | 101 | ||
| 92 | def error_unresolved_symbols: F<"error-unresolved-symbols">, | 102 | def error_unresolved_symbols: F<"error-unresolved-symbols">, |
| 93 | HelpText<"Report unresolved symbols as errors">; | 103 | HelpText<"Report unresolved symbols as errors">; |
| 94 | 104 | ||
| 95 | def exclude_libs: S<"exclude-libs">, | 105 | defm exclude_libs: Eq<"exclude-libs">, |
| 96 | HelpText<"Exclude static libraries from automatic export">; | 106 | HelpText<"Exclude static libraries from automatic export">; |
| 97 | 107 | ||
| 98 | def export_dynamic: F<"export-dynamic">, | 108 | def export_dynamic: F<"export-dynamic">, |
| 99 | HelpText<"Put symbols in the dynamic symbol table">; | 109 | HelpText<"Put symbols in the dynamic symbol table">; |
| 100 | 110 | ||
| 101 | def export_dynamic_symbol: S<"export-dynamic-symbol">, | 111 | defm export_dynamic_symbol: Eq<"export-dynamic-symbol">, |
| 102 | HelpText<"Put a symbol in the dynamic symbol table">; | 112 | HelpText<"Put a symbol in the dynamic symbol table">; |
| 103 | 113 | ||
| 104 | def fatal_warnings: F<"fatal-warnings">, | 114 | def fatal_warnings: F<"fatal-warnings">, |
| 105 | HelpText<"Treat warnings as errors">; | 115 | HelpText<"Treat warnings as errors">; |
| 106 | 116 | ||
| 107 | def filter: J<"filter=">, HelpText<"Set DT_FILTER field to the specified name">; | 117 | defm filter: Eq<"filter">, |
| 118 | HelpText<"Set DT_FILTER field to the specified name">; | ||
| 108 | 119 | ||
| 109 | def fini: S<"fini">, MetaVarName<"<symbol>">, | 120 | defm fini: Eq<"fini">, |
| 110 | HelpText<"Specify a finalizer function">; | 121 | HelpText<"Specify a finalizer function">, MetaVarName<"<symbol>">; |
| 122 | |||
| 123 | def fix_cortex_a53_843419: F<"fix-cortex-a53-843419">, | ||
| 124 | HelpText<"Apply fixes for AArch64 Cortex-A53 erratum 843419">; | ||
| 111 | 125 | ||
| 112 | def full_shutdown : F<"full-shutdown">, | 126 | def full_shutdown : F<"full-shutdown">, |
| 113 | HelpText<"Perform a full shutdown instead of calling _exit">; | 127 | HelpText<"Perform a full shutdown instead of calling _exit">; |
| 114 | 128 | ||
| 115 | def format: J<"format=">, MetaVarName<"<input-format>">, | 129 | defm format: Eq<"format">, |
| 116 | HelpText<"Change the input format of the inputs following this option">; | 130 | HelpText<"Change the input format of the inputs following this option">, |
| 131 | MetaVarName<"<input-format>">; | ||
| 117 | 132 | ||
| 118 | def gc_sections: F<"gc-sections">, | 133 | def gc_sections: F<"gc-sections">, |
| 119 | HelpText<"Enable garbage collection of unused sections">; | 134 | HelpText<"Enable garbage collection of unused sections">; |
| ... | @@ -121,29 +136,35 @@ def gc_sections: F<"gc-sections">, | ... | @@ -121,29 +136,35 @@ def gc_sections: F<"gc-sections">, |
| 121 | def gdb_index: F<"gdb-index">, | 136 | def gdb_index: F<"gdb-index">, |
| 122 | HelpText<"Generate .gdb_index section">; | 137 | HelpText<"Generate .gdb_index section">; |
| 123 | 138 | ||
| 124 | def hash_style: S<"hash-style">, | 139 | defm hash_style: Eq<"hash-style">, |
| 125 | HelpText<"Specify hash style (sysv, gnu or both)">; | 140 | HelpText<"Specify hash style (sysv, gnu or both)">; |
| 126 | 141 | ||
| 127 | def help: F<"help">, HelpText<"Print option help">; | 142 | def help: F<"help">, HelpText<"Print option help">; |
| 128 | 143 | ||
| 129 | def icf_all: F<"icf=all">, HelpText<"Enable identical code folding">; | 144 | def icf_all: F<"icf=all">, HelpText<"Enable identical code folding">; |
| 130 | 145 | ||
| 146 | def icf_data: F<"icf-data">, | ||
| 147 | HelpText<"Enable ICF to also fold identical read only data">; | ||
| 148 | |||
| 131 | def icf_none: F<"icf=none">, HelpText<"Disable identical code folding">; | 149 | def icf_none: F<"icf=none">, HelpText<"Disable identical code folding">; |
| 132 | 150 | ||
| 133 | def image_base : J<"image-base=">, HelpText<"Set the base address">; | 151 | defm image_base : Eq<"image-base">, HelpText<"Set the base address">; |
| 134 | 152 | ||
| 135 | def init: S<"init">, MetaVarName<"<symbol>">, | 153 | defm init: Eq<"init">, HelpText<"Specify an initializer function">, |
| 136 | HelpText<"Specify an initializer function">; | 154 | MetaVarName<"<symbol>">; |
| 137 | 155 | ||
| 138 | def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">, | 156 | defm library: Eq<"library">, HelpText<"Root name of library to use">, |
| 139 | HelpText<"Root name of library to use">; | 157 | MetaVarName<"<libName>">; |
| 140 | 158 | ||
| 141 | def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">, | 159 | def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">, |
| 142 | HelpText<"Optimization level for LTO">; | 160 | HelpText<"Optimization level for LTO">; |
| 143 | 161 | ||
| 144 | def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">; | 162 | def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">; |
| 145 | 163 | ||
| 146 | def Map: JS<"Map">, HelpText<"Print a link map to the specified file">; | 164 | defm Map: Eq<"Map">, HelpText<"Print a link map to the specified file">; |
| 165 | |||
| 166 | def merge_exidx_entries: F<"merge-exidx-entries">, | ||
| 167 | HelpText<"Enable merging .ARM.exidx entries">; | ||
| 147 | 168 | ||
| 148 | def nostdlib: F<"nostdlib">, | 169 | def nostdlib: F<"nostdlib">, |
| 149 | HelpText<"Only search directories specified on the command line">; | 170 | HelpText<"Only search directories specified on the command line">; |
| ... | @@ -163,15 +184,24 @@ def no_demangle: F<"no-demangle">, | ... | @@ -163,15 +184,24 @@ def no_demangle: F<"no-demangle">, |
| 163 | def no_dynamic_linker: F<"no-dynamic-linker">, | 184 | def no_dynamic_linker: F<"no-dynamic-linker">, |
| 164 | HelpText<"Inhibit output of .interp section">; | 185 | HelpText<"Inhibit output of .interp section">; |
| 165 | 186 | ||
| 187 | def no_eh_frame_hdr: F<"no-eh-frame-hdr">, | ||
| 188 | HelpText<"Do not create .eh_frame_hdr section">; | ||
| 189 | |||
| 166 | def no_export_dynamic: F<"no-export-dynamic">; | 190 | def no_export_dynamic: F<"no-export-dynamic">; |
| 167 | def no_fatal_warnings: F<"no-fatal-warnings">; | 191 | def no_fatal_warnings: F<"no-fatal-warnings">; |
| 168 | 192 | ||
| 169 | def no_gc_sections: F<"no-gc-sections">, | 193 | def no_gc_sections: F<"no-gc-sections">, |
| 170 | HelpText<"Disable garbage collection of unused sections">; | 194 | HelpText<"Disable garbage collection of unused sections">; |
| 171 | 195 | ||
| 196 | def no_gdb_index: F<"no-gdb-index">, | ||
| 197 | HelpText<"Do not generate .gdb_index section">; | ||
| 198 | |||
| 172 | def no_gnu_unique: F<"no-gnu-unique">, | 199 | def no_gnu_unique: F<"no-gnu-unique">, |
| 173 | HelpText<"Disable STB_GNU_UNIQUE symbol binding">; | 200 | HelpText<"Disable STB_GNU_UNIQUE symbol binding">; |
| 174 | 201 | ||
| 202 | def no_merge_exidx_entries: F<"no-merge-exidx-entries">, | ||
| 203 | HelpText<"Disable merging .ARM.exidx entries">; | ||
| 204 | |||
| 175 | def no_threads: F<"no-threads">, | 205 | def no_threads: F<"no-threads">, |
| 176 | HelpText<"Do not run the linker multi-threaded">; | 206 | HelpText<"Do not run the linker multi-threaded">; |
| 177 | 207 | ||
| ... | @@ -183,7 +213,14 @@ def noinhibit_exec: F<"noinhibit-exec">, | ... | @@ -183,7 +213,14 @@ def noinhibit_exec: F<"noinhibit-exec">, |
| 183 | 213 | ||
| 184 | def nopie: F<"nopie">, HelpText<"Do not create a position independent executable">; | 214 | def nopie: F<"nopie">, HelpText<"Do not create a position independent executable">; |
| 185 | 215 | ||
| 186 | def no_rosegment: F<"no-rosegment">, HelpText<"Do not put read-only non-executable sections in their own segment">; | 216 | def no_omagic: Flag<["--"], "no-omagic">, MetaVarName<"<magic>">, |
| 217 | HelpText<"Do not set the text data sections to be writable">; | ||
| 218 | |||
| 219 | def no_print_gc_sections: F<"no-print-gc-sections">, | ||
| 220 | HelpText<"Do not list removed unused sections">; | ||
| 221 | |||
| 222 | def no_rosegment: F<"no-rosegment">, | ||
| 223 | HelpText<"Do not put read-only non-executable sections in their own segment">; | ||
| 187 | 224 | ||
| 188 | def no_undefined: F<"no-undefined">, | 225 | def no_undefined: F<"no-undefined">, |
| 189 | HelpText<"Report unresolved symbols even if the linker is creating a shared library">; | 226 | HelpText<"Report unresolved symbols even if the linker is creating a shared library">; |
| ... | @@ -200,6 +237,12 @@ def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">, | ... | @@ -200,6 +237,12 @@ def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">, |
| 200 | def omagic: Flag<["--"], "omagic">, MetaVarName<"<magic>">, | 237 | def omagic: Flag<["--"], "omagic">, MetaVarName<"<magic>">, |
| 201 | HelpText<"Set the text and data sections to be readable and writable">; | 238 | HelpText<"Set the text and data sections to be readable and writable">; |
| 202 | 239 | ||
| 240 | defm orphan_handling: Eq<"orphan-handling">, | ||
| 241 | HelpText<"Control how orphan sections are handled when linker script used">; | ||
| 242 | |||
| 243 | def pack_dyn_relocs_eq: J<"pack-dyn-relocs=">, MetaVarName<"<format>">, | ||
| 244 | HelpText<"Pack dynamic relocations in the given format (none or android)">; | ||
| 245 | |||
| 203 | def pie: F<"pie">, HelpText<"Create a position independent executable">; | 246 | def pie: F<"pie">, HelpText<"Create a position independent executable">; |
| 204 | 247 | ||
| 205 | def print_gc_sections: F<"print-gc-sections">, | 248 | def print_gc_sections: F<"print-gc-sections">, |
| ... | @@ -208,26 +251,28 @@ def print_gc_sections: F<"print-gc-sections">, | ... | @@ -208,26 +251,28 @@ def print_gc_sections: F<"print-gc-sections">, |
| 208 | def print_map: F<"print-map">, | 251 | def print_map: F<"print-map">, |
| 209 | HelpText<"Print a link map to the standard output">; | 252 | HelpText<"Print a link map to the standard output">; |
| 210 | 253 | ||
| 211 | def reproduce: S<"reproduce">, | 254 | defm reproduce: Eq<"reproduce">, |
| 212 | HelpText<"Dump linker invocation and input files for debugging">; | 255 | HelpText<"Dump linker invocation and input files for debugging">; |
| 213 | 256 | ||
| 214 | def rpath: S<"rpath">, HelpText<"Add a DT_RUNPATH to the output">; | 257 | defm rpath: Eq<"rpath">, HelpText<"Add a DT_RUNPATH to the output">; |
| 215 | 258 | ||
| 216 | def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">; | 259 | def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">; |
| 217 | 260 | ||
| 218 | def retain_symbols_file: J<"retain-symbols-file=">, MetaVarName<"<file>">, | 261 | defm retain_symbols_file: Eq<"retain-symbols-file">, |
| 219 | HelpText<"Retain only the symbols listed in the file">; | 262 | HelpText<"Retain only the symbols listed in the file">, |
| 263 | MetaVarName<"<file>">; | ||
| 220 | 264 | ||
| 221 | def script: S<"script">, HelpText<"Read linker script">; | 265 | defm script: Eq<"script">, HelpText<"Read linker script">; |
| 222 | 266 | ||
| 223 | def section_start: S<"section-start">, MetaVarName<"<address>">, | 267 | def section_start: S<"section-start">, MetaVarName<"<address>">, |
| 224 | HelpText<"Set address of section">; | 268 | HelpText<"Set address of section">; |
| 225 | 269 | ||
| 226 | def shared: F<"shared">, HelpText<"Build a shared object">; | 270 | def shared: F<"shared">, HelpText<"Build a shared object">; |
| 227 | 271 | ||
| 228 | def soname: J<"soname=">, HelpText<"Set DT_SONAME">; | 272 | defm soname: Eq<"soname">, HelpText<"Set DT_SONAME">; |
| 229 | 273 | ||
| 230 | def sort_section: S<"sort-section">, HelpText<"Specifies sections sorting rule when linkerscript is used">; | 274 | defm sort_section: Eq<"sort-section">, |
| 275 | HelpText<"Specifies sections sorting rule when linkerscript is used">; | ||
| 231 | 276 | ||
| 232 | def start_lib: F<"start-lib">, | 277 | def start_lib: F<"start-lib">, |
| 233 | HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">; | 278 | HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">; |
| ... | @@ -239,27 +284,29 @@ def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; | ... | @@ -239,27 +284,29 @@ def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; |
| 239 | def symbol_ordering_file: S<"symbol-ordering-file">, | 284 | def symbol_ordering_file: S<"symbol-ordering-file">, |
| 240 | HelpText<"Layout sections in the order specified by symbol file">; | 285 | HelpText<"Layout sections in the order specified by symbol file">; |
| 241 | 286 | ||
| 242 | def sysroot: J<"sysroot=">, HelpText<"Set the system root">; | 287 | defm sysroot: Eq<"sysroot">, HelpText<"Set the system root">; |
| 243 | 288 | ||
| 244 | def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">; | 289 | def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">; |
| 245 | 290 | ||
| 246 | def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32">; | 291 | def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32">; |
| 247 | 292 | ||
| 248 | def target2: J<"target2=">, MetaVarName<"<type>">, HelpText<"Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel">; | 293 | defm target2: Eq<"target2">, |
| 294 | HelpText<"Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel">, | ||
| 295 | MetaVarName<"<type>">; | ||
| 249 | 296 | ||
| 250 | def threads: F<"threads">, HelpText<"Run the linker multi-threaded">; | 297 | def threads: F<"threads">, HelpText<"Run the linker multi-threaded">; |
| 251 | 298 | ||
| 252 | def trace: F<"trace">, HelpText<"Print the names of the input files">; | 299 | def trace: F<"trace">, HelpText<"Print the names of the input files">; |
| 253 | 300 | ||
| 254 | def trace_symbol : S<"trace-symbol">, HelpText<"Trace references to symbols">; | 301 | defm trace_symbol : Eq<"trace-symbol">, HelpText<"Trace references to symbols">; |
| 255 | 302 | ||
| 256 | def undefined: S<"undefined">, | 303 | defm undefined: Eq<"undefined">, |
| 257 | HelpText<"Force undefined symbol during linking">; | 304 | HelpText<"Force undefined symbol during linking">; |
| 258 | 305 | ||
| 259 | def unresolved_symbols: J<"unresolved-symbols=">, | 306 | defm unresolved_symbols: Eq<"unresolved-symbols">, |
| 260 | HelpText<"Determine how to handle unresolved symbols">; | 307 | HelpText<"Determine how to handle unresolved symbols">; |
| 261 | 308 | ||
| 262 | def rsp_quoting: J<"rsp-quoting=">, | 309 | defm rsp_quoting: Eq<"rsp-quoting">, |
| 263 | HelpText<"Quoting style for response files. Values supported: windows|posix">; | 310 | HelpText<"Quoting style for response files. Values supported: windows|posix">; |
| 264 | 311 | ||
| 265 | def v: Flag<["-"], "v">, HelpText<"Display the version number">; | 312 | def v: Flag<["-"], "v">, HelpText<"Display the version number">; |
| ... | @@ -268,8 +315,7 @@ def verbose: F<"verbose">, HelpText<"Verbose mode">; | ... | @@ -268,8 +315,7 @@ def verbose: F<"verbose">, HelpText<"Verbose mode">; |
| 268 | 315 | ||
| 269 | def version: F<"version">, HelpText<"Display the version number and exit">; | 316 | def version: F<"version">, HelpText<"Display the version number and exit">; |
| 270 | 317 | ||
| 271 | def version_script: S<"version-script">, | 318 | defm version_script: Eq<"version-script">, HelpText<"Read a version script">; |
| 272 | HelpText<"Read a version script">; | ||
| 273 | 319 | ||
| 274 | def warn_common: F<"warn-common">, | 320 | def warn_common: F<"warn-common">, |
| 275 | HelpText<"Warn about duplicate common symbols">; | 321 | HelpText<"Warn about duplicate common symbols">; |
| ... | @@ -280,8 +326,8 @@ def warn_unresolved_symbols: F<"warn-unresolved-symbols">, | ... | @@ -280,8 +326,8 @@ def warn_unresolved_symbols: F<"warn-unresolved-symbols">, |
| 280 | def whole_archive: F<"whole-archive">, | 326 | def whole_archive: F<"whole-archive">, |
| 281 | HelpText<"Force load of all members in a static library">; | 327 | HelpText<"Force load of all members in a static library">; |
| 282 | 328 | ||
| 283 | def wrap: S<"wrap">, MetaVarName<"<symbol>">, | 329 | defm wrap: Eq<"wrap">, HelpText<"Use wrapper functions for symbol">, |
| 284 | HelpText<"Use wrapper functions for symbol">; | 330 | MetaVarName<"<symbol>">; |
| 285 | 331 | ||
| 286 | def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">, | 332 | def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">, |
| 287 | HelpText<"Linker option extensions">; | 333 | HelpText<"Linker option extensions">; |
| ... | @@ -293,60 +339,36 @@ def alias_Bdynamic_dy: F<"dy">, Alias<Bdynamic>; | ... | @@ -293,60 +339,36 @@ def alias_Bdynamic_dy: F<"dy">, Alias<Bdynamic>; |
| 293 | def alias_Bstatic_dn: F<"dn">, Alias<Bstatic>; | 339 | def alias_Bstatic_dn: F<"dn">, Alias<Bstatic>; |
| 294 | def alias_Bstatic_non_shared: F<"non_shared">, Alias<Bstatic>; | 340 | def alias_Bstatic_non_shared: F<"non_shared">, Alias<Bstatic>; |
| 295 | def alias_Bstatic_static: F<"static">, Alias<Bstatic>; | 341 | def alias_Bstatic_static: F<"static">, Alias<Bstatic>; |
| 296 | def alias_L__library_path: J<"library-path=">, Alias<L>; | ||
| 297 | def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>; | 342 | def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>; |
| 298 | def alias_define_common_dc: F<"dc">, Alias<define_common>; | 343 | def alias_define_common_dc: F<"dc">, Alias<define_common>; |
| 299 | def alias_define_common_dp: F<"dp">, Alias<define_common>; | 344 | def alias_define_common_dp: F<"dp">, Alias<define_common>; |
| 300 | def alias_defsym: S<"defsym">, Alias<defsym>; | ||
| 301 | def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>; | 345 | def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>; |
| 302 | def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>; | 346 | def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>; |
| 303 | def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>; | ||
| 304 | def alias_emit_relocs: Flag<["-"], "q">, Alias<emit_relocs>; | 347 | def alias_emit_relocs: Flag<["-"], "q">, Alias<emit_relocs>; |
| 305 | def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; | 348 | def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; |
| 306 | def alias_entry_entry: J<"entry=">, Alias<entry>; | ||
| 307 | def alias_error_limit: J<"error-limit=">, Alias<error_limit>; | ||
| 308 | def alias_exclude_libs: J<"exclude-libs=">, Alias<exclude_libs>; | ||
| 309 | def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>; | 349 | def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>; |
| 310 | def alias_export_dynamic_symbol: J<"export-dynamic-symbol=">, | ||
| 311 | Alias<export_dynamic_symbol>; | ||
| 312 | def alias_filter: Separate<["-"], "F">, Alias<filter>; | 350 | def alias_filter: Separate<["-"], "F">, Alias<filter>; |
| 313 | def alias_fini_fini: J<"fini=">, Alias<fini>; | ||
| 314 | def alias_format_b: S<"b">, Alias<format>; | 351 | def alias_format_b: S<"b">, Alias<format>; |
| 315 | def alias_hash_style_hash_style: J<"hash-style=">, Alias<hash_style>; | 352 | def alias_library: JoinedOrSeparate<["-"], "l">, Alias<library>; |
| 316 | def alias_init_init: J<"init=">, Alias<init>; | 353 | def alias_library_path: JoinedOrSeparate<["-"], "L">, Alias<library_path>; |
| 317 | def alias_l__library: J<"library=">, Alias<l>; | ||
| 318 | def alias_Map_eq: J<"Map=">, Alias<Map>; | ||
| 319 | def alias_omagic: Flag<["-"], "N">, Alias<omagic>; | 354 | def alias_omagic: Flag<["-"], "N">, Alias<omagic>; |
| 320 | def alias_o_output: Joined<["--"], "output=">, Alias<o>; | 355 | def alias_o_output: Joined<["--"], "output=">, Alias<o>; |
| 321 | def alias_o_output2 : Separate<["--"], "output">, Alias<o>; | 356 | def alias_o_output2 : Separate<["--"], "output">, Alias<o>; |
| 322 | def alias_pie_pic_executable: F<"pic-executable">, Alias<pie>; | 357 | def alias_pie_pic_executable: F<"pic-executable">, Alias<pie>; |
| 323 | def alias_print_map_M: Flag<["-"], "M">, Alias<print_map>; | 358 | def alias_print_map_M: Flag<["-"], "M">, Alias<print_map>; |
| 324 | def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>; | 359 | def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>; |
| 325 | def alias_reproduce_eq: J<"reproduce=">, Alias<reproduce>; | ||
| 326 | def alias_retain_symbols_file: S<"retain-symbols-file">, Alias<retain_symbols_file>; | ||
| 327 | def alias_rpath_R: JoinedOrSeparate<["-"], "R">, Alias<rpath>; | 360 | def alias_rpath_R: JoinedOrSeparate<["-"], "R">, Alias<rpath>; |
| 328 | def alias_rpath_rpath: J<"rpath=">, Alias<rpath>; | ||
| 329 | def alias_script_T: JoinedOrSeparate<["-"], "T">, Alias<script>; | 361 | def alias_script_T: JoinedOrSeparate<["-"], "T">, Alias<script>; |
| 330 | def alias_shared_Bshareable: F<"Bshareable">, Alias<shared>; | 362 | def alias_shared_Bshareable: F<"Bshareable">, Alias<shared>; |
| 331 | def alias_soname_h: JoinedOrSeparate<["-"], "h">, Alias<soname>; | 363 | def alias_soname_h: JoinedOrSeparate<["-"], "h">, Alias<soname>; |
| 332 | def alias_soname_soname: S<"soname">, Alias<soname>; | ||
| 333 | def alias_sort_section: J<"sort-section=">, Alias<sort_section>; | ||
| 334 | def alias_script: J<"script=">, Alias<script>; | ||
| 335 | def alias_strip_all: Flag<["-"], "s">, Alias<strip_all>; | 364 | def alias_strip_all: Flag<["-"], "s">, Alias<strip_all>; |
| 336 | def alias_strip_debug_S: Flag<["-"], "S">, Alias<strip_debug>; | 365 | def alias_strip_debug_S: Flag<["-"], "S">, Alias<strip_debug>; |
| 337 | def alias_Tbss: J<"Tbss=">, Alias<Tbss>; | ||
| 338 | def alias_Tdata: J<"Tdata=">, Alias<Tdata>; | ||
| 339 | def alias_trace: Flag<["-"], "t">, Alias<trace>; | 366 | def alias_trace: Flag<["-"], "t">, Alias<trace>; |
| 340 | def trace_trace_symbol_eq : J<"trace-symbol=">, Alias<trace_symbol>; | ||
| 341 | def alias_trace_symbol_y : JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>; | 367 | def alias_trace_symbol_y : JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>; |
| 342 | def alias_Ttext: J<"Ttext=">, Alias<Ttext>; | ||
| 343 | def alias_Ttext_segment: S<"Ttext-segment">, Alias<Ttext>; | 368 | def alias_Ttext_segment: S<"Ttext-segment">, Alias<Ttext>; |
| 344 | def alias_Ttext_segment_eq: J<"Ttext-segment=">, Alias<Ttext>; | 369 | def alias_Ttext_segment_eq: J<"Ttext-segment=">, Alias<Ttext>; |
| 345 | def alias_undefined_eq: J<"undefined=">, Alias<undefined>; | ||
| 346 | def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>; | 370 | def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>; |
| 347 | def alias_version_script_eq: J<"version-script=">, Alias<version_script>; | ||
| 348 | def alias_version_V: Flag<["-"], "V">, Alias<version>; | 371 | def alias_version_V: Flag<["-"], "V">, Alias<version>; |
| 349 | def alias_wrap_wrap: J<"wrap=">, Alias<wrap>; | ||
| 350 | 372 | ||
| 351 | // Our symbol resolution algorithm handles symbols in archive files differently | 373 | // Our symbol resolution algorithm handles symbols in archive files differently |
| 352 | // than traditional linkers, so we don't need --start-group and --end-group. | 374 | // than traditional linkers, so we don't need --start-group and --end-group. |
| ... | @@ -369,6 +391,8 @@ def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">, | ... | @@ -369,6 +391,8 @@ def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">, |
| 369 | HelpText<"YAML output file for optimization remarks">; | 391 | HelpText<"YAML output file for optimization remarks">; |
| 370 | def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">, | 392 | def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">, |
| 371 | HelpText<"Include hotness informations in the optimization remarks file">; | 393 | HelpText<"Include hotness informations in the optimization remarks file">; |
| 394 | defm plugin_opt: Eq<"plugin-opt">, | ||
| 395 | HelpText<"specifies LTO options for compatibility with GNU linkers">; | ||
| 372 | def save_temps: F<"save-temps">; | 396 | def save_temps: F<"save-temps">; |
| 373 | def thinlto_cache_dir: J<"thinlto-cache-dir=">, | 397 | def thinlto_cache_dir: J<"thinlto-cache-dir=">, |
| 374 | HelpText<"Path to ThinLTO cached object file directory">; | 398 | HelpText<"Path to ThinLTO cached object file directory">; |
| ... | @@ -385,18 +409,17 @@ def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; | ... | @@ -385,18 +409,17 @@ def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; |
| 385 | // --version output. | 409 | // --version output. |
| 386 | def plugin: S<"plugin">; | 410 | def plugin: S<"plugin">; |
| 387 | def plugin_eq: J<"plugin=">; | 411 | def plugin_eq: J<"plugin=">; |
| 388 | def plugin_opt: S<"plugin-opt">; | ||
| 389 | def plugin_opt_eq: J<"plugin-opt=">; | ||
| 390 | 412 | ||
| 391 | // Options listed below are silently ignored for now for compatibility. | 413 | // Options listed below are silently ignored for now for compatibility. |
| 392 | def allow_shlib_undefined: F<"allow-shlib-undefined">; | 414 | def allow_shlib_undefined: F<"allow-shlib-undefined">; |
| 393 | def cref: Flag<["--"], "cref">; | 415 | def cref: F<"cref">; |
| 394 | def detect_odr_violations: F<"detect-odr-violations">; | 416 | def detect_odr_violations: F<"detect-odr-violations">; |
| 395 | def g: Flag<["-"], "g">; | 417 | def g: Flag<["-"], "g">; |
| 418 | def long_plt: F<"long-plt">; | ||
| 396 | def no_add_needed: F<"no-add-needed">; | 419 | def no_add_needed: F<"no-add-needed">; |
| 397 | def no_allow_shlib_undefined: F<"no-allow-shlib-undefined">; | 420 | def no_allow_shlib_undefined: F<"no-allow-shlib-undefined">; |
| 398 | def no_copy_dt_needed_entries: F<"no-copy-dt-needed-entries">, | 421 | def no_copy_dt_needed_entries: F<"no-copy-dt-needed-entries">; |
| 399 | Alias<no_add_needed>; | 422 | def no_ctors_in_init_array: F<"no-ctors-in-init-array">; |
| 400 | def no_keep_memory: F<"no-keep-memory">; | 423 | def no_keep_memory: F<"no-keep-memory">; |
| 401 | def no_mmap_output_file: F<"no-mmap-output-file">; | 424 | def no_mmap_output_file: F<"no-mmap-output-file">; |
| 402 | def no_warn_common: F<"no-warn-common">; | 425 | def no_warn_common: F<"no-warn-common">; |
| ... | @@ -406,9 +429,9 @@ def rpath_link_eq: J<"rpath-link=">; | ... | @@ -406,9 +429,9 @@ def rpath_link_eq: J<"rpath-link=">; |
| 406 | def sort_common: F<"sort-common">; | 429 | def sort_common: F<"sort-common">; |
| 407 | def stats: F<"stats">; | 430 | def stats: F<"stats">; |
| 408 | def warn_execstack: F<"warn-execstack">; | 431 | def warn_execstack: F<"warn-execstack">; |
| 432 | def warn_once: F<"warn-once">; | ||
| 409 | def warn_shared_textrel: F<"warn-shared-textrel">; | 433 | def warn_shared_textrel: F<"warn-shared-textrel">; |
| 410 | def EB : F<"EB">; | 434 | def EB : F<"EB">; |
| 411 | def EL : F<"EL">; | 435 | def EL : F<"EL">; |
| 412 | def G: JoinedOrSeparate<["-"], "G">; | 436 | def G: JoinedOrSeparate<["-"], "G">; |
| 413 | def Qy : F<"Qy">; | 437 | def Qy : F<"Qy">; |
| 414 |
deps/lld/ELF/OutputSections.cpp+318-161| ... | @@ -10,13 +10,14 @@ | ... | @@ -10,13 +10,14 @@ |
| 10 | #include "OutputSections.h" | 10 | #include "OutputSections.h" |
| 11 | #include "Config.h" | 11 | #include "Config.h" |
| 12 | #include "LinkerScript.h" | 12 | #include "LinkerScript.h" |
| 13 | #include "Memory.h" | ||
| 14 | #include "Strings.h" | 13 | #include "Strings.h" |
| 15 | #include "SymbolTable.h" | 14 | #include "SymbolTable.h" |
| 16 | #include "SyntheticSections.h" | 15 | #include "SyntheticSections.h" |
| 17 | #include "Target.h" | 16 | #include "Target.h" |
| 18 | #include "Threads.h" | 17 | #include "lld/Common/Memory.h" |
| 18 | #include "lld/Common/Threads.h" | ||
| 19 | #include "llvm/BinaryFormat/Dwarf.h" | 19 | #include "llvm/BinaryFormat/Dwarf.h" |
| 20 | #include "llvm/Support/Compression.h" | ||
| 20 | #include "llvm/Support/MD5.h" | 21 | #include "llvm/Support/MD5.h" |
| 21 | #include "llvm/Support/MathExtras.h" | 22 | #include "llvm/Support/MathExtras.h" |
| 22 | #include "llvm/Support/SHA1.h" | 23 | #include "llvm/Support/SHA1.h" |
| ... | @@ -42,7 +43,6 @@ OutputSection *Out::InitArray; | ... | @@ -42,7 +43,6 @@ OutputSection *Out::InitArray; |
| 42 | OutputSection *Out::FiniArray; | 43 | OutputSection *Out::FiniArray; |
| 43 | 44 | ||
| 44 | std::vector<OutputSection *> elf::OutputSections; | 45 | std::vector<OutputSection *> elf::OutputSections; |
| 45 | std::vector<OutputSectionCommand *> elf::OutputSectionCommands; | ||
| 46 | 46 | ||
| 47 | uint32_t OutputSection::getPhdrFlags() const { | 47 | uint32_t OutputSection::getPhdrFlags() const { |
| 48 | uint32_t Ret = PF_R; | 48 | uint32_t Ret = PF_R; |
| ... | @@ -68,210 +68,367 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) { | ... | @@ -68,210 +68,367 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) { |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags) | 70 | OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags) |
| 71 | : SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type, | 71 | : BaseCommand(OutputSectionKind), |
| 72 | SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type, | ||
| 72 | /*Info*/ 0, | 73 | /*Info*/ 0, |
| 73 | /*Link*/ 0), | 74 | /*Link*/ 0), |
| 74 | SectionIndex(INT_MAX) {} | 75 | SectionIndex(INT_MAX) { |
| 76 | Live = false; | ||
| 77 | } | ||
| 75 | 78 | ||
| 76 | static uint64_t updateOffset(uint64_t Off, InputSection *S) { | 79 | // We allow sections of types listed below to merged into a |
| 77 | Off = alignTo(Off, S->Alignment); | 80 | // single progbits section. This is typically done by linker |
| 78 | S->OutSecOff = Off; | 81 | // scripts. Merging nobits and progbits will force disk space |
| 79 | return Off + S->getSize(); | 82 | // to be allocated for nobits sections. Other ones don't require |
| 83 | // any special treatment on top of progbits, so there doesn't | ||
| 84 | // seem to be a harm in merging them. | ||
| 85 | static bool canMergeToProgbits(unsigned Type) { | ||
| 86 | return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY || | ||
| 87 | Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY || | ||
| 88 | Type == SHT_NOTE; | ||
| 80 | } | 89 | } |
| 81 | 90 | ||
| 82 | void OutputSection::addSection(InputSection *S) { | 91 | void OutputSection::addSection(InputSection *IS) { |
| 83 | assert(S->Live); | 92 | if (!Live) { |
| 84 | Sections.push_back(S); | 93 | // If IS is the first section to be added to this section, |
| 85 | S->Parent = this; | 94 | // initialize Type and Entsize from IS. |
| 86 | this->updateAlignment(S->Alignment); | 95 | Live = true; |
| 96 | Type = IS->Type; | ||
| 97 | Entsize = IS->Entsize; | ||
| 98 | } else { | ||
| 99 | // Otherwise, check if new type or flags are compatible with existing ones. | ||
| 100 | if ((Flags & (SHF_ALLOC | SHF_TLS)) != (IS->Flags & (SHF_ALLOC | SHF_TLS))) | ||
| 101 | error("incompatible section flags for " + Name + "\n>>> " + toString(IS) + | ||
| 102 | ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name + | ||
| 103 | ": 0x" + utohexstr(Flags)); | ||
| 104 | |||
| 105 | if (Type != IS->Type) { | ||
| 106 | if (!canMergeToProgbits(Type) || !canMergeToProgbits(IS->Type)) | ||
| 107 | error("section type mismatch for " + IS->Name + "\n>>> " + | ||
| 108 | toString(IS) + ": " + | ||
| 109 | getELFSectionTypeName(Config->EMachine, IS->Type) + | ||
| 110 | "\n>>> output section " + Name + ": " + | ||
| 111 | getELFSectionTypeName(Config->EMachine, Type)); | ||
| 112 | Type = SHT_PROGBITS; | ||
| 113 | } | ||
| 114 | } | ||
| 87 | 115 | ||
| 88 | // The actual offsets will be computed by assignAddresses. For now, use | 116 | IS->Parent = this; |
| 89 | // crude approximation so that it is at least easy for other code to know the | 117 | Flags |= IS->Flags; |
| 90 | // section order. It is also used to calculate the output section size early | 118 | Alignment = std::max(Alignment, IS->Alignment); |
| 91 | // for compressed debug sections. | 119 | IS->OutSecOff = Size++; |
| 92 | this->Size = updateOffset(Size, S); | ||
| 93 | 120 | ||
| 94 | // If this section contains a table of fixed-size entries, sh_entsize | 121 | // If this section contains a table of fixed-size entries, sh_entsize |
| 95 | // holds the element size. Consequently, if this contains two or more | 122 | // holds the element size. If it contains elements of different size we |
| 96 | // input sections, all of them must have the same sh_entsize. However, | 123 | // set sh_entsize to 0. |
| 97 | // you can put different types of input sections into one output | 124 | if (Entsize != IS->Entsize) |
| 98 | // sectin by using linker scripts. I don't know what to do here. | 125 | Entsize = 0; |
| 99 | // Probably we sholuld handle that as an error. But for now we just | 126 | |
| 100 | // pick the largest sh_entsize. | 127 | if (!IS->Assigned) { |
| 101 | this->Entsize = std::max(this->Entsize, S->Entsize); | 128 | IS->Assigned = true; |
| 129 | if (SectionCommands.empty() || | ||
| 130 | !isa<InputSectionDescription>(SectionCommands.back())) | ||
| 131 | SectionCommands.push_back(make<InputSectionDescription>("")); | ||
| 132 | auto *ISD = cast<InputSectionDescription>(SectionCommands.back()); | ||
| 133 | ISD->Sections.push_back(IS); | ||
| 134 | } | ||
| 102 | } | 135 | } |
| 103 | 136 | ||
| 104 | static SectionKey createKey(InputSectionBase *C, StringRef OutsecName) { | 137 | void elf::sortByOrder(MutableArrayRef<InputSection *> In, |
| 105 | // The ELF spec just says | 138 | std::function<int(InputSectionBase *S)> Order) { |
| 106 | // ---------------------------------------------------------------- | 139 | typedef std::pair<int, InputSection *> Pair; |
| 107 | // In the first phase, input sections that match in name, type and | 140 | auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; }; |
| 108 | // attribute flags should be concatenated into single sections. | 141 | |
| 109 | // ---------------------------------------------------------------- | 142 | std::vector<Pair> V; |
| 110 | // | 143 | for (InputSection *S : In) |
| 111 | // However, it is clear that at least some flags have to be ignored for | 144 | V.push_back({Order(S), S}); |
| 112 | // section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be | 145 | std::stable_sort(V.begin(), V.end(), Comp); |
| 113 | // ignored. We should not have two output .text sections just because one was | ||
| 114 | // in a group and another was not for example. | ||
| 115 | // | ||
| 116 | // It also seems that that wording was a late addition and didn't get the | ||
| 117 | // necessary scrutiny. | ||
| 118 | // | ||
| 119 | // Merging sections with different flags is expected by some users. One | ||
| 120 | // reason is that if one file has | ||
| 121 | // | ||
| 122 | // int *const bar __attribute__((section(".foo"))) = (int *)0; | ||
| 123 | // | ||
| 124 | // gcc with -fPIC will produce a read only .foo section. But if another | ||
| 125 | // file has | ||
| 126 | // | ||
| 127 | // int zed; | ||
| 128 | // int *const bar __attribute__((section(".foo"))) = (int *)&zed; | ||
| 129 | // | ||
| 130 | // gcc with -fPIC will produce a read write section. | ||
| 131 | // | ||
| 132 | // Last but not least, when using linker script the merge rules are forced by | ||
| 133 | // the script. Unfortunately, linker scripts are name based. This means that | ||
| 134 | // expressions like *(.foo*) can refer to multiple input sections with | ||
| 135 | // different flags. We cannot put them in different output sections or we | ||
| 136 | // would produce wrong results for | ||
| 137 | // | ||
| 138 | // start = .; *(.foo.*) end = .; *(.bar) | ||
| 139 | // | ||
| 140 | // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to | ||
| 141 | // another. The problem is that there is no way to layout those output | ||
| 142 | // sections such that the .foo sections are the only thing between the start | ||
| 143 | // and end symbols. | ||
| 144 | // | ||
| 145 | // Given the above issues, we instead merge sections by name and error on | ||
| 146 | // incompatible types and flags. | ||
| 147 | |||
| 148 | uint32_t Alignment = 0; | ||
| 149 | uint64_t Flags = 0; | ||
| 150 | if (Config->Relocatable && (C->Flags & SHF_MERGE)) { | ||
| 151 | Alignment = std::max<uint64_t>(C->Alignment, C->Entsize); | ||
| 152 | Flags = C->Flags & (SHF_MERGE | SHF_STRINGS); | ||
| 153 | } | ||
| 154 | 146 | ||
| 155 | return SectionKey{OutsecName, Flags, Alignment}; | 147 | for (size_t I = 0; I < V.size(); ++I) |
| 148 | In[I] = V[I].second; | ||
| 156 | } | 149 | } |
| 157 | 150 | ||
| 158 | OutputSectionFactory::OutputSectionFactory() {} | 151 | uint64_t elf::getHeaderSize() { |
| 152 | if (Config->OFormatBinary) | ||
| 153 | return 0; | ||
| 154 | return Out::ElfHeader->Size + Out::ProgramHeaders->Size; | ||
| 155 | } | ||
| 159 | 156 | ||
| 160 | static uint64_t getIncompatibleFlags(uint64_t Flags) { | 157 | bool OutputSection::classof(const BaseCommand *C) { |
| 161 | return Flags & (SHF_ALLOC | SHF_TLS); | 158 | return C->Kind == OutputSectionKind; |
| 162 | } | 159 | } |
| 163 | 160 | ||
| 164 | // We allow sections of types listed below to merged into a | 161 | void OutputSection::sort(std::function<int(InputSectionBase *S)> Order) { |
| 165 | // single progbits section. This is typically done by linker | 162 | assert(Live); |
| 166 | // scripts. Merging nobits and progbits will force disk space | 163 | assert(SectionCommands.size() == 1); |
| 167 | // to be allocated for nobits sections. Other ones don't require | 164 | sortByOrder(cast<InputSectionDescription>(SectionCommands[0])->Sections, |
| 168 | // any special treatment on top of progbits, so there doesn't | 165 | Order); |
| 169 | // seem to be a harm in merging them. | ||
| 170 | static bool canMergeToProgbits(unsigned Type) { | ||
| 171 | return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY || | ||
| 172 | Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY || | ||
| 173 | Type == SHT_NOTE; | ||
| 174 | } | 166 | } |
| 175 | 167 | ||
| 176 | void elf::reportDiscarded(InputSectionBase *IS) { | 168 | // Fill [Buf, Buf + Size) with Filler. |
| 177 | if (!Config->PrintGcSections) | 169 | // This is used for linker script "=fillexp" command. |
| 178 | return; | 170 | static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { |
| 179 | message("removing unused section from '" + IS->Name + "' in file '" + | 171 | size_t I = 0; |
| 180 | IS->File->getName() + "'"); | 172 | for (; I + 4 < Size; I += 4) |
| 173 | memcpy(Buf + I, &Filler, 4); | ||
| 174 | memcpy(Buf + I, &Filler, Size - I); | ||
| 181 | } | 175 | } |
| 182 | 176 | ||
| 183 | void OutputSectionFactory::addInputSec(InputSectionBase *IS, | 177 | // Compress section contents if this section contains debug info. |
| 184 | StringRef OutsecName) { | 178 | template <class ELFT> void OutputSection::maybeCompress() { |
| 185 | // Sections with the SHT_GROUP attribute reach here only when the - r option | 179 | typedef typename ELFT::Chdr Elf_Chdr; |
| 186 | // is given. Such sections define "section groups", and InputFiles.cpp has | ||
| 187 | // dedup'ed section groups by their signatures. For the -r, we want to pass | ||
| 188 | // through all SHT_GROUP sections without merging them because merging them | ||
| 189 | // creates broken section contents. | ||
| 190 | if (IS->Type == SHT_GROUP) { | ||
| 191 | OutputSection *Out = nullptr; | ||
| 192 | addInputSec(IS, OutsecName, Out); | ||
| 193 | return; | ||
| 194 | } | ||
| 195 | 180 | ||
| 196 | // Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have | 181 | // Compress only DWARF debug sections. |
| 197 | // relocation sections .rela.foo and .rela.bar for example. Most tools do | 182 | if (!Config->CompressDebugSections || (Flags & SHF_ALLOC) || |
| 198 | // not allow multiple REL[A] sections for output section. Hence we | 183 | !Name.startswith(".debug_")) |
| 199 | // should combine these relocation sections into single output. | ||
| 200 | // We skip synthetic sections because it can be .rela.dyn/.rela.plt or any | ||
| 201 | // other REL[A] sections created by linker itself. | ||
| 202 | if (!isa<SyntheticSection>(IS) && | ||
| 203 | (IS->Type == SHT_REL || IS->Type == SHT_RELA)) { | ||
| 204 | auto *Sec = cast<InputSection>(IS); | ||
| 205 | OutputSection *Out = Sec->getRelocatedSection()->getOutputSection(); | ||
| 206 | addInputSec(IS, OutsecName, Out->RelocationSection); | ||
| 207 | return; | 184 | return; |
| 208 | } | ||
| 209 | 185 | ||
| 210 | SectionKey Key = createKey(IS, OutsecName); | 186 | // Create a section header. |
| 211 | OutputSection *&Sec = Map[Key]; | 187 | ZDebugHeader.resize(sizeof(Elf_Chdr)); |
| 212 | addInputSec(IS, OutsecName, Sec); | 188 | auto *Hdr = reinterpret_cast<Elf_Chdr *>(ZDebugHeader.data()); |
| 189 | Hdr->ch_type = ELFCOMPRESS_ZLIB; | ||
| 190 | Hdr->ch_size = Size; | ||
| 191 | Hdr->ch_addralign = Alignment; | ||
| 192 | |||
| 193 | // Write section contents to a temporary buffer and compress it. | ||
| 194 | std::vector<uint8_t> Buf(Size); | ||
| 195 | writeTo<ELFT>(Buf.data()); | ||
| 196 | if (Error E = zlib::compress(toStringRef(Buf), CompressedData)) | ||
| 197 | fatal("compress failed: " + llvm::toString(std::move(E))); | ||
| 198 | |||
| 199 | // Update section headers. | ||
| 200 | Size = sizeof(Elf_Chdr) + CompressedData.size(); | ||
| 201 | Flags |= SHF_COMPRESSED; | ||
| 213 | } | 202 | } |
| 214 | 203 | ||
| 215 | void OutputSectionFactory::addInputSec(InputSectionBase *IS, | 204 | static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { |
| 216 | StringRef OutsecName, | 205 | if (Size == 1) |
| 217 | OutputSection *&Sec) { | 206 | *Buf = Data; |
| 218 | if (!IS->Live) { | 207 | else if (Size == 2) |
| 219 | reportDiscarded(IS); | 208 | write16(Buf, Data, Config->Endianness); |
| 209 | else if (Size == 4) | ||
| 210 | write32(Buf, Data, Config->Endianness); | ||
| 211 | else if (Size == 8) | ||
| 212 | write64(Buf, Data, Config->Endianness); | ||
| 213 | else | ||
| 214 | llvm_unreachable("unsupported Size argument"); | ||
| 215 | } | ||
| 216 | |||
| 217 | template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) { | ||
| 218 | if (Type == SHT_NOBITS) | ||
| 219 | return; | ||
| 220 | |||
| 221 | Loc = Buf; | ||
| 222 | |||
| 223 | // If -compress-debug-section is specified and if this is a debug seciton, | ||
| 224 | // we've already compressed section contents. If that's the case, | ||
| 225 | // just write it down. | ||
| 226 | if (!CompressedData.empty()) { | ||
| 227 | memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size()); | ||
| 228 | memcpy(Buf + ZDebugHeader.size(), CompressedData.data(), | ||
| 229 | CompressedData.size()); | ||
| 220 | return; | 230 | return; |
| 221 | } | 231 | } |
| 222 | 232 | ||
| 223 | if (Sec) { | 233 | // Write leading padding. |
| 224 | if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags)) | 234 | std::vector<InputSection *> Sections; |
| 225 | error("incompatible section flags for " + Sec->Name + "\n>>> " + | 235 | for (BaseCommand *Cmd : SectionCommands) |
| 226 | toString(IS) + ": 0x" + utohexstr(IS->Flags) + | 236 | if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd)) |
| 227 | "\n>>> output section " + Sec->Name + ": 0x" + | 237 | for (InputSection *IS : ISD->Sections) |
| 228 | utohexstr(Sec->Flags)); | 238 | if (IS->Live) |
| 229 | if (Sec->Type != IS->Type) { | 239 | Sections.push_back(IS); |
| 230 | if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(IS->Type)) | 240 | uint32_t Filler = getFiller(); |
| 231 | Sec->Type = SHT_PROGBITS; | 241 | if (Filler) |
| 242 | fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler); | ||
| 243 | |||
| 244 | parallelForEachN(0, Sections.size(), [&](size_t I) { | ||
| 245 | InputSection *IS = Sections[I]; | ||
| 246 | IS->writeTo<ELFT>(Buf); | ||
| 247 | |||
| 248 | // Fill gaps between sections. | ||
| 249 | if (Filler) { | ||
| 250 | uint8_t *Start = Buf + IS->OutSecOff + IS->getSize(); | ||
| 251 | uint8_t *End; | ||
| 252 | if (I + 1 == Sections.size()) | ||
| 253 | End = Buf + Size; | ||
| 232 | else | 254 | else |
| 233 | error("section type mismatch for " + IS->Name + "\n>>> " + | 255 | End = Buf + Sections[I + 1]->OutSecOff; |
| 234 | toString(IS) + ": " + | 256 | fill(Start, End - Start, Filler); |
| 235 | getELFSectionTypeName(Config->EMachine, IS->Type) + | ||
| 236 | "\n>>> output section " + Sec->Name + ": " + | ||
| 237 | getELFSectionTypeName(Config->EMachine, Sec->Type)); | ||
| 238 | } | 257 | } |
| 239 | Sec->Flags |= IS->Flags; | 258 | }); |
| 240 | } else { | 259 | |
| 241 | Sec = make<OutputSection>(OutsecName, IS->Type, IS->Flags); | 260 | // Linker scripts may have BYTE()-family commands with which you |
| 242 | OutputSections.push_back(Sec); | 261 | // can write arbitrary bytes to the output. Process them if any. |
| 262 | for (BaseCommand *Base : SectionCommands) | ||
| 263 | if (auto *Data = dyn_cast<ByteCommand>(Base)) | ||
| 264 | writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); | ||
| 265 | } | ||
| 266 | |||
| 267 | template <class ELFT> | ||
| 268 | static void finalizeShtGroup(OutputSection *OS, | ||
| 269 | InputSection *Section) { | ||
| 270 | assert(Config->Relocatable); | ||
| 271 | |||
| 272 | // sh_link field for SHT_GROUP sections should contain the section index of | ||
| 273 | // the symbol table. | ||
| 274 | OS->Link = InX::SymTab->getParent()->SectionIndex; | ||
| 275 | |||
| 276 | // sh_info then contain index of an entry in symbol table section which | ||
| 277 | // provides signature of the section group. | ||
| 278 | ObjFile<ELFT> *Obj = Section->getFile<ELFT>(); | ||
| 279 | ArrayRef<Symbol *> Symbols = Obj->getSymbols(); | ||
| 280 | OS->Info = InX::SymTab->getSymbolIndex(Symbols[Section->Info]); | ||
| 281 | } | ||
| 282 | |||
| 283 | template <class ELFT> void OutputSection::finalize() { | ||
| 284 | InputSection *First = nullptr; | ||
| 285 | for (BaseCommand *Base : SectionCommands) { | ||
| 286 | if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) { | ||
| 287 | if (ISD->Sections.empty()) | ||
| 288 | continue; | ||
| 289 | if (First == nullptr) | ||
| 290 | First = ISD->Sections.front(); | ||
| 291 | } | ||
| 292 | if (isa<ByteCommand>(Base) && Type == SHT_NOBITS) | ||
| 293 | Type = SHT_PROGBITS; | ||
| 294 | } | ||
| 295 | |||
| 296 | if (Flags & SHF_LINK_ORDER) { | ||
| 297 | // We must preserve the link order dependency of sections with the | ||
| 298 | // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We | ||
| 299 | // need to translate the InputSection sh_link to the OutputSection sh_link, | ||
| 300 | // all InputSections in the OutputSection have the same dependency. | ||
| 301 | if (auto *D = First->getLinkOrderDep()) | ||
| 302 | Link = D->getParent()->SectionIndex; | ||
| 303 | } | ||
| 304 | |||
| 305 | if (Type == SHT_GROUP) { | ||
| 306 | finalizeShtGroup<ELFT>(this, First); | ||
| 307 | return; | ||
| 243 | } | 308 | } |
| 244 | 309 | ||
| 245 | Sec->addSection(cast<InputSection>(IS)); | 310 | if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL)) |
| 311 | return; | ||
| 312 | |||
| 313 | if (isa<SyntheticSection>(First)) | ||
| 314 | return; | ||
| 315 | |||
| 316 | Link = InX::SymTab->getParent()->SectionIndex; | ||
| 317 | // sh_info for SHT_REL[A] sections should contain the section header index of | ||
| 318 | // the section to which the relocation applies. | ||
| 319 | InputSectionBase *S = First->getRelocatedSection(); | ||
| 320 | Info = S->getOutputSection()->SectionIndex; | ||
| 321 | Flags |= SHF_INFO_LINK; | ||
| 322 | } | ||
| 323 | |||
| 324 | // Returns true if S matches /Filename.?\.o$/. | ||
| 325 | static bool isCrtBeginEnd(StringRef S, StringRef Filename) { | ||
| 326 | if (!S.endswith(".o")) | ||
| 327 | return false; | ||
| 328 | S = S.drop_back(2); | ||
| 329 | if (S.endswith(Filename)) | ||
| 330 | return true; | ||
| 331 | return !S.empty() && S.drop_back().endswith(Filename); | ||
| 246 | } | 332 | } |
| 247 | 333 | ||
| 248 | OutputSectionFactory::~OutputSectionFactory() {} | 334 | static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); } |
| 335 | static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); } | ||
| 249 | 336 | ||
| 250 | SectionKey DenseMapInfo<SectionKey>::getEmptyKey() { | 337 | // .ctors and .dtors are sorted by this priority from highest to lowest. |
| 251 | return SectionKey{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0}; | 338 | // |
| 339 | // 1. The section was contained in crtbegin (crtbegin contains | ||
| 340 | // some sentinel value in its .ctors and .dtors so that the runtime | ||
| 341 | // can find the beginning of the sections.) | ||
| 342 | // | ||
| 343 | // 2. The section has an optional priority value in the form of ".ctors.N" | ||
| 344 | // or ".dtors.N" where N is a number. Unlike .{init,fini}_array, | ||
| 345 | // they are compared as string rather than number. | ||
| 346 | // | ||
| 347 | // 3. The section is just ".ctors" or ".dtors". | ||
| 348 | // | ||
| 349 | // 4. The section was contained in crtend, which contains an end marker. | ||
| 350 | // | ||
| 351 | // In an ideal world, we don't need this function because .init_array and | ||
| 352 | // .ctors are duplicate features (and .init_array is newer.) However, there | ||
| 353 | // are too many real-world use cases of .ctors, so we had no choice to | ||
| 354 | // support that with this rather ad-hoc semantics. | ||
| 355 | static bool compCtors(const InputSection *A, const InputSection *B) { | ||
| 356 | bool BeginA = isCrtbegin(A->File->getName()); | ||
| 357 | bool BeginB = isCrtbegin(B->File->getName()); | ||
| 358 | if (BeginA != BeginB) | ||
| 359 | return BeginA; | ||
| 360 | bool EndA = isCrtend(A->File->getName()); | ||
| 361 | bool EndB = isCrtend(B->File->getName()); | ||
| 362 | if (EndA != EndB) | ||
| 363 | return EndB; | ||
| 364 | StringRef X = A->Name; | ||
| 365 | StringRef Y = B->Name; | ||
| 366 | assert(X.startswith(".ctors") || X.startswith(".dtors")); | ||
| 367 | assert(Y.startswith(".ctors") || Y.startswith(".dtors")); | ||
| 368 | X = X.substr(6); | ||
| 369 | Y = Y.substr(6); | ||
| 370 | if (X.empty() && Y.empty()) | ||
| 371 | return false; | ||
| 372 | return X < Y; | ||
| 252 | } | 373 | } |
| 253 | 374 | ||
| 254 | SectionKey DenseMapInfo<SectionKey>::getTombstoneKey() { | 375 | // Sorts input sections by the special rules for .ctors and .dtors. |
| 255 | return SectionKey{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 0}; | 376 | // Unfortunately, the rules are different from the one for .{init,fini}_array. |
| 377 | // Read the comment above. | ||
| 378 | void OutputSection::sortCtorsDtors() { | ||
| 379 | assert(SectionCommands.size() == 1); | ||
| 380 | auto *ISD = cast<InputSectionDescription>(SectionCommands[0]); | ||
| 381 | std::stable_sort(ISD->Sections.begin(), ISD->Sections.end(), compCtors); | ||
| 256 | } | 382 | } |
| 257 | 383 | ||
| 258 | unsigned DenseMapInfo<SectionKey>::getHashValue(const SectionKey &Val) { | 384 | // If an input string is in the form of "foo.N" where N is a number, |
| 259 | return hash_combine(Val.Name, Val.Flags, Val.Alignment); | 385 | // return N. Otherwise, returns 65536, which is one greater than the |
| 386 | // lowest priority. | ||
| 387 | int elf::getPriority(StringRef S) { | ||
| 388 | size_t Pos = S.rfind('.'); | ||
| 389 | if (Pos == StringRef::npos) | ||
| 390 | return 65536; | ||
| 391 | int V; | ||
| 392 | if (!to_integer(S.substr(Pos + 1), V, 10)) | ||
| 393 | return 65536; | ||
| 394 | return V; | ||
| 260 | } | 395 | } |
| 261 | 396 | ||
| 262 | bool DenseMapInfo<SectionKey>::isEqual(const SectionKey &LHS, | 397 | // Sorts input sections by section name suffixes, so that .foo.N comes |
| 263 | const SectionKey &RHS) { | 398 | // before .foo.M if N < M. Used to sort .{init,fini}_array.N sections. |
| 264 | return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) && | 399 | // We want to keep the original order if the priorities are the same |
| 265 | LHS.Flags == RHS.Flags && LHS.Alignment == RHS.Alignment; | 400 | // because the compiler keeps the original initialization order in a |
| 401 | // translation unit and we need to respect that. | ||
| 402 | // For more detail, read the section of the GCC's manual about init_priority. | ||
| 403 | void OutputSection::sortInitFini() { | ||
| 404 | // Sort sections by priority. | ||
| 405 | sort([](InputSectionBase *S) { return getPriority(S->Name); }); | ||
| 266 | } | 406 | } |
| 267 | 407 | ||
| 268 | uint64_t elf::getHeaderSize() { | 408 | uint32_t OutputSection::getFiller() { |
| 269 | if (Config->OFormatBinary) | 409 | if (Filler) |
| 270 | return 0; | 410 | return *Filler; |
| 271 | return Out::ElfHeader->Size + Out::ProgramHeaders->Size; | 411 | if (Flags & SHF_EXECINSTR) |
| 412 | return Target->TrapInstr; | ||
| 413 | return 0; | ||
| 272 | } | 414 | } |
| 273 | 415 | ||
| 274 | template void OutputSection::writeHeaderTo<ELF32LE>(ELF32LE::Shdr *Shdr); | 416 | template void OutputSection::writeHeaderTo<ELF32LE>(ELF32LE::Shdr *Shdr); |
| 275 | template void OutputSection::writeHeaderTo<ELF32BE>(ELF32BE::Shdr *Shdr); | 417 | template void OutputSection::writeHeaderTo<ELF32BE>(ELF32BE::Shdr *Shdr); |
| 276 | template void OutputSection::writeHeaderTo<ELF64LE>(ELF64LE::Shdr *Shdr); | 418 | template void OutputSection::writeHeaderTo<ELF64LE>(ELF64LE::Shdr *Shdr); |
| 277 | template void OutputSection::writeHeaderTo<ELF64BE>(ELF64BE::Shdr *Shdr); | 419 | template void OutputSection::writeHeaderTo<ELF64BE>(ELF64BE::Shdr *Shdr); |
| 420 | |||
| 421 | template void OutputSection::writeTo<ELF32LE>(uint8_t *Buf); | ||
| 422 | template void OutputSection::writeTo<ELF32BE>(uint8_t *Buf); | ||
| 423 | template void OutputSection::writeTo<ELF64LE>(uint8_t *Buf); | ||
| 424 | template void OutputSection::writeTo<ELF64BE>(uint8_t *Buf); | ||
| 425 | |||
| 426 | template void OutputSection::maybeCompress<ELF32LE>(); | ||
| 427 | template void OutputSection::maybeCompress<ELF32BE>(); | ||
| 428 | template void OutputSection::maybeCompress<ELF64LE>(); | ||
| 429 | template void OutputSection::maybeCompress<ELF64BE>(); | ||
| 430 | |||
| 431 | template void OutputSection::finalize<ELF32LE>(); | ||
| 432 | template void OutputSection::finalize<ELF32BE>(); | ||
| 433 | template void OutputSection::finalize<ELF64LE>(); | ||
| 434 | template void OutputSection::finalize<ELF64BE>(); |
deps/lld/ELF/OutputSections.h+54-55| ... | @@ -12,9 +12,10 @@ | ... | @@ -12,9 +12,10 @@ |
| 12 | 12 | ||
| 13 | #include "Config.h" | 13 | #include "Config.h" |
| 14 | #include "InputSection.h" | 14 | #include "InputSection.h" |
| 15 | #include "LinkerScript.h" | ||
| 15 | #include "Relocations.h" | 16 | #include "Relocations.h" |
| 16 | 17 | ||
| 17 | #include "lld/Core/LLVM.h" | 18 | #include "lld/Common/LLVM.h" |
| 18 | #include "llvm/MC/StringTableBuilder.h" | 19 | #include "llvm/MC/StringTableBuilder.h" |
| 19 | #include "llvm/Object/ELF.h" | 20 | #include "llvm/Object/ELF.h" |
| 20 | 21 | ||
| ... | @@ -22,23 +23,23 @@ namespace lld { | ... | @@ -22,23 +23,23 @@ namespace lld { |
| 22 | namespace elf { | 23 | namespace elf { |
| 23 | 24 | ||
| 24 | struct PhdrEntry; | 25 | struct PhdrEntry; |
| 25 | class SymbolBody; | 26 | class Symbol; |
| 26 | struct EhSectionPiece; | 27 | struct EhSectionPiece; |
| 27 | class EhInputSection; | 28 | class EhInputSection; |
| 28 | class InputSection; | 29 | class InputSection; |
| 29 | class InputSectionBase; | 30 | class InputSectionBase; |
| 30 | class MergeInputSection; | 31 | class MergeInputSection; |
| 31 | class OutputSection; | 32 | class OutputSection; |
| 32 | template <class ELFT> class ObjectFile; | 33 | template <class ELFT> class ObjFile; |
| 33 | template <class ELFT> class SharedFile; | 34 | template <class ELFT> class SharedFile; |
| 34 | class SharedSymbol; | 35 | class SharedSymbol; |
| 35 | class DefinedRegular; | 36 | class Defined; |
| 36 | 37 | ||
| 37 | // This represents a section in an output file. | 38 | // This represents a section in an output file. |
| 38 | // It is composed of multiple InputSections. | 39 | // It is composed of multiple InputSections. |
| 39 | // The writer creates multiple OutputSections and assign them unique, | 40 | // The writer creates multiple OutputSections and assign them unique, |
| 40 | // non-overlapping file offsets and VAs. | 41 | // non-overlapping file offsets and VAs. |
| 41 | class OutputSection final : public SectionBase { | 42 | class OutputSection final : public BaseCommand, public SectionBase { |
| 42 | public: | 43 | public: |
| 43 | OutputSection(StringRef Name, uint32_t Type, uint64_t Flags); | 44 | OutputSection(StringRef Name, uint32_t Type, uint64_t Flags); |
| 44 | 45 | ||
| ... | @@ -46,6 +47,8 @@ public: | ... | @@ -46,6 +47,8 @@ public: |
| 46 | return S->kind() == SectionBase::Output; | 47 | return S->kind() == SectionBase::Output; |
| 47 | } | 48 | } |
| 48 | 49 | ||
| 50 | static bool classof(const BaseCommand *C); | ||
| 51 | |||
| 49 | uint64_t getLMA() const { return Addr + LMAOffset; } | 52 | uint64_t getLMA() const { return Addr + LMAOffset; } |
| 50 | template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr); | 53 | template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr); |
| 51 | 54 | ||
| ... | @@ -54,42 +57,68 @@ public: | ... | @@ -54,42 +57,68 @@ public: |
| 54 | 57 | ||
| 55 | uint32_t getPhdrFlags() const; | 58 | uint32_t getPhdrFlags() const; |
| 56 | 59 | ||
| 57 | void updateAlignment(uint32_t Val) { | 60 | // Pointer to the PT_LOAD segment, which this section resides in. This field |
| 58 | if (Val > Alignment) | 61 | // is used to correctly compute file offset of a section. When two sections |
| 59 | Alignment = Val; | 62 | // share the same load segment, difference between their file offsets should |
| 60 | } | 63 | // be equal to difference between their virtual addresses. To compute some |
| 61 | 64 | // section offset we use the following formula: Off = Off_first + VA - | |
| 62 | // Pointer to the first section in PT_LOAD segment, which this section | 65 | // VA_first, where Off_first and VA_first is file offset and VA of first |
| 63 | // also resides in. This field is used to correctly compute file offset | 66 | // section in PT_LOAD. |
| 64 | // of a section. When two sections share the same load segment, difference | 67 | PhdrEntry *PtLoad = nullptr; |
| 65 | // between their file offsets should be equal to difference between their | ||
| 66 | // virtual addresses. To compute some section offset we use the following | ||
| 67 | // formula: Off = Off_first + VA - VA_first. | ||
| 68 | OutputSection *FirstInPtLoad = nullptr; | ||
| 69 | 68 | ||
| 70 | // Pointer to a relocation section for this section. Usually nullptr because | 69 | // Pointer to a relocation section for this section. Usually nullptr because |
| 71 | // we consume relocations, but if --emit-relocs is specified (which is rare), | 70 | // we consume relocations, but if --emit-relocs is specified (which is rare), |
| 72 | // it may have a non-null value. | 71 | // it may have a non-null value. |
| 73 | OutputSection *RelocationSection = nullptr; | 72 | OutputSection *RelocationSection = nullptr; |
| 74 | 73 | ||
| 75 | // The following fields correspond to Elf_Shdr members. | 74 | // 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, it | ||
| 76 | // corresponds to the Elf_Shdr member. | ||
| 76 | uint64_t Size = 0; | 77 | uint64_t Size = 0; |
| 78 | |||
| 79 | // The following fields correspond to Elf_Shdr members. | ||
| 77 | uint64_t Offset = 0; | 80 | uint64_t Offset = 0; |
| 78 | uint64_t LMAOffset = 0; | 81 | uint64_t LMAOffset = 0; |
| 79 | uint64_t Addr = 0; | 82 | uint64_t Addr = 0; |
| 80 | uint32_t ShName = 0; | 83 | uint32_t ShName = 0; |
| 81 | 84 | ||
| 82 | void addSection(InputSection *S); | 85 | void addSection(InputSection *IS); |
| 83 | std::vector<InputSection *> Sections; | ||
| 84 | 86 | ||
| 87 | // Location in the output buffer. | ||
| 88 | uint8_t *Loc = nullptr; | ||
| 89 | |||
| 90 | // The following members are normally only used in linker scripts. | ||
| 91 | MemoryRegion *MemRegion = nullptr; | ||
| 92 | Expr AddrExpr; | ||
| 93 | Expr AlignExpr; | ||
| 94 | Expr LMAExpr; | ||
| 95 | Expr SubalignExpr; | ||
| 96 | std::vector<BaseCommand *> SectionCommands; | ||
| 97 | std::vector<StringRef> Phdrs; | ||
| 98 | llvm::Optional<uint32_t> Filler; | ||
| 99 | ConstraintKind Constraint = ConstraintKind::NoConstraint; | ||
| 100 | std::string Location; | ||
| 101 | std::string MemoryRegionName; | ||
| 102 | bool Noload = false; | ||
| 103 | |||
| 104 | template <class ELFT> void finalize(); | ||
| 105 | template <class ELFT> void writeTo(uint8_t *Buf); | ||
| 106 | template <class ELFT> void maybeCompress(); | ||
| 107 | |||
| 108 | void sort(std::function<int(InputSectionBase *S)> Order); | ||
| 109 | void sortInitFini(); | ||
| 110 | void sortCtorsDtors(); | ||
| 111 | |||
| 112 | private: | ||
| 85 | // Used for implementation of --compress-debug-sections option. | 113 | // Used for implementation of --compress-debug-sections option. |
| 86 | std::vector<uint8_t> ZDebugHeader; | 114 | std::vector<uint8_t> ZDebugHeader; |
| 87 | llvm::SmallVector<char, 1> CompressedData; | 115 | llvm::SmallVector<char, 1> CompressedData; |
| 88 | 116 | ||
| 89 | // Location in the output buffer. | 117 | uint32_t getFiller(); |
| 90 | uint8_t *Loc = nullptr; | ||
| 91 | }; | 118 | }; |
| 92 | 119 | ||
| 120 | int getPriority(StringRef S); | ||
| 121 | |||
| 93 | // All output sections that are handled by the linker specially are | 122 | // All output sections that are handled by the linker specially are |
| 94 | // globally accessible. Writer initializes them, so don't use them | 123 | // globally accessible. Writer initializes them, so don't use them |
| 95 | // until Writer is initialized. | 124 | // until Writer is initialized. |
| ... | @@ -106,47 +135,17 @@ struct Out { | ... | @@ -106,47 +135,17 @@ struct Out { |
| 106 | static OutputSection *FiniArray; | 135 | static OutputSection *FiniArray; |
| 107 | }; | 136 | }; |
| 108 | 137 | ||
| 109 | struct SectionKey { | ||
| 110 | StringRef Name; | ||
| 111 | uint64_t Flags; | ||
| 112 | uint32_t Alignment; | ||
| 113 | }; | ||
| 114 | } // namespace elf | 138 | } // namespace elf |
| 115 | } // namespace lld | 139 | } // namespace lld |
| 116 | namespace llvm { | 140 | |
| 117 | template <> struct DenseMapInfo<lld::elf::SectionKey> { | ||
| 118 | static lld::elf::SectionKey getEmptyKey(); | ||
| 119 | static lld::elf::SectionKey getTombstoneKey(); | ||
| 120 | static unsigned getHashValue(const lld::elf::SectionKey &Val); | ||
| 121 | static bool isEqual(const lld::elf::SectionKey &LHS, | ||
| 122 | const lld::elf::SectionKey &RHS); | ||
| 123 | }; | ||
| 124 | } // namespace llvm | ||
| 125 | namespace lld { | 141 | namespace lld { |
| 126 | namespace elf { | 142 | namespace elf { |
| 127 | 143 | ||
| 128 | // This class knows how to create an output section for a given | ||
| 129 | // input section. Output section type is determined by various | ||
| 130 | // factors, including input section's sh_flags, sh_type and | ||
| 131 | // linker scripts. | ||
| 132 | class OutputSectionFactory { | ||
| 133 | public: | ||
| 134 | OutputSectionFactory(); | ||
| 135 | ~OutputSectionFactory(); | ||
| 136 | |||
| 137 | void addInputSec(InputSectionBase *IS, StringRef OutsecName); | ||
| 138 | void addInputSec(InputSectionBase *IS, StringRef OutsecName, | ||
| 139 | OutputSection *&Sec); | ||
| 140 | |||
| 141 | private: | ||
| 142 | llvm::SmallDenseMap<SectionKey, OutputSection *> Map; | ||
| 143 | }; | ||
| 144 | |||
| 145 | uint64_t getHeaderSize(); | 144 | uint64_t getHeaderSize(); |
| 146 | void reportDiscarded(InputSectionBase *IS); | 145 | void sortByOrder(llvm::MutableArrayRef<InputSection *> In, |
| 146 | std::function<int(InputSectionBase *S)> Order); | ||
| 147 | 147 | ||
| 148 | extern std::vector<OutputSection *> OutputSections; | 148 | extern std::vector<OutputSection *> OutputSections; |
| 149 | extern std::vector<OutputSectionCommand *> OutputSectionCommands; | ||
| 150 | } // namespace elf | 149 | } // namespace elf |
| 151 | } // namespace lld | 150 | } // namespace lld |
| 152 | 151 |
deps/lld/ELF/Relocations.cpp+718-437| ... | @@ -44,13 +44,14 @@ | ... | @@ -44,13 +44,14 @@ |
| 44 | #include "Relocations.h" | 44 | #include "Relocations.h" |
| 45 | #include "Config.h" | 45 | #include "Config.h" |
| 46 | #include "LinkerScript.h" | 46 | #include "LinkerScript.h" |
| 47 | #include "Memory.h" | ||
| 48 | #include "OutputSections.h" | 47 | #include "OutputSections.h" |
| 49 | #include "Strings.h" | 48 | #include "Strings.h" |
| 50 | #include "SymbolTable.h" | 49 | #include "SymbolTable.h" |
| 50 | #include "Symbols.h" | ||
| 51 | #include "SyntheticSections.h" | 51 | #include "SyntheticSections.h" |
| 52 | #include "Target.h" | 52 | #include "Target.h" |
| 53 | #include "Thunks.h" | 53 | #include "Thunks.h" |
| 54 | #include "lld/Common/Memory.h" | ||
| 54 | 55 | ||
| 55 | #include "llvm/Support/Endian.h" | 56 | #include "llvm/Support/Endian.h" |
| 56 | #include "llvm/Support/raw_ostream.h" | 57 | #include "llvm/Support/raw_ostream.h" |
| ... | @@ -69,31 +70,35 @@ using namespace lld::elf; | ... | @@ -69,31 +70,35 @@ using namespace lld::elf; |
| 69 | // >>> defined in /home/alice/src/foo.o | 70 | // >>> defined in /home/alice/src/foo.o |
| 70 | // >>> referenced by bar.c:12 (/home/alice/src/bar.c:12) | 71 | // >>> referenced by bar.c:12 (/home/alice/src/bar.c:12) |
| 71 | // >>> /home/alice/src/bar.o:(.text+0x1) | 72 | // >>> /home/alice/src/bar.o:(.text+0x1) |
| 72 | template <class ELFT> | 73 | static std::string getLocation(InputSectionBase &S, const Symbol &Sym, |
| 73 | static std::string getLocation(InputSectionBase &S, const SymbolBody &Sym, | ||
| 74 | uint64_t Off) { | 74 | uint64_t Off) { |
| 75 | std::string Msg = | 75 | std::string Msg = |
| 76 | "\n>>> defined in " + toString(Sym.File) + "\n>>> referenced by "; | 76 | "\n>>> defined in " + toString(Sym.File) + "\n>>> referenced by "; |
| 77 | std::string Src = S.getSrcMsg<ELFT>(Off); | 77 | std::string Src = S.getSrcMsg(Sym, Off); |
| 78 | if (!Src.empty()) | 78 | if (!Src.empty()) |
| 79 | Msg += Src + "\n>>> "; | 79 | Msg += Src + "\n>>> "; |
| 80 | return Msg + S.getObjMsg<ELFT>(Off); | 80 | return Msg + S.getObjMsg(Off); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static bool isPreemptible(const SymbolBody &Body, uint32_t Type) { | 83 | // This is a MIPS-specific rule. |
| 84 | // In case of MIPS GP-relative relocations always resolve to a definition | 84 | // |
| 85 | // in a regular input file, ignoring the one-definition rule. So we, | 85 | // In case of MIPS GP-relative relocations always resolve to a definition |
| 86 | // for example, should not attempt to create a dynamic relocation even | 86 | // in a regular input file, ignoring the one-definition rule. So we, |
| 87 | // if the target symbol is preemptible. There are two two MIPS GP-relative | 87 | // for example, should not attempt to create a dynamic relocation even |
| 88 | // relocations R_MIPS_GPREL16 and R_MIPS_GPREL32. But only R_MIPS_GPREL16 | 88 | // if the target symbol is preemptible. There are two two MIPS GP-relative |
| 89 | // can be against a preemptible symbol. | 89 | // relocations R_MIPS_GPREL16 and R_MIPS_GPREL32. But only R_MIPS_GPREL16 |
| 90 | // To get MIPS relocation type we apply 0xff mask. In case of O32 ABI all | 90 | // can be against a preemptible symbol. |
| 91 | // relocation types occupy eight bit. In case of N64 ABI we extract first | 91 | // |
| 92 | // relocation from 3-in-1 packet because only the first relocation can | 92 | // To get MIPS relocation type we apply 0xff mask. In case of O32 ABI all |
| 93 | // be against a real symbol. | 93 | // relocation types occupy eight bit. In case of N64 ABI we extract first |
| 94 | if (Config->EMachine == EM_MIPS && (Type & 0xff) == R_MIPS_GPREL16) | 94 | // relocation from 3-in-1 packet because only the first relocation can |
| 95 | // be against a real symbol. | ||
| 96 | static bool isMipsGprel(RelType Type) { | ||
| 97 | if (Config->EMachine != EM_MIPS) | ||
| 95 | return false; | 98 | return false; |
| 96 | return Body.isPreemptible(); | 99 | Type &= 0xff; |
| 100 | return Type == R_MIPS_GPREL16 || Type == R_MICROMIPS_GPREL16 || | ||
| 101 | Type == R_MICROMIPS_GPREL7_S2; | ||
| 97 | } | 102 | } |
| 98 | 103 | ||
| 99 | // This function is similar to the `handleTlsRelocation`. MIPS does not | 104 | // This function is similar to the `handleTlsRelocation`. MIPS does not |
| ... | @@ -103,28 +108,28 @@ static bool isPreemptible(const SymbolBody &Body, uint32_t Type) { | ... | @@ -103,28 +108,28 @@ static bool isPreemptible(const SymbolBody &Body, uint32_t Type) { |
| 103 | // Mips has a custom MipsGotSection that handles the writing of GOT entries | 108 | // Mips has a custom MipsGotSection that handles the writing of GOT entries |
| 104 | // without dynamic relocations. | 109 | // without dynamic relocations. |
| 105 | template <class ELFT> | 110 | template <class ELFT> |
| 106 | static unsigned handleMipsTlsRelocation(uint32_t Type, SymbolBody &Body, | 111 | static unsigned handleMipsTlsRelocation(RelType Type, Symbol &Sym, |
| 107 | InputSectionBase &C, uint64_t Offset, | 112 | InputSectionBase &C, uint64_t Offset, |
| 108 | int64_t Addend, RelExpr Expr) { | 113 | int64_t Addend, RelExpr Expr) { |
| 109 | if (Expr == R_MIPS_TLSLD) { | 114 | if (Expr == R_MIPS_TLSLD) { |
| 110 | if (InX::MipsGot->addTlsIndex() && Config->Pic) | 115 | if (InX::MipsGot->addTlsIndex() && Config->Pic) |
| 111 | In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::MipsGot, | 116 | InX::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::MipsGot, |
| 112 | InX::MipsGot->getTlsIndexOff(), false, | 117 | InX::MipsGot->getTlsIndexOff(), false, nullptr, |
| 113 | nullptr, 0}); | 118 | 0}); |
| 114 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); | 119 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 115 | return 1; | 120 | return 1; |
| 116 | } | 121 | } |
| 117 | 122 | ||
| 118 | if (Expr == R_MIPS_TLSGD) { | 123 | if (Expr == R_MIPS_TLSGD) { |
| 119 | if (InX::MipsGot->addDynTlsEntry(Body) && Body.isPreemptible()) { | 124 | if (InX::MipsGot->addDynTlsEntry(Sym) && Sym.IsPreemptible) { |
| 120 | uint64_t Off = InX::MipsGot->getGlobalDynOffset(Body); | 125 | uint64_t Off = InX::MipsGot->getGlobalDynOffset(Sym); |
| 121 | In<ELFT>::RelaDyn->addReloc( | 126 | InX::RelaDyn->addReloc( |
| 122 | {Target->TlsModuleIndexRel, InX::MipsGot, Off, false, &Body, 0}); | 127 | {Target->TlsModuleIndexRel, InX::MipsGot, Off, false, &Sym, 0}); |
| 123 | if (Body.isPreemptible()) | 128 | if (Sym.IsPreemptible) |
| 124 | In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, InX::MipsGot, | 129 | InX::RelaDyn->addReloc({Target->TlsOffsetRel, InX::MipsGot, |
| 125 | Off + Config->Wordsize, false, &Body, 0}); | 130 | Off + Config->Wordsize, false, &Sym, 0}); |
| 126 | } | 131 | } |
| 127 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); | 132 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 128 | return 1; | 133 | return 1; |
| 129 | } | 134 | } |
| 130 | return 0; | 135 | return 0; |
| ... | @@ -145,19 +150,18 @@ static unsigned handleMipsTlsRelocation(uint32_t Type, SymbolBody &Body, | ... | @@ -145,19 +150,18 @@ static unsigned handleMipsTlsRelocation(uint32_t Type, SymbolBody &Body, |
| 145 | // GOT[e0] Module Index (Used to find pointer to TLS block at run-time) | 150 | // GOT[e0] Module Index (Used to find pointer to TLS block at run-time) |
| 146 | // GOT[e1] Offset of symbol in TLS block | 151 | // GOT[e1] Offset of symbol in TLS block |
| 147 | template <class ELFT> | 152 | template <class ELFT> |
| 148 | static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body, | 153 | static unsigned handleARMTlsRelocation(RelType Type, Symbol &Sym, |
| 149 | InputSectionBase &C, uint64_t Offset, | 154 | InputSectionBase &C, uint64_t Offset, |
| 150 | int64_t Addend, RelExpr Expr) { | 155 | int64_t Addend, RelExpr Expr) { |
| 151 | // The Dynamic TLS Module Index Relocation for a symbol defined in an | 156 | // The Dynamic TLS Module Index Relocation for a symbol defined in an |
| 152 | // executable is always 1. If the target Symbol is not preemtible then | 157 | // executable is always 1. If the target Symbol is not preemptible then |
| 153 | // we know the offset into the TLS block at static link time. | 158 | // we know the offset into the TLS block at static link time. |
| 154 | bool NeedDynId = Body.isPreemptible() || Config->Shared; | 159 | bool NeedDynId = Sym.IsPreemptible || Config->Shared; |
| 155 | bool NeedDynOff = Body.isPreemptible(); | 160 | bool NeedDynOff = Sym.IsPreemptible; |
| 156 | 161 | ||
| 157 | auto AddTlsReloc = [&](uint64_t Off, uint32_t Type, SymbolBody *Dest, | 162 | auto AddTlsReloc = [&](uint64_t Off, RelType Type, Symbol *Dest, bool Dyn) { |
| 158 | bool Dyn) { | ||
| 159 | if (Dyn) | 163 | if (Dyn) |
| 160 | In<ELFT>::RelaDyn->addReloc({Type, InX::Got, Off, false, Dest, 0}); | 164 | InX::RelaDyn->addReloc({Type, InX::Got, Off, false, Dest, 0}); |
| 161 | else | 165 | else |
| 162 | InX::Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest}); | 166 | InX::Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest}); |
| 163 | }; | 167 | }; |
| ... | @@ -168,8 +172,8 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body, | ... | @@ -168,8 +172,8 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body, |
| 168 | // module. GOT[e1] is unused. There only needs to be one module index entry. | 172 | // module. GOT[e1] is unused. There only needs to be one module index entry. |
| 169 | if (Expr == R_TLSLD_PC && InX::Got->addTlsIndex()) { | 173 | if (Expr == R_TLSLD_PC && InX::Got->addTlsIndex()) { |
| 170 | AddTlsReloc(InX::Got->getTlsIndexOff(), Target->TlsModuleIndexRel, | 174 | AddTlsReloc(InX::Got->getTlsIndexOff(), Target->TlsModuleIndexRel, |
| 171 | NeedDynId ? nullptr : &Body, NeedDynId); | 175 | NeedDynId ? nullptr : &Sym, NeedDynId); |
| 172 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); | 176 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 173 | return 1; | 177 | return 1; |
| 174 | } | 178 | } |
| 175 | 179 | ||
| ... | @@ -177,13 +181,13 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body, | ... | @@ -177,13 +181,13 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body, |
| 177 | // the module index and offset of symbol in TLS block we can fill these in | 181 | // the module index and offset of symbol in TLS block we can fill these in |
| 178 | // using static GOT relocations. | 182 | // using static GOT relocations. |
| 179 | if (Expr == R_TLSGD_PC) { | 183 | if (Expr == R_TLSGD_PC) { |
| 180 | if (InX::Got->addDynTlsEntry(Body)) { | 184 | if (InX::Got->addDynTlsEntry(Sym)) { |
| 181 | uint64_t Off = InX::Got->getGlobalDynOffset(Body); | 185 | uint64_t Off = InX::Got->getGlobalDynOffset(Sym); |
| 182 | AddTlsReloc(Off, Target->TlsModuleIndexRel, &Body, NeedDynId); | 186 | AddTlsReloc(Off, Target->TlsModuleIndexRel, &Sym, NeedDynId); |
| 183 | AddTlsReloc(Off + Config->Wordsize, Target->TlsOffsetRel, &Body, | 187 | AddTlsReloc(Off + Config->Wordsize, Target->TlsOffsetRel, &Sym, |
| 184 | NeedDynOff); | 188 | NeedDynOff); |
| 185 | } | 189 | } |
| 186 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); | 190 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 187 | return 1; | 191 | return 1; |
| 188 | } | 192 | } |
| 189 | return 0; | 193 | return 0; |
| ... | @@ -192,29 +196,28 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body, | ... | @@ -192,29 +196,28 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body, |
| 192 | // Returns the number of relocations processed. | 196 | // Returns the number of relocations processed. |
| 193 | template <class ELFT> | 197 | template <class ELFT> |
| 194 | static unsigned | 198 | static unsigned |
| 195 | handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, | 199 | handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, |
| 196 | typename ELFT::uint Offset, int64_t Addend, RelExpr Expr) { | 200 | typename ELFT::uint Offset, int64_t Addend, RelExpr Expr) { |
| 197 | if (!(C.Flags & SHF_ALLOC)) | 201 | if (!(C.Flags & SHF_ALLOC)) |
| 198 | return 0; | 202 | return 0; |
| 199 | 203 | ||
| 200 | if (!Body.isTls()) | 204 | if (!Sym.isTls()) |
| 201 | return 0; | 205 | return 0; |
| 202 | 206 | ||
| 203 | if (Config->EMachine == EM_ARM) | 207 | if (Config->EMachine == EM_ARM) |
| 204 | return handleARMTlsRelocation<ELFT>(Type, Body, C, Offset, Addend, Expr); | 208 | return handleARMTlsRelocation<ELFT>(Type, Sym, C, Offset, Addend, Expr); |
| 205 | if (Config->EMachine == EM_MIPS) | 209 | if (Config->EMachine == EM_MIPS) |
| 206 | return handleMipsTlsRelocation<ELFT>(Type, Body, C, Offset, Addend, Expr); | 210 | return handleMipsTlsRelocation<ELFT>(Type, Sym, C, Offset, Addend, Expr); |
| 207 | 211 | ||
| 208 | bool IsPreemptible = isPreemptible(Body, Type); | ||
| 209 | if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL>(Expr) && | 212 | if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL>(Expr) && |
| 210 | Config->Shared) { | 213 | Config->Shared) { |
| 211 | if (InX::Got->addDynTlsEntry(Body)) { | 214 | if (InX::Got->addDynTlsEntry(Sym)) { |
| 212 | uint64_t Off = InX::Got->getGlobalDynOffset(Body); | 215 | uint64_t Off = InX::Got->getGlobalDynOffset(Sym); |
| 213 | In<ELFT>::RelaDyn->addReloc( | 216 | InX::RelaDyn->addReloc( |
| 214 | {Target->TlsDescRel, InX::Got, Off, !IsPreemptible, &Body, 0}); | 217 | {Target->TlsDescRel, InX::Got, Off, !Sym.IsPreemptible, &Sym, 0}); |
| 215 | } | 218 | } |
| 216 | if (Expr != R_TLSDESC_CALL) | 219 | if (Expr != R_TLSDESC_CALL) |
| 217 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); | 220 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 218 | return 1; | 221 | return 1; |
| 219 | } | 222 | } |
| 220 | 223 | ||
| ... | @@ -222,61 +225,59 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, | ... | @@ -222,61 +225,59 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, |
| 222 | // Local-Dynamic relocs can be relaxed to Local-Exec. | 225 | // Local-Dynamic relocs can be relaxed to Local-Exec. |
| 223 | if (!Config->Shared) { | 226 | if (!Config->Shared) { |
| 224 | C.Relocations.push_back( | 227 | C.Relocations.push_back( |
| 225 | {R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Body}); | 228 | {R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym}); |
| 226 | return 2; | 229 | return 2; |
| 227 | } | 230 | } |
| 228 | if (InX::Got->addTlsIndex()) | 231 | if (InX::Got->addTlsIndex()) |
| 229 | In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::Got, | 232 | InX::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::Got, |
| 230 | InX::Got->getTlsIndexOff(), false, nullptr, | 233 | InX::Got->getTlsIndexOff(), false, nullptr, 0}); |
| 231 | 0}); | 234 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 232 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); | ||
| 233 | return 1; | 235 | return 1; |
| 234 | } | 236 | } |
| 235 | 237 | ||
| 236 | // Local-Dynamic relocs can be relaxed to Local-Exec. | 238 | // Local-Dynamic relocs can be relaxed to Local-Exec. |
| 237 | if (isRelExprOneOf<R_ABS, R_TLSLD, R_TLSLD_PC>(Expr) && !Config->Shared) { | 239 | if (isRelExprOneOf<R_ABS, R_TLSLD, R_TLSLD_PC>(Expr) && !Config->Shared) { |
| 238 | C.Relocations.push_back( | 240 | C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym}); |
| 239 | {R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Body}); | ||
| 240 | return 1; | 241 | return 1; |
| 241 | } | 242 | } |
| 242 | 243 | ||
| 243 | if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD, | 244 | if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD, |
| 244 | R_TLSGD_PC>(Expr)) { | 245 | R_TLSGD_PC>(Expr)) { |
| 245 | if (Config->Shared) { | 246 | if (Config->Shared) { |
| 246 | if (InX::Got->addDynTlsEntry(Body)) { | 247 | if (InX::Got->addDynTlsEntry(Sym)) { |
| 247 | uint64_t Off = InX::Got->getGlobalDynOffset(Body); | 248 | uint64_t Off = InX::Got->getGlobalDynOffset(Sym); |
| 248 | In<ELFT>::RelaDyn->addReloc( | 249 | InX::RelaDyn->addReloc( |
| 249 | {Target->TlsModuleIndexRel, InX::Got, Off, false, &Body, 0}); | 250 | {Target->TlsModuleIndexRel, InX::Got, Off, false, &Sym, 0}); |
| 250 | 251 | ||
| 251 | // If the symbol is preemptible we need the dynamic linker to write | 252 | // If the symbol is preemptible we need the dynamic linker to write |
| 252 | // the offset too. | 253 | // the offset too. |
| 253 | uint64_t OffsetOff = Off + Config->Wordsize; | 254 | uint64_t OffsetOff = Off + Config->Wordsize; |
| 254 | if (IsPreemptible) | 255 | if (Sym.IsPreemptible) |
| 255 | In<ELFT>::RelaDyn->addReloc( | 256 | InX::RelaDyn->addReloc( |
| 256 | {Target->TlsOffsetRel, InX::Got, OffsetOff, false, &Body, 0}); | 257 | {Target->TlsOffsetRel, InX::Got, OffsetOff, false, &Sym, 0}); |
| 257 | else | 258 | else |
| 258 | InX::Got->Relocations.push_back( | 259 | InX::Got->Relocations.push_back( |
| 259 | {R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Body}); | 260 | {R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Sym}); |
| 260 | } | 261 | } |
| 261 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); | 262 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 262 | return 1; | 263 | return 1; |
| 263 | } | 264 | } |
| 264 | 265 | ||
| 265 | // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec | 266 | // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec |
| 266 | // depending on the symbol being locally defined or not. | 267 | // depending on the symbol being locally defined or not. |
| 267 | if (IsPreemptible) { | 268 | if (Sym.IsPreemptible) { |
| 268 | C.Relocations.push_back( | 269 | C.Relocations.push_back( |
| 269 | {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_IE), Type, | 270 | {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_IE), Type, |
| 270 | Offset, Addend, &Body}); | 271 | Offset, Addend, &Sym}); |
| 271 | if (!Body.isInGot()) { | 272 | if (!Sym.isInGot()) { |
| 272 | InX::Got->addEntry(Body); | 273 | InX::Got->addEntry(Sym); |
| 273 | In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, InX::Got, | 274 | InX::RelaDyn->addReloc( |
| 274 | Body.getGotOffset(), false, &Body, 0}); | 275 | {Target->TlsGotRel, InX::Got, Sym.getGotOffset(), false, &Sym, 0}); |
| 275 | } | 276 | } |
| 276 | } else { | 277 | } else { |
| 277 | C.Relocations.push_back( | 278 | C.Relocations.push_back( |
| 278 | {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type, | 279 | {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type, |
| 279 | Offset, Addend, &Body}); | 280 | Offset, Addend, &Sym}); |
| 280 | } | 281 | } |
| 281 | return Target->TlsGdRelaxSkip; | 282 | return Target->TlsGdRelaxSkip; |
| 282 | } | 283 | } |
| ... | @@ -284,9 +285,8 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, | ... | @@ -284,9 +285,8 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, |
| 284 | // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally | 285 | // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally |
| 285 | // defined. | 286 | // defined. |
| 286 | if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_GOT_PAGE_PC>(Expr) && | 287 | if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_GOT_PAGE_PC>(Expr) && |
| 287 | !Config->Shared && !IsPreemptible) { | 288 | !Config->Shared && !Sym.IsPreemptible) { |
| 288 | C.Relocations.push_back( | 289 | C.Relocations.push_back({R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Sym}); |
| 289 | {R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Body}); | ||
| 290 | return 1; | 290 | return 1; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| ... | @@ -295,12 +295,22 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, | ... | @@ -295,12 +295,22 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, |
| 295 | return 0; | 295 | return 0; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static uint32_t getMipsPairType(uint32_t Type, const SymbolBody &Sym) { | 298 | static RelType getMipsPairType(RelType Type, bool IsLocal) { |
| 299 | switch (Type) { | 299 | switch (Type) { |
| 300 | case R_MIPS_HI16: | 300 | case R_MIPS_HI16: |
| 301 | return R_MIPS_LO16; | 301 | return R_MIPS_LO16; |
| 302 | case R_MIPS_GOT16: | 302 | case R_MIPS_GOT16: |
| 303 | return Sym.isLocal() ? R_MIPS_LO16 : R_MIPS_NONE; | 303 | // In case of global symbol, the R_MIPS_GOT16 relocation does not |
| 304 | // have a pair. Each global symbol has a unique entry in the GOT | ||
| 305 | // and a corresponding instruction with help of the R_MIPS_GOT16 | ||
| 306 | // relocation loads an address of the symbol. In case of local | ||
| 307 | // symbol, the R_MIPS_GOT16 relocation creates a GOT entry to hold | ||
| 308 | // the high 16 bits of the symbol's value. A paired R_MIPS_LO16 | ||
| 309 | // relocations handle low 16 bits of the address. That allows | ||
| 310 | // to allocate only one GOT entry for every 64 KBytes of local data. | ||
| 311 | return IsLocal ? R_MIPS_LO16 : R_MIPS_NONE; | ||
| 312 | case R_MICROMIPS_GOT16: | ||
| 313 | return IsLocal ? R_MICROMIPS_LO16 : R_MIPS_NONE; | ||
| 304 | case R_MIPS_PCHI16: | 314 | case R_MIPS_PCHI16: |
| 305 | return R_MIPS_PCLO16; | 315 | return R_MIPS_PCLO16; |
| 306 | case R_MICROMIPS_HI16: | 316 | case R_MICROMIPS_HI16: |
| ... | @@ -312,16 +322,16 @@ static uint32_t getMipsPairType(uint32_t Type, const SymbolBody &Sym) { | ... | @@ -312,16 +322,16 @@ static uint32_t getMipsPairType(uint32_t Type, const SymbolBody &Sym) { |
| 312 | 322 | ||
| 313 | // True if non-preemptable symbol always has the same value regardless of where | 323 | // True if non-preemptable symbol always has the same value regardless of where |
| 314 | // the DSO is loaded. | 324 | // the DSO is loaded. |
| 315 | static bool isAbsolute(const SymbolBody &Body) { | 325 | static bool isAbsolute(const Symbol &Sym) { |
| 316 | if (Body.isUndefined()) | 326 | if (Sym.isUndefWeak()) |
| 317 | return !Body.isLocal() && Body.symbol()->isWeak(); | 327 | return true; |
| 318 | if (const auto *DR = dyn_cast<DefinedRegular>(&Body)) | 328 | if (const auto *DR = dyn_cast<Defined>(&Sym)) |
| 319 | return DR->Section == nullptr; // Absolute symbol. | 329 | return DR->Section == nullptr; // Absolute symbol. |
| 320 | return false; | 330 | return false; |
| 321 | } | 331 | } |
| 322 | 332 | ||
| 323 | static bool isAbsoluteValue(const SymbolBody &Body) { | 333 | static bool isAbsoluteValue(const Symbol &Sym) { |
| 324 | return isAbsolute(Body) || Body.isTls(); | 334 | return isAbsolute(Sym) || Sym.isTls(); |
| 325 | } | 335 | } |
| 326 | 336 | ||
| 327 | // Returns true if Expr refers a PLT entry. | 337 | // Returns true if Expr refers a PLT entry. |
| ... | @@ -354,12 +364,10 @@ static bool isRelExpr(RelExpr Expr) { | ... | @@ -354,12 +364,10 @@ static bool isRelExpr(RelExpr Expr) { |
| 354 | // | 364 | // |
| 355 | // If this function returns false, that means we need to emit a | 365 | // If this function returns false, that means we need to emit a |
| 356 | // dynamic relocation so that the relocation will be fixed at load-time. | 366 | // dynamic relocation so that the relocation will be fixed at load-time. |
| 357 | template <class ELFT> | 367 | static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, |
| 358 | static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, | ||
| 359 | const SymbolBody &Body, | ||
| 360 | InputSectionBase &S, uint64_t RelOff) { | 368 | InputSectionBase &S, uint64_t RelOff) { |
| 361 | // These expressions always compute a constant | 369 | // These expressions always compute a constant |
| 362 | if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, | 370 | if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, |
| 363 | R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, | 371 | R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, |
| 364 | R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, | 372 | R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, |
| 365 | R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, R_TLSGD, | 373 | R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, R_TLSGD, |
| ... | @@ -371,14 +379,18 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, | ... | @@ -371,14 +379,18 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, |
| 371 | if (E == R_GOT || E == R_PLT || E == R_TLSDESC) | 379 | if (E == R_GOT || E == R_PLT || E == R_TLSDESC) |
| 372 | return Target->usesOnlyLowPageBits(Type) || !Config->Pic; | 380 | return Target->usesOnlyLowPageBits(Type) || !Config->Pic; |
| 373 | 381 | ||
| 374 | if (isPreemptible(Body, Type)) | 382 | if (Sym.IsPreemptible) |
| 375 | return false; | 383 | return false; |
| 376 | if (!Config->Pic) | 384 | if (!Config->Pic) |
| 377 | return true; | 385 | return true; |
| 378 | 386 | ||
| 387 | // The size of a non preemptible symbol is a constant. | ||
| 388 | if (E == R_SIZE) | ||
| 389 | return true; | ||
| 390 | |||
| 379 | // For the target and the relocation, we want to know if they are | 391 | // For the target and the relocation, we want to know if they are |
| 380 | // absolute or relative. | 392 | // absolute or relative. |
| 381 | bool AbsVal = isAbsoluteValue(Body); | 393 | bool AbsVal = isAbsoluteValue(Sym); |
| 382 | bool RelE = isRelExpr(E); | 394 | bool RelE = isRelExpr(E); |
| 383 | if (AbsVal && !RelE) | 395 | if (AbsVal && !RelE) |
| 384 | return true; | 396 | return true; |
| ... | @@ -396,11 +408,11 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, | ... | @@ -396,11 +408,11 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, |
| 396 | // between start of a function and '_gp' value and defined as absolute just | 408 | // between start of a function and '_gp' value and defined as absolute just |
| 397 | // to simplify the code. | 409 | // to simplify the code. |
| 398 | assert(AbsVal && RelE); | 410 | assert(AbsVal && RelE); |
| 399 | if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) | 411 | if (Sym.isUndefWeak()) |
| 400 | return true; | 412 | return true; |
| 401 | 413 | ||
| 402 | error("relocation " + toString(Type) + " cannot refer to absolute symbol: " + | 414 | error("relocation " + toString(Type) + " cannot refer to absolute symbol: " + |
| 403 | toString(Body) + getLocation<ELFT>(S, Body, RelOff)); | 415 | toString(Sym) + getLocation(S, Sym, RelOff)); |
| 404 | return true; | 416 | return true; |
| 405 | } | 417 | } |
| 406 | 418 | ||
| ... | @@ -431,14 +443,13 @@ static RelExpr fromPlt(RelExpr Expr) { | ... | @@ -431,14 +443,13 @@ static RelExpr fromPlt(RelExpr Expr) { |
| 431 | // Returns true if a given shared symbol is in a read-only segment in a DSO. | 443 | // Returns true if a given shared symbol is in a read-only segment in a DSO. |
| 432 | template <class ELFT> static bool isReadOnly(SharedSymbol *SS) { | 444 | template <class ELFT> static bool isReadOnly(SharedSymbol *SS) { |
| 433 | typedef typename ELFT::Phdr Elf_Phdr; | 445 | typedef typename ELFT::Phdr Elf_Phdr; |
| 434 | uint64_t Value = SS->getValue<ELFT>(); | ||
| 435 | 446 | ||
| 436 | // Determine if the symbol is read-only by scanning the DSO's program headers. | 447 | // Determine if the symbol is read-only by scanning the DSO's program headers. |
| 437 | auto *File = cast<SharedFile<ELFT>>(SS->File); | 448 | const SharedFile<ELFT> &File = SS->getFile<ELFT>(); |
| 438 | for (const Elf_Phdr &Phdr : check(File->getObj().program_headers())) | 449 | for (const Elf_Phdr &Phdr : check(File.getObj().program_headers())) |
| 439 | if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) && | 450 | if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) && |
| 440 | !(Phdr.p_flags & ELF::PF_W) && Value >= Phdr.p_vaddr && | 451 | !(Phdr.p_flags & ELF::PF_W) && SS->Value >= Phdr.p_vaddr && |
| 441 | Value < Phdr.p_vaddr + Phdr.p_memsz) | 452 | SS->Value < Phdr.p_vaddr + Phdr.p_memsz) |
| 442 | return true; | 453 | return true; |
| 443 | return false; | 454 | return false; |
| 444 | } | 455 | } |
| ... | @@ -452,16 +463,15 @@ template <class ELFT> | ... | @@ -452,16 +463,15 @@ template <class ELFT> |
| 452 | static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) { | 463 | static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) { |
| 453 | typedef typename ELFT::Sym Elf_Sym; | 464 | typedef typename ELFT::Sym Elf_Sym; |
| 454 | 465 | ||
| 455 | auto *File = cast<SharedFile<ELFT>>(SS->File); | 466 | SharedFile<ELFT> &File = SS->getFile<ELFT>(); |
| 456 | uint64_t Shndx = SS->getShndx<ELFT>(); | ||
| 457 | uint64_t Value = SS->getValue<ELFT>(); | ||
| 458 | 467 | ||
| 459 | std::vector<SharedSymbol *> Ret; | 468 | std::vector<SharedSymbol *> Ret; |
| 460 | for (const Elf_Sym &S : File->getGlobalSymbols()) { | 469 | for (const Elf_Sym &S : File.getGlobalELFSyms()) { |
| 461 | if (S.st_shndx != Shndx || S.st_value != Value) | 470 | if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS || |
| 471 | S.st_value != SS->Value) | ||
| 462 | continue; | 472 | continue; |
| 463 | StringRef Name = check(S.getName(File->getStringTable())); | 473 | StringRef Name = check(S.getName(File.getStringTable())); |
| 464 | SymbolBody *Sym = Symtab<ELFT>::X->find(Name); | 474 | Symbol *Sym = Symtab->find(Name); |
| 465 | if (auto *Alias = dyn_cast_or_null<SharedSymbol>(Sym)) | 475 | if (auto *Alias = dyn_cast_or_null<SharedSymbol>(Sym)) |
| 466 | Ret.push_back(Alias); | 476 | Ret.push_back(Alias); |
| 467 | } | 477 | } |
| ... | @@ -512,132 +522,153 @@ static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) { | ... | @@ -512,132 +522,153 @@ static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) { |
| 512 | // define an accessor getV(). | 522 | // define an accessor getV(). |
| 513 | template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) { | 523 | template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) { |
| 514 | // Copy relocation against zero-sized symbol doesn't make sense. | 524 | // Copy relocation against zero-sized symbol doesn't make sense. |
| 515 | uint64_t SymSize = SS->template getSize<ELFT>(); | 525 | uint64_t SymSize = SS->getSize(); |
| 516 | if (SymSize == 0) | 526 | if (SymSize == 0) |
| 517 | fatal("cannot create a copy relocation for symbol " + toString(*SS)); | 527 | fatal("cannot create a copy relocation for symbol " + toString(*SS)); |
| 518 | 528 | ||
| 519 | // See if this symbol is in a read-only segment. If so, preserve the symbol's | 529 | // See if this symbol is in a read-only segment. If so, preserve the symbol's |
| 520 | // memory protection by reserving space in the .bss.rel.ro section. | 530 | // memory protection by reserving space in the .bss.rel.ro section. |
| 521 | bool IsReadOnly = isReadOnly<ELFT>(SS); | 531 | bool IsReadOnly = isReadOnly<ELFT>(SS); |
| 522 | BssSection *Sec = IsReadOnly ? InX::BssRelRo : InX::Bss; | 532 | BssSection *Sec = make<BssSection>(IsReadOnly ? ".bss.rel.ro" : ".bss", |
| 523 | uint64_t Off = Sec->reserveSpace(SymSize, SS->getAlignment<ELFT>()); | 533 | SymSize, SS->Alignment); |
| 534 | if (IsReadOnly) | ||
| 535 | InX::BssRelRo->getParent()->addSection(Sec); | ||
| 536 | else | ||
| 537 | InX::Bss->getParent()->addSection(Sec); | ||
| 524 | 538 | ||
| 525 | // Look through the DSO's dynamic symbol table for aliases and create a | 539 | // Look through the DSO's dynamic symbol table for aliases and create a |
| 526 | // dynamic symbol for each one. This causes the copy relocation to correctly | 540 | // dynamic symbol for each one. This causes the copy relocation to correctly |
| 527 | // interpose any aliases. | 541 | // interpose any aliases. |
| 528 | for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) { | 542 | for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) { |
| 529 | Sym->NeedsCopy = true; | ||
| 530 | Sym->CopyRelSec = Sec; | 543 | Sym->CopyRelSec = Sec; |
| 531 | Sym->CopyRelSecOff = Off; | 544 | Sym->IsPreemptible = false; |
| 532 | Sym->symbol()->IsUsedInRegularObj = true; | 545 | Sym->IsUsedInRegularObj = true; |
| 546 | Sym->Used = true; | ||
| 533 | } | 547 | } |
| 534 | 548 | ||
| 535 | In<ELFT>::RelaDyn->addReloc({Target->CopyRel, Sec, Off, false, SS, 0}); | 549 | InX::RelaDyn->addReloc({Target->CopyRel, Sec, 0, false, SS, 0}); |
| 550 | } | ||
| 551 | |||
| 552 | static void errorOrWarn(const Twine &Msg) { | ||
| 553 | if (!Config->NoinhibitExec) | ||
| 554 | error(Msg); | ||
| 555 | else | ||
| 556 | warn(Msg); | ||
| 557 | } | ||
| 558 | |||
| 559 | // Returns PLT relocation expression. | ||
| 560 | // | ||
| 561 | // This handles a non PIC program call to function in a shared library. In | ||
| 562 | // an ideal world, we could just report an error saying the relocation can | ||
| 563 | // overflow at runtime. In the real world with glibc, crt1.o has a | ||
| 564 | // R_X86_64_PC32 pointing to libc.so. | ||
| 565 | // | ||
| 566 | // The general idea on how to handle such cases is to create a PLT entry and | ||
| 567 | // use that as the function value. | ||
| 568 | // | ||
| 569 | // For the static linking part, we just return a plt expr and everything | ||
| 570 | // else will use the the PLT entry as the address. | ||
| 571 | // | ||
| 572 | // The remaining problem is making sure pointer equality still works. We | ||
| 573 | // need the help of the dynamic linker for that. We let it know that we have | ||
| 574 | // a direct reference to a so symbol by creating an undefined symbol with a | ||
| 575 | // non zero st_value. Seeing that, the dynamic linker resolves the symbol to | ||
| 576 | // the value of the symbol we created. This is true even for got entries, so | ||
| 577 | // pointer equality is maintained. To avoid an infinite loop, the only entry | ||
| 578 | // that points to the real function is a dedicated got entry used by the | ||
| 579 | // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT, | ||
| 580 | // R_386_JMP_SLOT, etc). | ||
| 581 | static RelExpr getPltExpr(Symbol &Sym, RelExpr Expr, bool &IsConstant) { | ||
| 582 | Sym.NeedsPltAddr = true; | ||
| 583 | Sym.IsPreemptible = false; | ||
| 584 | IsConstant = true; | ||
| 585 | return toPlt(Expr); | ||
| 536 | } | 586 | } |
| 537 | 587 | ||
| 588 | // This modifies the expression if we can use a copy relocation or point the | ||
| 589 | // symbol to the PLT. | ||
| 538 | template <class ELFT> | 590 | template <class ELFT> |
| 539 | static RelExpr adjustExpr(SymbolBody &Body, RelExpr Expr, uint32_t Type, | 591 | static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type, |
| 540 | const uint8_t *Data, InputSectionBase &S, | 592 | InputSectionBase &S, uint64_t RelOff, |
| 541 | typename ELFT::uint RelOff) { | 593 | bool &IsConstant) { |
| 542 | if (Body.isGnuIFunc()) { | 594 | // If a relocation can be applied at link-time, we don't need to |
| 543 | Expr = toPlt(Expr); | 595 | // create a dynamic relocation in the first place. |
| 544 | } else if (!isPreemptible(Body, Type)) { | 596 | if (IsConstant) |
| 545 | if (needsPlt(Expr)) | 597 | return Expr; |
| 546 | Expr = fromPlt(Expr); | ||
| 547 | if (Expr == R_GOT_PC && !isAbsoluteValue(Body)) | ||
| 548 | Expr = Target->adjustRelaxExpr(Type, Data, Expr); | ||
| 549 | } | ||
| 550 | 598 | ||
| 551 | bool IsWrite = !Config->ZText || (S.Flags & SHF_WRITE); | 599 | // We can create any dynamic relocation supported by the dynamic linker if a |
| 552 | if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body, S, RelOff)) | 600 | // section is writable or we are passed -z notext. |
| 601 | bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText; | ||
| 602 | if (CanWrite && Target->isPicRel(Type)) | ||
| 553 | return Expr; | 603 | return Expr; |
| 554 | 604 | ||
| 555 | // This relocation would require the dynamic linker to write a value to read | 605 | // If the relocation is to a weak undef, and we are producing |
| 556 | // only memory. We can hack around it if we are producing an executable and | 606 | // executable, give up on it and produce a non preemptible 0. |
| 607 | if (!Config->Shared && Sym.isUndefWeak()) { | ||
| 608 | Sym.IsPreemptible = false; | ||
| 609 | IsConstant = true; | ||
| 610 | return Expr; | ||
| 611 | } | ||
| 612 | |||
| 613 | // If we got here we know that this relocation would require the dynamic | ||
| 614 | // linker to write a value to read only memory or use an unsupported | ||
| 615 | // relocation. | ||
| 616 | |||
| 617 | // We can hack around it if we are producing an executable and | ||
| 557 | // the refered symbol can be preemepted to refer to the executable. | 618 | // the refered symbol can be preemepted to refer to the executable. |
| 558 | if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) { | 619 | if (!CanWrite && (Config->Shared || (Config->Pic && !isRelExpr(Expr)))) { |
| 559 | error("can't create dynamic relocation " + toString(Type) + " against " + | 620 | error( |
| 560 | (Body.getName().empty() ? "local symbol" | 621 | "can't create dynamic relocation " + toString(Type) + " against " + |
| 561 | : "symbol: " + toString(Body)) + | 622 | (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) + |
| 562 | " in readonly segment" + getLocation<ELFT>(S, Body, RelOff)); | 623 | " in readonly segment; recompile object files with -fPIC" + |
| 624 | getLocation(S, Sym, RelOff)); | ||
| 563 | return Expr; | 625 | return Expr; |
| 564 | } | 626 | } |
| 565 | 627 | ||
| 566 | if (Body.getVisibility() != STV_DEFAULT) { | 628 | // Copy relocations are only possible if we are creating an executable and the |
| 567 | error("cannot preempt symbol: " + toString(Body) + | 629 | // symbol is shared. |
| 568 | getLocation<ELFT>(S, Body, RelOff)); | 630 | if (!Sym.isShared() || Config->Shared) |
| 631 | return Expr; | ||
| 632 | |||
| 633 | if (Sym.getVisibility() != STV_DEFAULT) { | ||
| 634 | error("cannot preempt symbol: " + toString(Sym) + | ||
| 635 | getLocation(S, Sym, RelOff)); | ||
| 569 | return Expr; | 636 | return Expr; |
| 570 | } | 637 | } |
| 571 | 638 | ||
| 572 | if (Body.isObject()) { | 639 | if (Sym.isObject()) { |
| 573 | // Produce a copy relocation. | 640 | // Produce a copy relocation. |
| 574 | auto *B = cast<SharedSymbol>(&Body); | 641 | auto *B = dyn_cast<SharedSymbol>(&Sym); |
| 575 | if (!B->NeedsCopy) { | 642 | if (B && !B->CopyRelSec) { |
| 576 | if (Config->ZNocopyreloc) | 643 | if (Config->ZNocopyreloc) |
| 577 | error("unresolvable relocation " + toString(Type) + | 644 | error("unresolvable relocation " + toString(Type) + |
| 578 | " against symbol '" + toString(*B) + | 645 | " against symbol '" + toString(*B) + |
| 579 | "'; recompile with -fPIC or remove '-z nocopyreloc'" + | 646 | "'; recompile with -fPIC or remove '-z nocopyreloc'" + |
| 580 | getLocation<ELFT>(S, Body, RelOff)); | 647 | getLocation(S, Sym, RelOff)); |
| 581 | 648 | ||
| 582 | addCopyRelSymbol<ELFT>(B); | 649 | addCopyRelSymbol<ELFT>(B); |
| 583 | } | 650 | } |
| 651 | IsConstant = true; | ||
| 584 | return Expr; | 652 | return Expr; |
| 585 | } | 653 | } |
| 586 | 654 | ||
| 587 | if (Body.isFunc()) { | 655 | if (Sym.isFunc()) |
| 588 | // This handles a non PIC program call to function in a shared library. In | 656 | return getPltExpr(Sym, Expr, IsConstant); |
| 589 | // an ideal world, we could just report an error saying the relocation can | ||
| 590 | // overflow at runtime. In the real world with glibc, crt1.o has a | ||
| 591 | // R_X86_64_PC32 pointing to libc.so. | ||
| 592 | // | ||
| 593 | // The general idea on how to handle such cases is to create a PLT entry and | ||
| 594 | // use that as the function value. | ||
| 595 | // | ||
| 596 | // For the static linking part, we just return a plt expr and everything | ||
| 597 | // else will use the the PLT entry as the address. | ||
| 598 | // | ||
| 599 | // The remaining problem is making sure pointer equality still works. We | ||
| 600 | // need the help of the dynamic linker for that. We let it know that we have | ||
| 601 | // a direct reference to a so symbol by creating an undefined symbol with a | ||
| 602 | // non zero st_value. Seeing that, the dynamic linker resolves the symbol to | ||
| 603 | // the value of the symbol we created. This is true even for got entries, so | ||
| 604 | // pointer equality is maintained. To avoid an infinite loop, the only entry | ||
| 605 | // that points to the real function is a dedicated got entry used by the | ||
| 606 | // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT, | ||
| 607 | // R_386_JMP_SLOT, etc). | ||
| 608 | Body.NeedsPltAddr = true; | ||
| 609 | return toPlt(Expr); | ||
| 610 | } | ||
| 611 | 657 | ||
| 612 | error("symbol '" + toString(Body) + "' defined in " + toString(Body.File) + | 658 | errorOrWarn("symbol '" + toString(Sym) + "' defined in " + |
| 613 | " has no type"); | 659 | toString(Sym.File) + " has no type"); |
| 614 | return Expr; | 660 | return Expr; |
| 615 | } | 661 | } |
| 616 | 662 | ||
| 617 | // Returns an addend of a given relocation. If it is RELA, an addend | ||
| 618 | // is in a relocation itself. If it is REL, we need to read it from an | ||
| 619 | // input section. | ||
| 620 | template <class ELFT, class RelTy> | ||
| 621 | static int64_t computeAddend(const RelTy &Rel, const uint8_t *Buf) { | ||
| 622 | uint32_t Type = Rel.getType(Config->IsMips64EL); | ||
| 623 | int64_t A = RelTy::IsRela | ||
| 624 | ? getAddend<ELFT>(Rel) | ||
| 625 | : Target->getImplicitAddend(Buf + Rel.r_offset, Type); | ||
| 626 | |||
| 627 | if (Config->EMachine == EM_PPC64 && Config->Pic && Type == R_PPC64_TOC) | ||
| 628 | A += getPPC64TocBase(); | ||
| 629 | return A; | ||
| 630 | } | ||
| 631 | |||
| 632 | // MIPS has an odd notion of "paired" relocations to calculate addends. | 663 | // MIPS has an odd notion of "paired" relocations to calculate addends. |
| 633 | // For example, if a relocation is of R_MIPS_HI16, there must be a | 664 | // For example, if a relocation is of R_MIPS_HI16, there must be a |
| 634 | // R_MIPS_LO16 relocation after that, and an addend is calculated using | 665 | // R_MIPS_LO16 relocation after that, and an addend is calculated using |
| 635 | // the two relocations. | 666 | // the two relocations. |
| 636 | template <class ELFT, class RelTy> | 667 | template <class ELFT, class RelTy> |
| 637 | static int64_t computeMipsAddend(const RelTy &Rel, InputSectionBase &Sec, | 668 | static int64_t computeMipsAddend(const RelTy &Rel, const RelTy *End, |
| 638 | RelExpr Expr, SymbolBody &Body, | 669 | InputSectionBase &Sec, RelExpr Expr, |
| 639 | const RelTy *End) { | 670 | bool IsLocal) { |
| 640 | if (Expr == R_MIPS_GOTREL && Body.isLocal()) | 671 | if (Expr == R_MIPS_GOTREL && IsLocal) |
| 641 | return Sec.getFile<ELFT>()->MipsGp0; | 672 | return Sec.getFile<ELFT>()->MipsGp0; |
| 642 | 673 | ||
| 643 | // The ABI says that the paired relocation is used only for REL. | 674 | // The ABI says that the paired relocation is used only for REL. |
| ... | @@ -645,8 +676,8 @@ static int64_t computeMipsAddend(const RelTy &Rel, InputSectionBase &Sec, | ... | @@ -645,8 +676,8 @@ static int64_t computeMipsAddend(const RelTy &Rel, InputSectionBase &Sec, |
| 645 | if (RelTy::IsRela) | 676 | if (RelTy::IsRela) |
| 646 | return 0; | 677 | return 0; |
| 647 | 678 | ||
| 648 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 679 | RelType Type = Rel.getType(Config->IsMips64EL); |
| 649 | uint32_t PairTy = getMipsPairType(Type, Body); | 680 | uint32_t PairTy = getMipsPairType(Type, IsLocal); |
| 650 | if (PairTy == R_MIPS_NONE) | 681 | if (PairTy == R_MIPS_NONE) |
| 651 | return 0; | 682 | return 0; |
| 652 | 683 | ||
| ... | @@ -655,64 +686,87 @@ static int64_t computeMipsAddend(const RelTy &Rel, InputSectionBase &Sec, | ... | @@ -655,64 +686,87 @@ static int64_t computeMipsAddend(const RelTy &Rel, InputSectionBase &Sec, |
| 655 | 686 | ||
| 656 | // To make things worse, paired relocations might not be contiguous in | 687 | // To make things worse, paired relocations might not be contiguous in |
| 657 | // the relocation table, so we need to do linear search. *sigh* | 688 | // the relocation table, so we need to do linear search. *sigh* |
| 658 | for (const RelTy *RI = &Rel; RI != End; ++RI) { | 689 | for (const RelTy *RI = &Rel; RI != End; ++RI) |
| 659 | if (RI->getType(Config->IsMips64EL) != PairTy) | 690 | if (RI->getType(Config->IsMips64EL) == PairTy && |
| 660 | continue; | 691 | RI->getSymbol(Config->IsMips64EL) == SymIndex) |
| 661 | if (RI->getSymbol(Config->IsMips64EL) != SymIndex) | 692 | return Target->getImplicitAddend(Buf + RI->r_offset, PairTy); |
| 662 | continue; | ||
| 663 | |||
| 664 | endianness E = Config->Endianness; | ||
| 665 | int32_t Hi = (read32(Buf + Rel.r_offset, E) & 0xffff) << 16; | ||
| 666 | int32_t Lo = SignExtend32<16>(read32(Buf + RI->r_offset, E)); | ||
| 667 | return Hi + Lo; | ||
| 668 | } | ||
| 669 | 693 | ||
| 670 | warn("can't find matching " + toString(PairTy) + " relocation for " + | 694 | warn("can't find matching " + toString(PairTy) + " relocation for " + |
| 671 | toString(Type)); | 695 | toString(Type)); |
| 672 | return 0; | 696 | return 0; |
| 673 | } | 697 | } |
| 674 | 698 | ||
| 675 | template <class ELFT> | 699 | // Returns an addend of a given relocation. If it is RELA, an addend |
| 676 | static void reportUndefined(SymbolBody &Sym, InputSectionBase &S, | 700 | // is in a relocation itself. If it is REL, we need to read it from an |
| 677 | uint64_t Offset) { | 701 | // input section. |
| 702 | template <class ELFT, class RelTy> | ||
| 703 | static int64_t computeAddend(const RelTy &Rel, const RelTy *End, | ||
| 704 | InputSectionBase &Sec, RelExpr Expr, | ||
| 705 | bool IsLocal) { | ||
| 706 | int64_t Addend; | ||
| 707 | RelType Type = Rel.getType(Config->IsMips64EL); | ||
| 708 | |||
| 709 | if (RelTy::IsRela) { | ||
| 710 | Addend = getAddend<ELFT>(Rel); | ||
| 711 | } else { | ||
| 712 | const uint8_t *Buf = Sec.Data.data(); | ||
| 713 | Addend = Target->getImplicitAddend(Buf + Rel.r_offset, Type); | ||
| 714 | } | ||
| 715 | |||
| 716 | if (Config->EMachine == EM_PPC64 && Config->Pic && Type == R_PPC64_TOC) | ||
| 717 | Addend += getPPC64TocBase(); | ||
| 718 | if (Config->EMachine == EM_MIPS) | ||
| 719 | Addend += computeMipsAddend<ELFT>(Rel, End, Sec, Expr, IsLocal); | ||
| 720 | |||
| 721 | return Addend; | ||
| 722 | } | ||
| 723 | |||
| 724 | // Report an undefined symbol if necessary. | ||
| 725 | // Returns true if this function printed out an error message. | ||
| 726 | static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec, | ||
| 727 | uint64_t Offset) { | ||
| 678 | if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll) | 728 | if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll) |
| 679 | return; | 729 | return false; |
| 680 | 730 | ||
| 681 | bool CanBeExternal = Sym.symbol()->computeBinding() != STB_LOCAL && | 731 | if (Sym.isLocal() || !Sym.isUndefined() || Sym.isWeak()) |
| 682 | Sym.getVisibility() == STV_DEFAULT; | 732 | return false; |
| 733 | |||
| 734 | bool CanBeExternal = | ||
| 735 | Sym.computeBinding() != STB_LOCAL && Sym.getVisibility() == STV_DEFAULT; | ||
| 683 | if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) | 736 | if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) |
| 684 | return; | 737 | return false; |
| 685 | 738 | ||
| 686 | std::string Msg = | 739 | std::string Msg = |
| 687 | "undefined symbol: " + toString(Sym) + "\n>>> referenced by "; | 740 | "undefined symbol: " + toString(Sym) + "\n>>> referenced by "; |
| 688 | 741 | ||
| 689 | std::string Src = S.getSrcMsg<ELFT>(Offset); | 742 | std::string Src = Sec.getSrcMsg(Sym, Offset); |
| 690 | if (!Src.empty()) | 743 | if (!Src.empty()) |
| 691 | Msg += Src + "\n>>> "; | 744 | Msg += Src + "\n>>> "; |
| 692 | Msg += S.getObjMsg<ELFT>(Offset); | 745 | Msg += Sec.getObjMsg(Offset); |
| 693 | 746 | ||
| 694 | if (Config->UnresolvedSymbols == UnresolvedPolicy::WarnAll || | 747 | if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) || |
| 695 | (Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal)) { | 748 | Config->NoinhibitExec) { |
| 696 | warn(Msg); | 749 | warn(Msg); |
| 697 | } else { | 750 | return false; |
| 698 | error(Msg); | ||
| 699 | } | 751 | } |
| 752 | |||
| 753 | error(Msg); | ||
| 754 | return true; | ||
| 700 | } | 755 | } |
| 701 | 756 | ||
| 702 | template <class RelTy> | 757 | // MIPS N32 ABI treats series of successive relocations with the same offset |
| 703 | static std::pair<uint32_t, uint32_t> | 758 | // as a single relocation. The similar approach used by N64 ABI, but this ABI |
| 704 | mergeMipsN32RelTypes(uint32_t Type, uint32_t Offset, RelTy *I, RelTy *E) { | 759 | // packs all relocations into the single relocation record. Here we emulate |
| 705 | // MIPS N32 ABI treats series of successive relocations with the same offset | 760 | // this for the N32 ABI. Iterate over relocation with the same offset and put |
| 706 | // as a single relocation. The similar approach used by N64 ABI, but this ABI | 761 | // theirs types into the single bit-set. |
| 707 | // packs all relocations into the single relocation record. Here we emulate | 762 | template <class RelTy> static RelType getMipsN32RelType(RelTy *&Rel, RelTy *End) { |
| 708 | // this for the N32 ABI. Iterate over relocation with the same offset and put | 763 | RelType Type = Rel->getType(Config->IsMips64EL); |
| 709 | // theirs types into the single bit-set. | 764 | uint64_t Offset = Rel->r_offset; |
| 710 | uint32_t Processed = 0; | 765 | |
| 711 | for (; I != E && Offset == I->r_offset; ++I) { | 766 | int N = 0; |
| 712 | ++Processed; | 767 | while (Rel + 1 != End && (Rel + 1)->r_offset == Offset) |
| 713 | Type |= I->getType(Config->IsMips64EL) << (8 * Processed); | 768 | Type |= (++Rel)->getType(Config->IsMips64EL) << (8 * ++N); |
| 714 | } | 769 | return Type; |
| 715 | return std::make_pair(Type, Processed); | ||
| 716 | } | 770 | } |
| 717 | 771 | ||
| 718 | // .eh_frame sections are mergeable input sections, so their input | 772 | // .eh_frame sections are mergeable input sections, so their input |
| ... | @@ -730,73 +784,84 @@ namespace { | ... | @@ -730,73 +784,84 @@ namespace { |
| 730 | class OffsetGetter { | 784 | class OffsetGetter { |
| 731 | public: | 785 | public: |
| 732 | explicit OffsetGetter(InputSectionBase &Sec) { | 786 | explicit OffsetGetter(InputSectionBase &Sec) { |
| 733 | if (auto *Eh = dyn_cast<EhInputSection>(&Sec)) { | 787 | if (auto *Eh = dyn_cast<EhInputSection>(&Sec)) |
| 734 | P = Eh->Pieces; | 788 | Pieces = Eh->Pieces; |
| 735 | Size = Eh->Pieces.size(); | ||
| 736 | } | ||
| 737 | } | 789 | } |
| 738 | 790 | ||
| 739 | // Translates offsets in input sections to offsets in output sections. | 791 | // Translates offsets in input sections to offsets in output sections. |
| 740 | // Given offset must increase monotonically. We assume that P is | 792 | // Given offset must increase monotonically. We assume that Piece is |
| 741 | // sorted by InputOff. | 793 | // sorted by InputOff. |
| 742 | uint64_t get(uint64_t Off) { | 794 | uint64_t get(uint64_t Off) { |
| 743 | if (P.empty()) | 795 | if (Pieces.empty()) |
| 744 | return Off; | 796 | return Off; |
| 745 | 797 | ||
| 746 | while (I != Size && P[I].InputOff + P[I].size() <= Off) | 798 | while (I != Pieces.size() && Pieces[I].InputOff + Pieces[I].Size <= Off) |
| 747 | ++I; | 799 | ++I; |
| 748 | if (I == Size) | 800 | if (I == Pieces.size()) |
| 749 | return Off; | 801 | return Off; |
| 750 | 802 | ||
| 751 | // P must be contiguous, so there must be no holes in between. | 803 | // Pieces must be contiguous, so there must be no holes in between. |
| 752 | assert(P[I].InputOff <= Off && "Relocation not in any piece"); | 804 | assert(Pieces[I].InputOff <= Off && "Relocation not in any piece"); |
| 753 | 805 | ||
| 754 | // Offset -1 means that the piece is dead (i.e. garbage collected). | 806 | // Offset -1 means that the piece is dead (i.e. garbage collected). |
| 755 | if (P[I].OutputOff == -1) | 807 | if (Pieces[I].OutputOff == -1) |
| 756 | return -1; | 808 | return -1; |
| 757 | return P[I].OutputOff + Off - P[I].InputOff; | 809 | return Pieces[I].OutputOff + Off - Pieces[I].InputOff; |
| 758 | } | 810 | } |
| 759 | 811 | ||
| 760 | private: | 812 | private: |
| 761 | ArrayRef<EhSectionPiece> P; | 813 | ArrayRef<EhSectionPiece> Pieces; |
| 762 | size_t I = 0; | 814 | size_t I = 0; |
| 763 | size_t Size; | ||
| 764 | }; | 815 | }; |
| 765 | } // namespace | 816 | } // namespace |
| 766 | 817 | ||
| 767 | template <class ELFT, class GotPltSection> | 818 | template <class ELFT, class GotPltSection> |
| 768 | static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt, | 819 | static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt, |
| 769 | RelocationSection<ELFT> *Rel, uint32_t Type, | 820 | RelocationBaseSection *Rel, RelType Type, Symbol &Sym, |
| 770 | SymbolBody &Sym, bool UseSymVA) { | 821 | bool UseSymVA) { |
| 771 | Plt->addEntry<ELFT>(Sym); | 822 | Plt->addEntry<ELFT>(Sym); |
| 772 | GotPlt->addEntry(Sym); | 823 | GotPlt->addEntry(Sym); |
| 773 | Rel->addReloc({Type, GotPlt, Sym.getGotPltOffset(), UseSymVA, &Sym, 0}); | 824 | Rel->addReloc({Type, GotPlt, Sym.getGotPltOffset(), UseSymVA, &Sym, 0}); |
| 774 | } | 825 | } |
| 775 | 826 | ||
| 776 | template <class ELFT> | 827 | template <class ELFT> static void addGotEntry(Symbol &Sym, bool Preemptible) { |
| 777 | static void addGotEntry(SymbolBody &Sym, bool Preemptible) { | ||
| 778 | InX::Got->addEntry(Sym); | 828 | InX::Got->addEntry(Sym); |
| 779 | 829 | ||
| 830 | RelExpr Expr = Sym.isTls() ? R_TLS : R_ABS; | ||
| 780 | uint64_t Off = Sym.getGotOffset(); | 831 | uint64_t Off = Sym.getGotOffset(); |
| 781 | uint32_t DynType; | ||
| 782 | RelExpr Expr = R_ABS; | ||
| 783 | |||
| 784 | if (Sym.isTls()) { | ||
| 785 | DynType = Target->TlsGotRel; | ||
| 786 | Expr = R_TLS; | ||
| 787 | } else if (!Preemptible && Config->Pic && !isAbsolute(Sym)) { | ||
| 788 | DynType = Target->RelativeRel; | ||
| 789 | } else { | ||
| 790 | DynType = Target->GotRel; | ||
| 791 | } | ||
| 792 | 832 | ||
| 793 | bool Constant = !Preemptible && !(Config->Pic && !isAbsolute(Sym)); | 833 | // If a GOT slot value can be calculated at link-time, which is now, |
| 794 | if (!Constant) | 834 | // we can just fill that out. |
| 795 | In<ELFT>::RelaDyn->addReloc( | 835 | // |
| 796 | {DynType, InX::Got, Off, !Preemptible, &Sym, 0}); | 836 | // (We don't actually write a value to a GOT slot right now, but we |
| 837 | // add a static relocation to a Relocations vector so that | ||
| 838 | // InputSection::relocate will do the work for us. We may be able | ||
| 839 | // to just write a value now, but it is a TODO.) | ||
| 840 | bool IsLinkTimeConstant = !Preemptible && (!Config->Pic || isAbsolute(Sym)); | ||
| 841 | if (IsLinkTimeConstant) { | ||
| 842 | InX::Got->Relocations.push_back({Expr, Target->GotRel, Off, 0, &Sym}); | ||
| 843 | return; | ||
| 844 | } | ||
| 797 | 845 | ||
| 798 | if (Constant || (!Config->IsRela && !Preemptible)) | 846 | // Otherwise, we emit a dynamic relocation to .rel[a].dyn so that |
| 799 | InX::Got->Relocations.push_back({Expr, DynType, Off, 0, &Sym}); | 847 | // the GOT slot will be fixed at load-time. |
| 848 | RelType Type; | ||
| 849 | if (Sym.isTls()) | ||
| 850 | Type = Target->TlsGotRel; | ||
| 851 | else if (!Preemptible && Config->Pic && !isAbsolute(Sym)) | ||
| 852 | Type = Target->RelativeRel; | ||
| 853 | else | ||
| 854 | Type = Target->GotRel; | ||
| 855 | InX::RelaDyn->addReloc({Type, InX::Got, Off, !Preemptible, &Sym, 0}); | ||
| 856 | |||
| 857 | // REL type relocations don't have addend fields unlike RELAs, and | ||
| 858 | // their addends are stored to the section to which they are applied. | ||
| 859 | // So, store addends if we need to. | ||
| 860 | // | ||
| 861 | // This is ugly -- the difference between REL and RELA should be | ||
| 862 | // handled in a better way. It's a TODO. | ||
| 863 | if (!Config->IsRela && !Preemptible) | ||
| 864 | InX::Got->Relocations.push_back({R_ABS, Target->GotRel, Off, 0, &Sym}); | ||
| 800 | } | 865 | } |
| 801 | 866 | ||
| 802 | // The reason we have to do this early scan is as follows | 867 | // The reason we have to do this early scan is as follows |
| ... | @@ -816,41 +881,67 @@ template <class ELFT, class RelTy> | ... | @@ -816,41 +881,67 @@ template <class ELFT, class RelTy> |
| 816 | static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { | 881 | static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { |
| 817 | OffsetGetter GetOffset(Sec); | 882 | OffsetGetter GetOffset(Sec); |
| 818 | 883 | ||
| 884 | // Not all relocations end up in Sec.Relocations, but a lot do. | ||
| 885 | Sec.Relocations.reserve(Rels.size()); | ||
| 886 | |||
| 819 | for (auto I = Rels.begin(), End = Rels.end(); I != End; ++I) { | 887 | for (auto I = Rels.begin(), End = Rels.end(); I != End; ++I) { |
| 820 | const RelTy &Rel = *I; | 888 | const RelTy &Rel = *I; |
| 821 | SymbolBody &Body = Sec.getFile<ELFT>()->getRelocTargetSym(Rel); | 889 | Symbol &Sym = Sec.getFile<ELFT>()->getRelocTargetSym(Rel); |
| 822 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 890 | RelType Type = Rel.getType(Config->IsMips64EL); |
| 823 | |||
| 824 | if (Config->MipsN32Abi) { | ||
| 825 | uint32_t Processed; | ||
| 826 | std::tie(Type, Processed) = | ||
| 827 | mergeMipsN32RelTypes(Type, Rel.r_offset, I + 1, End); | ||
| 828 | I += Processed; | ||
| 829 | } | ||
| 830 | 891 | ||
| 831 | // Compute the offset of this section in the output section. | 892 | // Deal with MIPS oddity. |
| 893 | if (Config->MipsN32Abi) | ||
| 894 | Type = getMipsN32RelType(I, End); | ||
| 895 | |||
| 896 | // Get an offset in an output section this relocation is applied to. | ||
| 832 | uint64_t Offset = GetOffset.get(Rel.r_offset); | 897 | uint64_t Offset = GetOffset.get(Rel.r_offset); |
| 833 | if (Offset == uint64_t(-1)) | 898 | if (Offset == uint64_t(-1)) |
| 834 | continue; | 899 | continue; |
| 835 | 900 | ||
| 836 | // Report undefined symbols. The fact that we report undefined | 901 | // Skip if the target symbol is an erroneous undefined symbol. |
| 837 | // symbols here means that we report undefined symbols only when | 902 | if (maybeReportUndefined(Sym, Sec, Rel.r_offset)) |
| 838 | // they have relocations pointing to them. We don't care about | 903 | continue; |
| 839 | // undefined symbols that are in dead-stripped sections. | ||
| 840 | if (!Body.isLocal() && Body.isUndefined() && !Body.symbol()->isWeak()) | ||
| 841 | reportUndefined<ELFT>(Body, Sec, Rel.r_offset); | ||
| 842 | 904 | ||
| 843 | RelExpr Expr = | 905 | RelExpr Expr = |
| 844 | Target->getRelExpr(Type, Body, Sec.Data.begin() + Rel.r_offset); | 906 | Target->getRelExpr(Type, Sym, Sec.Data.begin() + Rel.r_offset); |
| 845 | 907 | ||
| 846 | // Ignore "hint" relocations because they are only markers for relaxation. | 908 | // Ignore "hint" relocations because they are only markers for relaxation. |
| 847 | if (isRelExprOneOf<R_HINT, R_NONE>(Expr)) | 909 | if (isRelExprOneOf<R_HINT, R_NONE>(Expr)) |
| 848 | continue; | 910 | continue; |
| 849 | 911 | ||
| 850 | bool Preemptible = isPreemptible(Body, Type); | 912 | // Handle yet another MIPS-ness. |
| 851 | Expr = adjustExpr<ELFT>(Body, Expr, Type, Sec.Data.data() + Rel.r_offset, | 913 | if (isMipsGprel(Type)) { |
| 852 | Sec, Rel.r_offset); | 914 | int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal()); |
| 853 | if (ErrorCount) | 915 | Sec.Relocations.push_back({R_MIPS_GOTREL, Type, Offset, Addend, &Sym}); |
| 916 | continue; | ||
| 917 | } | ||
| 918 | |||
| 919 | bool Preemptible = Sym.IsPreemptible; | ||
| 920 | |||
| 921 | // Strenghten or relax a PLT access. | ||
| 922 | // | ||
| 923 | // GNU ifunc symbols must be accessed via PLT because their addresses | ||
| 924 | // are determined by runtime. | ||
| 925 | // | ||
| 926 | // On the other hand, if we know that a PLT entry will be resolved within | ||
| 927 | // the same ELF module, we can skip PLT access and directly jump to the | ||
| 928 | // destination function. For example, if we are linking a main exectuable, | ||
| 929 | // all dynamic symbols that can be resolved within the executable will | ||
| 930 | // actually be resolved that way at runtime, because the main exectuable | ||
| 931 | // is always at the beginning of a search list. We can leverage that fact. | ||
| 932 | if (Sym.isGnuIFunc()) | ||
| 933 | Expr = toPlt(Expr); | ||
| 934 | else if (!Preemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym)) | ||
| 935 | Expr = | ||
| 936 | Target->adjustRelaxExpr(Type, Sec.Data.data() + Rel.r_offset, Expr); | ||
| 937 | else if (!Preemptible) | ||
| 938 | Expr = fromPlt(Expr); | ||
| 939 | |||
| 940 | bool IsConstant = | ||
| 941 | isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Rel.r_offset); | ||
| 942 | |||
| 943 | Expr = adjustExpr<ELFT>(Sym, Expr, Type, Sec, Rel.r_offset, IsConstant); | ||
| 944 | if (errorCount()) | ||
| 854 | continue; | 945 | continue; |
| 855 | 946 | ||
| 856 | // This relocation does not require got entry, but it is relative to got and | 947 | // This relocation does not require got entry, but it is relative to got and |
| ... | @@ -860,26 +951,24 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { | ... | @@ -860,26 +951,24 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { |
| 860 | InX::Got->HasGotOffRel = true; | 951 | InX::Got->HasGotOffRel = true; |
| 861 | 952 | ||
| 862 | // Read an addend. | 953 | // Read an addend. |
| 863 | int64_t Addend = computeAddend<ELFT>(Rel, Sec.Data.data()); | 954 | int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal()); |
| 864 | if (Config->EMachine == EM_MIPS) | ||
| 865 | Addend += computeMipsAddend<ELFT>(Rel, Sec, Expr, Body, End); | ||
| 866 | 955 | ||
| 867 | // Process some TLS relocations, including relaxing TLS relocations. | 956 | // Process some TLS relocations, including relaxing TLS relocations. |
| 868 | // Note that this function does not handle all TLS relocations. | 957 | // Note that this function does not handle all TLS relocations. |
| 869 | if (unsigned Processed = | 958 | if (unsigned Processed = |
| 870 | handleTlsRelocation<ELFT>(Type, Body, Sec, Offset, Addend, Expr)) { | 959 | handleTlsRelocation<ELFT>(Type, Sym, Sec, Offset, Addend, Expr)) { |
| 871 | I += (Processed - 1); | 960 | I += (Processed - 1); |
| 872 | continue; | 961 | continue; |
| 873 | } | 962 | } |
| 874 | 963 | ||
| 875 | // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol. | 964 | // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol. |
| 876 | if (needsPlt(Expr) && !Body.isInPlt()) { | 965 | if (needsPlt(Expr) && !Sym.isInPlt()) { |
| 877 | if (Body.isGnuIFunc() && !Preemptible) | 966 | if (Sym.isGnuIFunc() && !Preemptible) |
| 878 | addPltEntry(InX::Iplt, InX::IgotPlt, In<ELFT>::RelaIplt, | 967 | addPltEntry<ELFT>(InX::Iplt, InX::IgotPlt, InX::RelaIplt, |
| 879 | Target->IRelativeRel, Body, true); | 968 | Target->IRelativeRel, Sym, true); |
| 880 | else | 969 | else |
| 881 | addPltEntry(InX::Plt, InX::GotPlt, In<ELFT>::RelaPlt, Target->PltRel, | 970 | addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel, |
| 882 | Body, !Preemptible); | 971 | Sym, !Preemptible); |
| 883 | } | 972 | } |
| 884 | 973 | ||
| 885 | // Create a GOT slot if a relocation needs GOT. | 974 | // Create a GOT slot if a relocation needs GOT. |
| ... | @@ -892,25 +981,26 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { | ... | @@ -892,25 +981,26 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { |
| 892 | // See "Global Offset Table" in Chapter 5 in the following document | 981 | // See "Global Offset Table" in Chapter 5 in the following document |
| 893 | // for detailed description: | 982 | // for detailed description: |
| 894 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 983 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
| 895 | InX::MipsGot->addEntry(Body, Addend, Expr); | 984 | InX::MipsGot->addEntry(Sym, Addend, Expr); |
| 896 | if (Body.isTls() && Body.isPreemptible()) | 985 | if (Sym.isTls() && Sym.IsPreemptible) |
| 897 | In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, InX::MipsGot, | 986 | InX::RelaDyn->addReloc({Target->TlsGotRel, InX::MipsGot, |
| 898 | Body.getGotOffset(), false, &Body, 0}); | 987 | Sym.getGotOffset(), false, &Sym, 0}); |
| 899 | } else if (!Body.isInGot()) { | 988 | } else if (!Sym.isInGot()) { |
| 900 | addGotEntry<ELFT>(Body, Preemptible); | 989 | addGotEntry<ELFT>(Sym, Preemptible); |
| 901 | } | 990 | } |
| 902 | } | 991 | } |
| 903 | 992 | ||
| 904 | if (!needsPlt(Expr) && !needsGot(Expr) && isPreemptible(Body, Type)) { | 993 | if (!needsPlt(Expr) && !needsGot(Expr) && Sym.IsPreemptible) { |
| 905 | // We don't know anything about the finaly symbol. Just ask the dynamic | 994 | // We don't know anything about the finaly symbol. Just ask the dynamic |
| 906 | // linker to handle the relocation for us. | 995 | // linker to handle the relocation for us. |
| 907 | if (!Target->isPicRel(Type)) | 996 | if (!Target->isPicRel(Type)) |
| 908 | error("relocation " + toString(Type) + | 997 | errorOrWarn( |
| 909 | " cannot be used against shared object; recompile with -fPIC" + | 998 | "relocation " + toString(Type) + |
| 910 | getLocation<ELFT>(Sec, Body, Offset)); | 999 | " cannot be used against shared object; recompile with -fPIC" + |
| 1000 | getLocation(Sec, Sym, Offset)); | ||
| 911 | 1001 | ||
| 912 | In<ELFT>::RelaDyn->addReloc( | 1002 | InX::RelaDyn->addReloc( |
| 913 | {Target->getDynRel(Type), &Sec, Offset, false, &Body, Addend}); | 1003 | {Target->getDynRel(Type), &Sec, Offset, false, &Sym, Addend}); |
| 914 | 1004 | ||
| 915 | // MIPS ABI turns using of GOT and dynamic relocations inside out. | 1005 | // MIPS ABI turns using of GOT and dynamic relocations inside out. |
| 916 | // While regular ABI uses dynamic relocations to fill up GOT entries | 1006 | // While regular ABI uses dynamic relocations to fill up GOT entries |
| ... | @@ -928,32 +1018,36 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { | ... | @@ -928,32 +1018,36 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { |
| 928 | // a dynamic relocation. | 1018 | // a dynamic relocation. |
| 929 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19 | 1019 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19 |
| 930 | if (Config->EMachine == EM_MIPS) | 1020 | if (Config->EMachine == EM_MIPS) |
| 931 | InX::MipsGot->addEntry(Body, Addend, Expr); | 1021 | InX::MipsGot->addEntry(Sym, Addend, Expr); |
| 932 | continue; | 1022 | continue; |
| 933 | } | 1023 | } |
| 934 | 1024 | ||
| 935 | // If the relocation points to something in the file, we can process it. | ||
| 936 | bool IsConstant = | ||
| 937 | isStaticLinkTimeConstant<ELFT>(Expr, Type, Body, Sec, Rel.r_offset); | ||
| 938 | |||
| 939 | // The size is not going to change, so we fold it in here. | 1025 | // The size is not going to change, so we fold it in here. |
| 940 | if (Expr == R_SIZE) | 1026 | if (Expr == R_SIZE) |
| 941 | Addend += Body.getSize<ELFT>(); | 1027 | Addend += Sym.getSize(); |
| 1028 | |||
| 1029 | // If the produced value is a constant, we just remember to write it | ||
| 1030 | // when outputting this section. We also have to do it if the format | ||
| 1031 | // uses Elf_Rel, since in that case the written value is the addend. | ||
| 1032 | if (IsConstant) { | ||
| 1033 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); | ||
| 1034 | continue; | ||
| 1035 | } | ||
| 942 | 1036 | ||
| 943 | // If the output being produced is position independent, the final value | 1037 | // If the output being produced is position independent, the final value |
| 944 | // is still not known. In that case we still need some help from the | 1038 | // is still not known. In that case we still need some help from the |
| 945 | // dynamic linker. We can however do better than just copying the incoming | 1039 | // dynamic linker. We can however do better than just copying the incoming |
| 946 | // relocation. We can process some of it and and just ask the dynamic | 1040 | // relocation. We can process some of it and and just ask the dynamic |
| 947 | // linker to add the load address. | 1041 | // linker to add the load address. |
| 948 | if (!IsConstant) | 1042 | if (Config->IsRela) { |
| 949 | In<ELFT>::RelaDyn->addReloc( | 1043 | InX::RelaDyn->addReloc( |
| 950 | {Target->RelativeRel, &Sec, Offset, true, &Body, Addend}); | 1044 | {Target->RelativeRel, &Sec, Offset, true, &Sym, Addend}); |
| 951 | 1045 | } else { | |
| 952 | // If the produced value is a constant, we just remember to write it | 1046 | // In REL, addends are stored to the target section. |
| 953 | // when outputting this section. We also have to do it if the format | 1047 | InX::RelaDyn->addReloc( |
| 954 | // uses Elf_Rel, since in that case the written value is the addend. | 1048 | {Target->RelativeRel, &Sec, Offset, true, &Sym, 0}); |
| 955 | if (IsConstant || !RelTy::IsRela) | 1049 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 956 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); | 1050 | } |
| 957 | } | 1051 | } |
| 958 | } | 1052 | } |
| 959 | 1053 | ||
| ... | @@ -964,178 +1058,365 @@ template <class ELFT> void elf::scanRelocations(InputSectionBase &S) { | ... | @@ -964,178 +1058,365 @@ template <class ELFT> void elf::scanRelocations(InputSectionBase &S) { |
| 964 | scanRelocs<ELFT>(S, S.rels<ELFT>()); | 1058 | scanRelocs<ELFT>(S, S.rels<ELFT>()); |
| 965 | } | 1059 | } |
| 966 | 1060 | ||
| 1061 | // Thunk Implementation | ||
| 1062 | // | ||
| 1063 | // Thunks (sometimes called stubs, veneers or branch islands) are small pieces | ||
| 1064 | // of code that the linker inserts inbetween a caller and a callee. The thunks | ||
| 1065 | // are added at link time rather than compile time as the decision on whether | ||
| 1066 | // a thunk is needed, such as the caller and callee being out of range, can only | ||
| 1067 | // be made at link time. | ||
| 1068 | // | ||
| 1069 | // It is straightforward to tell given the current state of the program when a | ||
| 1070 | // thunk is needed for a particular call. The more difficult part is that | ||
| 1071 | // the thunk needs to be placed in the program such that the caller can reach | ||
| 1072 | // the thunk and the thunk can reach the callee; furthermore, adding thunks to | ||
| 1073 | // the program alters addresses, which can mean more thunks etc. | ||
| 1074 | // | ||
| 1075 | // In lld we have a synthetic ThunkSection that can hold many Thunks. | ||
| 1076 | // The decision to have a ThunkSection act as a container means that we can | ||
| 1077 | // more easily handle the most common case of a single block of contiguous | ||
| 1078 | // Thunks by inserting just a single ThunkSection. | ||
| 1079 | // | ||
| 1080 | // The implementation of Thunks in lld is split across these areas | ||
| 1081 | // Relocations.cpp : Framework for creating and placing thunks | ||
| 1082 | // Thunks.cpp : The code generated for each supported thunk | ||
| 1083 | // Target.cpp : Target specific hooks that the framework uses to decide when | ||
| 1084 | // a thunk is used | ||
| 1085 | // Synthetic.cpp : Implementation of ThunkSection | ||
| 1086 | // Writer.cpp : Iteratively call framework until no more Thunks added | ||
| 1087 | // | ||
| 1088 | // Thunk placement requirements: | ||
| 1089 | // Mips LA25 thunks. These must be placed immediately before the callee section | ||
| 1090 | // We can assume that the caller is in range of the Thunk. These are modelled | ||
| 1091 | // by Thunks that return the section they must precede with | ||
| 1092 | // getTargetInputSection(). | ||
| 1093 | // | ||
| 1094 | // ARM interworking and range extension thunks. These thunks must be placed | ||
| 1095 | // within range of the caller. All implemented ARM thunks can always reach the | ||
| 1096 | // callee as they use an indirect jump via a register that has no range | ||
| 1097 | // restrictions. | ||
| 1098 | // | ||
| 1099 | // Thunk placement algorithm: | ||
| 1100 | // For Mips LA25 ThunkSections; the placement is explicit, it has to be before | ||
| 1101 | // getTargetInputSection(). | ||
| 1102 | // | ||
| 1103 | // For thunks that must be placed within range of the caller there are many | ||
| 1104 | // possible choices given that the maximum range from the caller is usually | ||
| 1105 | // much larger than the average InputSection size. Desirable properties include: | ||
| 1106 | // - Maximize reuse of thunks by multiple callers | ||
| 1107 | // - Minimize number of ThunkSections to simplify insertion | ||
| 1108 | // - Handle impact of already added Thunks on addresses | ||
| 1109 | // - Simple to understand and implement | ||
| 1110 | // | ||
| 1111 | // In lld for the first pass, we pre-create one or more ThunkSections per | ||
| 1112 | // InputSectionDescription at Target specific intervals. A ThunkSection is | ||
| 1113 | // placed so that the estimated end of the ThunkSection is within range of the | ||
| 1114 | // start of the InputSectionDescription or the previous ThunkSection. For | ||
| 1115 | // example: | ||
| 1116 | // InputSectionDescription | ||
| 1117 | // Section 0 | ||
| 1118 | // ... | ||
| 1119 | // Section N | ||
| 1120 | // ThunkSection 0 | ||
| 1121 | // Section N + 1 | ||
| 1122 | // ... | ||
| 1123 | // Section N + K | ||
| 1124 | // Thunk Section 1 | ||
| 1125 | // | ||
| 1126 | // The intention is that we can add a Thunk to a ThunkSection that is well | ||
| 1127 | // spaced enough to service a number of callers without having to do a lot | ||
| 1128 | // of work. An important principle is that it is not an error if a Thunk cannot | ||
| 1129 | // be placed in a pre-created ThunkSection; when this happens we create a new | ||
| 1130 | // ThunkSection placed next to the caller. This allows us to handle the vast | ||
| 1131 | // majority of thunks simply, but also handle rare cases where the branch range | ||
| 1132 | // is smaller than the target specific spacing. | ||
| 1133 | // | ||
| 1134 | // The algorithm is expected to create all the thunks that are needed in a | ||
| 1135 | // single pass, with a small number of programs needing a second pass due to | ||
| 1136 | // the insertion of thunks in the first pass increasing the offset between | ||
| 1137 | // callers and callees that were only just in range. | ||
| 1138 | // | ||
| 1139 | // A consequence of allowing new ThunkSections to be created outside of the | ||
| 1140 | // pre-created ThunkSections is that in rare cases calls to Thunks that were in | ||
| 1141 | // range in pass K, are out of range in some pass > K due to the insertion of | ||
| 1142 | // more Thunks in between the caller and callee. When this happens we retarget | ||
| 1143 | // the relocation back to the original target and create another Thunk. | ||
| 1144 | |||
| 1145 | // Remove ThunkSections that are empty, this should only be the initial set | ||
| 1146 | // precreated on pass 0. | ||
| 1147 | |||
| 967 | // Insert the Thunks for OutputSection OS into their designated place | 1148 | // Insert the Thunks for OutputSection OS into their designated place |
| 968 | // in the Sections vector, and recalculate the InputSection output section | 1149 | // in the Sections vector, and recalculate the InputSection output section |
| 969 | // offsets. | 1150 | // offsets. |
| 970 | // This may invalidate any output section offsets stored outside of InputSection | 1151 | // This may invalidate any output section offsets stored outside of InputSection |
| 971 | void ThunkCreator::mergeThunks() { | 1152 | void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> OutputSections) { |
| 972 | for (auto &KV : ThunkSections) { | 1153 | forEachInputSectionDescription( |
| 973 | std::vector<InputSection *> *ISR = KV.first; | 1154 | OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { |
| 974 | std::vector<ThunkSection *> &Thunks = KV.second; | 1155 | if (ISD->ThunkSections.empty()) |
| 975 | 1156 | return; | |
| 976 | // Order Thunks in ascending OutSecOff | 1157 | |
| 977 | auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) { | 1158 | // Remove any zero sized precreated Thunks. |
| 978 | return A->OutSecOff < B->OutSecOff; | 1159 | llvm::erase_if(ISD->ThunkSections, |
| 979 | }; | 1160 | [](const std::pair<ThunkSection *, uint32_t> &TS) { |
| 980 | std::stable_sort(Thunks.begin(), Thunks.end(), ThunkCmp); | 1161 | return TS.first->getSize() == 0; |
| 981 | 1162 | }); | |
| 982 | // Merge sorted vectors of Thunks and InputSections by OutSecOff | 1163 | // ISD->ThunkSections contains all created ThunkSections, including |
| 983 | std::vector<InputSection *> Tmp; | 1164 | // those inserted in previous passes. Extract the Thunks created this |
| 984 | Tmp.reserve(ISR->size() + Thunks.size()); | 1165 | // pass and order them in ascending OutSecOff. |
| 985 | auto MergeCmp = [](const InputSection *A, const InputSection *B) { | 1166 | std::vector<ThunkSection *> NewThunks; |
| 986 | // std::merge requires a strict weak ordering. | 1167 | for (const std::pair<ThunkSection *, uint32_t> TS : ISD->ThunkSections) |
| 987 | if (A->OutSecOff < B->OutSecOff) | 1168 | if (TS.second == Pass) |
| 988 | return true; | 1169 | NewThunks.push_back(TS.first); |
| 989 | if (A->OutSecOff == B->OutSecOff) | 1170 | std::stable_sort(NewThunks.begin(), NewThunks.end(), |
| 990 | // Check if Thunk is immediately before any specific Target InputSection | 1171 | [](const ThunkSection *A, const ThunkSection *B) { |
| 991 | // for example Mips LA25 Thunks. | 1172 | return A->OutSecOff < B->OutSecOff; |
| 992 | if (auto *TA = dyn_cast<ThunkSection>(A)) | 1173 | }); |
| 993 | if (TA && TA->getTargetInputSection() == B) | 1174 | |
| 1175 | // Merge sorted vectors of Thunks and InputSections by OutSecOff | ||
| 1176 | std::vector<InputSection *> Tmp; | ||
| 1177 | Tmp.reserve(ISD->Sections.size() + NewThunks.size()); | ||
| 1178 | auto MergeCmp = [](const InputSection *A, const InputSection *B) { | ||
| 1179 | // std::merge requires a strict weak ordering. | ||
| 1180 | if (A->OutSecOff < B->OutSecOff) | ||
| 994 | return true; | 1181 | return true; |
| 995 | return false; | 1182 | if (A->OutSecOff == B->OutSecOff) { |
| 996 | }; | 1183 | auto *TA = dyn_cast<ThunkSection>(A); |
| 997 | std::merge(ISR->begin(), ISR->end(), Thunks.begin(), Thunks.end(), | 1184 | auto *TB = dyn_cast<ThunkSection>(B); |
| 998 | std::back_inserter(Tmp), MergeCmp); | 1185 | // Check if Thunk is immediately before any specific Target |
| 999 | *ISR = std::move(Tmp); | 1186 | // InputSection for example Mips LA25 Thunks. |
| 1000 | } | 1187 | if (TA && TA->getTargetInputSection() == B) |
| 1188 | return true; | ||
| 1189 | if (TA && !TB && !TA->getTargetInputSection()) | ||
| 1190 | // Place Thunk Sections without specific targets before | ||
| 1191 | // non-Thunk Sections. | ||
| 1192 | return true; | ||
| 1193 | } | ||
| 1194 | return false; | ||
| 1195 | }; | ||
| 1196 | std::merge(ISD->Sections.begin(), ISD->Sections.end(), | ||
| 1197 | NewThunks.begin(), NewThunks.end(), std::back_inserter(Tmp), | ||
| 1198 | MergeCmp); | ||
| 1199 | ISD->Sections = std::move(Tmp); | ||
| 1200 | }); | ||
| 1001 | } | 1201 | } |
| 1002 | 1202 | ||
| 1003 | static uint32_t findEndOfFirstNonExec(OutputSectionCommand &Cmd) { | 1203 | // Find or create a ThunkSection within the InputSectionDescription (ISD) that |
| 1004 | for (BaseCommand *Base : Cmd.Commands) | 1204 | // is in range of Src. An ISD maps to a range of InputSections described by a |
| 1005 | if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) | 1205 | // linker script section pattern such as { .text .text.* }. |
| 1006 | for (auto *IS : ISD->Sections) | 1206 | ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *OS, InputSection *IS, |
| 1007 | if ((IS->Flags & SHF_EXECINSTR) == 0) | 1207 | InputSectionDescription *ISD, |
| 1008 | return IS->OutSecOff + IS->getSize(); | 1208 | uint32_t Type, uint64_t Src) { |
| 1009 | return 0; | 1209 | for (std::pair<ThunkSection *, uint32_t> TP : ISD->ThunkSections) { |
| 1010 | } | 1210 | ThunkSection *TS = TP.first; |
| 1211 | uint64_t TSBase = OS->Addr + TS->OutSecOff; | ||
| 1212 | uint64_t TSLimit = TSBase + TS->getSize(); | ||
| 1213 | if (Target->inBranchRange(Type, Src, (Src > TSLimit) ? TSBase : TSLimit)) | ||
| 1214 | return TS; | ||
| 1215 | } | ||
| 1011 | 1216 | ||
| 1012 | ThunkSection *ThunkCreator::getOSThunkSec(OutputSectionCommand *Cmd, | 1217 | // No suitable ThunkSection exists. This can happen when there is a branch |
| 1013 | std::vector<InputSection *> *ISR) { | 1218 | // with lower range than the ThunkSection spacing or when there are too |
| 1014 | if (CurTS == nullptr) { | 1219 | // many Thunks. Create a new ThunkSection as close to the InputSection as |
| 1015 | uint32_t Off = findEndOfFirstNonExec(*Cmd); | 1220 | // possible. Error if InputSection is so large we cannot place ThunkSection |
| 1016 | CurTS = addThunkSection(Cmd->Sec, ISR, Off); | 1221 | // anywhere in Range. |
| 1222 | uint64_t ThunkSecOff = IS->OutSecOff; | ||
| 1223 | if (!Target->inBranchRange(Type, Src, OS->Addr + ThunkSecOff)) { | ||
| 1224 | ThunkSecOff = IS->OutSecOff + IS->getSize(); | ||
| 1225 | if (!Target->inBranchRange(Type, Src, OS->Addr + ThunkSecOff)) | ||
| 1226 | fatal("InputSection too large for range extension thunk " + | ||
| 1227 | IS->getObjMsg(Src - (OS->Addr + IS->OutSecOff))); | ||
| 1017 | } | 1228 | } |
| 1018 | return CurTS; | 1229 | return addThunkSection(OS, ISD, ThunkSecOff); |
| 1019 | } | 1230 | } |
| 1020 | 1231 | ||
| 1021 | ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, OutputSection *OS) { | 1232 | // Add a Thunk that needs to be placed in a ThunkSection that immediately |
| 1233 | // precedes its Target. | ||
| 1234 | ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) { | ||
| 1022 | ThunkSection *TS = ThunkedSections.lookup(IS); | 1235 | ThunkSection *TS = ThunkedSections.lookup(IS); |
| 1023 | if (TS) | 1236 | if (TS) |
| 1024 | return TS; | 1237 | return TS; |
| 1025 | auto *TOS = IS->getParent(); | ||
| 1026 | 1238 | ||
| 1027 | // Find InputSectionRange within TOS that IS is in | 1239 | // Find InputSectionRange within Target Output Section (TOS) that the |
| 1028 | OutputSectionCommand *C = Script->getCmd(TOS); | 1240 | // InputSection (IS) that we need to precede is in. |
| 1029 | std::vector<InputSection *> *Range = nullptr; | 1241 | OutputSection *TOS = IS->getParent(); |
| 1030 | for (BaseCommand *BC : C->Commands) | 1242 | for (BaseCommand *BC : TOS->SectionCommands) |
| 1031 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) { | 1243 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) { |
| 1244 | if (ISD->Sections.empty()) | ||
| 1245 | continue; | ||
| 1032 | InputSection *first = ISD->Sections.front(); | 1246 | InputSection *first = ISD->Sections.front(); |
| 1033 | InputSection *last = ISD->Sections.back(); | 1247 | InputSection *last = ISD->Sections.back(); |
| 1034 | if (IS->OutSecOff >= first->OutSecOff && | 1248 | if (IS->OutSecOff >= first->OutSecOff && |
| 1035 | IS->OutSecOff <= last->OutSecOff) { | 1249 | IS->OutSecOff <= last->OutSecOff) { |
| 1036 | Range = &ISD->Sections; | 1250 | TS = addThunkSection(TOS, ISD, IS->OutSecOff); |
| 1251 | ThunkedSections[IS] = TS; | ||
| 1037 | break; | 1252 | break; |
| 1038 | } | 1253 | } |
| 1039 | } | 1254 | } |
| 1040 | TS = addThunkSection(TOS, Range, IS->OutSecOff); | ||
| 1041 | ThunkedSections[IS] = TS; | ||
| 1042 | return TS; | 1255 | return TS; |
| 1043 | } | 1256 | } |
| 1044 | 1257 | ||
| 1258 | // Create one or more ThunkSections per OS that can be used to place Thunks. | ||
| 1259 | // We attempt to place the ThunkSections using the following desirable | ||
| 1260 | // properties: | ||
| 1261 | // - Within range of the maximum number of callers | ||
| 1262 | // - Minimise the number of ThunkSections | ||
| 1263 | // | ||
| 1264 | // We follow a simple but conservative heuristic to place ThunkSections at | ||
| 1265 | // offsets that are multiples of a Target specific branch range. | ||
| 1266 | // For an InputSectionRange that is smaller than the range, a single | ||
| 1267 | // ThunkSection at the end of the range will do. | ||
| 1268 | void ThunkCreator::createInitialThunkSections( | ||
| 1269 | ArrayRef<OutputSection *> OutputSections) { | ||
| 1270 | forEachInputSectionDescription( | ||
| 1271 | OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { | ||
| 1272 | if (ISD->Sections.empty()) | ||
| 1273 | return; | ||
| 1274 | uint32_t ISLimit; | ||
| 1275 | uint32_t PrevISLimit = ISD->Sections.front()->OutSecOff; | ||
| 1276 | uint32_t ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing; | ||
| 1277 | |||
| 1278 | for (const InputSection *IS : ISD->Sections) { | ||
| 1279 | ISLimit = IS->OutSecOff + IS->getSize(); | ||
| 1280 | if (ISLimit > ThunkUpperBound) { | ||
| 1281 | addThunkSection(OS, ISD, PrevISLimit); | ||
| 1282 | ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing; | ||
| 1283 | } | ||
| 1284 | PrevISLimit = ISLimit; | ||
| 1285 | } | ||
| 1286 | addThunkSection(OS, ISD, ISLimit); | ||
| 1287 | }); | ||
| 1288 | } | ||
| 1289 | |||
| 1045 | ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS, | 1290 | ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS, |
| 1046 | std::vector<InputSection *> *ISR, | 1291 | InputSectionDescription *ISD, |
| 1047 | uint64_t Off) { | 1292 | uint64_t Off) { |
| 1048 | auto *TS = make<ThunkSection>(OS, Off); | 1293 | auto *TS = make<ThunkSection>(OS, Off); |
| 1049 | ThunkSections[ISR].push_back(TS); | 1294 | ISD->ThunkSections.push_back(std::make_pair(TS, Pass)); |
| 1050 | return TS; | 1295 | return TS; |
| 1051 | } | 1296 | } |
| 1052 | 1297 | ||
| 1053 | std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body, | 1298 | std::pair<Thunk *, bool> ThunkCreator::getThunk(Symbol &Sym, RelType Type, |
| 1054 | uint32_t Type) { | 1299 | uint64_t Src) { |
| 1055 | auto Res = ThunkedSymbols.insert({&Body, std::vector<Thunk *>()}); | 1300 | auto Res = ThunkedSymbols.insert({&Sym, std::vector<Thunk *>()}); |
| 1056 | if (!Res.second) { | 1301 | if (!Res.second) { |
| 1057 | // Check existing Thunks for Body to see if they can be reused | 1302 | // Check existing Thunks for Sym to see if they can be reused |
| 1058 | for (Thunk *ET : Res.first->second) | 1303 | for (Thunk *ET : Res.first->second) |
| 1059 | if (ET->isCompatibleWith(Type)) | 1304 | if (ET->isCompatibleWith(Type) && |
| 1305 | Target->inBranchRange(Type, Src, ET->ThunkSym->getVA())) | ||
| 1060 | return std::make_pair(ET, false); | 1306 | return std::make_pair(ET, false); |
| 1061 | } | 1307 | } |
| 1062 | // No existing compatible Thunk in range, create a new one | 1308 | // No existing compatible Thunk in range, create a new one |
| 1063 | Thunk *T = addThunk(Type, Body); | 1309 | Thunk *T = addThunk(Type, Sym); |
| 1064 | Res.first->second.push_back(T); | 1310 | Res.first->second.push_back(T); |
| 1065 | return std::make_pair(T, true); | 1311 | return std::make_pair(T, true); |
| 1066 | } | 1312 | } |
| 1067 | 1313 | ||
| 1068 | // Call Fn on every executable InputSection accessed via the linker script | 1314 | // Call Fn on every executable InputSection accessed via the linker script |
| 1069 | // InputSectionDescription::Sections. | 1315 | // InputSectionDescription::Sections. |
| 1070 | void ThunkCreator::forEachExecInputSection( | 1316 | void ThunkCreator::forEachInputSectionDescription( |
| 1071 | ArrayRef<OutputSectionCommand *> OutputSections, | 1317 | ArrayRef<OutputSection *> OutputSections, |
| 1072 | std::function<void(OutputSectionCommand *, std::vector<InputSection *> *, | 1318 | std::function<void(OutputSection *, InputSectionDescription *)> Fn) { |
| 1073 | InputSection *)> | 1319 | for (OutputSection *OS : OutputSections) { |
| 1074 | Fn) { | ||
| 1075 | for (OutputSectionCommand *Cmd : OutputSections) { | ||
| 1076 | OutputSection *OS = Cmd->Sec; | ||
| 1077 | if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) | 1320 | if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) |
| 1078 | continue; | 1321 | continue; |
| 1079 | for (BaseCommand *BC : Cmd->Commands) | 1322 | for (BaseCommand *BC : OS->SectionCommands) |
| 1080 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) { | 1323 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) |
| 1081 | CurTS = nullptr; | 1324 | Fn(OS, ISD); |
| 1082 | for (InputSection *IS : ISD->Sections) | ||
| 1083 | Fn(Cmd, &ISD->Sections, IS); | ||
| 1084 | } | ||
| 1085 | } | 1325 | } |
| 1086 | } | 1326 | } |
| 1087 | 1327 | ||
| 1328 | // Return true if the relocation target is an in range Thunk. | ||
| 1329 | // Return false if the relocation is not to a Thunk. If the relocation target | ||
| 1330 | // was originally to a Thunk, but is no longer in range we revert the | ||
| 1331 | // relocation back to its original non-Thunk target. | ||
| 1332 | bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) { | ||
| 1333 | if (Thunk *ET = Thunks.lookup(Rel.Sym)) { | ||
| 1334 | if (Target->inBranchRange(Rel.Type, Src, Rel.Sym->getVA())) | ||
| 1335 | return true; | ||
| 1336 | Rel.Sym = &ET->Destination; | ||
| 1337 | if (Rel.Sym->isInPlt()) | ||
| 1338 | Rel.Expr = toPlt(Rel.Expr); | ||
| 1339 | } | ||
| 1340 | return false; | ||
| 1341 | } | ||
| 1342 | |||
| 1088 | // Process all relocations from the InputSections that have been assigned | 1343 | // Process all relocations from the InputSections that have been assigned |
| 1089 | // to OutputSections and redirect through Thunks if needed. | 1344 | // to InputSectionDescriptions and redirect through Thunks if needed. The |
| 1345 | // function should be called iteratively until it returns false. | ||
| 1346 | // | ||
| 1347 | // PreConditions: | ||
| 1348 | // All InputSections that may need a Thunk are reachable from | ||
| 1349 | // OutputSectionCommands. | ||
| 1090 | // | 1350 | // |
| 1091 | // createThunks must be called after scanRelocs has created the Relocations for | 1351 | // All OutputSections have an address and all InputSections have an offset |
| 1092 | // each InputSection. It must be called before the static symbol table is | 1352 | // within the OutputSection. |
| 1093 | // finalized. If any Thunks are added to an OutputSection the output section | ||
| 1094 | // offsets of the InputSections will change. | ||
| 1095 | // | 1353 | // |
| 1096 | // FIXME: All Thunks are assumed to be in range of the relocation. Range | 1354 | // The offsets between caller (relocation place) and callee |
| 1097 | // extension Thunks are not yet supported. | 1355 | // (relocation target) will not be modified outside of createThunks(). |
| 1098 | bool ThunkCreator::createThunks( | 1356 | // |
| 1099 | ArrayRef<OutputSectionCommand *> OutputSections) { | 1357 | // PostConditions: |
| 1100 | if (Pass > 0) | 1358 | // If return value is true then ThunkSections have been inserted into |
| 1101 | ThunkSections.clear(); | 1359 | // OutputSections. All relocations that needed a Thunk based on the information |
| 1360 | // available to createThunks() on entry have been redirected to a Thunk. Note | ||
| 1361 | // that adding Thunks changes offsets between caller and callee so more Thunks | ||
| 1362 | // may be required. | ||
| 1363 | // | ||
| 1364 | // If return value is false then no more Thunks are needed, and createThunks has | ||
| 1365 | // made no changes. If the target requires range extension thunks, currently | ||
| 1366 | // ARM, then any future change in offset between caller and callee risks a | ||
| 1367 | // relocation out of range error. | ||
| 1368 | bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) { | ||
| 1369 | bool AddressesChanged = false; | ||
| 1370 | if (Pass == 0 && Target->ThunkSectionSpacing) | ||
| 1371 | createInitialThunkSections(OutputSections); | ||
| 1372 | else if (Pass == 10) | ||
| 1373 | // With Thunk Size much smaller than branch range we expect to | ||
| 1374 | // converge quickly; if we get to 10 something has gone wrong. | ||
| 1375 | fatal("thunk creation not converged"); | ||
| 1102 | 1376 | ||
| 1103 | // Create all the Thunks and insert them into synthetic ThunkSections. The | 1377 | // Create all the Thunks and insert them into synthetic ThunkSections. The |
| 1104 | // ThunkSections are later inserted back into the OutputSection. | 1378 | // ThunkSections are later inserted back into InputSectionDescriptions. |
| 1105 | |||
| 1106 | // We separate the creation of ThunkSections from the insertion of the | 1379 | // We separate the creation of ThunkSections from the insertion of the |
| 1107 | // ThunkSections back into the OutputSection as ThunkSections are not always | 1380 | // ThunkSections as ThunkSections are not always inserted into the same |
| 1108 | // inserted into the same OutputSection as the caller. | 1381 | // InputSectionDescription as the caller. |
| 1109 | forEachExecInputSection(OutputSections, [&](OutputSectionCommand *Cmd, | 1382 | forEachInputSectionDescription( |
| 1110 | std::vector<InputSection *> *ISR, | 1383 | OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { |
| 1111 | InputSection *IS) { | 1384 | for (InputSection *IS : ISD->Sections) |
| 1112 | for (Relocation &Rel : IS->Relocations) { | 1385 | for (Relocation &Rel : IS->Relocations) { |
| 1113 | SymbolBody &Body = *Rel.Sym; | 1386 | uint64_t Src = OS->Addr + IS->OutSecOff + Rel.Offset; |
| 1114 | if (Thunks.find(&Body) != Thunks.end() || | 1387 | |
| 1115 | !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) | 1388 | // If we are a relocation to an existing Thunk, check if it is |
| 1116 | continue; | 1389 | // still in range. If not then Rel will be altered to point to its |
| 1117 | Thunk *T; | 1390 | // original target so another Thunk can be generated. |
| 1118 | bool IsNew; | 1391 | if (Pass > 0 && normalizeExistingThunk(Rel, Src)) |
| 1119 | std::tie(T, IsNew) = getThunk(Body, Rel.Type); | 1392 | continue; |
| 1120 | if (IsNew) { | 1393 | |
| 1121 | // Find or create a ThunkSection for the new Thunk | 1394 | if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Src, |
| 1122 | ThunkSection *TS; | 1395 | *Rel.Sym)) |
| 1123 | if (auto *TIS = T->getTargetInputSection()) | 1396 | continue; |
| 1124 | TS = getISThunkSec(TIS, Cmd->Sec); | 1397 | Thunk *T; |
| 1125 | else | 1398 | bool IsNew; |
| 1126 | TS = getOSThunkSec(Cmd, ISR); | 1399 | std::tie(T, IsNew) = getThunk(*Rel.Sym, Rel.Type, Src); |
| 1127 | TS->addThunk(T); | 1400 | if (IsNew) { |
| 1128 | Thunks[T->ThunkSym] = T; | 1401 | AddressesChanged = true; |
| 1129 | } | 1402 | // Find or create a ThunkSection for the new Thunk |
| 1130 | // Redirect relocation to Thunk, we never go via the PLT to a Thunk | 1403 | ThunkSection *TS; |
| 1131 | Rel.Sym = T->ThunkSym; | 1404 | if (auto *TIS = T->getTargetInputSection()) |
| 1132 | Rel.Expr = fromPlt(Rel.Expr); | 1405 | TS = getISThunkSec(TIS); |
| 1133 | } | 1406 | else |
| 1134 | }); | 1407 | TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src); |
| 1408 | TS->addThunk(T); | ||
| 1409 | Thunks[T->ThunkSym] = T; | ||
| 1410 | } | ||
| 1411 | // Redirect relocation to Thunk, we never go via the PLT to a Thunk | ||
| 1412 | Rel.Sym = T->ThunkSym; | ||
| 1413 | Rel.Expr = fromPlt(Rel.Expr); | ||
| 1414 | } | ||
| 1415 | }); | ||
| 1135 | // Merge all created synthetic ThunkSections back into OutputSection | 1416 | // Merge all created synthetic ThunkSections back into OutputSection |
| 1136 | mergeThunks(); | 1417 | mergeThunks(OutputSections); |
| 1137 | ++Pass; | 1418 | ++Pass; |
| 1138 | return !ThunkSections.empty(); | 1419 | return AddressesChanged; |
| 1139 | } | 1420 | } |
| 1140 | 1421 | ||
| 1141 | template void elf::scanRelocations<ELF32LE>(InputSectionBase &); | 1422 | template void elf::scanRelocations<ELF32LE>(InputSectionBase &); |
deps/lld/ELF/Relocations.h+34-30| ... | @@ -10,23 +10,27 @@ | ... | @@ -10,23 +10,27 @@ |
| 10 | #ifndef LLD_ELF_RELOCATIONS_H | 10 | #ifndef LLD_ELF_RELOCATIONS_H |
| 11 | #define LLD_ELF_RELOCATIONS_H | 11 | #define LLD_ELF_RELOCATIONS_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "llvm/ADT/DenseMap.h" | 14 | #include "llvm/ADT/DenseMap.h" |
| 15 | #include <map> | 15 | #include <map> |
| 16 | #include <vector> | 16 | #include <vector> |
| 17 | 17 | ||
| 18 | namespace lld { | 18 | namespace lld { |
| 19 | namespace elf { | 19 | namespace elf { |
| 20 | class SymbolBody; | 20 | class Symbol; |
| 21 | class InputSection; | 21 | class InputSection; |
| 22 | class InputSectionBase; | 22 | class InputSectionBase; |
| 23 | class OutputSection; | 23 | class OutputSection; |
| 24 | struct OutputSectionCommand; | 24 | class OutputSection; |
| 25 | |||
| 26 | // Represents a relocation type, such as R_X86_64_PC32 or R_ARM_THM_CALL. | ||
| 27 | typedef uint32_t RelType; | ||
| 25 | 28 | ||
| 26 | // List of target-independent relocation types. Relocations read | 29 | // List of target-independent relocation types. Relocations read |
| 27 | // from files are converted to these types so that the main code | 30 | // from files are converted to these types so that the main code |
| 28 | // doesn't have to know about architecture-specific details. | 31 | // doesn't have to know about architecture-specific details. |
| 29 | enum RelExpr { | 32 | enum RelExpr { |
| 33 | R_INVALID, | ||
| 30 | R_ABS, | 34 | R_ABS, |
| 31 | R_ARM_SBREL, | 35 | R_ARM_SBREL, |
| 32 | R_GOT, | 36 | R_GOT, |
| ... | @@ -111,21 +115,22 @@ template <RelExpr... Exprs> bool isRelExprOneOf(RelExpr Expr) { | ... | @@ -111,21 +115,22 @@ template <RelExpr... Exprs> bool isRelExprOneOf(RelExpr Expr) { |
| 111 | // Architecture-neutral representation of relocation. | 115 | // Architecture-neutral representation of relocation. |
| 112 | struct Relocation { | 116 | struct Relocation { |
| 113 | RelExpr Expr; | 117 | RelExpr Expr; |
| 114 | uint32_t Type; | 118 | RelType Type; |
| 115 | uint64_t Offset; | 119 | uint64_t Offset; |
| 116 | int64_t Addend; | 120 | int64_t Addend; |
| 117 | SymbolBody *Sym; | 121 | Symbol *Sym; |
| 118 | }; | 122 | }; |
| 119 | 123 | ||
| 120 | template <class ELFT> void scanRelocations(InputSectionBase &); | 124 | template <class ELFT> void scanRelocations(InputSectionBase &); |
| 121 | 125 | ||
| 122 | class ThunkSection; | 126 | class ThunkSection; |
| 123 | class Thunk; | 127 | class Thunk; |
| 128 | struct InputSectionDescription; | ||
| 124 | 129 | ||
| 125 | class ThunkCreator { | 130 | class ThunkCreator { |
| 126 | public: | 131 | public: |
| 127 | // Return true if Thunks have been added to OutputSections | 132 | // Return true if Thunks have been added to OutputSections |
| 128 | bool createThunks(ArrayRef<OutputSectionCommand *> OutputSections); | 133 | bool createThunks(ArrayRef<OutputSection *> OutputSections); |
| 129 | 134 | ||
| 130 | // The number of completed passes of createThunks this permits us | 135 | // The number of completed passes of createThunks this permits us |
| 131 | // to do one time initialization on Pass 0 and put a limit on the | 136 | // to do one time initialization on Pass 0 and put a limit on the |
| ... | @@ -133,40 +138,39 @@ public: | ... | @@ -133,40 +138,39 @@ public: |
| 133 | uint32_t Pass = 0; | 138 | uint32_t Pass = 0; |
| 134 | 139 | ||
| 135 | private: | 140 | private: |
| 136 | void mergeThunks(); | 141 | void mergeThunks(ArrayRef<OutputSection *> OutputSections); |
| 137 | ThunkSection *getOSThunkSec(OutputSectionCommand *Cmd, | 142 | |
| 138 | std::vector<InputSection *> *ISR); | 143 | ThunkSection *getISDThunkSec(OutputSection *OS, InputSection *IS, |
| 139 | ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS); | 144 | InputSectionDescription *ISD, uint32_t Type, |
| 140 | void forEachExecInputSection( | 145 | uint64_t Src); |
| 141 | ArrayRef<OutputSectionCommand *> OutputSections, | 146 | |
| 142 | std::function<void(OutputSectionCommand *, std::vector<InputSection *> *, | 147 | ThunkSection *getISThunkSec(InputSection *IS); |
| 143 | InputSection *)> | 148 | |
| 144 | Fn); | 149 | void createInitialThunkSections(ArrayRef<OutputSection *> OutputSections); |
| 145 | std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type); | 150 | |
| 146 | ThunkSection *addThunkSection(OutputSection *OS, | 151 | void forEachInputSectionDescription( |
| 147 | std::vector<InputSection *> *, uint64_t Off); | 152 | ArrayRef<OutputSection *> OutputSections, |
| 153 | std::function<void(OutputSection *, InputSectionDescription *)> Fn); | ||
| 154 | |||
| 155 | std::pair<Thunk *, bool> getThunk(Symbol &Sym, RelType Type, uint64_t Src); | ||
| 156 | |||
| 157 | ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *, | ||
| 158 | uint64_t Off); | ||
| 159 | |||
| 160 | bool normalizeExistingThunk(Relocation &Rel, uint64_t Src); | ||
| 161 | |||
| 148 | // Record all the available Thunks for a Symbol | 162 | // Record all the available Thunks for a Symbol |
| 149 | llvm::DenseMap<SymbolBody *, std::vector<Thunk *>> ThunkedSymbols; | 163 | llvm::DenseMap<Symbol *, std::vector<Thunk *>> ThunkedSymbols; |
| 150 | 164 | ||
| 151 | // Find a Thunk from the Thunks symbol definition, we can use this to find | 165 | // Find a Thunk from the Thunks symbol definition, we can use this to find |
| 152 | // the Thunk from a relocation to the Thunks symbol definition. | 166 | // the Thunk from a relocation to the Thunks symbol definition. |
| 153 | llvm::DenseMap<SymbolBody *, Thunk *> Thunks; | 167 | llvm::DenseMap<Symbol *, Thunk *> Thunks; |
| 154 | 168 | ||
| 155 | // Track InputSections that have an inline ThunkSection placed in front | 169 | // Track InputSections that have an inline ThunkSection placed in front |
| 156 | // an inline ThunkSection may have control fall through to the section below | 170 | // an inline ThunkSection may have control fall through to the section below |
| 157 | // so we need to make sure that there is only one of them. | 171 | // so we need to make sure that there is only one of them. |
| 158 | // The Mips LA25 Thunk is an example of an inline ThunkSection. | 172 | // The Mips LA25 Thunk is an example of an inline ThunkSection. |
| 159 | llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections; | 173 | llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections; |
| 160 | |||
| 161 | // All the ThunkSections that we have created, organised by OutputSection | ||
| 162 | // will contain a mix of ThunkSections that have been created this pass, and | ||
| 163 | // ThunkSections that have been merged into the OutputSection on previous | ||
| 164 | // passes | ||
| 165 | std::map<std::vector<InputSection *> *, std::vector<ThunkSection *>> | ||
| 166 | ThunkSections; | ||
| 167 | |||
| 168 | // The ThunkSection for this vector of InputSections | ||
| 169 | ThunkSection *CurTS; | ||
| 170 | }; | 174 | }; |
| 171 | 175 | ||
| 172 | // Return a int64_t to make sure we get the sign extension out of the way as | 176 | // Return a int64_t to make sure we get the sign extension out of the way as |
deps/lld/ELF/ScriptLexer.cpp+31-23| ... | @@ -33,7 +33,7 @@ | ... | @@ -33,7 +33,7 @@ |
| 33 | //===----------------------------------------------------------------------===// | 33 | //===----------------------------------------------------------------------===// |
| 34 | 34 | ||
| 35 | #include "ScriptLexer.h" | 35 | #include "ScriptLexer.h" |
| 36 | #include "Error.h" | 36 | #include "lld/Common/ErrorHandler.h" |
| 37 | #include "llvm/ADT/Twine.h" | 37 | #include "llvm/ADT/Twine.h" |
| 38 | 38 | ||
| 39 | using namespace llvm; | 39 | using namespace llvm; |
| ... | @@ -75,19 +75,14 @@ ScriptLexer::ScriptLexer(MemoryBufferRef MB) { tokenize(MB); } | ... | @@ -75,19 +75,14 @@ ScriptLexer::ScriptLexer(MemoryBufferRef MB) { tokenize(MB); } |
| 75 | 75 | ||
| 76 | // We don't want to record cascading errors. Keep only the first one. | 76 | // We don't want to record cascading errors. Keep only the first one. |
| 77 | void ScriptLexer::setError(const Twine &Msg) { | 77 | void ScriptLexer::setError(const Twine &Msg) { |
| 78 | if (Error) | 78 | if (errorCount()) |
| 79 | return; | 79 | return; |
| 80 | Error = true; | ||
| 81 | 80 | ||
| 82 | if (!Pos) { | 81 | std::string S = (getCurrentLocation() + ": " + Msg).str(); |
| 83 | error(getCurrentLocation() + ": " + Msg); | 82 | if (Pos) |
| 84 | return; | 83 | S += "\n>>> " + getLine().str() + "\n>>> " + |
| 85 | } | 84 | std::string(getColumnNumber(), ' ') + "^"; |
| 86 | 85 | error(S); | |
| 87 | std::string S = getCurrentLocation() + ": "; | ||
| 88 | error(S + Msg); | ||
| 89 | error(S + getLine()); | ||
| 90 | error(S + std::string(getColumnNumber(), ' ') + "^"); | ||
| 91 | } | 86 | } |
| 92 | 87 | ||
| 93 | // Split S into linker script tokens. | 88 | // Split S into linker script tokens. |
| ... | @@ -120,11 +115,19 @@ void ScriptLexer::tokenize(MemoryBufferRef MB) { | ... | @@ -120,11 +115,19 @@ void ScriptLexer::tokenize(MemoryBufferRef MB) { |
| 120 | continue; | 115 | continue; |
| 121 | } | 116 | } |
| 122 | 117 | ||
| 118 | // ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>". | ||
| 119 | if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") || | ||
| 120 | S.startswith(">=")) { | ||
| 121 | Vec.push_back(S.substr(0, 2)); | ||
| 122 | S = S.substr(2); | ||
| 123 | continue; | ||
| 124 | } | ||
| 125 | |||
| 123 | // Unquoted token. This is more relaxed than tokens in C-like language, | 126 | // Unquoted token. This is more relaxed than tokens in C-like language, |
| 124 | // so that you can write "file-name.cpp" as one bare token, for example. | 127 | // so that you can write "file-name.cpp" as one bare token, for example. |
| 125 | size_t Pos = S.find_first_not_of( | 128 | size_t Pos = S.find_first_not_of( |
| 126 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" | 129 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" |
| 127 | "0123456789_.$/\\~=+[]*?-!<>^:"); | 130 | "0123456789_.$/\\~=+[]*?-!^:"); |
| 128 | 131 | ||
| 129 | // A character that cannot start a word (which is usually a | 132 | // A character that cannot start a word (which is usually a |
| 130 | // punctuation) forms a single character token. | 133 | // punctuation) forms a single character token. |
| ... | @@ -164,18 +167,18 @@ StringRef ScriptLexer::skipSpace(StringRef S) { | ... | @@ -164,18 +167,18 @@ StringRef ScriptLexer::skipSpace(StringRef S) { |
| 164 | } | 167 | } |
| 165 | 168 | ||
| 166 | // An erroneous token is handled as if it were the last token before EOF. | 169 | // An erroneous token is handled as if it were the last token before EOF. |
| 167 | bool ScriptLexer::atEOF() { return Error || Tokens.size() == Pos; } | 170 | bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; } |
| 168 | 171 | ||
| 169 | // Split a given string as an expression. | 172 | // Split a given string as an expression. |
| 170 | // This function returns "3", "*" and "5" for "3*5" for example. | 173 | // This function returns "3", "*" and "5" for "3*5" for example. |
| 171 | static std::vector<StringRef> tokenizeExpr(StringRef S) { | 174 | static std::vector<StringRef> tokenizeExpr(StringRef S) { |
| 172 | StringRef Ops = "+-*/:"; // List of operators | 175 | StringRef Ops = "+-*/:!~"; // List of operators |
| 173 | 176 | ||
| 174 | // Quoted strings are literal strings, so we don't want to split it. | 177 | // Quoted strings are literal strings, so we don't want to split it. |
| 175 | if (S.startswith("\"")) | 178 | if (S.startswith("\"")) |
| 176 | return {S}; | 179 | return {S}; |
| 177 | 180 | ||
| 178 | // Split S with +-*/ as separators. | 181 | // Split S with operators as separators. |
| 179 | std::vector<StringRef> Ret; | 182 | std::vector<StringRef> Ret; |
| 180 | while (!S.empty()) { | 183 | while (!S.empty()) { |
| 181 | size_t E = S.find_first_of(Ops); | 184 | size_t E = S.find_first_of(Ops); |
| ... | @@ -190,9 +193,14 @@ static std::vector<StringRef> tokenizeExpr(StringRef S) { | ... | @@ -190,9 +193,14 @@ static std::vector<StringRef> tokenizeExpr(StringRef S) { |
| 190 | if (E != 0) | 193 | if (E != 0) |
| 191 | Ret.push_back(S.substr(0, E)); | 194 | Ret.push_back(S.substr(0, E)); |
| 192 | 195 | ||
| 193 | // Get the operator as a token. | 196 | // Get the operator as a token. Keep != as one token. |
| 194 | Ret.push_back(S.substr(E, 1)); | 197 | if (S.substr(E).startswith("!=")) { |
| 195 | S = S.substr(E + 1); | 198 | Ret.push_back(S.substr(E, 2)); |
| 199 | S = S.substr(E + 2); | ||
| 200 | } else { | ||
| 201 | Ret.push_back(S.substr(E, 1)); | ||
| 202 | S = S.substr(E + 1); | ||
| 203 | } | ||
| 196 | } | 204 | } |
| 197 | return Ret; | 205 | return Ret; |
| 198 | } | 206 | } |
| ... | @@ -207,7 +215,7 @@ static std::vector<StringRef> tokenizeExpr(StringRef S) { | ... | @@ -207,7 +215,7 @@ static std::vector<StringRef> tokenizeExpr(StringRef S) { |
| 207 | // | 215 | // |
| 208 | // This function may split the current token into multiple tokens. | 216 | // This function may split the current token into multiple tokens. |
| 209 | void ScriptLexer::maybeSplitExpr() { | 217 | void ScriptLexer::maybeSplitExpr() { |
| 210 | if (!InExpr || Error || atEOF()) | 218 | if (!InExpr || errorCount() || atEOF()) |
| 211 | return; | 219 | return; |
| 212 | 220 | ||
| 213 | std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]); | 221 | std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]); |
| ... | @@ -220,7 +228,7 @@ void ScriptLexer::maybeSplitExpr() { | ... | @@ -220,7 +228,7 @@ void ScriptLexer::maybeSplitExpr() { |
| 220 | StringRef ScriptLexer::next() { | 228 | StringRef ScriptLexer::next() { |
| 221 | maybeSplitExpr(); | 229 | maybeSplitExpr(); |
| 222 | 230 | ||
| 223 | if (Error) | 231 | if (errorCount()) |
| 224 | return ""; | 232 | return ""; |
| 225 | if (atEOF()) { | 233 | if (atEOF()) { |
| 226 | setError("unexpected EOF"); | 234 | setError("unexpected EOF"); |
| ... | @@ -231,7 +239,7 @@ StringRef ScriptLexer::next() { | ... | @@ -231,7 +239,7 @@ StringRef ScriptLexer::next() { |
| 231 | 239 | ||
| 232 | StringRef ScriptLexer::peek() { | 240 | StringRef ScriptLexer::peek() { |
| 233 | StringRef Tok = next(); | 241 | StringRef Tok = next(); |
| 234 | if (Error) | 242 | if (errorCount()) |
| 235 | return ""; | 243 | return ""; |
| 236 | Pos = Pos - 1; | 244 | Pos = Pos - 1; |
| 237 | return Tok; | 245 | return Tok; |
| ... | @@ -260,7 +268,7 @@ bool ScriptLexer::consumeLabel(StringRef Tok) { | ... | @@ -260,7 +268,7 @@ bool ScriptLexer::consumeLabel(StringRef Tok) { |
| 260 | void ScriptLexer::skip() { (void)next(); } | 268 | void ScriptLexer::skip() { (void)next(); } |
| 261 | 269 | ||
| 262 | void ScriptLexer::expect(StringRef Expect) { | 270 | void ScriptLexer::expect(StringRef Expect) { |
| 263 | if (Error) | 271 | if (errorCount()) |
| 264 | return; | 272 | return; |
| 265 | StringRef Tok = next(); | 273 | StringRef Tok = next(); |
| 266 | if (Tok != Expect) | 274 | if (Tok != Expect) |
deps/lld/ELF/ScriptLexer.h+1-2| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_ELF_SCRIPT_LEXER_H | 10 | #ifndef LLD_ELF_SCRIPT_LEXER_H |
| 11 | #define LLD_ELF_SCRIPT_LEXER_H | 11 | #define LLD_ELF_SCRIPT_LEXER_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "llvm/ADT/StringRef.h" | 14 | #include "llvm/ADT/StringRef.h" |
| 15 | #include "llvm/Support/MemoryBuffer.h" | 15 | #include "llvm/Support/MemoryBuffer.h" |
| 16 | #include <utility> | 16 | #include <utility> |
| ... | @@ -39,7 +39,6 @@ public: | ... | @@ -39,7 +39,6 @@ public: |
| 39 | std::vector<StringRef> Tokens; | 39 | std::vector<StringRef> Tokens; |
| 40 | bool InExpr = false; | 40 | bool InExpr = false; |
| 41 | size_t Pos = 0; | 41 | size_t Pos = 0; |
| 42 | bool Error = false; | ||
| 43 | 42 | ||
| 44 | private: | 43 | private: |
| 45 | void maybeSplitExpr(); | 44 | void maybeSplitExpr(); |
deps/lld/ELF/ScriptParser.cpp+195-108| ... | @@ -17,13 +17,14 @@ | ... | @@ -17,13 +17,14 @@ |
| 17 | #include "Driver.h" | 17 | #include "Driver.h" |
| 18 | #include "InputSection.h" | 18 | #include "InputSection.h" |
| 19 | #include "LinkerScript.h" | 19 | #include "LinkerScript.h" |
| 20 | #include "Memory.h" | ||
| 21 | #include "OutputSections.h" | 20 | #include "OutputSections.h" |
| 22 | #include "ScriptLexer.h" | 21 | #include "ScriptLexer.h" |
| 23 | #include "Symbols.h" | 22 | #include "Symbols.h" |
| 24 | #include "Target.h" | 23 | #include "Target.h" |
| 24 | #include "lld/Common/Memory.h" | ||
| 25 | #include "llvm/ADT/SmallString.h" | 25 | #include "llvm/ADT/SmallString.h" |
| 26 | #include "llvm/ADT/StringRef.h" | 26 | #include "llvm/ADT/StringRef.h" |
| 27 | #include "llvm/ADT/StringSet.h" | ||
| 27 | #include "llvm/ADT/StringSwitch.h" | 28 | #include "llvm/ADT/StringSwitch.h" |
| 28 | #include "llvm/BinaryFormat/ELF.h" | 29 | #include "llvm/BinaryFormat/ELF.h" |
| 29 | #include "llvm/Support/Casting.h" | 30 | #include "llvm/Support/Casting.h" |
| ... | @@ -52,10 +53,10 @@ public: | ... | @@ -52,10 +53,10 @@ public: |
| 52 | void readLinkerScript(); | 53 | void readLinkerScript(); |
| 53 | void readVersionScript(); | 54 | void readVersionScript(); |
| 54 | void readDynamicList(); | 55 | void readDynamicList(); |
| 56 | void readDefsym(StringRef Name); | ||
| 55 | 57 | ||
| 56 | private: | 58 | private: |
| 57 | void addFile(StringRef Path); | 59 | void addFile(StringRef Path); |
| 58 | OutputSection *checkSection(OutputSectionCommand *Cmd, StringRef Loccation); | ||
| 59 | 60 | ||
| 60 | void readAsNeeded(); | 61 | void readAsNeeded(); |
| 61 | void readEntry(); | 62 | void readEntry(); |
| ... | @@ -67,17 +68,18 @@ private: | ... | @@ -67,17 +68,18 @@ private: |
| 67 | void readOutputArch(); | 68 | void readOutputArch(); |
| 68 | void readOutputFormat(); | 69 | void readOutputFormat(); |
| 69 | void readPhdrs(); | 70 | void readPhdrs(); |
| 71 | void readRegionAlias(); | ||
| 70 | void readSearchDir(); | 72 | void readSearchDir(); |
| 71 | void readSections(); | 73 | void readSections(); |
| 72 | void readVersion(); | 74 | void readVersion(); |
| 73 | void readVersionScriptCommand(); | 75 | void readVersionScriptCommand(); |
| 74 | 76 | ||
| 75 | SymbolAssignment *readAssignment(StringRef Name); | 77 | SymbolAssignment *readAssignment(StringRef Name); |
| 76 | BytesDataCommand *readBytesDataCommand(StringRef Tok); | 78 | ByteCommand *readByteCommand(StringRef Tok); |
| 77 | uint32_t readFill(); | 79 | uint32_t readFill(); |
| 78 | uint32_t parseFill(StringRef Tok); | 80 | uint32_t parseFill(StringRef Tok); |
| 79 | void readSectionAddressType(OutputSectionCommand *Cmd); | 81 | void readSectionAddressType(OutputSection *Cmd); |
| 80 | OutputSectionCommand *readOutputSectionDescription(StringRef OutSec); | 82 | OutputSection *readOutputSectionDescription(StringRef OutSec); |
| 81 | std::vector<StringRef> readOutputSectionPhdrs(); | 83 | std::vector<StringRef> readOutputSectionPhdrs(); |
| 82 | InputSectionDescription *readInputSectionDescription(StringRef Tok); | 84 | InputSectionDescription *readInputSectionDescription(StringRef Tok); |
| 83 | StringMatcher readFilePatterns(); | 85 | StringMatcher readFilePatterns(); |
| ... | @@ -90,6 +92,8 @@ private: | ... | @@ -90,6 +92,8 @@ private: |
| 90 | void readSort(); | 92 | void readSort(); |
| 91 | AssertCommand *readAssert(); | 93 | AssertCommand *readAssert(); |
| 92 | Expr readAssertExpr(); | 94 | Expr readAssertExpr(); |
| 95 | Expr readConstant(); | ||
| 96 | Expr getPageSize(); | ||
| 93 | 97 | ||
| 94 | uint64_t readMemoryAssignment(StringRef, StringRef, StringRef); | 98 | uint64_t readMemoryAssignment(StringRef, StringRef, StringRef); |
| 95 | std::pair<uint32_t, uint32_t> readMemoryAttributes(); | 99 | std::pair<uint32_t, uint32_t> readMemoryAttributes(); |
| ... | @@ -109,7 +113,11 @@ private: | ... | @@ -109,7 +113,11 @@ private: |
| 109 | std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>> | 113 | std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>> |
| 110 | readSymbols(); | 114 | readSymbols(); |
| 111 | 115 | ||
| 116 | // True if a script being read is in a subdirectory specified by -sysroot. | ||
| 112 | bool IsUnderSysroot; | 117 | bool IsUnderSysroot; |
| 118 | |||
| 119 | // A set to detect an INCLUDE() cycle. | ||
| 120 | StringSet<> Seen; | ||
| 113 | }; | 121 | }; |
| 114 | } // namespace | 122 | } // namespace |
| 115 | 123 | ||
| ... | @@ -131,7 +139,7 @@ static bool isUnderSysroot(StringRef Path) { | ... | @@ -131,7 +139,7 @@ static bool isUnderSysroot(StringRef Path) { |
| 131 | // Some operations only support one non absolute value. Move the | 139 | // Some operations only support one non absolute value. Move the |
| 132 | // absolute one to the right hand side for convenience. | 140 | // absolute one to the right hand side for convenience. |
| 133 | static void moveAbsRight(ExprValue &A, ExprValue &B) { | 141 | static void moveAbsRight(ExprValue &A, ExprValue &B) { |
| 134 | if (A.isAbsolute()) | 142 | if (A.Sec == nullptr || (A.ForceAbsolute && !B.isAbsolute())) |
| 135 | std::swap(A, B); | 143 | std::swap(A, B); |
| 136 | if (!B.isAbsolute()) | 144 | if (!B.isAbsolute()) |
| 137 | error(A.Loc + ": at least one side of the expression must be absolute"); | 145 | error(A.Loc + ": at least one side of the expression must be absolute"); |
| ... | @@ -139,11 +147,14 @@ static void moveAbsRight(ExprValue &A, ExprValue &B) { | ... | @@ -139,11 +147,14 @@ static void moveAbsRight(ExprValue &A, ExprValue &B) { |
| 139 | 147 | ||
| 140 | static ExprValue add(ExprValue A, ExprValue B) { | 148 | static ExprValue add(ExprValue A, ExprValue B) { |
| 141 | moveAbsRight(A, B); | 149 | moveAbsRight(A, B); |
| 142 | return {A.Sec, A.ForceAbsolute, A.Val + B.getValue(), A.Loc}; | 150 | return {A.Sec, A.ForceAbsolute, A.getSectionOffset() + B.getValue(), A.Loc}; |
| 143 | } | 151 | } |
| 144 | 152 | ||
| 145 | static ExprValue sub(ExprValue A, ExprValue B) { | 153 | static ExprValue sub(ExprValue A, ExprValue B) { |
| 146 | return {A.Sec, A.Val - B.getValue(), A.Loc}; | 154 | // The distance between two symbols in sections is absolute. |
| 155 | if (!A.isAbsolute() && !B.isAbsolute()) | ||
| 156 | return A.getValue() - B.getValue(); | ||
| 157 | return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc}; | ||
| 147 | } | 158 | } |
| 148 | 159 | ||
| 149 | static ExprValue mul(ExprValue A, ExprValue B) { | 160 | static ExprValue mul(ExprValue A, ExprValue B) { |
| ... | @@ -170,10 +181,24 @@ static ExprValue bitOr(ExprValue A, ExprValue B) { | ... | @@ -170,10 +181,24 @@ static ExprValue bitOr(ExprValue A, ExprValue B) { |
| 170 | } | 181 | } |
| 171 | 182 | ||
| 172 | void ScriptParser::readDynamicList() { | 183 | void ScriptParser::readDynamicList() { |
| 184 | Config->HasDynamicList = true; | ||
| 173 | expect("{"); | 185 | expect("{"); |
| 174 | readAnonymousDeclaration(); | 186 | std::vector<SymbolVersion> Locals; |
| 175 | if (!atEOF()) | 187 | std::vector<SymbolVersion> Globals; |
| 188 | std::tie(Locals, Globals) = readSymbols(); | ||
| 189 | expect(";"); | ||
| 190 | |||
| 191 | if (!atEOF()) { | ||
| 176 | setError("EOF expected, but got " + next()); | 192 | setError("EOF expected, but got " + next()); |
| 193 | return; | ||
| 194 | } | ||
| 195 | if (!Locals.empty()) { | ||
| 196 | setError("\"local:\" scope not supported in --dynamic-list"); | ||
| 197 | return; | ||
| 198 | } | ||
| 199 | |||
| 200 | for (SymbolVersion V : Globals) | ||
| 201 | Config->DynamicList.push_back(V); | ||
| 177 | } | 202 | } |
| 178 | 203 | ||
| 179 | void ScriptParser::readVersionScript() { | 204 | void ScriptParser::readVersionScript() { |
| ... | @@ -188,7 +213,7 @@ void ScriptParser::readVersionScriptCommand() { | ... | @@ -188,7 +213,7 @@ void ScriptParser::readVersionScriptCommand() { |
| 188 | return; | 213 | return; |
| 189 | } | 214 | } |
| 190 | 215 | ||
| 191 | while (!atEOF() && !Error && peek() != "}") { | 216 | while (!atEOF() && !errorCount() && peek() != "}") { |
| 192 | StringRef VerStr = next(); | 217 | StringRef VerStr = next(); |
| 193 | if (VerStr == "{") { | 218 | if (VerStr == "{") { |
| 194 | setError("anonymous version definition is used in " | 219 | setError("anonymous version definition is used in " |
| ... | @@ -213,7 +238,7 @@ void ScriptParser::readLinkerScript() { | ... | @@ -213,7 +238,7 @@ void ScriptParser::readLinkerScript() { |
| 213 | continue; | 238 | continue; |
| 214 | 239 | ||
| 215 | if (Tok == "ASSERT") { | 240 | if (Tok == "ASSERT") { |
| 216 | Script->Opt.Commands.push_back(readAssert()); | 241 | Script->SectionCommands.push_back(readAssert()); |
| 217 | } else if (Tok == "ENTRY") { | 242 | } else if (Tok == "ENTRY") { |
| 218 | readEntry(); | 243 | readEntry(); |
| 219 | } else if (Tok == "EXTERN") { | 244 | } else if (Tok == "EXTERN") { |
| ... | @@ -232,6 +257,8 @@ void ScriptParser::readLinkerScript() { | ... | @@ -232,6 +257,8 @@ void ScriptParser::readLinkerScript() { |
| 232 | readOutputFormat(); | 257 | readOutputFormat(); |
| 233 | } else if (Tok == "PHDRS") { | 258 | } else if (Tok == "PHDRS") { |
| 234 | readPhdrs(); | 259 | readPhdrs(); |
| 260 | } else if (Tok == "REGION_ALIAS") { | ||
| 261 | readRegionAlias(); | ||
| 235 | } else if (Tok == "SEARCH_DIR") { | 262 | } else if (Tok == "SEARCH_DIR") { |
| 236 | readSearchDir(); | 263 | readSearchDir(); |
| 237 | } else if (Tok == "SECTIONS") { | 264 | } else if (Tok == "SECTIONS") { |
| ... | @@ -239,13 +266,21 @@ void ScriptParser::readLinkerScript() { | ... | @@ -239,13 +266,21 @@ void ScriptParser::readLinkerScript() { |
| 239 | } else if (Tok == "VERSION") { | 266 | } else if (Tok == "VERSION") { |
| 240 | readVersion(); | 267 | readVersion(); |
| 241 | } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) { | 268 | } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) { |
| 242 | Script->Opt.Commands.push_back(Cmd); | 269 | Script->SectionCommands.push_back(Cmd); |
| 243 | } else { | 270 | } else { |
| 244 | setError("unknown directive: " + Tok); | 271 | setError("unknown directive: " + Tok); |
| 245 | } | 272 | } |
| 246 | } | 273 | } |
| 247 | } | 274 | } |
| 248 | 275 | ||
| 276 | void ScriptParser::readDefsym(StringRef Name) { | ||
| 277 | Expr E = readExpr(); | ||
| 278 | if (!atEOF()) | ||
| 279 | setError("EOF expected, but got " + next()); | ||
| 280 | SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation()); | ||
| 281 | Script->SectionCommands.push_back(Cmd); | ||
| 282 | } | ||
| 283 | |||
| 249 | void ScriptParser::addFile(StringRef S) { | 284 | void ScriptParser::addFile(StringRef S) { |
| 250 | if (IsUnderSysroot && S.startswith("/")) { | 285 | if (IsUnderSysroot && S.startswith("/")) { |
| 251 | SmallString<128> PathData; | 286 | SmallString<128> PathData; |
| ... | @@ -256,7 +291,7 @@ void ScriptParser::addFile(StringRef S) { | ... | @@ -256,7 +291,7 @@ void ScriptParser::addFile(StringRef S) { |
| 256 | } | 291 | } |
| 257 | } | 292 | } |
| 258 | 293 | ||
| 259 | if (sys::path::is_absolute(S)) { | 294 | if (S.startswith("/")) { |
| 260 | Driver->addFile(S, /*WithLOption=*/false); | 295 | Driver->addFile(S, /*WithLOption=*/false); |
| 261 | } else if (S.startswith("=")) { | 296 | } else if (S.startswith("=")) { |
| 262 | if (Config->Sysroot.empty()) | 297 | if (Config->Sysroot.empty()) |
| ... | @@ -280,7 +315,7 @@ void ScriptParser::readAsNeeded() { | ... | @@ -280,7 +315,7 @@ void ScriptParser::readAsNeeded() { |
| 280 | expect("("); | 315 | expect("("); |
| 281 | bool Orig = Config->AsNeeded; | 316 | bool Orig = Config->AsNeeded; |
| 282 | Config->AsNeeded = true; | 317 | Config->AsNeeded = true; |
| 283 | while (!Error && !consume(")")) | 318 | while (!errorCount() && !consume(")")) |
| 284 | addFile(unquote(next())); | 319 | addFile(unquote(next())); |
| 285 | Config->AsNeeded = Orig; | 320 | Config->AsNeeded = Orig; |
| 286 | } | 321 | } |
| ... | @@ -296,13 +331,13 @@ void ScriptParser::readEntry() { | ... | @@ -296,13 +331,13 @@ void ScriptParser::readEntry() { |
| 296 | 331 | ||
| 297 | void ScriptParser::readExtern() { | 332 | void ScriptParser::readExtern() { |
| 298 | expect("("); | 333 | expect("("); |
| 299 | while (!Error && !consume(")")) | 334 | while (!errorCount() && !consume(")")) |
| 300 | Config->Undefined.push_back(next()); | 335 | Config->Undefined.push_back(next()); |
| 301 | } | 336 | } |
| 302 | 337 | ||
| 303 | void ScriptParser::readGroup() { | 338 | void ScriptParser::readGroup() { |
| 304 | expect("("); | 339 | expect("("); |
| 305 | while (!Error && !consume(")")) { | 340 | while (!errorCount() && !consume(")")) { |
| 306 | if (consume("AS_NEEDED")) | 341 | if (consume("AS_NEEDED")) |
| 307 | readAsNeeded(); | 342 | readAsNeeded(); |
| 308 | else | 343 | else |
| ... | @@ -313,20 +348,17 @@ void ScriptParser::readGroup() { | ... | @@ -313,20 +348,17 @@ void ScriptParser::readGroup() { |
| 313 | void ScriptParser::readInclude() { | 348 | void ScriptParser::readInclude() { |
| 314 | StringRef Tok = unquote(next()); | 349 | StringRef Tok = unquote(next()); |
| 315 | 350 | ||
| 316 | // https://sourceware.org/binutils/docs/ld/File-Commands.html: | 351 | if (!Seen.insert(Tok).second) { |
| 317 | // The file will be searched for in the current directory, and in any | 352 | setError("there is a cycle in linker script INCLUDEs"); |
| 318 | // directory specified with the -L option. | ||
| 319 | if (sys::fs::exists(Tok)) { | ||
| 320 | if (Optional<MemoryBufferRef> MB = readFile(Tok)) | ||
| 321 | tokenize(*MB); | ||
| 322 | return; | 353 | return; |
| 323 | } | 354 | } |
| 324 | if (Optional<std::string> Path = findFromSearchPaths(Tok)) { | 355 | |
| 356 | if (Optional<std::string> Path = searchLinkerScript(Tok)) { | ||
| 325 | if (Optional<MemoryBufferRef> MB = readFile(*Path)) | 357 | if (Optional<MemoryBufferRef> MB = readFile(*Path)) |
| 326 | tokenize(*MB); | 358 | tokenize(*MB); |
| 327 | return; | 359 | return; |
| 328 | } | 360 | } |
| 329 | setError("cannot open " + Tok); | 361 | setError("cannot find linker script " + Tok); |
| 330 | } | 362 | } |
| 331 | 363 | ||
| 332 | void ScriptParser::readOutput() { | 364 | void ScriptParser::readOutput() { |
| ... | @@ -341,7 +373,7 @@ void ScriptParser::readOutput() { | ... | @@ -341,7 +373,7 @@ void ScriptParser::readOutput() { |
| 341 | void ScriptParser::readOutputArch() { | 373 | void ScriptParser::readOutputArch() { |
| 342 | // OUTPUT_ARCH is ignored for now. | 374 | // OUTPUT_ARCH is ignored for now. |
| 343 | expect("("); | 375 | expect("("); |
| 344 | while (!Error && !consume(")")) | 376 | while (!errorCount() && !consume(")")) |
| 345 | skip(); | 377 | skip(); |
| 346 | } | 378 | } |
| 347 | 379 | ||
| ... | @@ -360,28 +392,43 @@ void ScriptParser::readOutputFormat() { | ... | @@ -360,28 +392,43 @@ void ScriptParser::readOutputFormat() { |
| 360 | 392 | ||
| 361 | void ScriptParser::readPhdrs() { | 393 | void ScriptParser::readPhdrs() { |
| 362 | expect("{"); | 394 | expect("{"); |
| 363 | while (!Error && !consume("}")) { | ||
| 364 | Script->Opt.PhdrsCommands.push_back( | ||
| 365 | {next(), PT_NULL, false, false, UINT_MAX, nullptr}); | ||
| 366 | 395 | ||
| 367 | PhdrsCommand &PhdrCmd = Script->Opt.PhdrsCommands.back(); | 396 | while (!errorCount() && !consume("}")) { |
| 368 | PhdrCmd.Type = readPhdrType(); | 397 | PhdrsCommand Cmd; |
| 398 | Cmd.Name = next(); | ||
| 399 | Cmd.Type = readPhdrType(); | ||
| 369 | 400 | ||
| 370 | while (!Error && !consume(";")) { | 401 | while (!errorCount() && !consume(";")) { |
| 371 | if (consume("FILEHDR")) | 402 | if (consume("FILEHDR")) |
| 372 | PhdrCmd.HasFilehdr = true; | 403 | Cmd.HasFilehdr = true; |
| 373 | else if (consume("PHDRS")) | 404 | else if (consume("PHDRS")) |
| 374 | PhdrCmd.HasPhdrs = true; | 405 | Cmd.HasPhdrs = true; |
| 375 | else if (consume("AT")) | 406 | else if (consume("AT")) |
| 376 | PhdrCmd.LMAExpr = readParenExpr(); | 407 | Cmd.LMAExpr = readParenExpr(); |
| 377 | else if (consume("FLAGS")) | 408 | else if (consume("FLAGS")) |
| 378 | PhdrCmd.Flags = readParenExpr()().getValue(); | 409 | Cmd.Flags = readParenExpr()().getValue(); |
| 379 | else | 410 | else |
| 380 | setError("unexpected header attribute: " + next()); | 411 | setError("unexpected header attribute: " + next()); |
| 381 | } | 412 | } |
| 413 | |||
| 414 | Script->PhdrsCommands.push_back(Cmd); | ||
| 382 | } | 415 | } |
| 383 | } | 416 | } |
| 384 | 417 | ||
| 418 | void ScriptParser::readRegionAlias() { | ||
| 419 | expect("("); | ||
| 420 | StringRef Alias = unquote(next()); | ||
| 421 | expect(","); | ||
| 422 | StringRef Name = next(); | ||
| 423 | expect(")"); | ||
| 424 | |||
| 425 | if (Script->MemoryRegions.count(Alias)) | ||
| 426 | setError("redefinition of memory region '" + Alias + "'"); | ||
| 427 | if (!Script->MemoryRegions.count(Name)) | ||
| 428 | setError("memory region '" + Name + "' is not defined"); | ||
| 429 | Script->MemoryRegions.insert({Alias, Script->MemoryRegions[Name]}); | ||
| 430 | } | ||
| 431 | |||
| 385 | void ScriptParser::readSearchDir() { | 432 | void ScriptParser::readSearchDir() { |
| 386 | expect("("); | 433 | expect("("); |
| 387 | StringRef Tok = next(); | 434 | StringRef Tok = next(); |
| ... | @@ -391,7 +438,7 @@ void ScriptParser::readSearchDir() { | ... | @@ -391,7 +438,7 @@ void ScriptParser::readSearchDir() { |
| 391 | } | 438 | } |
| 392 | 439 | ||
| 393 | void ScriptParser::readSections() { | 440 | void ScriptParser::readSections() { |
| 394 | Script->Opt.HasSections = true; | 441 | Script->HasSectionsCommand = true; |
| 395 | 442 | ||
| 396 | // -no-rosegment is used to avoid placing read only non-executable sections in | 443 | // -no-rosegment is used to avoid placing read only non-executable sections in |
| 397 | // their own segment. We do the same if SECTIONS command is present in linker | 444 | // their own segment. We do the same if SECTIONS command is present in linker |
| ... | @@ -399,7 +446,7 @@ void ScriptParser::readSections() { | ... | @@ -399,7 +446,7 @@ void ScriptParser::readSections() { |
| 399 | Config->SingleRoRx = true; | 446 | Config->SingleRoRx = true; |
| 400 | 447 | ||
| 401 | expect("{"); | 448 | expect("{"); |
| 402 | while (!Error && !consume("}")) { | 449 | while (!errorCount() && !consume("}")) { |
| 403 | StringRef Tok = next(); | 450 | StringRef Tok = next(); |
| 404 | BaseCommand *Cmd = readProvideOrAssignment(Tok); | 451 | BaseCommand *Cmd = readProvideOrAssignment(Tok); |
| 405 | if (!Cmd) { | 452 | if (!Cmd) { |
| ... | @@ -408,7 +455,7 @@ void ScriptParser::readSections() { | ... | @@ -408,7 +455,7 @@ void ScriptParser::readSections() { |
| 408 | else | 455 | else |
| 409 | Cmd = readOutputSectionDescription(Tok); | 456 | Cmd = readOutputSectionDescription(Tok); |
| 410 | } | 457 | } |
| 411 | Script->Opt.Commands.push_back(Cmd); | 458 | Script->SectionCommands.push_back(Cmd); |
| 412 | } | 459 | } |
| 413 | } | 460 | } |
| 414 | 461 | ||
| ... | @@ -424,7 +471,7 @@ static int precedence(StringRef Op) { | ... | @@ -424,7 +471,7 @@ static int precedence(StringRef Op) { |
| 424 | 471 | ||
| 425 | StringMatcher ScriptParser::readFilePatterns() { | 472 | StringMatcher ScriptParser::readFilePatterns() { |
| 426 | std::vector<StringRef> V; | 473 | std::vector<StringRef> V; |
| 427 | while (!Error && !consume(")")) | 474 | while (!errorCount() && !consume(")")) |
| 428 | V.push_back(next()); | 475 | V.push_back(next()); |
| 429 | return StringMatcher(V); | 476 | return StringMatcher(V); |
| 430 | } | 477 | } |
| ... | @@ -456,7 +503,7 @@ SortSectionPolicy ScriptParser::readSortKind() { | ... | @@ -456,7 +503,7 @@ SortSectionPolicy ScriptParser::readSortKind() { |
| 456 | // any file but a.o, and section .baz in any file but b.o. | 503 | // any file but a.o, and section .baz in any file but b.o. |
| 457 | std::vector<SectionPattern> ScriptParser::readInputSectionsList() { | 504 | std::vector<SectionPattern> ScriptParser::readInputSectionsList() { |
| 458 | std::vector<SectionPattern> Ret; | 505 | std::vector<SectionPattern> Ret; |
| 459 | while (!Error && peek() != ")") { | 506 | while (!errorCount() && peek() != ")") { |
| 460 | StringMatcher ExcludeFilePat; | 507 | StringMatcher ExcludeFilePat; |
| 461 | if (consume("EXCLUDE_FILE")) { | 508 | if (consume("EXCLUDE_FILE")) { |
| 462 | expect("("); | 509 | expect("("); |
| ... | @@ -464,7 +511,7 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() { | ... | @@ -464,7 +511,7 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() { |
| 464 | } | 511 | } |
| 465 | 512 | ||
| 466 | std::vector<StringRef> V; | 513 | std::vector<StringRef> V; |
| 467 | while (!Error && peek() != ")" && peek() != "EXCLUDE_FILE") | 514 | while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE") |
| 468 | V.push_back(next()); | 515 | V.push_back(next()); |
| 469 | 516 | ||
| 470 | if (!V.empty()) | 517 | if (!V.empty()) |
| ... | @@ -491,7 +538,7 @@ ScriptParser::readInputSectionRules(StringRef FilePattern) { | ... | @@ -491,7 +538,7 @@ ScriptParser::readInputSectionRules(StringRef FilePattern) { |
| 491 | auto *Cmd = make<InputSectionDescription>(FilePattern); | 538 | auto *Cmd = make<InputSectionDescription>(FilePattern); |
| 492 | expect("("); | 539 | expect("("); |
| 493 | 540 | ||
| 494 | while (!Error && !consume(")")) { | 541 | while (!errorCount() && !consume(")")) { |
| 495 | SortSectionPolicy Outer = readSortKind(); | 542 | SortSectionPolicy Outer = readSortKind(); |
| 496 | SortSectionPolicy Inner = SortSectionPolicy::Default; | 543 | SortSectionPolicy Inner = SortSectionPolicy::Default; |
| 497 | std::vector<SectionPattern> V; | 544 | std::vector<SectionPattern> V; |
| ... | @@ -529,7 +576,7 @@ ScriptParser::readInputSectionDescription(StringRef Tok) { | ... | @@ -529,7 +576,7 @@ ScriptParser::readInputSectionDescription(StringRef Tok) { |
| 529 | StringRef FilePattern = next(); | 576 | StringRef FilePattern = next(); |
| 530 | InputSectionDescription *Cmd = readInputSectionRules(FilePattern); | 577 | InputSectionDescription *Cmd = readInputSectionRules(FilePattern); |
| 531 | expect(")"); | 578 | expect(")"); |
| 532 | Script->Opt.KeptSections.push_back(Cmd); | 579 | Script->KeptSections.push_back(Cmd); |
| 533 | return Cmd; | 580 | return Cmd; |
| 534 | } | 581 | } |
| 535 | return readInputSectionRules(Tok); | 582 | return readInputSectionRules(Tok); |
| ... | @@ -579,7 +626,7 @@ uint32_t ScriptParser::readFill() { | ... | @@ -579,7 +626,7 @@ uint32_t ScriptParser::readFill() { |
| 579 | // | 626 | // |
| 580 | // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html | 627 | // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html |
| 581 | // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html | 628 | // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html |
| 582 | void ScriptParser::readSectionAddressType(OutputSectionCommand *Cmd) { | 629 | void ScriptParser::readSectionAddressType(OutputSection *Cmd) { |
| 583 | if (consume("(")) { | 630 | if (consume("(")) { |
| 584 | if (consume("NOLOAD")) { | 631 | if (consume("NOLOAD")) { |
| 585 | expect(")"); | 632 | expect(")"); |
| ... | @@ -599,21 +646,32 @@ void ScriptParser::readSectionAddressType(OutputSectionCommand *Cmd) { | ... | @@ -599,21 +646,32 @@ void ScriptParser::readSectionAddressType(OutputSectionCommand *Cmd) { |
| 599 | } | 646 | } |
| 600 | } | 647 | } |
| 601 | 648 | ||
| 602 | OutputSectionCommand * | 649 | static Expr checkAlignment(Expr E, std::string &Loc) { |
| 603 | ScriptParser::readOutputSectionDescription(StringRef OutSec) { | 650 | return [=] { |
| 604 | OutputSectionCommand *Cmd = | 651 | uint64_t Alignment = std::max((uint64_t)1, E().getValue()); |
| 605 | Script->createOutputSectionCommand(OutSec, getCurrentLocation()); | 652 | if (!isPowerOf2_64(Alignment)) { |
| 653 | error(Loc + ": alignment must be power of 2"); | ||
| 654 | return (uint64_t)1; // Return a dummy value. | ||
| 655 | } | ||
| 656 | return Alignment; | ||
| 657 | }; | ||
| 658 | } | ||
| 659 | |||
| 660 | OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) { | ||
| 661 | OutputSection *Cmd = | ||
| 662 | Script->createOutputSection(OutSec, getCurrentLocation()); | ||
| 606 | 663 | ||
| 607 | if (peek() != ":") | 664 | if (peek() != ":") |
| 608 | readSectionAddressType(Cmd); | 665 | readSectionAddressType(Cmd); |
| 609 | expect(":"); | 666 | expect(":"); |
| 610 | 667 | ||
| 668 | std::string Location = getCurrentLocation(); | ||
| 611 | if (consume("AT")) | 669 | if (consume("AT")) |
| 612 | Cmd->LMAExpr = readParenExpr(); | 670 | Cmd->LMAExpr = readParenExpr(); |
| 613 | if (consume("ALIGN")) | 671 | if (consume("ALIGN")) |
| 614 | Cmd->AlignExpr = readParenExpr(); | 672 | Cmd->AlignExpr = checkAlignment(readParenExpr(), Location); |
| 615 | if (consume("SUBALIGN")) | 673 | if (consume("SUBALIGN")) |
| 616 | Cmd->SubalignExpr = readParenExpr(); | 674 | Cmd->SubalignExpr = checkAlignment(readParenExpr(), Location); |
| 617 | 675 | ||
| 618 | // Parse constraints. | 676 | // Parse constraints. |
| 619 | if (consume("ONLY_IF_RO")) | 677 | if (consume("ONLY_IF_RO")) |
| ... | @@ -622,16 +680,16 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) { | ... | @@ -622,16 +680,16 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) { |
| 622 | Cmd->Constraint = ConstraintKind::ReadWrite; | 680 | Cmd->Constraint = ConstraintKind::ReadWrite; |
| 623 | expect("{"); | 681 | expect("{"); |
| 624 | 682 | ||
| 625 | while (!Error && !consume("}")) { | 683 | while (!errorCount() && !consume("}")) { |
| 626 | StringRef Tok = next(); | 684 | StringRef Tok = next(); |
| 627 | if (Tok == ";") { | 685 | if (Tok == ";") { |
| 628 | // Empty commands are allowed. Do nothing here. | 686 | // Empty commands are allowed. Do nothing here. |
| 629 | } else if (SymbolAssignment *Assign = readProvideOrAssignment(Tok)) { | 687 | } else if (SymbolAssignment *Assign = readProvideOrAssignment(Tok)) { |
| 630 | Cmd->Commands.push_back(Assign); | 688 | Cmd->SectionCommands.push_back(Assign); |
| 631 | } else if (BytesDataCommand *Data = readBytesDataCommand(Tok)) { | 689 | } else if (ByteCommand *Data = readByteCommand(Tok)) { |
| 632 | Cmd->Commands.push_back(Data); | 690 | Cmd->SectionCommands.push_back(Data); |
| 633 | } else if (Tok == "ASSERT") { | 691 | } else if (Tok == "ASSERT") { |
| 634 | Cmd->Commands.push_back(readAssert()); | 692 | Cmd->SectionCommands.push_back(readAssert()); |
| 635 | expect(";"); | 693 | expect(";"); |
| 636 | } else if (Tok == "CONSTRUCTORS") { | 694 | } else if (Tok == "CONSTRUCTORS") { |
| 637 | // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors | 695 | // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors |
| ... | @@ -642,7 +700,7 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) { | ... | @@ -642,7 +700,7 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) { |
| 642 | } else if (Tok == "SORT") { | 700 | } else if (Tok == "SORT") { |
| 643 | readSort(); | 701 | readSort(); |
| 644 | } else if (peek() == "(") { | 702 | } else if (peek() == "(") { |
| 645 | Cmd->Commands.push_back(readInputSectionDescription(Tok)); | 703 | Cmd->SectionCommands.push_back(readInputSectionDescription(Tok)); |
| 646 | } else { | 704 | } else { |
| 647 | setError("unknown command " + Tok); | 705 | setError("unknown command " + Tok); |
| 648 | } | 706 | } |
| ... | @@ -712,7 +770,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { | ... | @@ -712,7 +770,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { |
| 712 | Expr E = readExpr(); | 770 | Expr E = readExpr(); |
| 713 | if (Op == "+=") { | 771 | if (Op == "+=") { |
| 714 | std::string Loc = getCurrentLocation(); | 772 | std::string Loc = getCurrentLocation(); |
| 715 | E = [=] { return add(Script->getSymbolValue(Loc, Name), E()); }; | 773 | E = [=] { return add(Script->getSymbolValue(Name, Loc), E()); }; |
| 716 | } | 774 | } |
| 717 | return make<SymbolAssignment>(Name, E, getCurrentLocation()); | 775 | return make<SymbolAssignment>(Name, E, getCurrentLocation()); |
| 718 | } | 776 | } |
| ... | @@ -764,7 +822,7 @@ static Expr combine(StringRef Op, Expr L, Expr R) { | ... | @@ -764,7 +822,7 @@ static Expr combine(StringRef Op, Expr L, Expr R) { |
| 764 | // This is a part of the operator-precedence parser. This function | 822 | // This is a part of the operator-precedence parser. This function |
| 765 | // assumes that the remaining token stream starts with an operator. | 823 | // assumes that the remaining token stream starts with an operator. |
| 766 | Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { | 824 | Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { |
| 767 | while (!atEOF() && !Error) { | 825 | while (!atEOF() && !errorCount()) { |
| 768 | // Read an operator and an expression. | 826 | // Read an operator and an expression. |
| 769 | if (consume("?")) | 827 | if (consume("?")) |
| 770 | return readTernary(Lhs); | 828 | return readTernary(Lhs); |
| ... | @@ -790,13 +848,24 @@ Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { | ... | @@ -790,13 +848,24 @@ Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { |
| 790 | return Lhs; | 848 | return Lhs; |
| 791 | } | 849 | } |
| 792 | 850 | ||
| 793 | uint64_t static getConstant(StringRef S) { | 851 | Expr ScriptParser::getPageSize() { |
| 852 | std::string Location = getCurrentLocation(); | ||
| 853 | return [=]() -> uint64_t { | ||
| 854 | if (Target) | ||
| 855 | return Target->PageSize; | ||
| 856 | error(Location + ": unable to calculate page size"); | ||
| 857 | return 4096; // Return a dummy value. | ||
| 858 | }; | ||
| 859 | } | ||
| 860 | |||
| 861 | Expr ScriptParser::readConstant() { | ||
| 862 | StringRef S = readParenLiteral(); | ||
| 794 | if (S == "COMMONPAGESIZE") | 863 | if (S == "COMMONPAGESIZE") |
| 795 | return Target->PageSize; | 864 | return getPageSize(); |
| 796 | if (S == "MAXPAGESIZE") | 865 | if (S == "MAXPAGESIZE") |
| 797 | return Config->MaxPageSize; | 866 | return [] { return Config->MaxPageSize; }; |
| 798 | error("unknown constant: " + S); | 867 | setError("unknown constant: " + S); |
| 799 | return 0; | 868 | return {}; |
| 800 | } | 869 | } |
| 801 | 870 | ||
| 802 | // Parses Tok as an integer. It recognizes hexadecimal (prefixed with | 871 | // Parses Tok as an integer. It recognizes hexadecimal (prefixed with |
| ... | @@ -812,10 +881,16 @@ static Optional<uint64_t> parseInt(StringRef Tok) { | ... | @@ -812,10 +881,16 @@ static Optional<uint64_t> parseInt(StringRef Tok) { |
| 812 | 881 | ||
| 813 | // Hexadecimal | 882 | // Hexadecimal |
| 814 | uint64_t Val; | 883 | uint64_t Val; |
| 815 | if (Tok.startswith_lower("0x") && to_integer(Tok.substr(2), Val, 16)) | 884 | if (Tok.startswith_lower("0x")) { |
| 885 | if (!to_integer(Tok.substr(2), Val, 16)) | ||
| 886 | return None; | ||
| 816 | return Val; | 887 | return Val; |
| 817 | if (Tok.endswith_lower("H") && to_integer(Tok.drop_back(), Val, 16)) | 888 | } |
| 889 | if (Tok.endswith_lower("H")) { | ||
| 890 | if (!to_integer(Tok.drop_back(), Val, 16)) | ||
| 891 | return None; | ||
| 818 | return Val; | 892 | return Val; |
| 893 | } | ||
| 819 | 894 | ||
| 820 | // Decimal | 895 | // Decimal |
| 821 | if (Tok.endswith_lower("K")) { | 896 | if (Tok.endswith_lower("K")) { |
| ... | @@ -833,7 +908,7 @@ static Optional<uint64_t> parseInt(StringRef Tok) { | ... | @@ -833,7 +908,7 @@ static Optional<uint64_t> parseInt(StringRef Tok) { |
| 833 | return Val; | 908 | return Val; |
| 834 | } | 909 | } |
| 835 | 910 | ||
| 836 | BytesDataCommand *ScriptParser::readBytesDataCommand(StringRef Tok) { | 911 | ByteCommand *ScriptParser::readByteCommand(StringRef Tok) { |
| 837 | int Size = StringSwitch<int>(Tok) | 912 | int Size = StringSwitch<int>(Tok) |
| 838 | .Case("BYTE", 1) | 913 | .Case("BYTE", 1) |
| 839 | .Case("SHORT", 2) | 914 | .Case("SHORT", 2) |
| ... | @@ -842,8 +917,7 @@ BytesDataCommand *ScriptParser::readBytesDataCommand(StringRef Tok) { | ... | @@ -842,8 +917,7 @@ BytesDataCommand *ScriptParser::readBytesDataCommand(StringRef Tok) { |
| 842 | .Default(-1); | 917 | .Default(-1); |
| 843 | if (Size == -1) | 918 | if (Size == -1) |
| 844 | return nullptr; | 919 | return nullptr; |
| 845 | 920 | return make<ByteCommand>(readParenExpr(), Size); | |
| 846 | return make<BytesDataCommand>(readParenExpr(), Size); | ||
| 847 | } | 921 | } |
| 848 | 922 | ||
| 849 | StringRef ScriptParser::readParenLiteral() { | 923 | StringRef ScriptParser::readParenLiteral() { |
| ... | @@ -853,14 +927,9 @@ StringRef ScriptParser::readParenLiteral() { | ... | @@ -853,14 +927,9 @@ StringRef ScriptParser::readParenLiteral() { |
| 853 | return Tok; | 927 | return Tok; |
| 854 | } | 928 | } |
| 855 | 929 | ||
| 856 | OutputSection *ScriptParser::checkSection(OutputSectionCommand *Cmd, | 930 | static void checkIfExists(OutputSection *Cmd, StringRef Location) { |
| 857 | StringRef Location) { | ||
| 858 | if (Cmd->Location.empty() && Script->ErrorOnMissingSection) | 931 | if (Cmd->Location.empty() && Script->ErrorOnMissingSection) |
| 859 | error(Location + ": undefined section " + Cmd->Name); | 932 | error(Location + ": undefined section " + Cmd->Name); |
| 860 | if (Cmd->Sec) | ||
| 861 | return Cmd->Sec; | ||
| 862 | static OutputSection Dummy("", 0, 0); | ||
| 863 | return &Dummy; | ||
| 864 | } | 933 | } |
| 865 | 934 | ||
| 866 | Expr ScriptParser::readPrimary() { | 935 | Expr ScriptParser::readPrimary() { |
| ... | @@ -871,6 +940,10 @@ Expr ScriptParser::readPrimary() { | ... | @@ -871,6 +940,10 @@ Expr ScriptParser::readPrimary() { |
| 871 | Expr E = readPrimary(); | 940 | Expr E = readPrimary(); |
| 872 | return [=] { return ~E().getValue(); }; | 941 | return [=] { return ~E().getValue(); }; |
| 873 | } | 942 | } |
| 943 | if (consume("!")) { | ||
| 944 | Expr E = readPrimary(); | ||
| 945 | return [=] { return !E().getValue(); }; | ||
| 946 | } | ||
| 874 | if (consume("-")) { | 947 | if (consume("-")) { |
| 875 | Expr E = readPrimary(); | 948 | Expr E = readPrimary(); |
| 876 | return [=] { return -E().getValue(); }; | 949 | return [=] { return -E().getValue(); }; |
| ... | @@ -891,18 +964,21 @@ Expr ScriptParser::readPrimary() { | ... | @@ -891,18 +964,21 @@ Expr ScriptParser::readPrimary() { |
| 891 | } | 964 | } |
| 892 | if (Tok == "ADDR") { | 965 | if (Tok == "ADDR") { |
| 893 | StringRef Name = readParenLiteral(); | 966 | StringRef Name = readParenLiteral(); |
| 894 | OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name); | 967 | OutputSection *Sec = Script->getOrCreateOutputSection(Name); |
| 895 | return [=]() -> ExprValue { | 968 | return [=]() -> ExprValue { |
| 896 | return {checkSection(Cmd, Location), 0, Location}; | 969 | checkIfExists(Sec, Location); |
| 970 | return {Sec, false, 0, Location}; | ||
| 897 | }; | 971 | }; |
| 898 | } | 972 | } |
| 899 | if (Tok == "ALIGN") { | 973 | if (Tok == "ALIGN") { |
| 900 | expect("("); | 974 | expect("("); |
| 901 | Expr E = readExpr(); | 975 | Expr E = readExpr(); |
| 902 | if (consume(")")) | 976 | if (consume(")")) { |
| 977 | E = checkAlignment(E, Location); | ||
| 903 | return [=] { return alignTo(Script->getDot(), E().getValue()); }; | 978 | return [=] { return alignTo(Script->getDot(), E().getValue()); }; |
| 979 | } | ||
| 904 | expect(","); | 980 | expect(","); |
| 905 | Expr E2 = readExpr(); | 981 | Expr E2 = checkAlignment(readExpr(), Location); |
| 906 | expect(")"); | 982 | expect(")"); |
| 907 | return [=] { | 983 | return [=] { |
| 908 | ExprValue V = E(); | 984 | ExprValue V = E(); |
| ... | @@ -912,22 +988,25 @@ Expr ScriptParser::readPrimary() { | ... | @@ -912,22 +988,25 @@ Expr ScriptParser::readPrimary() { |
| 912 | } | 988 | } |
| 913 | if (Tok == "ALIGNOF") { | 989 | if (Tok == "ALIGNOF") { |
| 914 | StringRef Name = readParenLiteral(); | 990 | StringRef Name = readParenLiteral(); |
| 915 | OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name); | 991 | OutputSection *Cmd = Script->getOrCreateOutputSection(Name); |
| 916 | return [=] { return checkSection(Cmd, Location)->Alignment; }; | 992 | return [=] { |
| 993 | checkIfExists(Cmd, Location); | ||
| 994 | return Cmd->Alignment; | ||
| 995 | }; | ||
| 917 | } | 996 | } |
| 918 | if (Tok == "ASSERT") | 997 | if (Tok == "ASSERT") |
| 919 | return readAssertExpr(); | 998 | return readAssertExpr(); |
| 920 | if (Tok == "CONSTANT") { | 999 | if (Tok == "CONSTANT") |
| 921 | StringRef Name = readParenLiteral(); | 1000 | return readConstant(); |
| 922 | return [=] { return getConstant(Name); }; | ||
| 923 | } | ||
| 924 | if (Tok == "DATA_SEGMENT_ALIGN") { | 1001 | if (Tok == "DATA_SEGMENT_ALIGN") { |
| 925 | expect("("); | 1002 | expect("("); |
| 926 | Expr E = readExpr(); | 1003 | Expr E = readExpr(); |
| 927 | expect(","); | 1004 | expect(","); |
| 928 | readExpr(); | 1005 | readExpr(); |
| 929 | expect(")"); | 1006 | expect(")"); |
| 930 | return [=] { return alignTo(Script->getDot(), E().getValue()); }; | 1007 | return [=] { |
| 1008 | return alignTo(Script->getDot(), std::max((uint64_t)1, E().getValue())); | ||
| 1009 | }; | ||
| 931 | } | 1010 | } |
| 932 | if (Tok == "DATA_SEGMENT_END") { | 1011 | if (Tok == "DATA_SEGMENT_END") { |
| 933 | expect("("); | 1012 | expect("("); |
| ... | @@ -944,28 +1023,32 @@ Expr ScriptParser::readPrimary() { | ... | @@ -944,28 +1023,32 @@ Expr ScriptParser::readPrimary() { |
| 944 | expect(","); | 1023 | expect(","); |
| 945 | readExpr(); | 1024 | readExpr(); |
| 946 | expect(")"); | 1025 | expect(")"); |
| 947 | return [] { return alignTo(Script->getDot(), Target->PageSize); }; | 1026 | Expr E = getPageSize(); |
| 1027 | return [=] { return alignTo(Script->getDot(), E().getValue()); }; | ||
| 948 | } | 1028 | } |
| 949 | if (Tok == "DEFINED") { | 1029 | if (Tok == "DEFINED") { |
| 950 | StringRef Name = readParenLiteral(); | 1030 | StringRef Name = readParenLiteral(); |
| 951 | return [=] { return Script->isDefined(Name) ? 1 : 0; }; | 1031 | return [=] { return Symtab->find(Name) ? 1 : 0; }; |
| 952 | } | 1032 | } |
| 953 | if (Tok == "LENGTH") { | 1033 | if (Tok == "LENGTH") { |
| 954 | StringRef Name = readParenLiteral(); | 1034 | StringRef Name = readParenLiteral(); |
| 955 | if (Script->Opt.MemoryRegions.count(Name) == 0) | 1035 | if (Script->MemoryRegions.count(Name) == 0) |
| 956 | setError("memory region not defined: " + Name); | 1036 | setError("memory region not defined: " + Name); |
| 957 | return [=] { return Script->Opt.MemoryRegions[Name].Length; }; | 1037 | return [=] { return Script->MemoryRegions[Name]->Length; }; |
| 958 | } | 1038 | } |
| 959 | if (Tok == "LOADADDR") { | 1039 | if (Tok == "LOADADDR") { |
| 960 | StringRef Name = readParenLiteral(); | 1040 | StringRef Name = readParenLiteral(); |
| 961 | OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name); | 1041 | OutputSection *Cmd = Script->getOrCreateOutputSection(Name); |
| 962 | return [=] { return checkSection(Cmd, Location)->getLMA(); }; | 1042 | return [=] { |
| 1043 | checkIfExists(Cmd, Location); | ||
| 1044 | return Cmd->getLMA(); | ||
| 1045 | }; | ||
| 963 | } | 1046 | } |
| 964 | if (Tok == "ORIGIN") { | 1047 | if (Tok == "ORIGIN") { |
| 965 | StringRef Name = readParenLiteral(); | 1048 | StringRef Name = readParenLiteral(); |
| 966 | if (Script->Opt.MemoryRegions.count(Name) == 0) | 1049 | if (Script->MemoryRegions.count(Name) == 0) |
| 967 | setError("memory region not defined: " + Name); | 1050 | setError("memory region not defined: " + Name); |
| 968 | return [=] { return Script->Opt.MemoryRegions[Name].Origin; }; | 1051 | return [=] { return Script->MemoryRegions[Name]->Origin; }; |
| 969 | } | 1052 | } |
| 970 | if (Tok == "SEGMENT_START") { | 1053 | if (Tok == "SEGMENT_START") { |
| 971 | expect("("); | 1054 | expect("("); |
| ... | @@ -977,18 +1060,18 @@ Expr ScriptParser::readPrimary() { | ... | @@ -977,18 +1060,18 @@ Expr ScriptParser::readPrimary() { |
| 977 | } | 1060 | } |
| 978 | if (Tok == "SIZEOF") { | 1061 | if (Tok == "SIZEOF") { |
| 979 | StringRef Name = readParenLiteral(); | 1062 | StringRef Name = readParenLiteral(); |
| 980 | OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name); | 1063 | OutputSection *Cmd = Script->getOrCreateOutputSection(Name); |
| 981 | // Linker script does not create an output section if its content is empty. | 1064 | // Linker script does not create an output section if its content is empty. |
| 982 | // We want to allow SIZEOF(.foo) where .foo is a section which happened to | 1065 | // We want to allow SIZEOF(.foo) where .foo is a section which happened to |
| 983 | // be empty. | 1066 | // be empty. |
| 984 | return [=] { return Cmd->Sec ? Cmd->Sec->Size : 0; }; | 1067 | return [=] { return Cmd->Size; }; |
| 985 | } | 1068 | } |
| 986 | if (Tok == "SIZEOF_HEADERS") | 1069 | if (Tok == "SIZEOF_HEADERS") |
| 987 | return [=] { return elf::getHeaderSize(); }; | 1070 | return [=] { return elf::getHeaderSize(); }; |
| 988 | 1071 | ||
| 989 | // Tok is the dot. | 1072 | // Tok is the dot. |
| 990 | if (Tok == ".") | 1073 | if (Tok == ".") |
| 991 | return [=] { return Script->getSymbolValue(Location, Tok); }; | 1074 | return [=] { return Script->getSymbolValue(Tok, Location); }; |
| 992 | 1075 | ||
| 993 | // Tok is a literal number. | 1076 | // Tok is a literal number. |
| 994 | if (Optional<uint64_t> Val = parseInt(Tok)) | 1077 | if (Optional<uint64_t> Val = parseInt(Tok)) |
| ... | @@ -997,8 +1080,8 @@ Expr ScriptParser::readPrimary() { | ... | @@ -997,8 +1080,8 @@ Expr ScriptParser::readPrimary() { |
| 997 | // Tok is a symbol name. | 1080 | // Tok is a symbol name. |
| 998 | if (!isValidCIdentifier(Tok)) | 1081 | if (!isValidCIdentifier(Tok)) |
| 999 | setError("malformed number: " + Tok); | 1082 | setError("malformed number: " + Tok); |
| 1000 | Script->Opt.ReferencedSymbols.push_back(Tok); | 1083 | Script->ReferencedSymbols.push_back(Tok); |
| 1001 | return [=] { return Script->getSymbolValue(Location, Tok); }; | 1084 | return [=] { return Script->getSymbolValue(Tok, Location); }; |
| 1002 | } | 1085 | } |
| 1003 | 1086 | ||
| 1004 | Expr ScriptParser::readTernary(Expr Cond) { | 1087 | Expr ScriptParser::readTernary(Expr Cond) { |
| ... | @@ -1017,7 +1100,7 @@ Expr ScriptParser::readParenExpr() { | ... | @@ -1017,7 +1100,7 @@ Expr ScriptParser::readParenExpr() { |
| 1017 | 1100 | ||
| 1018 | std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() { | 1101 | std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() { |
| 1019 | std::vector<StringRef> Phdrs; | 1102 | std::vector<StringRef> Phdrs; |
| 1020 | while (!Error && peek().startswith(":")) { | 1103 | while (!errorCount() && peek().startswith(":")) { |
| 1021 | StringRef Tok = next(); | 1104 | StringRef Tok = next(); |
| 1022 | Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1)); | 1105 | Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1)); |
| 1023 | } | 1106 | } |
| ... | @@ -1120,7 +1203,7 @@ ScriptParser::readSymbols() { | ... | @@ -1120,7 +1203,7 @@ ScriptParser::readSymbols() { |
| 1120 | std::vector<SymbolVersion> Globals; | 1203 | std::vector<SymbolVersion> Globals; |
| 1121 | std::vector<SymbolVersion> *V = &Globals; | 1204 | std::vector<SymbolVersion> *V = &Globals; |
| 1122 | 1205 | ||
| 1123 | while (!Error) { | 1206 | while (!errorCount()) { |
| 1124 | if (consume("}")) | 1207 | if (consume("}")) |
| 1125 | break; | 1208 | break; |
| 1126 | if (consumeLabel("local")) { | 1209 | if (consumeLabel("local")) { |
| ... | @@ -1154,7 +1237,7 @@ std::vector<SymbolVersion> ScriptParser::readVersionExtern() { | ... | @@ -1154,7 +1237,7 @@ std::vector<SymbolVersion> ScriptParser::readVersionExtern() { |
| 1154 | expect("{"); | 1237 | expect("{"); |
| 1155 | 1238 | ||
| 1156 | std::vector<SymbolVersion> Ret; | 1239 | std::vector<SymbolVersion> Ret; |
| 1157 | while (!Error && peek() != "}") { | 1240 | while (!errorCount() && peek() != "}") { |
| 1158 | StringRef Tok = next(); | 1241 | StringRef Tok = next(); |
| 1159 | bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok); | 1242 | bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok); |
| 1160 | Ret.push_back({unquote(Tok), IsCXX, HasWildcard}); | 1243 | Ret.push_back({unquote(Tok), IsCXX, HasWildcard}); |
| ... | @@ -1181,7 +1264,7 @@ uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2, | ... | @@ -1181,7 +1264,7 @@ uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2, |
| 1181 | // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... } | 1264 | // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... } |
| 1182 | void ScriptParser::readMemory() { | 1265 | void ScriptParser::readMemory() { |
| 1183 | expect("{"); | 1266 | expect("{"); |
| 1184 | while (!Error && !consume("}")) { | 1267 | while (!errorCount() && !consume("}")) { |
| 1185 | StringRef Name = next(); | 1268 | StringRef Name = next(); |
| 1186 | 1269 | ||
| 1187 | uint32_t Flags = 0; | 1270 | uint32_t Flags = 0; |
| ... | @@ -1196,12 +1279,12 @@ void ScriptParser::readMemory() { | ... | @@ -1196,12 +1279,12 @@ void ScriptParser::readMemory() { |
| 1196 | expect(","); | 1279 | expect(","); |
| 1197 | uint64_t Length = readMemoryAssignment("LENGTH", "len", "l"); | 1280 | uint64_t Length = readMemoryAssignment("LENGTH", "len", "l"); |
| 1198 | 1281 | ||
| 1199 | // Add the memory region to the region map (if it doesn't already exist). | 1282 | // Add the memory region to the region map. |
| 1200 | auto It = Script->Opt.MemoryRegions.find(Name); | 1283 | if (Script->MemoryRegions.count(Name)) |
| 1201 | if (It != Script->Opt.MemoryRegions.end()) | ||
| 1202 | setError("region '" + Name + "' already defined"); | 1284 | setError("region '" + Name + "' already defined"); |
| 1203 | else | 1285 | MemoryRegion *MR = make<MemoryRegion>(); |
| 1204 | Script->Opt.MemoryRegions[Name] = {Name, Origin, Length, Flags, NegFlags}; | 1286 | *MR = {Name, Origin, Length, Flags, NegFlags}; |
| 1287 | Script->MemoryRegions[Name] = MR; | ||
| 1205 | } | 1288 | } |
| 1206 | } | 1289 | } |
| 1207 | 1290 | ||
| ... | @@ -1245,3 +1328,7 @@ void elf::readVersionScript(MemoryBufferRef MB) { | ... | @@ -1245,3 +1328,7 @@ void elf::readVersionScript(MemoryBufferRef MB) { |
| 1245 | void elf::readDynamicList(MemoryBufferRef MB) { | 1328 | void elf::readDynamicList(MemoryBufferRef MB) { |
| 1246 | ScriptParser(MB).readDynamicList(); | 1329 | ScriptParser(MB).readDynamicList(); |
| 1247 | } | 1330 | } |
| 1331 | |||
| 1332 | void elf::readDefsym(StringRef Name, MemoryBufferRef MB) { | ||
| 1333 | ScriptParser(MB).readDefsym(Name); | ||
| 1334 | } |
deps/lld/ELF/ScriptParser.h+4-1| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_ELF_SCRIPT_PARSER_H | 10 | #ifndef LLD_ELF_SCRIPT_PARSER_H |
| 11 | #define LLD_ELF_SCRIPT_PARSER_H | 11 | #define LLD_ELF_SCRIPT_PARSER_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "llvm/Support/MemoryBuffer.h" | 14 | #include "llvm/Support/MemoryBuffer.h" |
| 15 | 15 | ||
| 16 | namespace lld { | 16 | namespace lld { |
| ... | @@ -25,6 +25,9 @@ void readVersionScript(MemoryBufferRef MB); | ... | @@ -25,6 +25,9 @@ void readVersionScript(MemoryBufferRef MB); |
| 25 | 25 | ||
| 26 | void readDynamicList(MemoryBufferRef MB); | 26 | void readDynamicList(MemoryBufferRef MB); |
| 27 | 27 | ||
| 28 | // Parses the defsym expression. | ||
| 29 | void readDefsym(StringRef Name, MemoryBufferRef MB); | ||
| 30 | |||
| 28 | } // namespace elf | 31 | } // namespace elf |
| 29 | } // namespace lld | 32 | } // namespace lld |
| 30 | 33 |
deps/lld/ELF/Strings.cpp+4-27| ... | @@ -9,7 +9,7 @@ | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | ||
| 10 | #include "Strings.h" | 10 | #include "Strings.h" |
| 11 | #include "Config.h" | 11 | #include "Config.h" |
| 12 | #include "Error.h" | 12 | #include "lld/Common/ErrorHandler.h" |
| 13 | #include "llvm/ADT/ArrayRef.h" | 13 | #include "llvm/ADT/ArrayRef.h" |
| 14 | #include "llvm/ADT/StringRef.h" | 14 | #include "llvm/ADT/StringRef.h" |
| 15 | #include "llvm/ADT/Twine.h" | 15 | #include "llvm/ADT/Twine.h" |
| ... | @@ -54,32 +54,9 @@ std::vector<uint8_t> elf::parseHex(StringRef S) { | ... | @@ -54,32 +54,9 @@ std::vector<uint8_t> elf::parseHex(StringRef S) { |
| 54 | return Hex; | 54 | return Hex; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static bool isAlpha(char C) { | ||
| 58 | return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_'; | ||
| 59 | } | ||
| 60 | |||
| 61 | static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); } | ||
| 62 | |||
| 63 | // Returns true if S is valid as a C language identifier. | 57 | // Returns true if S is valid as a C language identifier. |
| 64 | bool elf::isValidCIdentifier(StringRef S) { | 58 | bool elf::isValidCIdentifier(StringRef S) { |
| 65 | return !S.empty() && isAlpha(S[0]) && | 59 | return !S.empty() && (isAlpha(S[0]) || S[0] == '_') && |
| 66 | std::all_of(S.begin() + 1, S.end(), isAlnum); | 60 | std::all_of(S.begin() + 1, S.end(), |
| 67 | } | 61 | [](char C) { return C == '_' || isAlnum(C); }); |
| 68 | |||
| 69 | // Returns the demangled C++ symbol name for Name. | ||
| 70 | Optional<std::string> elf::demangle(StringRef Name) { | ||
| 71 | // itaniumDemangle can be used to demangle strings other than symbol | ||
| 72 | // names which do not necessarily start with "_Z". Name can be | ||
| 73 | // either a C or C++ symbol. Don't call itaniumDemangle if the name | ||
| 74 | // does not look like a C++ symbol name to avoid getting unexpected | ||
| 75 | // result for a C symbol that happens to match a mangled type name. | ||
| 76 | if (!Name.startswith("_Z")) | ||
| 77 | return None; | ||
| 78 | |||
| 79 | char *Buf = itaniumDemangle(Name.str().c_str(), nullptr, nullptr, nullptr); | ||
| 80 | if (!Buf) | ||
| 81 | return None; | ||
| 82 | std::string S(Buf); | ||
| 83 | free(Buf); | ||
| 84 | return S; | ||
| 85 | } | 62 | } |
deps/lld/ELF/Strings.h+1-5| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_ELF_STRINGS_H | 10 | #ifndef LLD_ELF_STRINGS_H |
| 11 | #define LLD_ELF_STRINGS_H | 11 | #define LLD_ELF_STRINGS_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "llvm/ADT/ArrayRef.h" | 14 | #include "llvm/ADT/ArrayRef.h" |
| 15 | #include "llvm/ADT/BitVector.h" | 15 | #include "llvm/ADT/BitVector.h" |
| 16 | #include "llvm/ADT/Optional.h" | 16 | #include "llvm/ADT/Optional.h" |
| ... | @@ -66,10 +66,6 @@ private: | ... | @@ -66,10 +66,6 @@ private: |
| 66 | std::vector<llvm::GlobPattern> Patterns; | 66 | std::vector<llvm::GlobPattern> Patterns; |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | // Returns a demangled C++ symbol name. If Name is not a mangled | ||
| 70 | // name, it returns Optional::None. | ||
| 71 | llvm::Optional<std::string> demangle(StringRef Name); | ||
| 72 | |||
| 73 | inline ArrayRef<uint8_t> toArrayRef(StringRef S) { | 69 | inline ArrayRef<uint8_t> toArrayRef(StringRef S) { |
| 74 | return {(const uint8_t *)S.data(), S.size()}; | 70 | return {(const uint8_t *)S.data(), S.size()}; |
| 75 | } | 71 | } |
deps/lld/ELF/SymbolTable.cpp+339-286| ... | @@ -16,10 +16,12 @@ | ... | @@ -16,10 +16,12 @@ |
| 16 | 16 | ||
| 17 | #include "SymbolTable.h" | 17 | #include "SymbolTable.h" |
| 18 | #include "Config.h" | 18 | #include "Config.h" |
| 19 | #include "Error.h" | ||
| 20 | #include "LinkerScript.h" | 19 | #include "LinkerScript.h" |
| 21 | #include "Memory.h" | ||
| 22 | #include "Symbols.h" | 20 | #include "Symbols.h" |
| 21 | #include "SyntheticSections.h" | ||
| 22 | #include "lld/Common/ErrorHandler.h" | ||
| 23 | #include "lld/Common/Memory.h" | ||
| 24 | #include "lld/Common/Strings.h" | ||
| 23 | #include "llvm/ADT/STLExtras.h" | 25 | #include "llvm/ADT/STLExtras.h" |
| 24 | 26 | ||
| 25 | using namespace llvm; | 27 | using namespace llvm; |
| ... | @@ -29,11 +31,21 @@ using namespace llvm::ELF; | ... | @@ -29,11 +31,21 @@ using namespace llvm::ELF; |
| 29 | using namespace lld; | 31 | using namespace lld; |
| 30 | using namespace lld::elf; | 32 | using namespace lld::elf; |
| 31 | 33 | ||
| 34 | SymbolTable *elf::Symtab; | ||
| 35 | |||
| 36 | static InputFile *getFirstElf() { | ||
| 37 | if (!ObjectFiles.empty()) | ||
| 38 | return ObjectFiles[0]; | ||
| 39 | if (!SharedFiles.empty()) | ||
| 40 | return SharedFiles[0]; | ||
| 41 | return nullptr; | ||
| 42 | } | ||
| 43 | |||
| 32 | // All input object files must be for the same architecture | 44 | // All input object files must be for the same architecture |
| 33 | // (e.g. it does not make sense to link x86 object files with | 45 | // (e.g. it does not make sense to link x86 object files with |
| 34 | // MIPS object files.) This function checks for that error. | 46 | // MIPS object files.) This function checks for that error. |
| 35 | template <class ELFT> static bool isCompatible(InputFile *F) { | 47 | static bool isCompatible(InputFile *F) { |
| 36 | if (!isa<ELFFileBase<ELFT>>(F) && !isa<BitcodeFile>(F)) | 48 | if (!F->isElf() && !isa<BitcodeFile>(F)) |
| 37 | return true; | 49 | return true; |
| 38 | 50 | ||
| 39 | if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) { | 51 | if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) { |
| ... | @@ -46,22 +58,19 @@ template <class ELFT> static bool isCompatible(InputFile *F) { | ... | @@ -46,22 +58,19 @@ template <class ELFT> static bool isCompatible(InputFile *F) { |
| 46 | if (!Config->Emulation.empty()) | 58 | if (!Config->Emulation.empty()) |
| 47 | error(toString(F) + " is incompatible with " + Config->Emulation); | 59 | error(toString(F) + " is incompatible with " + Config->Emulation); |
| 48 | else | 60 | else |
| 49 | error(toString(F) + " is incompatible with " + toString(Config->FirstElf)); | 61 | error(toString(F) + " is incompatible with " + toString(getFirstElf())); |
| 50 | return false; | 62 | return false; |
| 51 | } | 63 | } |
| 52 | 64 | ||
| 53 | // Add symbols in File to the symbol table. | 65 | // Add symbols in File to the symbol table. |
| 54 | template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { | 66 | template <class ELFT> void SymbolTable::addFile(InputFile *File) { |
| 55 | if (!Config->FirstElf && isa<ELFFileBase<ELFT>>(File)) | 67 | if (!isCompatible(File)) |
| 56 | Config->FirstElf = File; | ||
| 57 | |||
| 58 | if (!isCompatible<ELFT>(File)) | ||
| 59 | return; | 68 | return; |
| 60 | 69 | ||
| 61 | // Binary file | 70 | // Binary file |
| 62 | if (auto *F = dyn_cast<BinaryFile>(File)) { | 71 | if (auto *F = dyn_cast<BinaryFile>(File)) { |
| 63 | BinaryFiles.push_back(F); | 72 | BinaryFiles.push_back(F); |
| 64 | F->parse<ELFT>(); | 73 | F->parse(); |
| 65 | return; | 74 | return; |
| 66 | } | 75 | } |
| 67 | 76 | ||
| ... | @@ -72,7 +81,7 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { | ... | @@ -72,7 +81,7 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { |
| 72 | } | 81 | } |
| 73 | 82 | ||
| 74 | // Lazy object file | 83 | // Lazy object file |
| 75 | if (auto *F = dyn_cast<LazyObjectFile>(File)) { | 84 | if (auto *F = dyn_cast<LazyObjFile>(File)) { |
| 76 | F->parse<ELFT>(); | 85 | F->parse<ELFT>(); |
| 77 | return; | 86 | return; |
| 78 | } | 87 | } |
| ... | @@ -84,7 +93,7 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { | ... | @@ -84,7 +93,7 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { |
| 84 | if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { | 93 | if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { |
| 85 | // DSOs are uniquified not by filename but by soname. | 94 | // DSOs are uniquified not by filename but by soname. |
| 86 | F->parseSoName(); | 95 | F->parseSoName(); |
| 87 | if (ErrorCount || !SoNames.insert(F->SoName).second) | 96 | if (errorCount() || !SoNames.insert(F->SoName).second) |
| 88 | return; | 97 | return; |
| 89 | SharedFiles.push_back(F); | 98 | SharedFiles.push_back(F); |
| 90 | F->parseRest(); | 99 | F->parseRest(); |
| ... | @@ -99,9 +108,8 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { | ... | @@ -99,9 +108,8 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { |
| 99 | } | 108 | } |
| 100 | 109 | ||
| 101 | // Regular object file | 110 | // Regular object file |
| 102 | auto *F = cast<ObjectFile<ELFT>>(File); | 111 | ObjectFiles.push_back(File); |
| 103 | ObjectFiles.push_back(F); | 112 | cast<ObjFile<ELFT>>(File)->parse(ComdatGroups); |
| 104 | F->parse(ComdatGroups); | ||
| 105 | } | 113 | } |
| 106 | 114 | ||
| 107 | // This function is where all the optimizations of link-time | 115 | // This function is where all the optimizations of link-time |
| ... | @@ -111,7 +119,7 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { | ... | @@ -111,7 +119,7 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { |
| 111 | // using LLVM functions and replaces bitcode symbols with the results. | 119 | // using LLVM functions and replaces bitcode symbols with the results. |
| 112 | // Because all bitcode files that consist of a program are passed | 120 | // Because all bitcode files that consist of a program are passed |
| 113 | // to the compiler at once, it can do whole-program optimization. | 121 | // to the compiler at once, it can do whole-program optimization. |
| 114 | template <class ELFT> void SymbolTable<ELFT>::addCombinedLTOObject() { | 122 | template <class ELFT> void SymbolTable::addCombinedLTOObject() { |
| 115 | if (BitcodeFiles.empty()) | 123 | if (BitcodeFiles.empty()) |
| 116 | return; | 124 | return; |
| 117 | 125 | ||
| ... | @@ -121,82 +129,76 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLTOObject() { | ... | @@ -121,82 +129,76 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLTOObject() { |
| 121 | LTO->add(*F); | 129 | LTO->add(*F); |
| 122 | 130 | ||
| 123 | for (InputFile *File : LTO->compile()) { | 131 | for (InputFile *File : LTO->compile()) { |
| 124 | ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File); | ||
| 125 | DenseSet<CachedHashStringRef> DummyGroups; | 132 | DenseSet<CachedHashStringRef> DummyGroups; |
| 126 | Obj->parse(DummyGroups); | 133 | cast<ObjFile<ELFT>>(File)->parse(DummyGroups); |
| 127 | ObjectFiles.push_back(Obj); | 134 | ObjectFiles.push_back(File); |
| 128 | } | 135 | } |
| 129 | } | 136 | } |
| 130 | 137 | ||
| 131 | template <class ELFT> | 138 | Defined *SymbolTable::addAbsolute(StringRef Name, uint8_t Visibility, |
| 132 | DefinedRegular *SymbolTable<ELFT>::addAbsolute(StringRef Name, | 139 | uint8_t Binding) { |
| 133 | uint8_t Visibility, | ||
| 134 | uint8_t Binding) { | ||
| 135 | Symbol *Sym = | 140 | Symbol *Sym = |
| 136 | addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, nullptr, nullptr); | 141 | addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, nullptr, nullptr); |
| 137 | return cast<DefinedRegular>(Sym->body()); | 142 | return cast<Defined>(Sym); |
| 138 | } | ||
| 139 | |||
| 140 | // Add Name as an "ignored" symbol. An ignored symbol is a regular | ||
| 141 | // linker-synthesized defined symbol, but is only defined if needed. | ||
| 142 | template <class ELFT> | ||
| 143 | DefinedRegular *SymbolTable<ELFT>::addIgnored(StringRef Name, | ||
| 144 | uint8_t Visibility) { | ||
| 145 | SymbolBody *S = find(Name); | ||
| 146 | if (!S || S->isInCurrentDSO()) | ||
| 147 | return nullptr; | ||
| 148 | return addAbsolute(Name, Visibility); | ||
| 149 | } | 143 | } |
| 150 | 144 | ||
| 151 | // Set a flag for --trace-symbol so that we can print out a log message | 145 | // Set a flag for --trace-symbol so that we can print out a log message |
| 152 | // if a new symbol with the same name is inserted into the symbol table. | 146 | // if a new symbol with the same name is inserted into the symbol table. |
| 153 | template <class ELFT> void SymbolTable<ELFT>::trace(StringRef Name) { | 147 | void SymbolTable::trace(StringRef Name) { |
| 154 | Symtab.insert({CachedHashStringRef(Name), {-1, true}}); | 148 | SymMap.insert({CachedHashStringRef(Name), -1}); |
| 155 | } | 149 | } |
| 156 | 150 | ||
| 157 | // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. | 151 | // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. |
| 158 | // Used to implement --wrap. | 152 | // Used to implement --wrap. |
| 159 | template <class ELFT> void SymbolTable<ELFT>::addSymbolWrap(StringRef Name) { | 153 | template <class ELFT> void SymbolTable::addSymbolWrap(StringRef Name) { |
| 160 | SymbolBody *B = find(Name); | 154 | Symbol *Sym = find(Name); |
| 161 | if (!B) | 155 | if (!Sym) |
| 162 | return; | 156 | return; |
| 163 | Symbol *Sym = B->symbol(); | 157 | Symbol *Real = addUndefined<ELFT>(Saver.save("__real_" + Name)); |
| 164 | Symbol *Real = addUndefined(Saver.save("__real_" + Name)); | 158 | Symbol *Wrap = addUndefined<ELFT>(Saver.save("__wrap_" + Name)); |
| 165 | Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); | 159 | WrappedSymbols.push_back({Sym, Real, Wrap}); |
| 166 | 160 | ||
| 167 | // Tell LTO not to eliminate this symbol | 161 | // We want to tell LTO not to inline symbols to be overwritten |
| 168 | Wrap->IsUsedInRegularObj = true; | 162 | // because LTO doesn't know the final symbol contents after renaming. |
| 169 | 163 | Real->CanInline = false; | |
| 170 | Config->RenamedSymbols[Real] = {Sym, Real->Binding}; | 164 | Sym->CanInline = false; |
| 171 | Config->RenamedSymbols[Sym] = {Wrap, Sym->Binding}; | ||
| 172 | } | ||
| 173 | |||
| 174 | // Creates alias for symbol. Used to implement --defsym=ALIAS=SYM. | ||
| 175 | template <class ELFT> | ||
| 176 | void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias, StringRef Name) { | ||
| 177 | SymbolBody *B = find(Name); | ||
| 178 | if (!B) { | ||
| 179 | error("-defsym: undefined symbol: " + Name); | ||
| 180 | return; | ||
| 181 | } | ||
| 182 | Symbol *Sym = B->symbol(); | ||
| 183 | Symbol *AliasSym = addUndefined(Alias); | ||
| 184 | 165 | ||
| 185 | // Tell LTO not to eliminate this symbol | 166 | // Tell LTO not to eliminate these symbols. |
| 186 | Sym->IsUsedInRegularObj = true; | 167 | Sym->IsUsedInRegularObj = true; |
| 187 | Config->RenamedSymbols[AliasSym] = {Sym, AliasSym->Binding}; | 168 | Wrap->IsUsedInRegularObj = true; |
| 188 | } | 169 | } |
| 189 | 170 | ||
| 190 | // Apply symbol renames created by -wrap and -defsym. The renames are created | 171 | // Apply symbol renames created by -wrap. The renames are created |
| 191 | // before LTO in addSymbolWrap() and addSymbolAlias() to have a chance to inform | 172 | // before LTO in addSymbolWrap() to have a chance to inform LTO (if |
| 192 | // LTO (if LTO is running) not to include these symbols in IPO. Now that the | 173 | // LTO is running) not to include these symbols in IPO. Now that the |
| 193 | // symbols are finalized, we can perform the replacement. | 174 | // symbols are finalized, we can perform the replacement. |
| 194 | template <class ELFT> void SymbolTable<ELFT>::applySymbolRenames() { | 175 | void SymbolTable::applySymbolWrap() { |
| 195 | for (auto &KV : Config->RenamedSymbols) { | 176 | // This function rotates 3 symbols: |
| 196 | Symbol *Dst = KV.first; | 177 | // |
| 197 | Symbol *Src = KV.second.Target; | 178 | // __real_sym becomes sym |
| 198 | Dst->body()->copy(Src->body()); | 179 | // sym becomes __wrap_sym |
| 199 | Dst->Binding = KV.second.OriginalBinding; | 180 | // __wrap_sym becomes __real_sym |
| 181 | // | ||
| 182 | // The last part is special in that we don't want to change what references to | ||
| 183 | // __wrap_sym point to, we just want have __real_sym in the symbol table. | ||
| 184 | |||
| 185 | for (WrappedSymbol &W : WrappedSymbols) { | ||
| 186 | // First, make a copy of __real_sym. | ||
| 187 | Symbol *Real = nullptr; | ||
| 188 | if (W.Real->isDefined()) { | ||
| 189 | Real = (Symbol *)make<SymbolUnion>(); | ||
| 190 | memcpy(Real, W.Real, sizeof(SymbolUnion)); | ||
| 191 | } | ||
| 192 | |||
| 193 | // Replace __real_sym with sym and sym with __wrap_sym. | ||
| 194 | memcpy(W.Real, W.Sym, sizeof(SymbolUnion)); | ||
| 195 | memcpy(W.Sym, W.Wrap, sizeof(SymbolUnion)); | ||
| 196 | |||
| 197 | // We now have two copies of __wrap_sym. Drop one. | ||
| 198 | W.Wrap->IsUsedInRegularObj = false; | ||
| 199 | |||
| 200 | if (Real) | ||
| 201 | SymVector.push_back(Real); | ||
| 200 | } | 202 | } |
| 201 | } | 203 | } |
| 202 | 204 | ||
| ... | @@ -209,48 +211,50 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { | ... | @@ -209,48 +211,50 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { |
| 209 | } | 211 | } |
| 210 | 212 | ||
| 211 | // Find an existing symbol or create and insert a new one. | 213 | // Find an existing symbol or create and insert a new one. |
| 212 | template <class ELFT> | 214 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { |
| 213 | std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) { | ||
| 214 | // <name>@@<version> means the symbol is the default version. In that | 215 | // <name>@@<version> means the symbol is the default version. In that |
| 215 | // case <name>@@<version> will be used to resolve references to <name>. | 216 | // case <name>@@<version> will be used to resolve references to <name>. |
| 216 | size_t Pos = Name.find("@@"); | 217 | // |
| 217 | if (Pos != StringRef::npos) | 218 | // Since this is a hot path, the following string search code is |
| 219 | // optimized for speed. StringRef::find(char) is much faster than | ||
| 220 | // StringRef::find(StringRef). | ||
| 221 | size_t Pos = Name.find('@'); | ||
| 222 | if (Pos != StringRef::npos && Pos + 1 < Name.size() && Name[Pos + 1] == '@') | ||
| 218 | Name = Name.take_front(Pos); | 223 | Name = Name.take_front(Pos); |
| 219 | 224 | ||
| 220 | auto P = Symtab.insert( | 225 | auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()}); |
| 221 | {CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)}); | 226 | int &SymIndex = P.first->second; |
| 222 | SymIndex &V = P.first->second; | ||
| 223 | bool IsNew = P.second; | 227 | bool IsNew = P.second; |
| 228 | bool Traced = false; | ||
| 224 | 229 | ||
| 225 | if (V.Idx == -1) { | 230 | if (SymIndex == -1) { |
| 226 | IsNew = true; | 231 | SymIndex = SymVector.size(); |
| 227 | V = SymIndex((int)SymVector.size(), true); | 232 | IsNew = Traced = true; |
| 228 | } | 233 | } |
| 229 | 234 | ||
| 230 | Symbol *Sym; | 235 | Symbol *Sym; |
| 231 | if (IsNew) { | 236 | if (IsNew) { |
| 232 | Sym = make<Symbol>(); | 237 | Sym = (Symbol *)make<SymbolUnion>(); |
| 233 | Sym->InVersionScript = false; | 238 | Sym->InVersionScript = false; |
| 234 | Sym->Binding = STB_WEAK; | ||
| 235 | Sym->Visibility = STV_DEFAULT; | 239 | Sym->Visibility = STV_DEFAULT; |
| 236 | Sym->IsUsedInRegularObj = false; | 240 | Sym->IsUsedInRegularObj = false; |
| 237 | Sym->ExportDynamic = false; | 241 | Sym->ExportDynamic = false; |
| 238 | Sym->Traced = V.Traced; | 242 | Sym->CanInline = true; |
| 243 | Sym->Traced = Traced; | ||
| 239 | Sym->VersionId = Config->DefaultSymbolVersion; | 244 | Sym->VersionId = Config->DefaultSymbolVersion; |
| 240 | SymVector.push_back(Sym); | 245 | SymVector.push_back(Sym); |
| 241 | } else { | 246 | } else { |
| 242 | Sym = SymVector[V.Idx]; | 247 | Sym = SymVector[SymIndex]; |
| 243 | } | 248 | } |
| 244 | return {Sym, IsNew}; | 249 | return {Sym, IsNew}; |
| 245 | } | 250 | } |
| 246 | 251 | ||
| 247 | // Find an existing symbol or create and insert a new one, then apply the given | 252 | // Find an existing symbol or create and insert a new one, then apply the given |
| 248 | // attributes. | 253 | // attributes. |
| 249 | template <class ELFT> | 254 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, uint8_t Type, |
| 250 | std::pair<Symbol *, bool> | 255 | uint8_t Visibility, |
| 251 | SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility, | 256 | bool CanOmitFromDynSym, |
| 252 | bool CanOmitFromDynSym, InputFile *File) { | 257 | InputFile *File) { |
| 253 | bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind; | ||
| 254 | Symbol *S; | 258 | Symbol *S; |
| 255 | bool WasInserted; | 259 | bool WasInserted; |
| 256 | std::tie(S, WasInserted) = insert(Name); | 260 | std::tie(S, WasInserted) = insert(Name); |
| ... | @@ -261,32 +265,30 @@ SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility, | ... | @@ -261,32 +265,30 @@ SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility, |
| 261 | if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) | 265 | if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) |
| 262 | S->ExportDynamic = true; | 266 | S->ExportDynamic = true; |
| 263 | 267 | ||
| 264 | if (IsUsedInRegularObj) | 268 | if (!File || File->kind() == InputFile::ObjKind) |
| 265 | S->IsUsedInRegularObj = true; | 269 | S->IsUsedInRegularObj = true; |
| 266 | 270 | ||
| 267 | if (!WasInserted && S->body()->Type != SymbolBody::UnknownType && | 271 | if (!WasInserted && S->Type != Symbol::UnknownType && |
| 268 | ((Type == STT_TLS) != S->body()->isTls())) { | 272 | ((Type == STT_TLS) != S->isTls())) { |
| 269 | error("TLS attribute mismatch: " + toString(*S->body()) + | 273 | error("TLS attribute mismatch: " + toString(*S) + "\n>>> defined in " + |
| 270 | "\n>>> defined in " + toString(S->body()->File) + | 274 | toString(S->File) + "\n>>> defined in " + toString(File)); |
| 271 | "\n>>> defined in " + toString(File)); | ||
| 272 | } | 275 | } |
| 273 | 276 | ||
| 274 | return {S, WasInserted}; | 277 | return {S, WasInserted}; |
| 275 | } | 278 | } |
| 276 | 279 | ||
| 277 | template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) { | 280 | template <class ELFT> Symbol *SymbolTable::addUndefined(StringRef Name) { |
| 278 | return addUndefined(Name, /*IsLocal=*/false, STB_GLOBAL, STV_DEFAULT, | 281 | return addUndefined<ELFT>(Name, STB_GLOBAL, STV_DEFAULT, |
| 279 | /*Type*/ 0, | 282 | /*Type*/ 0, |
| 280 | /*CanOmitFromDynSym*/ false, /*File*/ nullptr); | 283 | /*CanOmitFromDynSym*/ false, /*File*/ nullptr); |
| 281 | } | 284 | } |
| 282 | 285 | ||
| 283 | static uint8_t getVisibility(uint8_t StOther) { return StOther & 3; } | 286 | static uint8_t getVisibility(uint8_t StOther) { return StOther & 3; } |
| 284 | 287 | ||
| 285 | template <class ELFT> | 288 | template <class ELFT> |
| 286 | Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal, | 289 | Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding, |
| 287 | uint8_t Binding, uint8_t StOther, | 290 | uint8_t StOther, uint8_t Type, |
| 288 | uint8_t Type, bool CanOmitFromDynSym, | 291 | bool CanOmitFromDynSym, InputFile *File) { |
| 289 | InputFile *File) { | ||
| 290 | Symbol *S; | 292 | Symbol *S; |
| 291 | bool WasInserted; | 293 | bool WasInserted; |
| 292 | uint8_t Visibility = getVisibility(StOther); | 294 | uint8_t Visibility = getVisibility(StOther); |
| ... | @@ -294,26 +296,24 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal, | ... | @@ -294,26 +296,24 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal, |
| 294 | insert(Name, Type, Visibility, CanOmitFromDynSym, File); | 296 | insert(Name, Type, Visibility, CanOmitFromDynSym, File); |
| 295 | // An undefined symbol with non default visibility must be satisfied | 297 | // An undefined symbol with non default visibility must be satisfied |
| 296 | // in the same DSO. | 298 | // in the same DSO. |
| 297 | if (WasInserted || | 299 | if (WasInserted || (isa<SharedSymbol>(S) && Visibility != STV_DEFAULT)) { |
| 298 | (isa<SharedSymbol>(S->body()) && Visibility != STV_DEFAULT)) { | 300 | replaceSymbol<Undefined>(S, File, Name, Binding, StOther, Type); |
| 299 | S->Binding = Binding; | ||
| 300 | replaceBody<Undefined>(S, Name, IsLocal, StOther, Type, File); | ||
| 301 | return S; | 301 | return S; |
| 302 | } | 302 | } |
| 303 | if (S->isShared() || S->isLazy() || (S->isUndefined() && Binding != STB_WEAK)) | ||
| 304 | S->Binding = Binding; | ||
| 303 | if (Binding != STB_WEAK) { | 305 | if (Binding != STB_WEAK) { |
| 304 | SymbolBody *B = S->body(); | 306 | if (auto *SS = dyn_cast<SharedSymbol>(S)) |
| 305 | if (B->isShared() || B->isLazy() || B->isUndefined()) | 307 | if (!Config->GcSections) |
| 306 | S->Binding = Binding; | 308 | SS->getFile<ELFT>().IsNeeded = true; |
| 307 | if (auto *SS = dyn_cast<SharedSymbol>(B)) | ||
| 308 | cast<SharedFile<ELFT>>(SS->File)->IsUsed = true; | ||
| 309 | } | 309 | } |
| 310 | if (auto *L = dyn_cast<Lazy>(S->body())) { | 310 | if (auto *L = dyn_cast<Lazy>(S)) { |
| 311 | // An undefined weak will not fetch archive members, but we have to remember | 311 | // An undefined weak will not fetch archive members. See comment on Lazy in |
| 312 | // its type. See also comment in addLazyArchive. | 312 | // Symbols.h for the details. |
| 313 | if (S->isWeak()) | 313 | if (Binding == STB_WEAK) |
| 314 | L->Type = Type; | 314 | L->Type = Type; |
| 315 | else if (InputFile *F = L->fetch()) | 315 | else if (InputFile *F = L->fetch()) |
| 316 | addFile(F); | 316 | addFile<ELFT>(F); |
| 317 | } | 317 | } |
| 318 | return S; | 318 | return S; |
| 319 | } | 319 | } |
| ... | @@ -325,11 +325,11 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal, | ... | @@ -325,11 +325,11 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal, |
| 325 | // .symver foo,foo@@@VER | 325 | // .symver foo,foo@@@VER |
| 326 | // we can delete this hack. | 326 | // we can delete this hack. |
| 327 | static int compareVersion(Symbol *S, StringRef Name) { | 327 | static int compareVersion(Symbol *S, StringRef Name) { |
| 328 | if (Name.find("@@") != StringRef::npos && | 328 | bool A = Name.contains("@@"); |
| 329 | S->body()->getName().find("@@") == StringRef::npos) | 329 | bool B = S->getName().contains("@@"); |
| 330 | if (A && !B) | ||
| 330 | return 1; | 331 | return 1; |
| 331 | if (Name.find("@@") == StringRef::npos && | 332 | if (!A && B) |
| 332 | S->body()->getName().find("@@") != StringRef::npos) | ||
| 333 | return -1; | 333 | return -1; |
| 334 | return 0; | 334 | return 0; |
| 335 | } | 335 | } |
| ... | @@ -341,13 +341,10 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding, | ... | @@ -341,13 +341,10 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding, |
| 341 | StringRef Name) { | 341 | StringRef Name) { |
| 342 | if (WasInserted) | 342 | if (WasInserted) |
| 343 | return 1; | 343 | return 1; |
| 344 | SymbolBody *Body = S->body(); | 344 | if (!S->isDefined()) |
| 345 | if (!Body->isInCurrentDSO()) | ||
| 346 | return 1; | 345 | return 1; |
| 347 | |||
| 348 | if (int R = compareVersion(S, Name)) | 346 | if (int R = compareVersion(S, Name)) |
| 349 | return R; | 347 | return R; |
| 350 | |||
| 351 | if (Binding == STB_WEAK) | 348 | if (Binding == STB_WEAK) |
| 352 | return -1; | 349 | return -1; |
| 353 | if (S->isWeak()) | 350 | if (S->isWeak()) |
| ... | @@ -358,22 +355,18 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding, | ... | @@ -358,22 +355,18 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding, |
| 358 | // We have a new non-common defined symbol with the specified binding. Return 1 | 355 | // We have a new non-common defined symbol with the specified binding. Return 1 |
| 359 | // if the new symbol should win, -1 if the new symbol should lose, or 0 if there | 356 | // if the new symbol should win, -1 if the new symbol should lose, or 0 if there |
| 360 | // is a conflict. If the new symbol wins, also update the binding. | 357 | // is a conflict. If the new symbol wins, also update the binding. |
| 361 | template <typename ELFT> | ||
| 362 | static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding, | 358 | static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding, |
| 363 | bool IsAbsolute, typename ELFT::uint Value, | 359 | bool IsAbsolute, uint64_t Value, |
| 364 | StringRef Name) { | 360 | StringRef Name) { |
| 365 | if (int Cmp = compareDefined(S, WasInserted, Binding, Name)) { | 361 | if (int Cmp = compareDefined(S, WasInserted, Binding, Name)) |
| 366 | if (Cmp > 0) | ||
| 367 | S->Binding = Binding; | ||
| 368 | return Cmp; | 362 | return Cmp; |
| 369 | } | 363 | if (auto *R = dyn_cast<Defined>(S)) { |
| 370 | SymbolBody *B = S->body(); | 364 | if (R->Section && isa<BssSection>(R->Section)) { |
| 371 | if (isa<DefinedCommon>(B)) { | 365 | // Non-common symbols take precedence over common symbols. |
| 372 | // Non-common symbols take precedence over common symbols. | 366 | if (Config->WarnCommon) |
| 373 | if (Config->WarnCommon) | 367 | warn("common " + S->getName() + " is overridden"); |
| 374 | warn("common " + S->body()->getName() + " is overridden"); | 368 | return 1; |
| 375 | return 1; | 369 | } |
| 376 | } else if (auto *R = dyn_cast<DefinedRegular>(B)) { | ||
| 377 | if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute && | 370 | if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute && |
| 378 | R->Value == Value) | 371 | R->Value == Value) |
| 379 | return -1; | 372 | return -1; |
| ... | @@ -381,34 +374,39 @@ static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding, | ... | @@ -381,34 +374,39 @@ static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding, |
| 381 | return 0; | 374 | return 0; |
| 382 | } | 375 | } |
| 383 | 376 | ||
| 384 | template <class ELFT> | 377 | Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment, |
| 385 | Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size, | 378 | uint8_t Binding, uint8_t StOther, uint8_t Type, |
| 386 | uint32_t Alignment, uint8_t Binding, | 379 | InputFile &File) { |
| 387 | uint8_t StOther, uint8_t Type, | ||
| 388 | InputFile *File) { | ||
| 389 | Symbol *S; | 380 | Symbol *S; |
| 390 | bool WasInserted; | 381 | bool WasInserted; |
| 391 | std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther), | 382 | std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther), |
| 392 | /*CanOmitFromDynSym*/ false, File); | 383 | /*CanOmitFromDynSym*/ false, &File); |
| 393 | int Cmp = compareDefined(S, WasInserted, Binding, N); | 384 | int Cmp = compareDefined(S, WasInserted, Binding, N); |
| 394 | if (Cmp > 0) { | 385 | if (Cmp > 0) { |
| 395 | S->Binding = Binding; | 386 | auto *Bss = make<BssSection>("COMMON", Size, Alignment); |
| 396 | replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File); | 387 | Bss->File = &File; |
| 388 | Bss->Live = !Config->GcSections; | ||
| 389 | InputSections.push_back(Bss); | ||
| 390 | |||
| 391 | replaceSymbol<Defined>(S, &File, N, Binding, StOther, Type, 0, Size, Bss); | ||
| 397 | } else if (Cmp == 0) { | 392 | } else if (Cmp == 0) { |
| 398 | auto *C = dyn_cast<DefinedCommon>(S->body()); | 393 | auto *D = cast<Defined>(S); |
| 399 | if (!C) { | 394 | auto *Bss = dyn_cast_or_null<BssSection>(D->Section); |
| 395 | if (!Bss) { | ||
| 400 | // Non-common symbols take precedence over common symbols. | 396 | // Non-common symbols take precedence over common symbols. |
| 401 | if (Config->WarnCommon) | 397 | if (Config->WarnCommon) |
| 402 | warn("common " + S->body()->getName() + " is overridden"); | 398 | warn("common " + S->getName() + " is overridden"); |
| 403 | return S; | 399 | return S; |
| 404 | } | 400 | } |
| 405 | 401 | ||
| 406 | if (Config->WarnCommon) | 402 | if (Config->WarnCommon) |
| 407 | warn("multiple common of " + S->body()->getName()); | 403 | warn("multiple common of " + D->getName()); |
| 408 | 404 | ||
| 409 | Alignment = C->Alignment = std::max(C->Alignment, Alignment); | 405 | Bss->Alignment = std::max(Bss->Alignment, Alignment); |
| 410 | if (Size > C->Size) | 406 | if (Size > Bss->Size) { |
| 411 | replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File); | 407 | D->File = Bss->File = &File; |
| 408 | D->Size = Bss->Size = Size; | ||
| 409 | } | ||
| 412 | } | 410 | } |
| 413 | return S; | 411 | return S; |
| 414 | } | 412 | } |
| ... | @@ -420,17 +418,16 @@ static void warnOrError(const Twine &Msg) { | ... | @@ -420,17 +418,16 @@ static void warnOrError(const Twine &Msg) { |
| 420 | error(Msg); | 418 | error(Msg); |
| 421 | } | 419 | } |
| 422 | 420 | ||
| 423 | static void reportDuplicate(SymbolBody *Sym, InputFile *NewFile) { | 421 | static void reportDuplicate(Symbol *Sym, InputFile *NewFile) { |
| 424 | warnOrError("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + | 422 | warnOrError("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + |
| 425 | toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); | 423 | toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); |
| 426 | } | 424 | } |
| 427 | 425 | ||
| 428 | template <class ELFT> | 426 | static void reportDuplicate(Symbol *Sym, InputSectionBase *ErrSec, |
| 429 | static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec, | 427 | uint64_t ErrOffset) { |
| 430 | typename ELFT::uint ErrOffset) { | 428 | Defined *D = cast<Defined>(Sym); |
| 431 | DefinedRegular *D = dyn_cast<DefinedRegular>(Sym); | 429 | if (!D->Section || !ErrSec) { |
| 432 | if (!D || !D->Section || !ErrSec) { | 430 | reportDuplicate(Sym, ErrSec ? ErrSec->File : nullptr); |
| 433 | reportDuplicate(Sym, ErrSec ? ErrSec->getFile<ELFT>() : nullptr); | ||
| 434 | return; | 431 | return; |
| 435 | } | 432 | } |
| 436 | 433 | ||
| ... | @@ -442,10 +439,10 @@ static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec, | ... | @@ -442,10 +439,10 @@ static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec, |
| 442 | // >>> defined at baz.c:563 | 439 | // >>> defined at baz.c:563 |
| 443 | // >>> baz.o in archive libbaz.a | 440 | // >>> baz.o in archive libbaz.a |
| 444 | auto *Sec1 = cast<InputSectionBase>(D->Section); | 441 | auto *Sec1 = cast<InputSectionBase>(D->Section); |
| 445 | std::string Src1 = Sec1->getSrcMsg<ELFT>(D->Value); | 442 | std::string Src1 = Sec1->getSrcMsg(*Sym, D->Value); |
| 446 | std::string Obj1 = Sec1->getObjMsg<ELFT>(D->Value); | 443 | std::string Obj1 = Sec1->getObjMsg(D->Value); |
| 447 | std::string Src2 = ErrSec->getSrcMsg<ELFT>(ErrOffset); | 444 | std::string Src2 = ErrSec->getSrcMsg(*Sym, ErrOffset); |
| 448 | std::string Obj2 = ErrSec->getObjMsg<ELFT>(ErrOffset); | 445 | std::string Obj2 = ErrSec->getObjMsg(ErrOffset); |
| 449 | 446 | ||
| 450 | std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at "; | 447 | std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at "; |
| 451 | if (!Src1.empty()) | 448 | if (!Src1.empty()) |
| ... | @@ -457,145 +454,134 @@ static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec, | ... | @@ -457,145 +454,134 @@ static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec, |
| 457 | warnOrError(Msg); | 454 | warnOrError(Msg); |
| 458 | } | 455 | } |
| 459 | 456 | ||
| 460 | template <typename ELFT> | 457 | Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, |
| 461 | Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther, | 458 | uint64_t Value, uint64_t Size, uint8_t Binding, |
| 462 | uint8_t Type, uint64_t Value, | 459 | SectionBase *Section, InputFile *File) { |
| 463 | uint64_t Size, uint8_t Binding, | ||
| 464 | SectionBase *Section, InputFile *File) { | ||
| 465 | Symbol *S; | 460 | Symbol *S; |
| 466 | bool WasInserted; | 461 | bool WasInserted; |
| 467 | std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), | 462 | std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), |
| 468 | /*CanOmitFromDynSym*/ false, File); | 463 | /*CanOmitFromDynSym*/ false, File); |
| 469 | int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding, | 464 | int Cmp = compareDefinedNonCommon(S, WasInserted, Binding, Section == nullptr, |
| 470 | Section == nullptr, Value, Name); | 465 | Value, Name); |
| 471 | if (Cmp > 0) | 466 | if (Cmp > 0) |
| 472 | replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, | 467 | replaceSymbol<Defined>(S, File, Name, Binding, StOther, Type, Value, Size, |
| 473 | Value, Size, Section, File); | 468 | Section); |
| 474 | else if (Cmp == 0) | 469 | else if (Cmp == 0) |
| 475 | reportDuplicate<ELFT>(S->body(), | 470 | reportDuplicate(S, dyn_cast_or_null<InputSectionBase>(Section), Value); |
| 476 | dyn_cast_or_null<InputSectionBase>(Section), Value); | ||
| 477 | return S; | 471 | return S; |
| 478 | } | 472 | } |
| 479 | 473 | ||
| 480 | template <typename ELFT> | 474 | template <typename ELFT> |
| 481 | void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *File, StringRef Name, | 475 | void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> &File, |
| 482 | const Elf_Sym &Sym, | 476 | const typename ELFT::Sym &Sym, uint32_t Alignment, |
| 483 | const typename ELFT::Verdef *Verdef) { | 477 | uint32_t VerdefIndex) { |
| 484 | // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT | 478 | // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT |
| 485 | // as the visibility, which will leave the visibility in the symbol table | 479 | // as the visibility, which will leave the visibility in the symbol table |
| 486 | // unchanged. | 480 | // unchanged. |
| 487 | Symbol *S; | 481 | Symbol *S; |
| 488 | bool WasInserted; | 482 | bool WasInserted; |
| 489 | std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT, | 483 | std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT, |
| 490 | /*CanOmitFromDynSym*/ true, File); | 484 | /*CanOmitFromDynSym*/ true, &File); |
| 491 | // Make sure we preempt DSO symbols with default visibility. | 485 | // Make sure we preempt DSO symbols with default visibility. |
| 492 | if (Sym.getVisibility() == STV_DEFAULT) | 486 | if (Sym.getVisibility() == STV_DEFAULT) |
| 493 | S->ExportDynamic = true; | 487 | S->ExportDynamic = true; |
| 494 | 488 | ||
| 495 | SymbolBody *Body = S->body(); | ||
| 496 | // An undefined symbol with non default visibility must be satisfied | 489 | // An undefined symbol with non default visibility must be satisfied |
| 497 | // in the same DSO. | 490 | // in the same DSO. |
| 498 | if (WasInserted || | 491 | if (WasInserted || ((S->isUndefined() || S->isLazy()) && |
| 499 | (isa<Undefined>(Body) && Body->getVisibility() == STV_DEFAULT)) { | 492 | S->getVisibility() == STV_DEFAULT)) { |
| 500 | replaceBody<SharedSymbol>(S, File, Name, Sym.st_other, Sym.getType(), &Sym, | 493 | uint8_t Binding = S->Binding; |
| 501 | Verdef); | 494 | replaceSymbol<SharedSymbol>(S, File, Name, Sym.getBinding(), Sym.st_other, |
| 502 | if (!S->isWeak()) | 495 | Sym.getType(), Sym.st_value, Sym.st_size, |
| 503 | File->IsUsed = true; | 496 | Alignment, VerdefIndex); |
| 497 | if (!WasInserted) { | ||
| 498 | S->Binding = Binding; | ||
| 499 | if (!S->isWeak() && !Config->GcSections) | ||
| 500 | File.IsNeeded = true; | ||
| 501 | } | ||
| 504 | } | 502 | } |
| 505 | } | 503 | } |
| 506 | 504 | ||
| 507 | template <class ELFT> | 505 | Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding, |
| 508 | Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding, | 506 | uint8_t StOther, uint8_t Type, |
| 509 | uint8_t StOther, uint8_t Type, | 507 | bool CanOmitFromDynSym, BitcodeFile &F) { |
| 510 | bool CanOmitFromDynSym, BitcodeFile *F) { | ||
| 511 | Symbol *S; | 508 | Symbol *S; |
| 512 | bool WasInserted; | 509 | bool WasInserted; |
| 513 | std::tie(S, WasInserted) = | 510 | std::tie(S, WasInserted) = |
| 514 | insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F); | 511 | insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, &F); |
| 515 | int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding, | 512 | int Cmp = compareDefinedNonCommon(S, WasInserted, Binding, |
| 516 | /*IsAbs*/ false, /*Value*/ 0, Name); | 513 | /*IsAbs*/ false, /*Value*/ 0, Name); |
| 517 | if (Cmp > 0) | 514 | if (Cmp > 0) |
| 518 | replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, 0, 0, | 515 | replaceSymbol<Defined>(S, &F, Name, Binding, StOther, Type, 0, 0, nullptr); |
| 519 | nullptr, F); | ||
| 520 | else if (Cmp == 0) | 516 | else if (Cmp == 0) |
| 521 | reportDuplicate(S->body(), F); | 517 | reportDuplicate(S, &F); |
| 522 | return S; | 518 | return S; |
| 523 | } | 519 | } |
| 524 | 520 | ||
| 525 | template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) { | 521 | Symbol *SymbolTable::find(StringRef Name) { |
| 526 | auto It = Symtab.find(CachedHashStringRef(Name)); | 522 | auto It = SymMap.find(CachedHashStringRef(Name)); |
| 527 | if (It == Symtab.end()) | 523 | if (It == SymMap.end()) |
| 528 | return nullptr; | 524 | return nullptr; |
| 529 | SymIndex V = It->second; | 525 | if (It->second == -1) |
| 530 | if (V.Idx == -1) | ||
| 531 | return nullptr; | 526 | return nullptr; |
| 532 | return SymVector[V.Idx]->body(); | 527 | return SymVector[It->second]; |
| 533 | } | 528 | } |
| 534 | 529 | ||
| 535 | template <class ELFT> | 530 | template <class ELFT> |
| 536 | SymbolBody *SymbolTable<ELFT>::findInCurrentDSO(StringRef Name) { | 531 | Symbol *SymbolTable::addLazyArchive(StringRef Name, ArchiveFile &F, |
| 537 | if (SymbolBody *S = find(Name)) | 532 | const object::Archive::Symbol Sym) { |
| 538 | if (S->isInCurrentDSO()) | ||
| 539 | return S; | ||
| 540 | return nullptr; | ||
| 541 | } | ||
| 542 | |||
| 543 | template <class ELFT> | ||
| 544 | Symbol *SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F, | ||
| 545 | const object::Archive::Symbol Sym) { | ||
| 546 | Symbol *S; | 533 | Symbol *S; |
| 547 | bool WasInserted; | 534 | bool WasInserted; |
| 548 | StringRef Name = Sym.getName(); | ||
| 549 | std::tie(S, WasInserted) = insert(Name); | 535 | std::tie(S, WasInserted) = insert(Name); |
| 550 | if (WasInserted) { | 536 | if (WasInserted) { |
| 551 | replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType); | 537 | replaceSymbol<LazyArchive>(S, F, Sym, Symbol::UnknownType); |
| 552 | return S; | 538 | return S; |
| 553 | } | 539 | } |
| 554 | if (!S->body()->isUndefined()) | 540 | if (!S->isUndefined()) |
| 555 | return S; | 541 | return S; |
| 556 | 542 | ||
| 557 | // Weak undefined symbols should not fetch members from archives. If we were | 543 | // An undefined weak will not fetch archive members. See comment on Lazy in |
| 558 | // to keep old symbol we would not know that an archive member was available | 544 | // Symbols.h for the details. |
| 559 | // if a strong undefined symbol shows up afterwards in the link. If a strong | ||
| 560 | // undefined symbol never shows up, this lazy symbol will get to the end of | ||
| 561 | // the link and must be treated as the weak undefined one. We already marked | ||
| 562 | // this symbol as used when we added it to the symbol table, but we also need | ||
| 563 | // to preserve its type. FIXME: Move the Type field to Symbol. | ||
| 564 | if (S->isWeak()) { | 545 | if (S->isWeak()) { |
| 565 | replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type); | 546 | replaceSymbol<LazyArchive>(S, F, Sym, S->Type); |
| 547 | S->Binding = STB_WEAK; | ||
| 566 | return S; | 548 | return S; |
| 567 | } | 549 | } |
| 568 | std::pair<MemoryBufferRef, uint64_t> MBInfo = F->getMember(&Sym); | 550 | std::pair<MemoryBufferRef, uint64_t> MBInfo = F.getMember(&Sym); |
| 569 | if (!MBInfo.first.getBuffer().empty()) | 551 | if (!MBInfo.first.getBuffer().empty()) |
| 570 | addFile(createObjectFile(MBInfo.first, F->getName(), MBInfo.second)); | 552 | addFile<ELFT>(createObjectFile(MBInfo.first, F.getName(), MBInfo.second)); |
| 571 | return S; | 553 | return S; |
| 572 | } | 554 | } |
| 573 | 555 | ||
| 574 | template <class ELFT> | 556 | template <class ELFT> |
| 575 | void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) { | 557 | void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &Obj) { |
| 576 | Symbol *S; | 558 | Symbol *S; |
| 577 | bool WasInserted; | 559 | bool WasInserted; |
| 578 | std::tie(S, WasInserted) = insert(Name); | 560 | std::tie(S, WasInserted) = insert(Name); |
| 579 | if (WasInserted) { | 561 | if (WasInserted) { |
| 580 | replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType); | 562 | replaceSymbol<LazyObject>(S, Obj, Name, Symbol::UnknownType); |
| 581 | return; | 563 | return; |
| 582 | } | 564 | } |
| 583 | if (!S->body()->isUndefined()) | 565 | if (!S->isUndefined()) |
| 584 | return; | 566 | return; |
| 585 | 567 | ||
| 586 | // See comment for addLazyArchive above. | 568 | // See comment for addLazyArchive above. |
| 587 | if (S->isWeak()) | 569 | if (S->isWeak()) |
| 588 | replaceBody<LazyObject>(S, Name, Obj, S->body()->Type); | 570 | replaceSymbol<LazyObject>(S, Obj, Name, S->Type); |
| 589 | else if (InputFile *F = Obj.fetch()) | 571 | else if (InputFile *F = Obj.fetch()) |
| 590 | addFile(F); | 572 | addFile<ELFT>(F); |
| 591 | } | 573 | } |
| 592 | 574 | ||
| 593 | // Process undefined (-u) flags by loading lazy symbols named by those flags. | 575 | // If we already saw this symbol, force loading its file. |
| 594 | template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() { | 576 | template <class ELFT> void SymbolTable::fetchIfLazy(StringRef Name) { |
| 595 | for (StringRef S : Config->Undefined) | 577 | if (Symbol *B = find(Name)) { |
| 596 | if (auto *L = dyn_cast_or_null<Lazy>(find(S))) | 578 | // Mark the symbol not to be eliminated by LTO |
| 579 | // even if it is a bitcode symbol. | ||
| 580 | B->IsUsedInRegularObj = true; | ||
| 581 | if (auto *L = dyn_cast<Lazy>(B)) | ||
| 597 | if (InputFile *File = L->fetch()) | 582 | if (InputFile *File = L->fetch()) |
| 598 | addFile(File); | 583 | addFile<ELFT>(File); |
| 584 | } | ||
| 599 | } | 585 | } |
| 600 | 586 | ||
| 601 | // This function takes care of the case in which shared libraries depend on | 587 | // This function takes care of the case in which shared libraries depend on |
| ... | @@ -605,19 +591,19 @@ template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() { | ... | @@ -605,19 +591,19 @@ template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() { |
| 605 | // We need to put such symbols to the main program's .dynsym so that | 591 | // We need to put such symbols to the main program's .dynsym so that |
| 606 | // shared libraries can find them. | 592 | // shared libraries can find them. |
| 607 | // Except this, we ignore undefined symbols in DSOs. | 593 | // Except this, we ignore undefined symbols in DSOs. |
| 608 | template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { | 594 | template <class ELFT> void SymbolTable::scanShlibUndefined() { |
| 609 | for (SharedFile<ELFT> *File : SharedFiles) { | 595 | for (InputFile *F : SharedFiles) { |
| 610 | for (StringRef U : File->getUndefinedSymbols()) { | 596 | for (StringRef U : cast<SharedFile<ELFT>>(F)->getUndefinedSymbols()) { |
| 611 | SymbolBody *Sym = find(U); | 597 | Symbol *Sym = find(U); |
| 612 | if (!Sym || !Sym->isDefined()) | 598 | if (!Sym || !Sym->isDefined()) |
| 613 | continue; | 599 | continue; |
| 614 | Sym->symbol()->ExportDynamic = true; | 600 | Sym->ExportDynamic = true; |
| 615 | 601 | ||
| 616 | // If -dynamic-list is given, the default version is set to | 602 | // If -dynamic-list is given, the default version is set to |
| 617 | // VER_NDX_LOCAL, which prevents a symbol to be exported via .dynsym. | 603 | // VER_NDX_LOCAL, which prevents a symbol to be exported via .dynsym. |
| 618 | // Set to VER_NDX_GLOBAL so the symbol will be handled as if it were | 604 | // Set to VER_NDX_GLOBAL so the symbol will be handled as if it were |
| 619 | // specified by -dynamic-list. | 605 | // specified by -dynamic-list. |
| 620 | Sym->symbol()->VersionId = VER_NDX_GLOBAL; | 606 | Sym->VersionId = VER_NDX_GLOBAL; |
| 621 | } | 607 | } |
| 622 | } | 608 | } |
| 623 | } | 609 | } |
| ... | @@ -635,37 +621,32 @@ template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { | ... | @@ -635,37 +621,32 @@ template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { |
| 635 | // other than trying to match a pattern against all demangled symbols. | 621 | // other than trying to match a pattern against all demangled symbols. |
| 636 | // So, if "extern C++" feature is used, we need to demangle all known | 622 | // So, if "extern C++" feature is used, we need to demangle all known |
| 637 | // symbols. | 623 | // symbols. |
| 638 | template <class ELFT> | 624 | StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() { |
| 639 | StringMap<std::vector<SymbolBody *>> &SymbolTable<ELFT>::getDemangledSyms() { | ||
| 640 | if (!DemangledSyms) { | 625 | if (!DemangledSyms) { |
| 641 | DemangledSyms.emplace(); | 626 | DemangledSyms.emplace(); |
| 642 | for (Symbol *Sym : SymVector) { | 627 | for (Symbol *Sym : SymVector) { |
| 643 | SymbolBody *B = Sym->body(); | 628 | if (!Sym->isDefined()) |
| 644 | if (B->isUndefined()) | ||
| 645 | continue; | 629 | continue; |
| 646 | if (Optional<std::string> S = demangle(B->getName())) | 630 | if (Optional<std::string> S = demangleItanium(Sym->getName())) |
| 647 | (*DemangledSyms)[*S].push_back(B); | 631 | (*DemangledSyms)[*S].push_back(Sym); |
| 648 | else | 632 | else |
| 649 | (*DemangledSyms)[B->getName()].push_back(B); | 633 | (*DemangledSyms)[Sym->getName()].push_back(Sym); |
| 650 | } | 634 | } |
| 651 | } | 635 | } |
| 652 | return *DemangledSyms; | 636 | return *DemangledSyms; |
| 653 | } | 637 | } |
| 654 | 638 | ||
| 655 | template <class ELFT> | 639 | std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion Ver) { |
| 656 | std::vector<SymbolBody *> SymbolTable<ELFT>::findByVersion(SymbolVersion Ver) { | ||
| 657 | if (Ver.IsExternCpp) | 640 | if (Ver.IsExternCpp) |
| 658 | return getDemangledSyms().lookup(Ver.Name); | 641 | return getDemangledSyms().lookup(Ver.Name); |
| 659 | if (SymbolBody *B = find(Ver.Name)) | 642 | if (Symbol *B = find(Ver.Name)) |
| 660 | if (!B->isUndefined()) | 643 | if (B->isDefined()) |
| 661 | return {B}; | 644 | return {B}; |
| 662 | return {}; | 645 | return {}; |
| 663 | } | 646 | } |
| 664 | 647 | ||
| 665 | template <class ELFT> | 648 | std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion Ver) { |
| 666 | std::vector<SymbolBody *> | 649 | std::vector<Symbol *> Res; |
| 667 | SymbolTable<ELFT>::findAllByVersion(SymbolVersion Ver) { | ||
| 668 | std::vector<SymbolBody *> Res; | ||
| 669 | StringMatcher M(Ver.Name); | 650 | StringMatcher M(Ver.Name); |
| 670 | 651 | ||
| 671 | if (Ver.IsExternCpp) { | 652 | if (Ver.IsExternCpp) { |
| ... | @@ -675,18 +656,16 @@ SymbolTable<ELFT>::findAllByVersion(SymbolVersion Ver) { | ... | @@ -675,18 +656,16 @@ SymbolTable<ELFT>::findAllByVersion(SymbolVersion Ver) { |
| 675 | return Res; | 656 | return Res; |
| 676 | } | 657 | } |
| 677 | 658 | ||
| 678 | for (Symbol *Sym : SymVector) { | 659 | for (Symbol *Sym : SymVector) |
| 679 | SymbolBody *B = Sym->body(); | 660 | if (Sym->isDefined() && M.match(Sym->getName())) |
| 680 | if (!B->isUndefined() && M.match(B->getName())) | 661 | Res.push_back(Sym); |
| 681 | Res.push_back(B); | ||
| 682 | } | ||
| 683 | return Res; | 662 | return Res; |
| 684 | } | 663 | } |
| 685 | 664 | ||
| 686 | // If there's only one anonymous version definition in a version | 665 | // If there's only one anonymous version definition in a version |
| 687 | // script file, the script does not actually define any symbol version, | 666 | // script file, the script does not actually define any symbol version, |
| 688 | // but just specifies symbols visibilities. | 667 | // but just specifies symbols visibilities. |
| 689 | template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() { | 668 | void SymbolTable::handleAnonymousVersion() { |
| 690 | for (SymbolVersion &Ver : Config->VersionScriptGlobals) | 669 | for (SymbolVersion &Ver : Config->VersionScriptGlobals) |
| 691 | assignExactVersion(Ver, VER_NDX_GLOBAL, "global"); | 670 | assignExactVersion(Ver, VER_NDX_GLOBAL, "global"); |
| 692 | for (SymbolVersion &Ver : Config->VersionScriptGlobals) | 671 | for (SymbolVersion &Ver : Config->VersionScriptGlobals) |
| ... | @@ -697,17 +676,33 @@ template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() { | ... | @@ -697,17 +676,33 @@ template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() { |
| 697 | assignWildcardVersion(Ver, VER_NDX_LOCAL); | 676 | assignWildcardVersion(Ver, VER_NDX_LOCAL); |
| 698 | } | 677 | } |
| 699 | 678 | ||
| 679 | // Handles -dynamic-list. | ||
| 680 | void SymbolTable::handleDynamicList() { | ||
| 681 | for (SymbolVersion &Ver : Config->DynamicList) { | ||
| 682 | std::vector<Symbol *> Syms; | ||
| 683 | if (Ver.HasWildcard) | ||
| 684 | Syms = findAllByVersion(Ver); | ||
| 685 | else | ||
| 686 | Syms = findByVersion(Ver); | ||
| 687 | |||
| 688 | for (Symbol *B : Syms) { | ||
| 689 | if (!Config->Shared) | ||
| 690 | B->ExportDynamic = true; | ||
| 691 | else if (B->includeInDynsym()) | ||
| 692 | B->IsPreemptible = true; | ||
| 693 | } | ||
| 694 | } | ||
| 695 | } | ||
| 696 | |||
| 700 | // Set symbol versions to symbols. This function handles patterns | 697 | // Set symbol versions to symbols. This function handles patterns |
| 701 | // containing no wildcard characters. | 698 | // containing no wildcard characters. |
| 702 | template <class ELFT> | 699 | void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId, |
| 703 | void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, | 700 | StringRef VersionName) { |
| 704 | uint16_t VersionId, | ||
| 705 | StringRef VersionName) { | ||
| 706 | if (Ver.HasWildcard) | 701 | if (Ver.HasWildcard) |
| 707 | return; | 702 | return; |
| 708 | 703 | ||
| 709 | // Get a list of symbols which we need to assign the version to. | 704 | // Get a list of symbols which we need to assign the version to. |
| 710 | std::vector<SymbolBody *> Syms = findByVersion(Ver); | 705 | std::vector<Symbol *> Syms = findByVersion(Ver); |
| 711 | if (Syms.empty()) { | 706 | if (Syms.empty()) { |
| 712 | if (Config->NoUndefinedVersion) | 707 | if (Config->NoUndefinedVersion) |
| 713 | error("version script assignment of '" + VersionName + "' to symbol '" + | 708 | error("version script assignment of '" + VersionName + "' to symbol '" + |
| ... | @@ -716,14 +711,13 @@ void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, | ... | @@ -716,14 +711,13 @@ void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, |
| 716 | } | 711 | } |
| 717 | 712 | ||
| 718 | // Assign the version. | 713 | // Assign the version. |
| 719 | for (SymbolBody *B : Syms) { | 714 | for (Symbol *Sym : Syms) { |
| 720 | // Skip symbols containing version info because symbol versions | 715 | // Skip symbols containing version info because symbol versions |
| 721 | // specified by symbol names take precedence over version scripts. | 716 | // specified by symbol names take precedence over version scripts. |
| 722 | // See parseSymbolVersion(). | 717 | // See parseSymbolVersion(). |
| 723 | if (B->getName().find('@') != StringRef::npos) | 718 | if (Sym->getName().contains('@')) |
| 724 | continue; | 719 | continue; |
| 725 | 720 | ||
| 726 | Symbol *Sym = B->symbol(); | ||
| 727 | if (Sym->InVersionScript) | 721 | if (Sym->InVersionScript) |
| 728 | warn("duplicate symbol '" + Ver.Name + "' in version script"); | 722 | warn("duplicate symbol '" + Ver.Name + "' in version script"); |
| 729 | Sym->VersionId = VersionId; | 723 | Sym->VersionId = VersionId; |
| ... | @@ -731,25 +725,24 @@ void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, | ... | @@ -731,25 +725,24 @@ void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, |
| 731 | } | 725 | } |
| 732 | } | 726 | } |
| 733 | 727 | ||
| 734 | template <class ELFT> | 728 | void SymbolTable::assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId) { |
| 735 | void SymbolTable<ELFT>::assignWildcardVersion(SymbolVersion Ver, | ||
| 736 | uint16_t VersionId) { | ||
| 737 | if (!Ver.HasWildcard) | 729 | if (!Ver.HasWildcard) |
| 738 | return; | 730 | return; |
| 739 | 731 | ||
| 740 | // Exact matching takes precendence over fuzzy matching, | 732 | // Exact matching takes precendence over fuzzy matching, |
| 741 | // so we set a version to a symbol only if no version has been assigned | 733 | // so we set a version to a symbol only if no version has been assigned |
| 742 | // to the symbol. This behavior is compatible with GNU. | 734 | // to the symbol. This behavior is compatible with GNU. |
| 743 | for (SymbolBody *B : findAllByVersion(Ver)) | 735 | for (Symbol *B : findAllByVersion(Ver)) |
| 744 | if (B->symbol()->VersionId == Config->DefaultSymbolVersion) | 736 | if (B->VersionId == Config->DefaultSymbolVersion) |
| 745 | B->symbol()->VersionId = VersionId; | 737 | B->VersionId = VersionId; |
| 746 | } | 738 | } |
| 747 | 739 | ||
| 748 | // This function processes version scripts by updating VersionId | 740 | // This function processes version scripts by updating VersionId |
| 749 | // member of symbols. | 741 | // member of symbols. |
| 750 | template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { | 742 | void SymbolTable::scanVersionScript() { |
| 751 | // Handle edge cases first. | 743 | // Handle edge cases first. |
| 752 | handleAnonymousVersion(); | 744 | handleAnonymousVersion(); |
| 745 | handleDynamicList(); | ||
| 753 | 746 | ||
| 754 | // Now we have version definitions, so we need to set version ids to symbols. | 747 | // Now we have version definitions, so we need to set version ids to symbols. |
| 755 | // Each version definition has a glob pattern, and all symbols that match | 748 | // Each version definition has a glob pattern, and all symbols that match |
| ... | @@ -773,10 +766,70 @@ template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { | ... | @@ -773,10 +766,70 @@ template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { |
| 773 | // can contain versions in the form of <name>@<version>. | 766 | // can contain versions in the form of <name>@<version>. |
| 774 | // Let them parse and update their names to exclude version suffix. | 767 | // Let them parse and update their names to exclude version suffix. |
| 775 | for (Symbol *Sym : SymVector) | 768 | for (Symbol *Sym : SymVector) |
| 776 | Sym->body()->parseSymbolVersion(); | 769 | Sym->parseSymbolVersion(); |
| 777 | } | 770 | } |
| 778 | 771 | ||
| 779 | template class elf::SymbolTable<ELF32LE>; | 772 | template void SymbolTable::addSymbolWrap<ELF32LE>(StringRef); |
| 780 | template class elf::SymbolTable<ELF32BE>; | 773 | template void SymbolTable::addSymbolWrap<ELF32BE>(StringRef); |
| 781 | template class elf::SymbolTable<ELF64LE>; | 774 | template void SymbolTable::addSymbolWrap<ELF64LE>(StringRef); |
| 782 | template class elf::SymbolTable<ELF64BE>; | 775 | template void SymbolTable::addSymbolWrap<ELF64BE>(StringRef); |
| 776 | |||
| 777 | template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef); | ||
| 778 | template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef); | ||
| 779 | template Symbol *SymbolTable::addUndefined<ELF64LE>(StringRef); | ||
| 780 | template Symbol *SymbolTable::addUndefined<ELF64BE>(StringRef); | ||
| 781 | |||
| 782 | template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef, uint8_t, uint8_t, | ||
| 783 | uint8_t, bool, InputFile *); | ||
| 784 | template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef, uint8_t, uint8_t, | ||
| 785 | uint8_t, bool, InputFile *); | ||
| 786 | template Symbol *SymbolTable::addUndefined<ELF64LE>(StringRef, uint8_t, uint8_t, | ||
| 787 | uint8_t, bool, InputFile *); | ||
| 788 | template Symbol *SymbolTable::addUndefined<ELF64BE>(StringRef, uint8_t, uint8_t, | ||
| 789 | uint8_t, bool, InputFile *); | ||
| 790 | |||
| 791 | template void SymbolTable::addCombinedLTOObject<ELF32LE>(); | ||
| 792 | template void SymbolTable::addCombinedLTOObject<ELF32BE>(); | ||
| 793 | template void SymbolTable::addCombinedLTOObject<ELF64LE>(); | ||
| 794 | template void SymbolTable::addCombinedLTOObject<ELF64BE>(); | ||
| 795 | |||
| 796 | template Symbol * | ||
| 797 | SymbolTable::addLazyArchive<ELF32LE>(StringRef, ArchiveFile &, | ||
| 798 | const object::Archive::Symbol); | ||
| 799 | template Symbol * | ||
| 800 | SymbolTable::addLazyArchive<ELF32BE>(StringRef, ArchiveFile &, | ||
| 801 | const object::Archive::Symbol); | ||
| 802 | template Symbol * | ||
| 803 | SymbolTable::addLazyArchive<ELF64LE>(StringRef, ArchiveFile &, | ||
| 804 | const object::Archive::Symbol); | ||
| 805 | template Symbol * | ||
| 806 | SymbolTable::addLazyArchive<ELF64BE>(StringRef, ArchiveFile &, | ||
| 807 | const object::Archive::Symbol); | ||
| 808 | |||
| 809 | template void SymbolTable::addLazyObject<ELF32LE>(StringRef, LazyObjFile &); | ||
| 810 | template void SymbolTable::addLazyObject<ELF32BE>(StringRef, LazyObjFile &); | ||
| 811 | template void SymbolTable::addLazyObject<ELF64LE>(StringRef, LazyObjFile &); | ||
| 812 | template void SymbolTable::addLazyObject<ELF64BE>(StringRef, LazyObjFile &); | ||
| 813 | |||
| 814 | template void SymbolTable::addShared<ELF32LE>(StringRef, SharedFile<ELF32LE> &, | ||
| 815 | const typename ELF32LE::Sym &, | ||
| 816 | uint32_t Alignment, uint32_t); | ||
| 817 | template void SymbolTable::addShared<ELF32BE>(StringRef, SharedFile<ELF32BE> &, | ||
| 818 | const typename ELF32BE::Sym &, | ||
| 819 | uint32_t Alignment, uint32_t); | ||
| 820 | template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile<ELF64LE> &, | ||
| 821 | const typename ELF64LE::Sym &, | ||
| 822 | uint32_t Alignment, uint32_t); | ||
| 823 | template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile<ELF64BE> &, | ||
| 824 | const typename ELF64BE::Sym &, | ||
| 825 | uint32_t Alignment, uint32_t); | ||
| 826 | |||
| 827 | template void SymbolTable::fetchIfLazy<ELF32LE>(StringRef); | ||
| 828 | template void SymbolTable::fetchIfLazy<ELF32BE>(StringRef); | ||
| 829 | template void SymbolTable::fetchIfLazy<ELF64LE>(StringRef); | ||
| 830 | template void SymbolTable::fetchIfLazy<ELF64BE>(StringRef); | ||
| 831 | |||
| 832 | template void SymbolTable::scanShlibUndefined<ELF32LE>(); | ||
| 833 | template void SymbolTable::scanShlibUndefined<ELF32BE>(); | ||
| 834 | template void SymbolTable::scanShlibUndefined<ELF64LE>(); | ||
| 835 | template void SymbolTable::scanShlibUndefined<ELF64BE>(); |
deps/lld/ELF/SymbolTable.h+48-53| ... | @@ -18,8 +18,8 @@ | ... | @@ -18,8 +18,8 @@ |
| 18 | 18 | ||
| 19 | namespace lld { | 19 | namespace lld { |
| 20 | namespace elf { | 20 | namespace elf { |
| 21 | 21 | class Defined; | |
| 22 | struct Symbol; | 22 | class SectionBase; |
| 23 | 23 | ||
| 24 | // SymbolTable is a bucket of all known symbols, including defined, | 24 | // SymbolTable is a bucket of all known symbols, including defined, |
| 25 | // undefined, or lazy symbols (the last one is symbols in archive | 25 | // undefined, or lazy symbols (the last one is symbols in archive |
| ... | @@ -33,78 +33,71 @@ struct Symbol; | ... | @@ -33,78 +33,71 @@ struct Symbol; |
| 33 | // to replace the lazy symbol. The logic is implemented in the | 33 | // to replace the lazy symbol. The logic is implemented in the |
| 34 | // add*() functions, which are called by input files as they are parsed. There | 34 | // add*() functions, which are called by input files as they are parsed. There |
| 35 | // is one add* function per symbol type. | 35 | // is one add* function per symbol type. |
| 36 | template <class ELFT> class SymbolTable { | 36 | class SymbolTable { |
| 37 | typedef typename ELFT::Sym Elf_Sym; | ||
| 38 | |||
| 39 | public: | 37 | public: |
| 40 | void addFile(InputFile *File); | 38 | template <class ELFT> void addFile(InputFile *File); |
| 41 | void addCombinedLTOObject(); | 39 | template <class ELFT> void addCombinedLTOObject(); |
| 42 | void addSymbolAlias(StringRef Alias, StringRef Name); | 40 | template <class ELFT> void addSymbolWrap(StringRef Name); |
| 43 | void addSymbolWrap(StringRef Name); | 41 | void applySymbolWrap(); |
| 44 | void applySymbolRenames(); | ||
| 45 | 42 | ||
| 46 | ArrayRef<Symbol *> getSymbols() const { return SymVector; } | 43 | ArrayRef<Symbol *> getSymbols() const { return SymVector; } |
| 47 | ArrayRef<ObjectFile<ELFT> *> getObjectFiles() const { return ObjectFiles; } | ||
| 48 | ArrayRef<BinaryFile *> getBinaryFiles() const { return BinaryFiles; } | ||
| 49 | ArrayRef<SharedFile<ELFT> *> getSharedFiles() const { return SharedFiles; } | ||
| 50 | 44 | ||
| 51 | DefinedRegular *addAbsolute(StringRef Name, | 45 | Defined *addAbsolute(StringRef Name, |
| 52 | uint8_t Visibility = llvm::ELF::STV_HIDDEN, | 46 | uint8_t Visibility = llvm::ELF::STV_HIDDEN, |
| 53 | uint8_t Binding = llvm::ELF::STB_GLOBAL); | 47 | uint8_t Binding = llvm::ELF::STB_GLOBAL); |
| 54 | DefinedRegular *addIgnored(StringRef Name, | ||
| 55 | uint8_t Visibility = llvm::ELF::STV_HIDDEN); | ||
| 56 | |||
| 57 | Symbol *addUndefined(StringRef Name); | ||
| 58 | Symbol *addUndefined(StringRef Name, bool IsLocal, uint8_t Binding, | ||
| 59 | uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, | ||
| 60 | InputFile *File); | ||
| 61 | 48 | ||
| 49 | template <class ELFT> Symbol *addUndefined(StringRef Name); | ||
| 50 | template <class ELFT> | ||
| 51 | Symbol *addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther, | ||
| 52 | uint8_t Type, bool CanOmitFromDynSym, InputFile *File); | ||
| 62 | Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, | 53 | Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, |
| 63 | uint64_t Value, uint64_t Size, uint8_t Binding, | 54 | uint64_t Value, uint64_t Size, uint8_t Binding, |
| 64 | SectionBase *Section, InputFile *File); | 55 | SectionBase *Section, InputFile *File); |
| 65 | 56 | ||
| 66 | void addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym, | 57 | template <class ELFT> |
| 67 | const typename ELFT::Verdef *Verdef); | 58 | void addShared(StringRef Name, SharedFile<ELFT> &F, |
| 59 | const typename ELFT::Sym &Sym, uint32_t Alignment, | ||
| 60 | uint32_t VerdefIndex); | ||
| 61 | |||
| 62 | template <class ELFT> | ||
| 63 | Symbol *addLazyArchive(StringRef Name, ArchiveFile &F, | ||
| 64 | const llvm::object::Archive::Symbol S); | ||
| 65 | |||
| 66 | template <class ELFT> void addLazyObject(StringRef Name, LazyObjFile &Obj); | ||
| 68 | 67 | ||
| 69 | Symbol *addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S); | ||
| 70 | void addLazyObject(StringRef Name, LazyObjectFile &Obj); | ||
| 71 | Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther, | 68 | Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther, |
| 72 | uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *File); | 69 | uint8_t Type, bool CanOmitFromDynSym, BitcodeFile &File); |
| 73 | 70 | ||
| 74 | Symbol *addCommon(StringRef N, uint64_t Size, uint32_t Alignment, | 71 | Symbol *addCommon(StringRef Name, uint64_t Size, uint32_t Alignment, |
| 75 | uint8_t Binding, uint8_t StOther, uint8_t Type, | 72 | uint8_t Binding, uint8_t StOther, uint8_t Type, |
| 76 | InputFile *File); | 73 | InputFile &File); |
| 77 | 74 | ||
| 78 | std::pair<Symbol *, bool> insert(StringRef Name); | 75 | std::pair<Symbol *, bool> insert(StringRef Name); |
| 79 | std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type, | 76 | std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type, |
| 80 | uint8_t Visibility, bool CanOmitFromDynSym, | 77 | uint8_t Visibility, bool CanOmitFromDynSym, |
| 81 | InputFile *File); | 78 | InputFile *File); |
| 82 | 79 | ||
| 83 | void scanUndefinedFlags(); | 80 | template <class ELFT> void fetchIfLazy(StringRef Name); |
| 84 | void scanShlibUndefined(); | 81 | template <class ELFT> void scanShlibUndefined(); |
| 85 | void scanVersionScript(); | 82 | void scanVersionScript(); |
| 86 | 83 | ||
| 87 | SymbolBody *find(StringRef Name); | 84 | Symbol *find(StringRef Name); |
| 88 | SymbolBody *findInCurrentDSO(StringRef Name); | ||
| 89 | 85 | ||
| 90 | void trace(StringRef Name); | 86 | void trace(StringRef Name); |
| 91 | 87 | ||
| 88 | void handleDynamicList(); | ||
| 89 | |||
| 92 | private: | 90 | private: |
| 93 | std::vector<SymbolBody *> findByVersion(SymbolVersion Ver); | 91 | std::vector<Symbol *> findByVersion(SymbolVersion Ver); |
| 94 | std::vector<SymbolBody *> findAllByVersion(SymbolVersion Ver); | 92 | std::vector<Symbol *> findAllByVersion(SymbolVersion Ver); |
| 93 | void defsym(Symbol *Dst, Symbol *Src); | ||
| 95 | 94 | ||
| 96 | llvm::StringMap<std::vector<SymbolBody *>> &getDemangledSyms(); | 95 | llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms(); |
| 97 | void handleAnonymousVersion(); | 96 | void handleAnonymousVersion(); |
| 98 | void assignExactVersion(SymbolVersion Ver, uint16_t VersionId, | 97 | void assignExactVersion(SymbolVersion Ver, uint16_t VersionId, |
| 99 | StringRef VersionName); | 98 | StringRef VersionName); |
| 100 | void assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId); | 99 | void assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId); |
| 101 | 100 | ||
| 102 | struct SymIndex { | ||
| 103 | SymIndex(int Idx, bool Traced) : Idx(Idx), Traced(Traced) {} | ||
| 104 | int Idx : 31; | ||
| 105 | unsigned Traced : 1; | ||
| 106 | }; | ||
| 107 | |||
| 108 | // The order the global symbols are in is not defined. We can use an arbitrary | 101 | // The order the global symbols are in is not defined. We can use an arbitrary |
| 109 | // order, but it has to be reproducible. That is true even when cross linking. | 102 | // order, but it has to be reproducible. That is true even when cross linking. |
| 110 | // The default hashing of StringRef produces different results on 32 and 64 | 103 | // The default hashing of StringRef produces different results on 32 and 64 |
| ... | @@ -112,7 +105,7 @@ private: | ... | @@ -112,7 +105,7 @@ private: |
| 112 | // but a bit inefficient. | 105 | // but a bit inefficient. |
| 113 | // FIXME: Experiment with passing in a custom hashing or sorting the symbols | 106 | // FIXME: Experiment with passing in a custom hashing or sorting the symbols |
| 114 | // once symbol resolution is finished. | 107 | // once symbol resolution is finished. |
| 115 | llvm::DenseMap<llvm::CachedHashStringRef, SymIndex> Symtab; | 108 | llvm::DenseMap<llvm::CachedHashStringRef, int> SymMap; |
| 116 | std::vector<Symbol *> SymVector; | 109 | std::vector<Symbol *> SymVector; |
| 117 | 110 | ||
| 118 | // Comdat groups define "link once" sections. If two comdat groups have the | 111 | // Comdat groups define "link once" sections. If two comdat groups have the |
| ... | @@ -120,11 +113,6 @@ private: | ... | @@ -120,11 +113,6 @@ private: |
| 120 | // is used to uniquify them. | 113 | // is used to uniquify them. |
| 121 | llvm::DenseSet<llvm::CachedHashStringRef> ComdatGroups; | 114 | llvm::DenseSet<llvm::CachedHashStringRef> ComdatGroups; |
| 122 | 115 | ||
| 123 | std::vector<ObjectFile<ELFT> *> ObjectFiles; | ||
| 124 | std::vector<SharedFile<ELFT> *> SharedFiles; | ||
| 125 | std::vector<BitcodeFile *> BitcodeFiles; | ||
| 126 | std::vector<BinaryFile *> BinaryFiles; | ||
| 127 | |||
| 128 | // Set of .so files to not link the same shared object file more than once. | 116 | // Set of .so files to not link the same shared object file more than once. |
| 129 | llvm::DenseSet<StringRef> SoNames; | 117 | llvm::DenseSet<StringRef> SoNames; |
| 130 | 118 | ||
| ... | @@ -132,15 +120,22 @@ private: | ... | @@ -132,15 +120,22 @@ private: |
| 132 | // This mapping is 1:N because two symbols with different versions | 120 | // This mapping is 1:N because two symbols with different versions |
| 133 | // can have the same name. We use this map to handle "extern C++ {}" | 121 | // can have the same name. We use this map to handle "extern C++ {}" |
| 134 | // directive in version scripts. | 122 | // directive in version scripts. |
| 135 | llvm::Optional<llvm::StringMap<std::vector<SymbolBody *>>> DemangledSyms; | 123 | llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> DemangledSyms; |
| 124 | |||
| 125 | struct WrappedSymbol { | ||
| 126 | Symbol *Sym; | ||
| 127 | Symbol *Real; | ||
| 128 | Symbol *Wrap; | ||
| 129 | }; | ||
| 130 | |||
| 131 | // For -wrap. | ||
| 132 | std::vector<WrappedSymbol> WrappedSymbols; | ||
| 136 | 133 | ||
| 137 | // For LTO. | 134 | // For LTO. |
| 138 | std::unique_ptr<BitcodeCompiler> LTO; | 135 | std::unique_ptr<BitcodeCompiler> LTO; |
| 139 | }; | 136 | }; |
| 140 | 137 | ||
| 141 | template <class ELFT> struct Symtab { static SymbolTable<ELFT> *X; }; | 138 | extern SymbolTable *Symtab; |
| 142 | template <class ELFT> SymbolTable<ELFT> *Symtab<ELFT>::X; | ||
| 143 | |||
| 144 | } // namespace elf | 139 | } // namespace elf |
| 145 | } // namespace lld | 140 | } // namespace lld |
| 146 | 141 |
deps/lld/ELF/Symbols.cpp+67-184| ... | @@ -8,15 +8,15 @@ | ... | @@ -8,15 +8,15 @@ |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Symbols.h" | 10 | #include "Symbols.h" |
| 11 | #include "Error.h" | ||
| 12 | #include "InputFiles.h" | 11 | #include "InputFiles.h" |
| 13 | #include "InputSection.h" | 12 | #include "InputSection.h" |
| 14 | #include "OutputSections.h" | 13 | #include "OutputSections.h" |
| 15 | #include "Strings.h" | ||
| 16 | #include "SyntheticSections.h" | 14 | #include "SyntheticSections.h" |
| 17 | #include "Target.h" | 15 | #include "Target.h" |
| 18 | #include "Writer.h" | 16 | #include "Writer.h" |
| 19 | 17 | ||
| 18 | #include "lld/Common/ErrorHandler.h" | ||
| 19 | #include "lld/Common/Strings.h" | ||
| 20 | #include "llvm/ADT/STLExtras.h" | 20 | #include "llvm/ADT/STLExtras.h" |
| 21 | #include "llvm/Support/Path.h" | 21 | #include "llvm/Support/Path.h" |
| 22 | #include <cstring> | 22 | #include <cstring> |
| ... | @@ -28,25 +28,23 @@ using namespace llvm::ELF; | ... | @@ -28,25 +28,23 @@ using namespace llvm::ELF; |
| 28 | using namespace lld; | 28 | using namespace lld; |
| 29 | using namespace lld::elf; | 29 | using namespace lld::elf; |
| 30 | 30 | ||
| 31 | DefinedRegular *ElfSym::Bss; | 31 | Defined *ElfSym::Bss; |
| 32 | DefinedRegular *ElfSym::Etext1; | 32 | Defined *ElfSym::Etext1; |
| 33 | DefinedRegular *ElfSym::Etext2; | 33 | Defined *ElfSym::Etext2; |
| 34 | DefinedRegular *ElfSym::Edata1; | 34 | Defined *ElfSym::Edata1; |
| 35 | DefinedRegular *ElfSym::Edata2; | 35 | Defined *ElfSym::Edata2; |
| 36 | DefinedRegular *ElfSym::End1; | 36 | Defined *ElfSym::End1; |
| 37 | DefinedRegular *ElfSym::End2; | 37 | Defined *ElfSym::End2; |
| 38 | DefinedRegular *ElfSym::GlobalOffsetTable; | 38 | Defined *ElfSym::GlobalOffsetTable; |
| 39 | DefinedRegular *ElfSym::MipsGp; | 39 | Defined *ElfSym::MipsGp; |
| 40 | DefinedRegular *ElfSym::MipsGpDisp; | 40 | Defined *ElfSym::MipsGpDisp; |
| 41 | DefinedRegular *ElfSym::MipsLocalGp; | 41 | Defined *ElfSym::MipsLocalGp; |
| 42 | 42 | ||
| 43 | static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) { | 43 | static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) { |
| 44 | switch (Body.kind()) { | 44 | switch (Sym.kind()) { |
| 45 | case SymbolBody::DefinedRegularKind: { | 45 | case Symbol::DefinedKind: { |
| 46 | auto &D = cast<DefinedRegular>(Body); | 46 | auto &D = cast<Defined>(Sym); |
| 47 | SectionBase *IS = D.Section; | 47 | SectionBase *IS = D.Section; |
| 48 | if (auto *ISB = dyn_cast_or_null<InputSectionBase>(IS)) | ||
| 49 | IS = ISB->Repl; | ||
| 50 | 48 | ||
| 51 | // According to the ELF spec reference to a local symbol from outside | 49 | // According to the ELF spec reference to a local symbol from outside |
| 52 | // the group are not allowed. Unfortunately .eh_frame breaks that rule | 50 | // the group are not allowed. Unfortunately .eh_frame breaks that rule |
| ... | @@ -59,6 +57,7 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) { | ... | @@ -59,6 +57,7 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) { |
| 59 | if (!IS) | 57 | if (!IS) |
| 60 | return D.Value; | 58 | return D.Value; |
| 61 | 59 | ||
| 60 | IS = IS->Repl; | ||
| 62 | uint64_t Offset = D.Value; | 61 | uint64_t Offset = D.Value; |
| 63 | 62 | ||
| 64 | // An object in an SHF_MERGE section might be referenced via a | 63 | // An object in an SHF_MERGE section might be referenced via a |
| ... | @@ -99,139 +98,79 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) { | ... | @@ -99,139 +98,79 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) { |
| 99 | } | 98 | } |
| 100 | return VA; | 99 | return VA; |
| 101 | } | 100 | } |
| 102 | case SymbolBody::DefinedCommonKind: | 101 | case Symbol::SharedKind: { |
| 103 | if (!Config->DefineCommon) | 102 | auto &SS = cast<SharedSymbol>(Sym); |
| 104 | return 0; | 103 | if (SS.CopyRelSec) |
| 105 | return InX::Common->getParent()->Addr + InX::Common->OutSecOff + | 104 | return SS.CopyRelSec->getParent()->Addr + SS.CopyRelSec->OutSecOff; |
| 106 | cast<DefinedCommon>(Body).Offset; | ||
| 107 | case SymbolBody::SharedKind: { | ||
| 108 | auto &SS = cast<SharedSymbol>(Body); | ||
| 109 | if (SS.NeedsCopy) | ||
| 110 | return SS.CopyRelSec->getParent()->Addr + SS.CopyRelSec->OutSecOff + | ||
| 111 | SS.CopyRelSecOff; | ||
| 112 | if (SS.NeedsPltAddr) | 105 | if (SS.NeedsPltAddr) |
| 113 | return Body.getPltVA(); | 106 | return Sym.getPltVA(); |
| 114 | return 0; | 107 | return 0; |
| 115 | } | 108 | } |
| 116 | case SymbolBody::UndefinedKind: | 109 | case Symbol::UndefinedKind: |
| 117 | return 0; | 110 | return 0; |
| 118 | case SymbolBody::LazyArchiveKind: | 111 | case Symbol::LazyArchiveKind: |
| 119 | case SymbolBody::LazyObjectKind: | 112 | case Symbol::LazyObjectKind: |
| 120 | assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer"); | 113 | assert(Sym.IsUsedInRegularObj && "lazy symbol reached writer"); |
| 121 | return 0; | 114 | return 0; |
| 122 | } | 115 | } |
| 123 | llvm_unreachable("invalid symbol kind"); | 116 | llvm_unreachable("invalid symbol kind"); |
| 124 | } | 117 | } |
| 125 | 118 | ||
| 126 | SymbolBody::SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, | 119 | uint64_t Symbol::getVA(int64_t Addend) const { |
| 127 | uint8_t Type) | ||
| 128 | : SymbolKind(K), NeedsCopy(false), NeedsPltAddr(false), IsLocal(IsLocal), | ||
| 129 | IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false), | ||
| 130 | IsInIgot(false), Type(Type), StOther(StOther), Name(Name) {} | ||
| 131 | |||
| 132 | // Returns true if a symbol can be replaced at load-time by a symbol | ||
| 133 | // with the same name defined in other ELF executable or DSO. | ||
| 134 | bool SymbolBody::isPreemptible() const { | ||
| 135 | if (isLocal()) | ||
| 136 | return false; | ||
| 137 | |||
| 138 | // Shared symbols resolve to the definition in the DSO. The exceptions are | ||
| 139 | // symbols with copy relocations (which resolve to .bss) or preempt plt | ||
| 140 | // entries (which resolve to that plt entry). | ||
| 141 | if (isShared()) | ||
| 142 | return !NeedsCopy && !NeedsPltAddr; | ||
| 143 | |||
| 144 | // That's all that can be preempted in a non-DSO. | ||
| 145 | if (!Config->Shared) | ||
| 146 | return false; | ||
| 147 | |||
| 148 | // Only symbols that appear in dynsym can be preempted. | ||
| 149 | if (!symbol()->includeInDynsym()) | ||
| 150 | return false; | ||
| 151 | |||
| 152 | // Only default visibility symbols can be preempted. | ||
| 153 | if (symbol()->Visibility != STV_DEFAULT) | ||
| 154 | return false; | ||
| 155 | |||
| 156 | // -Bsymbolic means that definitions are not preempted. | ||
| 157 | if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc())) | ||
| 158 | return !isDefined(); | ||
| 159 | return true; | ||
| 160 | } | ||
| 161 | |||
| 162 | // Overwrites all attributes with Other's so that this symbol becomes | ||
| 163 | // an alias to Other. This is useful for handling some options such as | ||
| 164 | // --wrap. | ||
| 165 | void SymbolBody::copy(SymbolBody *Other) { | ||
| 166 | memcpy(symbol()->Body.buffer, Other->symbol()->Body.buffer, | ||
| 167 | sizeof(Symbol::Body)); | ||
| 168 | } | ||
| 169 | |||
| 170 | uint64_t SymbolBody::getVA(int64_t Addend) const { | ||
| 171 | uint64_t OutVA = getSymVA(*this, Addend); | 120 | uint64_t OutVA = getSymVA(*this, Addend); |
| 172 | return OutVA + Addend; | 121 | return OutVA + Addend; |
| 173 | } | 122 | } |
| 174 | 123 | ||
| 175 | uint64_t SymbolBody::getGotVA() const { | 124 | uint64_t Symbol::getGotVA() const { return InX::Got->getVA() + getGotOffset(); } |
| 176 | return InX::Got->getVA() + getGotOffset(); | ||
| 177 | } | ||
| 178 | 125 | ||
| 179 | uint64_t SymbolBody::getGotOffset() const { | 126 | uint64_t Symbol::getGotOffset() const { |
| 180 | return GotIndex * Target->GotEntrySize; | 127 | return GotIndex * Target->GotEntrySize; |
| 181 | } | 128 | } |
| 182 | 129 | ||
| 183 | uint64_t SymbolBody::getGotPltVA() const { | 130 | uint64_t Symbol::getGotPltVA() const { |
| 184 | if (this->IsInIgot) | 131 | if (this->IsInIgot) |
| 185 | return InX::IgotPlt->getVA() + getGotPltOffset(); | 132 | return InX::IgotPlt->getVA() + getGotPltOffset(); |
| 186 | return InX::GotPlt->getVA() + getGotPltOffset(); | 133 | return InX::GotPlt->getVA() + getGotPltOffset(); |
| 187 | } | 134 | } |
| 188 | 135 | ||
| 189 | uint64_t SymbolBody::getGotPltOffset() const { | 136 | uint64_t Symbol::getGotPltOffset() const { |
| 190 | return GotPltIndex * Target->GotPltEntrySize; | 137 | return GotPltIndex * Target->GotPltEntrySize; |
| 191 | } | 138 | } |
| 192 | 139 | ||
| 193 | uint64_t SymbolBody::getPltVA() const { | 140 | uint64_t Symbol::getPltVA() const { |
| 194 | if (this->IsInIplt) | 141 | if (this->IsInIplt) |
| 195 | return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize; | 142 | return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize; |
| 196 | return InX::Plt->getVA() + Target->PltHeaderSize + | 143 | return InX::Plt->getVA() + Target->PltHeaderSize + |
| 197 | PltIndex * Target->PltEntrySize; | 144 | PltIndex * Target->PltEntrySize; |
| 198 | } | 145 | } |
| 199 | 146 | ||
| 200 | template <class ELFT> typename ELFT::uint SymbolBody::getSize() const { | 147 | uint64_t Symbol::getSize() const { |
| 201 | if (const auto *C = dyn_cast<DefinedCommon>(this)) | 148 | if (const auto *DR = dyn_cast<Defined>(this)) |
| 202 | return C->Size; | ||
| 203 | if (const auto *DR = dyn_cast<DefinedRegular>(this)) | ||
| 204 | return DR->Size; | 149 | return DR->Size; |
| 205 | if (const auto *S = dyn_cast<SharedSymbol>(this)) | 150 | if (const auto *S = dyn_cast<SharedSymbol>(this)) |
| 206 | return S->getSize<ELFT>(); | 151 | return S->Size; |
| 207 | return 0; | 152 | return 0; |
| 208 | } | 153 | } |
| 209 | 154 | ||
| 210 | OutputSection *SymbolBody::getOutputSection() const { | 155 | OutputSection *Symbol::getOutputSection() const { |
| 211 | if (auto *S = dyn_cast<DefinedRegular>(this)) { | 156 | if (auto *S = dyn_cast<Defined>(this)) { |
| 212 | if (S->Section) | 157 | if (auto *Sec = S->Section) |
| 213 | return S->Section->getOutputSection(); | 158 | return Sec->Repl->getOutputSection(); |
| 214 | return nullptr; | 159 | return nullptr; |
| 215 | } | 160 | } |
| 216 | 161 | ||
| 217 | if (auto *S = dyn_cast<SharedSymbol>(this)) { | 162 | if (auto *S = dyn_cast<SharedSymbol>(this)) { |
| 218 | if (S->NeedsCopy) | 163 | if (S->CopyRelSec) |
| 219 | return S->CopyRelSec->getParent(); | 164 | return S->CopyRelSec->getParent(); |
| 220 | return nullptr; | 165 | return nullptr; |
| 221 | } | 166 | } |
| 222 | 167 | ||
| 223 | if (isa<DefinedCommon>(this)) { | ||
| 224 | if (Config->DefineCommon) | ||
| 225 | return InX::Common->getParent(); | ||
| 226 | return nullptr; | ||
| 227 | } | ||
| 228 | |||
| 229 | return nullptr; | 168 | return nullptr; |
| 230 | } | 169 | } |
| 231 | 170 | ||
| 232 | // If a symbol name contains '@', the characters after that is | 171 | // If a symbol name contains '@', the characters after that is |
| 233 | // a symbol version name. This function parses that. | 172 | // a symbol version name. This function parses that. |
| 234 | void SymbolBody::parseSymbolVersion() { | 173 | void Symbol::parseSymbolVersion() { |
| 235 | StringRef S = getName(); | 174 | StringRef S = getName(); |
| 236 | size_t Pos = S.find('@'); | 175 | size_t Pos = S.find('@'); |
| 237 | if (Pos == 0 || Pos == StringRef::npos) | 176 | if (Pos == 0 || Pos == StringRef::npos) |
| ... | @@ -244,7 +183,7 @@ void SymbolBody::parseSymbolVersion() { | ... | @@ -244,7 +183,7 @@ void SymbolBody::parseSymbolVersion() { |
| 244 | Name = {S.data(), Pos}; | 183 | Name = {S.data(), Pos}; |
| 245 | 184 | ||
| 246 | // If this is not in this DSO, it is not a definition. | 185 | // If this is not in this DSO, it is not a definition. |
| 247 | if (!isInCurrentDSO()) | 186 | if (!isDefined()) |
| 248 | return; | 187 | return; |
| 249 | 188 | ||
| 250 | // '@@' in a symbol name means the default version. | 189 | // '@@' in a symbol name means the default version. |
| ... | @@ -258,9 +197,9 @@ void SymbolBody::parseSymbolVersion() { | ... | @@ -258,9 +197,9 @@ void SymbolBody::parseSymbolVersion() { |
| 258 | continue; | 197 | continue; |
| 259 | 198 | ||
| 260 | if (IsDefault) | 199 | if (IsDefault) |
| 261 | symbol()->VersionId = Ver.Id; | 200 | VersionId = Ver.Id; |
| 262 | else | 201 | else |
| 263 | symbol()->VersionId = Ver.Id | VERSYM_HIDDEN; | 202 | VersionId = Ver.Id | VERSYM_HIDDEN; |
| 264 | return; | 203 | return; |
| 265 | } | 204 | } |
| 266 | 205 | ||
| ... | @@ -273,81 +212,34 @@ void SymbolBody::parseSymbolVersion() { | ... | @@ -273,81 +212,34 @@ void SymbolBody::parseSymbolVersion() { |
| 273 | Verstr); | 212 | Verstr); |
| 274 | } | 213 | } |
| 275 | 214 | ||
| 276 | Defined::Defined(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, | ||
| 277 | uint8_t Type) | ||
| 278 | : SymbolBody(K, Name, IsLocal, StOther, Type) {} | ||
| 279 | |||
| 280 | template <class ELFT> bool DefinedRegular::isMipsPIC() const { | ||
| 281 | typedef typename ELFT::Ehdr Elf_Ehdr; | ||
| 282 | if (!Section || !isFunc()) | ||
| 283 | return false; | ||
| 284 | |||
| 285 | auto *Sec = cast<InputSectionBase>(Section); | ||
| 286 | const Elf_Ehdr *Hdr = Sec->template getFile<ELFT>()->getObj().getHeader(); | ||
| 287 | return (this->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC || | ||
| 288 | (Hdr->e_flags & EF_MIPS_PIC); | ||
| 289 | } | ||
| 290 | |||
| 291 | Undefined::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, | ||
| 292 | uint8_t Type, InputFile *File) | ||
| 293 | : SymbolBody(SymbolBody::UndefinedKind, Name, IsLocal, StOther, Type) { | ||
| 294 | this->File = File; | ||
| 295 | } | ||
| 296 | |||
| 297 | DefinedCommon::DefinedCommon(StringRef Name, uint64_t Size, uint32_t Alignment, | ||
| 298 | uint8_t StOther, uint8_t Type, InputFile *File) | ||
| 299 | : Defined(SymbolBody::DefinedCommonKind, Name, /*IsLocal=*/false, StOther, | ||
| 300 | Type), | ||
| 301 | Alignment(Alignment), Size(Size) { | ||
| 302 | this->File = File; | ||
| 303 | } | ||
| 304 | |||
| 305 | // If a shared symbol is referred via a copy relocation, its alignment | ||
| 306 | // becomes part of the ABI. This function returns a symbol alignment. | ||
| 307 | // Because symbols don't have alignment attributes, we need to infer that. | ||
| 308 | template <class ELFT> uint32_t SharedSymbol::getAlignment() const { | ||
| 309 | auto *File = cast<SharedFile<ELFT>>(this->File); | ||
| 310 | uint32_t SecAlign = File->getSection(getSym<ELFT>())->sh_addralign; | ||
| 311 | uint64_t SymValue = getSym<ELFT>().st_value; | ||
| 312 | uint32_t SymAlign = uint32_t(1) << countTrailingZeros(SymValue); | ||
| 313 | return std::min(SecAlign, SymAlign); | ||
| 314 | } | ||
| 315 | |||
| 316 | InputFile *Lazy::fetch() { | 215 | InputFile *Lazy::fetch() { |
| 317 | if (auto *S = dyn_cast<LazyArchive>(this)) | 216 | if (auto *S = dyn_cast<LazyArchive>(this)) |
| 318 | return S->fetch(); | 217 | return S->fetch(); |
| 319 | return cast<LazyObject>(this)->fetch(); | 218 | return cast<LazyObject>(this)->fetch(); |
| 320 | } | 219 | } |
| 321 | 220 | ||
| 322 | LazyArchive::LazyArchive(ArchiveFile &File, | 221 | ArchiveFile &LazyArchive::getFile() { return *cast<ArchiveFile>(File); } |
| 323 | const llvm::object::Archive::Symbol S, uint8_t Type) | ||
| 324 | : Lazy(LazyArchiveKind, S.getName(), Type), Sym(S) { | ||
| 325 | this->File = &File; | ||
| 326 | } | ||
| 327 | |||
| 328 | LazyObject::LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type) | ||
| 329 | : Lazy(LazyObjectKind, Name, Type) { | ||
| 330 | this->File = &File; | ||
| 331 | } | ||
| 332 | 222 | ||
| 333 | InputFile *LazyArchive::fetch() { | 223 | InputFile *LazyArchive::fetch() { |
| 334 | std::pair<MemoryBufferRef, uint64_t> MBInfo = file()->getMember(&Sym); | 224 | std::pair<MemoryBufferRef, uint64_t> MBInfo = getFile().getMember(&Sym); |
| 335 | 225 | ||
| 336 | // getMember returns an empty buffer if the member was already | 226 | // getMember returns an empty buffer if the member was already |
| 337 | // read from the library. | 227 | // read from the library. |
| 338 | if (MBInfo.first.getBuffer().empty()) | 228 | if (MBInfo.first.getBuffer().empty()) |
| 339 | return nullptr; | 229 | return nullptr; |
| 340 | return createObjectFile(MBInfo.first, file()->getName(), MBInfo.second); | 230 | return createObjectFile(MBInfo.first, getFile().getName(), MBInfo.second); |
| 341 | } | 231 | } |
| 342 | 232 | ||
| 343 | InputFile *LazyObject::fetch() { return file()->fetch(); } | 233 | LazyObjFile &LazyObject::getFile() { return *cast<LazyObjFile>(File); } |
| 234 | |||
| 235 | InputFile *LazyObject::fetch() { return getFile().fetch(); } | ||
| 344 | 236 | ||
| 345 | uint8_t Symbol::computeBinding() const { | 237 | uint8_t Symbol::computeBinding() const { |
| 346 | if (Config->Relocatable) | 238 | if (Config->Relocatable) |
| 347 | return Binding; | 239 | return Binding; |
| 348 | if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) | 240 | if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) |
| 349 | return STB_LOCAL; | 241 | return STB_LOCAL; |
| 350 | if (VersionId == VER_NDX_LOCAL && body()->isInCurrentDSO()) | 242 | if (VersionId == VER_NDX_LOCAL && isDefined()) |
| 351 | return STB_LOCAL; | 243 | return STB_LOCAL; |
| 352 | if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE) | 244 | if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE) |
| 353 | return STB_GLOBAL; | 245 | return STB_GLOBAL; |
| ... | @@ -355,45 +247,36 @@ uint8_t Symbol::computeBinding() const { | ... | @@ -355,45 +247,36 @@ uint8_t Symbol::computeBinding() const { |
| 355 | } | 247 | } |
| 356 | 248 | ||
| 357 | bool Symbol::includeInDynsym() const { | 249 | bool Symbol::includeInDynsym() const { |
| 250 | if (!Config->HasDynSymTab) | ||
| 251 | return false; | ||
| 358 | if (computeBinding() == STB_LOCAL) | 252 | if (computeBinding() == STB_LOCAL) |
| 359 | return false; | 253 | return false; |
| 360 | return ExportDynamic || body()->isShared() || | 254 | if (!isDefined()) |
| 361 | (body()->isUndefined() && Config->Shared); | 255 | return true; |
| 256 | return ExportDynamic; | ||
| 362 | } | 257 | } |
| 363 | 258 | ||
| 364 | // Print out a log message for --trace-symbol. | 259 | // Print out a log message for --trace-symbol. |
| 365 | void elf::printTraceSymbol(Symbol *Sym) { | 260 | void elf::printTraceSymbol(Symbol *Sym) { |
| 366 | SymbolBody *B = Sym->body(); | ||
| 367 | std::string S; | 261 | std::string S; |
| 368 | if (B->isUndefined()) | 262 | if (Sym->isUndefined()) |
| 369 | S = ": reference to "; | 263 | S = ": reference to "; |
| 370 | else if (B->isCommon()) | 264 | else if (Sym->isLazy()) |
| 265 | S = ": lazy definition of "; | ||
| 266 | else if (Sym->isShared()) | ||
| 267 | S = ": shared definition of "; | ||
| 268 | else if (dyn_cast_or_null<BssSection>(cast<Defined>(Sym)->Section)) | ||
| 371 | S = ": common definition of "; | 269 | S = ": common definition of "; |
| 372 | else | 270 | else |
| 373 | S = ": definition of "; | 271 | S = ": definition of "; |
| 374 | 272 | ||
| 375 | message(toString(B->File) + S + B->getName()); | 273 | message(toString(Sym->File) + S + Sym->getName()); |
| 376 | } | 274 | } |
| 377 | 275 | ||
| 378 | // Returns a symbol for an error message. | 276 | // Returns a symbol for an error message. |
| 379 | std::string lld::toString(const SymbolBody &B) { | 277 | std::string lld::toString(const Symbol &B) { |
| 380 | if (Config->Demangle) | 278 | if (Config->Demangle) |
| 381 | if (Optional<std::string> S = demangle(B.getName())) | 279 | if (Optional<std::string> S = demangleItanium(B.getName())) |
| 382 | return *S; | 280 | return *S; |
| 383 | return B.getName(); | 281 | return B.getName(); |
| 384 | } | 282 | } |
| 385 | |||
| 386 | template uint32_t SymbolBody::template getSize<ELF32LE>() const; | ||
| 387 | template uint32_t SymbolBody::template getSize<ELF32BE>() const; | ||
| 388 | template uint64_t SymbolBody::template getSize<ELF64LE>() const; | ||
| 389 | template uint64_t SymbolBody::template getSize<ELF64BE>() const; | ||
| 390 | |||
| 391 | template bool DefinedRegular::template isMipsPIC<ELF32LE>() const; | ||
| 392 | template bool DefinedRegular::template isMipsPIC<ELF32BE>() const; | ||
| 393 | template bool DefinedRegular::template isMipsPIC<ELF64LE>() const; | ||
| 394 | template bool DefinedRegular::template isMipsPIC<ELF64BE>() const; | ||
| 395 | |||
| 396 | template uint32_t SharedSymbol::template getAlignment<ELF32LE>() const; | ||
| 397 | template uint32_t SharedSymbol::template getAlignment<ELF32BE>() const; | ||
| 398 | template uint32_t SharedSymbol::template getAlignment<ELF64LE>() const; | ||
| 399 | template uint32_t SharedSymbol::template getAlignment<ELF64BE>() const; |
deps/lld/ELF/Symbols.h+184-216| ... | @@ -18,7 +18,7 @@ | ... | @@ -18,7 +18,7 @@ |
| 18 | #include "InputSection.h" | 18 | #include "InputSection.h" |
| 19 | #include "Strings.h" | 19 | #include "Strings.h" |
| 20 | 20 | ||
| 21 | #include "lld/Core/LLVM.h" | 21 | #include "lld/Common/LLVM.h" |
| 22 | #include "llvm/Object/Archive.h" | 22 | #include "llvm/Object/Archive.h" |
| 23 | #include "llvm/Object/ELF.h" | 23 | #include "llvm/Object/ELF.h" |
| 24 | 24 | ||
| ... | @@ -27,53 +27,89 @@ namespace elf { | ... | @@ -27,53 +27,89 @@ namespace elf { |
| 27 | 27 | ||
| 28 | class ArchiveFile; | 28 | class ArchiveFile; |
| 29 | class BitcodeFile; | 29 | class BitcodeFile; |
| 30 | class BssSection; | ||
| 30 | class InputFile; | 31 | class InputFile; |
| 31 | class LazyObjectFile; | 32 | class LazyObjFile; |
| 32 | template <class ELFT> class ObjectFile; | 33 | template <class ELFT> class ObjFile; |
| 33 | class OutputSection; | 34 | class OutputSection; |
| 34 | template <class ELFT> class SharedFile; | 35 | template <class ELFT> class SharedFile; |
| 35 | 36 | ||
| 36 | struct Symbol; | ||
| 37 | |||
| 38 | // The base class for real symbol classes. | 37 | // The base class for real symbol classes. |
| 39 | class SymbolBody { | 38 | class Symbol { |
| 40 | public: | 39 | public: |
| 41 | enum Kind { | 40 | enum Kind { |
| 42 | DefinedFirst, | 41 | DefinedKind, |
| 43 | DefinedRegularKind = DefinedFirst, | ||
| 44 | SharedKind, | 42 | SharedKind, |
| 45 | DefinedCommonKind, | ||
| 46 | DefinedLast = DefinedCommonKind, | ||
| 47 | UndefinedKind, | 43 | UndefinedKind, |
| 48 | LazyArchiveKind, | 44 | LazyArchiveKind, |
| 49 | LazyObjectKind, | 45 | LazyObjectKind, |
| 50 | }; | 46 | }; |
| 51 | 47 | ||
| 52 | SymbolBody(Kind K) : SymbolKind(K) {} | 48 | Kind kind() const { return static_cast<Kind>(SymbolKind); } |
| 53 | 49 | ||
| 54 | Symbol *symbol(); | 50 | // Symbol binding. This is not overwritten by replaceSymbol to track |
| 55 | const Symbol *symbol() const { | 51 | // changes during resolution. In particular: |
| 56 | return const_cast<SymbolBody *>(this)->symbol(); | 52 | // - An undefined weak is still weak when it resolves to a shared library. |
| 57 | } | 53 | // - An undefined weak will not fetch archive members, but we have to |
| 54 | // remember it is weak. | ||
| 55 | uint8_t Binding; | ||
| 58 | 56 | ||
| 59 | Kind kind() const { return static_cast<Kind>(SymbolKind); } | 57 | // Version definition index. |
| 58 | uint16_t VersionId; | ||
| 59 | |||
| 60 | // Symbol visibility. This is the computed minimum visibility of all | ||
| 61 | // observed non-DSO symbols. | ||
| 62 | unsigned Visibility : 2; | ||
| 63 | |||
| 64 | // True if the symbol was used for linking and thus need to be added to the | ||
| 65 | // output file's symbol table. This is true for all symbols except for | ||
| 66 | // unreferenced DSO symbols and bitcode symbols that are unreferenced except | ||
| 67 | // by other bitcode objects. | ||
| 68 | unsigned IsUsedInRegularObj : 1; | ||
| 69 | |||
| 70 | // If this flag is true and the symbol has protected or default visibility, it | ||
| 71 | // will appear in .dynsym. This flag is set by interposable DSO symbols in | ||
| 72 | // executables, by most symbols in DSOs and executables built with | ||
| 73 | // --export-dynamic, and by dynamic lists. | ||
| 74 | unsigned ExportDynamic : 1; | ||
| 75 | |||
| 76 | // False if LTO shouldn't inline whatever this symbol points to. If a symbol | ||
| 77 | // is overwritten after LTO, LTO shouldn't inline the symbol because it | ||
| 78 | // doesn't know the final contents of the symbol. | ||
| 79 | unsigned CanInline : 1; | ||
| 80 | |||
| 81 | // True if this symbol is specified by --trace-symbol option. | ||
| 82 | unsigned Traced : 1; | ||
| 83 | |||
| 84 | // This symbol version was found in a version script. | ||
| 85 | unsigned InVersionScript : 1; | ||
| 86 | |||
| 87 | // The file from which this symbol was created. | ||
| 88 | InputFile *File; | ||
| 89 | |||
| 90 | bool includeInDynsym() const; | ||
| 91 | uint8_t computeBinding() const; | ||
| 92 | bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } | ||
| 60 | 93 | ||
| 61 | bool isUndefined() const { return SymbolKind == UndefinedKind; } | 94 | bool isUndefined() const { return SymbolKind == UndefinedKind; } |
| 62 | bool isDefined() const { return SymbolKind <= DefinedLast; } | 95 | bool isDefined() const { return SymbolKind == DefinedKind; } |
| 63 | bool isCommon() const { return SymbolKind == DefinedCommonKind; } | 96 | bool isShared() const { return SymbolKind == SharedKind; } |
| 97 | bool isLocal() const { return Binding == llvm::ELF::STB_LOCAL; } | ||
| 98 | |||
| 64 | bool isLazy() const { | 99 | bool isLazy() const { |
| 65 | return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind; | 100 | return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind; |
| 66 | } | 101 | } |
| 67 | bool isShared() const { return SymbolKind == SharedKind; } | 102 | |
| 68 | bool isInCurrentDSO() const { | 103 | // True is this is an undefined weak symbol. This only works once |
| 69 | return !isUndefined() && !isShared() && !isLazy(); | 104 | // all input files have been added. |
| 105 | bool isUndefWeak() const { | ||
| 106 | // See comment on Lazy the details. | ||
| 107 | return isWeak() && (isUndefined() || isLazy()); | ||
| 70 | } | 108 | } |
| 71 | bool isLocal() const { return IsLocal; } | 109 | |
| 72 | bool isPreemptible() const; | ||
| 73 | StringRef getName() const { return Name; } | 110 | StringRef getName() const { return Name; } |
| 74 | uint8_t getVisibility() const { return StOther & 0x3; } | 111 | uint8_t getVisibility() const { return StOther & 0x3; } |
| 75 | void parseSymbolVersion(); | 112 | void parseSymbolVersion(); |
| 76 | void copy(SymbolBody *Other); | ||
| 77 | 113 | ||
| 78 | bool isInGot() const { return GotIndex != -1U; } | 114 | bool isInGot() const { return GotIndex != -1U; } |
| 79 | bool isInPlt() const { return PltIndex != -1U; } | 115 | bool isInPlt() const { return PltIndex != -1U; } |
| ... | @@ -85,12 +121,9 @@ public: | ... | @@ -85,12 +121,9 @@ public: |
| 85 | uint64_t getGotPltOffset() const; | 121 | uint64_t getGotPltOffset() const; |
| 86 | uint64_t getGotPltVA() const; | 122 | uint64_t getGotPltVA() const; |
| 87 | uint64_t getPltVA() const; | 123 | uint64_t getPltVA() const; |
| 88 | template <class ELFT> typename ELFT::uint getSize() const; | 124 | uint64_t getSize() const; |
| 89 | OutputSection *getOutputSection() const; | 125 | OutputSection *getOutputSection() const; |
| 90 | 126 | ||
| 91 | // The file from which this symbol was created. | ||
| 92 | InputFile *File = nullptr; | ||
| 93 | |||
| 94 | uint32_t DynsymIndex = 0; | 127 | uint32_t DynsymIndex = 0; |
| 95 | uint32_t GotIndex = -1; | 128 | uint32_t GotIndex = -1; |
| 96 | uint32_t GotPltIndex = -1; | 129 | uint32_t GotPltIndex = -1; |
| ... | @@ -98,23 +131,19 @@ public: | ... | @@ -98,23 +131,19 @@ public: |
| 98 | uint32_t GlobalDynIndex = -1; | 131 | uint32_t GlobalDynIndex = -1; |
| 99 | 132 | ||
| 100 | protected: | 133 | protected: |
| 101 | SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, | 134 | Symbol(Kind K, InputFile *File, StringRefZ Name, uint8_t Binding, |
| 102 | uint8_t Type); | 135 | uint8_t StOther, uint8_t Type) |
| 136 | : Binding(Binding), File(File), SymbolKind(K), NeedsPltAddr(false), | ||
| 137 | IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false), | ||
| 138 | IsInIgot(false), IsPreemptible(false), Used(!Config->GcSections), | ||
| 139 | Type(Type), StOther(StOther), Name(Name) {} | ||
| 103 | 140 | ||
| 104 | const unsigned SymbolKind : 8; | 141 | const unsigned SymbolKind : 8; |
| 105 | 142 | ||
| 106 | public: | 143 | public: |
| 107 | // True if the linker has to generate a copy relocation. | ||
| 108 | // For SharedSymbol only. | ||
| 109 | unsigned NeedsCopy : 1; | ||
| 110 | |||
| 111 | // True the symbol should point to its PLT entry. | 144 | // True the symbol should point to its PLT entry. |
| 112 | // For SharedSymbol only. | 145 | // For SharedSymbol only. |
| 113 | unsigned NeedsPltAddr : 1; | 146 | unsigned NeedsPltAddr : 1; |
| 114 | |||
| 115 | // True if this is a local symbol. | ||
| 116 | unsigned IsLocal : 1; | ||
| 117 | |||
| 118 | // True if this symbol has an entry in the global part of MIPS GOT. | 147 | // True if this symbol has an entry in the global part of MIPS GOT. |
| 119 | unsigned IsInGlobalMipsGot : 1; | 148 | unsigned IsInGlobalMipsGot : 1; |
| 120 | 149 | ||
| ... | @@ -127,6 +156,11 @@ public: | ... | @@ -127,6 +156,11 @@ public: |
| 127 | // True if this symbol is in the Igot sub-section of the .got.plt or .got. | 156 | // True if this symbol is in the Igot sub-section of the .got.plt or .got. |
| 128 | unsigned IsInIgot : 1; | 157 | unsigned IsInIgot : 1; |
| 129 | 158 | ||
| 159 | unsigned IsPreemptible : 1; | ||
| 160 | |||
| 161 | // True if an undefined or shared symbol is used from a live section. | ||
| 162 | unsigned Used : 1; | ||
| 163 | |||
| 130 | // The following fields have the same meaning as the ELF symbol attributes. | 164 | // The following fields have the same meaning as the ELF symbol attributes. |
| 131 | uint8_t Type; // symbol type | 165 | uint8_t Type; // symbol type |
| 132 | uint8_t StOther; // st_other field value | 166 | uint8_t StOther; // st_other field value |
| ... | @@ -149,139 +183,111 @@ protected: | ... | @@ -149,139 +183,111 @@ protected: |
| 149 | StringRefZ Name; | 183 | StringRefZ Name; |
| 150 | }; | 184 | }; |
| 151 | 185 | ||
| 152 | // The base class for any defined symbols. | 186 | // Represents a symbol that is defined in the current output file. |
| 153 | class Defined : public SymbolBody { | 187 | class Defined : public Symbol { |
| 154 | public: | ||
| 155 | Defined(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type); | ||
| 156 | static bool classof(const SymbolBody *S) { return S->isDefined(); } | ||
| 157 | }; | ||
| 158 | |||
| 159 | class DefinedCommon : public Defined { | ||
| 160 | public: | 188 | public: |
| 161 | DefinedCommon(StringRef N, uint64_t Size, uint32_t Alignment, uint8_t StOther, | 189 | Defined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther, |
| 162 | uint8_t Type, InputFile *File); | 190 | uint8_t Type, uint64_t Value, uint64_t Size, SectionBase *Section) |
| 163 | 191 | : Symbol(DefinedKind, File, Name, Binding, StOther, Type), Value(Value), | |
| 164 | static bool classof(const SymbolBody *S) { | 192 | Size(Size), Section(Section) {} |
| 165 | return S->kind() == SymbolBody::DefinedCommonKind; | ||
| 166 | } | ||
| 167 | 193 | ||
| 168 | // The output offset of this common symbol in the output bss. Computed by the | 194 | static bool classof(const Symbol *S) { return S->isDefined(); } |
| 169 | // writer. | ||
| 170 | uint64_t Offset; | ||
| 171 | |||
| 172 | // The maximum alignment we have seen for this symbol. | ||
| 173 | uint32_t Alignment; | ||
| 174 | |||
| 175 | uint64_t Size; | ||
| 176 | }; | ||
| 177 | |||
| 178 | // Regular defined symbols read from object file symbol tables. | ||
| 179 | class DefinedRegular : public Defined { | ||
| 180 | public: | ||
| 181 | DefinedRegular(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type, | ||
| 182 | uint64_t Value, uint64_t Size, SectionBase *Section, | ||
| 183 | InputFile *File) | ||
| 184 | : Defined(SymbolBody::DefinedRegularKind, Name, IsLocal, StOther, Type), | ||
| 185 | Value(Value), Size(Size), Section(Section) { | ||
| 186 | this->File = File; | ||
| 187 | } | ||
| 188 | |||
| 189 | // Return true if the symbol is a PIC function. | ||
| 190 | template <class ELFT> bool isMipsPIC() const; | ||
| 191 | |||
| 192 | static bool classof(const SymbolBody *S) { | ||
| 193 | return S->kind() == SymbolBody::DefinedRegularKind; | ||
| 194 | } | ||
| 195 | 195 | ||
| 196 | uint64_t Value; | 196 | uint64_t Value; |
| 197 | uint64_t Size; | 197 | uint64_t Size; |
| 198 | SectionBase *Section; | 198 | SectionBase *Section; |
| 199 | }; | 199 | }; |
| 200 | 200 | ||
| 201 | class Undefined : public SymbolBody { | 201 | class Undefined : public Symbol { |
| 202 | public: | 202 | public: |
| 203 | Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type, | 203 | Undefined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther, |
| 204 | InputFile *F); | 204 | uint8_t Type) |
| 205 | : Symbol(UndefinedKind, File, Name, Binding, StOther, Type) {} | ||
| 205 | 206 | ||
| 206 | static bool classof(const SymbolBody *S) { | 207 | static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; } |
| 207 | return S->kind() == UndefinedKind; | ||
| 208 | } | ||
| 209 | }; | 208 | }; |
| 210 | 209 | ||
| 211 | class SharedSymbol : public Defined { | 210 | class SharedSymbol : public Symbol { |
| 212 | public: | 211 | public: |
| 213 | static bool classof(const SymbolBody *S) { | 212 | static bool classof(const Symbol *S) { return S->kind() == SharedKind; } |
| 214 | return S->kind() == SymbolBody::SharedKind; | 213 | |
| 215 | } | 214 | SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding, |
| 216 | 215 | uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, | |
| 217 | SharedSymbol(InputFile *File, StringRef Name, uint8_t StOther, uint8_t Type, | 216 | uint32_t Alignment, uint32_t VerdefIndex) |
| 218 | const void *ElfSym, const void *Verdef) | 217 | : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value), |
| 219 | : Defined(SymbolBody::SharedKind, Name, /*IsLocal=*/false, StOther, Type), | 218 | Size(Size), VerdefIndex(VerdefIndex), Alignment(Alignment) { |
| 220 | Verdef(Verdef), ElfSym(ElfSym) { | 219 | // GNU ifunc is a mechanism to allow user-supplied functions to |
| 221 | // IFuncs defined in DSOs are treated as functions by the static linker. | 220 | // resolve PLT slot values at load-time. This is contrary to the |
| 222 | if (isGnuIFunc()) | 221 | // regular symbol resolution scheme in which symbols are resolved just |
| 222 | // by name. Using this hook, you can program how symbols are solved | ||
| 223 | // for you program. For example, you can make "memcpy" to be resolved | ||
| 224 | // to a SSE-enabled version of memcpy only when a machine running the | ||
| 225 | // program supports the SSE instruction set. | ||
| 226 | // | ||
| 227 | // Naturally, such symbols should always be called through their PLT | ||
| 228 | // slots. What GNU ifunc symbols point to are resolver functions, and | ||
| 229 | // calling them directly doesn't make sense (unless you are writing a | ||
| 230 | // loader). | ||
| 231 | // | ||
| 232 | // For DSO symbols, we always call them through PLT slots anyway. | ||
| 233 | // So there's no difference between GNU ifunc and regular function | ||
| 234 | // symbols if they are in DSOs. So we can handle GNU_IFUNC as FUNC. | ||
| 235 | if (this->Type == llvm::ELF::STT_GNU_IFUNC) | ||
| 223 | this->Type = llvm::ELF::STT_FUNC; | 236 | this->Type = llvm::ELF::STT_FUNC; |
| 224 | this->File = File; | ||
| 225 | } | 237 | } |
| 226 | 238 | ||
| 227 | template <class ELFT> uint64_t getShndx() const { | 239 | template <class ELFT> SharedFile<ELFT> &getFile() const { |
| 228 | return getSym<ELFT>().st_shndx; | 240 | return *cast<SharedFile<ELFT>>(File); |
| 229 | } | 241 | } |
| 230 | 242 | ||
| 231 | template <class ELFT> uint64_t getValue() const { | 243 | // If not null, there is a copy relocation to this section. |
| 232 | return getSym<ELFT>().st_value; | 244 | InputSection *CopyRelSec = nullptr; |
| 233 | } | ||
| 234 | 245 | ||
| 235 | template <class ELFT> uint64_t getSize() const { | 246 | uint64_t Value; // st_value |
| 236 | return getSym<ELFT>().st_size; | 247 | uint64_t Size; // st_size |
| 237 | } | ||
| 238 | |||
| 239 | template <class ELFT> uint32_t getAlignment() const; | ||
| 240 | 248 | ||
| 241 | // This field is a pointer to the symbol's version definition. | 249 | // This field is a index to the symbol's version definition. |
| 242 | const void *Verdef; | 250 | uint32_t VerdefIndex; |
| 243 | 251 | ||
| 244 | // CopyRelSec and CopyRelSecOff are significant only when NeedsCopy is true. | 252 | uint32_t Alignment; |
| 245 | InputSection *CopyRelSec; | ||
| 246 | uint64_t CopyRelSecOff; | ||
| 247 | |||
| 248 | private: | ||
| 249 | template <class ELFT> const typename ELFT::Sym &getSym() const { | ||
| 250 | return *(const typename ELFT::Sym *)ElfSym; | ||
| 251 | } | ||
| 252 | |||
| 253 | const void *ElfSym; | ||
| 254 | }; | 253 | }; |
| 255 | 254 | ||
| 256 | // This class represents a symbol defined in an archive file. It is | 255 | // This represents a symbol that is not yet in the link, but we know where to |
| 257 | // created from an archive file header, and it knows how to load an | 256 | // find it if needed. If the resolver finds both Undefined and Lazy for the same |
| 258 | // object file from an archive to replace itself with a defined | 257 | // name, it will ask the Lazy to load a file. |
| 259 | // symbol. If the resolver finds both Undefined and Lazy for | 258 | // |
| 260 | // the same name, it will ask the Lazy to load a file. | 259 | // A special complication is the handling of weak undefined symbols. They should |
| 261 | class Lazy : public SymbolBody { | 260 | // not load a file, but we have to remember we have seen both the weak undefined |
| 261 | // and the lazy. We represent that with a lazy symbol with a weak binding. This | ||
| 262 | // means that code looking for undefined symbols normally also has to take lazy | ||
| 263 | // symbols into consideration. | ||
| 264 | class Lazy : public Symbol { | ||
| 262 | public: | 265 | public: |
| 263 | static bool classof(const SymbolBody *S) { return S->isLazy(); } | 266 | static bool classof(const Symbol *S) { return S->isLazy(); } |
| 264 | 267 | ||
| 265 | // Returns an object file for this symbol, or a nullptr if the file | 268 | // Returns an object file for this symbol, or a nullptr if the file |
| 266 | // was already returned. | 269 | // was already returned. |
| 267 | InputFile *fetch(); | 270 | InputFile *fetch(); |
| 268 | 271 | ||
| 269 | protected: | 272 | protected: |
| 270 | Lazy(SymbolBody::Kind K, StringRef Name, uint8_t Type) | 273 | Lazy(Kind K, InputFile &File, StringRef Name, uint8_t Type) |
| 271 | : SymbolBody(K, Name, /*IsLocal=*/false, llvm::ELF::STV_DEFAULT, Type) {} | 274 | : Symbol(K, &File, Name, llvm::ELF::STB_GLOBAL, llvm::ELF::STV_DEFAULT, |
| 275 | Type) {} | ||
| 272 | }; | 276 | }; |
| 273 | 277 | ||
| 274 | // LazyArchive symbols represents symbols in archive files. | 278 | // This class represents a symbol defined in an archive file. It is |
| 279 | // created from an archive file header, and it knows how to load an | ||
| 280 | // object file from an archive to replace itself with a defined | ||
| 281 | // symbol. | ||
| 275 | class LazyArchive : public Lazy { | 282 | class LazyArchive : public Lazy { |
| 276 | public: | 283 | public: |
| 277 | LazyArchive(ArchiveFile &File, const llvm::object::Archive::Symbol S, | 284 | LazyArchive(InputFile &File, const llvm::object::Archive::Symbol S, |
| 278 | uint8_t Type); | 285 | uint8_t Type) |
| 286 | : Lazy(LazyArchiveKind, File, S.getName(), Type), Sym(S) {} | ||
| 279 | 287 | ||
| 280 | static bool classof(const SymbolBody *S) { | 288 | static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; } |
| 281 | return S->kind() == LazyArchiveKind; | ||
| 282 | } | ||
| 283 | 289 | ||
| 284 | ArchiveFile *file() { return (ArchiveFile *)this->File; } | 290 | ArchiveFile &getFile(); |
| 285 | InputFile *fetch(); | 291 | InputFile *fetch(); |
| 286 | 292 | ||
| 287 | private: | 293 | private: |
| ... | @@ -292,123 +298,85 @@ private: | ... | @@ -292,123 +298,85 @@ private: |
| 292 | // --start-lib and --end-lib options. | 298 | // --start-lib and --end-lib options. |
| 293 | class LazyObject : public Lazy { | 299 | class LazyObject : public Lazy { |
| 294 | public: | 300 | public: |
| 295 | LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type); | 301 | LazyObject(InputFile &File, StringRef Name, uint8_t Type) |
| 302 | : Lazy(LazyObjectKind, File, Name, Type) {} | ||
| 296 | 303 | ||
| 297 | static bool classof(const SymbolBody *S) { | 304 | static bool classof(const Symbol *S) { return S->kind() == LazyObjectKind; } |
| 298 | return S->kind() == LazyObjectKind; | ||
| 299 | } | ||
| 300 | 305 | ||
| 301 | LazyObjectFile *file() { return (LazyObjectFile *)this->File; } | 306 | LazyObjFile &getFile(); |
| 302 | InputFile *fetch(); | 307 | InputFile *fetch(); |
| 303 | }; | 308 | }; |
| 304 | 309 | ||
| 305 | // Some linker-generated symbols need to be created as | 310 | // Some linker-generated symbols need to be created as |
| 306 | // DefinedRegular symbols. | 311 | // Defined symbols. |
| 307 | struct ElfSym { | 312 | struct ElfSym { |
| 308 | // __bss_start | 313 | // __bss_start |
| 309 | static DefinedRegular *Bss; | 314 | static Defined *Bss; |
| 310 | 315 | ||
| 311 | // etext and _etext | 316 | // etext and _etext |
| 312 | static DefinedRegular *Etext1; | 317 | static Defined *Etext1; |
| 313 | static DefinedRegular *Etext2; | 318 | static Defined *Etext2; |
| 314 | 319 | ||
| 315 | // edata and _edata | 320 | // edata and _edata |
| 316 | static DefinedRegular *Edata1; | 321 | static Defined *Edata1; |
| 317 | static DefinedRegular *Edata2; | 322 | static Defined *Edata2; |
| 318 | 323 | ||
| 319 | // end and _end | 324 | // end and _end |
| 320 | static DefinedRegular *End1; | 325 | static Defined *End1; |
| 321 | static DefinedRegular *End2; | 326 | static Defined *End2; |
| 322 | 327 | ||
| 323 | // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to | 328 | // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to |
| 324 | // be at some offset from the base of the .got section, usually 0 or | 329 | // be at some offset from the base of the .got section, usually 0 or |
| 325 | // the end of the .got. | 330 | // the end of the .got. |
| 326 | static DefinedRegular *GlobalOffsetTable; | 331 | static Defined *GlobalOffsetTable; |
| 327 | 332 | ||
| 328 | // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS. | 333 | // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS. |
| 329 | static DefinedRegular *MipsGp; | 334 | static Defined *MipsGp; |
| 330 | static DefinedRegular *MipsGpDisp; | 335 | static Defined *MipsGpDisp; |
| 331 | static DefinedRegular *MipsLocalGp; | 336 | static Defined *MipsLocalGp; |
| 332 | }; | 337 | }; |
| 333 | 338 | ||
| 334 | // A real symbol object, SymbolBody, is usually stored within a Symbol. There's | 339 | // A buffer class that is large enough to hold any Symbol-derived |
| 335 | // always one Symbol for each symbol name. The resolver updates the SymbolBody | 340 | // object. We allocate memory using this class and instantiate a symbol |
| 336 | // stored in the Body field of this object as it resolves symbols. Symbol also | 341 | // using the placement new. |
| 337 | // holds computed properties of symbol names. | 342 | union SymbolUnion { |
| 338 | struct Symbol { | 343 | alignas(Defined) char A[sizeof(Defined)]; |
| 339 | // Symbol binding. This is on the Symbol to track changes during resolution. | 344 | alignas(Undefined) char C[sizeof(Undefined)]; |
| 340 | // In particular: | 345 | alignas(SharedSymbol) char D[sizeof(SharedSymbol)]; |
| 341 | // An undefined weak is still weak when it resolves to a shared library. | 346 | alignas(LazyArchive) char E[sizeof(LazyArchive)]; |
| 342 | // An undefined weak will not fetch archive members, but we have to remember | 347 | alignas(LazyObject) char F[sizeof(LazyObject)]; |
| 343 | // it is weak. | ||
| 344 | uint8_t Binding; | ||
| 345 | |||
| 346 | // Version definition index. | ||
| 347 | uint16_t VersionId; | ||
| 348 | |||
| 349 | // Symbol visibility. This is the computed minimum visibility of all | ||
| 350 | // observed non-DSO symbols. | ||
| 351 | unsigned Visibility : 2; | ||
| 352 | |||
| 353 | // True if the symbol was used for linking and thus need to be added to the | ||
| 354 | // output file's symbol table. This is true for all symbols except for | ||
| 355 | // unreferenced DSO symbols and bitcode symbols that are unreferenced except | ||
| 356 | // by other bitcode objects. | ||
| 357 | unsigned IsUsedInRegularObj : 1; | ||
| 358 | |||
| 359 | // If this flag is true and the symbol has protected or default visibility, it | ||
| 360 | // will appear in .dynsym. This flag is set by interposable DSO symbols in | ||
| 361 | // executables, by most symbols in DSOs and executables built with | ||
| 362 | // --export-dynamic, and by dynamic lists. | ||
| 363 | unsigned ExportDynamic : 1; | ||
| 364 | |||
| 365 | // True if this symbol is specified by --trace-symbol option. | ||
| 366 | unsigned Traced : 1; | ||
| 367 | |||
| 368 | // This symbol version was found in a version script. | ||
| 369 | unsigned InVersionScript : 1; | ||
| 370 | |||
| 371 | bool includeInDynsym() const; | ||
| 372 | uint8_t computeBinding() const; | ||
| 373 | bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } | ||
| 374 | |||
| 375 | // This field is used to store the Symbol's SymbolBody. This instantiation of | ||
| 376 | // AlignedCharArrayUnion gives us a struct with a char array field that is | ||
| 377 | // large and aligned enough to store any derived class of SymbolBody. | ||
| 378 | llvm::AlignedCharArrayUnion<DefinedCommon, DefinedRegular, Undefined, | ||
| 379 | SharedSymbol, LazyArchive, LazyObject> | ||
| 380 | Body; | ||
| 381 | |||
| 382 | SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); } | ||
| 383 | const SymbolBody *body() const { return const_cast<Symbol *>(this)->body(); } | ||
| 384 | }; | 348 | }; |
| 385 | 349 | ||
| 386 | void printTraceSymbol(Symbol *Sym); | 350 | void printTraceSymbol(Symbol *Sym); |
| 387 | 351 | ||
| 388 | template <typename T, typename... ArgT> | 352 | template <typename T, typename... ArgT> |
| 389 | void replaceBody(Symbol *S, ArgT &&... Arg) { | 353 | void replaceSymbol(Symbol *S, ArgT &&... Arg) { |
| 390 | static_assert(sizeof(T) <= sizeof(S->Body), "Body too small"); | 354 | static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small"); |
| 391 | static_assert(alignof(T) <= alignof(decltype(S->Body)), | 355 | static_assert(alignof(T) <= alignof(SymbolUnion), |
| 392 | "Body not aligned enough"); | 356 | "SymbolUnion not aligned enough"); |
| 393 | assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr && | 357 | assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr && |
| 394 | "Not a SymbolBody"); | 358 | "Not a Symbol"); |
| 359 | |||
| 360 | Symbol Sym = *S; | ||
| 395 | 361 | ||
| 396 | new (S->Body.buffer) T(std::forward<ArgT>(Arg)...); | 362 | new (S) T(std::forward<ArgT>(Arg)...); |
| 363 | |||
| 364 | S->VersionId = Sym.VersionId; | ||
| 365 | S->Visibility = Sym.Visibility; | ||
| 366 | S->IsUsedInRegularObj = Sym.IsUsedInRegularObj; | ||
| 367 | S->ExportDynamic = Sym.ExportDynamic; | ||
| 368 | S->CanInline = Sym.CanInline; | ||
| 369 | S->Traced = Sym.Traced; | ||
| 370 | S->InVersionScript = Sym.InVersionScript; | ||
| 397 | 371 | ||
| 398 | // Print out a log message if --trace-symbol was specified. | 372 | // Print out a log message if --trace-symbol was specified. |
| 399 | // This is for debugging. | 373 | // This is for debugging. |
| 400 | if (S->Traced) | 374 | if (S->Traced) |
| 401 | printTraceSymbol(S); | 375 | printTraceSymbol(S); |
| 402 | } | 376 | } |
| 403 | |||
| 404 | inline Symbol *SymbolBody::symbol() { | ||
| 405 | assert(!isLocal()); | ||
| 406 | return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) - | ||
| 407 | offsetof(Symbol, Body)); | ||
| 408 | } | ||
| 409 | } // namespace elf | 377 | } // namespace elf |
| 410 | 378 | ||
| 411 | std::string toString(const elf::SymbolBody &B); | 379 | std::string toString(const elf::Symbol &B); |
| 412 | } // namespace lld | 380 | } // namespace lld |
| 413 | 381 | ||
| 414 | #endif | 382 | #endif |
deps/lld/ELF/SyntheticSections.cpp+967-705| ... | @@ -15,28 +15,32 @@ | ... | @@ -15,28 +15,32 @@ |
| 15 | //===----------------------------------------------------------------------===// | 15 | //===----------------------------------------------------------------------===// |
| 16 | 16 | ||
| 17 | #include "SyntheticSections.h" | 17 | #include "SyntheticSections.h" |
| 18 | #include "Bits.h" | ||
| 18 | #include "Config.h" | 19 | #include "Config.h" |
| 19 | #include "Error.h" | ||
| 20 | #include "InputFiles.h" | 20 | #include "InputFiles.h" |
| 21 | #include "LinkerScript.h" | 21 | #include "LinkerScript.h" |
| 22 | #include "Memory.h" | ||
| 23 | #include "OutputSections.h" | 22 | #include "OutputSections.h" |
| 24 | #include "Strings.h" | 23 | #include "Strings.h" |
| 25 | #include "SymbolTable.h" | 24 | #include "SymbolTable.h" |
| 25 | #include "Symbols.h" | ||
| 26 | #include "Target.h" | 26 | #include "Target.h" |
| 27 | #include "Threads.h" | ||
| 28 | #include "Writer.h" | 27 | #include "Writer.h" |
| 29 | #include "lld/Config/Version.h" | 28 | #include "lld/Common/ErrorHandler.h" |
| 29 | #include "lld/Common/Memory.h" | ||
| 30 | #include "lld/Common/Threads.h" | ||
| 31 | #include "lld/Common/Version.h" | ||
| 30 | #include "llvm/BinaryFormat/Dwarf.h" | 32 | #include "llvm/BinaryFormat/Dwarf.h" |
| 31 | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" | 33 | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" |
| 32 | #include "llvm/Object/Decompressor.h" | 34 | #include "llvm/Object/Decompressor.h" |
| 33 | #include "llvm/Object/ELFObjectFile.h" | 35 | #include "llvm/Object/ELFObjectFile.h" |
| 34 | #include "llvm/Support/Endian.h" | 36 | #include "llvm/Support/Endian.h" |
| 37 | #include "llvm/Support/LEB128.h" | ||
| 35 | #include "llvm/Support/MD5.h" | 38 | #include "llvm/Support/MD5.h" |
| 36 | #include "llvm/Support/RandomNumberGenerator.h" | 39 | #include "llvm/Support/RandomNumberGenerator.h" |
| 37 | #include "llvm/Support/SHA1.h" | 40 | #include "llvm/Support/SHA1.h" |
| 38 | #include "llvm/Support/xxhash.h" | 41 | #include "llvm/Support/xxhash.h" |
| 39 | #include <cstdlib> | 42 | #include <cstdlib> |
| 43 | #include <thread> | ||
| 40 | 44 | ||
| 41 | using namespace llvm; | 45 | using namespace llvm; |
| 42 | using namespace llvm::dwarf; | 46 | using namespace llvm::dwarf; |
| ... | @@ -48,41 +52,18 @@ using namespace llvm::support::endian; | ... | @@ -48,41 +52,18 @@ using namespace llvm::support::endian; |
| 48 | using namespace lld; | 52 | using namespace lld; |
| 49 | using namespace lld::elf; | 53 | using namespace lld::elf; |
| 50 | 54 | ||
| 55 | constexpr size_t MergeNoTailSection::NumShards; | ||
| 56 | |||
| 57 | static void write32(void *Buf, uint32_t Val) { | ||
| 58 | endian::write32(Buf, Val, Config->Endianness); | ||
| 59 | } | ||
| 60 | |||
| 51 | uint64_t SyntheticSection::getVA() const { | 61 | uint64_t SyntheticSection::getVA() const { |
| 52 | if (OutputSection *Sec = getParent()) | 62 | if (OutputSection *Sec = getParent()) |
| 53 | return Sec->Addr + OutSecOff; | 63 | return Sec->Addr + OutSecOff; |
| 54 | return 0; | 64 | return 0; |
| 55 | } | 65 | } |
| 56 | 66 | ||
| 57 | template <class ELFT> static std::vector<DefinedCommon *> getCommonSymbols() { | ||
| 58 | std::vector<DefinedCommon *> V; | ||
| 59 | for (Symbol *S : Symtab<ELFT>::X->getSymbols()) | ||
| 60 | if (auto *B = dyn_cast<DefinedCommon>(S->body())) | ||
| 61 | V.push_back(B); | ||
| 62 | return V; | ||
| 63 | } | ||
| 64 | |||
| 65 | // Find all common symbols and allocate space for them. | ||
| 66 | template <class ELFT> InputSection *elf::createCommonSection() { | ||
| 67 | if (!Config->DefineCommon) | ||
| 68 | return nullptr; | ||
| 69 | |||
| 70 | // Sort the common symbols by alignment as an heuristic to pack them better. | ||
| 71 | std::vector<DefinedCommon *> Syms = getCommonSymbols<ELFT>(); | ||
| 72 | if (Syms.empty()) | ||
| 73 | return nullptr; | ||
| 74 | |||
| 75 | std::stable_sort(Syms.begin(), Syms.end(), | ||
| 76 | [](const DefinedCommon *A, const DefinedCommon *B) { | ||
| 77 | return A->Alignment > B->Alignment; | ||
| 78 | }); | ||
| 79 | |||
| 80 | BssSection *Sec = make<BssSection>("COMMON"); | ||
| 81 | for (DefinedCommon *Sym : Syms) | ||
| 82 | Sym->Offset = Sec->reserveSpace(Sym->Size, Sym->Alignment); | ||
| 83 | return Sec; | ||
| 84 | } | ||
| 85 | |||
| 86 | // Returns an LLD version string. | 67 | // Returns an LLD version string. |
| 87 | static ArrayRef<uint8_t> getVersion() { | 68 | static ArrayRef<uint8_t> getVersion() { |
| 88 | // Check LLD_VERSION first for ease of testing. | 69 | // Check LLD_VERSION first for ease of testing. |
| ... | @@ -100,18 +81,9 @@ static ArrayRef<uint8_t> getVersion() { | ... | @@ -100,18 +81,9 @@ static ArrayRef<uint8_t> getVersion() { |
| 100 | // With this feature, you can identify LLD-generated binaries easily | 81 | // With this feature, you can identify LLD-generated binaries easily |
| 101 | // by "readelf --string-dump .comment <file>". | 82 | // by "readelf --string-dump .comment <file>". |
| 102 | // The returned object is a mergeable string section. | 83 | // The returned object is a mergeable string section. |
| 103 | template <class ELFT> MergeInputSection *elf::createCommentSection() { | 84 | MergeInputSection *elf::createCommentSection() { |
| 104 | typename ELFT::Shdr Hdr = {}; | 85 | return make<MergeInputSection>(SHF_MERGE | SHF_STRINGS, SHT_PROGBITS, 1, |
| 105 | Hdr.sh_flags = SHF_MERGE | SHF_STRINGS; | 86 | getVersion(), ".comment"); |
| 106 | Hdr.sh_type = SHT_PROGBITS; | ||
| 107 | Hdr.sh_entsize = 1; | ||
| 108 | Hdr.sh_addralign = 1; | ||
| 109 | |||
| 110 | auto *Ret = | ||
| 111 | make<MergeInputSection>((ObjectFile<ELFT> *)nullptr, &Hdr, ".comment"); | ||
| 112 | Ret->Data = getVersion(); | ||
| 113 | Ret->splitIntoPieces(); | ||
| 114 | return Ret; | ||
| 115 | } | 87 | } |
| 116 | 88 | ||
| 117 | // .MIPS.abiflags section. | 89 | // .MIPS.abiflags section. |
| ... | @@ -137,7 +109,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { | ... | @@ -137,7 +109,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { |
| 137 | Sec->Live = false; | 109 | Sec->Live = false; |
| 138 | Create = true; | 110 | Create = true; |
| 139 | 111 | ||
| 140 | std::string Filename = toString(Sec->getFile<ELFT>()); | 112 | std::string Filename = toString(Sec->File); |
| 141 | const size_t Size = Sec->Data.size(); | 113 | const size_t Size = Sec->Data.size(); |
| 142 | // Older version of BFD (such as the default FreeBSD linker) concatenate | 114 | // Older version of BFD (such as the default FreeBSD linker) concatenate |
| 143 | // .MIPS.abiflags instead of merging. To allow for this case (or potential | 115 | // .MIPS.abiflags instead of merging. To allow for this case (or potential |
| ... | @@ -154,7 +126,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { | ... | @@ -154,7 +126,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { |
| 154 | return nullptr; | 126 | return nullptr; |
| 155 | } | 127 | } |
| 156 | 128 | ||
| 157 | // LLD checks ISA compatibility in getMipsEFlags(). Here we just | 129 | // LLD checks ISA compatibility in calcMipsEFlags(). Here we just |
| 158 | // select the highest number of ISA/Rev/Ext. | 130 | // select the highest number of ISA/Rev/Ext. |
| 159 | Flags.isa_level = std::max(Flags.isa_level, S->isa_level); | 131 | Flags.isa_level = std::max(Flags.isa_level, S->isa_level); |
| 160 | Flags.isa_rev = std::max(Flags.isa_rev, S->isa_rev); | 132 | Flags.isa_rev = std::max(Flags.isa_rev, S->isa_rev); |
| ... | @@ -197,16 +169,19 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { | ... | @@ -197,16 +169,19 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { |
| 197 | if (!ELFT::Is64Bits) | 169 | if (!ELFT::Is64Bits) |
| 198 | return nullptr; | 170 | return nullptr; |
| 199 | 171 | ||
| 200 | Elf_Mips_RegInfo Reginfo = {}; | 172 | std::vector<InputSectionBase *> Sections; |
| 201 | bool Create = false; | 173 | for (InputSectionBase *Sec : InputSections) |
| 174 | if (Sec->Type == SHT_MIPS_OPTIONS) | ||
| 175 | Sections.push_back(Sec); | ||
| 202 | 176 | ||
| 203 | for (InputSectionBase *Sec : InputSections) { | 177 | if (Sections.empty()) |
| 204 | if (Sec->Type != SHT_MIPS_OPTIONS) | 178 | return nullptr; |
| 205 | continue; | 179 | |
| 180 | Elf_Mips_RegInfo Reginfo = {}; | ||
| 181 | for (InputSectionBase *Sec : Sections) { | ||
| 206 | Sec->Live = false; | 182 | Sec->Live = false; |
| 207 | Create = true; | ||
| 208 | 183 | ||
| 209 | std::string Filename = toString(Sec->getFile<ELFT>()); | 184 | std::string Filename = toString(Sec->File); |
| 210 | ArrayRef<uint8_t> D = Sec->Data; | 185 | ArrayRef<uint8_t> D = Sec->Data; |
| 211 | 186 | ||
| 212 | while (!D.empty()) { | 187 | while (!D.empty()) { |
| ... | @@ -230,9 +205,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { | ... | @@ -230,9 +205,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { |
| 230 | } | 205 | } |
| 231 | }; | 206 | }; |
| 232 | 207 | ||
| 233 | if (Create) | 208 | return make<MipsOptionsSection<ELFT>>(Reginfo); |
| 234 | return make<MipsOptionsSection<ELFT>>(Reginfo); | ||
| 235 | return nullptr; | ||
| 236 | } | 209 | } |
| 237 | 210 | ||
| 238 | // MIPS .reginfo section. | 211 | // MIPS .reginfo section. |
| ... | @@ -255,32 +228,31 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { | ... | @@ -255,32 +228,31 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { |
| 255 | if (ELFT::Is64Bits) | 228 | if (ELFT::Is64Bits) |
| 256 | return nullptr; | 229 | return nullptr; |
| 257 | 230 | ||
| 258 | Elf_Mips_RegInfo Reginfo = {}; | 231 | std::vector<InputSectionBase *> Sections; |
| 259 | bool Create = false; | 232 | for (InputSectionBase *Sec : InputSections) |
| 233 | if (Sec->Type == SHT_MIPS_REGINFO) | ||
| 234 | Sections.push_back(Sec); | ||
| 260 | 235 | ||
| 261 | for (InputSectionBase *Sec : InputSections) { | 236 | if (Sections.empty()) |
| 262 | if (Sec->Type != SHT_MIPS_REGINFO) | 237 | return nullptr; |
| 263 | continue; | 238 | |
| 239 | Elf_Mips_RegInfo Reginfo = {}; | ||
| 240 | for (InputSectionBase *Sec : Sections) { | ||
| 264 | Sec->Live = false; | 241 | Sec->Live = false; |
| 265 | Create = true; | ||
| 266 | 242 | ||
| 267 | if (Sec->Data.size() != sizeof(Elf_Mips_RegInfo)) { | 243 | if (Sec->Data.size() != sizeof(Elf_Mips_RegInfo)) { |
| 268 | error(toString(Sec->getFile<ELFT>()) + | 244 | error(toString(Sec->File) + ": invalid size of .reginfo section"); |
| 269 | ": invalid size of .reginfo section"); | ||
| 270 | return nullptr; | 245 | return nullptr; |
| 271 | } | 246 | } |
| 272 | auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data()); | 247 | auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data()); |
| 273 | if (Config->Relocatable && R->ri_gp_value) | 248 | if (Config->Relocatable && R->ri_gp_value) |
| 274 | error(toString(Sec->getFile<ELFT>()) + | 249 | error(toString(Sec->File) + ": unsupported non-zero ri_gp_value"); |
| 275 | ": unsupported non-zero ri_gp_value"); | ||
| 276 | 250 | ||
| 277 | Reginfo.ri_gprmask |= R->ri_gprmask; | 251 | Reginfo.ri_gprmask |= R->ri_gprmask; |
| 278 | Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value; | 252 | Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value; |
| 279 | }; | 253 | }; |
| 280 | 254 | ||
| 281 | if (Create) | 255 | return make<MipsReginfoSection<ELFT>>(Reginfo); |
| 282 | return make<MipsReginfoSection<ELFT>>(Reginfo); | ||
| 283 | return nullptr; | ||
| 284 | } | 256 | } |
| 285 | 257 | ||
| 286 | InputSection *elf::createInterpSection() { | 258 | InputSection *elf::createInterpSection() { |
| ... | @@ -288,16 +260,16 @@ InputSection *elf::createInterpSection() { | ... | @@ -288,16 +260,16 @@ InputSection *elf::createInterpSection() { |
| 288 | StringRef S = Saver.save(Config->DynamicLinker); | 260 | StringRef S = Saver.save(Config->DynamicLinker); |
| 289 | ArrayRef<uint8_t> Contents = {(const uint8_t *)S.data(), S.size() + 1}; | 261 | ArrayRef<uint8_t> Contents = {(const uint8_t *)S.data(), S.size() + 1}; |
| 290 | 262 | ||
| 291 | auto *Sec = | 263 | auto *Sec = make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, Contents, |
| 292 | make<InputSection>(SHF_ALLOC, SHT_PROGBITS, 1, Contents, ".interp"); | 264 | ".interp"); |
| 293 | Sec->Live = true; | 265 | Sec->Live = true; |
| 294 | return Sec; | 266 | return Sec; |
| 295 | } | 267 | } |
| 296 | 268 | ||
| 297 | SymbolBody *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, | 269 | Symbol *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, |
| 298 | uint64_t Size, InputSectionBase *Section) { | 270 | uint64_t Size, InputSectionBase &Section) { |
| 299 | auto *S = make<DefinedRegular>(Name, /*IsLocal*/ true, STV_DEFAULT, Type, | 271 | auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type, |
| 300 | Value, Size, Section, nullptr); | 272 | Value, Size, &Section); |
| 301 | if (InX::SymTab) | 273 | if (InX::SymTab) |
| 302 | InX::SymTab->addSymbol(S); | 274 | InX::SymTab->addSymbol(S); |
| 303 | return S; | 275 | return S; |
| ... | @@ -320,14 +292,13 @@ static size_t getHashSize() { | ... | @@ -320,14 +292,13 @@ static size_t getHashSize() { |
| 320 | } | 292 | } |
| 321 | 293 | ||
| 322 | BuildIdSection::BuildIdSection() | 294 | BuildIdSection::BuildIdSection() |
| 323 | : SyntheticSection(SHF_ALLOC, SHT_NOTE, 1, ".note.gnu.build-id"), | 295 | : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"), |
| 324 | HashSize(getHashSize()) {} | 296 | HashSize(getHashSize()) {} |
| 325 | 297 | ||
| 326 | void BuildIdSection::writeTo(uint8_t *Buf) { | 298 | void BuildIdSection::writeTo(uint8_t *Buf) { |
| 327 | endianness E = Config->Endianness; | 299 | write32(Buf, 4); // Name size |
| 328 | write32(Buf, 4, E); // Name size | 300 | write32(Buf + 4, HashSize); // Content size |
| 329 | write32(Buf + 4, HashSize, E); // Content size | 301 | write32(Buf + 8, NT_GNU_BUILD_ID); // Type |
| 330 | write32(Buf + 8, NT_GNU_BUILD_ID, E); // Type | ||
| 331 | memcpy(Buf + 12, "GNU", 4); // Name string | 302 | memcpy(Buf + 12, "GNU", 4); // Name string |
| 332 | HashBuf = Buf + 16; | 303 | HashBuf = Buf + 16; |
| 333 | } | 304 | } |
| ... | @@ -364,15 +335,12 @@ void BuildIdSection::computeHash( | ... | @@ -364,15 +335,12 @@ void BuildIdSection::computeHash( |
| 364 | HashFn(HashBuf, Hashes); | 335 | HashFn(HashBuf, Hashes); |
| 365 | } | 336 | } |
| 366 | 337 | ||
| 367 | BssSection::BssSection(StringRef Name) | 338 | BssSection::BssSection(StringRef Name, uint64_t Size, uint32_t Alignment) |
| 368 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 0, Name) {} | 339 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Name) { |
| 369 | 340 | this->Bss = true; | |
| 370 | size_t BssSection::reserveSpace(uint64_t Size, uint32_t Alignment) { | ||
| 371 | if (OutputSection *Sec = getParent()) | 341 | if (OutputSection *Sec = getParent()) |
| 372 | Sec->updateAlignment(Alignment); | 342 | Sec->Alignment = std::max(Sec->Alignment, Alignment); |
| 373 | this->Size = alignTo(this->Size, Alignment) + Size; | 343 | this->Size = Size; |
| 374 | this->Alignment = std::max(this->Alignment, Alignment); | ||
| 375 | return this->Size - Size; | ||
| 376 | } | 344 | } |
| 377 | 345 | ||
| 378 | void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) { | 346 | void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) { |
| ... | @@ -393,8 +361,8 @@ void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) { | ... | @@ -393,8 +361,8 @@ void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) { |
| 393 | }); | 361 | }); |
| 394 | break; | 362 | break; |
| 395 | case BuildIdKind::Uuid: | 363 | case BuildIdKind::Uuid: |
| 396 | if (getRandomBytes(HashBuf, HashSize)) | 364 | if (auto EC = getRandomBytes(HashBuf, HashSize)) |
| 397 | error("entropy source failure"); | 365 | error("entropy source failure: " + EC.message()); |
| 398 | break; | 366 | break; |
| 399 | case BuildIdKind::Hexstring: | 367 | case BuildIdKind::Hexstring: |
| 400 | memcpy(HashBuf, Config->BuildIdVector.data(), Config->BuildIdVector.size()); | 368 | memcpy(HashBuf, Config->BuildIdVector.data(), Config->BuildIdVector.size()); |
| ... | @@ -404,101 +372,99 @@ void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) { | ... | @@ -404,101 +372,99 @@ void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) { |
| 404 | } | 372 | } |
| 405 | } | 373 | } |
| 406 | 374 | ||
| 407 | template <class ELFT> | 375 | EhFrameSection::EhFrameSection() |
| 408 | EhFrameSection<ELFT>::EhFrameSection() | ||
| 409 | : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame") {} | 376 | : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame") {} |
| 410 | 377 | ||
| 411 | // Search for an existing CIE record or create a new one. | 378 | // Search for an existing CIE record or create a new one. |
| 412 | // CIE records from input object files are uniquified by their contents | 379 | // CIE records from input object files are uniquified by their contents |
| 413 | // and where their relocations point to. | 380 | // and where their relocations point to. |
| 414 | template <class ELFT> | 381 | template <class ELFT, class RelTy> |
| 415 | template <class RelTy> | 382 | CieRecord *EhFrameSection::addCie(EhSectionPiece &Cie, ArrayRef<RelTy> Rels) { |
| 416 | CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Piece, | 383 | auto *Sec = cast<EhInputSection>(Cie.Sec); |
| 417 | ArrayRef<RelTy> Rels) { | 384 | if (read32(Cie.data().data() + 4, Config->Endianness) != 0) |
| 418 | auto *Sec = cast<EhInputSection>(Piece.ID); | ||
| 419 | const endianness E = ELFT::TargetEndianness; | ||
| 420 | if (read32<E>(Piece.data().data() + 4) != 0) | ||
| 421 | fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame"); | 385 | fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame"); |
| 422 | 386 | ||
| 423 | SymbolBody *Personality = nullptr; | 387 | Symbol *Personality = nullptr; |
| 424 | unsigned FirstRelI = Piece.FirstRelocation; | 388 | unsigned FirstRelI = Cie.FirstRelocation; |
| 425 | if (FirstRelI != (unsigned)-1) | 389 | if (FirstRelI != (unsigned)-1) |
| 426 | Personality = | 390 | Personality = |
| 427 | &Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]); | 391 | &Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]); |
| 428 | 392 | ||
| 429 | // Search for an existing CIE by CIE contents/relocation target pair. | 393 | // Search for an existing CIE by CIE contents/relocation target pair. |
| 430 | CieRecord *&Cie = CieMap[{Piece.data(), Personality}]; | 394 | CieRecord *&Rec = CieMap[{Cie.data(), Personality}]; |
| 431 | 395 | ||
| 432 | // If not found, create a new one. | 396 | // If not found, create a new one. |
| 433 | if (!Cie) { | 397 | if (!Rec) { |
| 434 | Cie = make<CieRecord>(); | 398 | Rec = make<CieRecord>(); |
| 435 | Cie->Piece = &Piece; | 399 | Rec->Cie = &Cie; |
| 436 | Cies.push_back(Cie); | 400 | CieRecords.push_back(Rec); |
| 437 | } | 401 | } |
| 438 | return Cie; | 402 | return Rec; |
| 439 | } | 403 | } |
| 440 | 404 | ||
| 441 | // There is one FDE per function. Returns true if a given FDE | 405 | // There is one FDE per function. Returns true if a given FDE |
| 442 | // points to a live function. | 406 | // points to a live function. |
| 443 | template <class ELFT> | 407 | template <class ELFT, class RelTy> |
| 444 | template <class RelTy> | 408 | bool EhFrameSection::isFdeLive(EhSectionPiece &Fde, ArrayRef<RelTy> Rels) { |
| 445 | bool EhFrameSection<ELFT>::isFdeLive(EhSectionPiece &Piece, | 409 | auto *Sec = cast<EhInputSection>(Fde.Sec); |
| 446 | ArrayRef<RelTy> Rels) { | 410 | unsigned FirstRelI = Fde.FirstRelocation; |
| 447 | auto *Sec = cast<EhInputSection>(Piece.ID); | 411 | |
| 448 | unsigned FirstRelI = Piece.FirstRelocation; | 412 | // An FDE should point to some function because FDEs are to describe |
| 413 | // functions. That's however not always the case due to an issue of | ||
| 414 | // ld.gold with -r. ld.gold may discard only functions and leave their | ||
| 415 | // corresponding FDEs, which results in creating bad .eh_frame sections. | ||
| 416 | // To deal with that, we ignore such FDEs. | ||
| 449 | if (FirstRelI == (unsigned)-1) | 417 | if (FirstRelI == (unsigned)-1) |
| 450 | return false; | 418 | return false; |
| 419 | |||
| 451 | const RelTy &Rel = Rels[FirstRelI]; | 420 | const RelTy &Rel = Rels[FirstRelI]; |
| 452 | SymbolBody &B = Sec->template getFile<ELFT>()->getRelocTargetSym(Rel); | 421 | Symbol &B = Sec->template getFile<ELFT>()->getRelocTargetSym(Rel); |
| 453 | auto *D = dyn_cast<DefinedRegular>(&B); | 422 | |
| 454 | if (!D || !D->Section) | 423 | // FDEs for garbage-collected or merged-by-ICF sections are dead. |
| 455 | return false; | 424 | if (auto *D = dyn_cast<Defined>(&B)) |
| 456 | auto *Target = | 425 | if (SectionBase *Sec = D->Section) |
| 457 | cast<InputSectionBase>(cast<InputSectionBase>(D->Section)->Repl); | 426 | return Sec->Live; |
| 458 | return Target && Target->Live; | 427 | return false; |
| 459 | } | 428 | } |
| 460 | 429 | ||
| 461 | // .eh_frame is a sequence of CIE or FDE records. In general, there | 430 | // .eh_frame is a sequence of CIE or FDE records. In general, there |
| 462 | // is one CIE record per input object file which is followed by | 431 | // is one CIE record per input object file which is followed by |
| 463 | // a list of FDEs. This function searches an existing CIE or create a new | 432 | // a list of FDEs. This function searches an existing CIE or create a new |
| 464 | // one and associates FDEs to the CIE. | 433 | // one and associates FDEs to the CIE. |
| 465 | template <class ELFT> | 434 | template <class ELFT, class RelTy> |
| 466 | template <class RelTy> | 435 | void EhFrameSection::addSectionAux(EhInputSection *Sec, ArrayRef<RelTy> Rels) { |
| 467 | void EhFrameSection<ELFT>::addSectionAux(EhInputSection *Sec, | ||
| 468 | ArrayRef<RelTy> Rels) { | ||
| 469 | const endianness E = ELFT::TargetEndianness; | ||
| 470 | |||
| 471 | DenseMap<size_t, CieRecord *> OffsetToCie; | 436 | DenseMap<size_t, CieRecord *> OffsetToCie; |
| 472 | for (EhSectionPiece &Piece : Sec->Pieces) { | 437 | for (EhSectionPiece &Piece : Sec->Pieces) { |
| 473 | // The empty record is the end marker. | 438 | // The empty record is the end marker. |
| 474 | if (Piece.size() == 4) | 439 | if (Piece.Size == 4) |
| 475 | return; | 440 | return; |
| 476 | 441 | ||
| 477 | size_t Offset = Piece.InputOff; | 442 | size_t Offset = Piece.InputOff; |
| 478 | uint32_t ID = read32<E>(Piece.data().data() + 4); | 443 | uint32_t ID = read32(Piece.data().data() + 4, Config->Endianness); |
| 479 | if (ID == 0) { | 444 | if (ID == 0) { |
| 480 | OffsetToCie[Offset] = addCie(Piece, Rels); | 445 | OffsetToCie[Offset] = addCie<ELFT>(Piece, Rels); |
| 481 | continue; | 446 | continue; |
| 482 | } | 447 | } |
| 483 | 448 | ||
| 484 | uint32_t CieOffset = Offset + 4 - ID; | 449 | uint32_t CieOffset = Offset + 4 - ID; |
| 485 | CieRecord *Cie = OffsetToCie[CieOffset]; | 450 | CieRecord *Rec = OffsetToCie[CieOffset]; |
| 486 | if (!Cie) | 451 | if (!Rec) |
| 487 | fatal(toString(Sec) + ": invalid CIE reference"); | 452 | fatal(toString(Sec) + ": invalid CIE reference"); |
| 488 | 453 | ||
| 489 | if (!isFdeLive(Piece, Rels)) | 454 | if (!isFdeLive<ELFT>(Piece, Rels)) |
| 490 | continue; | 455 | continue; |
| 491 | Cie->FdePieces.push_back(&Piece); | 456 | Rec->Fdes.push_back(&Piece); |
| 492 | NumFdes++; | 457 | NumFdes++; |
| 493 | } | 458 | } |
| 494 | } | 459 | } |
| 495 | 460 | ||
| 496 | template <class ELFT> | 461 | template <class ELFT> void EhFrameSection::addSection(InputSectionBase *C) { |
| 497 | void EhFrameSection<ELFT>::addSection(InputSectionBase *C) { | ||
| 498 | auto *Sec = cast<EhInputSection>(C); | 462 | auto *Sec = cast<EhInputSection>(C); |
| 499 | Sec->Parent = this; | 463 | Sec->Parent = this; |
| 500 | updateAlignment(Sec->Alignment); | 464 | |
| 465 | Alignment = std::max(Alignment, Sec->Alignment); | ||
| 501 | Sections.push_back(Sec); | 466 | Sections.push_back(Sec); |
| 467 | |||
| 502 | for (auto *DS : Sec->DependentSections) | 468 | for (auto *DS : Sec->DependentSections) |
| 503 | DependentSections.push_back(DS); | 469 | DependentSections.push_back(DS); |
| 504 | 470 | ||
| ... | @@ -509,42 +475,36 @@ void EhFrameSection<ELFT>::addSection(InputSectionBase *C) { | ... | @@ -509,42 +475,36 @@ void EhFrameSection<ELFT>::addSection(InputSectionBase *C) { |
| 509 | if (Sec->Pieces.empty()) | 475 | if (Sec->Pieces.empty()) |
| 510 | return; | 476 | return; |
| 511 | 477 | ||
| 512 | if (Sec->NumRelocations) { | 478 | if (Sec->AreRelocsRela) |
| 513 | if (Sec->AreRelocsRela) | 479 | addSectionAux<ELFT>(Sec, Sec->template relas<ELFT>()); |
| 514 | addSectionAux(Sec, Sec->template relas<ELFT>()); | 480 | else |
| 515 | else | 481 | addSectionAux<ELFT>(Sec, Sec->template rels<ELFT>()); |
| 516 | addSectionAux(Sec, Sec->template rels<ELFT>()); | ||
| 517 | return; | ||
| 518 | } | ||
| 519 | addSectionAux(Sec, makeArrayRef<Elf_Rela>(nullptr, nullptr)); | ||
| 520 | } | 482 | } |
| 521 | 483 | ||
| 522 | template <class ELFT> | ||
| 523 | static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) { | 484 | static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) { |
| 524 | memcpy(Buf, D.data(), D.size()); | 485 | memcpy(Buf, D.data(), D.size()); |
| 525 | 486 | ||
| 526 | size_t Aligned = alignTo(D.size(), sizeof(typename ELFT::uint)); | 487 | size_t Aligned = alignTo(D.size(), Config->Wordsize); |
| 527 | 488 | ||
| 528 | // Zero-clear trailing padding if it exists. | 489 | // Zero-clear trailing padding if it exists. |
| 529 | memset(Buf + D.size(), 0, Aligned - D.size()); | 490 | memset(Buf + D.size(), 0, Aligned - D.size()); |
| 530 | 491 | ||
| 531 | // Fix the size field. -4 since size does not include the size field itself. | 492 | // Fix the size field. -4 since size does not include the size field itself. |
| 532 | const endianness E = ELFT::TargetEndianness; | 493 | write32(Buf, Aligned - 4); |
| 533 | write32<E>(Buf, Aligned - 4); | ||
| 534 | } | 494 | } |
| 535 | 495 | ||
| 536 | template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() { | 496 | void EhFrameSection::finalizeContents() { |
| 537 | if (this->Size) | 497 | if (this->Size) |
| 538 | return; // Already finalized. | 498 | return; // Already finalized. |
| 539 | 499 | ||
| 540 | size_t Off = 0; | 500 | size_t Off = 0; |
| 541 | for (CieRecord *Cie : Cies) { | 501 | for (CieRecord *Rec : CieRecords) { |
| 542 | Cie->Piece->OutputOff = Off; | 502 | Rec->Cie->OutputOff = Off; |
| 543 | Off += alignTo(Cie->Piece->size(), Config->Wordsize); | 503 | Off += alignTo(Rec->Cie->Size, Config->Wordsize); |
| 544 | 504 | ||
| 545 | for (EhSectionPiece *Fde : Cie->FdePieces) { | 505 | for (EhSectionPiece *Fde : Rec->Fdes) { |
| 546 | Fde->OutputOff = Off; | 506 | Fde->OutputOff = Off; |
| 547 | Off += alignTo(Fde->size(), Config->Wordsize); | 507 | Off += alignTo(Fde->Size, Config->Wordsize); |
| 548 | } | 508 | } |
| 549 | } | 509 | } |
| 550 | 510 | ||
| ... | @@ -557,32 +517,46 @@ template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() { | ... | @@ -557,32 +517,46 @@ template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() { |
| 557 | this->Size = Off; | 517 | this->Size = Off; |
| 558 | } | 518 | } |
| 559 | 519 | ||
| 560 | template <class ELFT> static uint64_t readFdeAddr(uint8_t *Buf, int Size) { | 520 | // Returns data for .eh_frame_hdr. .eh_frame_hdr is a binary search table |
| 561 | const endianness E = ELFT::TargetEndianness; | 521 | // to get an FDE from an address to which FDE is applied. This function |
| 522 | // returns a list of such pairs. | ||
| 523 | std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const { | ||
| 524 | uint8_t *Buf = getParent()->Loc + OutSecOff; | ||
| 525 | std::vector<FdeData> Ret; | ||
| 526 | |||
| 527 | for (CieRecord *Rec : CieRecords) { | ||
| 528 | uint8_t Enc = getFdeEncoding(Rec->Cie); | ||
| 529 | for (EhSectionPiece *Fde : Rec->Fdes) { | ||
| 530 | uint32_t Pc = getFdePc(Buf, Fde->OutputOff, Enc); | ||
| 531 | uint32_t FdeVA = getParent()->Addr + Fde->OutputOff; | ||
| 532 | Ret.push_back({Pc, FdeVA}); | ||
| 533 | } | ||
| 534 | } | ||
| 535 | return Ret; | ||
| 536 | } | ||
| 537 | |||
| 538 | static uint64_t readFdeAddr(uint8_t *Buf, int Size) { | ||
| 562 | switch (Size) { | 539 | switch (Size) { |
| 563 | case DW_EH_PE_udata2: | 540 | case DW_EH_PE_udata2: |
| 564 | return read16<E>(Buf); | 541 | return read16(Buf, Config->Endianness); |
| 565 | case DW_EH_PE_udata4: | 542 | case DW_EH_PE_udata4: |
| 566 | return read32<E>(Buf); | 543 | return read32(Buf, Config->Endianness); |
| 567 | case DW_EH_PE_udata8: | 544 | case DW_EH_PE_udata8: |
| 568 | return read64<E>(Buf); | 545 | return read64(Buf, Config->Endianness); |
| 569 | case DW_EH_PE_absptr: | 546 | case DW_EH_PE_absptr: |
| 570 | if (ELFT::Is64Bits) | 547 | return readUint(Buf); |
| 571 | return read64<E>(Buf); | ||
| 572 | return read32<E>(Buf); | ||
| 573 | } | 548 | } |
| 574 | fatal("unknown FDE size encoding"); | 549 | fatal("unknown FDE size encoding"); |
| 575 | } | 550 | } |
| 576 | 551 | ||
| 577 | // Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to. | 552 | // Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to. |
| 578 | // We need it to create .eh_frame_hdr section. | 553 | // We need it to create .eh_frame_hdr section. |
| 579 | template <class ELFT> | 554 | uint64_t EhFrameSection::getFdePc(uint8_t *Buf, size_t FdeOff, |
| 580 | uint64_t EhFrameSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff, | 555 | uint8_t Enc) const { |
| 581 | uint8_t Enc) { | ||
| 582 | // The starting address to which this FDE applies is | 556 | // The starting address to which this FDE applies is |
| 583 | // stored at FDE + 8 byte. | 557 | // stored at FDE + 8 byte. |
| 584 | size_t Off = FdeOff + 8; | 558 | size_t Off = FdeOff + 8; |
| 585 | uint64_t Addr = readFdeAddr<ELFT>(Buf + Off, Enc & 0x7); | 559 | uint64_t Addr = readFdeAddr(Buf + Off, Enc & 0x7); |
| 586 | if ((Enc & 0x70) == DW_EH_PE_absptr) | 560 | if ((Enc & 0x70) == DW_EH_PE_absptr) |
| 587 | return Addr; | 561 | return Addr; |
| 588 | if ((Enc & 0x70) == DW_EH_PE_pcrel) | 562 | if ((Enc & 0x70) == DW_EH_PE_pcrel) |
| ... | @@ -590,50 +564,39 @@ uint64_t EhFrameSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff, | ... | @@ -590,50 +564,39 @@ uint64_t EhFrameSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff, |
| 590 | fatal("unknown FDE size relative encoding"); | 564 | fatal("unknown FDE size relative encoding"); |
| 591 | } | 565 | } |
| 592 | 566 | ||
| 593 | template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) { | 567 | void EhFrameSection::writeTo(uint8_t *Buf) { |
| 594 | const endianness E = ELFT::TargetEndianness; | 568 | // Write CIE and FDE records. |
| 595 | for (CieRecord *Cie : Cies) { | 569 | for (CieRecord *Rec : CieRecords) { |
| 596 | size_t CieOffset = Cie->Piece->OutputOff; | 570 | size_t CieOffset = Rec->Cie->OutputOff; |
| 597 | writeCieFde<ELFT>(Buf + CieOffset, Cie->Piece->data()); | 571 | writeCieFde(Buf + CieOffset, Rec->Cie->data()); |
| 598 | 572 | ||
| 599 | for (EhSectionPiece *Fde : Cie->FdePieces) { | 573 | for (EhSectionPiece *Fde : Rec->Fdes) { |
| 600 | size_t Off = Fde->OutputOff; | 574 | size_t Off = Fde->OutputOff; |
| 601 | writeCieFde<ELFT>(Buf + Off, Fde->data()); | 575 | writeCieFde(Buf + Off, Fde->data()); |
| 602 | 576 | ||
| 603 | // FDE's second word should have the offset to an associated CIE. | 577 | // FDE's second word should have the offset to an associated CIE. |
| 604 | // Write it. | 578 | // Write it. |
| 605 | write32<E>(Buf + Off + 4, Off + 4 - CieOffset); | 579 | write32(Buf + Off + 4, Off + 4 - CieOffset); |
| 606 | } | 580 | } |
| 607 | } | 581 | } |
| 608 | 582 | ||
| 583 | // Apply relocations. .eh_frame section contents are not contiguous | ||
| 584 | // in the output buffer, but relocateAlloc() still works because | ||
| 585 | // getOffset() takes care of discontiguous section pieces. | ||
| 609 | for (EhInputSection *S : Sections) | 586 | for (EhInputSection *S : Sections) |
| 610 | S->relocateAlloc(Buf, nullptr); | 587 | S->relocateAlloc(Buf, nullptr); |
| 611 | |||
| 612 | // Construct .eh_frame_hdr. .eh_frame_hdr is a binary search table | ||
| 613 | // to get a FDE from an address to which FDE is applied. So here | ||
| 614 | // we obtain two addresses and pass them to EhFrameHdr object. | ||
| 615 | if (In<ELFT>::EhFrameHdr) { | ||
| 616 | for (CieRecord *Cie : Cies) { | ||
| 617 | uint8_t Enc = getFdeEncoding<ELFT>(Cie->Piece); | ||
| 618 | for (SectionPiece *Fde : Cie->FdePieces) { | ||
| 619 | uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc); | ||
| 620 | uint64_t FdeVA = getParent()->Addr + Fde->OutputOff; | ||
| 621 | In<ELFT>::EhFrameHdr->addFde(Pc, FdeVA); | ||
| 622 | } | ||
| 623 | } | ||
| 624 | } | ||
| 625 | } | 588 | } |
| 626 | 589 | ||
| 627 | GotSection::GotSection() | 590 | GotSection::GotSection() |
| 628 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, | 591 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, |
| 629 | Target->GotEntrySize, ".got") {} | 592 | Target->GotEntrySize, ".got") {} |
| 630 | 593 | ||
| 631 | void GotSection::addEntry(SymbolBody &Sym) { | 594 | void GotSection::addEntry(Symbol &Sym) { |
| 632 | Sym.GotIndex = NumEntries; | 595 | Sym.GotIndex = NumEntries; |
| 633 | ++NumEntries; | 596 | ++NumEntries; |
| 634 | } | 597 | } |
| 635 | 598 | ||
| 636 | bool GotSection::addDynTlsEntry(SymbolBody &Sym) { | 599 | bool GotSection::addDynTlsEntry(Symbol &Sym) { |
| 637 | if (Sym.GlobalDynIndex != -1U) | 600 | if (Sym.GlobalDynIndex != -1U) |
| 638 | return false; | 601 | return false; |
| 639 | Sym.GlobalDynIndex = NumEntries; | 602 | Sym.GlobalDynIndex = NumEntries; |
| ... | @@ -652,20 +615,21 @@ bool GotSection::addTlsIndex() { | ... | @@ -652,20 +615,21 @@ bool GotSection::addTlsIndex() { |
| 652 | return true; | 615 | return true; |
| 653 | } | 616 | } |
| 654 | 617 | ||
| 655 | uint64_t GotSection::getGlobalDynAddr(const SymbolBody &B) const { | 618 | uint64_t GotSection::getGlobalDynAddr(const Symbol &B) const { |
| 656 | return this->getVA() + B.GlobalDynIndex * Config->Wordsize; | 619 | return this->getVA() + B.GlobalDynIndex * Config->Wordsize; |
| 657 | } | 620 | } |
| 658 | 621 | ||
| 659 | uint64_t GotSection::getGlobalDynOffset(const SymbolBody &B) const { | 622 | uint64_t GotSection::getGlobalDynOffset(const Symbol &B) const { |
| 660 | return B.GlobalDynIndex * Config->Wordsize; | 623 | return B.GlobalDynIndex * Config->Wordsize; |
| 661 | } | 624 | } |
| 662 | 625 | ||
| 663 | void GotSection::finalizeContents() { Size = NumEntries * Config->Wordsize; } | 626 | void GotSection::finalizeContents() { Size = NumEntries * Config->Wordsize; } |
| 664 | 627 | ||
| 665 | bool GotSection::empty() const { | 628 | bool GotSection::empty() const { |
| 666 | // If we have a relocation that is relative to GOT (such as GOTOFFREL), | 629 | // We need to emit a GOT even if it's empty if there's a relocation that is |
| 667 | // we need to emit a GOT even if it's empty. | 630 | // relative to GOT(such as GOTOFFREL) or there's a symbol that points to a GOT |
| 668 | return NumEntries == 0 && !HasGotOffRel; | 631 | // (i.e. _GLOBAL_OFFSET_TABLE_). |
| 632 | return NumEntries == 0 && !HasGotOffRel && !ElfSym::GlobalOffsetTable; | ||
| 669 | } | 633 | } |
| 670 | 634 | ||
| 671 | void GotSection::writeTo(uint8_t *Buf) { | 635 | void GotSection::writeTo(uint8_t *Buf) { |
| ... | @@ -679,7 +643,7 @@ MipsGotSection::MipsGotSection() | ... | @@ -679,7 +643,7 @@ MipsGotSection::MipsGotSection() |
| 679 | : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16, | 643 | : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16, |
| 680 | ".got") {} | 644 | ".got") {} |
| 681 | 645 | ||
| 682 | void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { | 646 | void MipsGotSection::addEntry(Symbol &Sym, int64_t Addend, RelExpr Expr) { |
| 683 | // For "true" local symbols which can be referenced from the same module | 647 | // For "true" local symbols which can be referenced from the same module |
| 684 | // only compiler creates two instructions for address loading: | 648 | // only compiler creates two instructions for address loading: |
| 685 | // | 649 | // |
| ... | @@ -721,7 +685,7 @@ void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { | ... | @@ -721,7 +685,7 @@ void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { |
| 721 | TlsEntries.push_back(&Sym); | 685 | TlsEntries.push_back(&Sym); |
| 722 | return; | 686 | return; |
| 723 | } | 687 | } |
| 724 | auto AddEntry = [&](SymbolBody &S, uint64_t A, GotEntries &Items) { | 688 | auto AddEntry = [&](Symbol &S, uint64_t A, GotEntries &Items) { |
| 725 | if (S.isInGot() && !A) | 689 | if (S.isInGot() && !A) |
| 726 | return; | 690 | return; |
| 727 | size_t NewIndex = Items.size(); | 691 | size_t NewIndex = Items.size(); |
| ... | @@ -731,7 +695,7 @@ void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { | ... | @@ -731,7 +695,7 @@ void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { |
| 731 | if (!A) | 695 | if (!A) |
| 732 | S.GotIndex = NewIndex; | 696 | S.GotIndex = NewIndex; |
| 733 | }; | 697 | }; |
| 734 | if (Sym.isPreemptible()) { | 698 | if (Sym.IsPreemptible) { |
| 735 | // Ignore addends for preemptible symbols. They got single GOT entry anyway. | 699 | // Ignore addends for preemptible symbols. They got single GOT entry anyway. |
| 736 | AddEntry(Sym, 0, GlobalEntries); | 700 | AddEntry(Sym, 0, GlobalEntries); |
| 737 | Sym.IsInGlobalMipsGot = true; | 701 | Sym.IsInGlobalMipsGot = true; |
| ... | @@ -746,7 +710,7 @@ void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { | ... | @@ -746,7 +710,7 @@ void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { |
| 746 | } | 710 | } |
| 747 | } | 711 | } |
| 748 | 712 | ||
| 749 | bool MipsGotSection::addDynTlsEntry(SymbolBody &Sym) { | 713 | bool MipsGotSection::addDynTlsEntry(Symbol &Sym) { |
| 750 | if (Sym.GlobalDynIndex != -1U) | 714 | if (Sym.GlobalDynIndex != -1U) |
| 751 | return false; | 715 | return false; |
| 752 | Sym.GlobalDynIndex = TlsEntries.size(); | 716 | Sym.GlobalDynIndex = TlsEntries.size(); |
| ... | @@ -775,7 +739,7 @@ static uint64_t getMipsPageCount(uint64_t Size) { | ... | @@ -775,7 +739,7 @@ static uint64_t getMipsPageCount(uint64_t Size) { |
| 775 | return (Size + 0xfffe) / 0xffff + 1; | 739 | return (Size + 0xfffe) / 0xffff + 1; |
| 776 | } | 740 | } |
| 777 | 741 | ||
| 778 | uint64_t MipsGotSection::getPageEntryOffset(const SymbolBody &B, | 742 | uint64_t MipsGotSection::getPageEntryOffset(const Symbol &B, |
| 779 | int64_t Addend) const { | 743 | int64_t Addend) const { |
| 780 | const OutputSection *OutSec = B.getOutputSection(); | 744 | const OutputSection *OutSec = B.getOutputSection(); |
| 781 | uint64_t SecAddr = getMipsPageAddr(OutSec->Addr); | 745 | uint64_t SecAddr = getMipsPageAddr(OutSec->Addr); |
| ... | @@ -785,8 +749,8 @@ uint64_t MipsGotSection::getPageEntryOffset(const SymbolBody &B, | ... | @@ -785,8 +749,8 @@ uint64_t MipsGotSection::getPageEntryOffset(const SymbolBody &B, |
| 785 | return (HeaderEntriesNum + Index) * Config->Wordsize; | 749 | return (HeaderEntriesNum + Index) * Config->Wordsize; |
| 786 | } | 750 | } |
| 787 | 751 | ||
| 788 | uint64_t MipsGotSection::getBodyEntryOffset(const SymbolBody &B, | 752 | uint64_t MipsGotSection::getSymEntryOffset(const Symbol &B, |
| 789 | int64_t Addend) const { | 753 | int64_t Addend) const { |
| 790 | // Calculate offset of the GOT entries block: TLS, global, local. | 754 | // Calculate offset of the GOT entries block: TLS, global, local. |
| 791 | uint64_t Index = HeaderEntriesNum + PageEntriesNum; | 755 | uint64_t Index = HeaderEntriesNum + PageEntriesNum; |
| 792 | if (B.isTls()) | 756 | if (B.isTls()) |
| ... | @@ -810,11 +774,11 @@ uint64_t MipsGotSection::getTlsOffset() const { | ... | @@ -810,11 +774,11 @@ uint64_t MipsGotSection::getTlsOffset() const { |
| 810 | return (getLocalEntriesNum() + GlobalEntries.size()) * Config->Wordsize; | 774 | return (getLocalEntriesNum() + GlobalEntries.size()) * Config->Wordsize; |
| 811 | } | 775 | } |
| 812 | 776 | ||
| 813 | uint64_t MipsGotSection::getGlobalDynOffset(const SymbolBody &B) const { | 777 | uint64_t MipsGotSection::getGlobalDynOffset(const Symbol &B) const { |
| 814 | return B.GlobalDynIndex * Config->Wordsize; | 778 | return B.GlobalDynIndex * Config->Wordsize; |
| 815 | } | 779 | } |
| 816 | 780 | ||
| 817 | const SymbolBody *MipsGotSection::getFirstGlobalEntry() const { | 781 | const Symbol *MipsGotSection::getFirstGlobalEntry() const { |
| 818 | return GlobalEntries.empty() ? nullptr : GlobalEntries.front().first; | 782 | return GlobalEntries.empty() ? nullptr : GlobalEntries.front().first; |
| 819 | } | 783 | } |
| 820 | 784 | ||
| ... | @@ -825,7 +789,7 @@ unsigned MipsGotSection::getLocalEntriesNum() const { | ... | @@ -825,7 +789,7 @@ unsigned MipsGotSection::getLocalEntriesNum() const { |
| 825 | 789 | ||
| 826 | void MipsGotSection::finalizeContents() { updateAllocSize(); } | 790 | void MipsGotSection::finalizeContents() { updateAllocSize(); } |
| 827 | 791 | ||
| 828 | void MipsGotSection::updateAllocSize() { | 792 | bool MipsGotSection::updateAllocSize() { |
| 829 | PageEntriesNum = 0; | 793 | PageEntriesNum = 0; |
| 830 | for (std::pair<const OutputSection *, size_t> &P : PageIndexMap) { | 794 | for (std::pair<const OutputSection *, size_t> &P : PageIndexMap) { |
| 831 | // For each output section referenced by GOT page relocations calculate | 795 | // For each output section referenced by GOT page relocations calculate |
| ... | @@ -839,6 +803,7 @@ void MipsGotSection::updateAllocSize() { | ... | @@ -839,6 +803,7 @@ void MipsGotSection::updateAllocSize() { |
| 839 | } | 803 | } |
| 840 | Size = (getLocalEntriesNum() + GlobalEntries.size() + TlsEntries.size()) * | 804 | Size = (getLocalEntriesNum() + GlobalEntries.size() + TlsEntries.size()) * |
| 841 | Config->Wordsize; | 805 | Config->Wordsize; |
| 806 | return false; | ||
| 842 | } | 807 | } |
| 843 | 808 | ||
| 844 | bool MipsGotSection::empty() const { | 809 | bool MipsGotSection::empty() const { |
| ... | @@ -849,19 +814,6 @@ bool MipsGotSection::empty() const { | ... | @@ -849,19 +814,6 @@ bool MipsGotSection::empty() const { |
| 849 | 814 | ||
| 850 | uint64_t MipsGotSection::getGp() const { return ElfSym::MipsGp->getVA(0); } | 815 | uint64_t MipsGotSection::getGp() const { return ElfSym::MipsGp->getVA(0); } |
| 851 | 816 | ||
| 852 | static uint64_t readUint(uint8_t *Buf) { | ||
| 853 | if (Config->Is64) | ||
| 854 | return read64(Buf, Config->Endianness); | ||
| 855 | return read32(Buf, Config->Endianness); | ||
| 856 | } | ||
| 857 | |||
| 858 | static void writeUint(uint8_t *Buf, uint64_t Val) { | ||
| 859 | if (Config->Is64) | ||
| 860 | write64(Buf, Val, Config->Endianness); | ||
| 861 | else | ||
| 862 | write32(Buf, Val, Config->Endianness); | ||
| 863 | } | ||
| 864 | |||
| 865 | void MipsGotSection::writeTo(uint8_t *Buf) { | 817 | void MipsGotSection::writeTo(uint8_t *Buf) { |
| 866 | // Set the MSB of the second GOT slot. This is not required by any | 818 | // Set the MSB of the second GOT slot. This is not required by any |
| 867 | // MIPS ABI documentation, though. | 819 | // MIPS ABI documentation, though. |
| ... | @@ -892,8 +844,10 @@ void MipsGotSection::writeTo(uint8_t *Buf) { | ... | @@ -892,8 +844,10 @@ void MipsGotSection::writeTo(uint8_t *Buf) { |
| 892 | auto AddEntry = [&](const GotEntry &SA) { | 844 | auto AddEntry = [&](const GotEntry &SA) { |
| 893 | uint8_t *Entry = Buf; | 845 | uint8_t *Entry = Buf; |
| 894 | Buf += Config->Wordsize; | 846 | Buf += Config->Wordsize; |
| 895 | const SymbolBody *Body = SA.first; | 847 | const Symbol *Sym = SA.first; |
| 896 | uint64_t VA = Body->getVA(SA.second); | 848 | uint64_t VA = Sym->getVA(SA.second); |
| 849 | if (Sym->StOther & STO_MIPS_MICROMIPS) | ||
| 850 | VA |= 1; | ||
| 897 | writeUint(Entry, VA); | 851 | writeUint(Entry, VA); |
| 898 | }; | 852 | }; |
| 899 | std::for_each(std::begin(LocalEntries), std::end(LocalEntries), AddEntry); | 853 | std::for_each(std::begin(LocalEntries), std::end(LocalEntries), AddEntry); |
| ... | @@ -906,8 +860,8 @@ void MipsGotSection::writeTo(uint8_t *Buf) { | ... | @@ -906,8 +860,8 @@ void MipsGotSection::writeTo(uint8_t *Buf) { |
| 906 | // https://www.linux-mips.org/wiki/NPTL | 860 | // https://www.linux-mips.org/wiki/NPTL |
| 907 | if (TlsIndexOff != -1U && !Config->Pic) | 861 | if (TlsIndexOff != -1U && !Config->Pic) |
| 908 | writeUint(Buf + TlsIndexOff, 1); | 862 | writeUint(Buf + TlsIndexOff, 1); |
| 909 | for (const SymbolBody *B : TlsEntries) { | 863 | for (const Symbol *B : TlsEntries) { |
| 910 | if (!B || B->isPreemptible()) | 864 | if (!B || B->IsPreemptible) |
| 911 | continue; | 865 | continue; |
| 912 | uint64_t VA = B->getVA(); | 866 | uint64_t VA = B->getVA(); |
| 913 | if (B->GotIndex != -1U) { | 867 | if (B->GotIndex != -1U) { |
| ... | @@ -927,7 +881,7 @@ GotPltSection::GotPltSection() | ... | @@ -927,7 +881,7 @@ GotPltSection::GotPltSection() |
| 927 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, | 881 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, |
| 928 | Target->GotPltEntrySize, ".got.plt") {} | 882 | Target->GotPltEntrySize, ".got.plt") {} |
| 929 | 883 | ||
| 930 | void GotPltSection::addEntry(SymbolBody &Sym) { | 884 | void GotPltSection::addEntry(Symbol &Sym) { |
| 931 | Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size(); | 885 | Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size(); |
| 932 | Entries.push_back(&Sym); | 886 | Entries.push_back(&Sym); |
| 933 | } | 887 | } |
| ... | @@ -940,7 +894,7 @@ size_t GotPltSection::getSize() const { | ... | @@ -940,7 +894,7 @@ size_t GotPltSection::getSize() const { |
| 940 | void GotPltSection::writeTo(uint8_t *Buf) { | 894 | void GotPltSection::writeTo(uint8_t *Buf) { |
| 941 | Target->writeGotPltHeader(Buf); | 895 | Target->writeGotPltHeader(Buf); |
| 942 | Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize; | 896 | Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize; |
| 943 | for (const SymbolBody *B : Entries) { | 897 | for (const Symbol *B : Entries) { |
| 944 | Target->writeGotPlt(Buf, *B); | 898 | Target->writeGotPlt(Buf, *B); |
| 945 | Buf += Config->Wordsize; | 899 | Buf += Config->Wordsize; |
| 946 | } | 900 | } |
| ... | @@ -953,7 +907,7 @@ IgotPltSection::IgotPltSection() | ... | @@ -953,7 +907,7 @@ IgotPltSection::IgotPltSection() |
| 953 | Target->GotPltEntrySize, | 907 | Target->GotPltEntrySize, |
| 954 | Config->EMachine == EM_ARM ? ".got" : ".got.plt") {} | 908 | Config->EMachine == EM_ARM ? ".got" : ".got.plt") {} |
| 955 | 909 | ||
| 956 | void IgotPltSection::addEntry(SymbolBody &Sym) { | 910 | void IgotPltSection::addEntry(Symbol &Sym) { |
| 957 | Sym.IsInIgot = true; | 911 | Sym.IsInIgot = true; |
| 958 | Sym.GotPltIndex = Entries.size(); | 912 | Sym.GotPltIndex = Entries.size(); |
| 959 | Entries.push_back(&Sym); | 913 | Entries.push_back(&Sym); |
| ... | @@ -964,7 +918,7 @@ size_t IgotPltSection::getSize() const { | ... | @@ -964,7 +918,7 @@ size_t IgotPltSection::getSize() const { |
| 964 | } | 918 | } |
| 965 | 919 | ||
| 966 | void IgotPltSection::writeTo(uint8_t *Buf) { | 920 | void IgotPltSection::writeTo(uint8_t *Buf) { |
| 967 | for (const SymbolBody *B : Entries) { | 921 | for (const Symbol *B : Entries) { |
| 968 | Target->writeIgotPlt(Buf, *B); | 922 | Target->writeIgotPlt(Buf, *B); |
| 969 | Buf += Config->Wordsize; | 923 | Buf += Config->Wordsize; |
| 970 | } | 924 | } |
| ... | @@ -996,6 +950,7 @@ unsigned StringTableSection::addString(StringRef S, bool HashIt) { | ... | @@ -996,6 +950,7 @@ unsigned StringTableSection::addString(StringRef S, bool HashIt) { |
| 996 | void StringTableSection::writeTo(uint8_t *Buf) { | 950 | void StringTableSection::writeTo(uint8_t *Buf) { |
| 997 | for (StringRef S : Strings) { | 951 | for (StringRef S : Strings) { |
| 998 | memcpy(Buf, S.data(), S.size()); | 952 | memcpy(Buf, S.data(), S.size()); |
| 953 | Buf[S.size()] = '\0'; | ||
| 999 | Buf += S.size() + 1; | 954 | Buf += S.size() + 1; |
| 1000 | } | 955 | } |
| 1001 | } | 956 | } |
| ... | @@ -1018,26 +973,61 @@ DynamicSection<ELFT>::DynamicSection() | ... | @@ -1018,26 +973,61 @@ DynamicSection<ELFT>::DynamicSection() |
| 1018 | if (Config->EMachine == EM_MIPS || Config->ZRodynamic) | 973 | if (Config->EMachine == EM_MIPS || Config->ZRodynamic) |
| 1019 | this->Flags = SHF_ALLOC; | 974 | this->Flags = SHF_ALLOC; |
| 1020 | 975 | ||
| 1021 | addEntries(); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | // There are some dynamic entries that don't depend on other sections. | ||
| 1025 | // Such entries can be set early. | ||
| 1026 | template <class ELFT> void DynamicSection<ELFT>::addEntries() { | ||
| 1027 | // Add strings to .dynstr early so that .dynstr's size will be | 976 | // Add strings to .dynstr early so that .dynstr's size will be |
| 1028 | // fixed early. | 977 | // fixed early. |
| 1029 | for (StringRef S : Config->FilterList) | 978 | for (StringRef S : Config->FilterList) |
| 1030 | add({DT_FILTER, InX::DynStrTab->addString(S)}); | 979 | addInt(DT_FILTER, InX::DynStrTab->addString(S)); |
| 1031 | for (StringRef S : Config->AuxiliaryList) | 980 | for (StringRef S : Config->AuxiliaryList) |
| 1032 | add({DT_AUXILIARY, InX::DynStrTab->addString(S)}); | 981 | addInt(DT_AUXILIARY, InX::DynStrTab->addString(S)); |
| 982 | |||
| 1033 | if (!Config->Rpath.empty()) | 983 | if (!Config->Rpath.empty()) |
| 1034 | add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, | 984 | addInt(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, |
| 1035 | InX::DynStrTab->addString(Config->Rpath)}); | 985 | InX::DynStrTab->addString(Config->Rpath)); |
| 1036 | for (SharedFile<ELFT> *F : Symtab<ELFT>::X->getSharedFiles()) | 986 | |
| 1037 | if (F->isNeeded()) | 987 | for (InputFile *File : SharedFiles) { |
| 1038 | add({DT_NEEDED, InX::DynStrTab->addString(F->SoName)}); | 988 | SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File); |
| 989 | if (F->IsNeeded) | ||
| 990 | addInt(DT_NEEDED, InX::DynStrTab->addString(F->SoName)); | ||
| 991 | } | ||
| 1039 | if (!Config->SoName.empty()) | 992 | if (!Config->SoName.empty()) |
| 1040 | add({DT_SONAME, InX::DynStrTab->addString(Config->SoName)}); | 993 | addInt(DT_SONAME, InX::DynStrTab->addString(Config->SoName)); |
| 994 | } | ||
| 995 | |||
| 996 | template <class ELFT> | ||
| 997 | void DynamicSection<ELFT>::add(int32_t Tag, std::function<uint64_t()> Fn) { | ||
| 998 | Entries.push_back({Tag, Fn}); | ||
| 999 | } | ||
| 1000 | |||
| 1001 | template <class ELFT> | ||
| 1002 | void DynamicSection<ELFT>::addInt(int32_t Tag, uint64_t Val) { | ||
| 1003 | Entries.push_back({Tag, [=] { return Val; }}); | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | template <class ELFT> | ||
| 1007 | void DynamicSection<ELFT>::addInSec(int32_t Tag, InputSection *Sec) { | ||
| 1008 | Entries.push_back( | ||
| 1009 | {Tag, [=] { return Sec->getParent()->Addr + Sec->OutSecOff; }}); | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | template <class ELFT> | ||
| 1013 | void DynamicSection<ELFT>::addOutSec(int32_t Tag, OutputSection *Sec) { | ||
| 1014 | Entries.push_back({Tag, [=] { return Sec->Addr; }}); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | template <class ELFT> | ||
| 1018 | void DynamicSection<ELFT>::addSize(int32_t Tag, OutputSection *Sec) { | ||
| 1019 | Entries.push_back({Tag, [=] { return Sec->Size; }}); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | template <class ELFT> | ||
| 1023 | void DynamicSection<ELFT>::addSym(int32_t Tag, Symbol *Sym) { | ||
| 1024 | Entries.push_back({Tag, [=] { return Sym->getVA(); }}); | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | // Add remaining entries to complete .dynamic contents. | ||
| 1028 | template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { | ||
| 1029 | if (this->Size) | ||
| 1030 | return; // Already finalized. | ||
| 1041 | 1031 | ||
| 1042 | // Set DT_FLAGS and DT_FLAGS_1. | 1032 | // Set DT_FLAGS and DT_FLAGS_1. |
| 1043 | uint32_t DtFlags = 0; | 1033 | uint32_t DtFlags = 0; |
| ... | @@ -1058,9 +1048,9 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() { | ... | @@ -1058,9 +1048,9 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() { |
| 1058 | } | 1048 | } |
| 1059 | 1049 | ||
| 1060 | if (DtFlags) | 1050 | if (DtFlags) |
| 1061 | add({DT_FLAGS, DtFlags}); | 1051 | addInt(DT_FLAGS, DtFlags); |
| 1062 | if (DtFlags1) | 1052 | if (DtFlags1) |
| 1063 | add({DT_FLAGS_1, DtFlags1}); | 1053 | addInt(DT_FLAGS_1, DtFlags1); |
| 1064 | 1054 | ||
| 1065 | // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We | 1055 | // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We |
| 1066 | // need it for each process, so we don't write it for DSOs. The loader writes | 1056 | // need it for each process, so we don't write it for DSOs. The loader writes |
| ... | @@ -1071,133 +1061,121 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() { | ... | @@ -1071,133 +1061,121 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() { |
| 1071 | // debugger this information. Such systems may choose make .dynamic read-only. | 1061 | // debugger this information. Such systems may choose make .dynamic read-only. |
| 1072 | // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. | 1062 | // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. |
| 1073 | if (!Config->Shared && !Config->Relocatable && !Config->ZRodynamic) | 1063 | if (!Config->Shared && !Config->Relocatable && !Config->ZRodynamic) |
| 1074 | add({DT_DEBUG, (uint64_t)0}); | 1064 | addInt(DT_DEBUG, 0); |
| 1075 | } | ||
| 1076 | |||
| 1077 | // Add remaining entries to complete .dynamic contents. | ||
| 1078 | template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { | ||
| 1079 | if (this->Size) | ||
| 1080 | return; // Already finalized. | ||
| 1081 | 1065 | ||
| 1082 | this->Link = InX::DynStrTab->getParent()->SectionIndex; | 1066 | this->Link = InX::DynStrTab->getParent()->SectionIndex; |
| 1083 | if (In<ELFT>::RelaDyn->getParent() && !In<ELFT>::RelaDyn->empty()) { | 1067 | if (!InX::RelaDyn->empty()) { |
| 1068 | addInSec(InX::RelaDyn->DynamicTag, InX::RelaDyn); | ||
| 1069 | addSize(InX::RelaDyn->SizeDynamicTag, InX::RelaDyn->getParent()); | ||
| 1070 | |||
| 1084 | bool IsRela = Config->IsRela; | 1071 | bool IsRela = Config->IsRela; |
| 1085 | add({IsRela ? DT_RELA : DT_REL, In<ELFT>::RelaDyn}); | 1072 | addInt(IsRela ? DT_RELAENT : DT_RELENT, |
| 1086 | add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->getParent(), | 1073 | IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)); |
| 1087 | Entry::SecSize}); | ||
| 1088 | add({IsRela ? DT_RELAENT : DT_RELENT, | ||
| 1089 | uint64_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); | ||
| 1090 | 1074 | ||
| 1091 | // MIPS dynamic loader does not support RELCOUNT tag. | 1075 | // MIPS dynamic loader does not support RELCOUNT tag. |
| 1092 | // The problem is in the tight relation between dynamic | 1076 | // The problem is in the tight relation between dynamic |
| 1093 | // relocations and GOT. So do not emit this tag on MIPS. | 1077 | // relocations and GOT. So do not emit this tag on MIPS. |
| 1094 | if (Config->EMachine != EM_MIPS) { | 1078 | if (Config->EMachine != EM_MIPS) { |
| 1095 | size_t NumRelativeRels = In<ELFT>::RelaDyn->getRelativeRelocCount(); | 1079 | size_t NumRelativeRels = InX::RelaDyn->getRelativeRelocCount(); |
| 1096 | if (Config->ZCombreloc && NumRelativeRels) | 1080 | if (Config->ZCombreloc && NumRelativeRels) |
| 1097 | add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels}); | 1081 | addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels); |
| 1098 | } | 1082 | } |
| 1099 | } | 1083 | } |
| 1100 | if (In<ELFT>::RelaPlt->getParent() && !In<ELFT>::RelaPlt->empty()) { | 1084 | // .rel[a].plt section usually consists of two parts, containing plt and |
| 1101 | add({DT_JMPREL, In<ELFT>::RelaPlt}); | 1085 | // iplt relocations. It is possible to have only iplt relocations in the |
| 1102 | add({DT_PLTRELSZ, In<ELFT>::RelaPlt->getParent(), Entry::SecSize}); | 1086 | // output. In that case RelaPlt is empty and have zero offset, the same offset |
| 1087 | // as RelaIplt have. And we still want to emit proper dynamic tags for that | ||
| 1088 | // case, so here we always use RelaPlt as marker for the begining of | ||
| 1089 | // .rel[a].plt section. | ||
| 1090 | if (InX::RelaPlt->getParent()->Live) { | ||
| 1091 | addInSec(DT_JMPREL, InX::RelaPlt); | ||
| 1092 | addSize(DT_PLTRELSZ, InX::RelaPlt->getParent()); | ||
| 1103 | switch (Config->EMachine) { | 1093 | switch (Config->EMachine) { |
| 1104 | case EM_MIPS: | 1094 | case EM_MIPS: |
| 1105 | add({DT_MIPS_PLTGOT, In<ELFT>::GotPlt}); | 1095 | addInSec(DT_MIPS_PLTGOT, InX::GotPlt); |
| 1106 | break; | 1096 | break; |
| 1107 | case EM_SPARCV9: | 1097 | case EM_SPARCV9: |
| 1108 | add({DT_PLTGOT, In<ELFT>::Plt}); | 1098 | addInSec(DT_PLTGOT, InX::Plt); |
| 1109 | break; | 1099 | break; |
| 1110 | default: | 1100 | default: |
| 1111 | add({DT_PLTGOT, In<ELFT>::GotPlt}); | 1101 | addInSec(DT_PLTGOT, InX::GotPlt); |
| 1112 | break; | 1102 | break; |
| 1113 | } | 1103 | } |
| 1114 | add({DT_PLTREL, uint64_t(Config->IsRela ? DT_RELA : DT_REL)}); | 1104 | addInt(DT_PLTREL, Config->IsRela ? DT_RELA : DT_REL); |
| 1115 | } | 1105 | } |
| 1116 | 1106 | ||
| 1117 | add({DT_SYMTAB, InX::DynSymTab}); | 1107 | addInSec(DT_SYMTAB, InX::DynSymTab); |
| 1118 | add({DT_SYMENT, sizeof(Elf_Sym)}); | 1108 | addInt(DT_SYMENT, sizeof(Elf_Sym)); |
| 1119 | add({DT_STRTAB, InX::DynStrTab}); | 1109 | addInSec(DT_STRTAB, InX::DynStrTab); |
| 1120 | add({DT_STRSZ, InX::DynStrTab->getSize()}); | 1110 | addInt(DT_STRSZ, InX::DynStrTab->getSize()); |
| 1121 | if (!Config->ZText) | 1111 | if (!Config->ZText) |
| 1122 | add({DT_TEXTREL, (uint64_t)0}); | 1112 | addInt(DT_TEXTREL, 0); |
| 1123 | if (InX::GnuHashTab) | 1113 | if (InX::GnuHashTab) |
| 1124 | add({DT_GNU_HASH, InX::GnuHashTab}); | 1114 | addInSec(DT_GNU_HASH, InX::GnuHashTab); |
| 1125 | if (In<ELFT>::HashTab) | 1115 | if (InX::HashTab) |
| 1126 | add({DT_HASH, In<ELFT>::HashTab}); | 1116 | addInSec(DT_HASH, InX::HashTab); |
| 1127 | 1117 | ||
| 1128 | if (Out::PreinitArray) { | 1118 | if (Out::PreinitArray) { |
| 1129 | add({DT_PREINIT_ARRAY, Out::PreinitArray}); | 1119 | addOutSec(DT_PREINIT_ARRAY, Out::PreinitArray); |
| 1130 | add({DT_PREINIT_ARRAYSZ, Out::PreinitArray, Entry::SecSize}); | 1120 | addSize(DT_PREINIT_ARRAYSZ, Out::PreinitArray); |
| 1131 | } | 1121 | } |
| 1132 | if (Out::InitArray) { | 1122 | if (Out::InitArray) { |
| 1133 | add({DT_INIT_ARRAY, Out::InitArray}); | 1123 | addOutSec(DT_INIT_ARRAY, Out::InitArray); |
| 1134 | add({DT_INIT_ARRAYSZ, Out::InitArray, Entry::SecSize}); | 1124 | addSize(DT_INIT_ARRAYSZ, Out::InitArray); |
| 1135 | } | 1125 | } |
| 1136 | if (Out::FiniArray) { | 1126 | if (Out::FiniArray) { |
| 1137 | add({DT_FINI_ARRAY, Out::FiniArray}); | 1127 | addOutSec(DT_FINI_ARRAY, Out::FiniArray); |
| 1138 | add({DT_FINI_ARRAYSZ, Out::FiniArray, Entry::SecSize}); | 1128 | addSize(DT_FINI_ARRAYSZ, Out::FiniArray); |
| 1139 | } | 1129 | } |
| 1140 | 1130 | ||
| 1141 | if (SymbolBody *B = Symtab<ELFT>::X->findInCurrentDSO(Config->Init)) | 1131 | if (Symbol *B = Symtab->find(Config->Init)) |
| 1142 | add({DT_INIT, B}); | 1132 | if (B->isDefined()) |
| 1143 | if (SymbolBody *B = Symtab<ELFT>::X->findInCurrentDSO(Config->Fini)) | 1133 | addSym(DT_INIT, B); |
| 1144 | add({DT_FINI, B}); | 1134 | if (Symbol *B = Symtab->find(Config->Fini)) |
| 1135 | if (B->isDefined()) | ||
| 1136 | addSym(DT_FINI, B); | ||
| 1145 | 1137 | ||
| 1146 | bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0; | 1138 | bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0; |
| 1147 | if (HasVerNeed || In<ELFT>::VerDef) | 1139 | if (HasVerNeed || In<ELFT>::VerDef) |
| 1148 | add({DT_VERSYM, In<ELFT>::VerSym}); | 1140 | addInSec(DT_VERSYM, In<ELFT>::VerSym); |
| 1149 | if (In<ELFT>::VerDef) { | 1141 | if (In<ELFT>::VerDef) { |
| 1150 | add({DT_VERDEF, In<ELFT>::VerDef}); | 1142 | addInSec(DT_VERDEF, In<ELFT>::VerDef); |
| 1151 | add({DT_VERDEFNUM, getVerDefNum()}); | 1143 | addInt(DT_VERDEFNUM, getVerDefNum()); |
| 1152 | } | 1144 | } |
| 1153 | if (HasVerNeed) { | 1145 | if (HasVerNeed) { |
| 1154 | add({DT_VERNEED, In<ELFT>::VerNeed}); | 1146 | addInSec(DT_VERNEED, In<ELFT>::VerNeed); |
| 1155 | add({DT_VERNEEDNUM, In<ELFT>::VerNeed->getNeedNum()}); | 1147 | addInt(DT_VERNEEDNUM, In<ELFT>::VerNeed->getNeedNum()); |
| 1156 | } | 1148 | } |
| 1157 | 1149 | ||
| 1158 | if (Config->EMachine == EM_MIPS) { | 1150 | if (Config->EMachine == EM_MIPS) { |
| 1159 | add({DT_MIPS_RLD_VERSION, 1}); | 1151 | addInt(DT_MIPS_RLD_VERSION, 1); |
| 1160 | add({DT_MIPS_FLAGS, RHF_NOTPOT}); | 1152 | addInt(DT_MIPS_FLAGS, RHF_NOTPOT); |
| 1161 | add({DT_MIPS_BASE_ADDRESS, Config->ImageBase}); | 1153 | addInt(DT_MIPS_BASE_ADDRESS, Target->getImageBase()); |
| 1162 | add({DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols()}); | 1154 | addInt(DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols()); |
| 1163 | add({DT_MIPS_LOCAL_GOTNO, InX::MipsGot->getLocalEntriesNum()}); | 1155 | |
| 1164 | if (const SymbolBody *B = InX::MipsGot->getFirstGlobalEntry()) | 1156 | add(DT_MIPS_LOCAL_GOTNO, [] { return InX::MipsGot->getLocalEntriesNum(); }); |
| 1165 | add({DT_MIPS_GOTSYM, B->DynsymIndex}); | 1157 | |
| 1158 | if (const Symbol *B = InX::MipsGot->getFirstGlobalEntry()) | ||
| 1159 | addInt(DT_MIPS_GOTSYM, B->DynsymIndex); | ||
| 1166 | else | 1160 | else |
| 1167 | add({DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols()}); | 1161 | addInt(DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols()); |
| 1168 | add({DT_PLTGOT, InX::MipsGot}); | 1162 | addInSec(DT_PLTGOT, InX::MipsGot); |
| 1169 | if (InX::MipsRldMap) | 1163 | if (InX::MipsRldMap) |
| 1170 | add({DT_MIPS_RLD_MAP, InX::MipsRldMap}); | 1164 | addInSec(DT_MIPS_RLD_MAP, InX::MipsRldMap); |
| 1171 | } | 1165 | } |
| 1172 | 1166 | ||
| 1173 | getParent()->Link = this->Link; | 1167 | addInt(DT_NULL, 0); |
| 1174 | 1168 | ||
| 1175 | // +1 for DT_NULL | 1169 | getParent()->Link = this->Link; |
| 1176 | this->Size = (Entries.size() + 1) * this->Entsize; | 1170 | this->Size = Entries.size() * this->Entsize; |
| 1177 | } | 1171 | } |
| 1178 | 1172 | ||
| 1179 | template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { | 1173 | template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { |
| 1180 | auto *P = reinterpret_cast<Elf_Dyn *>(Buf); | 1174 | auto *P = reinterpret_cast<Elf_Dyn *>(Buf); |
| 1181 | 1175 | ||
| 1182 | for (const Entry &E : Entries) { | 1176 | for (std::pair<int32_t, std::function<uint64_t()>> &KV : Entries) { |
| 1183 | P->d_tag = E.Tag; | 1177 | P->d_tag = KV.first; |
| 1184 | switch (E.Kind) { | 1178 | P->d_un.d_val = KV.second(); |
| 1185 | case Entry::SecAddr: | ||
| 1186 | P->d_un.d_ptr = E.OutSec->Addr; | ||
| 1187 | break; | ||
| 1188 | case Entry::InSecAddr: | ||
| 1189 | P->d_un.d_ptr = E.InSec->getParent()->Addr + E.InSec->OutSecOff; | ||
| 1190 | break; | ||
| 1191 | case Entry::SecSize: | ||
| 1192 | P->d_un.d_val = E.OutSec->Size; | ||
| 1193 | break; | ||
| 1194 | case Entry::SymAddr: | ||
| 1195 | P->d_un.d_ptr = E.Sym->getVA(); | ||
| 1196 | break; | ||
| 1197 | case Entry::PlainInt: | ||
| 1198 | P->d_un.d_val = E.Val; | ||
| 1199 | break; | ||
| 1200 | } | ||
| 1201 | ++P; | 1179 | ++P; |
| 1202 | } | 1180 | } |
| 1203 | } | 1181 | } |
| ... | @@ -1218,21 +1196,57 @@ uint32_t DynamicReloc::getSymIndex() const { | ... | @@ -1218,21 +1196,57 @@ uint32_t DynamicReloc::getSymIndex() const { |
| 1218 | return 0; | 1196 | return 0; |
| 1219 | } | 1197 | } |
| 1220 | 1198 | ||
| 1221 | template <class ELFT> | 1199 | RelocationBaseSection::RelocationBaseSection(StringRef Name, uint32_t Type, |
| 1222 | RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort) | 1200 | int32_t DynamicTag, |
| 1223 | : SyntheticSection(SHF_ALLOC, Config->IsRela ? SHT_RELA : SHT_REL, | 1201 | int32_t SizeDynamicTag) |
| 1224 | Config->Wordsize, Name), | 1202 | : SyntheticSection(SHF_ALLOC, Type, Config->Wordsize, Name), |
| 1225 | Sort(Sort) { | 1203 | DynamicTag(DynamicTag), SizeDynamicTag(SizeDynamicTag) {} |
| 1226 | this->Entsize = Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); | ||
| 1227 | } | ||
| 1228 | 1204 | ||
| 1229 | template <class ELFT> | 1205 | void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) { |
| 1230 | void RelocationSection<ELFT>::addReloc(const DynamicReloc &Reloc) { | ||
| 1231 | if (Reloc.Type == Target->RelativeRel) | 1206 | if (Reloc.Type == Target->RelativeRel) |
| 1232 | ++NumRelativeRelocs; | 1207 | ++NumRelativeRelocs; |
| 1233 | Relocs.push_back(Reloc); | 1208 | Relocs.push_back(Reloc); |
| 1234 | } | 1209 | } |
| 1235 | 1210 | ||
| 1211 | void RelocationBaseSection::finalizeContents() { | ||
| 1212 | // If all relocations are R_*_RELATIVE they don't refer to any | ||
| 1213 | // dynamic symbol and we don't need a dynamic symbol table. If that | ||
| 1214 | // is the case, just use 0 as the link. | ||
| 1215 | Link = InX::DynSymTab ? InX::DynSymTab->getParent()->SectionIndex : 0; | ||
| 1216 | |||
| 1217 | // Set required output section properties. | ||
| 1218 | getParent()->Link = Link; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | template <class ELFT> | ||
| 1222 | static void encodeDynamicReloc(typename ELFT::Rela *P, | ||
| 1223 | const DynamicReloc &Rel) { | ||
| 1224 | if (Config->IsRela) | ||
| 1225 | P->r_addend = Rel.getAddend(); | ||
| 1226 | P->r_offset = Rel.getOffset(); | ||
| 1227 | if (Config->EMachine == EM_MIPS && Rel.getInputSec() == InX::MipsGot) | ||
| 1228 | // The MIPS GOT section contains dynamic relocations that correspond to TLS | ||
| 1229 | // entries. These entries are placed after the global and local sections of | ||
| 1230 | // the GOT. At the point when we create these relocations, the size of the | ||
| 1231 | // global and local sections is unknown, so the offset that we store in the | ||
| 1232 | // TLS entry's DynamicReloc is relative to the start of the TLS section of | ||
| 1233 | // the GOT, rather than being relative to the start of the GOT. This line of | ||
| 1234 | // code adds the size of the global and local sections to the virtual | ||
| 1235 | // address computed by getOffset() in order to adjust it into the TLS | ||
| 1236 | // section. | ||
| 1237 | P->r_offset += InX::MipsGot->getTlsOffset(); | ||
| 1238 | P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->IsMips64EL); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | template <class ELFT> | ||
| 1242 | RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort) | ||
| 1243 | : RelocationBaseSection(Name, Config->IsRela ? SHT_RELA : SHT_REL, | ||
| 1244 | Config->IsRela ? DT_RELA : DT_REL, | ||
| 1245 | Config->IsRela ? DT_RELASZ : DT_RELSZ), | ||
| 1246 | Sort(Sort) { | ||
| 1247 | this->Entsize = Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); | ||
| 1248 | } | ||
| 1249 | |||
| 1236 | template <class ELFT, class RelTy> | 1250 | template <class ELFT, class RelTy> |
| 1237 | static bool compRelocations(const RelTy &A, const RelTy &B) { | 1251 | static bool compRelocations(const RelTy &A, const RelTy &B) { |
| 1238 | bool AIsRel = A.getType(Config->IsMips64EL) == Target->RelativeRel; | 1252 | bool AIsRel = A.getType(Config->IsMips64EL) == Target->RelativeRel; |
| ... | @@ -1246,18 +1260,8 @@ static bool compRelocations(const RelTy &A, const RelTy &B) { | ... | @@ -1246,18 +1260,8 @@ static bool compRelocations(const RelTy &A, const RelTy &B) { |
| 1246 | template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { | 1260 | template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { |
| 1247 | uint8_t *BufBegin = Buf; | 1261 | uint8_t *BufBegin = Buf; |
| 1248 | for (const DynamicReloc &Rel : Relocs) { | 1262 | for (const DynamicReloc &Rel : Relocs) { |
| 1249 | auto *P = reinterpret_cast<Elf_Rela *>(Buf); | 1263 | encodeDynamicReloc<ELFT>(reinterpret_cast<Elf_Rela *>(Buf), Rel); |
| 1250 | Buf += Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); | 1264 | Buf += Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); |
| 1251 | |||
| 1252 | if (Config->IsRela) | ||
| 1253 | P->r_addend = Rel.getAddend(); | ||
| 1254 | P->r_offset = Rel.getOffset(); | ||
| 1255 | if (Config->EMachine == EM_MIPS && Rel.getInputSec() == InX::MipsGot) | ||
| 1256 | // Dynamic relocation against MIPS GOT section make deal TLS entries | ||
| 1257 | // allocated in the end of the GOT. We need to adjust the offset to take | ||
| 1258 | // in account 'local' and 'global' GOT entries. | ||
| 1259 | P->r_offset += InX::MipsGot->getTlsOffset(); | ||
| 1260 | P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->IsMips64EL); | ||
| 1261 | } | 1265 | } |
| 1262 | 1266 | ||
| 1263 | if (Sort) { | 1267 | if (Sort) { |
| ... | @@ -1275,12 +1279,192 @@ template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() { | ... | @@ -1275,12 +1279,192 @@ template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() { |
| 1275 | return this->Entsize * Relocs.size(); | 1279 | return this->Entsize * Relocs.size(); |
| 1276 | } | 1280 | } |
| 1277 | 1281 | ||
| 1278 | template <class ELFT> void RelocationSection<ELFT>::finalizeContents() { | 1282 | template <class ELFT> |
| 1279 | this->Link = InX::DynSymTab ? InX::DynSymTab->getParent()->SectionIndex | 1283 | AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection( |
| 1280 | : InX::SymTab->getParent()->SectionIndex; | 1284 | StringRef Name) |
| 1285 | : RelocationBaseSection( | ||
| 1286 | Name, Config->IsRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL, | ||
| 1287 | Config->IsRela ? DT_ANDROID_RELA : DT_ANDROID_REL, | ||
| 1288 | Config->IsRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) { | ||
| 1289 | this->Entsize = 1; | ||
| 1290 | } | ||
| 1281 | 1291 | ||
| 1282 | // Set required output section properties. | 1292 | template <class ELFT> |
| 1283 | getParent()->Link = this->Link; | 1293 | bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() { |
| 1294 | // This function computes the contents of an Android-format packed relocation | ||
| 1295 | // section. | ||
| 1296 | // | ||
| 1297 | // This format compresses relocations by using relocation groups to factor out | ||
| 1298 | // fields that are common between relocations and storing deltas from previous | ||
| 1299 | // relocations in SLEB128 format (which has a short representation for small | ||
| 1300 | // numbers). A good example of a relocation type with common fields is | ||
| 1301 | // R_*_RELATIVE, which is normally used to represent function pointers in | ||
| 1302 | // vtables. In the REL format, each relative relocation has the same r_info | ||
| 1303 | // field, and is only different from other relative relocations in terms of | ||
| 1304 | // the r_offset field. By sorting relocations by offset, grouping them by | ||
| 1305 | // r_info and representing each relocation with only the delta from the | ||
| 1306 | // previous offset, each 8-byte relocation can be compressed to as little as 1 | ||
| 1307 | // byte (or less with run-length encoding). This relocation packer was able to | ||
| 1308 | // reduce the size of the relocation section in an Android Chromium DSO from | ||
| 1309 | // 2,911,184 bytes to 174,693 bytes, or 6% of the original size. | ||
| 1310 | // | ||
| 1311 | // A relocation section consists of a header containing the literal bytes | ||
| 1312 | // 'APS2' followed by a sequence of SLEB128-encoded integers. The first two | ||
| 1313 | // elements are the total number of relocations in the section and an initial | ||
| 1314 | // r_offset value. The remaining elements define a sequence of relocation | ||
| 1315 | // groups. Each relocation group starts with a header consisting of the | ||
| 1316 | // following elements: | ||
| 1317 | // | ||
| 1318 | // - the number of relocations in the relocation group | ||
| 1319 | // - flags for the relocation group | ||
| 1320 | // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is set) the r_offset delta | ||
| 1321 | // for each relocation in the group. | ||
| 1322 | // - (if RELOCATION_GROUPED_BY_INFO_FLAG is set) the value of the r_info | ||
| 1323 | // field for each relocation in the group. | ||
| 1324 | // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG and | ||
| 1325 | // RELOCATION_GROUPED_BY_ADDEND_FLAG are set) the r_addend delta for | ||
| 1326 | // each relocation in the group. | ||
| 1327 | // | ||
| 1328 | // Following the relocation group header are descriptions of each of the | ||
| 1329 | // relocations in the group. They consist of the following elements: | ||
| 1330 | // | ||
| 1331 | // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is not set) the r_offset | ||
| 1332 | // delta for this relocation. | ||
| 1333 | // - (if RELOCATION_GROUPED_BY_INFO_FLAG is not set) the value of the r_info | ||
| 1334 | // field for this relocation. | ||
| 1335 | // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG is set and | ||
| 1336 | // RELOCATION_GROUPED_BY_ADDEND_FLAG is not set) the r_addend delta for | ||
| 1337 | // this relocation. | ||
| 1338 | |||
| 1339 | size_t OldSize = RelocData.size(); | ||
| 1340 | |||
| 1341 | RelocData = {'A', 'P', 'S', '2'}; | ||
| 1342 | raw_svector_ostream OS(RelocData); | ||
| 1343 | auto Add = [&](int64_t V) { encodeSLEB128(V, OS); }; | ||
| 1344 | |||
| 1345 | // The format header includes the number of relocations and the initial | ||
| 1346 | // offset (we set this to zero because the first relocation group will | ||
| 1347 | // perform the initial adjustment). | ||
| 1348 | Add(Relocs.size()); | ||
| 1349 | Add(0); | ||
| 1350 | |||
| 1351 | std::vector<Elf_Rela> Relatives, NonRelatives; | ||
| 1352 | |||
| 1353 | for (const DynamicReloc &Rel : Relocs) { | ||
| 1354 | Elf_Rela R; | ||
| 1355 | encodeDynamicReloc<ELFT>(&R, Rel); | ||
| 1356 | |||
| 1357 | if (R.getType(Config->IsMips64EL) == Target->RelativeRel) | ||
| 1358 | Relatives.push_back(R); | ||
| 1359 | else | ||
| 1360 | NonRelatives.push_back(R); | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | std::sort(Relatives.begin(), Relatives.end(), | ||
| 1364 | [](const Elf_Rel &A, const Elf_Rel &B) { | ||
| 1365 | return A.r_offset < B.r_offset; | ||
| 1366 | }); | ||
| 1367 | |||
| 1368 | // Try to find groups of relative relocations which are spaced one word | ||
| 1369 | // apart from one another. These generally correspond to vtable entries. The | ||
| 1370 | // format allows these groups to be encoded using a sort of run-length | ||
| 1371 | // encoding, but each group will cost 7 bytes in addition to the offset from | ||
| 1372 | // the previous group, so it is only profitable to do this for groups of | ||
| 1373 | // size 8 or larger. | ||
| 1374 | std::vector<Elf_Rela> UngroupedRelatives; | ||
| 1375 | std::vector<std::vector<Elf_Rela>> RelativeGroups; | ||
| 1376 | for (auto I = Relatives.begin(), E = Relatives.end(); I != E;) { | ||
| 1377 | std::vector<Elf_Rela> Group; | ||
| 1378 | do { | ||
| 1379 | Group.push_back(*I++); | ||
| 1380 | } while (I != E && (I - 1)->r_offset + Config->Wordsize == I->r_offset); | ||
| 1381 | |||
| 1382 | if (Group.size() < 8) | ||
| 1383 | UngroupedRelatives.insert(UngroupedRelatives.end(), Group.begin(), | ||
| 1384 | Group.end()); | ||
| 1385 | else | ||
| 1386 | RelativeGroups.emplace_back(std::move(Group)); | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | unsigned HasAddendIfRela = | ||
| 1390 | Config->IsRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0; | ||
| 1391 | |||
| 1392 | uint64_t Offset = 0; | ||
| 1393 | uint64_t Addend = 0; | ||
| 1394 | |||
| 1395 | // Emit the run-length encoding for the groups of adjacent relative | ||
| 1396 | // relocations. Each group is represented using two groups in the packed | ||
| 1397 | // format. The first is used to set the current offset to the start of the | ||
| 1398 | // group (and also encodes the first relocation), and the second encodes the | ||
| 1399 | // remaining relocations. | ||
| 1400 | for (std::vector<Elf_Rela> &G : RelativeGroups) { | ||
| 1401 | // The first relocation in the group. | ||
| 1402 | Add(1); | ||
| 1403 | Add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | | ||
| 1404 | RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela); | ||
| 1405 | Add(G[0].r_offset - Offset); | ||
| 1406 | Add(Target->RelativeRel); | ||
| 1407 | if (Config->IsRela) { | ||
| 1408 | Add(G[0].r_addend - Addend); | ||
| 1409 | Addend = G[0].r_addend; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | // The remaining relocations. | ||
| 1413 | Add(G.size() - 1); | ||
| 1414 | Add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | | ||
| 1415 | RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela); | ||
| 1416 | Add(Config->Wordsize); | ||
| 1417 | Add(Target->RelativeRel); | ||
| 1418 | if (Config->IsRela) { | ||
| 1419 | for (auto I = G.begin() + 1, E = G.end(); I != E; ++I) { | ||
| 1420 | Add(I->r_addend - Addend); | ||
| 1421 | Addend = I->r_addend; | ||
| 1422 | } | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | Offset = G.back().r_offset; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | // Now the ungrouped relatives. | ||
| 1429 | if (!UngroupedRelatives.empty()) { | ||
| 1430 | Add(UngroupedRelatives.size()); | ||
| 1431 | Add(RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela); | ||
| 1432 | Add(Target->RelativeRel); | ||
| 1433 | for (Elf_Rela &R : UngroupedRelatives) { | ||
| 1434 | Add(R.r_offset - Offset); | ||
| 1435 | Offset = R.r_offset; | ||
| 1436 | if (Config->IsRela) { | ||
| 1437 | Add(R.r_addend - Addend); | ||
| 1438 | Addend = R.r_addend; | ||
| 1439 | } | ||
| 1440 | } | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | // Finally the non-relative relocations. | ||
| 1444 | std::sort(NonRelatives.begin(), NonRelatives.end(), | ||
| 1445 | [](const Elf_Rela &A, const Elf_Rela &B) { | ||
| 1446 | return A.r_offset < B.r_offset; | ||
| 1447 | }); | ||
| 1448 | if (!NonRelatives.empty()) { | ||
| 1449 | Add(NonRelatives.size()); | ||
| 1450 | Add(HasAddendIfRela); | ||
| 1451 | for (Elf_Rela &R : NonRelatives) { | ||
| 1452 | Add(R.r_offset - Offset); | ||
| 1453 | Offset = R.r_offset; | ||
| 1454 | Add(R.r_info); | ||
| 1455 | if (Config->IsRela) { | ||
| 1456 | Add(R.r_addend - Addend); | ||
| 1457 | Addend = R.r_addend; | ||
| 1458 | } | ||
| 1459 | } | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | // Returns whether the section size changed. We need to keep recomputing both | ||
| 1463 | // section layout and the contents of this section until the size converges | ||
| 1464 | // because changing this section's size can affect section layout, which in | ||
| 1465 | // turn can affect the sizes of the LEB-encoded integers stored in this | ||
| 1466 | // section. | ||
| 1467 | return RelocData.size() != OldSize; | ||
| 1284 | } | 1468 | } |
| 1285 | 1469 | ||
| 1286 | SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec) | 1470 | SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec) |
| ... | @@ -1299,17 +1483,13 @@ static bool sortMipsSymbols(const SymbolTableEntry &L, | ... | @@ -1299,17 +1483,13 @@ static bool sortMipsSymbols(const SymbolTableEntry &L, |
| 1299 | const SymbolTableEntry &R) { | 1483 | const SymbolTableEntry &R) { |
| 1300 | // Sort entries related to non-local preemptible symbols by GOT indexes. | 1484 | // Sort entries related to non-local preemptible symbols by GOT indexes. |
| 1301 | // All other entries go to the first part of GOT in arbitrary order. | 1485 | // All other entries go to the first part of GOT in arbitrary order. |
| 1302 | bool LIsInLocalGot = !L.Symbol->IsInGlobalMipsGot; | 1486 | bool LIsInLocalGot = !L.Sym->IsInGlobalMipsGot; |
| 1303 | bool RIsInLocalGot = !R.Symbol->IsInGlobalMipsGot; | 1487 | bool RIsInLocalGot = !R.Sym->IsInGlobalMipsGot; |
| 1304 | if (LIsInLocalGot || RIsInLocalGot) | 1488 | if (LIsInLocalGot || RIsInLocalGot) |
| 1305 | return !RIsInLocalGot; | 1489 | return !RIsInLocalGot; |
| 1306 | return L.Symbol->GotIndex < R.Symbol->GotIndex; | 1490 | return L.Sym->GotIndex < R.Sym->GotIndex; |
| 1307 | } | 1491 | } |
| 1308 | 1492 | ||
| 1309 | // Finalize a symbol table. The ELF spec requires that all local | ||
| 1310 | // symbols precede global symbols, so we sort symbol entries in this | ||
| 1311 | // function. (For .dynsym, we don't do that because symbols for | ||
| 1312 | // dynamic linking are inherently all globals.) | ||
| 1313 | void SymbolTableBaseSection::finalizeContents() { | 1493 | void SymbolTableBaseSection::finalizeContents() { |
| 1314 | getParent()->Link = StrTabSec.getParent()->SectionIndex; | 1494 | getParent()->Link = StrTabSec.getParent()->SectionIndex; |
| 1315 | 1495 | ||
| ... | @@ -1328,26 +1508,27 @@ void SymbolTableBaseSection::finalizeContents() { | ... | @@ -1328,26 +1508,27 @@ void SymbolTableBaseSection::finalizeContents() { |
| 1328 | } | 1508 | } |
| 1329 | 1509 | ||
| 1330 | size_t I = 0; | 1510 | size_t I = 0; |
| 1331 | for (const SymbolTableEntry &S : Symbols) | 1511 | for (const SymbolTableEntry &S : Symbols) S.Sym->DynsymIndex = ++I; |
| 1332 | S.Symbol->DynsymIndex = ++I; | ||
| 1333 | return; | 1512 | return; |
| 1334 | } | 1513 | } |
| 1335 | } | 1514 | } |
| 1336 | 1515 | ||
| 1516 | // The ELF spec requires that all local symbols precede global symbols, so we | ||
| 1517 | // sort symbol entries in this function. (For .dynsym, we don't do that because | ||
| 1518 | // symbols for dynamic linking are inherently all globals.) | ||
| 1337 | void SymbolTableBaseSection::postThunkContents() { | 1519 | void SymbolTableBaseSection::postThunkContents() { |
| 1338 | if (this->Type == SHT_DYNSYM) | 1520 | if (this->Type == SHT_DYNSYM) |
| 1339 | return; | 1521 | return; |
| 1340 | // move all local symbols before global symbols. | 1522 | // move all local symbols before global symbols. |
| 1341 | auto It = std::stable_partition( | 1523 | auto It = std::stable_partition( |
| 1342 | Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) { | 1524 | Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) { |
| 1343 | return S.Symbol->isLocal() || | 1525 | return S.Sym->isLocal() || S.Sym->computeBinding() == STB_LOCAL; |
| 1344 | S.Symbol->symbol()->computeBinding() == STB_LOCAL; | ||
| 1345 | }); | 1526 | }); |
| 1346 | size_t NumLocals = It - Symbols.begin(); | 1527 | size_t NumLocals = It - Symbols.begin(); |
| 1347 | getParent()->Info = NumLocals + 1; | 1528 | getParent()->Info = NumLocals + 1; |
| 1348 | } | 1529 | } |
| 1349 | 1530 | ||
| 1350 | void SymbolTableBaseSection::addSymbol(SymbolBody *B) { | 1531 | void SymbolTableBaseSection::addSymbol(Symbol *B) { |
| 1351 | // Adding a local symbol to a .dynsym is a bug. | 1532 | // Adding a local symbol to a .dynsym is a bug. |
| 1352 | assert(this->Type != SHT_DYNSYM || !B->isLocal()); | 1533 | assert(this->Type != SHT_DYNSYM || !B->isLocal()); |
| 1353 | 1534 | ||
| ... | @@ -1355,19 +1536,25 @@ void SymbolTableBaseSection::addSymbol(SymbolBody *B) { | ... | @@ -1355,19 +1536,25 @@ void SymbolTableBaseSection::addSymbol(SymbolBody *B) { |
| 1355 | Symbols.push_back({B, StrTabSec.addString(B->getName(), HashIt)}); | 1536 | Symbols.push_back({B, StrTabSec.addString(B->getName(), HashIt)}); |
| 1356 | } | 1537 | } |
| 1357 | 1538 | ||
| 1358 | size_t SymbolTableBaseSection::getSymbolIndex(SymbolBody *Body) { | 1539 | size_t SymbolTableBaseSection::getSymbolIndex(Symbol *Sym) { |
| 1359 | auto I = llvm::find_if(Symbols, [&](const SymbolTableEntry &E) { | 1540 | // Initializes symbol lookup tables lazily. This is used only |
| 1360 | if (E.Symbol == Body) | 1541 | // for -r or -emit-relocs. |
| 1361 | return true; | 1542 | llvm::call_once(OnceFlag, [&] { |
| 1362 | // This is used for -r, so we have to handle multiple section | 1543 | SymbolIndexMap.reserve(Symbols.size()); |
| 1363 | // symbols being combined. | 1544 | size_t I = 0; |
| 1364 | if (Body->Type == STT_SECTION && E.Symbol->Type == STT_SECTION) | 1545 | for (const SymbolTableEntry &E : Symbols) { |
| 1365 | return Body->getOutputSection() == E.Symbol->getOutputSection(); | 1546 | if (E.Sym->Type == STT_SECTION) |
| 1366 | return false; | 1547 | SectionIndexMap[E.Sym->getOutputSection()] = ++I; |
| 1548 | else | ||
| 1549 | SymbolIndexMap[E.Sym] = ++I; | ||
| 1550 | } | ||
| 1367 | }); | 1551 | }); |
| 1368 | if (I == Symbols.end()) | 1552 | |
| 1369 | return 0; | 1553 | // Section symbols are mapped based on their output sections |
| 1370 | return I - Symbols.begin() + 1; | 1554 | // to maintain their semantics. |
| 1555 | if (Sym->Type == STT_SECTION) | ||
| 1556 | return SectionIndexMap.lookup(Sym->getOutputSection()); | ||
| 1557 | return SymbolIndexMap.lookup(Sym); | ||
| 1371 | } | 1558 | } |
| 1372 | 1559 | ||
| 1373 | template <class ELFT> | 1560 | template <class ELFT> |
| ... | @@ -1379,46 +1566,56 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec) | ... | @@ -1379,46 +1566,56 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec) |
| 1379 | // Write the internal symbol table contents to the output symbol table. | 1566 | // Write the internal symbol table contents to the output symbol table. |
| 1380 | template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { | 1567 | template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { |
| 1381 | // The first entry is a null entry as per the ELF spec. | 1568 | // The first entry is a null entry as per the ELF spec. |
| 1569 | memset(Buf, 0, sizeof(Elf_Sym)); | ||
| 1382 | Buf += sizeof(Elf_Sym); | 1570 | Buf += sizeof(Elf_Sym); |
| 1383 | 1571 | ||
| 1384 | auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); | 1572 | auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); |
| 1385 | 1573 | ||
| 1386 | for (SymbolTableEntry &Ent : Symbols) { | 1574 | for (SymbolTableEntry &Ent : Symbols) { |
| 1387 | SymbolBody *Body = Ent.Symbol; | 1575 | Symbol *Sym = Ent.Sym; |
| 1388 | 1576 | ||
| 1389 | // Set st_info and st_other. | 1577 | // Set st_info and st_other. |
| 1390 | if (Body->isLocal()) { | 1578 | ESym->st_other = 0; |
| 1391 | ESym->setBindingAndType(STB_LOCAL, Body->Type); | 1579 | if (Sym->isLocal()) { |
| 1580 | ESym->setBindingAndType(STB_LOCAL, Sym->Type); | ||
| 1392 | } else { | 1581 | } else { |
| 1393 | ESym->setBindingAndType(Body->symbol()->computeBinding(), Body->Type); | 1582 | ESym->setBindingAndType(Sym->computeBinding(), Sym->Type); |
| 1394 | ESym->setVisibility(Body->symbol()->Visibility); | 1583 | ESym->setVisibility(Sym->Visibility); |
| 1395 | } | 1584 | } |
| 1396 | 1585 | ||
| 1397 | ESym->st_name = Ent.StrTabOffset; | 1586 | ESym->st_name = Ent.StrTabOffset; |
| 1398 | 1587 | ||
| 1399 | // Set a section index. | 1588 | // Set a section index. |
| 1400 | if (const OutputSection *OutSec = Body->getOutputSection()) | 1589 | BssSection *CommonSec = nullptr; |
| 1590 | if (!Config->DefineCommon) | ||
| 1591 | if (auto *D = dyn_cast<Defined>(Sym)) | ||
| 1592 | CommonSec = dyn_cast_or_null<BssSection>(D->Section); | ||
| 1593 | if (CommonSec) | ||
| 1594 | ESym->st_shndx = SHN_COMMON; | ||
| 1595 | else if (const OutputSection *OutSec = Sym->getOutputSection()) | ||
| 1401 | ESym->st_shndx = OutSec->SectionIndex; | 1596 | ESym->st_shndx = OutSec->SectionIndex; |
| 1402 | else if (isa<DefinedRegular>(Body)) | 1597 | else if (isa<Defined>(Sym)) |
| 1403 | ESym->st_shndx = SHN_ABS; | 1598 | ESym->st_shndx = SHN_ABS; |
| 1404 | else if (isa<DefinedCommon>(Body)) | 1599 | else |
| 1405 | ESym->st_shndx = SHN_COMMON; | 1600 | ESym->st_shndx = SHN_UNDEF; |
| 1406 | 1601 | ||
| 1407 | // Copy symbol size if it is a defined symbol. st_size is not significant | 1602 | // Copy symbol size if it is a defined symbol. st_size is not significant |
| 1408 | // for undefined symbols, so whether copying it or not is up to us if that's | 1603 | // for undefined symbols, so whether copying it or not is up to us if that's |
| 1409 | // the case. We'll leave it as zero because by not setting a value, we can | 1604 | // the case. We'll leave it as zero because by not setting a value, we can |
| 1410 | // get the exact same outputs for two sets of input files that differ only | 1605 | // get the exact same outputs for two sets of input files that differ only |
| 1411 | // in undefined symbol size in DSOs. | 1606 | // in undefined symbol size in DSOs. |
| 1412 | if (ESym->st_shndx != SHN_UNDEF) | 1607 | if (ESym->st_shndx == SHN_UNDEF) |
| 1413 | ESym->st_size = Body->getSize<ELFT>(); | 1608 | ESym->st_size = 0; |
| 1609 | else | ||
| 1610 | ESym->st_size = Sym->getSize(); | ||
| 1414 | 1611 | ||
| 1415 | // st_value is usually an address of a symbol, but that has a | 1612 | // st_value is usually an address of a symbol, but that has a |
| 1416 | // special meaining for uninstantiated common symbols (this can | 1613 | // special meaining for uninstantiated common symbols (this can |
| 1417 | // occur if -r is given). | 1614 | // occur if -r is given). |
| 1418 | if (!Config->DefineCommon && isa<DefinedCommon>(Body)) | 1615 | if (CommonSec) |
| 1419 | ESym->st_value = cast<DefinedCommon>(Body)->Alignment; | 1616 | ESym->st_value = CommonSec->Alignment; |
| 1420 | else | 1617 | else |
| 1421 | ESym->st_value = Body->getVA(); | 1618 | ESym->st_value = Sym->getVA(); |
| 1422 | 1619 | ||
| 1423 | ++ESym; | 1620 | ++ESym; |
| 1424 | } | 1621 | } |
| ... | @@ -1431,13 +1628,22 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { | ... | @@ -1431,13 +1628,22 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { |
| 1431 | auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); | 1628 | auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); |
| 1432 | 1629 | ||
| 1433 | for (SymbolTableEntry &Ent : Symbols) { | 1630 | for (SymbolTableEntry &Ent : Symbols) { |
| 1434 | SymbolBody *Body = Ent.Symbol; | 1631 | Symbol *Sym = Ent.Sym; |
| 1435 | if (Body->isInPlt() && Body->NeedsPltAddr) | 1632 | if (Sym->isInPlt() && Sym->NeedsPltAddr) |
| 1436 | ESym->st_other |= STO_MIPS_PLT; | 1633 | ESym->st_other |= STO_MIPS_PLT; |
| 1437 | 1634 | if (isMicroMips()) { | |
| 1635 | // Set STO_MIPS_MICROMIPS flag and less-significant bit for | ||
| 1636 | // defined microMIPS symbols and shared symbols with PLT record. | ||
| 1637 | if ((Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) || | ||
| 1638 | (Sym->isShared() && Sym->NeedsPltAddr)) { | ||
| 1639 | if (StrTabSec.isDynamic()) | ||
| 1640 | ESym->st_value |= 1; | ||
| 1641 | ESym->st_other |= STO_MIPS_MICROMIPS; | ||
| 1642 | } | ||
| 1643 | } | ||
| 1438 | if (Config->Relocatable) | 1644 | if (Config->Relocatable) |
| 1439 | if (auto *D = dyn_cast<DefinedRegular>(Body)) | 1645 | if (auto *D = dyn_cast<Defined>(Sym)) |
| 1440 | if (D->isMipsPIC<ELFT>()) | 1646 | if (isMipsPIC<ELFT>(D)) |
| 1441 | ESym->st_other |= STO_MIPS_PIC; | 1647 | ESym->st_other |= STO_MIPS_PIC; |
| 1442 | ++ESym; | 1648 | ++ESym; |
| 1443 | } | 1649 | } |
| ... | @@ -1496,12 +1702,16 @@ void GnuHashTableSection::finalizeContents() { | ... | @@ -1496,12 +1702,16 @@ void GnuHashTableSection::finalizeContents() { |
| 1496 | } | 1702 | } |
| 1497 | 1703 | ||
| 1498 | void GnuHashTableSection::writeTo(uint8_t *Buf) { | 1704 | void GnuHashTableSection::writeTo(uint8_t *Buf) { |
| 1705 | // The output buffer is not guaranteed to be zero-cleared because we pre- | ||
| 1706 | // fill executable sections with trap instructions. This is a precaution | ||
| 1707 | // for that case, which happens only when -no-rosegment is given. | ||
| 1708 | memset(Buf, 0, Size); | ||
| 1709 | |||
| 1499 | // Write a header. | 1710 | // Write a header. |
| 1500 | write32(Buf, NBuckets, Config->Endianness); | 1711 | write32(Buf, NBuckets); |
| 1501 | write32(Buf + 4, InX::DynSymTab->getNumSymbols() - Symbols.size(), | 1712 | write32(Buf + 4, InX::DynSymTab->getNumSymbols() - Symbols.size()); |
| 1502 | Config->Endianness); | 1713 | write32(Buf + 8, MaskWords); |
| 1503 | write32(Buf + 8, MaskWords, Config->Endianness); | 1714 | write32(Buf + 12, getShift2()); |
| 1504 | write32(Buf + 12, getShift2(), Config->Endianness); | ||
| 1505 | Buf += 16; | 1715 | Buf += 16; |
| 1506 | 1716 | ||
| 1507 | // Write a bloom filter and a hash table. | 1717 | // Write a bloom filter and a hash table. |
| ... | @@ -1529,29 +1739,24 @@ void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) { | ... | @@ -1529,29 +1739,24 @@ void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) { |
| 1529 | } | 1739 | } |
| 1530 | 1740 | ||
| 1531 | void GnuHashTableSection::writeHashTable(uint8_t *Buf) { | 1741 | void GnuHashTableSection::writeHashTable(uint8_t *Buf) { |
| 1532 | // Group symbols by hash value. | ||
| 1533 | std::vector<std::vector<Entry>> Syms(NBuckets); | ||
| 1534 | for (const Entry &Ent : Symbols) | ||
| 1535 | Syms[Ent.Hash % NBuckets].push_back(Ent); | ||
| 1536 | |||
| 1537 | // Write hash buckets. Hash buckets contain indices in the following | ||
| 1538 | // hash value table. | ||
| 1539 | uint32_t *Buckets = reinterpret_cast<uint32_t *>(Buf); | 1742 | uint32_t *Buckets = reinterpret_cast<uint32_t *>(Buf); |
| 1540 | for (size_t I = 0; I < NBuckets; ++I) | 1743 | uint32_t OldBucket = -1; |
| 1541 | if (!Syms[I].empty()) | ||
| 1542 | write32(Buckets + I, Syms[I][0].Body->DynsymIndex, Config->Endianness); | ||
| 1543 | |||
| 1544 | // Write a hash value table. It represents a sequence of chains that | ||
| 1545 | // share the same hash modulo value. The last element of each chain | ||
| 1546 | // is terminated by LSB 1. | ||
| 1547 | uint32_t *Values = Buckets + NBuckets; | 1744 | uint32_t *Values = Buckets + NBuckets; |
| 1548 | size_t I = 0; | 1745 | for (auto I = Symbols.begin(), E = Symbols.end(); I != E; ++I) { |
| 1549 | for (std::vector<Entry> &Vec : Syms) { | 1746 | // Write a hash value. It represents a sequence of chains that share the |
| 1550 | if (Vec.empty()) | 1747 | // same hash modulo value. The last element of each chain is terminated by |
| 1748 | // LSB 1. | ||
| 1749 | uint32_t Hash = I->Hash; | ||
| 1750 | bool IsLastInChain = (I + 1) == E || I->BucketIdx != (I + 1)->BucketIdx; | ||
| 1751 | Hash = IsLastInChain ? Hash | 1 : Hash & ~1; | ||
| 1752 | write32(Values++, Hash); | ||
| 1753 | |||
| 1754 | if (I->BucketIdx == OldBucket) | ||
| 1551 | continue; | 1755 | continue; |
| 1552 | for (const Entry &Ent : makeArrayRef(Vec).drop_back()) | 1756 | // Write a hash bucket. Hash buckets contain indices in the following hash |
| 1553 | write32(Values + I++, Ent.Hash & ~1, Config->Endianness); | 1757 | // value table. |
| 1554 | write32(Values + I++, Vec.back().Hash | 1, Config->Endianness); | 1758 | write32(Buckets + I->BucketIdx, I->Sym->DynsymIndex); |
| 1759 | OldBucket = I->BucketIdx; | ||
| 1555 | } | 1760 | } |
| 1556 | } | 1761 | } |
| 1557 | 1762 | ||
| ... | @@ -1562,22 +1767,6 @@ static uint32_t hashGnu(StringRef Name) { | ... | @@ -1562,22 +1767,6 @@ static uint32_t hashGnu(StringRef Name) { |
| 1562 | return H; | 1767 | return H; |
| 1563 | } | 1768 | } |
| 1564 | 1769 | ||
| 1565 | // Returns a number of hash buckets to accomodate given number of elements. | ||
| 1566 | // We want to choose a moderate number that is not too small (which | ||
| 1567 | // causes too many hash collisions) and not too large (which wastes | ||
| 1568 | // disk space.) | ||
| 1569 | // | ||
| 1570 | // We return a prime number because it (is believed to) achieve good | ||
| 1571 | // hash distribution. | ||
| 1572 | static size_t getBucketSize(size_t NumSymbols) { | ||
| 1573 | // List of largest prime numbers that are not greater than 2^n + 1. | ||
| 1574 | for (size_t N : {131071, 65521, 32749, 16381, 8191, 4093, 2039, 1021, 509, | ||
| 1575 | 251, 127, 61, 31, 13, 7, 3, 1}) | ||
| 1576 | if (N <= NumSymbols) | ||
| 1577 | return N; | ||
| 1578 | return 0; | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | // Add symbols to this symbol hash table. Note that this function | 1770 | // Add symbols to this symbol hash table. Note that this function |
| 1582 | // destructively sort a given vector -- which is needed because | 1771 | // destructively sort a given vector -- which is needed because |
| 1583 | // GNU-style hash table places some sorting requirements. | 1772 | // GNU-style hash table places some sorting requirements. |
| ... | @@ -1586,66 +1775,73 @@ void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &V) { | ... | @@ -1586,66 +1775,73 @@ void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &V) { |
| 1586 | // its type correctly. | 1775 | // its type correctly. |
| 1587 | std::vector<SymbolTableEntry>::iterator Mid = | 1776 | std::vector<SymbolTableEntry>::iterator Mid = |
| 1588 | std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) { | 1777 | std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) { |
| 1589 | return S.Symbol->isUndefined(); | 1778 | // Shared symbols that this executable preempts are special. The dynamic |
| 1779 | // linker has to look them up, so they have to be in the hash table. | ||
| 1780 | if (auto *SS = dyn_cast<SharedSymbol>(S.Sym)) | ||
| 1781 | return SS->CopyRelSec == nullptr && !SS->NeedsPltAddr; | ||
| 1782 | return !S.Sym->isDefined(); | ||
| 1590 | }); | 1783 | }); |
| 1591 | if (Mid == V.end()) | 1784 | if (Mid == V.end()) |
| 1592 | return; | 1785 | return; |
| 1593 | 1786 | ||
| 1787 | // We chose load factor 4 for the on-disk hash table. For each hash | ||
| 1788 | // collision, the dynamic linker will compare a uint32_t hash value. | ||
| 1789 | // Since the integer comparison is quite fast, we believe we can make | ||
| 1790 | // the load factor even larger. 4 is just a conservative choice. | ||
| 1791 | NBuckets = std::max<size_t>((V.end() - Mid) / 4, 1); | ||
| 1792 | |||
| 1594 | for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) { | 1793 | for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) { |
| 1595 | SymbolBody *B = Ent.Symbol; | 1794 | Symbol *B = Ent.Sym; |
| 1596 | Symbols.push_back({B, Ent.StrTabOffset, hashGnu(B->getName())}); | 1795 | uint32_t Hash = hashGnu(B->getName()); |
| 1796 | uint32_t BucketIdx = Hash % NBuckets; | ||
| 1797 | Symbols.push_back({B, Ent.StrTabOffset, Hash, BucketIdx}); | ||
| 1597 | } | 1798 | } |
| 1598 | 1799 | ||
| 1599 | NBuckets = getBucketSize(Symbols.size()); | 1800 | std::stable_sort( |
| 1600 | std::stable_sort(Symbols.begin(), Symbols.end(), | 1801 | Symbols.begin(), Symbols.end(), |
| 1601 | [&](const Entry &L, const Entry &R) { | 1802 | [](const Entry &L, const Entry &R) { return L.BucketIdx < R.BucketIdx; }); |
| 1602 | return L.Hash % NBuckets < R.Hash % NBuckets; | ||
| 1603 | }); | ||
| 1604 | 1803 | ||
| 1605 | V.erase(Mid, V.end()); | 1804 | V.erase(Mid, V.end()); |
| 1606 | for (const Entry &Ent : Symbols) | 1805 | for (const Entry &Ent : Symbols) |
| 1607 | V.push_back({Ent.Body, Ent.StrTabOffset}); | 1806 | V.push_back({Ent.Sym, Ent.StrTabOffset}); |
| 1608 | } | 1807 | } |
| 1609 | 1808 | ||
| 1610 | template <class ELFT> | 1809 | HashTableSection::HashTableSection() |
| 1611 | HashTableSection<ELFT>::HashTableSection() | ||
| 1612 | : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") { | 1810 | : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") { |
| 1613 | this->Entsize = 4; | 1811 | this->Entsize = 4; |
| 1614 | } | 1812 | } |
| 1615 | 1813 | ||
| 1616 | template <class ELFT> void HashTableSection<ELFT>::finalizeContents() { | 1814 | void HashTableSection::finalizeContents() { |
| 1617 | getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; | 1815 | getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; |
| 1618 | 1816 | ||
| 1619 | unsigned NumEntries = 2; // nbucket and nchain. | 1817 | unsigned NumEntries = 2; // nbucket and nchain. |
| 1620 | NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries. | 1818 | NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries. |
| 1621 | 1819 | ||
| 1622 | // Create as many buckets as there are symbols. | 1820 | // Create as many buckets as there are symbols. |
| 1623 | // FIXME: This is simplistic. We can try to optimize it, but implementing | ||
| 1624 | // support for SHT_GNU_HASH is probably even more profitable. | ||
| 1625 | NumEntries += InX::DynSymTab->getNumSymbols(); | 1821 | NumEntries += InX::DynSymTab->getNumSymbols(); |
| 1626 | this->Size = NumEntries * 4; | 1822 | this->Size = NumEntries * 4; |
| 1627 | } | 1823 | } |
| 1628 | 1824 | ||
| 1629 | template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) { | 1825 | void HashTableSection::writeTo(uint8_t *Buf) { |
| 1630 | // A 32-bit integer type in the target endianness. | 1826 | // See comment in GnuHashTableSection::writeTo. |
| 1631 | typedef typename ELFT::Word Elf_Word; | 1827 | memset(Buf, 0, Size); |
| 1632 | 1828 | ||
| 1633 | unsigned NumSymbols = InX::DynSymTab->getNumSymbols(); | 1829 | unsigned NumSymbols = InX::DynSymTab->getNumSymbols(); |
| 1634 | 1830 | ||
| 1635 | auto *P = reinterpret_cast<Elf_Word *>(Buf); | 1831 | uint32_t *P = reinterpret_cast<uint32_t *>(Buf); |
| 1636 | *P++ = NumSymbols; // nbucket | 1832 | write32(P++, NumSymbols); // nbucket |
| 1637 | *P++ = NumSymbols; // nchain | 1833 | write32(P++, NumSymbols); // nchain |
| 1638 | 1834 | ||
| 1639 | Elf_Word *Buckets = P; | 1835 | uint32_t *Buckets = P; |
| 1640 | Elf_Word *Chains = P + NumSymbols; | 1836 | uint32_t *Chains = P + NumSymbols; |
| 1641 | 1837 | ||
| 1642 | for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { | 1838 | for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { |
| 1643 | SymbolBody *Body = S.Symbol; | 1839 | Symbol *Sym = S.Sym; |
| 1644 | StringRef Name = Body->getName(); | 1840 | StringRef Name = Sym->getName(); |
| 1645 | unsigned I = Body->DynsymIndex; | 1841 | unsigned I = Sym->DynsymIndex; |
| 1646 | uint32_t Hash = hashSysV(Name) % NumSymbols; | 1842 | uint32_t Hash = hashSysV(Name) % NumSymbols; |
| 1647 | Chains[I] = Buckets[Hash]; | 1843 | Chains[I] = Buckets[Hash]; |
| 1648 | Buckets[Hash] = I; | 1844 | write32(Buckets + Hash, I); |
| 1649 | } | 1845 | } |
| 1650 | } | 1846 | } |
| 1651 | 1847 | ||
| ... | @@ -1668,7 +1864,7 @@ void PltSection::writeTo(uint8_t *Buf) { | ... | @@ -1668,7 +1864,7 @@ void PltSection::writeTo(uint8_t *Buf) { |
| 1668 | unsigned PltOff = getPltRelocOff(); | 1864 | unsigned PltOff = getPltRelocOff(); |
| 1669 | 1865 | ||
| 1670 | for (auto &I : Entries) { | 1866 | for (auto &I : Entries) { |
| 1671 | const SymbolBody *B = I.first; | 1867 | const Symbol *B = I.first; |
| 1672 | unsigned RelOff = I.second + PltOff; | 1868 | unsigned RelOff = I.second + PltOff; |
| 1673 | uint64_t Got = B->getGotPltVA(); | 1869 | uint64_t Got = B->getGotPltVA(); |
| 1674 | uint64_t Plt = this->getVA() + Off; | 1870 | uint64_t Plt = this->getVA() + Off; |
| ... | @@ -1677,14 +1873,15 @@ void PltSection::writeTo(uint8_t *Buf) { | ... | @@ -1677,14 +1873,15 @@ void PltSection::writeTo(uint8_t *Buf) { |
| 1677 | } | 1873 | } |
| 1678 | } | 1874 | } |
| 1679 | 1875 | ||
| 1680 | template <class ELFT> void PltSection::addEntry(SymbolBody &Sym) { | 1876 | template <class ELFT> void PltSection::addEntry(Symbol &Sym) { |
| 1681 | Sym.PltIndex = Entries.size(); | 1877 | Sym.PltIndex = Entries.size(); |
| 1682 | RelocationSection<ELFT> *PltRelocSection = In<ELFT>::RelaPlt; | 1878 | RelocationBaseSection *PltRelocSection = InX::RelaPlt; |
| 1683 | if (HeaderSize == 0) { | 1879 | if (HeaderSize == 0) { |
| 1684 | PltRelocSection = In<ELFT>::RelaIplt; | 1880 | PltRelocSection = InX::RelaIplt; |
| 1685 | Sym.IsInIplt = true; | 1881 | Sym.IsInIplt = true; |
| 1686 | } | 1882 | } |
| 1687 | unsigned RelOff = PltRelocSection->getRelocOffset(); | 1883 | unsigned RelOff = |
| 1884 | static_cast<RelocationSection<ELFT> *>(PltRelocSection)->getRelocOffset(); | ||
| 1688 | Entries.push_back(std::make_pair(&Sym, RelOff)); | 1885 | Entries.push_back(std::make_pair(&Sym, RelOff)); |
| 1689 | } | 1886 | } |
| 1690 | 1887 | ||
| ... | @@ -1697,10 +1894,10 @@ size_t PltSection::getSize() const { | ... | @@ -1697,10 +1894,10 @@ size_t PltSection::getSize() const { |
| 1697 | void PltSection::addSymbols() { | 1894 | void PltSection::addSymbols() { |
| 1698 | // The PLT may have symbols defined for the Header, the IPLT has no header | 1895 | // The PLT may have symbols defined for the Header, the IPLT has no header |
| 1699 | if (HeaderSize != 0) | 1896 | if (HeaderSize != 0) |
| 1700 | Target->addPltHeaderSymbols(this); | 1897 | Target->addPltHeaderSymbols(*this); |
| 1701 | size_t Off = HeaderSize; | 1898 | size_t Off = HeaderSize; |
| 1702 | for (size_t I = 0; I < Entries.size(); ++I) { | 1899 | for (size_t I = 0; I < Entries.size(); ++I) { |
| 1703 | Target->addPltSymbols(this, Off); | 1900 | Target->addPltSymbols(*this, Off); |
| 1704 | Off += Target->PltEntrySize; | 1901 | Off += Target->PltEntrySize; |
| 1705 | } | 1902 | } |
| 1706 | } | 1903 | } |
| ... | @@ -1709,35 +1906,29 @@ unsigned PltSection::getPltRelocOff() const { | ... | @@ -1709,35 +1906,29 @@ unsigned PltSection::getPltRelocOff() const { |
| 1709 | return (HeaderSize == 0) ? InX::Plt->getSize() : 0; | 1906 | return (HeaderSize == 0) ? InX::Plt->getSize() : 0; |
| 1710 | } | 1907 | } |
| 1711 | 1908 | ||
| 1712 | GdbIndexSection::GdbIndexSection(std::vector<GdbIndexChunk> &&Chunks) | 1909 | // The string hash function for .gdb_index. |
| 1713 | : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index"), | 1910 | static uint32_t computeGdbHash(StringRef S) { |
| 1714 | StringPool(llvm::StringTableBuilder::ELF), Chunks(std::move(Chunks)) {} | 1911 | uint32_t H = 0; |
| 1715 | 1912 | for (uint8_t C : S) | |
| 1716 | // Iterative hash function for symbol's name is described in .gdb_index format | 1913 | H = H * 67 + tolower(C) - 113; |
| 1717 | // specification. Note that we use one for version 5 to 7 here, it is different | 1914 | return H; |
| 1718 | // for version 4. | ||
| 1719 | static uint32_t hash(StringRef Str) { | ||
| 1720 | uint32_t R = 0; | ||
| 1721 | for (uint8_t C : Str) | ||
| 1722 | R = R * 67 + tolower(C) - 113; | ||
| 1723 | return R; | ||
| 1724 | } | 1915 | } |
| 1725 | 1916 | ||
| 1726 | static std::vector<CompilationUnitEntry> readCuList(DWARFContext &Dwarf) { | 1917 | static std::vector<GdbIndexChunk::CuEntry> readCuList(DWARFContext &Dwarf) { |
| 1727 | std::vector<CompilationUnitEntry> Ret; | 1918 | std::vector<GdbIndexChunk::CuEntry> Ret; |
| 1728 | for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units()) | 1919 | for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units()) |
| 1729 | Ret.push_back({CU->getOffset(), CU->getLength() + 4}); | 1920 | Ret.push_back({Cu->getOffset(), Cu->getLength() + 4}); |
| 1730 | return Ret; | 1921 | return Ret; |
| 1731 | } | 1922 | } |
| 1732 | 1923 | ||
| 1733 | static std::vector<AddressEntry> readAddressArea(DWARFContext &Dwarf, | 1924 | static std::vector<GdbIndexChunk::AddressEntry> |
| 1734 | InputSection *Sec) { | 1925 | readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) { |
| 1735 | std::vector<AddressEntry> Ret; | 1926 | std::vector<GdbIndexChunk::AddressEntry> Ret; |
| 1736 | 1927 | ||
| 1737 | uint32_t CurrentCu = 0; | 1928 | uint32_t CuIdx = 0; |
| 1738 | for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units()) { | 1929 | for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units()) { |
| 1739 | DWARFAddressRangesVector Ranges; | 1930 | DWARFAddressRangesVector Ranges; |
| 1740 | CU->collectAddressRanges(Ranges); | 1931 | Cu->collectAddressRanges(Ranges); |
| 1741 | 1932 | ||
| 1742 | ArrayRef<InputSectionBase *> Sections = Sec->File->getSections(); | 1933 | ArrayRef<InputSectionBase *> Sections = Sec->File->getSections(); |
| 1743 | for (DWARFAddressRange &R : Ranges) { | 1934 | for (DWARFAddressRange &R : Ranges) { |
| ... | @@ -1747,24 +1938,29 @@ static std::vector<AddressEntry> readAddressArea(DWARFContext &Dwarf, | ... | @@ -1747,24 +1938,29 @@ static std::vector<AddressEntry> readAddressArea(DWARFContext &Dwarf, |
| 1747 | // Range list with zero size has no effect. | 1938 | // Range list with zero size has no effect. |
| 1748 | if (R.LowPC == R.HighPC) | 1939 | if (R.LowPC == R.HighPC) |
| 1749 | continue; | 1940 | continue; |
| 1750 | Ret.push_back({cast<InputSection>(S), R.LowPC, R.HighPC, CurrentCu}); | 1941 | auto *IS = cast<InputSection>(S); |
| 1942 | uint64_t Offset = IS->getOffsetInFile(); | ||
| 1943 | Ret.push_back({IS, R.LowPC - Offset, R.HighPC - Offset, CuIdx}); | ||
| 1751 | } | 1944 | } |
| 1752 | ++CurrentCu; | 1945 | ++CuIdx; |
| 1753 | } | 1946 | } |
| 1754 | return Ret; | 1947 | return Ret; |
| 1755 | } | 1948 | } |
| 1756 | 1949 | ||
| 1757 | static std::vector<NameTypeEntry> readPubNamesAndTypes(DWARFContext &Dwarf, | 1950 | static std::vector<GdbIndexChunk::NameTypeEntry> |
| 1758 | bool IsLE) { | 1951 | readPubNamesAndTypes(DWARFContext &Dwarf) { |
| 1759 | StringRef Data[] = {Dwarf.getGnuPubNamesSection(), | 1952 | StringRef Sec1 = Dwarf.getDWARFObj().getGnuPubNamesSection(); |
| 1760 | Dwarf.getGnuPubTypesSection()}; | 1953 | StringRef Sec2 = Dwarf.getDWARFObj().getGnuPubTypesSection(); |
| 1761 | 1954 | ||
| 1762 | std::vector<NameTypeEntry> Ret; | 1955 | std::vector<GdbIndexChunk::NameTypeEntry> Ret; |
| 1763 | for (StringRef D : Data) { | 1956 | for (StringRef Sec : {Sec1, Sec2}) { |
| 1764 | DWARFDebugPubTable PubTable(D, IsLE, true); | 1957 | DWARFDebugPubTable Table(Sec, Config->IsLE, true); |
| 1765 | for (const DWARFDebugPubTable::Set &Set : PubTable.getData()) | 1958 | for (const DWARFDebugPubTable::Set &Set : Table.getData()) { |
| 1766 | for (const DWARFDebugPubTable::Entry &Ent : Set.Entries) | 1959 | for (const DWARFDebugPubTable::Entry &Ent : Set.Entries) { |
| 1767 | Ret.push_back({Ent.Name, Ent.Descriptor.toBits()}); | 1960 | CachedHashStringRef S(Ent.Name, computeGdbHash(Ent.Name)); |
| 1961 | Ret.push_back({S, Ent.Descriptor.toBits()}); | ||
| 1962 | } | ||
| 1963 | } | ||
| 1768 | } | 1964 | } |
| 1769 | return Ret; | 1965 | return Ret; |
| 1770 | } | 1966 | } |
| ... | @@ -1778,119 +1974,140 @@ static std::vector<InputSection *> getDebugInfoSections() { | ... | @@ -1778,119 +1974,140 @@ static std::vector<InputSection *> getDebugInfoSections() { |
| 1778 | return Ret; | 1974 | return Ret; |
| 1779 | } | 1975 | } |
| 1780 | 1976 | ||
| 1781 | void GdbIndexSection::buildIndex() { | 1977 | void GdbIndexSection::fixCuIndex() { |
| 1782 | if (Chunks.empty()) | 1978 | uint32_t Idx = 0; |
| 1783 | return; | 1979 | for (GdbIndexChunk &Chunk : Chunks) { |
| 1980 | for (GdbIndexChunk::AddressEntry &Ent : Chunk.AddressAreas) | ||
| 1981 | Ent.CuIndex += Idx; | ||
| 1982 | Idx += Chunk.CompilationUnits.size(); | ||
| 1983 | } | ||
| 1984 | } | ||
| 1784 | 1985 | ||
| 1785 | uint32_t CuId = 0; | 1986 | std::vector<std::vector<uint32_t>> GdbIndexSection::createCuVectors() { |
| 1786 | for (GdbIndexChunk &D : Chunks) { | 1987 | std::vector<std::vector<uint32_t>> Ret; |
| 1787 | for (AddressEntry &E : D.AddressArea) | 1988 | uint32_t Idx = 0; |
| 1788 | E.CuIndex += CuId; | 1989 | uint32_t Off = 0; |
| 1789 | 1990 | ||
| 1790 | // Populate constant pool area. | 1991 | for (GdbIndexChunk &Chunk : Chunks) { |
| 1791 | for (NameTypeEntry &NameType : D.NamesAndTypes) { | 1992 | for (GdbIndexChunk::NameTypeEntry &Ent : Chunk.NamesAndTypes) { |
| 1792 | uint32_t Hash = hash(NameType.Name); | 1993 | GdbSymbol *&Sym = Symbols[Ent.Name]; |
| 1793 | size_t Offset = StringPool.add(NameType.Name); | 1994 | if (!Sym) { |
| 1794 | 1995 | Sym = make<GdbSymbol>(GdbSymbol{Ent.Name.hash(), Off, Ret.size()}); | |
| 1795 | bool IsNew; | 1996 | Off += Ent.Name.size() + 1; |
| 1796 | GdbSymbol *Sym; | 1997 | Ret.push_back({}); |
| 1797 | std::tie(IsNew, Sym) = SymbolTable.add(Hash, Offset); | ||
| 1798 | if (IsNew) { | ||
| 1799 | Sym->CuVectorIndex = CuVectors.size(); | ||
| 1800 | CuVectors.resize(CuVectors.size() + 1); | ||
| 1801 | } | 1998 | } |
| 1802 | 1999 | ||
| 1803 | CuVectors[Sym->CuVectorIndex].insert(CuId | (NameType.Type << 24)); | 2000 | // gcc 5.4.1 produces a buggy .debug_gnu_pubnames that contains |
| 2001 | // duplicate entries, so we want to dedup them. | ||
| 2002 | std::vector<uint32_t> &Vec = Ret[Sym->CuVectorIndex]; | ||
| 2003 | uint32_t Val = (Ent.Type << 24) | Idx; | ||
| 2004 | if (Vec.empty() || Vec.back() != Val) | ||
| 2005 | Vec.push_back(Val); | ||
| 1804 | } | 2006 | } |
| 1805 | 2007 | Idx += Chunk.CompilationUnits.size(); | |
| 1806 | CuId += D.CompilationUnits.size(); | ||
| 1807 | } | 2008 | } |
| 1808 | } | ||
| 1809 | 2009 | ||
| 1810 | static GdbIndexChunk readDwarf(DWARFContextInMemory &Dwarf, InputSection *Sec) { | 2010 | StringPoolSize = Off; |
| 1811 | GdbIndexChunk Ret; | ||
| 1812 | Ret.DebugInfoSec = Sec; | ||
| 1813 | Ret.CompilationUnits = readCuList(Dwarf); | ||
| 1814 | Ret.AddressArea = readAddressArea(Dwarf, Sec); | ||
| 1815 | Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE); | ||
| 1816 | return Ret; | 2011 | return Ret; |
| 1817 | } | 2012 | } |
| 1818 | 2013 | ||
| 1819 | template <class ELFT> GdbIndexSection *elf::createGdbIndex() { | 2014 | template <class ELFT> GdbIndexSection *elf::createGdbIndex() { |
| 1820 | std::vector<GdbIndexChunk> Chunks; | 2015 | // Gather debug info to create a .gdb_index section. |
| 1821 | for (InputSection *Sec : getDebugInfoSections()) { | 2016 | std::vector<InputSection *> Sections = getDebugInfoSections(); |
| 1822 | InputFile *F = Sec->File; | 2017 | std::vector<GdbIndexChunk> Chunks(Sections.size()); |
| 1823 | std::error_code EC; | 2018 | |
| 1824 | ELFObjectFile<ELFT> Obj(F->MB, EC); | 2019 | parallelForEachN(0, Chunks.size(), [&](size_t I) { |
| 1825 | if (EC) | 2020 | ObjFile<ELFT> *File = Sections[I]->getFile<ELFT>(); |
| 1826 | fatal(EC.message()); | 2021 | DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(File)); |
| 1827 | DWARFContextInMemory Dwarf(Obj, nullptr, [&](Error E) { | 2022 | |
| 1828 | error(toString(F) + ": error parsing DWARF data:\n>>> " + | 2023 | Chunks[I].DebugInfoSec = Sections[I]; |
| 1829 | toString(std::move(E))); | 2024 | Chunks[I].CompilationUnits = readCuList(Dwarf); |
| 1830 | return ErrorPolicy::Continue; | 2025 | Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]); |
| 1831 | }); | 2026 | Chunks[I].NamesAndTypes = readPubNamesAndTypes(Dwarf); |
| 1832 | Chunks.push_back(readDwarf(Dwarf, Sec)); | 2027 | }); |
| 1833 | } | 2028 | |
| 2029 | // .debug_gnu_pub{names,types} are useless in executables. | ||
| 2030 | // They are present in input object files solely for creating | ||
| 2031 | // a .gdb_index. So we can remove it from the output. | ||
| 2032 | for (InputSectionBase *S : InputSections) | ||
| 2033 | if (S->Name == ".debug_gnu_pubnames" || S->Name == ".debug_gnu_pubtypes") | ||
| 2034 | S->Live = false; | ||
| 2035 | |||
| 2036 | // Create a .gdb_index and returns it. | ||
| 1834 | return make<GdbIndexSection>(std::move(Chunks)); | 2037 | return make<GdbIndexSection>(std::move(Chunks)); |
| 1835 | } | 2038 | } |
| 1836 | 2039 | ||
| 1837 | static size_t getCuSize(std::vector<GdbIndexChunk> &C) { | 2040 | static size_t getCuSize(ArrayRef<GdbIndexChunk> Arr) { |
| 1838 | size_t Ret = 0; | 2041 | size_t Ret = 0; |
| 1839 | for (GdbIndexChunk &D : C) | 2042 | for (const GdbIndexChunk &D : Arr) |
| 1840 | Ret += D.CompilationUnits.size(); | 2043 | Ret += D.CompilationUnits.size(); |
| 1841 | return Ret; | 2044 | return Ret; |
| 1842 | } | 2045 | } |
| 1843 | 2046 | ||
| 1844 | static size_t getAddressAreaSize(std::vector<GdbIndexChunk> &C) { | 2047 | static size_t getAddressAreaSize(ArrayRef<GdbIndexChunk> Arr) { |
| 1845 | size_t Ret = 0; | 2048 | size_t Ret = 0; |
| 1846 | for (GdbIndexChunk &D : C) | 2049 | for (const GdbIndexChunk &D : Arr) |
| 1847 | Ret += D.AddressArea.size(); | 2050 | Ret += D.AddressAreas.size(); |
| 1848 | return Ret; | 2051 | return Ret; |
| 1849 | } | 2052 | } |
| 1850 | 2053 | ||
| 1851 | void GdbIndexSection::finalizeContents() { | 2054 | std::vector<GdbSymbol *> GdbIndexSection::createGdbSymtab() { |
| 1852 | if (Finalized) | 2055 | uint32_t Size = NextPowerOf2(Symbols.size() * 4 / 3); |
| 1853 | return; | 2056 | if (Size < 1024) |
| 1854 | Finalized = true; | 2057 | Size = 1024; |
| 2058 | |||
| 2059 | uint32_t Mask = Size - 1; | ||
| 2060 | std::vector<GdbSymbol *> Ret(Size); | ||
| 1855 | 2061 | ||
| 1856 | buildIndex(); | 2062 | for (auto &KV : Symbols) { |
| 2063 | GdbSymbol *Sym = KV.second; | ||
| 2064 | uint32_t I = Sym->NameHash & Mask; | ||
| 2065 | uint32_t Step = ((Sym->NameHash * 17) & Mask) | 1; | ||
| 1857 | 2066 | ||
| 1858 | SymbolTable.finalizeContents(); | 2067 | while (Ret[I]) |
| 2068 | I = (I + Step) & Mask; | ||
| 2069 | Ret[I] = Sym; | ||
| 2070 | } | ||
| 2071 | return Ret; | ||
| 2072 | } | ||
| 1859 | 2073 | ||
| 1860 | // GdbIndex header consist from version fields | 2074 | GdbIndexSection::GdbIndexSection(std::vector<GdbIndexChunk> &&C) |
| 1861 | // and 5 more fields with different kinds of offsets. | 2075 | : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index"), Chunks(std::move(C)) { |
| 1862 | CuTypesOffset = CuListOffset + getCuSize(Chunks) * CompilationUnitSize; | 2076 | fixCuIndex(); |
| 1863 | SymTabOffset = CuTypesOffset + getAddressAreaSize(Chunks) * AddressEntrySize; | 2077 | CuVectors = createCuVectors(); |
| 2078 | GdbSymtab = createGdbSymtab(); | ||
| 1864 | 2079 | ||
| 1865 | ConstantPoolOffset = | 2080 | // Compute offsets early to know the section size. |
| 1866 | SymTabOffset + SymbolTable.getCapacity() * SymTabEntrySize; | 2081 | // Each chunk size needs to be in sync with what we write in writeTo. |
| 2082 | CuTypesOffset = CuListOffset + getCuSize(Chunks) * 16; | ||
| 2083 | SymtabOffset = CuTypesOffset + getAddressAreaSize(Chunks) * 20; | ||
| 2084 | ConstantPoolOffset = SymtabOffset + GdbSymtab.size() * 8; | ||
| 1867 | 2085 | ||
| 1868 | for (std::set<uint32_t> &CuVec : CuVectors) { | 2086 | size_t Off = 0; |
| 1869 | CuVectorsOffset.push_back(CuVectorsSize); | 2087 | for (ArrayRef<uint32_t> Vec : CuVectors) { |
| 1870 | CuVectorsSize += OffsetTypeSize * (CuVec.size() + 1); | 2088 | CuVectorOffsets.push_back(Off); |
| 2089 | Off += (Vec.size() + 1) * 4; | ||
| 1871 | } | 2090 | } |
| 1872 | StringPoolOffset = ConstantPoolOffset + CuVectorsSize; | 2091 | StringPoolOffset = ConstantPoolOffset + Off; |
| 1873 | |||
| 1874 | StringPool.finalizeInOrder(); | ||
| 1875 | } | 2092 | } |
| 1876 | 2093 | ||
| 1877 | size_t GdbIndexSection::getSize() const { | 2094 | size_t GdbIndexSection::getSize() const { |
| 1878 | const_cast<GdbIndexSection *>(this)->finalizeContents(); | 2095 | return StringPoolOffset + StringPoolSize; |
| 1879 | return StringPoolOffset + StringPool.getSize(); | ||
| 1880 | } | 2096 | } |
| 1881 | 2097 | ||
| 1882 | void GdbIndexSection::writeTo(uint8_t *Buf) { | 2098 | void GdbIndexSection::writeTo(uint8_t *Buf) { |
| 1883 | write32le(Buf, 7); // Write version. | 2099 | // Write the section header. |
| 1884 | write32le(Buf + 4, CuListOffset); // CU list offset. | 2100 | write32le(Buf, 7); |
| 1885 | write32le(Buf + 8, CuTypesOffset); // Types CU list offset. | 2101 | write32le(Buf + 4, CuListOffset); |
| 1886 | write32le(Buf + 12, CuTypesOffset); // Address area offset. | 2102 | write32le(Buf + 8, CuTypesOffset); |
| 1887 | write32le(Buf + 16, SymTabOffset); // Symbol table offset. | 2103 | write32le(Buf + 12, CuTypesOffset); |
| 1888 | write32le(Buf + 20, ConstantPoolOffset); // Constant pool offset. | 2104 | write32le(Buf + 16, SymtabOffset); |
| 2105 | write32le(Buf + 20, ConstantPoolOffset); | ||
| 1889 | Buf += 24; | 2106 | Buf += 24; |
| 1890 | 2107 | ||
| 1891 | // Write the CU list. | 2108 | // Write the CU list. |
| 1892 | for (GdbIndexChunk &D : Chunks) { | 2109 | for (GdbIndexChunk &D : Chunks) { |
| 1893 | for (CompilationUnitEntry &Cu : D.CompilationUnits) { | 2110 | for (GdbIndexChunk::CuEntry &Cu : D.CompilationUnits) { |
| 1894 | write64le(Buf, D.DebugInfoSec->OutSecOff + Cu.CuOffset); | 2111 | write64le(Buf, D.DebugInfoSec->OutSecOff + Cu.CuOffset); |
| 1895 | write64le(Buf + 8, Cu.CuLength); | 2112 | write64le(Buf + 8, Cu.CuLength); |
| 1896 | Buf += 16; | 2113 | Buf += 16; |
| ... | @@ -1899,7 +2116,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { | ... | @@ -1899,7 +2116,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { |
| 1899 | 2116 | ||
| 1900 | // Write the address area. | 2117 | // Write the address area. |
| 1901 | for (GdbIndexChunk &D : Chunks) { | 2118 | for (GdbIndexChunk &D : Chunks) { |
| 1902 | for (AddressEntry &E : D.AddressArea) { | 2119 | for (GdbIndexChunk::AddressEntry &E : D.AddressAreas) { |
| 1903 | uint64_t BaseAddr = | 2120 | uint64_t BaseAddr = |
| 1904 | E.Section->getParent()->Addr + E.Section->getOffset(0); | 2121 | E.Section->getParent()->Addr + E.Section->getOffset(0); |
| 1905 | write64le(Buf, BaseAddr + E.LowAddress); | 2122 | write64le(Buf, BaseAddr + E.LowAddress); |
| ... | @@ -1910,43 +2127,47 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { | ... | @@ -1910,43 +2127,47 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { |
| 1910 | } | 2127 | } |
| 1911 | 2128 | ||
| 1912 | // Write the symbol table. | 2129 | // Write the symbol table. |
| 1913 | for (size_t I = 0; I < SymbolTable.getCapacity(); ++I) { | 2130 | for (GdbSymbol *Sym : GdbSymtab) { |
| 1914 | GdbSymbol *Sym = SymbolTable.getSymbol(I); | ||
| 1915 | if (Sym) { | 2131 | if (Sym) { |
| 1916 | size_t NameOffset = | 2132 | write32le(Buf, Sym->NameOffset + StringPoolOffset - ConstantPoolOffset); |
| 1917 | Sym->NameOffset + StringPoolOffset - ConstantPoolOffset; | 2133 | write32le(Buf + 4, CuVectorOffsets[Sym->CuVectorIndex]); |
| 1918 | size_t CuVectorOffset = CuVectorsOffset[Sym->CuVectorIndex]; | ||
| 1919 | write32le(Buf, NameOffset); | ||
| 1920 | write32le(Buf + 4, CuVectorOffset); | ||
| 1921 | } | 2134 | } |
| 1922 | Buf += 8; | 2135 | Buf += 8; |
| 1923 | } | 2136 | } |
| 1924 | 2137 | ||
| 1925 | // Write the CU vectors into the constant pool. | 2138 | // Write the CU vectors. |
| 1926 | for (std::set<uint32_t> &CuVec : CuVectors) { | 2139 | for (ArrayRef<uint32_t> Vec : CuVectors) { |
| 1927 | write32le(Buf, CuVec.size()); | 2140 | write32le(Buf, Vec.size()); |
| 1928 | Buf += 4; | 2141 | Buf += 4; |
| 1929 | for (uint32_t Val : CuVec) { | 2142 | for (uint32_t Val : Vec) { |
| 1930 | write32le(Buf, Val); | 2143 | write32le(Buf, Val); |
| 1931 | Buf += 4; | 2144 | Buf += 4; |
| 1932 | } | 2145 | } |
| 1933 | } | 2146 | } |
| 1934 | 2147 | ||
| 1935 | StringPool.write(Buf); | 2148 | // Write the string pool. |
| 2149 | for (auto &KV : Symbols) { | ||
| 2150 | CachedHashStringRef S = KV.first; | ||
| 2151 | GdbSymbol *Sym = KV.second; | ||
| 2152 | size_t Off = Sym->NameOffset; | ||
| 2153 | memcpy(Buf + Off, S.val().data(), S.size()); | ||
| 2154 | Buf[Off + S.size()] = '\0'; | ||
| 2155 | } | ||
| 1936 | } | 2156 | } |
| 1937 | 2157 | ||
| 1938 | bool GdbIndexSection::empty() const { return !Out::DebugInfo; } | 2158 | bool GdbIndexSection::empty() const { return !Out::DebugInfo; } |
| 1939 | 2159 | ||
| 1940 | template <class ELFT> | 2160 | EhFrameHeader::EhFrameHeader() |
| 1941 | EhFrameHeader<ELFT>::EhFrameHeader() | ||
| 1942 | : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame_hdr") {} | 2161 | : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame_hdr") {} |
| 1943 | 2162 | ||
| 1944 | // .eh_frame_hdr contains a binary search table of pointers to FDEs. | 2163 | // .eh_frame_hdr contains a binary search table of pointers to FDEs. |
| 1945 | // Each entry of the search table consists of two values, | 2164 | // Each entry of the search table consists of two values, |
| 1946 | // the starting PC from where FDEs covers, and the FDE's address. | 2165 | // the starting PC from where FDEs covers, and the FDE's address. |
| 1947 | // It is sorted by PC. | 2166 | // It is sorted by PC. |
| 1948 | template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) { | 2167 | void EhFrameHeader::writeTo(uint8_t *Buf) { |
| 1949 | const endianness E = ELFT::TargetEndianness; | 2168 | typedef EhFrameSection::FdeData FdeData; |
| 2169 | |||
| 2170 | std::vector<FdeData> Fdes = InX::EhFrame->getFdeData(); | ||
| 1950 | 2171 | ||
| 1951 | // Sort the FDE list by their PC and uniqueify. Usually there is only | 2172 | // Sort the FDE list by their PC and uniqueify. Usually there is only |
| 1952 | // one FDE for a PC (i.e. function), but if ICF merges two functions | 2173 | // one FDE for a PC (i.e. function), but if ICF merges two functions |
| ... | @@ -1960,31 +2181,24 @@ template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) { | ... | @@ -1960,31 +2181,24 @@ template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) { |
| 1960 | Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; | 2181 | Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; |
| 1961 | Buf[2] = DW_EH_PE_udata4; | 2182 | Buf[2] = DW_EH_PE_udata4; |
| 1962 | Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; | 2183 | Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; |
| 1963 | write32<E>(Buf + 4, In<ELFT>::EhFrame->getParent()->Addr - this->getVA() - 4); | 2184 | write32(Buf + 4, InX::EhFrame->getParent()->Addr - this->getVA() - 4); |
| 1964 | write32<E>(Buf + 8, Fdes.size()); | 2185 | write32(Buf + 8, Fdes.size()); |
| 1965 | Buf += 12; | 2186 | Buf += 12; |
| 1966 | 2187 | ||
| 1967 | uint64_t VA = this->getVA(); | 2188 | uint64_t VA = this->getVA(); |
| 1968 | for (FdeData &Fde : Fdes) { | 2189 | for (FdeData &Fde : Fdes) { |
| 1969 | write32<E>(Buf, Fde.Pc - VA); | 2190 | write32(Buf, Fde.Pc - VA); |
| 1970 | write32<E>(Buf + 4, Fde.FdeVA - VA); | 2191 | write32(Buf + 4, Fde.FdeVA - VA); |
| 1971 | Buf += 8; | 2192 | Buf += 8; |
| 1972 | } | 2193 | } |
| 1973 | } | 2194 | } |
| 1974 | 2195 | ||
| 1975 | template <class ELFT> size_t EhFrameHeader<ELFT>::getSize() const { | 2196 | size_t EhFrameHeader::getSize() const { |
| 1976 | // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs. | 2197 | // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs. |
| 1977 | return 12 + In<ELFT>::EhFrame->NumFdes * 8; | 2198 | return 12 + InX::EhFrame->NumFdes * 8; |
| 1978 | } | ||
| 1979 | |||
| 1980 | template <class ELFT> | ||
| 1981 | void EhFrameHeader<ELFT>::addFde(uint32_t Pc, uint32_t FdeVA) { | ||
| 1982 | Fdes.push_back({Pc, FdeVA}); | ||
| 1983 | } | 2199 | } |
| 1984 | 2200 | ||
| 1985 | template <class ELFT> bool EhFrameHeader<ELFT>::empty() const { | 2201 | bool EhFrameHeader::empty() const { return InX::EhFrame->empty(); } |
| 1986 | return In<ELFT>::EhFrame->empty(); | ||
| 1987 | } | ||
| 1988 | 2202 | ||
| 1989 | template <class ELFT> | 2203 | template <class ELFT> |
| 1990 | VersionDefinitionSection<ELFT>::VersionDefinitionSection() | 2204 | VersionDefinitionSection<ELFT>::VersionDefinitionSection() |
| ... | @@ -2065,7 +2279,7 @@ template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const { | ... | @@ -2065,7 +2279,7 @@ template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const { |
| 2065 | template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) { | 2279 | template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) { |
| 2066 | auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1; | 2280 | auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1; |
| 2067 | for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { | 2281 | for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { |
| 2068 | OutVersym->vs_index = S.Symbol->symbol()->VersionId; | 2282 | OutVersym->vs_index = S.Sym->VersionId; |
| 2069 | ++OutVersym; | 2283 | ++OutVersym; |
| 2070 | } | 2284 | } |
| 2071 | } | 2285 | } |
| ... | @@ -2086,29 +2300,28 @@ VersionNeedSection<ELFT>::VersionNeedSection() | ... | @@ -2086,29 +2300,28 @@ VersionNeedSection<ELFT>::VersionNeedSection() |
| 2086 | 2300 | ||
| 2087 | template <class ELFT> | 2301 | template <class ELFT> |
| 2088 | void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) { | 2302 | void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) { |
| 2089 | auto *Ver = reinterpret_cast<const typename ELFT::Verdef *>(SS->Verdef); | 2303 | SharedFile<ELFT> &File = SS->getFile<ELFT>(); |
| 2304 | const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex]; | ||
| 2090 | if (!Ver) { | 2305 | if (!Ver) { |
| 2091 | SS->symbol()->VersionId = VER_NDX_GLOBAL; | 2306 | SS->VersionId = VER_NDX_GLOBAL; |
| 2092 | return; | 2307 | return; |
| 2093 | } | 2308 | } |
| 2094 | 2309 | ||
| 2095 | auto *File = cast<SharedFile<ELFT>>(SS->File); | ||
| 2096 | |||
| 2097 | // If we don't already know that we need an Elf_Verneed for this DSO, prepare | 2310 | // If we don't already know that we need an Elf_Verneed for this DSO, prepare |
| 2098 | // to create one by adding it to our needed list and creating a dynstr entry | 2311 | // to create one by adding it to our needed list and creating a dynstr entry |
| 2099 | // for the soname. | 2312 | // for the soname. |
| 2100 | if (File->VerdefMap.empty()) | 2313 | if (File.VerdefMap.empty()) |
| 2101 | Needed.push_back({File, InX::DynStrTab->addString(File->SoName)}); | 2314 | Needed.push_back({&File, InX::DynStrTab->addString(File.SoName)}); |
| 2102 | typename SharedFile<ELFT>::NeededVer &NV = File->VerdefMap[Ver]; | 2315 | typename SharedFile<ELFT>::NeededVer &NV = File.VerdefMap[Ver]; |
| 2103 | // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef, | 2316 | // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef, |
| 2104 | // prepare to create one by allocating a version identifier and creating a | 2317 | // prepare to create one by allocating a version identifier and creating a |
| 2105 | // dynstr entry for the version name. | 2318 | // dynstr entry for the version name. |
| 2106 | if (NV.Index == 0) { | 2319 | if (NV.Index == 0) { |
| 2107 | NV.StrTab = InX::DynStrTab->addString(File->getStringTable().data() + | 2320 | NV.StrTab = InX::DynStrTab->addString(File.getStringTable().data() + |
| 2108 | Ver->getAux()->vda_name); | 2321 | Ver->getAux()->vda_name); |
| 2109 | NV.Index = NextIndex++; | 2322 | NV.Index = NextIndex++; |
| 2110 | } | 2323 | } |
| 2111 | SS->symbol()->VersionId = NV.Index; | 2324 | SS->VersionId = NV.Index; |
| 2112 | } | 2325 | } |
| 2113 | 2326 | ||
| 2114 | template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) { | 2327 | template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) { |
| ... | @@ -2162,23 +2375,21 @@ template <class ELFT> bool VersionNeedSection<ELFT>::empty() const { | ... | @@ -2162,23 +2375,21 @@ template <class ELFT> bool VersionNeedSection<ELFT>::empty() const { |
| 2162 | return getNeedNum() == 0; | 2375 | return getNeedNum() == 0; |
| 2163 | } | 2376 | } |
| 2164 | 2377 | ||
| 2165 | MergeSyntheticSection::MergeSyntheticSection(StringRef Name, uint32_t Type, | ||
| 2166 | uint64_t Flags, uint32_t Alignment) | ||
| 2167 | : SyntheticSection(Flags, Type, Alignment, Name), | ||
| 2168 | Builder(StringTableBuilder::RAW, Alignment) {} | ||
| 2169 | |||
| 2170 | void MergeSyntheticSection::addSection(MergeInputSection *MS) { | 2378 | void MergeSyntheticSection::addSection(MergeInputSection *MS) { |
| 2171 | MS->Parent = this; | 2379 | MS->Parent = this; |
| 2172 | Sections.push_back(MS); | 2380 | Sections.push_back(MS); |
| 2173 | } | 2381 | } |
| 2174 | 2382 | ||
| 2175 | void MergeSyntheticSection::writeTo(uint8_t *Buf) { Builder.write(Buf); } | 2383 | MergeTailSection::MergeTailSection(StringRef Name, uint32_t Type, |
| 2384 | uint64_t Flags, uint32_t Alignment) | ||
| 2385 | : MergeSyntheticSection(Name, Type, Flags, Alignment), | ||
| 2386 | Builder(StringTableBuilder::RAW, Alignment) {} | ||
| 2176 | 2387 | ||
| 2177 | bool MergeSyntheticSection::shouldTailMerge() const { | 2388 | size_t MergeTailSection::getSize() const { return Builder.getSize(); } |
| 2178 | return (this->Flags & SHF_STRINGS) && Config->Optimize >= 2; | ||
| 2179 | } | ||
| 2180 | 2389 | ||
| 2181 | void MergeSyntheticSection::finalizeTailMerge() { | 2390 | void MergeTailSection::writeTo(uint8_t *Buf) { Builder.write(Buf); } |
| 2391 | |||
| 2392 | void MergeTailSection::finalizeContents() { | ||
| 2182 | // Add all string pieces to the string table builder to create section | 2393 | // Add all string pieces to the string table builder to create section |
| 2183 | // contents. | 2394 | // contents. |
| 2184 | for (MergeInputSection *Sec : Sections) | 2395 | for (MergeInputSection *Sec : Sections) |
| ... | @@ -2198,46 +2409,96 @@ void MergeSyntheticSection::finalizeTailMerge() { | ... | @@ -2198,46 +2409,96 @@ void MergeSyntheticSection::finalizeTailMerge() { |
| 2198 | Sec->Pieces[I].OutputOff = Builder.getOffset(Sec->getData(I)); | 2409 | Sec->Pieces[I].OutputOff = Builder.getOffset(Sec->getData(I)); |
| 2199 | } | 2410 | } |
| 2200 | 2411 | ||
| 2201 | void MergeSyntheticSection::finalizeNoTailMerge() { | 2412 | void MergeNoTailSection::writeTo(uint8_t *Buf) { |
| 2202 | // Add all string pieces to the string table builder to create section | 2413 | for (size_t I = 0; I < NumShards; ++I) |
| 2203 | // contents. Because we are not tail-optimizing, offsets of strings are | 2414 | Shards[I].write(Buf + ShardOffsets[I]); |
| 2204 | // fixed when they are added to the builder (string table builder contains | 2415 | } |
| 2205 | // a hash table from strings to offsets). | 2416 | |
| 2206 | for (MergeInputSection *Sec : Sections) | 2417 | // This function is very hot (i.e. it can take several seconds to finish) |
| 2418 | // because sometimes the number of inputs is in an order of magnitude of | ||
| 2419 | // millions. So, we use multi-threading. | ||
| 2420 | // | ||
| 2421 | // For any strings S and T, we know S is not mergeable with T if S's hash | ||
| 2422 | // value is different from T's. If that's the case, we can safely put S and | ||
| 2423 | // T into different string builders without worrying about merge misses. | ||
| 2424 | // We do it in parallel. | ||
| 2425 | void MergeNoTailSection::finalizeContents() { | ||
| 2426 | // Initializes string table builders. | ||
| 2427 | for (size_t I = 0; I < NumShards; ++I) | ||
| 2428 | Shards.emplace_back(StringTableBuilder::RAW, Alignment); | ||
| 2429 | |||
| 2430 | // Concurrency level. Must be a power of 2 to avoid expensive modulo | ||
| 2431 | // operations in the following tight loop. | ||
| 2432 | size_t Concurrency = 1; | ||
| 2433 | if (ThreadsEnabled) | ||
| 2434 | Concurrency = | ||
| 2435 | std::min<size_t>(PowerOf2Floor(hardware_concurrency()), NumShards); | ||
| 2436 | |||
| 2437 | // Add section pieces to the builders. | ||
| 2438 | parallelForEachN(0, Concurrency, [&](size_t ThreadId) { | ||
| 2439 | for (MergeInputSection *Sec : Sections) { | ||
| 2440 | for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) { | ||
| 2441 | size_t ShardId = getShardId(Sec->Pieces[I].Hash); | ||
| 2442 | if ((ShardId & (Concurrency - 1)) == ThreadId && Sec->Pieces[I].Live) | ||
| 2443 | Sec->Pieces[I].OutputOff = Shards[ShardId].add(Sec->getData(I)); | ||
| 2444 | } | ||
| 2445 | } | ||
| 2446 | }); | ||
| 2447 | |||
| 2448 | // Compute an in-section offset for each shard. | ||
| 2449 | size_t Off = 0; | ||
| 2450 | for (size_t I = 0; I < NumShards; ++I) { | ||
| 2451 | Shards[I].finalizeInOrder(); | ||
| 2452 | if (Shards[I].getSize() > 0) | ||
| 2453 | Off = alignTo(Off, Alignment); | ||
| 2454 | ShardOffsets[I] = Off; | ||
| 2455 | Off += Shards[I].getSize(); | ||
| 2456 | } | ||
| 2457 | Size = Off; | ||
| 2458 | |||
| 2459 | // So far, section pieces have offsets from beginning of shards, but | ||
| 2460 | // we want offsets from beginning of the whole section. Fix them. | ||
| 2461 | parallelForEach(Sections, [&](MergeInputSection *Sec) { | ||
| 2207 | for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) | 2462 | for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) |
| 2208 | if (Sec->Pieces[I].Live) | 2463 | if (Sec->Pieces[I].Live) |
| 2209 | Sec->Pieces[I].OutputOff = Builder.add(Sec->getData(I)); | 2464 | Sec->Pieces[I].OutputOff += |
| 2465 | ShardOffsets[getShardId(Sec->Pieces[I].Hash)]; | ||
| 2466 | }); | ||
| 2467 | } | ||
| 2210 | 2468 | ||
| 2211 | Builder.finalizeInOrder(); | 2469 | static MergeSyntheticSection *createMergeSynthetic(StringRef Name, |
| 2470 | uint32_t Type, | ||
| 2471 | uint64_t Flags, | ||
| 2472 | uint32_t Alignment) { | ||
| 2473 | bool ShouldTailMerge = (Flags & SHF_STRINGS) && Config->Optimize >= 2; | ||
| 2474 | if (ShouldTailMerge) | ||
| 2475 | return make<MergeTailSection>(Name, Type, Flags, Alignment); | ||
| 2476 | return make<MergeNoTailSection>(Name, Type, Flags, Alignment); | ||
| 2212 | } | 2477 | } |
| 2213 | 2478 | ||
| 2214 | void MergeSyntheticSection::finalizeContents() { | 2479 | // Debug sections may be compressed by zlib. Uncompress if exists. |
| 2215 | if (shouldTailMerge()) | 2480 | void elf::decompressSections() { |
| 2216 | finalizeTailMerge(); | 2481 | parallelForEach(InputSections, [](InputSectionBase *Sec) { |
| 2217 | else | 2482 | if (Sec->Live) |
| 2218 | finalizeNoTailMerge(); | 2483 | Sec->maybeUncompress(); |
| 2219 | } | 2484 | }); |
| 2220 | 2485 | } | |
| 2221 | size_t MergeSyntheticSection::getSize() const { return Builder.getSize(); } | 2486 | |
| 2222 | 2487 | // This function scans over the inputsections to create mergeable | |
| 2223 | // This function decompresses compressed sections and scans over the input | 2488 | // synthetic sections. |
| 2224 | // sections to create mergeable synthetic sections. It removes | 2489 | // |
| 2225 | // MergeInputSections from the input section array and adds new synthetic | 2490 | // It removes MergeInputSections from the input section array and adds |
| 2226 | // sections at the location of the first input section that it replaces. It then | 2491 | // new synthetic sections at the location of the first input section |
| 2227 | // finalizes each synthetic section in order to compute an output offset for | 2492 | // that it replaces. It then finalizes each synthetic section in order |
| 2228 | // each piece of each input section. | 2493 | // to compute an output offset for each piece of each input section. |
| 2229 | void elf::decompressAndMergeSections() { | 2494 | void elf::mergeSections() { |
| 2230 | // splitIntoPieces needs to be called on each MergeInputSection before calling | 2495 | // splitIntoPieces needs to be called on each MergeInputSection |
| 2231 | // finalizeContents(). Do that first. | 2496 | // before calling finalizeContents(). Do that first. |
| 2232 | parallelForEach(InputSections.begin(), InputSections.end(), | 2497 | parallelForEach(InputSections, [](InputSectionBase *Sec) { |
| 2233 | [](InputSectionBase *S) { | 2498 | if (Sec->Live) |
| 2234 | if (!S->Live) | 2499 | if (auto *S = dyn_cast<MergeInputSection>(Sec)) |
| 2235 | return; | 2500 | S->splitIntoPieces(); |
| 2236 | if (Decompressor::isCompressedELFSection(S->Flags, S->Name)) | 2501 | }); |
| 2237 | S->uncompress(); | ||
| 2238 | if (auto *MS = dyn_cast<MergeInputSection>(S)) | ||
| 2239 | MS->splitIntoPieces(); | ||
| 2240 | }); | ||
| 2241 | 2502 | ||
| 2242 | std::vector<MergeSyntheticSection *> MergeSections; | 2503 | std::vector<MergeSyntheticSection *> MergeSections; |
| 2243 | for (InputSectionBase *&S : InputSections) { | 2504 | for (InputSectionBase *&S : InputSections) { |
| ... | @@ -2250,20 +2511,28 @@ void elf::decompressAndMergeSections() { | ... | @@ -2250,20 +2511,28 @@ void elf::decompressAndMergeSections() { |
| 2250 | if (!MS->Live) | 2511 | if (!MS->Live) |
| 2251 | continue; | 2512 | continue; |
| 2252 | 2513 | ||
| 2253 | StringRef OutsecName = getOutputSectionName(MS->Name); | 2514 | StringRef OutsecName = getOutputSectionName(MS); |
| 2254 | uint64_t Flags = MS->Flags & ~(uint64_t)SHF_GROUP; | ||
| 2255 | uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize); | 2515 | uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize); |
| 2256 | 2516 | ||
| 2257 | auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) { | 2517 | auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) { |
| 2258 | return Sec->Name == OutsecName && Sec->Flags == Flags && | 2518 | // While we could create a single synthetic section for two different |
| 2259 | Sec->Alignment == Alignment; | 2519 | // values of Entsize, it is better to take Entsize into consideration. |
| 2520 | // | ||
| 2521 | // With a single synthetic section no two pieces with different Entsize | ||
| 2522 | // could be equal, so we may as well have two sections. | ||
| 2523 | // | ||
| 2524 | // Using Entsize in here also allows us to propagate it to the synthetic | ||
| 2525 | // section. | ||
| 2526 | return Sec->Name == OutsecName && Sec->Flags == MS->Flags && | ||
| 2527 | Sec->Entsize == MS->Entsize && Sec->Alignment == Alignment; | ||
| 2260 | }); | 2528 | }); |
| 2261 | if (I == MergeSections.end()) { | 2529 | if (I == MergeSections.end()) { |
| 2262 | MergeSyntheticSection *Syn = | 2530 | MergeSyntheticSection *Syn = |
| 2263 | make<MergeSyntheticSection>(OutsecName, MS->Type, Flags, Alignment); | 2531 | createMergeSynthetic(OutsecName, MS->Type, MS->Flags, Alignment); |
| 2264 | MergeSections.push_back(Syn); | 2532 | MergeSections.push_back(Syn); |
| 2265 | I = std::prev(MergeSections.end()); | 2533 | I = std::prev(MergeSections.end()); |
| 2266 | S = Syn; | 2534 | S = Syn; |
| 2535 | Syn->Entsize = MS->Entsize; | ||
| 2267 | } else { | 2536 | } else { |
| 2268 | S = nullptr; | 2537 | S = nullptr; |
| 2269 | } | 2538 | } |
| ... | @@ -2291,22 +2560,23 @@ ARMExidxSentinelSection::ARMExidxSentinelSection() | ... | @@ -2291,22 +2560,23 @@ ARMExidxSentinelSection::ARMExidxSentinelSection() |
| 2291 | // The sentinel must have the PREL31 value of an address higher than any | 2560 | // The sentinel must have the PREL31 value of an address higher than any |
| 2292 | // address described by any other table entry. | 2561 | // address described by any other table entry. |
| 2293 | void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { | 2562 | void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { |
| 2294 | // The Sections are sorted in order of ascending PREL31 address with the | 2563 | assert(Highest); |
| 2295 | // sentinel last. We need to find the InputSection that precedes the | 2564 | uint64_t S = |
| 2296 | // sentinel. By construction the Sentinel is in the last | 2565 | Highest->getParent()->Addr + Highest->getOffset(Highest->getSize()); |
| 2297 | // InputSectionDescription as the InputSection that precedes it. | ||
| 2298 | OutputSectionCommand *C = Script->getCmd(getParent()); | ||
| 2299 | auto ISD = std::find_if(C->Commands.rbegin(), C->Commands.rend(), | ||
| 2300 | [](const BaseCommand *Base) { | ||
| 2301 | return isa<InputSectionDescription>(Base); | ||
| 2302 | }); | ||
| 2303 | auto L = cast<InputSectionDescription>(*ISD); | ||
| 2304 | InputSection *Highest = L->Sections[L->Sections.size() - 2]; | ||
| 2305 | InputSection *LS = Highest->getLinkOrderDep(); | ||
| 2306 | uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize()); | ||
| 2307 | uint64_t P = getVA(); | 2566 | uint64_t P = getVA(); |
| 2308 | Target->relocateOne(Buf, R_ARM_PREL31, S - P); | 2567 | Target->relocateOne(Buf, R_ARM_PREL31, S - P); |
| 2309 | write32le(Buf + 4, 0x1); | 2568 | write32le(Buf + 4, 1); |
| 2569 | } | ||
| 2570 | |||
| 2571 | // The sentinel has to be removed if there are no other .ARM.exidx entries. | ||
| 2572 | bool ARMExidxSentinelSection::empty() const { | ||
| 2573 | OutputSection *OS = getParent(); | ||
| 2574 | for (auto *B : OS->SectionCommands) | ||
| 2575 | if (auto *ISD = dyn_cast<InputSectionDescription>(B)) | ||
| 2576 | for (auto *S : ISD->Sections) | ||
| 2577 | if (!isa<ARMExidxSentinelSection>(S)) | ||
| 2578 | return false; | ||
| 2579 | return true; | ||
| 2310 | } | 2580 | } |
| 2311 | 2581 | ||
| 2312 | ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off) | 2582 | ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off) |
| ... | @@ -2330,6 +2600,8 @@ void ThunkSection::writeTo(uint8_t *Buf) { | ... | @@ -2330,6 +2600,8 @@ void ThunkSection::writeTo(uint8_t *Buf) { |
| 2330 | } | 2600 | } |
| 2331 | 2601 | ||
| 2332 | InputSection *ThunkSection::getTargetInputSection() const { | 2602 | InputSection *ThunkSection::getTargetInputSection() const { |
| 2603 | if (Thunks.empty()) | ||
| 2604 | return nullptr; | ||
| 2333 | const Thunk *T = Thunks.front(); | 2605 | const Thunk *T = Thunks.front(); |
| 2334 | return T->getTargetInputSection(); | 2606 | return T->getTargetInputSection(); |
| 2335 | } | 2607 | } |
| ... | @@ -2338,7 +2610,8 @@ InputSection *InX::ARMAttributes; | ... | @@ -2338,7 +2610,8 @@ InputSection *InX::ARMAttributes; |
| 2338 | BssSection *InX::Bss; | 2610 | BssSection *InX::Bss; |
| 2339 | BssSection *InX::BssRelRo; | 2611 | BssSection *InX::BssRelRo; |
| 2340 | BuildIdSection *InX::BuildId; | 2612 | BuildIdSection *InX::BuildId; |
| 2341 | InputSection *InX::Common; | 2613 | EhFrameHeader *InX::EhFrameHdr; |
| 2614 | EhFrameSection *InX::EhFrame; | ||
| 2342 | SyntheticSection *InX::Dynamic; | 2615 | SyntheticSection *InX::Dynamic; |
| 2343 | StringTableSection *InX::DynStrTab; | 2616 | StringTableSection *InX::DynStrTab; |
| 2344 | SymbolTableBaseSection *InX::DynSymTab; | 2617 | SymbolTableBaseSection *InX::DynSymTab; |
| ... | @@ -2347,11 +2620,15 @@ GdbIndexSection *InX::GdbIndex; | ... | @@ -2347,11 +2620,15 @@ GdbIndexSection *InX::GdbIndex; |
| 2347 | GotSection *InX::Got; | 2620 | GotSection *InX::Got; |
| 2348 | GotPltSection *InX::GotPlt; | 2621 | GotPltSection *InX::GotPlt; |
| 2349 | GnuHashTableSection *InX::GnuHashTab; | 2622 | GnuHashTableSection *InX::GnuHashTab; |
| 2623 | HashTableSection *InX::HashTab; | ||
| 2350 | IgotPltSection *InX::IgotPlt; | 2624 | IgotPltSection *InX::IgotPlt; |
| 2351 | MipsGotSection *InX::MipsGot; | 2625 | MipsGotSection *InX::MipsGot; |
| 2352 | MipsRldMapSection *InX::MipsRldMap; | 2626 | MipsRldMapSection *InX::MipsRldMap; |
| 2353 | PltSection *InX::Plt; | 2627 | PltSection *InX::Plt; |
| 2354 | PltSection *InX::Iplt; | 2628 | PltSection *InX::Iplt; |
| 2629 | RelocationBaseSection *InX::RelaDyn; | ||
| 2630 | RelocationBaseSection *InX::RelaPlt; | ||
| 2631 | RelocationBaseSection *InX::RelaIplt; | ||
| 2355 | StringTableSection *InX::ShStrTab; | 2632 | StringTableSection *InX::ShStrTab; |
| 2356 | StringTableSection *InX::StrTab; | 2633 | StringTableSection *InX::StrTab; |
| 2357 | SymbolTableBaseSection *InX::SymTab; | 2634 | SymbolTableBaseSection *InX::SymTab; |
| ... | @@ -2361,20 +2638,15 @@ template GdbIndexSection *elf::createGdbIndex<ELF32BE>(); | ... | @@ -2361,20 +2638,15 @@ template GdbIndexSection *elf::createGdbIndex<ELF32BE>(); |
| 2361 | template GdbIndexSection *elf::createGdbIndex<ELF64LE>(); | 2638 | template GdbIndexSection *elf::createGdbIndex<ELF64LE>(); |
| 2362 | template GdbIndexSection *elf::createGdbIndex<ELF64BE>(); | 2639 | template GdbIndexSection *elf::createGdbIndex<ELF64BE>(); |
| 2363 | 2640 | ||
| 2364 | template void PltSection::addEntry<ELF32LE>(SymbolBody &Sym); | 2641 | template void EhFrameSection::addSection<ELF32LE>(InputSectionBase *); |
| 2365 | template void PltSection::addEntry<ELF32BE>(SymbolBody &Sym); | 2642 | template void EhFrameSection::addSection<ELF32BE>(InputSectionBase *); |
| 2366 | template void PltSection::addEntry<ELF64LE>(SymbolBody &Sym); | 2643 | template void EhFrameSection::addSection<ELF64LE>(InputSectionBase *); |
| 2367 | template void PltSection::addEntry<ELF64BE>(SymbolBody &Sym); | 2644 | template void EhFrameSection::addSection<ELF64BE>(InputSectionBase *); |
| 2368 | |||
| 2369 | template InputSection *elf::createCommonSection<ELF32LE>(); | ||
| 2370 | template InputSection *elf::createCommonSection<ELF32BE>(); | ||
| 2371 | template InputSection *elf::createCommonSection<ELF64LE>(); | ||
| 2372 | template InputSection *elf::createCommonSection<ELF64BE>(); | ||
| 2373 | 2645 | ||
| 2374 | template MergeInputSection *elf::createCommentSection<ELF32LE>(); | 2646 | template void PltSection::addEntry<ELF32LE>(Symbol &Sym); |
| 2375 | template MergeInputSection *elf::createCommentSection<ELF32BE>(); | 2647 | template void PltSection::addEntry<ELF32BE>(Symbol &Sym); |
| 2376 | template MergeInputSection *elf::createCommentSection<ELF64LE>(); | 2648 | template void PltSection::addEntry<ELF64LE>(Symbol &Sym); |
| 2377 | template MergeInputSection *elf::createCommentSection<ELF64BE>(); | 2649 | template void PltSection::addEntry<ELF64BE>(Symbol &Sym); |
| 2378 | 2650 | ||
| 2379 | template class elf::MipsAbiFlagsSection<ELF32LE>; | 2651 | template class elf::MipsAbiFlagsSection<ELF32LE>; |
| 2380 | template class elf::MipsAbiFlagsSection<ELF32BE>; | 2652 | template class elf::MipsAbiFlagsSection<ELF32BE>; |
| ... | @@ -2401,21 +2673,16 @@ template class elf::RelocationSection<ELF32BE>; | ... | @@ -2401,21 +2673,16 @@ template class elf::RelocationSection<ELF32BE>; |
| 2401 | template class elf::RelocationSection<ELF64LE>; | 2673 | template class elf::RelocationSection<ELF64LE>; |
| 2402 | template class elf::RelocationSection<ELF64BE>; | 2674 | template class elf::RelocationSection<ELF64BE>; |
| 2403 | 2675 | ||
| 2676 | template class elf::AndroidPackedRelocationSection<ELF32LE>; | ||
| 2677 | template class elf::AndroidPackedRelocationSection<ELF32BE>; | ||
| 2678 | template class elf::AndroidPackedRelocationSection<ELF64LE>; | ||
| 2679 | template class elf::AndroidPackedRelocationSection<ELF64BE>; | ||
| 2680 | |||
| 2404 | template class elf::SymbolTableSection<ELF32LE>; | 2681 | template class elf::SymbolTableSection<ELF32LE>; |
| 2405 | template class elf::SymbolTableSection<ELF32BE>; | 2682 | template class elf::SymbolTableSection<ELF32BE>; |
| 2406 | template class elf::SymbolTableSection<ELF64LE>; | 2683 | template class elf::SymbolTableSection<ELF64LE>; |
| 2407 | template class elf::SymbolTableSection<ELF64BE>; | 2684 | template class elf::SymbolTableSection<ELF64BE>; |
| 2408 | 2685 | ||
| 2409 | template class elf::HashTableSection<ELF32LE>; | ||
| 2410 | template class elf::HashTableSection<ELF32BE>; | ||
| 2411 | template class elf::HashTableSection<ELF64LE>; | ||
| 2412 | template class elf::HashTableSection<ELF64BE>; | ||
| 2413 | |||
| 2414 | template class elf::EhFrameHeader<ELF32LE>; | ||
| 2415 | template class elf::EhFrameHeader<ELF32BE>; | ||
| 2416 | template class elf::EhFrameHeader<ELF64LE>; | ||
| 2417 | template class elf::EhFrameHeader<ELF64BE>; | ||
| 2418 | |||
| 2419 | template class elf::VersionTableSection<ELF32LE>; | 2686 | template class elf::VersionTableSection<ELF32LE>; |
| 2420 | template class elf::VersionTableSection<ELF32BE>; | 2687 | template class elf::VersionTableSection<ELF32BE>; |
| 2421 | template class elf::VersionTableSection<ELF64LE>; | 2688 | template class elf::VersionTableSection<ELF64LE>; |
| ... | @@ -2430,8 +2697,3 @@ template class elf::VersionDefinitionSection<ELF32LE>; | ... | @@ -2430,8 +2697,3 @@ template class elf::VersionDefinitionSection<ELF32LE>; |
| 2430 | template class elf::VersionDefinitionSection<ELF32BE>; | 2697 | template class elf::VersionDefinitionSection<ELF32BE>; |
| 2431 | template class elf::VersionDefinitionSection<ELF64LE>; | 2698 | template class elf::VersionDefinitionSection<ELF64LE>; |
| 2432 | template class elf::VersionDefinitionSection<ELF64BE>; | 2699 | template class elf::VersionDefinitionSection<ELF64BE>; |
| 2433 | |||
| 2434 | template class elf::EhFrameSection<ELF32LE>; | ||
| 2435 | template class elf::EhFrameSection<ELF32BE>; | ||
| 2436 | template class elf::EhFrameSection<ELF64LE>; | ||
| 2437 | template class elf::EhFrameSection<ELF64BE>; |
deps/lld/ELF/SyntheticSections.h+208-150| ... | @@ -26,17 +26,17 @@ | ... | @@ -26,17 +26,17 @@ |
| 26 | #include "InputSection.h" | 26 | #include "InputSection.h" |
| 27 | #include "llvm/ADT/MapVector.h" | 27 | #include "llvm/ADT/MapVector.h" |
| 28 | #include "llvm/MC/StringTableBuilder.h" | 28 | #include "llvm/MC/StringTableBuilder.h" |
| 29 | 29 | #include <functional> | |
| 30 | #include <set> | ||
| 31 | 30 | ||
| 32 | namespace lld { | 31 | namespace lld { |
| 33 | namespace elf { | 32 | namespace elf { |
| 33 | class SharedSymbol; | ||
| 34 | 34 | ||
| 35 | class SyntheticSection : public InputSection { | 35 | class SyntheticSection : public InputSection { |
| 36 | public: | 36 | public: |
| 37 | SyntheticSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, | 37 | SyntheticSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, |
| 38 | StringRef Name) | 38 | StringRef Name) |
| 39 | : InputSection(Flags, Type, Alignment, {}, Name, | 39 | : InputSection(nullptr, Flags, Type, Alignment, {}, Name, |
| 40 | InputSectionBase::Synthetic) { | 40 | InputSectionBase::Synthetic) { |
| 41 | this->Live = true; | 41 | this->Live = true; |
| 42 | } | 42 | } |
| ... | @@ -47,7 +47,7 @@ public: | ... | @@ -47,7 +47,7 @@ public: |
| 47 | virtual void finalizeContents() {} | 47 | virtual void finalizeContents() {} |
| 48 | // If the section has the SHF_ALLOC flag and the size may be changed if | 48 | // If the section has the SHF_ALLOC flag and the size may be changed if |
| 49 | // thunks are added, update the section size. | 49 | // thunks are added, update the section size. |
| 50 | virtual void updateAllocSize() {} | 50 | virtual bool updateAllocSize() { return false; } |
| 51 | // If any additional finalization of contents are needed post thunk creation. | 51 | // If any additional finalization of contents are needed post thunk creation. |
| 52 | virtual void postThunkContents() {} | 52 | virtual void postThunkContents() {} |
| 53 | virtual bool empty() const { return false; } | 53 | virtual bool empty() const { return false; } |
| ... | @@ -59,21 +59,12 @@ public: | ... | @@ -59,21 +59,12 @@ public: |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | struct CieRecord { | 61 | struct CieRecord { |
| 62 | EhSectionPiece *Piece = nullptr; | 62 | EhSectionPiece *Cie = nullptr; |
| 63 | std::vector<EhSectionPiece *> FdePieces; | 63 | std::vector<EhSectionPiece *> Fdes; |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | // Section for .eh_frame. | 66 | // Section for .eh_frame. |
| 67 | template <class ELFT> class EhFrameSection final : public SyntheticSection { | 67 | class EhFrameSection final : public SyntheticSection { |
| 68 | typedef typename ELFT::Shdr Elf_Shdr; | ||
| 69 | typedef typename ELFT::Rel Elf_Rel; | ||
| 70 | typedef typename ELFT::Rela Elf_Rela; | ||
| 71 | |||
| 72 | void updateAlignment(uint64_t Val) { | ||
| 73 | if (Val > this->Alignment) | ||
| 74 | this->Alignment = Val; | ||
| 75 | } | ||
| 76 | |||
| 77 | public: | 68 | public: |
| 78 | EhFrameSection(); | 69 | EhFrameSection(); |
| 79 | void writeTo(uint8_t *Buf) override; | 70 | void writeTo(uint8_t *Buf) override; |
| ... | @@ -81,30 +72,36 @@ public: | ... | @@ -81,30 +72,36 @@ public: |
| 81 | bool empty() const override { return Sections.empty(); } | 72 | bool empty() const override { return Sections.empty(); } |
| 82 | size_t getSize() const override { return Size; } | 73 | size_t getSize() const override { return Size; } |
| 83 | 74 | ||
| 84 | void addSection(InputSectionBase *S); | 75 | template <class ELFT> void addSection(InputSectionBase *S); |
| 85 | 76 | ||
| 77 | std::vector<EhInputSection *> Sections; | ||
| 86 | size_t NumFdes = 0; | 78 | size_t NumFdes = 0; |
| 87 | 79 | ||
| 88 | std::vector<EhInputSection *> Sections; | 80 | struct FdeData { |
| 81 | uint32_t Pc; | ||
| 82 | uint32_t FdeVA; | ||
| 83 | }; | ||
| 84 | |||
| 85 | std::vector<FdeData> getFdeData() const; | ||
| 89 | 86 | ||
| 90 | private: | 87 | private: |
| 91 | uint64_t Size = 0; | 88 | uint64_t Size = 0; |
| 92 | template <class RelTy> | 89 | |
| 90 | template <class ELFT, class RelTy> | ||
| 93 | void addSectionAux(EhInputSection *S, llvm::ArrayRef<RelTy> Rels); | 91 | void addSectionAux(EhInputSection *S, llvm::ArrayRef<RelTy> Rels); |
| 94 | 92 | ||
| 95 | template <class RelTy> | 93 | template <class ELFT, class RelTy> |
| 96 | CieRecord *addCie(EhSectionPiece &Piece, ArrayRef<RelTy> Rels); | 94 | CieRecord *addCie(EhSectionPiece &Piece, ArrayRef<RelTy> Rels); |
| 97 | 95 | ||
| 98 | template <class RelTy> | 96 | template <class ELFT, class RelTy> |
| 99 | bool isFdeLive(EhSectionPiece &Piece, ArrayRef<RelTy> Rels); | 97 | bool isFdeLive(EhSectionPiece &Piece, ArrayRef<RelTy> Rels); |
| 100 | 98 | ||
| 101 | uint64_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc); | 99 | uint64_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc) const; |
| 102 | 100 | ||
| 103 | std::vector<CieRecord *> Cies; | 101 | std::vector<CieRecord *> CieRecords; |
| 104 | 102 | ||
| 105 | // CIE records are uniquified by their contents and personality functions. | 103 | // CIE records are uniquified by their contents and personality functions. |
| 106 | llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord *> | 104 | llvm::DenseMap<std::pair<ArrayRef<uint8_t>, Symbol *>, CieRecord *> CieMap; |
| 107 | CieMap; | ||
| 108 | }; | 105 | }; |
| 109 | 106 | ||
| 110 | class GotSection : public SyntheticSection { | 107 | class GotSection : public SyntheticSection { |
| ... | @@ -115,11 +112,11 @@ public: | ... | @@ -115,11 +112,11 @@ public: |
| 115 | bool empty() const override; | 112 | bool empty() const override; |
| 116 | void writeTo(uint8_t *Buf) override; | 113 | void writeTo(uint8_t *Buf) override; |
| 117 | 114 | ||
| 118 | void addEntry(SymbolBody &Sym); | 115 | void addEntry(Symbol &Sym); |
| 119 | bool addDynTlsEntry(SymbolBody &Sym); | 116 | bool addDynTlsEntry(Symbol &Sym); |
| 120 | bool addTlsIndex(); | 117 | bool addTlsIndex(); |
| 121 | uint64_t getGlobalDynAddr(const SymbolBody &B) const; | 118 | uint64_t getGlobalDynAddr(const Symbol &B) const; |
| 122 | uint64_t getGlobalDynOffset(const SymbolBody &B) const; | 119 | uint64_t getGlobalDynOffset(const Symbol &B) const; |
| 123 | 120 | ||
| 124 | uint64_t getTlsIndexVA() { return this->getVA() + TlsIndexOff; } | 121 | uint64_t getTlsIndexVA() { return this->getVA() + TlsIndexOff; } |
| 125 | uint32_t getTlsIndexOff() const { return TlsIndexOff; } | 122 | uint32_t getTlsIndexOff() const { return TlsIndexOff; } |
| ... | @@ -159,14 +156,13 @@ private: | ... | @@ -159,14 +156,13 @@ private: |
| 159 | // respectively. | 156 | // respectively. |
| 160 | class BssSection final : public SyntheticSection { | 157 | class BssSection final : public SyntheticSection { |
| 161 | public: | 158 | public: |
| 162 | BssSection(StringRef Name); | 159 | BssSection(StringRef Name, uint64_t Size, uint32_t Alignment); |
| 163 | void writeTo(uint8_t *) override {} | 160 | void writeTo(uint8_t *) override {} |
| 164 | bool empty() const override { return getSize() == 0; } | 161 | bool empty() const override { return getSize() == 0; } |
| 165 | size_t reserveSpace(uint64_t Size, uint32_t Alignment); | ||
| 166 | size_t getSize() const override { return Size; } | 162 | size_t getSize() const override { return Size; } |
| 167 | 163 | ||
| 168 | private: | 164 | static bool classof(const SectionBase *S) { return S->Bss; } |
| 169 | uint64_t Size = 0; | 165 | uint64_t Size; |
| 170 | }; | 166 | }; |
| 171 | 167 | ||
| 172 | class MipsGotSection final : public SyntheticSection { | 168 | class MipsGotSection final : public SyntheticSection { |
| ... | @@ -174,21 +170,21 @@ public: | ... | @@ -174,21 +170,21 @@ public: |
| 174 | MipsGotSection(); | 170 | MipsGotSection(); |
| 175 | void writeTo(uint8_t *Buf) override; | 171 | void writeTo(uint8_t *Buf) override; |
| 176 | size_t getSize() const override { return Size; } | 172 | size_t getSize() const override { return Size; } |
| 177 | void updateAllocSize() override; | 173 | bool updateAllocSize() override; |
| 178 | void finalizeContents() override; | 174 | void finalizeContents() override; |
| 179 | bool empty() const override; | 175 | bool empty() const override; |
| 180 | void addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr); | 176 | void addEntry(Symbol &Sym, int64_t Addend, RelExpr Expr); |
| 181 | bool addDynTlsEntry(SymbolBody &Sym); | 177 | bool addDynTlsEntry(Symbol &Sym); |
| 182 | bool addTlsIndex(); | 178 | bool addTlsIndex(); |
| 183 | uint64_t getPageEntryOffset(const SymbolBody &B, int64_t Addend) const; | 179 | uint64_t getPageEntryOffset(const Symbol &B, int64_t Addend) const; |
| 184 | uint64_t getBodyEntryOffset(const SymbolBody &B, int64_t Addend) const; | 180 | uint64_t getSymEntryOffset(const Symbol &B, int64_t Addend) const; |
| 185 | uint64_t getGlobalDynOffset(const SymbolBody &B) const; | 181 | uint64_t getGlobalDynOffset(const Symbol &B) const; |
| 186 | 182 | ||
| 187 | // Returns the symbol which corresponds to the first entry of the global part | 183 | // Returns the symbol which corresponds to the first entry of the global part |
| 188 | // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic | 184 | // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic |
| 189 | // table properties. | 185 | // table properties. |
| 190 | // Returns nullptr if the global part is empty. | 186 | // Returns nullptr if the global part is empty. |
| 191 | const SymbolBody *getFirstGlobalEntry() const; | 187 | const Symbol *getFirstGlobalEntry() const; |
| 192 | 188 | ||
| 193 | // Returns the number of entries in the local part of GOT including | 189 | // Returns the number of entries in the local part of GOT including |
| 194 | // the number of reserved entries. | 190 | // the number of reserved entries. |
| ... | @@ -248,7 +244,7 @@ private: | ... | @@ -248,7 +244,7 @@ private: |
| 248 | // to the first index of "Page" entries allocated for this section. | 244 | // to the first index of "Page" entries allocated for this section. |
| 249 | llvm::SmallMapVector<const OutputSection *, size_t, 16> PageIndexMap; | 245 | llvm::SmallMapVector<const OutputSection *, size_t, 16> PageIndexMap; |
| 250 | 246 | ||
| 251 | typedef std::pair<const SymbolBody *, uint64_t> GotEntry; | 247 | typedef std::pair<const Symbol *, uint64_t> GotEntry; |
| 252 | typedef std::vector<GotEntry> GotEntries; | 248 | typedef std::vector<GotEntry> GotEntries; |
| 253 | // Map from Symbol-Addend pair to the GOT index. | 249 | // Map from Symbol-Addend pair to the GOT index. |
| 254 | llvm::DenseMap<GotEntry, size_t> EntryIndexMap; | 250 | llvm::DenseMap<GotEntry, size_t> EntryIndexMap; |
| ... | @@ -261,7 +257,7 @@ private: | ... | @@ -261,7 +257,7 @@ private: |
| 261 | GotEntries GlobalEntries; | 257 | GotEntries GlobalEntries; |
| 262 | 258 | ||
| 263 | // TLS entries. | 259 | // TLS entries. |
| 264 | std::vector<const SymbolBody *> TlsEntries; | 260 | std::vector<const Symbol *> TlsEntries; |
| 265 | 261 | ||
| 266 | uint32_t TlsIndexOff = -1; | 262 | uint32_t TlsIndexOff = -1; |
| 267 | uint64_t Size = 0; | 263 | uint64_t Size = 0; |
| ... | @@ -270,13 +266,13 @@ private: | ... | @@ -270,13 +266,13 @@ private: |
| 270 | class GotPltSection final : public SyntheticSection { | 266 | class GotPltSection final : public SyntheticSection { |
| 271 | public: | 267 | public: |
| 272 | GotPltSection(); | 268 | GotPltSection(); |
| 273 | void addEntry(SymbolBody &Sym); | 269 | void addEntry(Symbol &Sym); |
| 274 | size_t getSize() const override; | 270 | size_t getSize() const override; |
| 275 | void writeTo(uint8_t *Buf) override; | 271 | void writeTo(uint8_t *Buf) override; |
| 276 | bool empty() const override { return Entries.empty(); } | 272 | bool empty() const override { return Entries.empty(); } |
| 277 | 273 | ||
| 278 | private: | 274 | private: |
| 279 | std::vector<const SymbolBody *> Entries; | 275 | std::vector<const Symbol *> Entries; |
| 280 | }; | 276 | }; |
| 281 | 277 | ||
| 282 | // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc | 278 | // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc |
| ... | @@ -286,13 +282,13 @@ private: | ... | @@ -286,13 +282,13 @@ private: |
| 286 | class IgotPltSection final : public SyntheticSection { | 282 | class IgotPltSection final : public SyntheticSection { |
| 287 | public: | 283 | public: |
| 288 | IgotPltSection(); | 284 | IgotPltSection(); |
| 289 | void addEntry(SymbolBody &Sym); | 285 | void addEntry(Symbol &Sym); |
| 290 | size_t getSize() const override; | 286 | size_t getSize() const override; |
| 291 | void writeTo(uint8_t *Buf) override; | 287 | void writeTo(uint8_t *Buf) override; |
| 292 | bool empty() const override { return Entries.empty(); } | 288 | bool empty() const override { return Entries.empty(); } |
| 293 | 289 | ||
| 294 | private: | 290 | private: |
| 295 | std::vector<const SymbolBody *> Entries; | 291 | std::vector<const Symbol *> Entries; |
| 296 | }; | 292 | }; |
| 297 | 293 | ||
| 298 | class StringTableSection final : public SyntheticSection { | 294 | class StringTableSection final : public SyntheticSection { |
| ... | @@ -315,8 +311,7 @@ private: | ... | @@ -315,8 +311,7 @@ private: |
| 315 | class DynamicReloc { | 311 | class DynamicReloc { |
| 316 | public: | 312 | public: |
| 317 | DynamicReloc(uint32_t Type, const InputSectionBase *InputSec, | 313 | DynamicReloc(uint32_t Type, const InputSectionBase *InputSec, |
| 318 | uint64_t OffsetInSec, bool UseSymVA, SymbolBody *Sym, | 314 | uint64_t OffsetInSec, bool UseSymVA, Symbol *Sym, int64_t Addend) |
| 319 | int64_t Addend) | ||
| 320 | : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec), | 315 | : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec), |
| 321 | UseSymVA(UseSymVA), Addend(Addend) {} | 316 | UseSymVA(UseSymVA), Addend(Addend) {} |
| 322 | 317 | ||
| ... | @@ -328,7 +323,7 @@ public: | ... | @@ -328,7 +323,7 @@ public: |
| 328 | uint32_t Type; | 323 | uint32_t Type; |
| 329 | 324 | ||
| 330 | private: | 325 | private: |
| 331 | SymbolBody *Sym; | 326 | Symbol *Sym; |
| 332 | const InputSectionBase *InputSec = nullptr; | 327 | const InputSectionBase *InputSec = nullptr; |
| 333 | uint64_t OffsetInSec; | 328 | uint64_t OffsetInSec; |
| 334 | bool UseSymVA; | 329 | bool UseSymVA; |
| ... | @@ -342,30 +337,8 @@ template <class ELFT> class DynamicSection final : public SyntheticSection { | ... | @@ -342,30 +337,8 @@ template <class ELFT> class DynamicSection final : public SyntheticSection { |
| 342 | typedef typename ELFT::Shdr Elf_Shdr; | 337 | typedef typename ELFT::Shdr Elf_Shdr; |
| 343 | typedef typename ELFT::Sym Elf_Sym; | 338 | typedef typename ELFT::Sym Elf_Sym; |
| 344 | 339 | ||
| 345 | // The .dynamic section contains information for the dynamic linker. | ||
| 346 | // The section consists of fixed size entries, which consist of | ||
| 347 | // type and value fields. Value are one of plain integers, symbol | ||
| 348 | // addresses, or section addresses. This struct represents the entry. | ||
| 349 | struct Entry { | ||
| 350 | int32_t Tag; | ||
| 351 | union { | ||
| 352 | OutputSection *OutSec; | ||
| 353 | InputSection *InSec; | ||
| 354 | uint64_t Val; | ||
| 355 | const SymbolBody *Sym; | ||
| 356 | }; | ||
| 357 | enum KindT { SecAddr, SecSize, SymAddr, PlainInt, InSecAddr } Kind; | ||
| 358 | Entry(int32_t Tag, OutputSection *OutSec, KindT Kind = SecAddr) | ||
| 359 | : Tag(Tag), OutSec(OutSec), Kind(Kind) {} | ||
| 360 | Entry(int32_t Tag, InputSection *Sec) | ||
| 361 | : Tag(Tag), InSec(Sec), Kind(InSecAddr) {} | ||
| 362 | Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {} | ||
| 363 | Entry(int32_t Tag, const SymbolBody *Sym) | ||
| 364 | : Tag(Tag), Sym(Sym), Kind(SymAddr) {} | ||
| 365 | }; | ||
| 366 | |||
| 367 | // finalizeContents() fills this vector with the section contents. | 340 | // finalizeContents() fills this vector with the section contents. |
| 368 | std::vector<Entry> Entries; | 341 | std::vector<std::pair<int32_t, std::function<uint64_t()>>> Entries; |
| 369 | 342 | ||
| 370 | public: | 343 | public: |
| 371 | DynamicSection(); | 344 | DynamicSection(); |
| ... | @@ -374,33 +347,66 @@ public: | ... | @@ -374,33 +347,66 @@ public: |
| 374 | size_t getSize() const override { return Size; } | 347 | size_t getSize() const override { return Size; } |
| 375 | 348 | ||
| 376 | private: | 349 | private: |
| 377 | void addEntries(); | 350 | void add(int32_t Tag, std::function<uint64_t()> Fn); |
| 378 | void add(Entry E) { Entries.push_back(E); } | 351 | void addInt(int32_t Tag, uint64_t Val); |
| 352 | void addInSec(int32_t Tag, InputSection *Sec); | ||
| 353 | void addOutSec(int32_t Tag, OutputSection *Sec); | ||
| 354 | void addSize(int32_t Tag, OutputSection *Sec); | ||
| 355 | void addSym(int32_t Tag, Symbol *Sym); | ||
| 356 | |||
| 379 | uint64_t Size = 0; | 357 | uint64_t Size = 0; |
| 380 | }; | 358 | }; |
| 381 | 359 | ||
| 382 | template <class ELFT> class RelocationSection final : public SyntheticSection { | 360 | class RelocationBaseSection : public SyntheticSection { |
| 361 | public: | ||
| 362 | RelocationBaseSection(StringRef Name, uint32_t Type, int32_t DynamicTag, | ||
| 363 | int32_t SizeDynamicTag); | ||
| 364 | void addReloc(const DynamicReloc &Reloc); | ||
| 365 | bool empty() const override { return Relocs.empty(); } | ||
| 366 | size_t getSize() const override { return Relocs.size() * this->Entsize; } | ||
| 367 | size_t getRelativeRelocCount() const { return NumRelativeRelocs; } | ||
| 368 | void finalizeContents() override; | ||
| 369 | int32_t DynamicTag, SizeDynamicTag; | ||
| 370 | |||
| 371 | protected: | ||
| 372 | std::vector<DynamicReloc> Relocs; | ||
| 373 | size_t NumRelativeRelocs = 0; | ||
| 374 | }; | ||
| 375 | |||
| 376 | template <class ELFT> | ||
| 377 | class RelocationSection final : public RelocationBaseSection { | ||
| 383 | typedef typename ELFT::Rel Elf_Rel; | 378 | typedef typename ELFT::Rel Elf_Rel; |
| 384 | typedef typename ELFT::Rela Elf_Rela; | 379 | typedef typename ELFT::Rela Elf_Rela; |
| 385 | 380 | ||
| 386 | public: | 381 | public: |
| 387 | RelocationSection(StringRef Name, bool Sort); | 382 | RelocationSection(StringRef Name, bool Sort); |
| 388 | void addReloc(const DynamicReloc &Reloc); | ||
| 389 | unsigned getRelocOffset(); | 383 | unsigned getRelocOffset(); |
| 390 | void finalizeContents() override; | ||
| 391 | void writeTo(uint8_t *Buf) override; | 384 | void writeTo(uint8_t *Buf) override; |
| 392 | bool empty() const override { return Relocs.empty(); } | ||
| 393 | size_t getSize() const override { return Relocs.size() * this->Entsize; } | ||
| 394 | size_t getRelativeRelocCount() const { return NumRelativeRelocs; } | ||
| 395 | 385 | ||
| 396 | private: | 386 | private: |
| 397 | bool Sort; | 387 | bool Sort; |
| 398 | size_t NumRelativeRelocs = 0; | 388 | }; |
| 399 | std::vector<DynamicReloc> Relocs; | 389 | |
| 390 | template <class ELFT> | ||
| 391 | class AndroidPackedRelocationSection final : public RelocationBaseSection { | ||
| 392 | typedef typename ELFT::Rel Elf_Rel; | ||
| 393 | typedef typename ELFT::Rela Elf_Rela; | ||
| 394 | |||
| 395 | public: | ||
| 396 | AndroidPackedRelocationSection(StringRef Name); | ||
| 397 | |||
| 398 | bool updateAllocSize() override; | ||
| 399 | size_t getSize() const override { return RelocData.size(); } | ||
| 400 | void writeTo(uint8_t *Buf) override { | ||
| 401 | memcpy(Buf, RelocData.data(), RelocData.size()); | ||
| 402 | } | ||
| 403 | |||
| 404 | private: | ||
| 405 | SmallVector<char, 0> RelocData; | ||
| 400 | }; | 406 | }; |
| 401 | 407 | ||
| 402 | struct SymbolTableEntry { | 408 | struct SymbolTableEntry { |
| 403 | SymbolBody *Symbol; | 409 | Symbol *Sym; |
| 404 | size_t StrTabOffset; | 410 | size_t StrTabOffset; |
| 405 | }; | 411 | }; |
| 406 | 412 | ||
| ... | @@ -410,9 +416,9 @@ public: | ... | @@ -410,9 +416,9 @@ public: |
| 410 | void finalizeContents() override; | 416 | void finalizeContents() override; |
| 411 | void postThunkContents() override; | 417 | void postThunkContents() override; |
| 412 | size_t getSize() const override { return getNumSymbols() * Entsize; } | 418 | size_t getSize() const override { return getNumSymbols() * Entsize; } |
| 413 | void addSymbol(SymbolBody *Body); | 419 | void addSymbol(Symbol *Sym); |
| 414 | unsigned getNumSymbols() const { return Symbols.size() + 1; } | 420 | unsigned getNumSymbols() const { return Symbols.size() + 1; } |
| 415 | size_t getSymbolIndex(SymbolBody *Body); | 421 | size_t getSymbolIndex(Symbol *Sym); |
| 416 | ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; } | 422 | ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; } |
| 417 | 423 | ||
| 418 | protected: | 424 | protected: |
| ... | @@ -420,6 +426,10 @@ protected: | ... | @@ -420,6 +426,10 @@ protected: |
| 420 | std::vector<SymbolTableEntry> Symbols; | 426 | std::vector<SymbolTableEntry> Symbols; |
| 421 | 427 | ||
| 422 | StringTableSection &StrTabSec; | 428 | StringTableSection &StrTabSec; |
| 429 | |||
| 430 | llvm::once_flag OnceFlag; | ||
| 431 | llvm::DenseMap<Symbol *, size_t> SymbolIndexMap; | ||
| 432 | llvm::DenseMap<OutputSection *, size_t> SectionIndexMap; | ||
| 423 | }; | 433 | }; |
| 424 | 434 | ||
| 425 | template <class ELFT> | 435 | template <class ELFT> |
| ... | @@ -451,9 +461,10 @@ private: | ... | @@ -451,9 +461,10 @@ private: |
| 451 | void writeHashTable(uint8_t *Buf); | 461 | void writeHashTable(uint8_t *Buf); |
| 452 | 462 | ||
| 453 | struct Entry { | 463 | struct Entry { |
| 454 | SymbolBody *Body; | 464 | Symbol *Sym; |
| 455 | size_t StrTabOffset; | 465 | size_t StrTabOffset; |
| 456 | uint32_t Hash; | 466 | uint32_t Hash; |
| 467 | uint32_t BucketIdx; | ||
| 457 | }; | 468 | }; |
| 458 | 469 | ||
| 459 | std::vector<Entry> Symbols; | 470 | std::vector<Entry> Symbols; |
| ... | @@ -462,7 +473,7 @@ private: | ... | @@ -462,7 +473,7 @@ private: |
| 462 | size_t Size = 0; | 473 | size_t Size = 0; |
| 463 | }; | 474 | }; |
| 464 | 475 | ||
| 465 | template <class ELFT> class HashTableSection final : public SyntheticSection { | 476 | class HashTableSection final : public SyntheticSection { |
| 466 | public: | 477 | public: |
| 467 | HashTableSection(); | 478 | HashTableSection(); |
| 468 | void finalizeContents() override; | 479 | void finalizeContents() override; |
| ... | @@ -485,57 +496,81 @@ public: | ... | @@ -485,57 +496,81 @@ public: |
| 485 | bool empty() const override { return Entries.empty(); } | 496 | bool empty() const override { return Entries.empty(); } |
| 486 | void addSymbols(); | 497 | void addSymbols(); |
| 487 | 498 | ||
| 488 | template <class ELFT> void addEntry(SymbolBody &Sym); | 499 | template <class ELFT> void addEntry(Symbol &Sym); |
| 489 | 500 | ||
| 490 | private: | 501 | private: |
| 491 | void writeHeader(uint8_t *Buf){}; | ||
| 492 | void addHeaderSymbols(){}; | ||
| 493 | unsigned getPltRelocOff() const; | 502 | unsigned getPltRelocOff() const; |
| 494 | std::vector<std::pair<const SymbolBody *, unsigned>> Entries; | 503 | std::vector<std::pair<const Symbol *, unsigned>> Entries; |
| 495 | // Iplt always has HeaderSize of 0, the Plt HeaderSize is always non-zero | 504 | // Iplt always has HeaderSize of 0, the Plt HeaderSize is always non-zero |
| 496 | size_t HeaderSize; | 505 | size_t HeaderSize; |
| 497 | }; | 506 | }; |
| 498 | 507 | ||
| 499 | class GdbIndexSection final : public SyntheticSection { | 508 | // GdbIndexChunk is created for each .debug_info section and contains |
| 500 | const unsigned OffsetTypeSize = 4; | 509 | // information to create a part of .gdb_index for a given input section. |
| 501 | const unsigned CuListOffset = 6 * OffsetTypeSize; | 510 | struct GdbIndexChunk { |
| 502 | const unsigned CompilationUnitSize = 16; | 511 | struct AddressEntry { |
| 503 | const unsigned AddressEntrySize = 16 + OffsetTypeSize; | 512 | InputSection *Section; |
| 504 | const unsigned SymTabEntrySize = 2 * OffsetTypeSize; | 513 | uint64_t LowAddress; |
| 514 | uint64_t HighAddress; | ||
| 515 | uint32_t CuIndex; | ||
| 516 | }; | ||
| 517 | |||
| 518 | struct CuEntry { | ||
| 519 | uint64_t CuOffset; | ||
| 520 | uint64_t CuLength; | ||
| 521 | }; | ||
| 505 | 522 | ||
| 523 | struct NameTypeEntry { | ||
| 524 | llvm::CachedHashStringRef Name; | ||
| 525 | uint8_t Type; | ||
| 526 | }; | ||
| 527 | |||
| 528 | InputSection *DebugInfoSec; | ||
| 529 | std::vector<AddressEntry> AddressAreas; | ||
| 530 | std::vector<CuEntry> CompilationUnits; | ||
| 531 | std::vector<NameTypeEntry> NamesAndTypes; | ||
| 532 | }; | ||
| 533 | |||
| 534 | // The symbol type for the .gdb_index section. | ||
| 535 | struct GdbSymbol { | ||
| 536 | uint32_t NameHash; | ||
| 537 | size_t NameOffset; | ||
| 538 | size_t CuVectorIndex; | ||
| 539 | }; | ||
| 540 | |||
| 541 | class GdbIndexSection final : public SyntheticSection { | ||
| 506 | public: | 542 | public: |
| 507 | GdbIndexSection(std::vector<GdbIndexChunk> &&Chunks); | 543 | GdbIndexSection(std::vector<GdbIndexChunk> &&Chunks); |
| 508 | void finalizeContents() override; | ||
| 509 | void writeTo(uint8_t *Buf) override; | 544 | void writeTo(uint8_t *Buf) override; |
| 510 | size_t getSize() const override; | 545 | size_t getSize() const override; |
| 511 | bool empty() const override; | 546 | bool empty() const override; |
| 512 | 547 | ||
| 513 | // Symbol table is a hash table for types and names. | 548 | private: |
| 514 | // It is the area of gdb index. | 549 | void fixCuIndex(); |
| 515 | GdbHashTab SymbolTable; | 550 | std::vector<std::vector<uint32_t>> createCuVectors(); |
| 551 | std::vector<GdbSymbol *> createGdbSymtab(); | ||
| 552 | |||
| 553 | // A symbol table for this .gdb_index section. | ||
| 554 | std::vector<GdbSymbol *> GdbSymtab; | ||
| 516 | 555 | ||
| 517 | // CU vector is a part of constant pool area of section. | 556 | // CU vector is a part of constant pool area of section. |
| 518 | std::vector<std::set<uint32_t>> CuVectors; | 557 | std::vector<std::vector<uint32_t>> CuVectors; |
| 519 | 558 | ||
| 520 | // String pool is also a part of constant pool, it follows CU vectors. | 559 | // Symbol table contents. |
| 521 | llvm::StringTableBuilder StringPool; | 560 | llvm::DenseMap<llvm::CachedHashStringRef, GdbSymbol *> Symbols; |
| 522 | 561 | ||
| 523 | // Each chunk contains information gathered from a debug sections of single | 562 | // Each chunk contains information gathered from a debug sections of single |
| 524 | // object and used to build different areas of gdb index. | 563 | // object and used to build different areas of gdb index. |
| 525 | std::vector<GdbIndexChunk> Chunks; | 564 | std::vector<GdbIndexChunk> Chunks; |
| 526 | 565 | ||
| 527 | private: | 566 | static constexpr uint32_t CuListOffset = 24; |
| 528 | void buildIndex(); | ||
| 529 | |||
| 530 | uint32_t CuTypesOffset; | 567 | uint32_t CuTypesOffset; |
| 531 | uint32_t SymTabOffset; | 568 | uint32_t SymtabOffset; |
| 532 | uint32_t ConstantPoolOffset; | 569 | uint32_t ConstantPoolOffset; |
| 533 | uint32_t StringPoolOffset; | 570 | uint32_t StringPoolOffset; |
| 571 | uint32_t StringPoolSize; | ||
| 534 | 572 | ||
| 535 | size_t CuVectorsSize = 0; | 573 | std::vector<size_t> CuVectorOffsets; |
| 536 | std::vector<size_t> CuVectorsOffset; | ||
| 537 | |||
| 538 | bool Finalized = false; | ||
| 539 | }; | 574 | }; |
| 540 | 575 | ||
| 541 | template <class ELFT> GdbIndexSection *createGdbIndex(); | 576 | template <class ELFT> GdbIndexSection *createGdbIndex(); |
| ... | @@ -549,21 +584,12 @@ template <class ELFT> GdbIndexSection *createGdbIndex(); | ... | @@ -549,21 +584,12 @@ template <class ELFT> GdbIndexSection *createGdbIndex(); |
| 549 | // Detailed info about internals can be found in Ian Lance Taylor's blog: | 584 | // Detailed info about internals can be found in Ian Lance Taylor's blog: |
| 550 | // http://www.airs.com/blog/archives/460 (".eh_frame") | 585 | // http://www.airs.com/blog/archives/460 (".eh_frame") |
| 551 | // http://www.airs.com/blog/archives/462 (".eh_frame_hdr") | 586 | // http://www.airs.com/blog/archives/462 (".eh_frame_hdr") |
| 552 | template <class ELFT> class EhFrameHeader final : public SyntheticSection { | 587 | class EhFrameHeader final : public SyntheticSection { |
| 553 | public: | 588 | public: |
| 554 | EhFrameHeader(); | 589 | EhFrameHeader(); |
| 555 | void writeTo(uint8_t *Buf) override; | 590 | void writeTo(uint8_t *Buf) override; |
| 556 | size_t getSize() const override; | 591 | size_t getSize() const override; |
| 557 | void addFde(uint32_t Pc, uint32_t FdeVA); | ||
| 558 | bool empty() const override; | 592 | bool empty() const override; |
| 559 | |||
| 560 | private: | ||
| 561 | struct FdeData { | ||
| 562 | uint32_t Pc; | ||
| 563 | uint32_t FdeVA; | ||
| 564 | }; | ||
| 565 | |||
| 566 | std::vector<FdeData> Fdes; | ||
| 567 | }; | 593 | }; |
| 568 | 594 | ||
| 569 | // For more information about .gnu.version and .gnu.version_r see: | 595 | // For more information about .gnu.version and .gnu.version_r see: |
| ... | @@ -639,22 +665,58 @@ public: | ... | @@ -639,22 +665,58 @@ public: |
| 639 | // with different attributes in a single output sections. To do that | 665 | // with different attributes in a single output sections. To do that |
| 640 | // we put them into MergeSyntheticSection synthetic input sections which are | 666 | // we put them into MergeSyntheticSection synthetic input sections which are |
| 641 | // attached to regular output sections. | 667 | // attached to regular output sections. |
| 642 | class MergeSyntheticSection final : public SyntheticSection { | 668 | class MergeSyntheticSection : public SyntheticSection { |
| 643 | public: | 669 | public: |
| 644 | MergeSyntheticSection(StringRef Name, uint32_t Type, uint64_t Flags, | ||
| 645 | uint32_t Alignment); | ||
| 646 | void addSection(MergeInputSection *MS); | 670 | void addSection(MergeInputSection *MS); |
| 671 | |||
| 672 | protected: | ||
| 673 | MergeSyntheticSection(StringRef Name, uint32_t Type, uint64_t Flags, | ||
| 674 | uint32_t Alignment) | ||
| 675 | : SyntheticSection(Flags, Type, Alignment, Name) {} | ||
| 676 | |||
| 677 | std::vector<MergeInputSection *> Sections; | ||
| 678 | }; | ||
| 679 | |||
| 680 | class MergeTailSection final : public MergeSyntheticSection { | ||
| 681 | public: | ||
| 682 | MergeTailSection(StringRef Name, uint32_t Type, uint64_t Flags, | ||
| 683 | uint32_t Alignment); | ||
| 684 | |||
| 685 | size_t getSize() const override; | ||
| 647 | void writeTo(uint8_t *Buf) override; | 686 | void writeTo(uint8_t *Buf) override; |
| 648 | void finalizeContents() override; | 687 | void finalizeContents() override; |
| 649 | bool shouldTailMerge() const; | ||
| 650 | size_t getSize() const override; | ||
| 651 | 688 | ||
| 652 | private: | 689 | private: |
| 653 | void finalizeTailMerge(); | ||
| 654 | void finalizeNoTailMerge(); | ||
| 655 | |||
| 656 | llvm::StringTableBuilder Builder; | 690 | llvm::StringTableBuilder Builder; |
| 657 | std::vector<MergeInputSection *> Sections; | 691 | }; |
| 692 | |||
| 693 | class MergeNoTailSection final : public MergeSyntheticSection { | ||
| 694 | public: | ||
| 695 | MergeNoTailSection(StringRef Name, uint32_t Type, uint64_t Flags, | ||
| 696 | uint32_t Alignment) | ||
| 697 | : MergeSyntheticSection(Name, Type, Flags, Alignment) {} | ||
| 698 | |||
| 699 | size_t getSize() const override { return Size; } | ||
| 700 | void writeTo(uint8_t *Buf) override; | ||
| 701 | void finalizeContents() override; | ||
| 702 | |||
| 703 | private: | ||
| 704 | // We use the most significant bits of a hash as a shard ID. | ||
| 705 | // The reason why we don't want to use the least significant bits is | ||
| 706 | // because DenseMap also uses lower bits to determine a bucket ID. | ||
| 707 | // If we use lower bits, it significantly increases the probability of | ||
| 708 | // hash collisons. | ||
| 709 | size_t getShardId(uint32_t Hash) { | ||
| 710 | return Hash >> (32 - llvm::countTrailingZeros(NumShards)); | ||
| 711 | } | ||
| 712 | |||
| 713 | // Section size | ||
| 714 | size_t Size; | ||
| 715 | |||
| 716 | // String table contents | ||
| 717 | constexpr static size_t NumShards = 32; | ||
| 718 | std::vector<llvm::StringTableBuilder> Shards; | ||
| 719 | size_t ShardOffsets[NumShards]; | ||
| 658 | }; | 720 | }; |
| 659 | 721 | ||
| 660 | // .MIPS.abiflags section. | 722 | // .MIPS.abiflags section. |
| ... | @@ -723,6 +785,9 @@ public: | ... | @@ -723,6 +785,9 @@ public: |
| 723 | ARMExidxSentinelSection(); | 785 | ARMExidxSentinelSection(); |
| 724 | size_t getSize() const override { return 8; } | 786 | size_t getSize() const override { return 8; } |
| 725 | void writeTo(uint8_t *Buf) override; | 787 | void writeTo(uint8_t *Buf) override; |
| 788 | bool empty() const override; | ||
| 789 | |||
| 790 | InputSection *Highest = 0; | ||
| 726 | }; | 791 | }; |
| 727 | 792 | ||
| 728 | // A container for one or more linker generated thunks. Instances of these | 793 | // A container for one or more linker generated thunks. Instances of these |
| ... | @@ -746,13 +811,13 @@ private: | ... | @@ -746,13 +811,13 @@ private: |
| 746 | size_t Size = 0; | 811 | size_t Size = 0; |
| 747 | }; | 812 | }; |
| 748 | 813 | ||
| 749 | template <class ELFT> InputSection *createCommonSection(); | ||
| 750 | InputSection *createInterpSection(); | 814 | InputSection *createInterpSection(); |
| 751 | template <class ELFT> MergeInputSection *createCommentSection(); | 815 | MergeInputSection *createCommentSection(); |
| 752 | void decompressAndMergeSections(); | 816 | void decompressSections(); |
| 817 | void mergeSections(); | ||
| 753 | 818 | ||
| 754 | SymbolBody *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, | 819 | Symbol *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, |
| 755 | uint64_t Size, InputSectionBase *Section); | 820 | uint64_t Size, InputSectionBase &Section); |
| 756 | 821 | ||
| 757 | // Linker generated sections which can be used as inputs. | 822 | // Linker generated sections which can be used as inputs. |
| 758 | struct InX { | 823 | struct InX { |
| ... | @@ -760,11 +825,13 @@ struct InX { | ... | @@ -760,11 +825,13 @@ struct InX { |
| 760 | static BssSection *Bss; | 825 | static BssSection *Bss; |
| 761 | static BssSection *BssRelRo; | 826 | static BssSection *BssRelRo; |
| 762 | static BuildIdSection *BuildId; | 827 | static BuildIdSection *BuildId; |
| 763 | static InputSection *Common; | 828 | static EhFrameHeader *EhFrameHdr; |
| 829 | static EhFrameSection *EhFrame; | ||
| 764 | static SyntheticSection *Dynamic; | 830 | static SyntheticSection *Dynamic; |
| 765 | static StringTableSection *DynStrTab; | 831 | static StringTableSection *DynStrTab; |
| 766 | static SymbolTableBaseSection *DynSymTab; | 832 | static SymbolTableBaseSection *DynSymTab; |
| 767 | static GnuHashTableSection *GnuHashTab; | 833 | static GnuHashTableSection *GnuHashTab; |
| 834 | static HashTableSection *HashTab; | ||
| 768 | static InputSection *Interp; | 835 | static InputSection *Interp; |
| 769 | static GdbIndexSection *GdbIndex; | 836 | static GdbIndexSection *GdbIndex; |
| 770 | static GotSection *Got; | 837 | static GotSection *Got; |
| ... | @@ -774,29 +841,20 @@ struct InX { | ... | @@ -774,29 +841,20 @@ struct InX { |
| 774 | static MipsRldMapSection *MipsRldMap; | 841 | static MipsRldMapSection *MipsRldMap; |
| 775 | static PltSection *Plt; | 842 | static PltSection *Plt; |
| 776 | static PltSection *Iplt; | 843 | static PltSection *Iplt; |
| 844 | static RelocationBaseSection *RelaDyn; | ||
| 845 | static RelocationBaseSection *RelaPlt; | ||
| 846 | static RelocationBaseSection *RelaIplt; | ||
| 777 | static StringTableSection *ShStrTab; | 847 | static StringTableSection *ShStrTab; |
| 778 | static StringTableSection *StrTab; | 848 | static StringTableSection *StrTab; |
| 779 | static SymbolTableBaseSection *SymTab; | 849 | static SymbolTableBaseSection *SymTab; |
| 780 | }; | 850 | }; |
| 781 | 851 | ||
| 782 | template <class ELFT> struct In : public InX { | 852 | template <class ELFT> struct In { |
| 783 | static EhFrameHeader<ELFT> *EhFrameHdr; | ||
| 784 | static EhFrameSection<ELFT> *EhFrame; | ||
| 785 | static HashTableSection<ELFT> *HashTab; | ||
| 786 | static RelocationSection<ELFT> *RelaDyn; | ||
| 787 | static RelocationSection<ELFT> *RelaPlt; | ||
| 788 | static RelocationSection<ELFT> *RelaIplt; | ||
| 789 | static VersionDefinitionSection<ELFT> *VerDef; | 853 | static VersionDefinitionSection<ELFT> *VerDef; |
| 790 | static VersionTableSection<ELFT> *VerSym; | 854 | static VersionTableSection<ELFT> *VerSym; |
| 791 | static VersionNeedSection<ELFT> *VerNeed; | 855 | static VersionNeedSection<ELFT> *VerNeed; |
| 792 | }; | 856 | }; |
| 793 | 857 | ||
| 794 | template <class ELFT> EhFrameHeader<ELFT> *In<ELFT>::EhFrameHdr; | ||
| 795 | template <class ELFT> EhFrameSection<ELFT> *In<ELFT>::EhFrame; | ||
| 796 | template <class ELFT> HashTableSection<ELFT> *In<ELFT>::HashTab; | ||
| 797 | template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaDyn; | ||
| 798 | template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaPlt; | ||
| 799 | template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaIplt; | ||
| 800 | template <class ELFT> VersionDefinitionSection<ELFT> *In<ELFT>::VerDef; | 858 | template <class ELFT> VersionDefinitionSection<ELFT> *In<ELFT>::VerDef; |
| 801 | template <class ELFT> VersionTableSection<ELFT> *In<ELFT>::VerSym; | 859 | template <class ELFT> VersionTableSection<ELFT> *In<ELFT>::VerSym; |
| 802 | template <class ELFT> VersionNeedSection<ELFT> *In<ELFT>::VerNeed; | 860 | template <class ELFT> VersionNeedSection<ELFT> *In<ELFT>::VerNeed; |
deps/lld/ELF/Target.cpp+21-15| ... | @@ -25,11 +25,11 @@ | ... | @@ -25,11 +25,11 @@ |
| 25 | //===----------------------------------------------------------------------===// | 25 | //===----------------------------------------------------------------------===// |
| 26 | 26 | ||
| 27 | #include "Target.h" | 27 | #include "Target.h" |
| 28 | #include "Error.h" | ||
| 29 | #include "InputFiles.h" | 28 | #include "InputFiles.h" |
| 30 | #include "OutputSections.h" | 29 | #include "OutputSections.h" |
| 31 | #include "SymbolTable.h" | 30 | #include "SymbolTable.h" |
| 32 | #include "Symbols.h" | 31 | #include "Symbols.h" |
| 32 | #include "lld/Common/ErrorHandler.h" | ||
| 33 | #include "llvm/Object/ELF.h" | 33 | #include "llvm/Object/ELF.h" |
| 34 | 34 | ||
| 35 | using namespace llvm; | 35 | using namespace llvm; |
| ... | @@ -40,7 +40,7 @@ using namespace lld::elf; | ... | @@ -40,7 +40,7 @@ using namespace lld::elf; |
| 40 | 40 | ||
| 41 | TargetInfo *elf::Target; | 41 | TargetInfo *elf::Target; |
| 42 | 42 | ||
| 43 | std::string lld::toString(uint32_t Type) { | 43 | std::string lld::toString(RelType Type) { |
| 44 | StringRef S = getELFRelocationTypeName(elf::Config->EMachine, Type); | 44 | StringRef S = getELFRelocationTypeName(elf::Config->EMachine, Type); |
| 45 | if (S == "Unknown") | 45 | if (S == "Unknown") |
| 46 | return ("Unknown (" + Twine(Type) + ")").str(); | 46 | return ("Unknown (" + Twine(Type) + ")").str(); |
| ... | @@ -89,7 +89,7 @@ TargetInfo *elf::getTarget() { | ... | @@ -89,7 +89,7 @@ TargetInfo *elf::getTarget() { |
| 89 | 89 | ||
| 90 | template <class ELFT> static std::string getErrorLoc(const uint8_t *Loc) { | 90 | template <class ELFT> static std::string getErrorLoc(const uint8_t *Loc) { |
| 91 | for (InputSectionBase *D : InputSections) { | 91 | for (InputSectionBase *D : InputSections) { |
| 92 | auto *IS = dyn_cast_or_null<InputSection>(D); | 92 | auto *IS = dyn_cast<InputSection>(D); |
| 93 | if (!IS || !IS->getParent()) | 93 | if (!IS || !IS->getParent()) |
| 94 | continue; | 94 | continue; |
| 95 | 95 | ||
| ... | @@ -117,27 +117,26 @@ std::string elf::getErrorLocation(const uint8_t *Loc) { | ... | @@ -117,27 +117,26 @@ std::string elf::getErrorLocation(const uint8_t *Loc) { |
| 117 | 117 | ||
| 118 | TargetInfo::~TargetInfo() {} | 118 | TargetInfo::~TargetInfo() {} |
| 119 | 119 | ||
| 120 | int64_t TargetInfo::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { | 120 | int64_t TargetInfo::getImplicitAddend(const uint8_t *Buf, RelType Type) const { |
| 121 | return 0; | 121 | return 0; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; } | 124 | bool TargetInfo::usesOnlyLowPageBits(RelType Type) const { return false; } |
| 125 | 125 | ||
| 126 | bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType, | 126 | bool TargetInfo::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 127 | const InputFile *File, const SymbolBody &S) const { | 127 | uint64_t BranchAddr, const Symbol &S) const { |
| 128 | return false; | 128 | return false; |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | bool TargetInfo::inBranchRange(uint32_t RelocType, uint64_t Src, | 131 | bool TargetInfo::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { |
| 132 | uint64_t Dst) const { | ||
| 133 | return true; | 132 | return true; |
| 134 | } | 133 | } |
| 135 | 134 | ||
| 136 | void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const { | 135 | void TargetInfo::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { |
| 137 | writeGotPlt(Buf, S); | 136 | writeGotPlt(Buf, S); |
| 138 | } | 137 | } |
| 139 | 138 | ||
| 140 | RelExpr TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | 139 | RelExpr TargetInfo::adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 141 | RelExpr Expr) const { | 140 | RelExpr Expr) const { |
| 142 | return Expr; | 141 | return Expr; |
| 143 | } | 142 | } |
| ... | @@ -146,22 +145,29 @@ void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const { | ... | @@ -146,22 +145,29 @@ void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const { |
| 146 | llvm_unreachable("Should not have claimed to be relaxable"); | 145 | llvm_unreachable("Should not have claimed to be relaxable"); |
| 147 | } | 146 | } |
| 148 | 147 | ||
| 149 | void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, | 148 | void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, RelType Type, |
| 150 | uint64_t Val) const { | 149 | uint64_t Val) const { |
| 151 | llvm_unreachable("Should not have claimed to be relaxable"); | 150 | llvm_unreachable("Should not have claimed to be relaxable"); |
| 152 | } | 151 | } |
| 153 | 152 | ||
| 154 | void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, | 153 | void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, RelType Type, |
| 155 | uint64_t Val) const { | 154 | uint64_t Val) const { |
| 156 | llvm_unreachable("Should not have claimed to be relaxable"); | 155 | llvm_unreachable("Should not have claimed to be relaxable"); |
| 157 | } | 156 | } |
| 158 | 157 | ||
| 159 | void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, | 158 | void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, RelType Type, |
| 160 | uint64_t Val) const { | 159 | uint64_t Val) const { |
| 161 | llvm_unreachable("Should not have claimed to be relaxable"); | 160 | llvm_unreachable("Should not have claimed to be relaxable"); |
| 162 | } | 161 | } |
| 163 | 162 | ||
| 164 | void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, | 163 | void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, RelType Type, |
| 165 | uint64_t Val) const { | 164 | uint64_t Val) const { |
| 166 | llvm_unreachable("Should not have claimed to be relaxable"); | 165 | llvm_unreachable("Should not have claimed to be relaxable"); |
| 167 | } | 166 | } |
| 167 | |||
| 168 | uint64_t TargetInfo::getImageBase() { | ||
| 169 | // Use -image-base if set. Fall back to the target default if not. | ||
| 170 | if (Config->ImageBase) | ||
| 171 | return *Config->ImageBase; | ||
| 172 | return Config->Pic ? 0 : DefaultImageBase; | ||
| 173 | } |
deps/lld/ELF/Target.h+69-46| ... | @@ -10,25 +10,27 @@ | ... | @@ -10,25 +10,27 @@ |
| 10 | #ifndef LLD_ELF_TARGET_H | 10 | #ifndef LLD_ELF_TARGET_H |
| 11 | #define LLD_ELF_TARGET_H | 11 | #define LLD_ELF_TARGET_H |
| 12 | 12 | ||
| 13 | #include "Error.h" | ||
| 14 | #include "InputSection.h" | 13 | #include "InputSection.h" |
| 14 | #include "lld/Common/ErrorHandler.h" | ||
| 15 | #include "llvm/Object/ELF.h" | 15 | #include "llvm/Object/ELF.h" |
| 16 | 16 | ||
| 17 | namespace lld { | 17 | namespace lld { |
| 18 | std::string toString(uint32_t RelType); | 18 | std::string toString(elf::RelType Type); |
| 19 | 19 | ||
| 20 | namespace elf { | 20 | namespace elf { |
| 21 | class Defined; | ||
| 21 | class InputFile; | 22 | class InputFile; |
| 22 | class SymbolBody; | 23 | class Symbol; |
| 23 | 24 | ||
| 24 | class TargetInfo { | 25 | class TargetInfo { |
| 25 | public: | 26 | public: |
| 26 | virtual bool isPicRel(uint32_t Type) const { return true; } | 27 | virtual uint32_t calcEFlags() const { return 0; } |
| 27 | virtual uint32_t getDynRel(uint32_t Type) const { return Type; } | 28 | virtual bool isPicRel(RelType Type) const { return true; } |
| 29 | virtual RelType getDynRel(RelType Type) const { return Type; } | ||
| 28 | virtual void writeGotPltHeader(uint8_t *Buf) const {} | 30 | virtual void writeGotPltHeader(uint8_t *Buf) const {} |
| 29 | virtual void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {}; | 31 | virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {}; |
| 30 | virtual void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const; | 32 | virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const; |
| 31 | virtual int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const; | 33 | virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const; |
| 32 | 34 | ||
| 33 | // If lazy binding is supported, the first entry of the PLT has code | 35 | // If lazy binding is supported, the first entry of the PLT has code |
| 34 | // to call the dynamic linker to resolve PLT entries the first time | 36 | // to call the dynamic linker to resolve PLT entries the first time |
| ... | @@ -38,50 +40,54 @@ public: | ... | @@ -38,50 +40,54 @@ public: |
| 38 | virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, | 40 | virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, |
| 39 | uint64_t PltEntryAddr, int32_t Index, | 41 | uint64_t PltEntryAddr, int32_t Index, |
| 40 | unsigned RelOff) const {} | 42 | unsigned RelOff) const {} |
| 41 | virtual void addPltHeaderSymbols(InputSectionBase *IS) const {} | 43 | virtual void addPltHeaderSymbols(InputSection &IS) const {} |
| 42 | virtual void addPltSymbols(InputSectionBase *IS, uint64_t Off) const {} | 44 | virtual void addPltSymbols(InputSection &IS, uint64_t Off) const {} |
| 45 | |||
| 43 | // Returns true if a relocation only uses the low bits of a value such that | 46 | // Returns true if a relocation only uses the low bits of a value such that |
| 44 | // all those bits are in in the same page. For example, if the relocation | 47 | // all those bits are in in the same page. For example, if the relocation |
| 45 | // only uses the low 12 bits in a system with 4k pages. If this is true, the | 48 | // only uses the low 12 bits in a system with 4k pages. If this is true, the |
| 46 | // bits will always have the same value at runtime and we don't have to emit | 49 | // bits will always have the same value at runtime and we don't have to emit |
| 47 | // a dynamic relocation. | 50 | // a dynamic relocation. |
| 48 | virtual bool usesOnlyLowPageBits(uint32_t Type) const; | 51 | virtual bool usesOnlyLowPageBits(RelType Type) const; |
| 49 | 52 | ||
| 50 | // Decide whether a Thunk is needed for the relocation from File | 53 | // Decide whether a Thunk is needed for the relocation from File |
| 51 | // targeting S. | 54 | // targeting S. |
| 52 | virtual bool needsThunk(RelExpr Expr, uint32_t RelocType, | 55 | virtual bool needsThunk(RelExpr Expr, RelType RelocType, |
| 53 | const InputFile *File, const SymbolBody &S) const; | 56 | const InputFile *File, uint64_t BranchAddr, |
| 57 | const Symbol &S) const; | ||
| 54 | // Return true if we can reach Dst from Src with Relocation RelocType | 58 | // Return true if we can reach Dst from Src with Relocation RelocType |
| 55 | virtual bool inBranchRange(uint32_t RelocType, uint64_t Src, | 59 | virtual bool inBranchRange(RelType Type, uint64_t Src, |
| 56 | uint64_t Dst) const; | 60 | uint64_t Dst) const; |
| 57 | virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, | 61 | virtual RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 58 | const uint8_t *Loc) const = 0; | 62 | const uint8_t *Loc) const = 0; |
| 59 | virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0; | 63 | |
| 64 | virtual void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const = 0; | ||
| 65 | |||
| 60 | virtual ~TargetInfo(); | 66 | virtual ~TargetInfo(); |
| 61 | 67 | ||
| 62 | unsigned TlsGdRelaxSkip = 1; | 68 | unsigned TlsGdRelaxSkip = 1; |
| 63 | unsigned PageSize = 4096; | 69 | unsigned PageSize = 4096; |
| 64 | unsigned DefaultMaxPageSize = 4096; | 70 | unsigned DefaultMaxPageSize = 4096; |
| 65 | 71 | ||
| 66 | // On FreeBSD x86_64 the first page cannot be mmaped. | 72 | uint64_t getImageBase(); |
| 67 | // On Linux that is controled by vm.mmap_min_addr. At least on some x86_64 | ||
| 68 | // installs that is 65536, so the first 15 pages cannot be used. | ||
| 69 | // Given that, the smallest value that can be used in here is 0x10000. | ||
| 70 | uint64_t DefaultImageBase = 0x10000; | ||
| 71 | 73 | ||
| 72 | // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got section. Use -1 for | 74 | // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got section. Use -1 for |
| 73 | // end of .got | 75 | // end of .got |
| 74 | uint64_t GotBaseSymOff = 0; | 76 | uint64_t GotBaseSymOff = 0; |
| 75 | 77 | ||
| 76 | uint32_t CopyRel; | 78 | // On systems with range extensions we place collections of Thunks at |
| 77 | uint32_t GotRel; | 79 | // regular spacings that enable the majority of branches reach the Thunks. |
| 78 | uint32_t PltRel; | 80 | uint32_t ThunkSectionSpacing = 0; |
| 79 | uint32_t RelativeRel; | 81 | |
| 80 | uint32_t IRelativeRel; | 82 | RelType CopyRel; |
| 81 | uint32_t TlsDescRel; | 83 | RelType GotRel; |
| 82 | uint32_t TlsGotRel; | 84 | RelType PltRel; |
| 83 | uint32_t TlsModuleIndexRel; | 85 | RelType RelativeRel; |
| 84 | uint32_t TlsOffsetRel; | 86 | RelType IRelativeRel; |
| 87 | RelType TlsDescRel; | ||
| 88 | RelType TlsGotRel; | ||
| 89 | RelType TlsModuleIndexRel; | ||
| 90 | RelType TlsOffsetRel; | ||
| 85 | unsigned GotEntrySize = 0; | 91 | unsigned GotEntrySize = 0; |
| 86 | unsigned GotPltEntrySize = 0; | 92 | unsigned GotPltEntrySize = 0; |
| 87 | unsigned PltEntrySize; | 93 | unsigned PltEntrySize; |
| ... | @@ -100,13 +106,20 @@ public: | ... | @@ -100,13 +106,20 @@ public: |
| 100 | // executable OutputSections. | 106 | // executable OutputSections. |
| 101 | uint32_t TrapInstr = 0; | 107 | uint32_t TrapInstr = 0; |
| 102 | 108 | ||
| 103 | virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, | 109 | virtual RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 104 | RelExpr Expr) const; | 110 | RelExpr Expr) const; |
| 105 | virtual void relaxGot(uint8_t *Loc, uint64_t Val) const; | 111 | virtual void relaxGot(uint8_t *Loc, uint64_t Val) const; |
| 106 | virtual void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const; | 112 | virtual void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const; |
| 107 | virtual void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const; | 113 | virtual void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; |
| 108 | virtual void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const; | 114 | virtual void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; |
| 109 | virtual void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const; | 115 | virtual void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; |
| 116 | |||
| 117 | protected: | ||
| 118 | // On FreeBSD x86_64 the first page cannot be mmaped. | ||
| 119 | // On Linux that is controled by vm.mmap_min_addr. At least on some x86_64 | ||
| 120 | // installs that is 65536, so the first 15 pages cannot be used. | ||
| 121 | // Given that, the smallest value that can be used in here is 0x10000. | ||
| 122 | uint64_t DefaultImageBase = 0x10000; | ||
| 110 | }; | 123 | }; |
| 111 | 124 | ||
| 112 | TargetInfo *getAArch64TargetInfo(); | 125 | TargetInfo *getAArch64TargetInfo(); |
| ... | @@ -129,32 +142,42 @@ uint64_t getAArch64Page(uint64_t Expr); | ... | @@ -129,32 +142,42 @@ uint64_t getAArch64Page(uint64_t Expr); |
| 129 | extern TargetInfo *Target; | 142 | extern TargetInfo *Target; |
| 130 | TargetInfo *getTarget(); | 143 | TargetInfo *getTarget(); |
| 131 | 144 | ||
| 145 | template <class ELFT> bool isMipsPIC(const Defined *Sym); | ||
| 146 | |||
| 147 | static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V, | ||
| 148 | int64_t Min, uint64_t Max) { | ||
| 149 | error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) + | ||
| 150 | " out of range: " + V + " is not in [" + Twine(Min) + ", " + | ||
| 151 | Twine(Max) + "]"); | ||
| 152 | } | ||
| 153 | |||
| 132 | template <unsigned N> | 154 | template <unsigned N> |
| 133 | static void checkInt(uint8_t *Loc, int64_t V, uint32_t Type) { | 155 | static void checkInt(uint8_t *Loc, int64_t V, RelType Type) { |
| 134 | if (!llvm::isInt<N>(V)) | 156 | if (!llvm::isInt<N>(V)) |
| 135 | error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) + | 157 | reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N)); |
| 136 | " out of range"); | ||
| 137 | } | 158 | } |
| 138 | 159 | ||
| 139 | template <unsigned N> | 160 | template <unsigned N> |
| 140 | static void checkUInt(uint8_t *Loc, uint64_t V, uint32_t Type) { | 161 | static void checkUInt(uint8_t *Loc, uint64_t V, RelType Type) { |
| 141 | if (!llvm::isUInt<N>(V)) | 162 | if (!llvm::isUInt<N>(V)) |
| 142 | error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) + | 163 | reportRangeError(Loc, Type, Twine(V), 0, llvm::maxUIntN(N)); |
| 143 | " out of range"); | ||
| 144 | } | 164 | } |
| 145 | 165 | ||
| 146 | template <unsigned N> | 166 | template <unsigned N> |
| 147 | static void checkIntUInt(uint8_t *Loc, uint64_t V, uint32_t Type) { | 167 | static void checkIntUInt(uint8_t *Loc, uint64_t V, RelType Type) { |
| 148 | if (!llvm::isInt<N>(V) && !llvm::isUInt<N>(V)) | 168 | if (!llvm::isInt<N>(V) && !llvm::isUInt<N>(V)) |
| 149 | error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) + | 169 | // For the error message we should cast V to a signed integer so that error |
| 150 | " out of range"); | 170 | // messages show a small negative value rather than an extremely large one |
| 171 | reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N), | ||
| 172 | llvm::maxUIntN(N)); | ||
| 151 | } | 173 | } |
| 152 | 174 | ||
| 153 | template <unsigned N> | 175 | template <unsigned N> |
| 154 | static void checkAlignment(uint8_t *Loc, uint64_t V, uint32_t Type) { | 176 | static void checkAlignment(uint8_t *Loc, uint64_t V, RelType Type) { |
| 155 | if ((V & (N - 1)) != 0) | 177 | if ((V & (N - 1)) != 0) |
| 156 | error(getErrorLocation(Loc) + "improper alignment for relocation " + | 178 | error(getErrorLocation(Loc) + "improper alignment for relocation " + |
| 157 | lld::toString(Type)); | 179 | lld::toString(Type) + ": 0x" + llvm::utohexstr(V) + |
| 180 | " is not aligned to " + Twine(N) + " bytes"); | ||
| 158 | } | 181 | } |
| 159 | } // namespace elf | 182 | } // namespace elf |
| 160 | } // namespace lld | 183 | } // namespace lld |
deps/lld/ELF/Threads.h deleted-88| ... | @@ -1,88 +0,0 @@ | ||
| 1 | //===- Threads.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 | // LLD supports threads to distribute workloads to multiple cores. Using | ||
| 11 | // multicore is most effective when more than one core are idle. At the | ||
| 12 | // last step of a build, it is often the case that a linker is the only | ||
| 13 | // active process on a computer. So, we are naturally interested in using | ||
| 14 | // threads wisely to reduce latency to deliver results to users. | ||
| 15 | // | ||
| 16 | // That said, we don't want to do "too clever" things using threads. | ||
| 17 | // Complex multi-threaded algorithms are sometimes extremely hard to | ||
| 18 | // reason about and can easily mess up the entire design. | ||
| 19 | // | ||
| 20 | // Fortunately, when a linker links large programs (when the link time is | ||
| 21 | // most critical), it spends most of the time to work on massive number of | ||
| 22 | // small pieces of data of the same kind, and there are opportunities for | ||
| 23 | // large parallelism there. Here are examples: | ||
| 24 | // | ||
| 25 | // - We have hundreds of thousands of input sections that need to be | ||
| 26 | // copied to a result file at the last step of link. Once we fix a file | ||
| 27 | // layout, each section can be copied to its destination and its | ||
| 28 | // relocations can be applied independently. | ||
| 29 | // | ||
| 30 | // - We have tens of millions of small strings when constructing a | ||
| 31 | // mergeable string section. | ||
| 32 | // | ||
| 33 | // For the cases such as the former, we can just use parallel_for_each | ||
| 34 | // instead of std::for_each (or a plain for loop). Because tasks are | ||
| 35 | // completely independent from each other, we can run them in parallel | ||
| 36 | // without any coordination between them. That's very easy to understand | ||
| 37 | // and reason about. | ||
| 38 | // | ||
| 39 | // For the cases such as the latter, we can use parallel algorithms to | ||
| 40 | // deal with massive data. We have to write code for a tailored algorithm | ||
| 41 | // for each problem, but the complexity of multi-threading is isolated in | ||
| 42 | // a single pass and doesn't affect the linker's overall design. | ||
| 43 | // | ||
| 44 | // The above approach seems to be working fairly well. As an example, when | ||
| 45 | // linking Chromium (output size 1.6 GB), using 4 cores reduces latency to | ||
| 46 | // 75% compared to single core (from 12.66 seconds to 9.55 seconds) on my | ||
| 47 | // Ivy Bridge Xeon 2.8 GHz machine. Using 40 cores reduces it to 63% (from | ||
| 48 | // 12.66 seconds to 7.95 seconds). Because of the Amdahl's law, the | ||
| 49 | // speedup is not linear, but as you add more cores, it gets faster. | ||
| 50 | // | ||
| 51 | // On a final note, if you are trying to optimize, keep the axiom "don't | ||
| 52 | // guess, measure!" in mind. Some important passes of the linker are not | ||
| 53 | // that slow. For example, resolving all symbols is not a very heavy pass, | ||
| 54 | // although it would be very hard to parallelize it. You want to first | ||
| 55 | // identify a slow pass and then optimize it. | ||
| 56 | // | ||
| 57 | //===----------------------------------------------------------------------===// | ||
| 58 | |||
| 59 | #ifndef LLD_ELF_THREADS_H | ||
| 60 | #define LLD_ELF_THREADS_H | ||
| 61 | |||
| 62 | #include "Config.h" | ||
| 63 | |||
| 64 | #include "llvm/Support/Parallel.h" | ||
| 65 | #include <functional> | ||
| 66 | |||
| 67 | namespace lld { | ||
| 68 | namespace elf { | ||
| 69 | |||
| 70 | template <class IterTy, class FuncTy> | ||
| 71 | void parallelForEach(IterTy Begin, IterTy End, FuncTy Fn) { | ||
| 72 | if (Config->Threads) | ||
| 73 | for_each(llvm::parallel::par, Begin, End, Fn); | ||
| 74 | else | ||
| 75 | for_each(llvm::parallel::seq, Begin, End, Fn); | ||
| 76 | } | ||
| 77 | |||
| 78 | inline void parallelForEachN(size_t Begin, size_t End, | ||
| 79 | std::function<void(size_t)> Fn) { | ||
| 80 | if (Config->Threads) | ||
| 81 | for_each_n(llvm::parallel::par, Begin, End, Fn); | ||
| 82 | else | ||
| 83 | for_each_n(llvm::parallel::seq, Begin, End, Fn); | ||
| 84 | } | ||
| 85 | } // namespace elf | ||
| 86 | } // namespace lld | ||
| 87 | |||
| 88 | #endif | ||
deps/lld/ELF/Thunks.cpp+208-47| ... | @@ -23,13 +23,13 @@ | ... | @@ -23,13 +23,13 @@ |
| 23 | 23 | ||
| 24 | #include "Thunks.h" | 24 | #include "Thunks.h" |
| 25 | #include "Config.h" | 25 | #include "Config.h" |
| 26 | #include "Error.h" | ||
| 27 | #include "InputSection.h" | 26 | #include "InputSection.h" |
| 28 | #include "Memory.h" | ||
| 29 | #include "OutputSections.h" | 27 | #include "OutputSections.h" |
| 30 | #include "Symbols.h" | 28 | #include "Symbols.h" |
| 31 | #include "SyntheticSections.h" | 29 | #include "SyntheticSections.h" |
| 32 | #include "Target.h" | 30 | #include "Target.h" |
| 31 | #include "lld/Common/ErrorHandler.h" | ||
| 32 | #include "lld/Common/Memory.h" | ||
| 33 | #include "llvm/BinaryFormat/ELF.h" | 33 | #include "llvm/BinaryFormat/ELF.h" |
| 34 | #include "llvm/Support/Casting.h" | 34 | #include "llvm/Support/Casting.h" |
| 35 | #include "llvm/Support/Endian.h" | 35 | #include "llvm/Support/Endian.h" |
| ... | @@ -48,52 +48,69 @@ namespace elf { | ... | @@ -48,52 +48,69 @@ namespace elf { |
| 48 | 48 | ||
| 49 | namespace { | 49 | namespace { |
| 50 | 50 | ||
| 51 | // AArch64 long range Thunks | ||
| 52 | class AArch64ABSLongThunk final : public Thunk { | ||
| 53 | public: | ||
| 54 | AArch64ABSLongThunk(Symbol &Dest) : Thunk(Dest) {} | ||
| 55 | uint32_t size() const override { return 16; } | ||
| 56 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | ||
| 57 | void addSymbols(ThunkSection &IS) override; | ||
| 58 | }; | ||
| 59 | |||
| 60 | class AArch64ADRPThunk final : public Thunk { | ||
| 61 | public: | ||
| 62 | AArch64ADRPThunk(Symbol &Dest) : Thunk(Dest) {} | ||
| 63 | uint32_t size() const override { return 12; } | ||
| 64 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | ||
| 65 | void addSymbols(ThunkSection &IS) override; | ||
| 66 | }; | ||
| 67 | |||
| 51 | // Specific ARM Thunk implementations. The naming convention is: | 68 | // Specific ARM Thunk implementations. The naming convention is: |
| 52 | // Source State, TargetState, Target Requirement, ABS or PI, Range | 69 | // Source State, TargetState, Target Requirement, ABS or PI, Range |
| 53 | class ARMV7ABSLongThunk final : public Thunk { | 70 | class ARMV7ABSLongThunk final : public Thunk { |
| 54 | public: | 71 | public: |
| 55 | ARMV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) {} | 72 | ARMV7ABSLongThunk(Symbol &Dest) : Thunk(Dest) {} |
| 56 | 73 | ||
| 57 | uint32_t size() const override { return 12; } | 74 | uint32_t size() const override { return 12; } |
| 58 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | 75 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; |
| 59 | void addSymbols(ThunkSection &IS) override; | 76 | void addSymbols(ThunkSection &IS) override; |
| 60 | bool isCompatibleWith(uint32_t RelocType) const override; | 77 | bool isCompatibleWith(RelType Type) const override; |
| 61 | }; | 78 | }; |
| 62 | 79 | ||
| 63 | class ARMV7PILongThunk final : public Thunk { | 80 | class ARMV7PILongThunk final : public Thunk { |
| 64 | public: | 81 | public: |
| 65 | ARMV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) {} | 82 | ARMV7PILongThunk(Symbol &Dest) : Thunk(Dest) {} |
| 66 | 83 | ||
| 67 | uint32_t size() const override { return 16; } | 84 | uint32_t size() const override { return 16; } |
| 68 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | 85 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; |
| 69 | void addSymbols(ThunkSection &IS) override; | 86 | void addSymbols(ThunkSection &IS) override; |
| 70 | bool isCompatibleWith(uint32_t RelocType) const override; | 87 | bool isCompatibleWith(RelType Type) const override; |
| 71 | }; | 88 | }; |
| 72 | 89 | ||
| 73 | class ThumbV7ABSLongThunk final : public Thunk { | 90 | class ThumbV7ABSLongThunk final : public Thunk { |
| 74 | public: | 91 | public: |
| 75 | ThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) { Alignment = 2; } | 92 | ThumbV7ABSLongThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; } |
| 76 | 93 | ||
| 77 | uint32_t size() const override { return 10; } | 94 | uint32_t size() const override { return 10; } |
| 78 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | 95 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; |
| 79 | void addSymbols(ThunkSection &IS) override; | 96 | void addSymbols(ThunkSection &IS) override; |
| 80 | bool isCompatibleWith(uint32_t RelocType) const override; | 97 | bool isCompatibleWith(RelType Type) const override; |
| 81 | }; | 98 | }; |
| 82 | 99 | ||
| 83 | class ThumbV7PILongThunk final : public Thunk { | 100 | class ThumbV7PILongThunk final : public Thunk { |
| 84 | public: | 101 | public: |
| 85 | ThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) { Alignment = 2; } | 102 | ThumbV7PILongThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; } |
| 86 | 103 | ||
| 87 | uint32_t size() const override { return 12; } | 104 | uint32_t size() const override { return 12; } |
| 88 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | 105 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; |
| 89 | void addSymbols(ThunkSection &IS) override; | 106 | void addSymbols(ThunkSection &IS) override; |
| 90 | bool isCompatibleWith(uint32_t RelocType) const override; | 107 | bool isCompatibleWith(RelType Type) const override; |
| 91 | }; | 108 | }; |
| 92 | 109 | ||
| 93 | // MIPS LA25 thunk | 110 | // MIPS LA25 thunk |
| 94 | class MipsThunk final : public Thunk { | 111 | class MipsThunk final : public Thunk { |
| 95 | public: | 112 | public: |
| 96 | MipsThunk(const SymbolBody &Dest) : Thunk(Dest) {} | 113 | MipsThunk(Symbol &Dest) : Thunk(Dest) {} |
| 97 | 114 | ||
| 98 | uint32_t size() const override { return 16; } | 115 | uint32_t size() const override { return 16; } |
| 99 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | 116 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; |
| ... | @@ -101,10 +118,86 @@ public: | ... | @@ -101,10 +118,86 @@ public: |
| 101 | InputSection *getTargetInputSection() const override; | 118 | InputSection *getTargetInputSection() const override; |
| 102 | }; | 119 | }; |
| 103 | 120 | ||
| 121 | // microMIPS R2-R5 LA25 thunk | ||
| 122 | class MicroMipsThunk final : public Thunk { | ||
| 123 | public: | ||
| 124 | MicroMipsThunk(Symbol &Dest) : Thunk(Dest) {} | ||
| 125 | |||
| 126 | uint32_t size() const override { return 14; } | ||
| 127 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | ||
| 128 | void addSymbols(ThunkSection &IS) override; | ||
| 129 | InputSection *getTargetInputSection() const override; | ||
| 130 | }; | ||
| 131 | |||
| 132 | // microMIPS R6 LA25 thunk | ||
| 133 | class MicroMipsR6Thunk final : public Thunk { | ||
| 134 | public: | ||
| 135 | MicroMipsR6Thunk(Symbol &Dest) : Thunk(Dest) {} | ||
| 136 | |||
| 137 | uint32_t size() const override { return 12; } | ||
| 138 | void writeTo(uint8_t *Buf, ThunkSection &IS) const override; | ||
| 139 | void addSymbols(ThunkSection &IS) override; | ||
| 140 | InputSection *getTargetInputSection() const override; | ||
| 141 | }; | ||
| 142 | |||
| 104 | } // end anonymous namespace | 143 | } // end anonymous namespace |
| 105 | 144 | ||
| 145 | // AArch64 long range Thunks | ||
| 146 | |||
| 147 | static uint64_t getAArch64ThunkDestVA(const Symbol &S) { | ||
| 148 | uint64_t V = S.isInPlt() ? S.getPltVA() : S.getVA(); | ||
| 149 | return V; | ||
| 150 | } | ||
| 151 | |||
| 152 | void AArch64ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { | ||
| 153 | const uint8_t Data[] = { | ||
| 154 | 0x50, 0x00, 0x00, 0x58, // ldr x16, L0 | ||
| 155 | 0x00, 0x02, 0x1f, 0xd6, // br x16 | ||
| 156 | 0x00, 0x00, 0x00, 0x00, // L0: .xword S | ||
| 157 | 0x00, 0x00, 0x00, 0x00, | ||
| 158 | }; | ||
| 159 | uint64_t S = getAArch64ThunkDestVA(Destination); | ||
| 160 | memcpy(Buf, Data, sizeof(Data)); | ||
| 161 | Target->relocateOne(Buf + 8, R_AARCH64_ABS64, S); | ||
| 162 | } | ||
| 163 | |||
| 164 | void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) { | ||
| 165 | ThunkSym = addSyntheticLocal( | ||
| 166 | Saver.save("__AArch64AbsLongThunk_" + Destination.getName()), STT_FUNC, | ||
| 167 | Offset, size(), IS); | ||
| 168 | addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS); | ||
| 169 | addSyntheticLocal("$d", STT_NOTYPE, Offset + 8, 0, IS); | ||
| 170 | } | ||
| 171 | |||
| 172 | // This Thunk has a maximum range of 4Gb, this is sufficient for all programs | ||
| 173 | // using the small code model, including pc-relative ones. At time of writing | ||
| 174 | // clang and gcc do not support the large code model for position independent | ||
| 175 | // code so it is safe to use this for position independent thunks without | ||
| 176 | // worrying about the destination being more than 4Gb away. | ||
| 177 | void AArch64ADRPThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { | ||
| 178 | const uint8_t Data[] = { | ||
| 179 | 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest) | ||
| 180 | 0x10, 0x02, 0x00, 0x91, // add x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest) | ||
| 181 | 0x00, 0x02, 0x1f, 0xd6, // br x16 | ||
| 182 | }; | ||
| 183 | uint64_t S = getAArch64ThunkDestVA(Destination); | ||
| 184 | uint64_t P = ThunkSym->getVA(); | ||
| 185 | memcpy(Buf, Data, sizeof(Data)); | ||
| 186 | Target->relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21, | ||
| 187 | getAArch64Page(S) - getAArch64Page(P)); | ||
| 188 | Target->relocateOne(Buf + 4, R_AARCH64_ADD_ABS_LO12_NC, S); | ||
| 189 | } | ||
| 190 | |||
| 191 | void AArch64ADRPThunk::addSymbols(ThunkSection &IS) | ||
| 192 | { | ||
| 193 | ThunkSym = addSyntheticLocal( | ||
| 194 | Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC, | ||
| 195 | Offset, size(), IS); | ||
| 196 | addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS); | ||
| 197 | } | ||
| 198 | |||
| 106 | // ARM Target Thunks | 199 | // ARM Target Thunks |
| 107 | static uint64_t getARMThunkDestVA(const SymbolBody &S) { | 200 | static uint64_t getARMThunkDestVA(const Symbol &S) { |
| 108 | uint64_t V = S.isInPlt() ? S.getPltVA() : S.getVA(); | 201 | uint64_t V = S.isInPlt() ? S.getPltVA() : S.getVA(); |
| 109 | return SignExtend64<32>(V); | 202 | return SignExtend64<32>(V); |
| 110 | } | 203 | } |
| ... | @@ -124,13 +217,13 @@ void ARMV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { | ... | @@ -124,13 +217,13 @@ void ARMV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { |
| 124 | void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) { | 217 | void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) { |
| 125 | ThunkSym = addSyntheticLocal( | 218 | ThunkSym = addSyntheticLocal( |
| 126 | Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()), STT_FUNC, | 219 | Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()), STT_FUNC, |
| 127 | Offset, size(), &IS); | 220 | Offset, size(), IS); |
| 128 | addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS); | 221 | addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS); |
| 129 | } | 222 | } |
| 130 | 223 | ||
| 131 | bool ARMV7ABSLongThunk::isCompatibleWith(uint32_t RelocType) const { | 224 | bool ARMV7ABSLongThunk::isCompatibleWith(RelType Type) const { |
| 132 | // Thumb branch relocations can't use BLX | 225 | // Thumb branch relocations can't use BLX |
| 133 | return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24; | 226 | return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24; |
| 134 | } | 227 | } |
| 135 | 228 | ||
| 136 | void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { | 229 | void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { |
| ... | @@ -148,67 +241,67 @@ void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { | ... | @@ -148,67 +241,67 @@ void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { |
| 148 | void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) { | 241 | void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) { |
| 149 | ThunkSym = addSyntheticLocal( | 242 | ThunkSym = addSyntheticLocal( |
| 150 | Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()), STT_FUNC, | 243 | Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()), STT_FUNC, |
| 151 | Offset | 0x1, size(), &IS); | 244 | Offset | 0x1, size(), IS); |
| 152 | addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS); | 245 | addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS); |
| 153 | } | 246 | } |
| 154 | 247 | ||
| 155 | bool ThumbV7ABSLongThunk::isCompatibleWith(uint32_t RelocType) const { | 248 | bool ThumbV7ABSLongThunk::isCompatibleWith(RelType Type) const { |
| 156 | // ARM branch relocations can't use BLX | 249 | // ARM branch relocations can't use BLX |
| 157 | return RelocType != R_ARM_JUMP24 && RelocType != R_ARM_PC24 && | 250 | return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32; |
| 158 | RelocType != R_ARM_PLT32; | ||
| 159 | } | 251 | } |
| 160 | 252 | ||
| 161 | void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { | 253 | void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { |
| 162 | const uint8_t Data[] = { | 254 | const uint8_t Data[] = { |
| 163 | 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) +8) | 255 | 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) + 8) |
| 164 | 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P+4) +8) | 256 | 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P) + 8) |
| 165 | 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc | 257 | 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc |
| 166 | 0x1c, 0xff, 0x2f, 0xe1, // bx r12 | 258 | 0x1c, 0xff, 0x2f, 0xe1, // bx r12 |
| 167 | }; | 259 | }; |
| 168 | uint64_t S = getARMThunkDestVA(Destination); | 260 | uint64_t S = getARMThunkDestVA(Destination); |
| 169 | uint64_t P = ThunkSym->getVA(); | 261 | uint64_t P = ThunkSym->getVA(); |
| 262 | uint64_t Offset = S - P - 16; | ||
| 170 | memcpy(Buf, Data, sizeof(Data)); | 263 | memcpy(Buf, Data, sizeof(Data)); |
| 171 | Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, S - P - 16); | 264 | Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, Offset); |
| 172 | Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, S - P - 12); | 265 | Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, Offset); |
| 173 | } | 266 | } |
| 174 | 267 | ||
| 175 | void ARMV7PILongThunk::addSymbols(ThunkSection &IS) { | 268 | void ARMV7PILongThunk::addSymbols(ThunkSection &IS) { |
| 176 | ThunkSym = addSyntheticLocal( | 269 | ThunkSym = addSyntheticLocal( |
| 177 | Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC, | 270 | Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC, |
| 178 | Offset, size(), &IS); | 271 | Offset, size(), IS); |
| 179 | addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS); | 272 | addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS); |
| 180 | } | 273 | } |
| 181 | 274 | ||
| 182 | bool ARMV7PILongThunk::isCompatibleWith(uint32_t RelocType) const { | 275 | bool ARMV7PILongThunk::isCompatibleWith(RelType Type) const { |
| 183 | // Thumb branch relocations can't use BLX | 276 | // Thumb branch relocations can't use BLX |
| 184 | return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24; | 277 | return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24; |
| 185 | } | 278 | } |
| 186 | 279 | ||
| 187 | void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { | 280 | void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const { |
| 188 | const uint8_t Data[] = { | 281 | const uint8_t Data[] = { |
| 189 | 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4) | 282 | 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4) |
| 190 | 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P+4) + 4) | 283 | 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4) |
| 191 | 0xfc, 0x44, // L1: add r12, pc | 284 | 0xfc, 0x44, // L1: add r12, pc |
| 192 | 0x60, 0x47, // bx r12 | 285 | 0x60, 0x47, // bx r12 |
| 193 | }; | 286 | }; |
| 194 | uint64_t S = getARMThunkDestVA(Destination); | 287 | uint64_t S = getARMThunkDestVA(Destination); |
| 195 | uint64_t P = ThunkSym->getVA() & ~0x1; | 288 | uint64_t P = ThunkSym->getVA() & ~0x1; |
| 289 | uint64_t Offset = S - P - 12; | ||
| 196 | memcpy(Buf, Data, sizeof(Data)); | 290 | memcpy(Buf, Data, sizeof(Data)); |
| 197 | Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, S - P - 12); | 291 | Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, Offset); |
| 198 | Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, S - P - 8); | 292 | Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, Offset); |
| 199 | } | 293 | } |
| 200 | 294 | ||
| 201 | void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) { | 295 | void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) { |
| 202 | ThunkSym = addSyntheticLocal( | 296 | ThunkSym = addSyntheticLocal( |
| 203 | Saver.save("__ThumbV7PILongThunk_" + Destination.getName()), STT_FUNC, | 297 | Saver.save("__ThumbV7PILongThunk_" + Destination.getName()), STT_FUNC, |
| 204 | Offset | 0x1, size(), &IS); | 298 | Offset | 0x1, size(), IS); |
| 205 | addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS); | 299 | addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS); |
| 206 | } | 300 | } |
| 207 | 301 | ||
| 208 | bool ThumbV7PILongThunk::isCompatibleWith(uint32_t RelocType) const { | 302 | bool ThumbV7PILongThunk::isCompatibleWith(RelType Type) const { |
| 209 | // ARM branch relocations can't use BLX | 303 | // ARM branch relocations can't use BLX |
| 210 | return RelocType != R_ARM_JUMP24 && RelocType != R_ARM_PC24 && | 304 | return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32; |
| 211 | RelocType != R_ARM_PLT32; | ||
| 212 | } | 305 | } |
| 213 | 306 | ||
| 214 | // Write MIPS LA25 thunk code to call PIC function from the non-PIC one. | 307 | // Write MIPS LA25 thunk code to call PIC function from the non-PIC one. |
| ... | @@ -225,20 +318,78 @@ void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const { | ... | @@ -225,20 +318,78 @@ void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const { |
| 225 | void MipsThunk::addSymbols(ThunkSection &IS) { | 318 | void MipsThunk::addSymbols(ThunkSection &IS) { |
| 226 | ThunkSym = | 319 | ThunkSym = |
| 227 | addSyntheticLocal(Saver.save("__LA25Thunk_" + Destination.getName()), | 320 | addSyntheticLocal(Saver.save("__LA25Thunk_" + Destination.getName()), |
| 228 | STT_FUNC, Offset, size(), &IS); | 321 | STT_FUNC, Offset, size(), IS); |
| 229 | } | 322 | } |
| 230 | 323 | ||
| 231 | InputSection *MipsThunk::getTargetInputSection() const { | 324 | InputSection *MipsThunk::getTargetInputSection() const { |
| 232 | auto *DR = dyn_cast<DefinedRegular>(&Destination); | 325 | auto &DR = cast<Defined>(Destination); |
| 233 | return dyn_cast<InputSection>(DR->Section); | 326 | return dyn_cast<InputSection>(DR.Section); |
| 234 | } | 327 | } |
| 235 | 328 | ||
| 236 | Thunk::Thunk(const SymbolBody &D) : Destination(D), Offset(0) {} | 329 | // Write microMIPS R2-R5 LA25 thunk code |
| 330 | // to call PIC function from the non-PIC one. | ||
| 331 | void MicroMipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const { | ||
| 332 | uint64_t S = Destination.getVA() | 1; | ||
| 333 | write16(Buf, 0x41b9, Config->Endianness); // lui $25, %hi(func) | ||
| 334 | write16(Buf + 4, 0xd400, Config->Endianness); // j func | ||
| 335 | write16(Buf + 8, 0x3339, Config->Endianness); // addiu $25, $25, %lo(func) | ||
| 336 | write16(Buf + 12, 0x0c00, Config->Endianness); // nop | ||
| 337 | Target->relocateOne(Buf, R_MICROMIPS_HI16, S); | ||
| 338 | Target->relocateOne(Buf + 4, R_MICROMIPS_26_S1, S); | ||
| 339 | Target->relocateOne(Buf + 8, R_MICROMIPS_LO16, S); | ||
| 340 | } | ||
| 341 | |||
| 342 | void MicroMipsThunk::addSymbols(ThunkSection &IS) { | ||
| 343 | ThunkSym = | ||
| 344 | addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()), | ||
| 345 | STT_FUNC, Offset, size(), IS); | ||
| 346 | ThunkSym->StOther |= STO_MIPS_MICROMIPS; | ||
| 347 | } | ||
| 348 | |||
| 349 | InputSection *MicroMipsThunk::getTargetInputSection() const { | ||
| 350 | auto &DR = cast<Defined>(Destination); | ||
| 351 | return dyn_cast<InputSection>(DR.Section); | ||
| 352 | } | ||
| 353 | |||
| 354 | // Write microMIPS R6 LA25 thunk code | ||
| 355 | // to call PIC function from the non-PIC one. | ||
| 356 | void MicroMipsR6Thunk::writeTo(uint8_t *Buf, ThunkSection &) const { | ||
| 357 | uint64_t S = Destination.getVA() | 1; | ||
| 358 | uint64_t P = ThunkSym->getVA(); | ||
| 359 | write16(Buf, 0x1320, Config->Endianness); // lui $25, %hi(func) | ||
| 360 | write16(Buf + 4, 0x3339, Config->Endianness); // addiu $25, $25, %lo(func) | ||
| 361 | write16(Buf + 8, 0x9400, Config->Endianness); // bc func | ||
| 362 | Target->relocateOne(Buf, R_MICROMIPS_HI16, S); | ||
| 363 | Target->relocateOne(Buf + 4, R_MICROMIPS_LO16, S); | ||
| 364 | Target->relocateOne(Buf + 8, R_MICROMIPS_PC26_S1, S - P - 12); | ||
| 365 | } | ||
| 366 | |||
| 367 | void MicroMipsR6Thunk::addSymbols(ThunkSection &IS) { | ||
| 368 | ThunkSym = | ||
| 369 | addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()), | ||
| 370 | STT_FUNC, Offset, size(), IS); | ||
| 371 | ThunkSym->StOther |= STO_MIPS_MICROMIPS; | ||
| 372 | } | ||
| 373 | |||
| 374 | InputSection *MicroMipsR6Thunk::getTargetInputSection() const { | ||
| 375 | auto &DR = cast<Defined>(Destination); | ||
| 376 | return dyn_cast<InputSection>(DR.Section); | ||
| 377 | } | ||
| 378 | |||
| 379 | Thunk::Thunk(Symbol &D) : Destination(D), Offset(0) {} | ||
| 237 | 380 | ||
| 238 | Thunk::~Thunk() = default; | 381 | Thunk::~Thunk() = default; |
| 239 | 382 | ||
| 383 | static Thunk *addThunkAArch64(RelType Type, Symbol &S) { | ||
| 384 | if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) | ||
| 385 | fatal("unrecognized relocation type"); | ||
| 386 | if (Config->Pic) | ||
| 387 | return make<AArch64ADRPThunk>(S); | ||
| 388 | return make<AArch64ABSLongThunk>(S); | ||
| 389 | } | ||
| 390 | |||
| 240 | // Creates a thunk for Thumb-ARM interworking. | 391 | // Creates a thunk for Thumb-ARM interworking. |
| 241 | static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) { | 392 | static Thunk *addThunkArm(RelType Reloc, Symbol &S) { |
| 242 | // ARM relocations need ARM to Thumb interworking Thunks. | 393 | // ARM relocations need ARM to Thumb interworking Thunks. |
| 243 | // Thumb relocations need Thumb to ARM relocations. | 394 | // Thumb relocations need Thumb to ARM relocations. |
| 244 | // Use position independent Thunks if we require position independent code. | 395 | // Use position independent Thunks if we require position independent code. |
| ... | @@ -246,11 +397,13 @@ static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) { | ... | @@ -246,11 +397,13 @@ static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) { |
| 246 | case R_ARM_PC24: | 397 | case R_ARM_PC24: |
| 247 | case R_ARM_PLT32: | 398 | case R_ARM_PLT32: |
| 248 | case R_ARM_JUMP24: | 399 | case R_ARM_JUMP24: |
| 400 | case R_ARM_CALL: | ||
| 249 | if (Config->Pic) | 401 | if (Config->Pic) |
| 250 | return make<ARMV7PILongThunk>(S); | 402 | return make<ARMV7PILongThunk>(S); |
| 251 | return make<ARMV7ABSLongThunk>(S); | 403 | return make<ARMV7ABSLongThunk>(S); |
| 252 | case R_ARM_THM_JUMP19: | 404 | case R_ARM_THM_JUMP19: |
| 253 | case R_ARM_THM_JUMP24: | 405 | case R_ARM_THM_JUMP24: |
| 406 | case R_ARM_THM_CALL: | ||
| 254 | if (Config->Pic) | 407 | if (Config->Pic) |
| 255 | return make<ThumbV7PILongThunk>(S); | 408 | return make<ThumbV7PILongThunk>(S); |
| 256 | return make<ThumbV7ABSLongThunk>(S); | 409 | return make<ThumbV7ABSLongThunk>(S); |
| ... | @@ -258,13 +411,21 @@ static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) { | ... | @@ -258,13 +411,21 @@ static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) { |
| 258 | fatal("unrecognized relocation type"); | 411 | fatal("unrecognized relocation type"); |
| 259 | } | 412 | } |
| 260 | 413 | ||
| 261 | static Thunk *addThunkMips(SymbolBody &S) { return make<MipsThunk>(S); } | 414 | static Thunk *addThunkMips(RelType Type, Symbol &S) { |
| 415 | if ((S.StOther & STO_MIPS_MICROMIPS) && isMipsR6()) | ||
| 416 | return make<MicroMipsR6Thunk>(S); | ||
| 417 | if (S.StOther & STO_MIPS_MICROMIPS) | ||
| 418 | return make<MicroMipsThunk>(S); | ||
| 419 | return make<MipsThunk>(S); | ||
| 420 | } | ||
| 262 | 421 | ||
| 263 | Thunk *addThunk(uint32_t RelocType, SymbolBody &S) { | 422 | Thunk *addThunk(RelType Type, Symbol &S) { |
| 264 | if (Config->EMachine == EM_ARM) | 423 | if (Config->EMachine == EM_AARCH64) |
| 265 | return addThunkArm(RelocType, S); | 424 | return addThunkAArch64(Type, S); |
| 425 | else if (Config->EMachine == EM_ARM) | ||
| 426 | return addThunkArm(Type, S); | ||
| 266 | else if (Config->EMachine == EM_MIPS) | 427 | else if (Config->EMachine == EM_MIPS) |
| 267 | return addThunkMips(S); | 428 | return addThunkMips(Type, S); |
| 268 | llvm_unreachable("add Thunk only supported for ARM and Mips"); | 429 | llvm_unreachable("add Thunk only supported for ARM and Mips"); |
| 269 | return nullptr; | 430 | return nullptr; |
| 270 | } | 431 | } |
deps/lld/ELF/Thunks.h+9-9| ... | @@ -14,7 +14,7 @@ | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | ||
| 15 | namespace lld { | 15 | namespace lld { |
| 16 | namespace elf { | 16 | namespace elf { |
| 17 | class SymbolBody; | 17 | class Symbol; |
| 18 | class ThunkSection; | 18 | class ThunkSection; |
| 19 | // Class to describe an instance of a Thunk. | 19 | // Class to describe an instance of a Thunk. |
| 20 | // A Thunk is a code-sequence inserted by the linker in between a caller and | 20 | // A Thunk is a code-sequence inserted by the linker in between a caller and |
| ... | @@ -23,11 +23,11 @@ class ThunkSection; | ... | @@ -23,11 +23,11 @@ class ThunkSection; |
| 23 | // include transferring control from non-pi to pi and changing state on | 23 | // include transferring control from non-pi to pi and changing state on |
| 24 | // targets like ARM. | 24 | // targets like ARM. |
| 25 | // | 25 | // |
| 26 | // Thunks can be created for DefinedRegular, Shared and Undefined Symbols. | 26 | // Thunks can be created for Defined, Shared and Undefined Symbols. |
| 27 | // Thunks are assigned to synthetic ThunkSections | 27 | // Thunks are assigned to synthetic ThunkSections |
| 28 | class Thunk { | 28 | class Thunk { |
| 29 | public: | 29 | public: |
| 30 | Thunk(const SymbolBody &Destination); | 30 | Thunk(Symbol &Destination); |
| 31 | virtual ~Thunk(); | 31 | virtual ~Thunk(); |
| 32 | 32 | ||
| 33 | virtual uint32_t size() const { return 0; } | 33 | virtual uint32_t size() const { return 0; } |
| ... | @@ -41,21 +41,21 @@ public: | ... | @@ -41,21 +41,21 @@ public: |
| 41 | // a branch and fall through to the first Symbol in the Target. | 41 | // a branch and fall through to the first Symbol in the Target. |
| 42 | virtual InputSection *getTargetInputSection() const { return nullptr; } | 42 | virtual InputSection *getTargetInputSection() const { return nullptr; } |
| 43 | 43 | ||
| 44 | // To reuse a Thunk the caller as identified by the RelocType must be | 44 | // To reuse a Thunk the caller as identified by the Type must be |
| 45 | // compatible with it. | 45 | // compatible with it. |
| 46 | virtual bool isCompatibleWith(uint32_t RelocType) const { return true; } | 46 | virtual bool isCompatibleWith(RelType Type) const { return true; } |
| 47 | 47 | ||
| 48 | // The alignment requirement for this Thunk, defaults to the size of the | 48 | // The alignment requirement for this Thunk, defaults to the size of the |
| 49 | // typical code section alignment. | 49 | // typical code section alignment. |
| 50 | const SymbolBody &Destination; | 50 | Symbol &Destination; |
| 51 | SymbolBody *ThunkSym; | 51 | Symbol *ThunkSym; |
| 52 | uint64_t Offset; | 52 | uint64_t Offset = 0; |
| 53 | uint32_t Alignment = 4; | 53 | uint32_t Alignment = 4; |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | // For a Relocation to symbol S create a Thunk to be added to a synthetic | 56 | // For a Relocation to symbol S create a Thunk to be added to a synthetic |
| 57 | // ThunkSection. At present there are implementations for ARM and Mips Thunks. | 57 | // ThunkSection. At present there are implementations for ARM and Mips Thunks. |
| 58 | Thunk *addThunk(uint32_t RelocType, SymbolBody &S); | 58 | Thunk *addThunk(RelType Type, Symbol &S); |
| 59 | 59 | ||
| 60 | } // namespace elf | 60 | } // namespace elf |
| 61 | } // namespace lld | 61 | } // namespace lld |
deps/lld/ELF/Writer.cpp+906-748| ... | @@ -8,22 +8,22 @@ | ... | @@ -8,22 +8,22 @@ |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "Writer.h" | 10 | #include "Writer.h" |
| 11 | #include "AArch64ErrataFix.h" | ||
| 11 | #include "Config.h" | 12 | #include "Config.h" |
| 12 | #include "Filesystem.h" | 13 | #include "Filesystem.h" |
| 13 | #include "LinkerScript.h" | 14 | #include "LinkerScript.h" |
| 14 | #include "MapFile.h" | 15 | #include "MapFile.h" |
| 15 | #include "Memory.h" | ||
| 16 | #include "OutputSections.h" | 16 | #include "OutputSections.h" |
| 17 | #include "Relocations.h" | 17 | #include "Relocations.h" |
| 18 | #include "Strings.h" | 18 | #include "Strings.h" |
| 19 | #include "SymbolTable.h" | 19 | #include "SymbolTable.h" |
| 20 | #include "Symbols.h" | ||
| 20 | #include "SyntheticSections.h" | 21 | #include "SyntheticSections.h" |
| 21 | #include "Target.h" | 22 | #include "Target.h" |
| 22 | #include "Threads.h" | 23 | #include "lld/Common/Memory.h" |
| 24 | #include "lld/Common/Threads.h" | ||
| 23 | #include "llvm/ADT/StringMap.h" | 25 | #include "llvm/ADT/StringMap.h" |
| 24 | #include "llvm/ADT/StringSwitch.h" | 26 | #include "llvm/ADT/StringSwitch.h" |
| 25 | #include "llvm/Support/FileOutputBuffer.h" | ||
| 26 | #include "llvm/Support/raw_ostream.h" | ||
| 27 | #include <climits> | 27 | #include <climits> |
| 28 | 28 | ||
| 29 | using namespace llvm; | 29 | using namespace llvm; |
| ... | @@ -39,6 +39,7 @@ namespace { | ... | @@ -39,6 +39,7 @@ namespace { |
| 39 | // The writer writes a SymbolTable result to a file. | 39 | // The writer writes a SymbolTable result to a file. |
| 40 | template <class ELFT> class Writer { | 40 | template <class ELFT> class Writer { |
| 41 | public: | 41 | public: |
| 42 | Writer() : Buffer(errorHandler().OutputBuffer) {} | ||
| 42 | typedef typename ELFT::Shdr Elf_Shdr; | 43 | typedef typename ELFT::Shdr Elf_Shdr; |
| 43 | typedef typename ELFT::Ehdr Elf_Ehdr; | 44 | typedef typename ELFT::Ehdr Elf_Ehdr; |
| 44 | typedef typename ELFT::Phdr Elf_Phdr; | 45 | typedef typename ELFT::Phdr Elf_Phdr; |
| ... | @@ -46,43 +47,37 @@ public: | ... | @@ -46,43 +47,37 @@ public: |
| 46 | void run(); | 47 | void run(); |
| 47 | 48 | ||
| 48 | private: | 49 | private: |
| 49 | void clearOutputSections(); | ||
| 50 | void createSyntheticSections(); | ||
| 51 | void copyLocalSymbols(); | 50 | void copyLocalSymbols(); |
| 52 | void addSectionSymbols(); | 51 | void addSectionSymbols(); |
| 53 | void addReservedSymbols(); | ||
| 54 | void createSections(); | ||
| 55 | void forEachRelSec(std::function<void(InputSectionBase &)> Fn); | 52 | void forEachRelSec(std::function<void(InputSectionBase &)> Fn); |
| 56 | void sortSections(); | 53 | void sortSections(); |
| 54 | void resolveShfLinkOrder(); | ||
| 55 | void sortInputSections(); | ||
| 57 | void finalizeSections(); | 56 | void finalizeSections(); |
| 58 | void addPredefinedSections(); | 57 | void setReservedSymbolSections(); |
| 59 | 58 | ||
| 60 | std::vector<PhdrEntry> createPhdrs(); | 59 | std::vector<PhdrEntry *> createPhdrs(); |
| 61 | void removeEmptyPTLoad(); | 60 | void removeEmptyPTLoad(); |
| 62 | void addPtArmExid(std::vector<PhdrEntry> &Phdrs); | 61 | void addPtArmExid(std::vector<PhdrEntry *> &Phdrs); |
| 63 | void assignFileOffsets(); | 62 | void assignFileOffsets(); |
| 64 | void assignFileOffsetsBinary(); | 63 | void assignFileOffsetsBinary(); |
| 65 | void setPhdrs(); | 64 | void setPhdrs(); |
| 66 | void fixSectionAlignments(); | 65 | void fixSectionAlignments(); |
| 67 | void fixPredefinedSymbols(); | ||
| 68 | void openFile(); | 66 | void openFile(); |
| 67 | void writeTrapInstr(); | ||
| 69 | void writeHeader(); | 68 | void writeHeader(); |
| 70 | void writeSections(); | 69 | void writeSections(); |
| 71 | void writeSectionsBinary(); | 70 | void writeSectionsBinary(); |
| 72 | void writeBuildId(); | 71 | void writeBuildId(); |
| 73 | 72 | ||
| 74 | std::unique_ptr<FileOutputBuffer> Buffer; | 73 | std::unique_ptr<FileOutputBuffer> &Buffer; |
| 75 | |||
| 76 | OutputSectionFactory Factory; | ||
| 77 | 74 | ||
| 78 | void addRelIpltSymbols(); | 75 | void addRelIpltSymbols(); |
| 79 | void addStartEndSymbols(); | 76 | void addStartEndSymbols(); |
| 80 | void addStartStopSymbols(OutputSection *Sec); | 77 | void addStartStopSymbols(OutputSection *Sec); |
| 81 | uint64_t getEntryAddr(); | 78 | uint64_t getEntryAddr(); |
| 82 | OutputSection *findSectionInScript(StringRef Name); | ||
| 83 | OutputSectionCommand *findSectionCommand(StringRef Name); | ||
| 84 | 79 | ||
| 85 | std::vector<PhdrEntry> Phdrs; | 80 | std::vector<PhdrEntry *> Phdrs; |
| 86 | 81 | ||
| 87 | uint64_t FileSize; | 82 | uint64_t FileSize; |
| 88 | uint64_t SectionHeaderOff; | 83 | uint64_t SectionHeaderOff; |
| ... | @@ -91,49 +86,60 @@ private: | ... | @@ -91,49 +86,60 @@ private: |
| 91 | }; | 86 | }; |
| 92 | } // anonymous namespace | 87 | } // anonymous namespace |
| 93 | 88 | ||
| 94 | StringRef elf::getOutputSectionName(StringRef Name) { | 89 | StringRef elf::getOutputSectionName(InputSectionBase *S) { |
| 95 | // ".zdebug_" is a prefix for ZLIB-compressed sections. | 90 | // ".zdebug_" is a prefix for ZLIB-compressed sections. |
| 96 | // Because we decompressed input sections, we want to remove 'z'. | 91 | // Because we decompressed input sections, we want to remove 'z'. |
| 97 | if (Name.startswith(".zdebug_")) | 92 | if (S->Name.startswith(".zdebug_")) |
| 98 | return Saver.save("." + Name.substr(2)); | 93 | return Saver.save("." + S->Name.substr(2)); |
| 99 | 94 | ||
| 100 | if (Config->Relocatable) | 95 | if (Config->Relocatable) |
| 101 | return Name; | 96 | return S->Name; |
| 97 | |||
| 98 | // 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 not | ||
| 100 | // technically required, but not doing it is odd). This code guarantees that. | ||
| 101 | if ((S->Type == SHT_REL || S->Type == SHT_RELA) && | ||
| 102 | !isa<SyntheticSection>(S)) { | ||
| 103 | OutputSection *Out = | ||
| 104 | cast<InputSection>(S)->getRelocatedSection()->getOutputSection(); | ||
| 105 | if (S->Type == SHT_RELA) | ||
| 106 | return Saver.save(".rela" + Out->Name); | ||
| 107 | return Saver.save(".rel" + Out->Name); | ||
| 108 | } | ||
| 102 | 109 | ||
| 103 | for (StringRef V : | 110 | for (StringRef V : |
| 104 | {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", | 111 | {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", |
| 105 | ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", | 112 | ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", |
| 106 | ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) { | 113 | ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) { |
| 107 | StringRef Prefix = V.drop_back(); | 114 | StringRef Prefix = V.drop_back(); |
| 108 | if (Name.startswith(V) || Name == Prefix) | 115 | if (S->Name.startswith(V) || S->Name == Prefix) |
| 109 | return Prefix; | 116 | return Prefix; |
| 110 | } | 117 | } |
| 111 | 118 | ||
| 112 | // CommonSection is identified as "COMMON" in linker scripts. | 119 | // CommonSection is identified as "COMMON" in linker scripts. |
| 113 | // By default, it should go to .bss section. | 120 | // By default, it should go to .bss section. |
| 114 | if (Name == "COMMON") | 121 | if (S->Name == "COMMON") |
| 115 | return ".bss"; | 122 | return ".bss"; |
| 116 | 123 | ||
| 117 | return Name; | 124 | return S->Name; |
| 118 | } | 125 | } |
| 119 | 126 | ||
| 120 | template <class ELFT> static bool needsInterpSection() { | 127 | static bool needsInterpSection() { |
| 121 | return !Symtab<ELFT>::X->getSharedFiles().empty() && | 128 | return !SharedFiles.empty() && !Config->DynamicLinker.empty() && |
| 122 | !Config->DynamicLinker.empty() && !Script->ignoreInterpSection(); | 129 | Script->needsInterpSection(); |
| 123 | } | 130 | } |
| 124 | 131 | ||
| 125 | template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); } | 132 | template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); } |
| 126 | 133 | ||
| 127 | template <class ELFT> void Writer<ELFT>::removeEmptyPTLoad() { | 134 | template <class ELFT> void Writer<ELFT>::removeEmptyPTLoad() { |
| 128 | auto I = std::remove_if(Phdrs.begin(), Phdrs.end(), [&](const PhdrEntry &P) { | 135 | llvm::erase_if(Phdrs, [&](const PhdrEntry *P) { |
| 129 | if (P.p_type != PT_LOAD) | 136 | if (P->p_type != PT_LOAD) |
| 130 | return false; | 137 | return false; |
| 131 | if (!P.First) | 138 | if (!P->FirstSec) |
| 132 | return true; | 139 | return true; |
| 133 | uint64_t Size = P.Last->Addr + P.Last->Size - P.First->Addr; | 140 | uint64_t Size = P->LastSec->Addr + P->LastSec->Size - P->FirstSec->Addr; |
| 134 | return Size == 0; | 141 | return Size == 0; |
| 135 | }); | 142 | }); |
| 136 | Phdrs.erase(I, Phdrs.end()); | ||
| 137 | } | 143 | } |
| 138 | 144 | ||
| 139 | template <class ELFT> static void combineEhFrameSections() { | 145 | template <class ELFT> static void combineEhFrameSections() { |
| ... | @@ -142,7 +148,7 @@ template <class ELFT> static void combineEhFrameSections() { | ... | @@ -142,7 +148,7 @@ template <class ELFT> static void combineEhFrameSections() { |
| 142 | if (!ES || !ES->Live) | 148 | if (!ES || !ES->Live) |
| 143 | continue; | 149 | continue; |
| 144 | 150 | ||
| 145 | In<ELFT>::EhFrame->addSection(ES); | 151 | InX::EhFrame->addSection<ELFT>(ES); |
| 146 | S = nullptr; | 152 | S = nullptr; |
| 147 | } | 153 | } |
| 148 | 154 | ||
| ... | @@ -150,130 +156,87 @@ template <class ELFT> static void combineEhFrameSections() { | ... | @@ -150,130 +156,87 @@ template <class ELFT> static void combineEhFrameSections() { |
| 150 | V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); | 156 | V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); |
| 151 | } | 157 | } |
| 152 | 158 | ||
| 153 | template <class ELFT> void Writer<ELFT>::clearOutputSections() { | 159 | static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec, |
| 154 | // Clear the OutputSections to make sure it is not used anymore. Any | 160 | uint64_t Val, uint8_t StOther = STV_HIDDEN, |
| 155 | // code from this point on should be using the linker script | 161 | uint8_t Binding = STB_GLOBAL) { |
| 156 | // commands. | 162 | Symbol *S = Symtab->find(Name); |
| 157 | for (OutputSection *Sec : OutputSections) | 163 | if (!S || S->isDefined()) |
| 158 | Sec->Sections.clear(); | 164 | return nullptr; |
| 159 | OutputSections.clear(); | 165 | Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, |
| 166 | /*Size=*/0, Binding, Sec, | ||
| 167 | /*File=*/nullptr); | ||
| 168 | return cast<Defined>(Sym); | ||
| 160 | } | 169 | } |
| 161 | 170 | ||
| 162 | // The main function of the writer. | 171 | // The linker is expected to define some symbols depending on |
| 163 | template <class ELFT> void Writer<ELFT>::run() { | 172 | // the linking result. This function defines such symbols. |
| 164 | // Create linker-synthesized sections such as .got or .plt. | 173 | void elf::addReservedSymbols() { |
| 165 | // Such sections are of type input section. | 174 | if (Config->EMachine == EM_MIPS) { |
| 166 | createSyntheticSections(); | 175 | // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer |
| 167 | 176 | // so that it points to an absolute address which by default is relative | |
| 168 | if (!Config->Relocatable) | 177 | // to GOT. Default offset is 0x7ff0. |
| 169 | combineEhFrameSections<ELFT>(); | 178 | // See "Global Data Symbols" in Chapter 6 in the following document: |
| 170 | 179 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | |
| 171 | // We need to create some reserved symbols such as _end. Create them. | 180 | ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL); |
| 172 | if (!Config->Relocatable) | ||
| 173 | addReservedSymbols(); | ||
| 174 | |||
| 175 | // Create output sections. | ||
| 176 | if (Script->Opt.HasSections) { | ||
| 177 | // If linker script contains SECTIONS commands, let it create sections. | ||
| 178 | Script->processCommands(Factory); | ||
| 179 | |||
| 180 | // Linker scripts may have left some input sections unassigned. | ||
| 181 | // Assign such sections using the default rule. | ||
| 182 | Script->addOrphanSections(Factory); | ||
| 183 | } else { | ||
| 184 | // If linker script does not contain SECTIONS commands, create | ||
| 185 | // output sections by default rules. We still need to give the | ||
| 186 | // linker script a chance to run, because it might contain | ||
| 187 | // non-SECTIONS commands such as ASSERT. | ||
| 188 | Script->processCommands(Factory); | ||
| 189 | createSections(); | ||
| 190 | } | ||
| 191 | clearOutputSections(); | ||
| 192 | |||
| 193 | if (Config->Discard != DiscardPolicy::All) | ||
| 194 | copyLocalSymbols(); | ||
| 195 | |||
| 196 | if (Config->CopyRelocs) | ||
| 197 | addSectionSymbols(); | ||
| 198 | |||
| 199 | // Now that we have a complete set of output sections. This function | ||
| 200 | // completes section contents. For example, we need to add strings | ||
| 201 | // to the string table, and add entries to .got and .plt. | ||
| 202 | // finalizeSections does that. | ||
| 203 | finalizeSections(); | ||
| 204 | if (ErrorCount) | ||
| 205 | return; | ||
| 206 | |||
| 207 | if (!Script->Opt.HasSections && !Config->Relocatable) | ||
| 208 | fixSectionAlignments(); | ||
| 209 | |||
| 210 | // If -compressed-debug-sections is specified, we need to compress | ||
| 211 | // .debug_* sections. Do it right now because it changes the size of | ||
| 212 | // output sections. | ||
| 213 | parallelForEach( | ||
| 214 | OutputSectionCommands.begin(), OutputSectionCommands.end(), | ||
| 215 | [](OutputSectionCommand *Cmd) { Cmd->maybeCompress<ELFT>(); }); | ||
| 216 | |||
| 217 | Script->assignAddresses(); | ||
| 218 | Script->allocateHeaders(Phdrs); | ||
| 219 | |||
| 220 | // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a | ||
| 221 | // 0 sized region. This has to be done late since only after assignAddresses | ||
| 222 | // we know the size of the sections. | ||
| 223 | removeEmptyPTLoad(); | ||
| 224 | |||
| 225 | if (!Config->OFormatBinary) | ||
| 226 | assignFileOffsets(); | ||
| 227 | else | ||
| 228 | assignFileOffsetsBinary(); | ||
| 229 | 181 | ||
| 230 | setPhdrs(); | 182 | // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between |
| 183 | // start of function and 'gp' pointer into GOT. | ||
| 184 | if (Symtab->find("_gp_disp")) | ||
| 185 | ElfSym::MipsGpDisp = | ||
| 186 | Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL); | ||
| 231 | 187 | ||
| 232 | if (Config->Relocatable) { | 188 | // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' |
| 233 | for (OutputSectionCommand *Cmd : OutputSectionCommands) | 189 | // pointer. This symbol is used in the code generated by .cpload pseudo-op |
| 234 | Cmd->Sec->Addr = 0; | 190 | // in case of using -mno-shared option. |
| 235 | } else { | 191 | // https://sourceware.org/ml/binutils/2004-12/msg00094.html |
| 236 | fixPredefinedSymbols(); | 192 | if (Symtab->find("__gnu_local_gp")) |
| 193 | ElfSym::MipsLocalGp = | ||
| 194 | Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL); | ||
| 237 | } | 195 | } |
| 238 | 196 | ||
| 239 | // It does not make sense try to open the file if we have error already. | 197 | ElfSym::GlobalOffsetTable = addOptionalRegular( |
| 240 | if (ErrorCount) | 198 | "_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff); |
| 241 | return; | ||
| 242 | // Write the result down to a file. | ||
| 243 | openFile(); | ||
| 244 | if (ErrorCount) | ||
| 245 | return; | ||
| 246 | 199 | ||
| 247 | if (!Config->OFormatBinary) { | 200 | // __ehdr_start is the location of ELF file headers. Note that we define |
| 248 | writeHeader(); | 201 | // this symbol unconditionally even when using a linker script, which |
| 249 | writeSections(); | 202 | // differs from the behavior implemented by GNU linker which only define |
| 250 | } else { | 203 | // this symbol if ELF headers are in the memory mapped segment. |
| 251 | writeSectionsBinary(); | 204 | // __executable_start is not documented, but the expectation of at |
| 252 | } | 205 | // least the android libc is that it points to the elf header too. |
| 206 | // __dso_handle symbol is passed to cxa_finalize as a marker to identify | ||
| 207 | // each DSO. The address of the symbol doesn't matter as long as they are | ||
| 208 | // different in different DSOs, so we chose the start address of the DSO. | ||
| 209 | for (const char *Name : | ||
| 210 | {"__ehdr_start", "__executable_start", "__dso_handle"}) | ||
| 211 | addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN); | ||
| 253 | 212 | ||
| 254 | // Backfill .note.gnu.build-id section content. This is done at last | 213 | // If linker script do layout we do not need to create any standart symbols. |
| 255 | // because the content is usually a hash value of the entire output file. | 214 | if (Script->HasSectionsCommand) |
| 256 | writeBuildId(); | ||
| 257 | if (ErrorCount) | ||
| 258 | return; | 215 | return; |
| 259 | 216 | ||
| 260 | // Handle -Map option. | 217 | auto Add = [](StringRef S, int64_t Pos) { |
| 261 | writeMapFile<ELFT>(OutputSectionCommands); | 218 | return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT); |
| 262 | if (ErrorCount) | 219 | }; |
| 263 | return; | ||
| 264 | 220 | ||
| 265 | if (auto EC = Buffer->commit()) | 221 | ElfSym::Bss = Add("__bss_start", 0); |
| 266 | error("failed to write to the output file: " + EC.message()); | 222 | ElfSym::End1 = Add("end", -1); |
| 223 | ElfSym::End2 = Add("_end", -1); | ||
| 224 | ElfSym::Etext1 = Add("etext", -1); | ||
| 225 | ElfSym::Etext2 = Add("_etext", -1); | ||
| 226 | ElfSym::Edata1 = Add("edata", -1); | ||
| 227 | ElfSym::Edata2 = Add("_edata", -1); | ||
| 228 | } | ||
| 267 | 229 | ||
| 268 | // Flush the output streams and exit immediately. A full shutdown | 230 | static OutputSection *findSection(StringRef Name) { |
| 269 | // is a good test that we are keeping track of all allocated memory, | 231 | for (BaseCommand *Base : Script->SectionCommands) |
| 270 | // but actually freeing it is a waste of time in a regular linker run. | 232 | if (auto *Sec = dyn_cast<OutputSection>(Base)) |
| 271 | if (Config->ExitEarly) | 233 | if (Sec->Name == Name) |
| 272 | exitLld(0); | 234 | return Sec; |
| 235 | return nullptr; | ||
| 273 | } | 236 | } |
| 274 | 237 | ||
| 275 | // Initialize Out members. | 238 | // Initialize Out members. |
| 276 | template <class ELFT> void Writer<ELFT>::createSyntheticSections() { | 239 | template <class ELFT> static void createSyntheticSections() { |
| 277 | // Initialize all pointers with NULL. This is needed because | 240 | // Initialize all pointers with NULL. This is needed because |
| 278 | // you can call lld::elf::main more than once as a library. | 241 | // you can call lld::elf::main more than once as a library. |
| 279 | memset(&Out::First, 0, sizeof(Out)); | 242 | memset(&Out::First, 0, sizeof(Out)); |
| ... | @@ -282,16 +245,19 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { | ... | @@ -282,16 +245,19 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { |
| 282 | 245 | ||
| 283 | InX::DynStrTab = make<StringTableSection>(".dynstr", true); | 246 | InX::DynStrTab = make<StringTableSection>(".dynstr", true); |
| 284 | InX::Dynamic = make<DynamicSection<ELFT>>(); | 247 | InX::Dynamic = make<DynamicSection<ELFT>>(); |
| 285 | In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>( | 248 | if (Config->AndroidPackDynRelocs) { |
| 286 | Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); | 249 | InX::RelaDyn = make<AndroidPackedRelocationSection<ELFT>>( |
| 250 | Config->IsRela ? ".rela.dyn" : ".rel.dyn"); | ||
| 251 | } else { | ||
| 252 | InX::RelaDyn = make<RelocationSection<ELFT>>( | ||
| 253 | Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); | ||
| 254 | } | ||
| 287 | InX::ShStrTab = make<StringTableSection>(".shstrtab", false); | 255 | InX::ShStrTab = make<StringTableSection>(".shstrtab", false); |
| 288 | 256 | ||
| 289 | Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC); | ||
| 290 | Out::ElfHeader->Size = sizeof(Elf_Ehdr); | ||
| 291 | Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC); | 257 | Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC); |
| 292 | Out::ProgramHeaders->updateAlignment(Config->Wordsize); | 258 | Out::ProgramHeaders->Alignment = Config->Wordsize; |
| 293 | 259 | ||
| 294 | if (needsInterpSection<ELFT>()) { | 260 | if (needsInterpSection()) { |
| 295 | InX::Interp = createInterpSection(); | 261 | InX::Interp = createInterpSection(); |
| 296 | Add(InX::Interp); | 262 | Add(InX::Interp); |
| 297 | } else { | 263 | } else { |
| ... | @@ -308,20 +274,21 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { | ... | @@ -308,20 +274,21 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { |
| 308 | Add(InX::BuildId); | 274 | Add(InX::BuildId); |
| 309 | } | 275 | } |
| 310 | 276 | ||
| 311 | InX::Common = createCommonSection<ELFT>(); | 277 | InX::Bss = make<BssSection>(".bss", 0, 1); |
| 312 | if (InX::Common) | ||
| 313 | Add(InX::Common); | ||
| 314 | |||
| 315 | InX::Bss = make<BssSection>(".bss"); | ||
| 316 | Add(InX::Bss); | 278 | Add(InX::Bss); |
| 317 | InX::BssRelRo = make<BssSection>(".bss.rel.ro"); | 279 | |
| 280 | // If there is a SECTIONS command and a .data.rel.ro section name use name | ||
| 281 | // .data.rel.ro.bss so that we match in the .data.rel.ro output section. | ||
| 282 | // This makes sure our relro is contiguous. | ||
| 283 | bool HasDataRelRo = | ||
| 284 | Script->HasSectionsCommand && findSection(".data.rel.ro"); | ||
| 285 | InX::BssRelRo = make<BssSection>( | ||
| 286 | HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1); | ||
| 318 | Add(InX::BssRelRo); | 287 | Add(InX::BssRelRo); |
| 319 | 288 | ||
| 320 | // Add MIPS-specific sections. | 289 | // Add MIPS-specific sections. |
| 321 | bool HasDynSymTab = !Symtab<ELFT>::X->getSharedFiles().empty() || | ||
| 322 | Config->Pic || Config->ExportDynamic; | ||
| 323 | if (Config->EMachine == EM_MIPS) { | 290 | if (Config->EMachine == EM_MIPS) { |
| 324 | if (!Config->Shared && HasDynSymTab) { | 291 | if (!Config->Shared && Config->HasDynSymTab) { |
| 325 | InX::MipsRldMap = make<MipsRldMapSection>(); | 292 | InX::MipsRldMap = make<MipsRldMapSection>(); |
| 326 | Add(InX::MipsRldMap); | 293 | Add(InX::MipsRldMap); |
| 327 | } | 294 | } |
| ... | @@ -333,7 +300,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { | ... | @@ -333,7 +300,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { |
| 333 | Add(Sec); | 300 | Add(Sec); |
| 334 | } | 301 | } |
| 335 | 302 | ||
| 336 | if (HasDynSymTab) { | 303 | if (Config->HasDynSymTab) { |
| 337 | InX::DynSymTab = make<SymbolTableSection<ELFT>>(*InX::DynStrTab); | 304 | InX::DynSymTab = make<SymbolTableSection<ELFT>>(*InX::DynStrTab); |
| 338 | Add(InX::DynSymTab); | 305 | Add(InX::DynSymTab); |
| 339 | 306 | ||
| ... | @@ -354,13 +321,13 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { | ... | @@ -354,13 +321,13 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { |
| 354 | } | 321 | } |
| 355 | 322 | ||
| 356 | if (Config->SysvHash) { | 323 | if (Config->SysvHash) { |
| 357 | In<ELFT>::HashTab = make<HashTableSection<ELFT>>(); | 324 | InX::HashTab = make<HashTableSection>(); |
| 358 | Add(In<ELFT>::HashTab); | 325 | Add(InX::HashTab); |
| 359 | } | 326 | } |
| 360 | 327 | ||
| 361 | Add(InX::Dynamic); | 328 | Add(InX::Dynamic); |
| 362 | Add(InX::DynStrTab); | 329 | Add(InX::DynStrTab); |
| 363 | Add(In<ELFT>::RelaDyn); | 330 | Add(InX::RelaDyn); |
| 364 | } | 331 | } |
| 365 | 332 | ||
| 366 | // Add .got. MIPS' .got is so different from the other archs, | 333 | // Add .got. MIPS' .got is so different from the other archs, |
| ... | @@ -385,16 +352,22 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { | ... | @@ -385,16 +352,22 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { |
| 385 | 352 | ||
| 386 | // We always need to add rel[a].plt to output if it has entries. | 353 | // We always need to add rel[a].plt to output if it has entries. |
| 387 | // Even for static linking it can contain R_[*]_IRELATIVE relocations. | 354 | // Even for static linking it can contain R_[*]_IRELATIVE relocations. |
| 388 | In<ELFT>::RelaPlt = make<RelocationSection<ELFT>>( | 355 | InX::RelaPlt = make<RelocationSection<ELFT>>( |
| 389 | Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/); | 356 | Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/); |
| 390 | Add(In<ELFT>::RelaPlt); | 357 | Add(InX::RelaPlt); |
| 391 | 358 | ||
| 392 | // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure | 359 | // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure |
| 393 | // that the IRelative relocations are processed last by the dynamic loader | 360 | // that the IRelative relocations are processed last by the dynamic loader. |
| 394 | In<ELFT>::RelaIplt = make<RelocationSection<ELFT>>( | 361 | // We cannot place the iplt section in .rel.dyn when Android relocation |
| 395 | (Config->EMachine == EM_ARM) ? ".rel.dyn" : In<ELFT>::RelaPlt->Name, | 362 | // packing is enabled because that would cause a section type mismatch. |
| 363 | // However, because the Android dynamic loader reads .rel.plt after .rel.dyn, | ||
| 364 | // we can get the desired behaviour by placing the iplt section in .rel.plt. | ||
| 365 | InX::RelaIplt = make<RelocationSection<ELFT>>( | ||
| 366 | (Config->EMachine == EM_ARM && !Config->AndroidPackDynRelocs) | ||
| 367 | ? ".rel.dyn" | ||
| 368 | : InX::RelaPlt->Name, | ||
| 396 | false /*Sort*/); | 369 | false /*Sort*/); |
| 397 | Add(In<ELFT>::RelaIplt); | 370 | Add(InX::RelaIplt); |
| 398 | 371 | ||
| 399 | InX::Plt = make<PltSection>(Target->PltHeaderSize); | 372 | InX::Plt = make<PltSection>(Target->PltHeaderSize); |
| 400 | Add(InX::Plt); | 373 | Add(InX::Plt); |
| ... | @@ -403,11 +376,11 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { | ... | @@ -403,11 +376,11 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { |
| 403 | 376 | ||
| 404 | if (!Config->Relocatable) { | 377 | if (!Config->Relocatable) { |
| 405 | if (Config->EhFrameHdr) { | 378 | if (Config->EhFrameHdr) { |
| 406 | In<ELFT>::EhFrameHdr = make<EhFrameHeader<ELFT>>(); | 379 | InX::EhFrameHdr = make<EhFrameHeader>(); |
| 407 | Add(In<ELFT>::EhFrameHdr); | 380 | Add(InX::EhFrameHdr); |
| 408 | } | 381 | } |
| 409 | In<ELFT>::EhFrame = make<EhFrameSection<ELFT>>(); | 382 | InX::EhFrame = make<EhFrameSection>(); |
| 410 | Add(In<ELFT>::EhFrame); | 383 | Add(InX::EhFrame); |
| 411 | } | 384 | } |
| 412 | 385 | ||
| 413 | if (InX::SymTab) | 386 | if (InX::SymTab) |
| ... | @@ -415,10 +388,105 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { | ... | @@ -415,10 +388,105 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { |
| 415 | Add(InX::ShStrTab); | 388 | Add(InX::ShStrTab); |
| 416 | if (InX::StrTab) | 389 | if (InX::StrTab) |
| 417 | Add(InX::StrTab); | 390 | Add(InX::StrTab); |
| 391 | |||
| 392 | if (Config->EMachine == EM_ARM && !Config->Relocatable) | ||
| 393 | // Add a sentinel to terminate .ARM.exidx. It helps an unwinder | ||
| 394 | // to find the exact address range of the last entry. | ||
| 395 | Add(make<ARMExidxSentinelSection>()); | ||
| 396 | } | ||
| 397 | |||
| 398 | // The main function of the writer. | ||
| 399 | template <class ELFT> void Writer<ELFT>::run() { | ||
| 400 | // Create linker-synthesized sections such as .got or .plt. | ||
| 401 | // Such sections are of type input section. | ||
| 402 | createSyntheticSections<ELFT>(); | ||
| 403 | |||
| 404 | if (!Config->Relocatable) | ||
| 405 | combineEhFrameSections<ELFT>(); | ||
| 406 | |||
| 407 | // We want to process linker script commands. When SECTIONS command | ||
| 408 | // is given we let it create sections. | ||
| 409 | Script->processSectionCommands(); | ||
| 410 | |||
| 411 | // Linker scripts controls how input sections are assigned to output sections. | ||
| 412 | // Input sections that were not handled by scripts are called "orphans", and | ||
| 413 | // they are assigned to output sections by the default rule. Process that. | ||
| 414 | Script->addOrphanSections(); | ||
| 415 | |||
| 416 | if (Config->Discard != DiscardPolicy::All) | ||
| 417 | copyLocalSymbols(); | ||
| 418 | |||
| 419 | if (Config->CopyRelocs) | ||
| 420 | addSectionSymbols(); | ||
| 421 | |||
| 422 | // Now that we have a complete set of output sections. This function | ||
| 423 | // completes section contents. For example, we need to add strings | ||
| 424 | // to the string table, and add entries to .got and .plt. | ||
| 425 | // finalizeSections does that. | ||
| 426 | finalizeSections(); | ||
| 427 | if (errorCount()) | ||
| 428 | return; | ||
| 429 | |||
| 430 | Script->assignAddresses(); | ||
| 431 | |||
| 432 | // If -compressed-debug-sections is specified, we need to compress | ||
| 433 | // .debug_* sections. Do it right now because it changes the size of | ||
| 434 | // output sections. | ||
| 435 | for (OutputSection *Sec : OutputSections) | ||
| 436 | Sec->maybeCompress<ELFT>(); | ||
| 437 | |||
| 438 | Script->allocateHeaders(Phdrs); | ||
| 439 | |||
| 440 | // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a | ||
| 441 | // 0 sized region. This has to be done late since only after assignAddresses | ||
| 442 | // we know the size of the sections. | ||
| 443 | removeEmptyPTLoad(); | ||
| 444 | |||
| 445 | if (!Config->OFormatBinary) | ||
| 446 | assignFileOffsets(); | ||
| 447 | else | ||
| 448 | assignFileOffsetsBinary(); | ||
| 449 | |||
| 450 | setPhdrs(); | ||
| 451 | |||
| 452 | if (Config->Relocatable) { | ||
| 453 | for (OutputSection *Sec : OutputSections) | ||
| 454 | Sec->Addr = 0; | ||
| 455 | } | ||
| 456 | |||
| 457 | // It does not make sense try to open the file if we have error already. | ||
| 458 | if (errorCount()) | ||
| 459 | return; | ||
| 460 | // Write the result down to a file. | ||
| 461 | openFile(); | ||
| 462 | if (errorCount()) | ||
| 463 | return; | ||
| 464 | |||
| 465 | if (!Config->OFormatBinary) { | ||
| 466 | writeTrapInstr(); | ||
| 467 | writeHeader(); | ||
| 468 | writeSections(); | ||
| 469 | } else { | ||
| 470 | writeSectionsBinary(); | ||
| 471 | } | ||
| 472 | |||
| 473 | // Backfill .note.gnu.build-id section content. This is done at last | ||
| 474 | // because the content is usually a hash value of the entire output file. | ||
| 475 | writeBuildId(); | ||
| 476 | if (errorCount()) | ||
| 477 | return; | ||
| 478 | |||
| 479 | // Handle -Map option. | ||
| 480 | writeMapFile(); | ||
| 481 | if (errorCount()) | ||
| 482 | return; | ||
| 483 | |||
| 484 | if (auto E = Buffer->commit()) | ||
| 485 | error("failed to write to the output file: " + toString(std::move(E))); | ||
| 418 | } | 486 | } |
| 419 | 487 | ||
| 420 | static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, | 488 | static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, |
| 421 | const SymbolBody &B) { | 489 | const Symbol &B) { |
| 422 | if (B.isFile() || B.isSection()) | 490 | if (B.isFile() || B.isSection()) |
| 423 | return false; | 491 | return false; |
| 424 | 492 | ||
| ... | @@ -443,27 +511,25 @@ static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, | ... | @@ -443,27 +511,25 @@ static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, |
| 443 | return !Sec || !(Sec->Flags & SHF_MERGE); | 511 | return !Sec || !(Sec->Flags & SHF_MERGE); |
| 444 | } | 512 | } |
| 445 | 513 | ||
| 446 | static bool includeInSymtab(const SymbolBody &B) { | 514 | static bool includeInSymtab(const Symbol &B) { |
| 447 | if (!B.isLocal() && !B.symbol()->IsUsedInRegularObj) | 515 | if (!B.isLocal() && !B.IsUsedInRegularObj) |
| 448 | return false; | 516 | return false; |
| 449 | 517 | ||
| 450 | if (auto *D = dyn_cast<DefinedRegular>(&B)) { | 518 | if (auto *D = dyn_cast<Defined>(&B)) { |
| 451 | // Always include absolute symbols. | 519 | // Always include absolute symbols. |
| 452 | SectionBase *Sec = D->Section; | 520 | SectionBase *Sec = D->Section; |
| 453 | if (!Sec) | 521 | if (!Sec) |
| 454 | return true; | 522 | return true; |
| 455 | if (auto *IS = dyn_cast<InputSectionBase>(Sec)) { | 523 | Sec = Sec->Repl; |
| 456 | Sec = IS->Repl; | 524 | // Exclude symbols pointing to garbage-collected sections. |
| 457 | IS = cast<InputSectionBase>(Sec); | 525 | if (isa<InputSectionBase>(Sec) && !Sec->Live) |
| 458 | // Exclude symbols pointing to garbage-collected sections. | 526 | return false; |
| 459 | if (!IS->Live) | ||
| 460 | return false; | ||
| 461 | } | ||
| 462 | if (auto *S = dyn_cast<MergeInputSection>(Sec)) | 527 | if (auto *S = dyn_cast<MergeInputSection>(Sec)) |
| 463 | if (!S->getSectionPiece(D->Value)->Live) | 528 | if (!S->getSectionPiece(D->Value)->Live) |
| 464 | return false; | 529 | return false; |
| 530 | return true; | ||
| 465 | } | 531 | } |
| 466 | return true; | 532 | return B.Used; |
| 467 | } | 533 | } |
| 468 | 534 | ||
| 469 | // Local symbols are not in the linker's symbol table. This function scans | 535 | // Local symbols are not in the linker's symbol table. This function scans |
| ... | @@ -471,12 +537,13 @@ static bool includeInSymtab(const SymbolBody &B) { | ... | @@ -471,12 +537,13 @@ static bool includeInSymtab(const SymbolBody &B) { |
| 471 | template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { | 537 | template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { |
| 472 | if (!InX::SymTab) | 538 | if (!InX::SymTab) |
| 473 | return; | 539 | return; |
| 474 | for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) { | 540 | for (InputFile *File : ObjectFiles) { |
| 475 | for (SymbolBody *B : F->getLocalSymbols()) { | 541 | ObjFile<ELFT> *F = cast<ObjFile<ELFT>>(File); |
| 476 | if (!B->IsLocal) | 542 | for (Symbol *B : F->getLocalSymbols()) { |
| 543 | if (!B->isLocal()) | ||
| 477 | fatal(toString(F) + | 544 | fatal(toString(F) + |
| 478 | ": broken object: getLocalSymbols returns a non-local symbol"); | 545 | ": broken object: getLocalSymbols returns a non-local symbol"); |
| 479 | auto *DR = dyn_cast<DefinedRegular>(B); | 546 | auto *DR = dyn_cast<Defined>(B); |
| 480 | 547 | ||
| 481 | // No reason to keep local undefined symbol in symtab. | 548 | // No reason to keep local undefined symbol in symtab. |
| 482 | if (!DR) | 549 | if (!DR) |
| ... | @@ -493,27 +560,36 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { | ... | @@ -493,27 +560,36 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { |
| 493 | } | 560 | } |
| 494 | 561 | ||
| 495 | template <class ELFT> void Writer<ELFT>::addSectionSymbols() { | 562 | template <class ELFT> void Writer<ELFT>::addSectionSymbols() { |
| 496 | // Create one STT_SECTION symbol for each output section we might | 563 | // Create a section symbol for each output section so that we can represent |
| 497 | // have a relocation with. | 564 | // relocations that point to the section. If we know that no relocation is |
| 498 | for (BaseCommand *Base : Script->Opt.Commands) { | 565 | // referring to a section (that happens if the section is a synthetic one), we |
| 499 | auto *Cmd = dyn_cast<OutputSectionCommand>(Base); | 566 | // don't create a section symbol for that section. |
| 500 | if (!Cmd) | 567 | for (BaseCommand *Base : Script->SectionCommands) { |
| 568 | auto *Sec = dyn_cast<OutputSection>(Base); | ||
| 569 | if (!Sec) | ||
| 501 | continue; | 570 | continue; |
| 502 | auto I = llvm::find_if(Cmd->Commands, [](BaseCommand *Base) { | 571 | auto I = llvm::find_if(Sec->SectionCommands, [](BaseCommand *Base) { |
| 503 | if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) | 572 | if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) |
| 504 | return !ISD->Sections.empty(); | 573 | return !ISD->Sections.empty(); |
| 505 | return false; | 574 | return false; |
| 506 | }); | 575 | }); |
| 507 | if (I == Cmd->Commands.end()) | 576 | if (I == Sec->SectionCommands.end()) |
| 508 | continue; | 577 | continue; |
| 509 | InputSection *IS = cast<InputSectionDescription>(*I)->Sections[0]; | 578 | InputSection *IS = cast<InputSectionDescription>(*I)->Sections[0]; |
| 510 | if (isa<SyntheticSection>(IS) || IS->Type == SHT_REL || | 579 | |
| 511 | IS->Type == SHT_RELA) | 580 | // Relocations are not using REL[A] section symbols. |
| 581 | if (IS->Type == SHT_REL || IS->Type == SHT_RELA) | ||
| 582 | continue; | ||
| 583 | |||
| 584 | // Unlike other synthetic sections, mergeable output sections contain data | ||
| 585 | // copied from input sections, and there may be a relocation pointing to its | ||
| 586 | // contents if -r or -emit-reloc are given. | ||
| 587 | if (isa<SyntheticSection>(IS) && !(IS->Flags & SHF_MERGE)) | ||
| 512 | continue; | 588 | continue; |
| 513 | 589 | ||
| 514 | auto *Sym = | 590 | auto *Sym = |
| 515 | make<DefinedRegular>("", /*IsLocal=*/true, /*StOther=*/0, STT_SECTION, | 591 | make<Defined>(IS->File, "", STB_LOCAL, /*StOther=*/0, STT_SECTION, |
| 516 | /*Value=*/0, /*Size=*/0, IS, nullptr); | 592 | /*Value=*/0, /*Size=*/0, IS); |
| 517 | InX::SymTab->addSymbol(Sym); | 593 | InX::SymTab->addSymbol(Sym); |
| 518 | } | 594 | } |
| 519 | } | 595 | } |
| ... | @@ -524,7 +600,7 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() { | ... | @@ -524,7 +600,7 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() { |
| 524 | // | 600 | // |
| 525 | // This function returns true if a section needs to be put into a | 601 | // This function returns true if a section needs to be put into a |
| 526 | // PT_GNU_RELRO segment. | 602 | // PT_GNU_RELRO segment. |
| 527 | bool elf::isRelroSection(const OutputSection *Sec) { | 603 | static bool isRelroSection(const OutputSection *Sec) { |
| 528 | if (!Config->ZRelro) | 604 | if (!Config->ZRelro) |
| 529 | return false; | 605 | return false; |
| 530 | 606 | ||
| ... | @@ -575,20 +651,14 @@ bool elf::isRelroSection(const OutputSection *Sec) { | ... | @@ -575,20 +651,14 @@ bool elf::isRelroSection(const OutputSection *Sec) { |
| 575 | if (Sec == InX::Dynamic->getParent()) | 651 | if (Sec == InX::Dynamic->getParent()) |
| 576 | return true; | 652 | return true; |
| 577 | 653 | ||
| 578 | // .bss.rel.ro is used for copy relocations for read-only symbols. | ||
| 579 | // Since the dynamic linker needs to process copy relocations, the | ||
| 580 | // section cannot be read-only, but once initialized, they shouldn't | ||
| 581 | // change. | ||
| 582 | if (Sec == InX::BssRelRo->getParent()) | ||
| 583 | return true; | ||
| 584 | |||
| 585 | // Sections with some special names are put into RELRO. This is a | 654 | // Sections with some special names are put into RELRO. This is a |
| 586 | // bit unfortunate because section names shouldn't be significant in | 655 | // bit unfortunate because section names shouldn't be significant in |
| 587 | // ELF in spirit. But in reality many linker features depend on | 656 | // ELF in spirit. But in reality many linker features depend on |
| 588 | // magic section names. | 657 | // magic section names. |
| 589 | StringRef S = Sec->Name; | 658 | StringRef S = Sec->Name; |
| 590 | return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" || | 659 | return S == ".data.rel.ro" || S == ".bss.rel.ro" || S == ".ctors" || |
| 591 | S == ".eh_frame" || S == ".openbsd.randomdata"; | 660 | S == ".dtors" || S == ".jcr" || S == ".eh_frame" || |
| 661 | S == ".openbsd.randomdata"; | ||
| 592 | } | 662 | } |
| 593 | 663 | ||
| 594 | // We compute a rank for each section. The rank indicates where the | 664 | // We compute a rank for each section. The rank indicates where the |
| ... | @@ -696,8 +766,8 @@ static unsigned getSectionRank(const OutputSection *Sec) { | ... | @@ -696,8 +766,8 @@ static unsigned getSectionRank(const OutputSection *Sec) { |
| 696 | if (IsNoBits) | 766 | if (IsNoBits) |
| 697 | Rank |= RF_BSS; | 767 | Rank |= RF_BSS; |
| 698 | 768 | ||
| 699 | // // Some architectures have additional ordering restrictions for sections | 769 | // Some architectures have additional ordering restrictions for sections |
| 700 | // // within the same PT_LOAD. | 770 | // within the same PT_LOAD. |
| 701 | if (Config->EMachine == EM_PPC64) { | 771 | if (Config->EMachine == EM_PPC64) { |
| 702 | // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections | 772 | // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections |
| 703 | // that we would like to make sure appear is a specific order to maximize | 773 | // that we would like to make sure appear is a specific order to maximize |
| ... | @@ -735,8 +805,8 @@ static unsigned getSectionRank(const OutputSection *Sec) { | ... | @@ -735,8 +805,8 @@ static unsigned getSectionRank(const OutputSection *Sec) { |
| 735 | } | 805 | } |
| 736 | 806 | ||
| 737 | static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) { | 807 | static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) { |
| 738 | const OutputSection *A = cast<OutputSectionCommand>(ACmd)->Sec; | 808 | const OutputSection *A = cast<OutputSection>(ACmd); |
| 739 | const OutputSection *B = cast<OutputSectionCommand>(BCmd)->Sec; | 809 | const OutputSection *B = cast<OutputSection>(BCmd); |
| 740 | if (A->SortRank != B->SortRank) | 810 | if (A->SortRank != B->SortRank) |
| 741 | return A->SortRank < B->SortRank; | 811 | return A->SortRank < B->SortRank; |
| 742 | if (!(A->SortRank & RF_NOT_ADDR_SET)) | 812 | if (!(A->SortRank & RF_NOT_ADDR_SET)) |
| ... | @@ -746,36 +816,12 @@ static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) { | ... | @@ -746,36 +816,12 @@ static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) { |
| 746 | } | 816 | } |
| 747 | 817 | ||
| 748 | void PhdrEntry::add(OutputSection *Sec) { | 818 | void PhdrEntry::add(OutputSection *Sec) { |
| 749 | Last = Sec; | 819 | LastSec = Sec; |
| 750 | if (!First) | 820 | if (!FirstSec) |
| 751 | First = Sec; | 821 | FirstSec = Sec; |
| 752 | p_align = std::max(p_align, Sec->Alignment); | 822 | p_align = std::max(p_align, Sec->Alignment); |
| 753 | if (p_type == PT_LOAD) | 823 | if (p_type == PT_LOAD) |
| 754 | Sec->FirstInPtLoad = First; | 824 | Sec->PtLoad = this; |
| 755 | } | ||
| 756 | |||
| 757 | template <class ELFT> | ||
| 758 | static Symbol *addRegular(StringRef Name, SectionBase *Sec, uint64_t Value, | ||
| 759 | uint8_t StOther = STV_HIDDEN, | ||
| 760 | uint8_t Binding = STB_WEAK) { | ||
| 761 | // The linker generated symbols are added as STB_WEAK to allow user defined | ||
| 762 | // ones to override them. | ||
| 763 | return Symtab<ELFT>::X->addRegular(Name, StOther, STT_NOTYPE, Value, | ||
| 764 | /*Size=*/0, Binding, Sec, | ||
| 765 | /*File=*/nullptr); | ||
| 766 | } | ||
| 767 | |||
| 768 | template <class ELFT> | ||
| 769 | static DefinedRegular * | ||
| 770 | addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, | ||
| 771 | uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) { | ||
| 772 | SymbolBody *S = Symtab<ELFT>::X->find(Name); | ||
| 773 | if (!S) | ||
| 774 | return nullptr; | ||
| 775 | if (S->isInCurrentDSO()) | ||
| 776 | return nullptr; | ||
| 777 | return cast<DefinedRegular>( | ||
| 778 | addRegular<ELFT>(Name, Sec, Val, StOther, Binding)->body()); | ||
| 779 | } | 825 | } |
| 780 | 826 | ||
| 781 | // The beginning and the ending of .rel[a].plt section are marked | 827 | // The beginning and the ending of .rel[a].plt section are marked |
| ... | @@ -785,177 +831,115 @@ addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, | ... | @@ -785,177 +831,115 @@ addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, |
| 785 | // need these symbols, since IRELATIVE relocs are resolved through GOT | 831 | // need these symbols, since IRELATIVE relocs are resolved through GOT |
| 786 | // and PLT. For details, see http://www.airs.com/blog/archives/403. | 832 | // and PLT. For details, see http://www.airs.com/blog/archives/403. |
| 787 | template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { | 833 | template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { |
| 788 | if (InX::DynSymTab) | 834 | if (!Config->Static) |
| 789 | return; | 835 | return; |
| 790 | StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; | 836 | StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; |
| 791 | addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0, STV_HIDDEN, STB_WEAK); | 837 | addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); |
| 792 | 838 | ||
| 793 | S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; | 839 | S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; |
| 794 | addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1, STV_HIDDEN, STB_WEAK); | 840 | addOptionalRegular(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK); |
| 795 | } | 841 | } |
| 796 | 842 | ||
| 797 | // The linker is expected to define some symbols depending on | 843 | template <class ELFT> |
| 798 | // the linking result. This function defines such symbols. | 844 | void Writer<ELFT>::forEachRelSec(std::function<void(InputSectionBase &)> Fn) { |
| 799 | template <class ELFT> void Writer<ELFT>::addReservedSymbols() { | 845 | // Scan all relocations. Each relocation goes through a series |
| 800 | if (Config->EMachine == EM_MIPS) { | 846 | // of tests to determine if it needs special treatment, such as |
| 801 | // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer | 847 | // creating GOT, PLT, copy relocations, etc. |
| 802 | // so that it points to an absolute address which by default is relative | 848 | // Note that relocations for non-alloc sections are directly |
| 803 | // to GOT. Default offset is 0x7ff0. | 849 | // processed by InputSection::relocateNonAlloc. |
| 804 | // See "Global Data Symbols" in Chapter 6 in the following document: | 850 | for (InputSectionBase *IS : InputSections) |
| 805 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 851 | if (IS->Live && isa<InputSection>(IS) && (IS->Flags & SHF_ALLOC)) |
| 806 | ElfSym::MipsGp = Symtab<ELFT>::X->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL); | 852 | Fn(*IS); |
| 807 | 853 | for (EhInputSection *ES : InX::EhFrame->Sections) | |
| 808 | // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between | 854 | Fn(*ES); |
| 809 | // start of function and 'gp' pointer into GOT. | 855 | } |
| 810 | if (Symtab<ELFT>::X->find("_gp_disp")) | ||
| 811 | ElfSym::MipsGpDisp = | ||
| 812 | Symtab<ELFT>::X->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL); | ||
| 813 | 856 | ||
| 814 | // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' | 857 | // This function generates assignments for predefined symbols (e.g. _end or |
| 815 | // pointer. This symbol is used in the code generated by .cpload pseudo-op | 858 | // _etext) and inserts them into the commands sequence to be processed at the |
| 816 | // in case of using -mno-shared option. | 859 | // appropriate time. This ensures that the value is going to be correct by the |
| 817 | // https://sourceware.org/ml/binutils/2004-12/msg00094.html | 860 | // time any references to these symbols are processed and is equivalent to |
| 818 | if (Symtab<ELFT>::X->find("__gnu_local_gp")) | 861 | // defining these symbols explicitly in the linker script. |
| 819 | ElfSym::MipsLocalGp = | 862 | template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { |
| 820 | Symtab<ELFT>::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); | 863 | if (ElfSym::GlobalOffsetTable) { |
| 864 | // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to | ||
| 865 | // be at some offset from the base of the .got section, usually 0 or the end | ||
| 866 | // of the .got | ||
| 867 | InputSection *GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot) | ||
| 868 | : cast<InputSection>(InX::Got); | ||
| 869 | ElfSym::GlobalOffsetTable->Section = GotSection; | ||
| 821 | } | 870 | } |
| 822 | 871 | ||
| 823 | // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to | 872 | PhdrEntry *Last = nullptr; |
| 824 | // be at some offset from the base of the .got section, usually 0 or the end | 873 | PhdrEntry *LastRO = nullptr; |
| 825 | // of the .got | ||
| 826 | InputSection *GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot) | ||
| 827 | : cast<InputSection>(InX::Got); | ||
| 828 | ElfSym::GlobalOffsetTable = addOptionalRegular<ELFT>( | ||
| 829 | "_GLOBAL_OFFSET_TABLE_", GotSection, Target->GotBaseSymOff); | ||
| 830 | |||
| 831 | // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For | ||
| 832 | // static linking the linker is required to optimize away any references to | ||
| 833 | // __tls_get_addr, so it's not defined anywhere. Create a hidden definition | ||
| 834 | // to avoid the undefined symbol error. | ||
| 835 | if (!InX::DynSymTab) | ||
| 836 | Symtab<ELFT>::X->addIgnored("__tls_get_addr"); | ||
| 837 | |||
| 838 | // __ehdr_start is the location of ELF file headers. Note that we define | ||
| 839 | // this symbol unconditionally even when using a linker script, which | ||
| 840 | // differs from the behavior implemented by GNU linker which only define | ||
| 841 | // this symbol if ELF headers are in the memory mapped segment. | ||
| 842 | // __executable_start is not documented, but the expectation of at | ||
| 843 | // least the android libc is that it points to the elf header too. | ||
| 844 | // __dso_handle symbol is passed to cxa_finalize as a marker to identify | ||
| 845 | // each DSO. The address of the symbol doesn't matter as long as they are | ||
| 846 | // different in different DSOs, so we chose the start address of the DSO. | ||
| 847 | for (const char *Name : | ||
| 848 | {"__ehdr_start", "__executable_start", "__dso_handle"}) | ||
| 849 | addOptionalRegular<ELFT>(Name, Out::ElfHeader, 0, STV_HIDDEN); | ||
| 850 | |||
| 851 | // If linker script do layout we do not need to create any standart symbols. | ||
| 852 | if (Script->Opt.HasSections) | ||
| 853 | return; | ||
| 854 | |||
| 855 | auto Add = [](StringRef S) { | ||
| 856 | return addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT); | ||
| 857 | }; | ||
| 858 | |||
| 859 | ElfSym::Bss = Add("__bss_start"); | ||
| 860 | ElfSym::End1 = Add("end"); | ||
| 861 | ElfSym::End2 = Add("_end"); | ||
| 862 | ElfSym::Etext1 = Add("etext"); | ||
| 863 | ElfSym::Etext2 = Add("_etext"); | ||
| 864 | ElfSym::Edata1 = Add("edata"); | ||
| 865 | ElfSym::Edata2 = Add("_edata"); | ||
| 866 | } | ||
| 867 | |||
| 868 | // Sort input sections by section name suffixes for | ||
| 869 | // __attribute__((init_priority(N))). | ||
| 870 | static void sortInitFini(OutputSectionCommand *Cmd) { | ||
| 871 | if (Cmd) | ||
| 872 | Cmd->sortInitFini(); | ||
| 873 | } | ||
| 874 | 874 | ||
| 875 | // Sort input sections by the special rule for .ctors and .dtors. | 875 | for (PhdrEntry *P : Phdrs) { |
| 876 | static void sortCtorsDtors(OutputSectionCommand *Cmd) { | 876 | if (P->p_type != PT_LOAD) |
| 877 | if (Cmd) | 877 | continue; |
| 878 | Cmd->sortCtorsDtors(); | 878 | Last = P; |
| 879 | } | 879 | if (!(P->p_flags & PF_W)) |
| 880 | LastRO = P; | ||
| 881 | } | ||
| 880 | 882 | ||
| 881 | // Sort input sections using the list provided by --symbol-ordering-file. | 883 | if (LastRO) { |
| 882 | template <class ELFT> static void sortBySymbolsOrder() { | 884 | // _etext is the first location after the last read-only loadable segment. |
| 883 | if (Config->SymbolOrderingFile.empty()) | 885 | if (ElfSym::Etext1) |
| 884 | return; | 886 | ElfSym::Etext1->Section = LastRO->LastSec; |
| 887 | if (ElfSym::Etext2) | ||
| 888 | ElfSym::Etext2->Section = LastRO->LastSec; | ||
| 889 | } | ||
| 885 | 890 | ||
| 886 | // Build a map from symbols to their priorities. Symbols that didn't | 891 | if (Last) { |
| 887 | // appear in the symbol ordering file have the lowest priority 0. | 892 | // _edata points to the end of the last mapped initialized section. |
| 888 | // All explicitly mentioned symbols have negative (higher) priorities. | 893 | OutputSection *Edata = nullptr; |
| 889 | DenseMap<StringRef, int> SymbolOrder; | 894 | for (OutputSection *OS : OutputSections) { |
| 890 | int Priority = -Config->SymbolOrderingFile.size(); | 895 | if (OS->Type != SHT_NOBITS) |
| 891 | for (StringRef S : Config->SymbolOrderingFile) | 896 | Edata = OS; |
| 892 | SymbolOrder.insert({S, Priority++}); | 897 | if (OS == Last->LastSec) |
| 893 | 898 | break; | |
| 894 | // Build a map from sections to their priorities. | ||
| 895 | DenseMap<SectionBase *, int> SectionOrder; | ||
| 896 | for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) { | ||
| 897 | for (SymbolBody *Body : File->getSymbols()) { | ||
| 898 | auto *D = dyn_cast<DefinedRegular>(Body); | ||
| 899 | if (!D || !D->Section) | ||
| 900 | continue; | ||
| 901 | int &Priority = SectionOrder[D->Section]; | ||
| 902 | Priority = std::min(Priority, SymbolOrder.lookup(D->getName())); | ||
| 903 | } | 899 | } |
| 904 | } | ||
| 905 | 900 | ||
| 906 | // Sort sections by priority. | 901 | if (ElfSym::Edata1) |
| 907 | for (BaseCommand *Base : Script->Opt.Commands) | 902 | ElfSym::Edata1->Section = Edata; |
| 908 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) | 903 | if (ElfSym::Edata2) |
| 909 | Cmd->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); }); | 904 | ElfSym::Edata2->Section = Edata; |
| 910 | } | ||
| 911 | 905 | ||
| 912 | template <class ELFT> | 906 | // _end is the first location after the uninitialized data region. |
| 913 | void Writer<ELFT>::forEachRelSec(std::function<void(InputSectionBase &)> Fn) { | 907 | if (ElfSym::End1) |
| 914 | for (InputSectionBase *IS : InputSections) { | 908 | ElfSym::End1->Section = Last->LastSec; |
| 915 | if (!IS->Live) | 909 | if (ElfSym::End2) |
| 916 | continue; | 910 | ElfSym::End2->Section = Last->LastSec; |
| 917 | // Scan all relocations. Each relocation goes through a series | ||
| 918 | // of tests to determine if it needs special treatment, such as | ||
| 919 | // creating GOT, PLT, copy relocations, etc. | ||
| 920 | // Note that relocations for non-alloc sections are directly | ||
| 921 | // processed by InputSection::relocateNonAlloc. | ||
| 922 | if (!(IS->Flags & SHF_ALLOC)) | ||
| 923 | continue; | ||
| 924 | if (isa<InputSection>(IS) || isa<EhInputSection>(IS)) | ||
| 925 | Fn(*IS); | ||
| 926 | } | 911 | } |
| 927 | 912 | ||
| 928 | if (!Config->Relocatable) { | 913 | if (ElfSym::Bss) |
| 929 | for (EhInputSection *ES : In<ELFT>::EhFrame->Sections) | 914 | ElfSym::Bss->Section = findSection(".bss"); |
| 930 | Fn(*ES); | ||
| 931 | } | ||
| 932 | } | ||
| 933 | 915 | ||
| 934 | template <class ELFT> void Writer<ELFT>::createSections() { | 916 | // Setup MIPS _gp_disp/__gnu_local_gp symbols which should |
| 935 | for (InputSectionBase *IS : InputSections) | 917 | // be equal to the _gp symbol's value. |
| 936 | if (IS) | 918 | if (ElfSym::MipsGp) { |
| 937 | Factory.addInputSec(IS, getOutputSectionName(IS->Name)); | 919 | // Find GP-relative section with the lowest address |
| 938 | 920 | // and use this address to calculate default _gp value. | |
| 939 | Script->fabricateDefaultCommands(); | 921 | for (OutputSection *OS : OutputSections) { |
| 940 | sortBySymbolsOrder<ELFT>(); | 922 | if (OS->Flags & SHF_MIPS_GPREL) { |
| 941 | sortInitFini(findSectionCommand(".init_array")); | 923 | ElfSym::MipsGp->Section = OS; |
| 942 | sortInitFini(findSectionCommand(".fini_array")); | 924 | ElfSym::MipsGp->Value = 0x7ff0; |
| 943 | sortCtorsDtors(findSectionCommand(".ctors")); | 925 | break; |
| 944 | sortCtorsDtors(findSectionCommand(".dtors")); | 926 | } |
| 927 | } | ||
| 928 | } | ||
| 945 | } | 929 | } |
| 946 | 930 | ||
| 947 | // We want to find how similar two ranks are. | 931 | // We want to find how similar two ranks are. |
| 948 | // The more branches in getSectionRank that match, the more similar they are. | 932 | // The more branches in getSectionRank that match, the more similar they are. |
| 949 | // Since each branch corresponds to a bit flag, we can just use | 933 | // Since each branch corresponds to a bit flag, we can just use |
| 950 | // countLeadingZeros. | 934 | // countLeadingZeros. |
| 951 | static int getRankProximity(OutputSection *A, OutputSection *B) { | 935 | static int getRankProximityAux(OutputSection *A, OutputSection *B) { |
| 952 | return countLeadingZeros(A->SortRank ^ B->SortRank); | 936 | return countLeadingZeros(A->SortRank ^ B->SortRank); |
| 953 | } | 937 | } |
| 954 | 938 | ||
| 955 | static int getRankProximity(OutputSection *A, BaseCommand *B) { | 939 | static int getRankProximity(OutputSection *A, BaseCommand *B) { |
| 956 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(B)) | 940 | if (auto *Sec = dyn_cast<OutputSection>(B)) |
| 957 | if (Cmd->Sec) | 941 | if (Sec->Live) |
| 958 | return getRankProximity(A, Cmd->Sec); | 942 | return getRankProximityAux(A, Sec); |
| 959 | return -1; | 943 | return -1; |
| 960 | } | 944 | } |
| 961 | 945 | ||
| ... | @@ -974,7 +958,7 @@ static int getRankProximity(OutputSection *A, BaseCommand *B) { | ... | @@ -974,7 +958,7 @@ static int getRankProximity(OutputSection *A, BaseCommand *B) { |
| 974 | // rw_sec : { *(rw_sec) } | 958 | // rw_sec : { *(rw_sec) } |
| 975 | // would mean that the RW PT_LOAD would become unaligned. | 959 | // would mean that the RW PT_LOAD would become unaligned. |
| 976 | static bool shouldSkip(BaseCommand *Cmd) { | 960 | static bool shouldSkip(BaseCommand *Cmd) { |
| 977 | if (isa<OutputSectionCommand>(Cmd)) | 961 | if (isa<OutputSection>(Cmd)) |
| 978 | return false; | 962 | return false; |
| 979 | if (auto *Assign = dyn_cast<SymbolAssignment>(Cmd)) | 963 | if (auto *Assign = dyn_cast<SymbolAssignment>(Cmd)) |
| 980 | return Assign->Name != "."; | 964 | return Assign->Name != "."; |
| ... | @@ -988,7 +972,7 @@ template <typename ELFT> | ... | @@ -988,7 +972,7 @@ template <typename ELFT> |
| 988 | static std::vector<BaseCommand *>::iterator | 972 | static std::vector<BaseCommand *>::iterator |
| 989 | findOrphanPos(std::vector<BaseCommand *>::iterator B, | 973 | findOrphanPos(std::vector<BaseCommand *>::iterator B, |
| 990 | std::vector<BaseCommand *>::iterator E) { | 974 | std::vector<BaseCommand *>::iterator E) { |
| 991 | OutputSection *Sec = cast<OutputSectionCommand>(*E)->Sec; | 975 | OutputSection *Sec = cast<OutputSection>(*E); |
| 992 | 976 | ||
| 993 | // Find the first element that has as close a rank as possible. | 977 | // Find the first element that has as close a rank as possible. |
| 994 | auto I = std::max_element(B, E, [=](BaseCommand *A, BaseCommand *B) { | 978 | auto I = std::max_element(B, E, [=](BaseCommand *A, BaseCommand *B) { |
| ... | @@ -1000,44 +984,84 @@ findOrphanPos(std::vector<BaseCommand *>::iterator B, | ... | @@ -1000,44 +984,84 @@ findOrphanPos(std::vector<BaseCommand *>::iterator B, |
| 1000 | // Consider all existing sections with the same proximity. | 984 | // Consider all existing sections with the same proximity. |
| 1001 | int Proximity = getRankProximity(Sec, *I); | 985 | int Proximity = getRankProximity(Sec, *I); |
| 1002 | for (; I != E; ++I) { | 986 | for (; I != E; ++I) { |
| 1003 | auto *Cmd = dyn_cast<OutputSectionCommand>(*I); | 987 | auto *CurSec = dyn_cast<OutputSection>(*I); |
| 1004 | if (!Cmd || !Cmd->Sec) | 988 | if (!CurSec || !CurSec->Live) |
| 1005 | continue; | 989 | continue; |
| 1006 | if (getRankProximity(Sec, Cmd->Sec) != Proximity || | 990 | if (getRankProximity(Sec, CurSec) != Proximity || |
| 1007 | Sec->SortRank < Cmd->Sec->SortRank) | 991 | Sec->SortRank < CurSec->SortRank) |
| 1008 | break; | 992 | break; |
| 1009 | } | 993 | } |
| 1010 | auto J = std::find_if( | 994 | |
| 1011 | llvm::make_reverse_iterator(I), llvm::make_reverse_iterator(B), | 995 | auto IsLiveSection = [](BaseCommand *Cmd) { |
| 1012 | [](BaseCommand *Cmd) { return isa<OutputSectionCommand>(Cmd); }); | 996 | auto *OS = dyn_cast<OutputSection>(Cmd); |
| 997 | return OS && OS->Live; | ||
| 998 | }; | ||
| 999 | |||
| 1000 | auto J = std::find_if(llvm::make_reverse_iterator(I), | ||
| 1001 | llvm::make_reverse_iterator(B), IsLiveSection); | ||
| 1013 | I = J.base(); | 1002 | I = J.base(); |
| 1003 | |||
| 1004 | // As a special case, if the orphan section is the last section, put | ||
| 1005 | // it at the very end, past any other commands. | ||
| 1006 | // This matches bfd's behavior and is convenient when the linker script fully | ||
| 1007 | // specifies the start of the file, but doesn't care about the end (the non | ||
| 1008 | // alloc sections for example). | ||
| 1009 | auto NextSec = std::find_if(I, E, IsLiveSection); | ||
| 1010 | if (NextSec == E) | ||
| 1011 | return E; | ||
| 1012 | |||
| 1014 | while (I != E && shouldSkip(*I)) | 1013 | while (I != E && shouldSkip(*I)) |
| 1015 | ++I; | 1014 | ++I; |
| 1016 | return I; | 1015 | return I; |
| 1017 | } | 1016 | } |
| 1018 | 1017 | ||
| 1018 | // If no layout was provided by linker script, we want to apply default | ||
| 1019 | // sorting for special input sections and handle --symbol-ordering-file. | ||
| 1020 | template <class ELFT> void Writer<ELFT>::sortInputSections() { | ||
| 1021 | assert(!Script->HasSectionsCommand); | ||
| 1022 | |||
| 1023 | // Sort input sections by priority using the list provided | ||
| 1024 | // by --symbol-ordering-file. | ||
| 1025 | DenseMap<SectionBase *, int> Order = buildSectionOrder(); | ||
| 1026 | if (!Order.empty()) | ||
| 1027 | for (BaseCommand *Base : Script->SectionCommands) | ||
| 1028 | if (auto *Sec = dyn_cast<OutputSection>(Base)) | ||
| 1029 | if (Sec->Live) | ||
| 1030 | Sec->sort([&](InputSectionBase *S) { return Order.lookup(S); }); | ||
| 1031 | |||
| 1032 | // Sort input sections by section name suffixes for | ||
| 1033 | // __attribute__((init_priority(N))). | ||
| 1034 | if (OutputSection *Sec = findSection(".init_array")) | ||
| 1035 | Sec->sortInitFini(); | ||
| 1036 | if (OutputSection *Sec = findSection(".fini_array")) | ||
| 1037 | Sec->sortInitFini(); | ||
| 1038 | |||
| 1039 | // Sort input sections by the special rule for .ctors and .dtors. | ||
| 1040 | if (OutputSection *Sec = findSection(".ctors")) | ||
| 1041 | Sec->sortCtorsDtors(); | ||
| 1042 | if (OutputSection *Sec = findSection(".dtors")) | ||
| 1043 | Sec->sortCtorsDtors(); | ||
| 1044 | } | ||
| 1045 | |||
| 1019 | template <class ELFT> void Writer<ELFT>::sortSections() { | 1046 | template <class ELFT> void Writer<ELFT>::sortSections() { |
| 1020 | if (Script->Opt.HasSections) | 1047 | Script->adjustSectionsBeforeSorting(); |
| 1021 | Script->adjustSectionsBeforeSorting(); | ||
| 1022 | 1048 | ||
| 1023 | // Don't sort if using -r. It is not necessary and we want to preserve the | 1049 | // Don't sort if using -r. It is not necessary and we want to preserve the |
| 1024 | // relative order for SHF_LINK_ORDER sections. | 1050 | // relative order for SHF_LINK_ORDER sections. |
| 1025 | if (Config->Relocatable) | 1051 | if (Config->Relocatable) |
| 1026 | return; | 1052 | return; |
| 1027 | 1053 | ||
| 1028 | for (BaseCommand *Base : Script->Opt.Commands) | 1054 | for (BaseCommand *Base : Script->SectionCommands) |
| 1029 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) | 1055 | if (auto *Sec = dyn_cast<OutputSection>(Base)) |
| 1030 | if (OutputSection *Sec = Cmd->Sec) | 1056 | Sec->SortRank = getSectionRank(Sec); |
| 1031 | Sec->SortRank = getSectionRank(Sec); | 1057 | |
| 1032 | 1058 | if (!Script->HasSectionsCommand) { | |
| 1033 | if (!Script->Opt.HasSections) { | 1059 | sortInputSections(); |
| 1034 | // We know that all the OutputSectionCommands are contiguous in | 1060 | |
| 1035 | // this case. | 1061 | // We know that all the OutputSections are contiguous in this case. |
| 1036 | auto E = Script->Opt.Commands.end(); | 1062 | auto E = Script->SectionCommands.end(); |
| 1037 | auto I = Script->Opt.Commands.begin(); | 1063 | auto I = Script->SectionCommands.begin(); |
| 1038 | auto IsSection = [](BaseCommand *Base) { | 1064 | auto IsSection = [](BaseCommand *Base) { return isa<OutputSection>(Base); }; |
| 1039 | return isa<OutputSectionCommand>(Base); | ||
| 1040 | }; | ||
| 1041 | I = std::find_if(I, E, IsSection); | 1065 | I = std::find_if(I, E, IsSection); |
| 1042 | E = std::find_if(llvm::make_reverse_iterator(E), | 1066 | E = std::find_if(llvm::make_reverse_iterator(E), |
| 1043 | llvm::make_reverse_iterator(I), IsSection) | 1067 | llvm::make_reverse_iterator(I), IsSection) |
| ... | @@ -1077,7 +1101,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() { | ... | @@ -1077,7 +1101,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() { |
| 1077 | // a PT_LOAD. | 1101 | // a PT_LOAD. |
| 1078 | // | 1102 | // |
| 1079 | // There is some ambiguity as to where exactly a new entry should be | 1103 | // There is some ambiguity as to where exactly a new entry should be |
| 1080 | // inserted, because Opt.Commands contains not only output section | 1104 | // inserted, because Commands contains not only output section |
| 1081 | // commands but also other types of commands such as symbol assignment | 1105 | // commands but also other types of commands such as symbol assignment |
| 1082 | // expressions. There's no correct answer here due to the lack of the | 1106 | // expressions. There's no correct answer here due to the lack of the |
| 1083 | // formal specification of the linker script. We use heuristics to | 1107 | // formal specification of the linker script. We use heuristics to |
| ... | @@ -1085,11 +1109,11 @@ template <class ELFT> void Writer<ELFT>::sortSections() { | ... | @@ -1085,11 +1109,11 @@ template <class ELFT> void Writer<ELFT>::sortSections() { |
| 1085 | // after another commands. For the details, look at shouldSkip | 1109 | // after another commands. For the details, look at shouldSkip |
| 1086 | // function. | 1110 | // function. |
| 1087 | 1111 | ||
| 1088 | auto I = Script->Opt.Commands.begin(); | 1112 | auto I = Script->SectionCommands.begin(); |
| 1089 | auto E = Script->Opt.Commands.end(); | 1113 | auto E = Script->SectionCommands.end(); |
| 1090 | auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) { | 1114 | auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) { |
| 1091 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) | 1115 | if (auto *Sec = dyn_cast<OutputSection>(Base)) |
| 1092 | return Cmd->Sec && Cmd->Sec->SectionIndex == INT_MAX; | 1116 | return Sec->Live && Sec->SectionIndex == INT_MAX; |
| 1093 | return false; | 1117 | return false; |
| 1094 | }); | 1118 | }); |
| 1095 | 1119 | ||
| ... | @@ -1109,13 +1133,13 @@ template <class ELFT> void Writer<ELFT>::sortSections() { | ... | @@ -1109,13 +1133,13 @@ template <class ELFT> void Writer<ELFT>::sortSections() { |
| 1109 | 1133 | ||
| 1110 | while (NonScriptI != E) { | 1134 | while (NonScriptI != E) { |
| 1111 | auto Pos = findOrphanPos<ELFT>(I, NonScriptI); | 1135 | auto Pos = findOrphanPos<ELFT>(I, NonScriptI); |
| 1112 | OutputSection *Orphan = cast<OutputSectionCommand>(*NonScriptI)->Sec; | 1136 | OutputSection *Orphan = cast<OutputSection>(*NonScriptI); |
| 1113 | 1137 | ||
| 1114 | // As an optimization, find all sections with the same sort rank | 1138 | // As an optimization, find all sections with the same sort rank |
| 1115 | // and insert them with one rotate. | 1139 | // and insert them with one rotate. |
| 1116 | unsigned Rank = Orphan->SortRank; | 1140 | unsigned Rank = Orphan->SortRank; |
| 1117 | auto End = std::find_if(NonScriptI + 1, E, [=](BaseCommand *Cmd) { | 1141 | auto End = std::find_if(NonScriptI + 1, E, [=](BaseCommand *Cmd) { |
| 1118 | return cast<OutputSectionCommand>(Cmd)->Sec->SortRank != Rank; | 1142 | return cast<OutputSection>(Cmd)->SortRank != Rank; |
| 1119 | }); | 1143 | }); |
| 1120 | std::rotate(Pos, NonScriptI, End); | 1144 | std::rotate(Pos, NonScriptI, End); |
| 1121 | NonScriptI = End; | 1145 | NonScriptI = End; |
| ... | @@ -1124,6 +1148,139 @@ template <class ELFT> void Writer<ELFT>::sortSections() { | ... | @@ -1124,6 +1148,139 @@ template <class ELFT> void Writer<ELFT>::sortSections() { |
| 1124 | Script->adjustSectionsAfterSorting(); | 1148 | Script->adjustSectionsAfterSorting(); |
| 1125 | } | 1149 | } |
| 1126 | 1150 | ||
| 1151 | static bool compareByFilePosition(InputSection *A, InputSection *B) { | ||
| 1152 | // Synthetic, i. e. a sentinel section, should go last. | ||
| 1153 | if (A->kind() == InputSectionBase::Synthetic || | ||
| 1154 | B->kind() == InputSectionBase::Synthetic) | ||
| 1155 | return A->kind() != InputSectionBase::Synthetic; | ||
| 1156 | InputSection *LA = A->getLinkOrderDep(); | ||
| 1157 | InputSection *LB = B->getLinkOrderDep(); | ||
| 1158 | OutputSection *AOut = LA->getParent(); | ||
| 1159 | OutputSection *BOut = LB->getParent(); | ||
| 1160 | if (AOut != BOut) | ||
| 1161 | return AOut->SectionIndex < BOut->SectionIndex; | ||
| 1162 | return LA->OutSecOff < LB->OutSecOff; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | // This function is used by the --merge-exidx-entries to detect duplicate | ||
| 1166 | // .ARM.exidx sections. It is Arm only. | ||
| 1167 | // | ||
| 1168 | // The .ARM.exidx section is of the form: | ||
| 1169 | // | PREL31 offset to function | Unwind instructions for function | | ||
| 1170 | // where the unwind instructions are either a small number of unwind | ||
| 1171 | // instructions inlined into the table entry, the special CANT_UNWIND value of | ||
| 1172 | // 0x1 or a PREL31 offset into a .ARM.extab Section that contains unwind | ||
| 1173 | // instructions. | ||
| 1174 | // | ||
| 1175 | // We return true if all the unwind instructions in the .ARM.exidx entries of | ||
| 1176 | // Cur can be merged into the last entry of Prev. | ||
| 1177 | static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) { | ||
| 1178 | |||
| 1179 | // References to .ARM.Extab Sections have bit 31 clear and are not the | ||
| 1180 | // special EXIDX_CANTUNWIND bit-pattern. | ||
| 1181 | auto IsExtabRef = [](uint32_t Unwind) { | ||
| 1182 | return (Unwind & 0x80000000) == 0 && Unwind != 0x1; | ||
| 1183 | }; | ||
| 1184 | |||
| 1185 | struct ExidxEntry { | ||
| 1186 | ulittle32_t Fn; | ||
| 1187 | ulittle32_t Unwind; | ||
| 1188 | }; | ||
| 1189 | |||
| 1190 | // Get the last table Entry from the previous .ARM.exidx section. | ||
| 1191 | const ExidxEntry &PrevEntry = *reinterpret_cast<const ExidxEntry *>( | ||
| 1192 | Prev->Data.data() + Prev->getSize() - sizeof(ExidxEntry)); | ||
| 1193 | if (IsExtabRef(PrevEntry.Unwind)) | ||
| 1194 | return false; | ||
| 1195 | |||
| 1196 | // We consider the unwind instructions of an .ARM.exidx table entry | ||
| 1197 | // a duplicate if the previous unwind instructions if: | ||
| 1198 | // - Both are the special EXIDX_CANTUNWIND. | ||
| 1199 | // - Both are the same inline unwind instructions. | ||
| 1200 | // We do not attempt to follow and check links into .ARM.extab tables as | ||
| 1201 | // consecutive identical entries are rare and the effort to check that they | ||
| 1202 | // are identical is high. | ||
| 1203 | |||
| 1204 | if (isa<SyntheticSection>(Cur)) | ||
| 1205 | // Exidx sentinel section has implicit EXIDX_CANTUNWIND; | ||
| 1206 | return PrevEntry.Unwind == 0x1; | ||
| 1207 | |||
| 1208 | ArrayRef<const ExidxEntry> Entries( | ||
| 1209 | reinterpret_cast<const ExidxEntry *>(Cur->Data.data()), | ||
| 1210 | Cur->getSize() / sizeof(ExidxEntry)); | ||
| 1211 | for (const ExidxEntry &Entry : Entries) | ||
| 1212 | if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind) | ||
| 1213 | return false; | ||
| 1214 | // All table entries in this .ARM.exidx Section can be merged into the | ||
| 1215 | // previous Section. | ||
| 1216 | return true; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { | ||
| 1220 | for (OutputSection *Sec : OutputSections) { | ||
| 1221 | if (!(Sec->Flags & SHF_LINK_ORDER)) | ||
| 1222 | continue; | ||
| 1223 | |||
| 1224 | // Link order may be distributed across several InputSectionDescriptions | ||
| 1225 | // but sort must consider them all at once. | ||
| 1226 | std::vector<InputSection **> ScriptSections; | ||
| 1227 | std::vector<InputSection *> Sections; | ||
| 1228 | for (BaseCommand *Base : Sec->SectionCommands) { | ||
| 1229 | if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) { | ||
| 1230 | for (InputSection *&IS : ISD->Sections) { | ||
| 1231 | ScriptSections.push_back(&IS); | ||
| 1232 | Sections.push_back(IS); | ||
| 1233 | } | ||
| 1234 | } | ||
| 1235 | } | ||
| 1236 | std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); | ||
| 1237 | |||
| 1238 | if (!Config->Relocatable && Config->EMachine == EM_ARM && | ||
| 1239 | Sec->Type == SHT_ARM_EXIDX) { | ||
| 1240 | |||
| 1241 | if (!Sections.empty() && isa<ARMExidxSentinelSection>(Sections.back())) { | ||
| 1242 | assert(Sections.size() >= 2 && | ||
| 1243 | "We should create a sentinel section only if there are " | ||
| 1244 | "alive regular exidx sections."); | ||
| 1245 | // The last executable section is required to fill the sentinel. | ||
| 1246 | // Remember it here so that we don't have to find it again. | ||
| 1247 | auto *Sentinel = cast<ARMExidxSentinelSection>(Sections.back()); | ||
| 1248 | Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep(); | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | if (Config->MergeArmExidx) { | ||
| 1252 | // The EHABI for the Arm Architecture permits consecutive identical | ||
| 1253 | // table entries to be merged. We use a simple implementation that | ||
| 1254 | // removes a .ARM.exidx Input Section if it can be merged into the | ||
| 1255 | // previous one. This does not require any rewriting of InputSection | ||
| 1256 | // contents but misses opportunities for fine grained deduplication | ||
| 1257 | // where only a subset of the InputSection contents can be merged. | ||
| 1258 | int Cur = 1; | ||
| 1259 | int Prev = 0; | ||
| 1260 | // The last one is a sentinel entry which should not be removed. | ||
| 1261 | int N = Sections.size() - 1; | ||
| 1262 | while (Cur < N) { | ||
| 1263 | if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur])) | ||
| 1264 | Sections[Cur] = nullptr; | ||
| 1265 | else | ||
| 1266 | Prev = Cur; | ||
| 1267 | ++Cur; | ||
| 1268 | } | ||
| 1269 | } | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | for (int I = 0, N = Sections.size(); I < N; ++I) | ||
| 1273 | *ScriptSections[I] = Sections[I]; | ||
| 1274 | |||
| 1275 | // Remove the Sections we marked as duplicate earlier. | ||
| 1276 | for (BaseCommand *Base : Sec->SectionCommands) | ||
| 1277 | if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) | ||
| 1278 | ISD->Sections.erase( | ||
| 1279 | std::remove(ISD->Sections.begin(), ISD->Sections.end(), nullptr), | ||
| 1280 | ISD->Sections.end()); | ||
| 1281 | } | ||
| 1282 | } | ||
| 1283 | |||
| 1127 | static void applySynthetic(const std::vector<SyntheticSection *> &Sections, | 1284 | static void applySynthetic(const std::vector<SyntheticSection *> &Sections, |
| 1128 | std::function<void(SyntheticSection *)> Fn) { | 1285 | std::function<void(SyntheticSection *)> Fn) { |
| 1129 | for (SyntheticSection *SS : Sections) | 1286 | for (SyntheticSection *SS : Sections) |
| ... | @@ -1131,10 +1288,18 @@ static void applySynthetic(const std::vector<SyntheticSection *> &Sections, | ... | @@ -1131,10 +1288,18 @@ static void applySynthetic(const std::vector<SyntheticSection *> &Sections, |
| 1131 | Fn(SS); | 1288 | Fn(SS); |
| 1132 | } | 1289 | } |
| 1133 | 1290 | ||
| 1134 | // We need to add input synthetic sections early in createSyntheticSections() | 1291 | // In order to allow users to manipulate linker-synthesized sections, |
| 1135 | // to make them visible from linkescript side. But not all sections are always | 1292 | // we had to add synthetic sections to the input section list early, |
| 1136 | // required to be in output. For example we don't need dynamic section content | 1293 | // even before we make decisions whether they are needed. This allows |
| 1137 | // sometimes. This function filters out such unused sections from the output. | 1294 | // users to write scripts like this: ".mygot : { .got }". |
| 1295 | // | ||
| 1296 | // Doing it has an unintended side effects. If it turns out that we | ||
| 1297 | // don't need a .got (for example) at all because there's no | ||
| 1298 | // relocation that needs a .got, we don't want to emit .got. | ||
| 1299 | // | ||
| 1300 | // To deal with the above problem, this function is called after | ||
| 1301 | // scanRelocations is called to remove synthetic sections that turn | ||
| 1302 | // out to be empty. | ||
| 1138 | static void removeUnusedSyntheticSections() { | 1303 | static void removeUnusedSyntheticSections() { |
| 1139 | // All input synthetic sections that can be empty are placed after | 1304 | // All input synthetic sections that can be empty are placed after |
| 1140 | // all regular ones. We iterate over them all and exit at first | 1305 | // all regular ones. We iterate over them all and exit at first |
| ... | @@ -1146,55 +1311,73 @@ static void removeUnusedSyntheticSections() { | ... | @@ -1146,55 +1311,73 @@ static void removeUnusedSyntheticSections() { |
| 1146 | OutputSection *OS = SS->getParent(); | 1311 | OutputSection *OS = SS->getParent(); |
| 1147 | if (!SS->empty() || !OS) | 1312 | if (!SS->empty() || !OS) |
| 1148 | continue; | 1313 | continue; |
| 1149 | if ((SS == InX::Got || SS == InX::MipsGot) && ElfSym::GlobalOffsetTable) | ||
| 1150 | continue; | ||
| 1151 | 1314 | ||
| 1152 | OutputSectionCommand *Cmd = Script->getCmd(OS); | 1315 | std::vector<BaseCommand *>::iterator Empty = OS->SectionCommands.end(); |
| 1153 | std::vector<BaseCommand *>::iterator Empty = Cmd->Commands.end(); | 1316 | for (auto I = OS->SectionCommands.begin(), E = OS->SectionCommands.end(); |
| 1154 | for (auto I = Cmd->Commands.begin(), E = Cmd->Commands.end(); I != E; ++I) { | 1317 | I != E; ++I) { |
| 1155 | BaseCommand *B = *I; | 1318 | BaseCommand *B = *I; |
| 1156 | if (auto *ISD = dyn_cast<InputSectionDescription>(B)) { | 1319 | if (auto *ISD = dyn_cast<InputSectionDescription>(B)) { |
| 1157 | auto P = std::find(ISD->Sections.begin(), ISD->Sections.end(), SS); | 1320 | llvm::erase_if(ISD->Sections, |
| 1158 | if (P != ISD->Sections.end()) | 1321 | [=](InputSection *IS) { return IS == SS; }); |
| 1159 | ISD->Sections.erase(P); | ||
| 1160 | if (ISD->Sections.empty()) | 1322 | if (ISD->Sections.empty()) |
| 1161 | Empty = I; | 1323 | Empty = I; |
| 1162 | } | 1324 | } |
| 1163 | } | 1325 | } |
| 1164 | if (Empty != Cmd->Commands.end()) | 1326 | if (Empty != OS->SectionCommands.end()) |
| 1165 | Cmd->Commands.erase(Empty); | 1327 | OS->SectionCommands.erase(Empty); |
| 1166 | 1328 | ||
| 1167 | // If there are no other sections in the output section, remove it from the | 1329 | // If there are no other sections in the output section, remove it from the |
| 1168 | // output. | 1330 | // output. |
| 1169 | if (Cmd->Commands.empty()) { | 1331 | if (OS->SectionCommands.empty()) |
| 1170 | // Also remove script commands matching the output section. | 1332 | OS->Live = false; |
| 1171 | auto &Cmds = Script->Opt.Commands; | ||
| 1172 | auto I = std::remove_if(Cmds.begin(), Cmds.end(), [&](BaseCommand *Cmd) { | ||
| 1173 | if (auto *OSCmd = dyn_cast<OutputSectionCommand>(Cmd)) | ||
| 1174 | return OSCmd->Sec == OS; | ||
| 1175 | return false; | ||
| 1176 | }); | ||
| 1177 | Cmds.erase(I, Cmds.end()); | ||
| 1178 | } | ||
| 1179 | } | 1333 | } |
| 1180 | } | 1334 | } |
| 1181 | 1335 | ||
| 1336 | // Returns true if a symbol can be replaced at load-time by a symbol | ||
| 1337 | // with the same name defined in other ELF executable or DSO. | ||
| 1338 | static bool computeIsPreemptible(const Symbol &B) { | ||
| 1339 | assert(!B.isLocal()); | ||
| 1340 | // Only symbols that appear in dynsym can be preempted. | ||
| 1341 | if (!B.includeInDynsym()) | ||
| 1342 | return false; | ||
| 1343 | |||
| 1344 | // Only default visibility symbols can be preempted. | ||
| 1345 | if (B.Visibility != STV_DEFAULT) | ||
| 1346 | return false; | ||
| 1347 | |||
| 1348 | // At this point copy relocations have not been created yet, so any | ||
| 1349 | // symbol that is not defined locally is preemptible. | ||
| 1350 | if (!B.isDefined()) | ||
| 1351 | return true; | ||
| 1352 | |||
| 1353 | // If we have a dynamic list it specifies which local symbols are preemptible. | ||
| 1354 | if (Config->HasDynamicList) | ||
| 1355 | return false; | ||
| 1356 | |||
| 1357 | if (!Config->Shared) | ||
| 1358 | return false; | ||
| 1359 | |||
| 1360 | // -Bsymbolic means that definitions are not preempted. | ||
| 1361 | if (Config->Bsymbolic || (Config->BsymbolicFunctions && B.isFunc())) | ||
| 1362 | return false; | ||
| 1363 | return true; | ||
| 1364 | } | ||
| 1365 | |||
| 1182 | // Create output section objects and add them to OutputSections. | 1366 | // Create output section objects and add them to OutputSections. |
| 1183 | template <class ELFT> void Writer<ELFT>::finalizeSections() { | 1367 | template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1184 | Out::DebugInfo = findSectionInScript(".debug_info"); | 1368 | Out::DebugInfo = findSection(".debug_info"); |
| 1185 | Out::PreinitArray = findSectionInScript(".preinit_array"); | 1369 | Out::PreinitArray = findSection(".preinit_array"); |
| 1186 | Out::InitArray = findSectionInScript(".init_array"); | 1370 | Out::InitArray = findSection(".init_array"); |
| 1187 | Out::FiniArray = findSectionInScript(".fini_array"); | 1371 | Out::FiniArray = findSection(".fini_array"); |
| 1188 | 1372 | ||
| 1189 | // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop | 1373 | // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop |
| 1190 | // symbols for sections, so that the runtime can get the start and end | 1374 | // symbols for sections, so that the runtime can get the start and end |
| 1191 | // addresses of each section by section name. Add such symbols. | 1375 | // addresses of each section by section name. Add such symbols. |
| 1192 | if (!Config->Relocatable) { | 1376 | if (!Config->Relocatable) { |
| 1193 | addStartEndSymbols(); | 1377 | addStartEndSymbols(); |
| 1194 | for (BaseCommand *Base : Script->Opt.Commands) | 1378 | for (BaseCommand *Base : Script->SectionCommands) |
| 1195 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) | 1379 | if (auto *Sec = dyn_cast<OutputSection>(Base)) |
| 1196 | if (Cmd->Sec) | 1380 | addStartStopSymbols(Sec); |
| 1197 | addStartStopSymbols(Cmd->Sec); | ||
| 1198 | } | 1381 | } |
| 1199 | 1382 | ||
| 1200 | // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. | 1383 | // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. |
| ... | @@ -1202,7 +1385,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { | ... | @@ -1202,7 +1385,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1202 | // Even the author of gold doesn't remember why gold behaves that way. | 1385 | // Even the author of gold doesn't remember why gold behaves that way. |
| 1203 | // https://sourceware.org/ml/binutils/2002-03/msg00360.html | 1386 | // https://sourceware.org/ml/binutils/2002-03/msg00360.html |
| 1204 | if (InX::DynSymTab) | 1387 | if (InX::DynSymTab) |
| 1205 | addRegular<ELFT>("_DYNAMIC", InX::Dynamic, 0); | 1388 | Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, |
| 1389 | /*Size=*/0, STB_WEAK, InX::Dynamic, | ||
| 1390 | /*File=*/nullptr); | ||
| 1206 | 1391 | ||
| 1207 | // Define __rel[a]_iplt_{start,end} symbols if needed. | 1392 | // Define __rel[a]_iplt_{start,end} symbols if needed. |
| 1208 | addRelIpltSymbols(); | 1393 | addRelIpltSymbols(); |
| ... | @@ -1210,12 +1395,16 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { | ... | @@ -1210,12 +1395,16 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1210 | // This responsible for splitting up .eh_frame section into | 1395 | // This responsible for splitting up .eh_frame section into |
| 1211 | // pieces. The relocation scan uses those pieces, so this has to be | 1396 | // pieces. The relocation scan uses those pieces, so this has to be |
| 1212 | // earlier. | 1397 | // earlier. |
| 1213 | applySynthetic({In<ELFT>::EhFrame}, | 1398 | applySynthetic({InX::EhFrame}, |
| 1214 | [](SyntheticSection *SS) { SS->finalizeContents(); }); | 1399 | [](SyntheticSection *SS) { SS->finalizeContents(); }); |
| 1215 | 1400 | ||
| 1401 | for (Symbol *S : Symtab->getSymbols()) | ||
| 1402 | S->IsPreemptible |= computeIsPreemptible(*S); | ||
| 1403 | |||
| 1216 | // Scan relocations. This must be done after every symbol is declared so that | 1404 | // Scan relocations. This must be done after every symbol is declared so that |
| 1217 | // we can correctly decide if a dynamic relocation is needed. | 1405 | // we can correctly decide if a dynamic relocation is needed. |
| 1218 | forEachRelSec(scanRelocations<ELFT>); | 1406 | if (!Config->Relocatable) |
| 1407 | forEachRelSec(scanRelocations<ELFT>); | ||
| 1219 | 1408 | ||
| 1220 | if (InX::Plt && !InX::Plt->empty()) | 1409 | if (InX::Plt && !InX::Plt->empty()) |
| 1221 | InX::Plt->addSymbols(); | 1410 | InX::Plt->addSymbols(); |
| ... | @@ -1224,42 +1413,40 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { | ... | @@ -1224,42 +1413,40 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1224 | 1413 | ||
| 1225 | // Now that we have defined all possible global symbols including linker- | 1414 | // Now that we have defined all possible global symbols including linker- |
| 1226 | // synthesized ones. Visit all symbols to give the finishing touches. | 1415 | // synthesized ones. Visit all symbols to give the finishing touches. |
| 1227 | for (Symbol *S : Symtab<ELFT>::X->getSymbols()) { | 1416 | for (Symbol *Sym : Symtab->getSymbols()) { |
| 1228 | SymbolBody *Body = S->body(); | 1417 | if (!includeInSymtab(*Sym)) |
| 1229 | |||
| 1230 | if (!includeInSymtab(*Body)) | ||
| 1231 | continue; | 1418 | continue; |
| 1232 | if (InX::SymTab) | 1419 | if (InX::SymTab) |
| 1233 | InX::SymTab->addSymbol(Body); | 1420 | InX::SymTab->addSymbol(Sym); |
| 1234 | 1421 | ||
| 1235 | if (InX::DynSymTab && S->includeInDynsym()) { | 1422 | if (InX::DynSymTab && Sym->includeInDynsym()) { |
| 1236 | InX::DynSymTab->addSymbol(Body); | 1423 | InX::DynSymTab->addSymbol(Sym); |
| 1237 | if (auto *SS = dyn_cast<SharedSymbol>(Body)) | 1424 | if (auto *SS = dyn_cast<SharedSymbol>(Sym)) |
| 1238 | if (cast<SharedFile<ELFT>>(SS->File)->isNeeded()) | 1425 | if (cast<SharedFile<ELFT>>(Sym->File)->IsNeeded) |
| 1239 | In<ELFT>::VerNeed->addSymbol(SS); | 1426 | In<ELFT>::VerNeed->addSymbol(SS); |
| 1240 | } | 1427 | } |
| 1241 | } | 1428 | } |
| 1242 | 1429 | ||
| 1243 | // Do not proceed if there was an undefined symbol. | 1430 | // Do not proceed if there was an undefined symbol. |
| 1244 | if (ErrorCount) | 1431 | if (errorCount()) |
| 1245 | return; | 1432 | return; |
| 1246 | 1433 | ||
| 1247 | addPredefinedSections(); | ||
| 1248 | removeUnusedSyntheticSections(); | 1434 | removeUnusedSyntheticSections(); |
| 1249 | 1435 | ||
| 1250 | sortSections(); | 1436 | sortSections(); |
| 1437 | Script->removeEmptyCommands(); | ||
| 1251 | 1438 | ||
| 1252 | // Now that we have the final list, create a list of all the | 1439 | // Now that we have the final list, create a list of all the |
| 1253 | // OutputSectionCommands for convenience. | 1440 | // OutputSections for convenience. |
| 1254 | for (BaseCommand *Base : Script->Opt.Commands) | 1441 | for (BaseCommand *Base : Script->SectionCommands) |
| 1255 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) | 1442 | if (auto *Sec = dyn_cast<OutputSection>(Base)) |
| 1256 | OutputSectionCommands.push_back(Cmd); | 1443 | OutputSections.push_back(Sec); |
| 1257 | 1444 | ||
| 1258 | // Prefer command line supplied address over other constraints. | 1445 | // Prefer command line supplied address over other constraints. |
| 1259 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 1446 | for (OutputSection *Sec : OutputSections) { |
| 1260 | auto I = Config->SectionStartMap.find(Cmd->Name); | 1447 | auto I = Config->SectionStartMap.find(Sec->Name); |
| 1261 | if (I != Config->SectionStartMap.end()) | 1448 | if (I != Config->SectionStartMap.end()) |
| 1262 | Cmd->AddrExpr = [=] { return I->second; }; | 1449 | Sec->AddrExpr = [=] { return I->second; }; |
| 1263 | } | 1450 | } |
| 1264 | 1451 | ||
| 1265 | // This is a bit of a hack. A value of 0 means undef, so we set it | 1452 | // This is a bit of a hack. A value of 0 means undef, so we set it |
| ... | @@ -1268,8 +1455,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { | ... | @@ -1268,8 +1455,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1268 | Out::ElfHeader->SectionIndex = 1; | 1455 | Out::ElfHeader->SectionIndex = 1; |
| 1269 | 1456 | ||
| 1270 | unsigned I = 1; | 1457 | unsigned I = 1; |
| 1271 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 1458 | for (OutputSection *Sec : OutputSections) { |
| 1272 | OutputSection *Sec = Cmd->Sec; | ||
| 1273 | Sec->SectionIndex = I++; | 1459 | Sec->SectionIndex = I++; |
| 1274 | Sec->ShName = InX::ShStrTab->addString(Sec->Name); | 1460 | Sec->ShName = InX::ShStrTab->addString(Sec->Name); |
| 1275 | } | 1461 | } |
| ... | @@ -1283,66 +1469,64 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { | ... | @@ -1283,66 +1469,64 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1283 | Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); | 1469 | Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); |
| 1284 | } | 1470 | } |
| 1285 | 1471 | ||
| 1472 | // Some symbols are defined in term of program headers. Now that we | ||
| 1473 | // have the headers, we can find out which sections they point to. | ||
| 1474 | setReservedSymbolSections(); | ||
| 1475 | |||
| 1286 | // Dynamic section must be the last one in this list and dynamic | 1476 | // Dynamic section must be the last one in this list and dynamic |
| 1287 | // symbol table section (DynSymTab) must be the first one. | 1477 | // symbol table section (DynSymTab) must be the first one. |
| 1288 | applySynthetic({InX::DynSymTab, InX::Bss, InX::BssRelRo, | 1478 | applySynthetic( |
| 1289 | InX::GnuHashTab, In<ELFT>::HashTab, InX::SymTab, | 1479 | {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab, |
| 1290 | InX::ShStrTab, InX::StrTab, In<ELFT>::VerDef, | 1480 | InX::HashTab, InX::SymTab, InX::ShStrTab, InX::StrTab, |
| 1291 | InX::DynStrTab, InX::GdbIndex, InX::Got, | 1481 | In<ELFT>::VerDef, InX::DynStrTab, InX::Got, InX::MipsGot, |
| 1292 | InX::MipsGot, InX::IgotPlt, InX::GotPlt, | 1482 | InX::IgotPlt, InX::GotPlt, InX::RelaDyn, InX::RelaIplt, |
| 1293 | In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::RelaPlt, | 1483 | InX::RelaPlt, InX::Plt, InX::Iplt, InX::EhFrameHdr, |
| 1294 | InX::Plt, InX::Iplt, In<ELFT>::EhFrameHdr, | 1484 | In<ELFT>::VerSym, In<ELFT>::VerNeed, InX::Dynamic}, |
| 1295 | In<ELFT>::VerSym, In<ELFT>::VerNeed, InX::Dynamic}, | 1485 | [](SyntheticSection *SS) { SS->finalizeContents(); }); |
| 1296 | [](SyntheticSection *SS) { SS->finalizeContents(); }); | 1486 | |
| 1487 | if (!Script->HasSectionsCommand && !Config->Relocatable) | ||
| 1488 | fixSectionAlignments(); | ||
| 1489 | |||
| 1490 | // After link order processing .ARM.exidx sections can be deduplicated, which | ||
| 1491 | // needs to be resolved before any other address dependent operation. | ||
| 1492 | resolveShfLinkOrder(); | ||
| 1297 | 1493 | ||
| 1298 | // Some architectures use small displacements for jump instructions. | 1494 | // Some architectures need to generate content that depends on the address |
| 1299 | // It is linker's responsibility to create thunks containing long | 1495 | // of InputSections. For example some architectures use small displacements |
| 1300 | // jump instructions if jump targets are too far. Create thunks. | 1496 | // for jump instructions that is is the linker's responsibility for creating |
| 1301 | if (Target->NeedsThunks) { | 1497 | // range extension thunks for. As the generation of the content may also |
| 1302 | // FIXME: only ARM Interworking and Mips LA25 Thunks are implemented, | 1498 | // alter InputSection addresses we must converge to a fixed point. |
| 1303 | // these | 1499 | if (Target->NeedsThunks || Config->AndroidPackDynRelocs) { |
| 1304 | // do not require address information. To support range extension Thunks | ||
| 1305 | // we need to assign addresses so that we can tell if jump instructions | ||
| 1306 | // are out of range. This will need to turn into a loop that converges | ||
| 1307 | // when no more Thunks are added | ||
| 1308 | ThunkCreator TC; | 1500 | ThunkCreator TC; |
| 1309 | Script->assignAddresses(); | 1501 | AArch64Err843419Patcher A64P; |
| 1310 | if (TC.createThunks(OutputSectionCommands)) { | 1502 | bool Changed; |
| 1311 | applySynthetic({InX::MipsGot}, | 1503 | do { |
| 1312 | [](SyntheticSection *SS) { SS->updateAllocSize(); }); | 1504 | Script->assignAddresses(); |
| 1313 | if (TC.createThunks(OutputSectionCommands)) | 1505 | Changed = false; |
| 1314 | fatal("All non-range thunks should be created in first call"); | 1506 | if (Target->NeedsThunks) |
| 1315 | } | 1507 | Changed |= TC.createThunks(OutputSections); |
| 1508 | if (Config->FixCortexA53Errata843419) { | ||
| 1509 | if (Changed) | ||
| 1510 | Script->assignAddresses(); | ||
| 1511 | Changed |= A64P.createFixes(); | ||
| 1512 | } | ||
| 1513 | if (InX::MipsGot) | ||
| 1514 | InX::MipsGot->updateAllocSize(); | ||
| 1515 | Changed |= InX::RelaDyn->updateAllocSize(); | ||
| 1516 | } while (Changed); | ||
| 1316 | } | 1517 | } |
| 1317 | 1518 | ||
| 1318 | // Fill other section headers. The dynamic table is finalized | 1519 | // Fill other section headers. The dynamic table is finalized |
| 1319 | // at the end because some tags like RELSZ depend on result | 1520 | // at the end because some tags like RELSZ depend on result |
| 1320 | // of finalizing other sections. | 1521 | // of finalizing other sections. |
| 1321 | for (OutputSectionCommand *Cmd : OutputSectionCommands) | 1522 | for (OutputSection *Sec : OutputSections) |
| 1322 | Cmd->finalize<ELFT>(); | 1523 | Sec->finalize<ELFT>(); |
| 1323 | 1524 | ||
| 1324 | // createThunks may have added local symbols to the static symbol table | 1525 | // createThunks may have added local symbols to the static symbol table |
| 1325 | applySynthetic({InX::SymTab, InX::ShStrTab, InX::StrTab}, | 1526 | applySynthetic({InX::SymTab}, |
| 1326 | [](SyntheticSection *SS) { SS->postThunkContents(); }); | 1527 | [](SyntheticSection *SS) { SS->postThunkContents(); }); |
| 1327 | } | 1528 | } |
| 1328 | 1529 | ||
| 1329 | template <class ELFT> void Writer<ELFT>::addPredefinedSections() { | ||
| 1330 | // ARM ABI requires .ARM.exidx to be terminated by some piece of data. | ||
| 1331 | // We have the terminater synthetic section class. Add that at the end. | ||
| 1332 | OutputSectionCommand *Cmd = findSectionCommand(".ARM.exidx"); | ||
| 1333 | if (!Cmd || !Cmd->Sec || Config->Relocatable) | ||
| 1334 | return; | ||
| 1335 | |||
| 1336 | auto *Sentinel = make<ARMExidxSentinelSection>(); | ||
| 1337 | Cmd->Sec->addSection(Sentinel); | ||
| 1338 | // Add the sentinel to the last of these too. | ||
| 1339 | auto ISD = std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(), | ||
| 1340 | [](const BaseCommand *Base) { | ||
| 1341 | return isa<InputSectionDescription>(Base); | ||
| 1342 | }); | ||
| 1343 | cast<InputSectionDescription>(*ISD)->Sections.push_back(Sentinel); | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | // The linker is expected to define SECNAME_start and SECNAME_end | 1530 | // The linker is expected to define SECNAME_start and SECNAME_end |
| 1347 | // symbols for a few sections. This function defines them. | 1531 | // symbols for a few sections. This function defines them. |
| 1348 | template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { | 1532 | template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { |
| ... | @@ -1350,13 +1534,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { | ... | @@ -1350,13 +1534,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { |
| 1350 | // These symbols resolve to the image base if the section does not exist. | 1534 | // These symbols resolve to the image base if the section does not exist. |
| 1351 | // A special value -1 indicates end of the section. | 1535 | // A special value -1 indicates end of the section. |
| 1352 | if (OS) { | 1536 | if (OS) { |
| 1353 | addOptionalRegular<ELFT>(Start, OS, 0); | 1537 | addOptionalRegular(Start, OS, 0); |
| 1354 | addOptionalRegular<ELFT>(End, OS, -1); | 1538 | addOptionalRegular(End, OS, -1); |
| 1355 | } else { | 1539 | } else { |
| 1356 | if (Config->Pic) | 1540 | if (Config->Pic) |
| 1357 | OS = Out::ElfHeader; | 1541 | OS = Out::ElfHeader; |
| 1358 | addOptionalRegular<ELFT>(Start, OS, 0); | 1542 | addOptionalRegular(Start, OS, 0); |
| 1359 | addOptionalRegular<ELFT>(End, OS, 0); | 1543 | addOptionalRegular(End, OS, 0); |
| 1360 | } | 1544 | } |
| 1361 | }; | 1545 | }; |
| 1362 | 1546 | ||
| ... | @@ -1364,7 +1548,7 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { | ... | @@ -1364,7 +1548,7 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { |
| 1364 | Define("__init_array_start", "__init_array_end", Out::InitArray); | 1548 | Define("__init_array_start", "__init_array_end", Out::InitArray); |
| 1365 | Define("__fini_array_start", "__fini_array_end", Out::FiniArray); | 1549 | Define("__fini_array_start", "__fini_array_end", Out::FiniArray); |
| 1366 | 1550 | ||
| 1367 | if (OutputSection *Sec = findSectionInScript(".ARM.exidx")) | 1551 | if (OutputSection *Sec = findSection(".ARM.exidx")) |
| 1368 | Define("__exidx_start", "__exidx_end", Sec); | 1552 | Define("__exidx_start", "__exidx_end", Sec); |
| 1369 | } | 1553 | } |
| 1370 | 1554 | ||
| ... | @@ -1378,24 +1562,8 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) { | ... | @@ -1378,24 +1562,8 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) { |
| 1378 | StringRef S = Sec->Name; | 1562 | StringRef S = Sec->Name; |
| 1379 | if (!isValidCIdentifier(S)) | 1563 | if (!isValidCIdentifier(S)) |
| 1380 | return; | 1564 | return; |
| 1381 | addOptionalRegular<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); | 1565 | addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); |
| 1382 | addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); | 1566 | addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); |
| 1383 | } | ||
| 1384 | |||
| 1385 | template <class ELFT> | ||
| 1386 | OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) { | ||
| 1387 | for (BaseCommand *Base : Script->Opt.Commands) | ||
| 1388 | if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) | ||
| 1389 | if (Cmd->Name == Name) | ||
| 1390 | return Cmd; | ||
| 1391 | return nullptr; | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | template <class ELFT> | ||
| 1395 | OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) { | ||
| 1396 | if (OutputSectionCommand *Cmd = findSectionCommand(Name)) | ||
| 1397 | return Cmd->Sec; | ||
| 1398 | return nullptr; | ||
| 1399 | } | 1567 | } |
| 1400 | 1568 | ||
| 1401 | static bool needsPtLoad(OutputSection *Sec) { | 1569 | static bool needsPtLoad(OutputSection *Sec) { |
| ... | @@ -1424,19 +1592,19 @@ static uint64_t computeFlags(uint64_t Flags) { | ... | @@ -1424,19 +1592,19 @@ static uint64_t computeFlags(uint64_t Flags) { |
| 1424 | 1592 | ||
| 1425 | // Decide which program headers to create and which sections to include in each | 1593 | // Decide which program headers to create and which sections to include in each |
| 1426 | // one. | 1594 | // one. |
| 1427 | template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { | 1595 | template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() { |
| 1428 | std::vector<PhdrEntry> Ret; | 1596 | std::vector<PhdrEntry *> Ret; |
| 1429 | auto AddHdr = [&](unsigned Type, unsigned Flags) -> PhdrEntry * { | 1597 | auto AddHdr = [&](unsigned Type, unsigned Flags) -> PhdrEntry * { |
| 1430 | Ret.emplace_back(Type, Flags); | 1598 | Ret.push_back(make<PhdrEntry>(Type, Flags)); |
| 1431 | return &Ret.back(); | 1599 | return Ret.back(); |
| 1432 | }; | 1600 | }; |
| 1433 | 1601 | ||
| 1434 | // The first phdr entry is PT_PHDR which describes the program header itself. | 1602 | // The first phdr entry is PT_PHDR which describes the program header itself. |
| 1435 | AddHdr(PT_PHDR, PF_R)->add(Out::ProgramHeaders); | 1603 | AddHdr(PT_PHDR, PF_R)->add(Out::ProgramHeaders); |
| 1436 | 1604 | ||
| 1437 | // PT_INTERP must be the second entry if exists. | 1605 | // PT_INTERP must be the second entry if exists. |
| 1438 | if (OutputSection *Sec = findSectionInScript(".interp")) | 1606 | if (OutputSection *Cmd = findSection(".interp")) |
| 1439 | AddHdr(PT_INTERP, Sec->getPhdrFlags())->add(Sec); | 1607 | AddHdr(PT_INTERP, Cmd->getPhdrFlags())->add(Cmd); |
| 1440 | 1608 | ||
| 1441 | // Add the first PT_LOAD segment for regular output sections. | 1609 | // Add the first PT_LOAD segment for regular output sections. |
| 1442 | uint64_t Flags = computeFlags(PF_R); | 1610 | uint64_t Flags = computeFlags(PF_R); |
| ... | @@ -1446,8 +1614,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { | ... | @@ -1446,8 +1614,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { |
| 1446 | Load->add(Out::ElfHeader); | 1614 | Load->add(Out::ElfHeader); |
| 1447 | Load->add(Out::ProgramHeaders); | 1615 | Load->add(Out::ProgramHeaders); |
| 1448 | 1616 | ||
| 1449 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 1617 | for (OutputSection *Sec : OutputSections) { |
| 1450 | OutputSection *Sec = Cmd->Sec; | ||
| 1451 | if (!(Sec->Flags & SHF_ALLOC)) | 1618 | if (!(Sec->Flags & SHF_ALLOC)) |
| 1452 | break; | 1619 | break; |
| 1453 | if (!needsPtLoad(Sec)) | 1620 | if (!needsPtLoad(Sec)) |
| ... | @@ -1459,7 +1626,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { | ... | @@ -1459,7 +1626,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { |
| 1459 | // different flags or is loaded at a discontiguous address using AT linker | 1626 | // different flags or is loaded at a discontiguous address using AT linker |
| 1460 | // script command. | 1627 | // script command. |
| 1461 | uint64_t NewFlags = computeFlags(Sec->getPhdrFlags()); | 1628 | uint64_t NewFlags = computeFlags(Sec->getPhdrFlags()); |
| 1462 | if (Cmd->LMAExpr || Flags != NewFlags) { | 1629 | if (Sec->LMAExpr || Flags != NewFlags) { |
| 1463 | Load = AddHdr(PT_LOAD, NewFlags); | 1630 | Load = AddHdr(PT_LOAD, NewFlags); |
| 1464 | Flags = NewFlags; | 1631 | Flags = NewFlags; |
| 1465 | } | 1632 | } |
| ... | @@ -1468,14 +1635,12 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { | ... | @@ -1468,14 +1635,12 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { |
| 1468 | } | 1635 | } |
| 1469 | 1636 | ||
| 1470 | // Add a TLS segment if any. | 1637 | // Add a TLS segment if any. |
| 1471 | PhdrEntry TlsHdr(PT_TLS, PF_R); | 1638 | PhdrEntry *TlsHdr = make<PhdrEntry>(PT_TLS, PF_R); |
| 1472 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 1639 | for (OutputSection *Sec : OutputSections) |
| 1473 | OutputSection *Sec = Cmd->Sec; | ||
| 1474 | if (Sec->Flags & SHF_TLS) | 1640 | if (Sec->Flags & SHF_TLS) |
| 1475 | TlsHdr.add(Sec); | 1641 | TlsHdr->add(Sec); |
| 1476 | } | 1642 | if (TlsHdr->FirstSec) |
| 1477 | if (TlsHdr.First) | 1643 | Ret.push_back(TlsHdr); |
| 1478 | Ret.push_back(std::move(TlsHdr)); | ||
| 1479 | 1644 | ||
| 1480 | // Add an entry for .dynamic. | 1645 | // Add an entry for .dynamic. |
| 1481 | if (InX::DynSymTab) | 1646 | if (InX::DynSymTab) |
| ... | @@ -1484,25 +1649,39 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { | ... | @@ -1484,25 +1649,39 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { |
| 1484 | 1649 | ||
| 1485 | // PT_GNU_RELRO includes all sections that should be marked as | 1650 | // PT_GNU_RELRO includes all sections that should be marked as |
| 1486 | // read-only by dynamic linker after proccessing relocations. | 1651 | // read-only by dynamic linker after proccessing relocations. |
| 1487 | PhdrEntry RelRo(PT_GNU_RELRO, PF_R); | 1652 | // Current dynamic loaders only support one PT_GNU_RELRO PHDR, give |
| 1488 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 1653 | // an error message if more than one PT_GNU_RELRO PHDR is required. |
| 1489 | OutputSection *Sec = Cmd->Sec; | 1654 | PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R); |
| 1490 | if (needsPtLoad(Sec) && isRelroSection(Sec)) | 1655 | bool InRelroPhdr = false; |
| 1491 | RelRo.add(Sec); | 1656 | bool IsRelroFinished = false; |
| 1657 | for (OutputSection *Sec : OutputSections) { | ||
| 1658 | if (!needsPtLoad(Sec)) | ||
| 1659 | continue; | ||
| 1660 | if (isRelroSection(Sec)) { | ||
| 1661 | InRelroPhdr = true; | ||
| 1662 | if (!IsRelroFinished) | ||
| 1663 | RelRo->add(Sec); | ||
| 1664 | else | ||
| 1665 | error("section: " + Sec->Name + " is not contiguous with other relro" + | ||
| 1666 | " sections"); | ||
| 1667 | } else if (InRelroPhdr) { | ||
| 1668 | InRelroPhdr = false; | ||
| 1669 | IsRelroFinished = true; | ||
| 1670 | } | ||
| 1492 | } | 1671 | } |
| 1493 | if (RelRo.First) | 1672 | if (RelRo->FirstSec) |
| 1494 | Ret.push_back(std::move(RelRo)); | 1673 | Ret.push_back(RelRo); |
| 1495 | 1674 | ||
| 1496 | // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. | 1675 | // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. |
| 1497 | if (!In<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr && | 1676 | if (!InX::EhFrame->empty() && InX::EhFrameHdr && InX::EhFrame->getParent() && |
| 1498 | In<ELFT>::EhFrame->getParent() && In<ELFT>::EhFrameHdr->getParent()) | 1677 | InX::EhFrameHdr->getParent()) |
| 1499 | AddHdr(PT_GNU_EH_FRAME, In<ELFT>::EhFrameHdr->getParent()->getPhdrFlags()) | 1678 | AddHdr(PT_GNU_EH_FRAME, InX::EhFrameHdr->getParent()->getPhdrFlags()) |
| 1500 | ->add(In<ELFT>::EhFrameHdr->getParent()); | 1679 | ->add(InX::EhFrameHdr->getParent()); |
| 1501 | 1680 | ||
| 1502 | // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes | 1681 | // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes |
| 1503 | // the dynamic linker fill the segment with random data. | 1682 | // the dynamic linker fill the segment with random data. |
| 1504 | if (OutputSection *Sec = findSectionInScript(".openbsd.randomdata")) | 1683 | if (OutputSection *Cmd = findSection(".openbsd.randomdata")) |
| 1505 | AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags())->add(Sec); | 1684 | AddHdr(PT_OPENBSD_RANDOMIZE, Cmd->getPhdrFlags())->add(Cmd); |
| 1506 | 1685 | ||
| 1507 | // PT_GNU_STACK is a special section to tell the loader to make the | 1686 | // PT_GNU_STACK is a special section to tell the loader to make the |
| 1508 | // pages for the stack non-executable. If you really want an executable | 1687 | // pages for the stack non-executable. If you really want an executable |
| ... | @@ -1524,10 +1703,9 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { | ... | @@ -1524,10 +1703,9 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { |
| 1524 | 1703 | ||
| 1525 | // Create one PT_NOTE per a group of contiguous .note sections. | 1704 | // Create one PT_NOTE per a group of contiguous .note sections. |
| 1526 | PhdrEntry *Note = nullptr; | 1705 | PhdrEntry *Note = nullptr; |
| 1527 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 1706 | for (OutputSection *Sec : OutputSections) { |
| 1528 | OutputSection *Sec = Cmd->Sec; | ||
| 1529 | if (Sec->Type == SHT_NOTE) { | 1707 | if (Sec->Type == SHT_NOTE) { |
| 1530 | if (!Note || Cmd->LMAExpr) | 1708 | if (!Note || Sec->LMAExpr) |
| 1531 | Note = AddHdr(PT_NOTE, PF_R); | 1709 | Note = AddHdr(PT_NOTE, PF_R); |
| 1532 | Note->add(Sec); | 1710 | Note->add(Sec); |
| 1533 | } else { | 1711 | } else { |
| ... | @@ -1538,18 +1716,18 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { | ... | @@ -1538,18 +1716,18 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { |
| 1538 | } | 1716 | } |
| 1539 | 1717 | ||
| 1540 | template <class ELFT> | 1718 | template <class ELFT> |
| 1541 | void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) { | 1719 | void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry *> &Phdrs) { |
| 1542 | if (Config->EMachine != EM_ARM) | 1720 | if (Config->EMachine != EM_ARM) |
| 1543 | return; | 1721 | return; |
| 1544 | auto I = llvm::find_if(OutputSectionCommands, [](OutputSectionCommand *Cmd) { | 1722 | auto I = llvm::find_if(OutputSections, [](OutputSection *Cmd) { |
| 1545 | return Cmd->Sec->Type == SHT_ARM_EXIDX; | 1723 | return Cmd->Type == SHT_ARM_EXIDX; |
| 1546 | }); | 1724 | }); |
| 1547 | if (I == OutputSectionCommands.end()) | 1725 | if (I == OutputSections.end()) |
| 1548 | return; | 1726 | return; |
| 1549 | 1727 | ||
| 1550 | // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME | 1728 | // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME |
| 1551 | PhdrEntry ARMExidx(PT_ARM_EXIDX, PF_R); | 1729 | PhdrEntry *ARMExidx = make<PhdrEntry>(PT_ARM_EXIDX, PF_R); |
| 1552 | ARMExidx.add((*I)->Sec); | 1730 | ARMExidx->add(*I); |
| 1553 | Phdrs.push_back(ARMExidx); | 1731 | Phdrs.push_back(ARMExidx); |
| 1554 | } | 1732 | } |
| 1555 | 1733 | ||
| ... | @@ -1557,33 +1735,31 @@ void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) { | ... | @@ -1557,33 +1735,31 @@ void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) { |
| 1557 | // first section after PT_GNU_RELRO have to be page aligned so that the dynamic | 1735 | // first section after PT_GNU_RELRO have to be page aligned so that the dynamic |
| 1558 | // linker can set the permissions. | 1736 | // linker can set the permissions. |
| 1559 | template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { | 1737 | template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { |
| 1560 | auto PageAlign = [](OutputSection *Sec) { | 1738 | auto PageAlign = [](OutputSection *Cmd) { |
| 1561 | OutputSectionCommand *Cmd = Script->getCmd(Sec); | ||
| 1562 | if (Cmd && !Cmd->AddrExpr) | 1739 | if (Cmd && !Cmd->AddrExpr) |
| 1563 | Cmd->AddrExpr = [=] { | 1740 | Cmd->AddrExpr = [=] { |
| 1564 | return alignTo(Script->getDot(), Config->MaxPageSize); | 1741 | return alignTo(Script->getDot(), Config->MaxPageSize); |
| 1565 | }; | 1742 | }; |
| 1566 | }; | 1743 | }; |
| 1567 | 1744 | ||
| 1568 | for (const PhdrEntry &P : Phdrs) | 1745 | for (const PhdrEntry *P : Phdrs) |
| 1569 | if (P.p_type == PT_LOAD && P.First) | 1746 | if (P->p_type == PT_LOAD && P->FirstSec) |
| 1570 | PageAlign(P.First); | 1747 | PageAlign(P->FirstSec); |
| 1571 | 1748 | ||
| 1572 | for (const PhdrEntry &P : Phdrs) { | 1749 | for (const PhdrEntry *P : Phdrs) { |
| 1573 | if (P.p_type != PT_GNU_RELRO) | 1750 | if (P->p_type != PT_GNU_RELRO) |
| 1574 | continue; | 1751 | continue; |
| 1575 | if (P.First) | 1752 | if (P->FirstSec) |
| 1576 | PageAlign(P.First); | 1753 | PageAlign(P->FirstSec); |
| 1577 | // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we | 1754 | // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we |
| 1578 | // have to align it to a page. | 1755 | // have to align it to a page. |
| 1579 | auto End = OutputSectionCommands.end(); | 1756 | auto End = OutputSections.end(); |
| 1580 | auto I = | 1757 | auto I = std::find(OutputSections.begin(), End, P->LastSec); |
| 1581 | std::find(OutputSectionCommands.begin(), End, Script->getCmd(P.Last)); | ||
| 1582 | if (I == End || (I + 1) == End) | 1758 | if (I == End || (I + 1) == End) |
| 1583 | continue; | 1759 | continue; |
| 1584 | OutputSection *Sec = (*(I + 1))->Sec; | 1760 | OutputSection *Cmd = (*(I + 1)); |
| 1585 | if (needsPtLoad(Sec)) | 1761 | if (needsPtLoad(Cmd)) |
| 1586 | PageAlign(Sec); | 1762 | PageAlign(Cmd); |
| 1587 | } | 1763 | } |
| 1588 | } | 1764 | } |
| 1589 | 1765 | ||
| ... | @@ -1591,40 +1767,45 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { | ... | @@ -1591,40 +1767,45 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { |
| 1591 | // its new file offset. The file offset must be the same with its | 1767 | // its new file offset. The file offset must be the same with its |
| 1592 | // virtual address (modulo the page size) so that the loader can load | 1768 | // virtual address (modulo the page size) so that the loader can load |
| 1593 | // executables without any address adjustment. | 1769 | // executables without any address adjustment. |
| 1594 | static uint64_t getFileAlignment(uint64_t Off, OutputSection *Sec) { | 1770 | static uint64_t getFileAlignment(uint64_t Off, OutputSection *Cmd) { |
| 1595 | OutputSection *First = Sec->FirstInPtLoad; | 1771 | OutputSection *First = Cmd->PtLoad ? Cmd->PtLoad->FirstSec : nullptr; |
| 1596 | // If the section is not in a PT_LOAD, we just have to align it. | ||
| 1597 | if (!First) | ||
| 1598 | return alignTo(Off, Sec->Alignment); | ||
| 1599 | |||
| 1600 | // The first section in a PT_LOAD has to have congruent offset and address | 1772 | // The first section in a PT_LOAD has to have congruent offset and address |
| 1601 | // module the page size. | 1773 | // module the page size. |
| 1602 | if (Sec == First) | 1774 | if (Cmd == First) |
| 1603 | return alignTo(Off, Config->MaxPageSize, Sec->Addr); | 1775 | return alignTo(Off, std::max<uint64_t>(Cmd->Alignment, Config->MaxPageSize), |
| 1776 | Cmd->Addr); | ||
| 1777 | |||
| 1778 | // For SHT_NOBITS we don't want the alignment of the section to impact the | ||
| 1779 | // offset of the sections that follow. Since nothing seems to care about the | ||
| 1780 | // sh_offset of the SHT_NOBITS section itself, just ignore it. | ||
| 1781 | if (Cmd->Type == SHT_NOBITS) | ||
| 1782 | return Off; | ||
| 1783 | |||
| 1784 | // If the section is not in a PT_LOAD, we just have to align it. | ||
| 1785 | if (!Cmd->PtLoad) | ||
| 1786 | return alignTo(Off, Cmd->Alignment); | ||
| 1604 | 1787 | ||
| 1605 | // If two sections share the same PT_LOAD the file offset is calculated | 1788 | // If two sections share the same PT_LOAD the file offset is calculated |
| 1606 | // using this formula: Off2 = Off1 + (VA2 - VA1). | 1789 | // using this formula: Off2 = Off1 + (VA2 - VA1). |
| 1607 | return First->Offset + Sec->Addr - First->Addr; | 1790 | return First->Offset + Cmd->Addr - First->Addr; |
| 1608 | } | 1791 | } |
| 1609 | 1792 | ||
| 1610 | static uint64_t setOffset(OutputSection *Sec, uint64_t Off) { | 1793 | static uint64_t setOffset(OutputSection *Cmd, uint64_t Off) { |
| 1611 | if (Sec->Type == SHT_NOBITS) { | 1794 | Off = getFileAlignment(Off, Cmd); |
| 1612 | Sec->Offset = Off; | 1795 | Cmd->Offset = Off; |
| 1796 | |||
| 1797 | // For SHT_NOBITS we should not count the size. | ||
| 1798 | if (Cmd->Type == SHT_NOBITS) | ||
| 1613 | return Off; | 1799 | return Off; |
| 1614 | } | ||
| 1615 | 1800 | ||
| 1616 | Off = getFileAlignment(Off, Sec); | 1801 | return Off + Cmd->Size; |
| 1617 | Sec->Offset = Off; | ||
| 1618 | return Off + Sec->Size; | ||
| 1619 | } | 1802 | } |
| 1620 | 1803 | ||
| 1621 | template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { | 1804 | template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { |
| 1622 | uint64_t Off = 0; | 1805 | uint64_t Off = 0; |
| 1623 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 1806 | for (OutputSection *Sec : OutputSections) |
| 1624 | OutputSection *Sec = Cmd->Sec; | ||
| 1625 | if (Sec->Flags & SHF_ALLOC) | 1807 | if (Sec->Flags & SHF_ALLOC) |
| 1626 | Off = setOffset(Sec, Off); | 1808 | Off = setOffset(Sec, Off); |
| 1627 | } | ||
| 1628 | FileSize = alignTo(Off, Config->Wordsize); | 1809 | FileSize = alignTo(Off, Config->Wordsize); |
| 1629 | } | 1810 | } |
| 1630 | 1811 | ||
| ... | @@ -1634,46 +1815,58 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { | ... | @@ -1634,46 +1815,58 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { |
| 1634 | Off = setOffset(Out::ElfHeader, Off); | 1815 | Off = setOffset(Out::ElfHeader, Off); |
| 1635 | Off = setOffset(Out::ProgramHeaders, Off); | 1816 | Off = setOffset(Out::ProgramHeaders, Off); |
| 1636 | 1817 | ||
| 1637 | for (OutputSectionCommand *Cmd : OutputSectionCommands) | 1818 | PhdrEntry *LastRX = nullptr; |
| 1638 | Off = setOffset(Cmd->Sec, Off); | 1819 | for (PhdrEntry *P : Phdrs) |
| 1820 | if (P->p_type == PT_LOAD && (P->p_flags & PF_X)) | ||
| 1821 | LastRX = P; | ||
| 1822 | |||
| 1823 | for (OutputSection *Sec : OutputSections) { | ||
| 1824 | Off = setOffset(Sec, Off); | ||
| 1825 | if (Script->HasSectionsCommand) | ||
| 1826 | continue; | ||
| 1827 | // If this is a last section of the last executable segment and that | ||
| 1828 | // segment is the last loadable segment, align the offset of the | ||
| 1829 | // following section to avoid loading non-segments parts of the file. | ||
| 1830 | if (LastRX && LastRX->LastSec == Sec) | ||
| 1831 | Off = alignTo(Off, Target->PageSize); | ||
| 1832 | } | ||
| 1639 | 1833 | ||
| 1640 | SectionHeaderOff = alignTo(Off, Config->Wordsize); | 1834 | SectionHeaderOff = alignTo(Off, Config->Wordsize); |
| 1641 | FileSize = | 1835 | FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr); |
| 1642 | SectionHeaderOff + (OutputSectionCommands.size() + 1) * sizeof(Elf_Shdr); | ||
| 1643 | } | 1836 | } |
| 1644 | 1837 | ||
| 1645 | // Finalize the program headers. We call this function after we assign | 1838 | // Finalize the program headers. We call this function after we assign |
| 1646 | // file offsets and VAs to all sections. | 1839 | // file offsets and VAs to all sections. |
| 1647 | template <class ELFT> void Writer<ELFT>::setPhdrs() { | 1840 | template <class ELFT> void Writer<ELFT>::setPhdrs() { |
| 1648 | for (PhdrEntry &P : Phdrs) { | 1841 | for (PhdrEntry *P : Phdrs) { |
| 1649 | OutputSection *First = P.First; | 1842 | OutputSection *First = P->FirstSec; |
| 1650 | OutputSection *Last = P.Last; | 1843 | OutputSection *Last = P->LastSec; |
| 1651 | if (First) { | 1844 | if (First) { |
| 1652 | P.p_filesz = Last->Offset - First->Offset; | 1845 | P->p_filesz = Last->Offset - First->Offset; |
| 1653 | if (Last->Type != SHT_NOBITS) | 1846 | if (Last->Type != SHT_NOBITS) |
| 1654 | P.p_filesz += Last->Size; | 1847 | P->p_filesz += Last->Size; |
| 1655 | P.p_memsz = Last->Addr + Last->Size - First->Addr; | 1848 | P->p_memsz = Last->Addr + Last->Size - First->Addr; |
| 1656 | P.p_offset = First->Offset; | 1849 | P->p_offset = First->Offset; |
| 1657 | P.p_vaddr = First->Addr; | 1850 | P->p_vaddr = First->Addr; |
| 1658 | if (!P.HasLMA) | 1851 | if (!P->HasLMA) |
| 1659 | P.p_paddr = First->getLMA(); | 1852 | P->p_paddr = First->getLMA(); |
| 1660 | } | 1853 | } |
| 1661 | if (P.p_type == PT_LOAD) | 1854 | if (P->p_type == PT_LOAD) |
| 1662 | P.p_align = Config->MaxPageSize; | 1855 | P->p_align = std::max<uint64_t>(P->p_align, Config->MaxPageSize); |
| 1663 | else if (P.p_type == PT_GNU_RELRO) { | 1856 | else if (P->p_type == PT_GNU_RELRO) { |
| 1664 | P.p_align = 1; | 1857 | P->p_align = 1; |
| 1665 | // The glibc dynamic loader rounds the size down, so we need to round up | 1858 | // The glibc dynamic loader rounds the size down, so we need to round up |
| 1666 | // to protect the last page. This is a no-op on FreeBSD which always | 1859 | // to protect the last page. This is a no-op on FreeBSD which always |
| 1667 | // rounds up. | 1860 | // rounds up. |
| 1668 | P.p_memsz = alignTo(P.p_memsz, Target->PageSize); | 1861 | P->p_memsz = alignTo(P->p_memsz, Target->PageSize); |
| 1669 | } | 1862 | } |
| 1670 | 1863 | ||
| 1671 | // The TLS pointer goes after PT_TLS. At least glibc will align it, | 1864 | // The TLS pointer goes after PT_TLS. At least glibc will align it, |
| 1672 | // so round up the size to make sure the offsets are correct. | 1865 | // so round up the size to make sure the offsets are correct. |
| 1673 | if (P.p_type == PT_TLS) { | 1866 | if (P->p_type == PT_TLS) { |
| 1674 | Out::TlsPhdr = &P; | 1867 | Out::TlsPhdr = P; |
| 1675 | if (P.p_memsz) | 1868 | if (P->p_memsz) |
| 1676 | P.p_memsz = alignTo(P.p_memsz, P.p_align); | 1869 | P->p_memsz = alignTo(P->p_memsz, P->p_align); |
| 1677 | } | 1870 | } |
| 1678 | } | 1871 | } |
| 1679 | } | 1872 | } |
| ... | @@ -1682,27 +1875,29 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() { | ... | @@ -1682,27 +1875,29 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() { |
| 1682 | // | 1875 | // |
| 1683 | // 1. the '-e' entry command-line option; | 1876 | // 1. the '-e' entry command-line option; |
| 1684 | // 2. the ENTRY(symbol) command in a linker control script; | 1877 | // 2. the ENTRY(symbol) command in a linker control script; |
| 1685 | // 3. the value of the symbol start, if present; | 1878 | // 3. the value of the symbol _start, if present; |
| 1686 | // 4. the address of the first byte of the .text section, if present; | 1879 | // 4. the number represented by the entry symbol, if it is a number; |
| 1687 | // 5. the address 0. | 1880 | // 5. the address of the first byte of the .text section, if present; |
| 1881 | // 6. the address 0. | ||
| 1688 | template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() { | 1882 | template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() { |
| 1689 | // Case 1, 2 or 3. As a special case, if the symbol is actually | 1883 | // Case 1, 2 or 3 |
| 1690 | // a number, we'll use that number as an address. | 1884 | if (Symbol *B = Symtab->find(Config->Entry)) |
| 1691 | if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Entry)) | ||
| 1692 | return B->getVA(); | 1885 | return B->getVA(); |
| 1886 | |||
| 1887 | // Case 4 | ||
| 1693 | uint64_t Addr; | 1888 | uint64_t Addr; |
| 1694 | if (to_integer(Config->Entry, Addr)) | 1889 | if (to_integer(Config->Entry, Addr)) |
| 1695 | return Addr; | 1890 | return Addr; |
| 1696 | 1891 | ||
| 1697 | // Case 4 | 1892 | // Case 5 |
| 1698 | if (OutputSection *Sec = findSectionInScript(".text")) { | 1893 | if (OutputSection *Sec = findSection(".text")) { |
| 1699 | if (Config->WarnMissingEntry) | 1894 | if (Config->WarnMissingEntry) |
| 1700 | warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" + | 1895 | warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" + |
| 1701 | utohexstr(Sec->Addr)); | 1896 | utohexstr(Sec->Addr)); |
| 1702 | return Sec->Addr; | 1897 | return Sec->Addr; |
| 1703 | } | 1898 | } |
| 1704 | 1899 | ||
| 1705 | // Case 5 | 1900 | // Case 6 |
| 1706 | if (Config->WarnMissingEntry) | 1901 | if (Config->WarnMissingEntry) |
| 1707 | warn("cannot find entry symbol " + Config->Entry + | 1902 | warn("cannot find entry symbol " + Config->Entry + |
| 1708 | "; not setting start address"); | 1903 | "; not setting start address"); |
| ... | @@ -1717,64 +1912,6 @@ static uint16_t getELFType() { | ... | @@ -1717,64 +1912,6 @@ static uint16_t getELFType() { |
| 1717 | return ET_EXEC; | 1912 | return ET_EXEC; |
| 1718 | } | 1913 | } |
| 1719 | 1914 | ||
| 1720 | // This function is called after we have assigned address and size | ||
| 1721 | // to each section. This function fixes some predefined | ||
| 1722 | // symbol values that depend on section address and size. | ||
| 1723 | template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() { | ||
| 1724 | // _etext is the first location after the last read-only loadable segment. | ||
| 1725 | // _edata is the first location after the last read-write loadable segment. | ||
| 1726 | // _end is the first location after the uninitialized data region. | ||
| 1727 | PhdrEntry *Last = nullptr; | ||
| 1728 | PhdrEntry *LastRO = nullptr; | ||
| 1729 | PhdrEntry *LastRW = nullptr; | ||
| 1730 | for (PhdrEntry &P : Phdrs) { | ||
| 1731 | if (P.p_type != PT_LOAD) | ||
| 1732 | continue; | ||
| 1733 | Last = &P; | ||
| 1734 | if (P.p_flags & PF_W) | ||
| 1735 | LastRW = &P; | ||
| 1736 | else | ||
| 1737 | LastRO = &P; | ||
| 1738 | } | ||
| 1739 | |||
| 1740 | auto Set = [](DefinedRegular *S, OutputSection *Sec, uint64_t Value) { | ||
| 1741 | if (S) { | ||
| 1742 | S->Section = Sec; | ||
| 1743 | S->Value = Value; | ||
| 1744 | } | ||
| 1745 | }; | ||
| 1746 | |||
| 1747 | if (Last) { | ||
| 1748 | Set(ElfSym::End1, Last->First, Last->p_memsz); | ||
| 1749 | Set(ElfSym::End2, Last->First, Last->p_memsz); | ||
| 1750 | } | ||
| 1751 | if (LastRO) { | ||
| 1752 | Set(ElfSym::Etext1, LastRO->First, LastRO->p_filesz); | ||
| 1753 | Set(ElfSym::Etext2, LastRO->First, LastRO->p_filesz); | ||
| 1754 | } | ||
| 1755 | if (LastRW) { | ||
| 1756 | Set(ElfSym::Edata1, LastRW->First, LastRW->p_filesz); | ||
| 1757 | Set(ElfSym::Edata2, LastRW->First, LastRW->p_filesz); | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | if (ElfSym::Bss) | ||
| 1761 | ElfSym::Bss->Section = findSectionInScript(".bss"); | ||
| 1762 | |||
| 1763 | // Setup MIPS _gp_disp/__gnu_local_gp symbols which should | ||
| 1764 | // be equal to the _gp symbol's value. | ||
| 1765 | if (Config->EMachine == EM_MIPS && !ElfSym::MipsGp->Value) { | ||
| 1766 | // Find GP-relative section with the lowest address | ||
| 1767 | // and use this address to calculate default _gp value. | ||
| 1768 | for (const OutputSectionCommand *Cmd : OutputSectionCommands) { | ||
| 1769 | OutputSection *OS = Cmd->Sec; | ||
| 1770 | if (OS->Flags & SHF_MIPS_GPREL) { | ||
| 1771 | ElfSym::MipsGp->Value = OS->Addr + 0x7ff0; | ||
| 1772 | break; | ||
| 1773 | } | ||
| 1774 | } | ||
| 1775 | } | ||
| 1776 | } | ||
| 1777 | |||
| 1778 | template <class ELFT> void Writer<ELFT>::writeHeader() { | 1915 | template <class ELFT> void Writer<ELFT>::writeHeader() { |
| 1779 | uint8_t *Buf = Buffer->getBufferStart(); | 1916 | uint8_t *Buf = Buffer->getBufferStart(); |
| 1780 | memcpy(Buf, "\177ELF", 4); | 1917 | memcpy(Buf, "\177ELF", 4); |
| ... | @@ -1790,20 +1927,13 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { | ... | @@ -1790,20 +1927,13 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { |
| 1790 | EHdr->e_version = EV_CURRENT; | 1927 | EHdr->e_version = EV_CURRENT; |
| 1791 | EHdr->e_entry = getEntryAddr(); | 1928 | EHdr->e_entry = getEntryAddr(); |
| 1792 | EHdr->e_shoff = SectionHeaderOff; | 1929 | EHdr->e_shoff = SectionHeaderOff; |
| 1930 | EHdr->e_flags = Config->EFlags; | ||
| 1793 | EHdr->e_ehsize = sizeof(Elf_Ehdr); | 1931 | EHdr->e_ehsize = sizeof(Elf_Ehdr); |
| 1794 | EHdr->e_phnum = Phdrs.size(); | 1932 | EHdr->e_phnum = Phdrs.size(); |
| 1795 | EHdr->e_shentsize = sizeof(Elf_Shdr); | 1933 | EHdr->e_shentsize = sizeof(Elf_Shdr); |
| 1796 | EHdr->e_shnum = OutputSectionCommands.size() + 1; | 1934 | EHdr->e_shnum = OutputSections.size() + 1; |
| 1797 | EHdr->e_shstrndx = InX::ShStrTab->getParent()->SectionIndex; | 1935 | EHdr->e_shstrndx = InX::ShStrTab->getParent()->SectionIndex; |
| 1798 | 1936 | ||
| 1799 | if (Config->EMachine == EM_ARM) | ||
| 1800 | // We don't currently use any features incompatible with EF_ARM_EABI_VER5, | ||
| 1801 | // but we don't have any firm guarantees of conformance. Linux AArch64 | ||
| 1802 | // kernels (as of 2016) require an EABI version to be set. | ||
| 1803 | EHdr->e_flags = EF_ARM_EABI_VER5; | ||
| 1804 | else if (Config->EMachine == EM_MIPS) | ||
| 1805 | EHdr->e_flags = getMipsEFlags<ELFT>(); | ||
| 1806 | |||
| 1807 | if (!Config->Relocatable) { | 1937 | if (!Config->Relocatable) { |
| 1808 | EHdr->e_phoff = sizeof(Elf_Ehdr); | 1938 | EHdr->e_phoff = sizeof(Elf_Ehdr); |
| 1809 | EHdr->e_phentsize = sizeof(Elf_Phdr); | 1939 | EHdr->e_phentsize = sizeof(Elf_Phdr); |
| ... | @@ -1811,22 +1941,22 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { | ... | @@ -1811,22 +1941,22 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { |
| 1811 | 1941 | ||
| 1812 | // Write the program header table. | 1942 | // Write the program header table. |
| 1813 | auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff); | 1943 | auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff); |
| 1814 | for (PhdrEntry &P : Phdrs) { | 1944 | for (PhdrEntry *P : Phdrs) { |
| 1815 | HBuf->p_type = P.p_type; | 1945 | HBuf->p_type = P->p_type; |
| 1816 | HBuf->p_flags = P.p_flags; | 1946 | HBuf->p_flags = P->p_flags; |
| 1817 | HBuf->p_offset = P.p_offset; | 1947 | HBuf->p_offset = P->p_offset; |
| 1818 | HBuf->p_vaddr = P.p_vaddr; | 1948 | HBuf->p_vaddr = P->p_vaddr; |
| 1819 | HBuf->p_paddr = P.p_paddr; | 1949 | HBuf->p_paddr = P->p_paddr; |
| 1820 | HBuf->p_filesz = P.p_filesz; | 1950 | HBuf->p_filesz = P->p_filesz; |
| 1821 | HBuf->p_memsz = P.p_memsz; | 1951 | HBuf->p_memsz = P->p_memsz; |
| 1822 | HBuf->p_align = P.p_align; | 1952 | HBuf->p_align = P->p_align; |
| 1823 | ++HBuf; | 1953 | ++HBuf; |
| 1824 | } | 1954 | } |
| 1825 | 1955 | ||
| 1826 | // Write the section header table. Note that the first table entry is null. | 1956 | // Write the section header table. Note that the first table entry is null. |
| 1827 | auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff); | 1957 | auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff); |
| 1828 | for (OutputSectionCommand *Cmd : OutputSectionCommands) | 1958 | for (OutputSection *Sec : OutputSections) |
| 1829 | Cmd->Sec->writeHeaderTo<ELFT>(++SHdrs); | 1959 | Sec->writeHeaderTo<ELFT>(++SHdrs); |
| 1830 | } | 1960 | } |
| 1831 | 1961 | ||
| 1832 | // Open a result file. | 1962 | // Open a result file. |
| ... | @@ -1837,23 +1967,58 @@ template <class ELFT> void Writer<ELFT>::openFile() { | ... | @@ -1837,23 +1967,58 @@ template <class ELFT> void Writer<ELFT>::openFile() { |
| 1837 | } | 1967 | } |
| 1838 | 1968 | ||
| 1839 | unlinkAsync(Config->OutputFile); | 1969 | unlinkAsync(Config->OutputFile); |
| 1840 | ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = | 1970 | unsigned Flags = 0; |
| 1841 | FileOutputBuffer::create(Config->OutputFile, FileSize, | 1971 | if (!Config->Relocatable) |
| 1842 | FileOutputBuffer::F_executable); | 1972 | Flags = FileOutputBuffer::F_executable; |
| 1973 | Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = | ||
| 1974 | FileOutputBuffer::create(Config->OutputFile, FileSize, Flags); | ||
| 1843 | 1975 | ||
| 1844 | if (auto EC = BufferOrErr.getError()) | 1976 | if (!BufferOrErr) |
| 1845 | error("failed to open " + Config->OutputFile + ": " + EC.message()); | 1977 | error("failed to open " + Config->OutputFile + ": " + |
| 1978 | llvm::toString(BufferOrErr.takeError())); | ||
| 1846 | else | 1979 | else |
| 1847 | Buffer = std::move(*BufferOrErr); | 1980 | Buffer = std::move(*BufferOrErr); |
| 1848 | } | 1981 | } |
| 1849 | 1982 | ||
| 1850 | template <class ELFT> void Writer<ELFT>::writeSectionsBinary() { | 1983 | template <class ELFT> void Writer<ELFT>::writeSectionsBinary() { |
| 1851 | uint8_t *Buf = Buffer->getBufferStart(); | 1984 | uint8_t *Buf = Buffer->getBufferStart(); |
| 1852 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 1985 | for (OutputSection *Sec : OutputSections) |
| 1853 | OutputSection *Sec = Cmd->Sec; | ||
| 1854 | if (Sec->Flags & SHF_ALLOC) | 1986 | if (Sec->Flags & SHF_ALLOC) |
| 1855 | Cmd->writeTo<ELFT>(Buf + Sec->Offset); | 1987 | Sec->writeTo<ELFT>(Buf + Sec->Offset); |
| 1856 | } | 1988 | } |
| 1989 | |||
| 1990 | static void fillTrap(uint8_t *I, uint8_t *End) { | ||
| 1991 | for (; I + 4 <= End; I += 4) | ||
| 1992 | memcpy(I, &Target->TrapInstr, 4); | ||
| 1993 | } | ||
| 1994 | |||
| 1995 | // Fill the last page of executable segments with trap instructions | ||
| 1996 | // instead of leaving them as zero. Even though it is not required by any | ||
| 1997 | // standard, it is in general a good thing to do for security reasons. | ||
| 1998 | // | ||
| 1999 | // We'll leave other pages in segments as-is because the rest will be | ||
| 2000 | // overwritten by output sections. | ||
| 2001 | template <class ELFT> void Writer<ELFT>::writeTrapInstr() { | ||
| 2002 | if (Script->HasSectionsCommand) | ||
| 2003 | return; | ||
| 2004 | |||
| 2005 | // Fill the last page. | ||
| 2006 | uint8_t *Buf = Buffer->getBufferStart(); | ||
| 2007 | for (PhdrEntry *P : Phdrs) | ||
| 2008 | if (P->p_type == PT_LOAD && (P->p_flags & PF_X)) | ||
| 2009 | fillTrap(Buf + alignDown(P->p_offset + P->p_filesz, Target->PageSize), | ||
| 2010 | Buf + alignTo(P->p_offset + P->p_filesz, Target->PageSize)); | ||
| 2011 | |||
| 2012 | // Round up the file size of the last segment to the page boundary iff it is | ||
| 2013 | // an executable segment to ensure that other tools don't accidentally | ||
| 2014 | // trim the instruction padding (e.g. when stripping the file). | ||
| 2015 | PhdrEntry *Last = nullptr; | ||
| 2016 | for (PhdrEntry *P : Phdrs) | ||
| 2017 | if (P->p_type == PT_LOAD) | ||
| 2018 | Last = P; | ||
| 2019 | |||
| 2020 | if (Last && (Last->p_flags & PF_X)) | ||
| 2021 | Last->p_memsz = Last->p_filesz = alignTo(Last->p_filesz, Target->PageSize); | ||
| 1857 | } | 2022 | } |
| 1858 | 2023 | ||
| 1859 | // Write section contents to a mmap'ed file. | 2024 | // Write section contents to a mmap'ed file. |
| ... | @@ -1862,39 +2027,32 @@ template <class ELFT> void Writer<ELFT>::writeSections() { | ... | @@ -1862,39 +2027,32 @@ template <class ELFT> void Writer<ELFT>::writeSections() { |
| 1862 | 2027 | ||
| 1863 | // PPC64 needs to process relocations in the .opd section | 2028 | // PPC64 needs to process relocations in the .opd section |
| 1864 | // before processing relocations in code-containing sections. | 2029 | // before processing relocations in code-containing sections. |
| 1865 | if (auto *OpdCmd = findSectionCommand(".opd")) { | 2030 | if (auto *OpdCmd = findSection(".opd")) { |
| 1866 | Out::Opd = OpdCmd->Sec; | 2031 | Out::Opd = OpdCmd; |
| 1867 | Out::OpdBuf = Buf + Out::Opd->Offset; | 2032 | Out::OpdBuf = Buf + Out::Opd->Offset; |
| 1868 | OpdCmd->template writeTo<ELFT>(Buf + Out::Opd->Offset); | 2033 | OpdCmd->template writeTo<ELFT>(Buf + Out::Opd->Offset); |
| 1869 | } | 2034 | } |
| 1870 | 2035 | ||
| 1871 | OutputSection *EhFrameHdr = | 2036 | OutputSection *EhFrameHdr = nullptr; |
| 1872 | (In<ELFT>::EhFrameHdr && !In<ELFT>::EhFrameHdr->empty()) | 2037 | if (InX::EhFrameHdr && !InX::EhFrameHdr->empty()) |
| 1873 | ? In<ELFT>::EhFrameHdr->getParent() | 2038 | EhFrameHdr = InX::EhFrameHdr->getParent(); |
| 1874 | : nullptr; | ||
| 1875 | 2039 | ||
| 1876 | // In -r or -emit-relocs mode, write the relocation sections first as in | 2040 | // In -r or -emit-relocs mode, write the relocation sections first as in |
| 1877 | // ELf_Rel targets we might find out that we need to modify the relocated | 2041 | // ELf_Rel targets we might find out that we need to modify the relocated |
| 1878 | // section while doing it. | 2042 | // section while doing it. |
| 1879 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 2043 | for (OutputSection *Sec : OutputSections) |
| 1880 | OutputSection *Sec = Cmd->Sec; | ||
| 1881 | if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) | 2044 | if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) |
| 1882 | Cmd->writeTo<ELFT>(Buf + Sec->Offset); | 2045 | Sec->writeTo<ELFT>(Buf + Sec->Offset); |
| 1883 | } | ||
| 1884 | 2046 | ||
| 1885 | for (OutputSectionCommand *Cmd : OutputSectionCommands) { | 2047 | for (OutputSection *Sec : OutputSections) |
| 1886 | OutputSection *Sec = Cmd->Sec; | ||
| 1887 | if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL && | 2048 | if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL && |
| 1888 | Sec->Type != SHT_RELA) | 2049 | Sec->Type != SHT_RELA) |
| 1889 | Cmd->writeTo<ELFT>(Buf + Sec->Offset); | 2050 | Sec->writeTo<ELFT>(Buf + Sec->Offset); |
| 1890 | } | ||
| 1891 | 2051 | ||
| 1892 | // The .eh_frame_hdr depends on .eh_frame section contents, therefore | 2052 | // The .eh_frame_hdr depends on .eh_frame section contents, therefore |
| 1893 | // it should be written after .eh_frame is written. | 2053 | // it should be written after .eh_frame is written. |
| 1894 | if (EhFrameHdr) { | 2054 | if (EhFrameHdr) |
| 1895 | OutputSectionCommand *Cmd = Script->getCmd(EhFrameHdr); | 2055 | EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset); |
| 1896 | Cmd->writeTo<ELFT>(Buf + EhFrameHdr->Offset); | ||
| 1897 | } | ||
| 1898 | } | 2056 | } |
| 1899 | 2057 | ||
| 1900 | template <class ELFT> void Writer<ELFT>::writeBuildId() { | 2058 | template <class ELFT> void Writer<ELFT>::writeBuildId() { |
deps/lld/ELF/Writer.h+9-7| ... | @@ -20,11 +20,10 @@ namespace elf { | ... | @@ -20,11 +20,10 @@ namespace elf { |
| 20 | class InputFile; | 20 | class InputFile; |
| 21 | class OutputSection; | 21 | class OutputSection; |
| 22 | class InputSectionBase; | 22 | class InputSectionBase; |
| 23 | template <class ELFT> class ObjectFile; | 23 | template <class ELFT> class ObjFile; |
| 24 | template <class ELFT> class SymbolTable; | 24 | class SymbolTable; |
| 25 | template <class ELFT> void writeResult(); | 25 | template <class ELFT> void writeResult(); |
| 26 | template <class ELFT> void markLive(); | 26 | template <class ELFT> void markLive(); |
| 27 | bool isRelroSection(const OutputSection *Sec); | ||
| 28 | 27 | ||
| 29 | // This describes a program header entry. | 28 | // This describes a program header entry. |
| 30 | // Each contains type, access flags and range of output sections that will be | 29 | // Each contains type, access flags and range of output sections that will be |
| ... | @@ -42,19 +41,22 @@ struct PhdrEntry { | ... | @@ -42,19 +41,22 @@ struct PhdrEntry { |
| 42 | uint32_t p_type = 0; | 41 | uint32_t p_type = 0; |
| 43 | uint32_t p_flags = 0; | 42 | uint32_t p_flags = 0; |
| 44 | 43 | ||
| 45 | OutputSection *First = nullptr; | 44 | OutputSection *FirstSec = nullptr; |
| 46 | OutputSection *Last = nullptr; | 45 | OutputSection *LastSec = nullptr; |
| 47 | bool HasLMA = false; | 46 | bool HasLMA = false; |
| 48 | }; | 47 | }; |
| 49 | 48 | ||
| 50 | llvm::StringRef getOutputSectionName(llvm::StringRef Name); | 49 | void addReservedSymbols(); |
| 50 | llvm::StringRef getOutputSectionName(InputSectionBase *S); | ||
| 51 | 51 | ||
| 52 | template <class ELFT> uint32_t getMipsEFlags(); | 52 | template <class ELFT> uint32_t calcMipsEFlags(); |
| 53 | 53 | ||
| 54 | uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, | 54 | uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, |
| 55 | llvm::StringRef FileName); | 55 | llvm::StringRef FileName); |
| 56 | 56 | ||
| 57 | bool isMipsN32Abi(const InputFile *F); | 57 | bool isMipsN32Abi(const InputFile *F); |
| 58 | bool isMicroMips(); | ||
| 59 | bool isMipsR6(); | ||
| 58 | } // namespace elf | 60 | } // namespace elf |
| 59 | } // namespace lld | 61 | } // namespace lld |
| 60 | 62 |
deps/lld/MinGW/CMakeLists.txt created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | set(LLVM_TARGET_DEFINITIONS Options.td) | ||
| 2 | tablegen(LLVM Options.inc -gen-opt-parser-defs) | ||
| 3 | add_public_tablegen_target(MinGWOptionsTableGen) | ||
| 4 | |||
| 5 | if(NOT LLD_BUILT_STANDALONE) | ||
| 6 | set(tablegen_deps intrinsics_gen) | ||
| 7 | endif() | ||
| 8 | |||
| 9 | add_lld_library(lldMinGW | ||
| 10 | Driver.cpp | ||
| 11 | |||
| 12 | LINK_COMPONENTS | ||
| 13 | Option | ||
| 14 | Support | ||
| 15 | |||
| 16 | LINK_LIBS | ||
| 17 | lldCOFF | ||
| 18 | lldCommon | ||
| 19 | |||
| 20 | DEPENDS | ||
| 21 | MinGWOptionsTableGen | ||
| 22 | ${tablegen_deps} | ||
| 23 | ) | ||
deps/lld/MinGW/Driver.cpp created+247| ... | @@ -0,0 +1,247 @@ | ||
| 1 | //===- MinGW/Driver.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 | /// GNU ld style linker driver for COFF currently supporting mingw-w64. | ||
| 11 | /// | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #include "lld/Common/Driver.h" | ||
| 15 | #include "lld/Common/ErrorHandler.h" | ||
| 16 | #include "llvm/ADT/ArrayRef.h" | ||
| 17 | #include "llvm/ADT/Optional.h" | ||
| 18 | #include "llvm/ADT/StringExtras.h" | ||
| 19 | #include "llvm/ADT/StringRef.h" | ||
| 20 | #include "llvm/Option/Arg.h" | ||
| 21 | #include "llvm/Option/ArgList.h" | ||
| 22 | #include "llvm/Option/Option.h" | ||
| 23 | #include "llvm/Support/CommandLine.h" | ||
| 24 | #include "llvm/Support/FileSystem.h" | ||
| 25 | #include "llvm/Support/Path.h" | ||
| 26 | |||
| 27 | #if !defined(_MSC_VER) && !defined(__MINGW32__) | ||
| 28 | #include <unistd.h> | ||
| 29 | #endif | ||
| 30 | |||
| 31 | using namespace lld; | ||
| 32 | using namespace llvm; | ||
| 33 | |||
| 34 | // Create OptTable | ||
| 35 | enum { | ||
| 36 | OPT_INVALID = 0, | ||
| 37 | #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, | ||
| 38 | #include "Options.inc" | ||
| 39 | #undef OPTION | ||
| 40 | }; | ||
| 41 | |||
| 42 | // Create prefix string literals used in Options.td | ||
| 43 | #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; | ||
| 44 | #include "Options.inc" | ||
| 45 | #undef PREFIX | ||
| 46 | |||
| 47 | // Create table mapping all options defined in Options.td | ||
| 48 | static const opt::OptTable::Info InfoTable[] = { | ||
| 49 | #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ | ||
| 50 | {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ | ||
| 51 | X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, | ||
| 52 | #include "Options.inc" | ||
| 53 | #undef OPTION | ||
| 54 | }; | ||
| 55 | |||
| 56 | namespace { | ||
| 57 | class MinGWOptTable : public opt::OptTable { | ||
| 58 | public: | ||
| 59 | MinGWOptTable() : OptTable(InfoTable, false) {} | ||
| 60 | opt::InputArgList parse(ArrayRef<const char *> Argv); | ||
| 61 | }; | ||
| 62 | } // namespace | ||
| 63 | |||
| 64 | opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> Argv) { | ||
| 65 | unsigned MissingIndex; | ||
| 66 | unsigned MissingCount; | ||
| 67 | |||
| 68 | SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); | ||
| 69 | opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); | ||
| 70 | |||
| 71 | if (MissingCount) | ||
| 72 | fatal(StringRef(Args.getArgString(MissingIndex)) + ": missing argument"); | ||
| 73 | for (auto *Arg : Args.filtered(OPT_UNKNOWN)) | ||
| 74 | fatal("unknown argument: " + Arg->getSpelling()); | ||
| 75 | if (!Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l)) | ||
| 76 | fatal("no input files"); | ||
| 77 | return Args; | ||
| 78 | } | ||
| 79 | |||
| 80 | // Find a file by concatenating given paths. | ||
| 81 | static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) { | ||
| 82 | SmallString<128> S; | ||
| 83 | sys::path::append(S, Path1, Path2); | ||
| 84 | if (sys::fs::exists(S)) | ||
| 85 | return S.str().str(); | ||
| 86 | return None; | ||
| 87 | } | ||
| 88 | |||
| 89 | // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. | ||
| 90 | static std::string | ||
| 91 | searchLibrary(StringRef Name, ArrayRef<StringRef> SearchPaths, bool BStatic) { | ||
| 92 | if (Name.startswith(":")) { | ||
| 93 | for (StringRef Dir : SearchPaths) | ||
| 94 | if (Optional<std::string> S = findFile(Dir, Name.substr(1))) | ||
| 95 | return *S; | ||
| 96 | fatal("unable to find library -l" + Name); | ||
| 97 | } | ||
| 98 | |||
| 99 | for (StringRef Dir : SearchPaths) { | ||
| 100 | if (!BStatic) | ||
| 101 | if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a")) | ||
| 102 | return *S; | ||
| 103 | if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) | ||
| 104 | return *S; | ||
| 105 | } | ||
| 106 | fatal("unable to find library -l" + Name); | ||
| 107 | } | ||
| 108 | |||
| 109 | // Convert Unix-ish command line arguments to Windows-ish ones and | ||
| 110 | // then call coff::link. | ||
| 111 | bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) { | ||
| 112 | MinGWOptTable Parser; | ||
| 113 | opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); | ||
| 114 | |||
| 115 | std::vector<std::string> LinkArgs; | ||
| 116 | auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); }; | ||
| 117 | |||
| 118 | Add("lld-link"); | ||
| 119 | Add("-lldmingw"); | ||
| 120 | |||
| 121 | if (auto *A = Args.getLastArg(OPT_entry)) { | ||
| 122 | StringRef S = A->getValue(); | ||
| 123 | if (Args.getLastArgValue(OPT_m) == "i386pe" && S.startswith("_")) | ||
| 124 | Add("-entry:" + S.substr(1)); | ||
| 125 | else | ||
| 126 | Add("-entry:" + S); | ||
| 127 | } | ||
| 128 | |||
| 129 | if (auto *A = Args.getLastArg(OPT_subs)) | ||
| 130 | Add("-subsystem:" + StringRef(A->getValue())); | ||
| 131 | if (auto *A = Args.getLastArg(OPT_out_implib)) | ||
| 132 | Add("-implib:" + StringRef(A->getValue())); | ||
| 133 | if (auto *A = Args.getLastArg(OPT_stack)) | ||
| 134 | Add("-stack:" + StringRef(A->getValue())); | ||
| 135 | if (auto *A = Args.getLastArg(OPT_output_def)) | ||
| 136 | Add("-output-def:" + StringRef(A->getValue())); | ||
| 137 | if (auto *A = Args.getLastArg(OPT_image_base)) | ||
| 138 | Add("-base:" + StringRef(A->getValue())); | ||
| 139 | |||
| 140 | if (auto *A = Args.getLastArg(OPT_o)) | ||
| 141 | Add("-out:" + StringRef(A->getValue())); | ||
| 142 | else if (Args.hasArg(OPT_shared)) | ||
| 143 | Add("-out:a.dll"); | ||
| 144 | else | ||
| 145 | Add("-out:a.exe"); | ||
| 146 | |||
| 147 | if (Args.hasArg(OPT_shared)) | ||
| 148 | Add("-dll"); | ||
| 149 | if (Args.hasArg(OPT_verbose)) | ||
| 150 | Add("-verbose"); | ||
| 151 | if (Args.hasArg(OPT_export_all_symbols)) | ||
| 152 | Add("-export-all-symbols"); | ||
| 153 | if (!Args.hasArg(OPT_strip_all)) | ||
| 154 | Add("-debug:dwarf"); | ||
| 155 | if (Args.hasArg(OPT_large_address_aware)) | ||
| 156 | Add("-largeaddressaware"); | ||
| 157 | |||
| 158 | if (Args.getLastArgValue(OPT_m) != "thumb2pe" && | ||
| 159 | Args.getLastArgValue(OPT_m) != "arm64pe" && !Args.hasArg(OPT_dynamicbase)) | ||
| 160 | Add("-dynamicbase:no"); | ||
| 161 | |||
| 162 | if (Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) | ||
| 163 | Add("-opt:ref"); | ||
| 164 | else | ||
| 165 | Add("-opt:noref"); | ||
| 166 | |||
| 167 | if (auto *A = Args.getLastArg(OPT_icf)) { | ||
| 168 | StringRef S = A->getValue(); | ||
| 169 | if (S == "all") | ||
| 170 | Add("-opt:icf"); | ||
| 171 | else if (S == "safe" || S == "none") | ||
| 172 | Add("-opt:noicf"); | ||
| 173 | else | ||
| 174 | fatal("unknown parameter: --icf=" + S); | ||
| 175 | } else { | ||
| 176 | Add("-opt:noicf"); | ||
| 177 | } | ||
| 178 | |||
| 179 | if (auto *A = Args.getLastArg(OPT_m)) { | ||
| 180 | StringRef S = A->getValue(); | ||
| 181 | if (S == "i386pe") | ||
| 182 | Add("-machine:x86"); | ||
| 183 | else if (S == "i386pep") | ||
| 184 | Add("-machine:x64"); | ||
| 185 | else if (S == "thumb2pe") | ||
| 186 | Add("-machine:arm"); | ||
| 187 | else if (S == "arm64pe") | ||
| 188 | Add("-machine:arm64"); | ||
| 189 | else | ||
| 190 | fatal("unknown parameter: -m" + S); | ||
| 191 | } | ||
| 192 | |||
| 193 | for (auto *A : Args.filtered(OPT_mllvm)) | ||
| 194 | Add("-mllvm:" + StringRef(A->getValue())); | ||
| 195 | |||
| 196 | for (auto *A : Args.filtered(OPT_Xlink)) | ||
| 197 | Add(A->getValue()); | ||
| 198 | |||
| 199 | if (Args.getLastArgValue(OPT_m) == "i386pe") | ||
| 200 | Add("-alternatename:__image_base__=___ImageBase"); | ||
| 201 | else | ||
| 202 | Add("-alternatename:__image_base__=__ImageBase"); | ||
| 203 | |||
| 204 | std::vector<StringRef> SearchPaths; | ||
| 205 | for (auto *A : Args.filtered(OPT_L)) | ||
| 206 | SearchPaths.push_back(A->getValue()); | ||
| 207 | |||
| 208 | StringRef Prefix = ""; | ||
| 209 | bool Static = false; | ||
| 210 | for (auto *A : Args) { | ||
| 211 | switch (A->getOption().getUnaliasedOption().getID()) { | ||
| 212 | case OPT_INPUT: | ||
| 213 | if (StringRef(A->getValue()).endswith_lower(".def")) | ||
| 214 | Add("-def:" + StringRef(A->getValue())); | ||
| 215 | else | ||
| 216 | Add(Prefix + StringRef(A->getValue())); | ||
| 217 | break; | ||
| 218 | case OPT_l: | ||
| 219 | Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static)); | ||
| 220 | break; | ||
| 221 | case OPT_whole_archive: | ||
| 222 | Prefix = "-wholearchive:"; | ||
| 223 | break; | ||
| 224 | case OPT_no_whole_archive: | ||
| 225 | Prefix = ""; | ||
| 226 | break; | ||
| 227 | case OPT_Bstatic: | ||
| 228 | Static = true; | ||
| 229 | break; | ||
| 230 | case OPT_Bdynamic: | ||
| 231 | Static = false; | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | if (Args.hasArg(OPT_verbose) || Args.hasArg(OPT__HASH_HASH_HASH)) | ||
| 237 | outs() << llvm::join(LinkArgs, " ") << "\n"; | ||
| 238 | |||
| 239 | if (Args.hasArg(OPT__HASH_HASH_HASH)) | ||
| 240 | return true; | ||
| 241 | |||
| 242 | // Repack vector of strings to vector of const char pointers for coff::link. | ||
| 243 | std::vector<const char *> Vec; | ||
| 244 | for (const std::string &S : LinkArgs) | ||
| 245 | Vec.push_back(S.c_str()); | ||
| 246 | return coff::link(Vec, true); | ||
| 247 | } | ||
deps/lld/MinGW/Options.td created+68| ... | @@ -0,0 +1,68 @@ | ||
| 1 | include "llvm/Option/OptParser.td" | ||
| 2 | |||
| 3 | class F<string name>: Flag<["--", "-"], name>; | ||
| 4 | class J<string name>: Joined<["--", "-"], name>; | ||
| 5 | class S<string name>: Separate<["--", "-"], name>; | ||
| 6 | |||
| 7 | def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">, | ||
| 8 | HelpText<"Add a directory to the library search path">; | ||
| 9 | def dynamicbase: F<"dynamicbase">, HelpText<"Enable ASLR">; | ||
| 10 | def entry: S<"entry">, MetaVarName<"<entry>">, | ||
| 11 | HelpText<"Name of entry point symbol">; | ||
| 12 | def export_all_symbols: F<"export-all-symbols">, | ||
| 13 | HelpText<"Export all symbols even if a def file or dllexport attributes are used">; | ||
| 14 | def gc_sections: F<"gc-sections">, HelpText<"Remove unused sections">; | ||
| 15 | def icf: J<"icf=">, HelpText<"Identical code folding">; | ||
| 16 | def image_base: S<"image-base">, HelpText<"Base address of the program">; | ||
| 17 | def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">, | ||
| 18 | HelpText<"Root name of library to use">; | ||
| 19 | def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">; | ||
| 20 | def no_whole_archive: F<"no-whole-archive">, | ||
| 21 | HelpText<"No longer include all object files for following archives">; | ||
| 22 | def large_address_aware: Flag<["--"], "large-address-aware">, | ||
| 23 | HelpText<"Enable large addresses">; | ||
| 24 | def no_gc_sections: F<"no-gc-sections">, HelpText<"Don't remove unused sections">; | ||
| 25 | def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">, | ||
| 26 | HelpText<"Path to file to write output">; | ||
| 27 | def out_implib: Separate<["--"], "out-implib">, HelpText<"Import library name">; | ||
| 28 | def out_implib_eq: Joined<["--"], "out-implib=">, Alias<out_implib>; | ||
| 29 | def output_def: S<"output-def">, HelpText<"Output def file">; | ||
| 30 | def shared: F<"shared">, HelpText<"Build a shared object">; | ||
| 31 | def subs: S<"subsystem">, HelpText<"Specify subsystem">; | ||
| 32 | def stack: S<"stack">; | ||
| 33 | def strip_all: F<"strip-all">, | ||
| 34 | HelpText<"Omit all symbol information from the output binary">; | ||
| 35 | def whole_archive: F<"whole-archive">, | ||
| 36 | HelpText<"Include all object files for following archives">; | ||
| 37 | def verbose: F<"verbose">, HelpText<"Verbose mode">; | ||
| 38 | |||
| 39 | // LLD specific options | ||
| 40 | def _HASH_HASH_HASH : Flag<["-"], "###">, | ||
| 41 | HelpText<"Print (but do not run) the commands to run for this compilation">; | ||
| 42 | def mllvm: S<"mllvm">; | ||
| 43 | def Xlink : J<"Xlink=">, MetaVarName<"<arg>">, | ||
| 44 | HelpText<"Pass <arg> to the COFF linker">; | ||
| 45 | |||
| 46 | // Currently stubs to avoid errors | ||
| 47 | def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">; | ||
| 48 | def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">; | ||
| 49 | def O: Joined<["-"], "O">, HelpText<"Optimize output file size">; | ||
| 50 | def build_id: F<"build-id">; | ||
| 51 | def disable_auto_image_base: F<"disable-auto-image-base">; | ||
| 52 | def enable_auto_image_base: F<"enable-auto-image-base">; | ||
| 53 | def enable_auto_import: F<"enable-auto-import">; | ||
| 54 | def full_shutdown: Flag<["--"], "full-shutdown">; | ||
| 55 | def high_entropy_va: F<"high-entropy-va">, HelpText<"Enable 64-bit ASLR">; | ||
| 56 | def major_image_version: S<"major-image-version">; | ||
| 57 | def minor_image_version: S<"minor-image-version">; | ||
| 58 | def no_seh: F<"no-seh">; | ||
| 59 | def nxcompat: F<"nxcompat">, HelpText<"Enable data execution prevention">; | ||
| 60 | def pic_executable: F<"pic-executable">; | ||
| 61 | def sysroot: J<"sysroot">, HelpText<"Sysroot">; | ||
| 62 | def tsaware: F<"tsaware">, HelpText<"Create Terminal Server aware executable">; | ||
| 63 | def v: Flag<["-"], "v">, HelpText<"Display the version number">; | ||
| 64 | def version: F<"version">, HelpText<"Display the version number and exit">; | ||
| 65 | |||
| 66 | // Alias | ||
| 67 | def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; | ||
| 68 | def alias_strip_s: Flag<["-"], "s">, Alias<strip_all>; | ||
deps/lld/README.md+10-2| ... | @@ -1,6 +1,5 @@ | ... | @@ -1,6 +1,5 @@ |
| 1 | |||
| 2 | LLVM Linker (lld) | 1 | LLVM Linker (lld) |
| 3 | ============================== | 2 | ================= |
| 4 | 3 | ||
| 5 | This directory and its subdirectories contain source code for the LLVM Linker, a | 4 | This directory and its subdirectories contain source code for the LLVM Linker, a |
| 6 | modular cross platform linker which is built as part of the LLVM compiler | 5 | modular cross platform linker which is built as part of the LLVM compiler |
| ... | @@ -9,3 +8,12 @@ infrastructure project. | ... | @@ -9,3 +8,12 @@ infrastructure project. |
| 9 | lld is open source software. You may freely distribute it under the terms of | 8 | lld is open source software. You may freely distribute it under the terms of |
| 10 | the license agreement found in LICENSE.txt. | 9 | the license agreement found in LICENSE.txt. |
| 11 | 10 | ||
| 11 | Benchmarking | ||
| 12 | ============ | ||
| 13 | |||
| 14 | In order to make sure various developers can evaluate patches over the | ||
| 15 | same tests, we create a collection of self contained programs. | ||
| 16 | |||
| 17 | It is hosted at https://s3-us-west-2.amazonaws.com/linker-tests/lld-speed-test.tar.xz | ||
| 18 | |||
| 19 | The current sha256 is 10eec685463d5a8bbf08d77f4ca96282161d396c65bd97dc99dbde644a31610f. |
deps/lld/cmake/modules/AddLLD.cmake+4-8| ... | @@ -25,11 +25,9 @@ macro(add_lld_library name) | ... | @@ -25,11 +25,9 @@ macro(add_lld_library name) |
| 25 | RUNTIME DESTINATION bin) | 25 | RUNTIME DESTINATION bin) |
| 26 | 26 | ||
| 27 | if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES) | 27 | if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES) |
| 28 | add_custom_target(install-${name} | 28 | add_llvm_install_targets(install-${name} |
| 29 | DEPENDS ${name} | 29 | DEPENDS ${name} |
| 30 | COMMAND "${CMAKE_COMMAND}" | 30 | COMPONENT ${name}) |
| 31 | -DCMAKE_INSTALL_COMPONENT=${name} | ||
| 32 | -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") | ||
| 33 | endif() | 31 | endif() |
| 34 | set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) | 32 | set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) |
| 35 | endif() | 33 | endif() |
| ... | @@ -60,11 +58,9 @@ macro(add_lld_tool name) | ... | @@ -60,11 +58,9 @@ macro(add_lld_tool name) |
| 60 | COMPONENT ${name}) | 58 | COMPONENT ${name}) |
| 61 | 59 | ||
| 62 | if(NOT CMAKE_CONFIGURATION_TYPES) | 60 | if(NOT CMAKE_CONFIGURATION_TYPES) |
| 63 | add_custom_target(install-${name} | 61 | add_llvm_install_targets(install-${name} |
| 64 | DEPENDS ${name} | 62 | DEPENDS ${name} |
| 65 | COMMAND "${CMAKE_COMMAND}" | 63 | COMPONENT ${name}) |
| 66 | -DCMAKE_INSTALL_COMPONENT=${name} | ||
| 67 | -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") | ||
| 68 | endif() | 64 | endif() |
| 69 | set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) | 65 | set_property(GLOBAL APPEND PROPERTY LLD_EXPORTS ${name}) |
| 70 | endif() | 66 | endif() |
deps/lld/docs/Driver.rst+1-1| ... | @@ -65,7 +65,7 @@ Adding an Option to an existing Flavor | ... | @@ -65,7 +65,7 @@ Adding an Option to an existing Flavor |
| 65 | Adding a Flavor | 65 | Adding a Flavor |
| 66 | =============== | 66 | =============== |
| 67 | 67 | ||
| 68 | #. Add an entry for the flavor in :file:`include/lld/Driver/Driver.h` to | 68 | #. Add an entry for the flavor in :file:`include/lld/Common/Driver.h` to |
| 69 | :cpp:class:`lld::UniversalDriver::Flavor`. | 69 | :cpp:class:`lld::UniversalDriver::Flavor`. |
| 70 | 70 | ||
| 71 | #. Add an entry in :file:`lib/Driver/UniversalDriver.cpp` to | 71 | #. Add an entry in :file:`lib/Driver/UniversalDriver.cpp` to |
deps/lld/docs/NewLLD.rst+67-72| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | The ELF and COFF Linkers | 1 | The ELF, COFF and Wasm Linkers |
| 2 | ======================== | 2 | ============================== |
| 3 | 3 | ||
| 4 | The ELF Linker as a Library | 4 | The ELF Linker as a Library |
| 5 | --------------------------- | 5 | --------------------------- |
| ... | @@ -33,11 +33,12 @@ between speed, simplicity and extensibility. | ... | @@ -33,11 +33,12 @@ between speed, simplicity and extensibility. |
| 33 | 33 | ||
| 34 | We implemented the linkers as native linkers for each file format. | 34 | We implemented the linkers as native linkers for each file format. |
| 35 | 35 | ||
| 36 | The two linkers share the same design but do not share code. | 36 | The linkers share the same design but share very little code. |
| 37 | Sharing code makes sense if the benefit is worth its cost. | 37 | Sharing code makes sense if the benefit is worth its cost. |
| 38 | In our case, ELF and COFF are different enough that we thought the layer to | 38 | In our case, the object formats are different enough that we thought the layer |
| 39 | abstract the differences wouldn't worth its complexity and run-time cost. | 39 | to abstract the differences wouldn't be worth its complexity and run-time |
| 40 | Elimination of the abstract layer has greatly simplified the implementation. | 40 | cost. Elimination of the abstract layer has greatly simplified the |
| 41 | implementation. | ||
| 41 | 42 | ||
| 42 | * Speed by design | 43 | * Speed by design |
| 43 | 44 | ||
| ... | @@ -57,59 +58,61 @@ between speed, simplicity and extensibility. | ... | @@ -57,59 +58,61 @@ between speed, simplicity and extensibility. |
| 57 | 58 | ||
| 58 | * Efficient archive file handling | 59 | * Efficient archive file handling |
| 59 | 60 | ||
| 60 | LLD's handling of archive files (the files with ".a" file extension) is different | 61 | LLD's handling of archive files (the files with ".a" file extension) is |
| 61 | from the traditional Unix linkers and similar to Windows linkers. | 62 | different from the traditional Unix linkers and similar to Windows linkers. |
| 62 | We'll describe how the traditional Unix linker handles archive files, | 63 | We'll describe how the traditional Unix linker handles archive files, what the |
| 63 | what the problem is, and how LLD approached the problem. | 64 | problem is, and how LLD approached the problem. |
| 64 | 65 | ||
| 65 | The traditional Unix linker maintains a set of undefined symbols during linking. | 66 | The traditional Unix linker maintains a set of undefined symbols during |
| 66 | The linker visits each file in the order as they appeared in the command line | 67 | linking. The linker visits each file in the order as they appeared in the |
| 67 | until the set becomes empty. What the linker would do depends on file type. | 68 | command line until the set becomes empty. What the linker would do depends on |
| 69 | file type. | ||
| 68 | 70 | ||
| 69 | - If the linker visits an object file, the linker links object files to the result, | 71 | - If the linker visits an object file, the linker links object files to the |
| 70 | and undefined symbols in the object file are added to the set. | 72 | result, and undefined symbols in the object file are added to the set. |
| 71 | 73 | ||
| 72 | - If the linker visits an archive file, it checks for the archive file's symbol table | 74 | - If the linker visits an archive file, it checks for the archive file's |
| 73 | and extracts all object files that have definitions for any symbols in the set. | 75 | symbol table and extracts all object files that have definitions for any |
| 76 | symbols in the set. | ||
| 74 | 77 | ||
| 75 | This algorithm sometimes leads to a counter-intuitive behavior. | 78 | This algorithm sometimes leads to a counter-intuitive behavior. If you give |
| 76 | If you give archive files before object files, nothing will happen | 79 | archive files before object files, nothing will happen because when the linker |
| 77 | because when the linker visits archives, there is no undefined symbols in the set. | 80 | visits archives, there is no undefined symbols in the set. As a result, no |
| 78 | As a result, no files are extracted from the first archive file, | 81 | files are extracted from the first archive file, and the link is done at that |
| 79 | and the link is done at that point because the set is empty after it visits one file. | 82 | point because the set is empty after it visits one file. |
| 80 | 83 | ||
| 81 | You can fix the problem by reordering the files, | 84 | You can fix the problem by reordering the files, |
| 82 | but that cannot fix the issue of mutually-dependent archive files. | 85 | but that cannot fix the issue of mutually-dependent archive files. |
| 83 | 86 | ||
| 84 | Linking mutually-dependent archive files is tricky. | 87 | Linking mutually-dependent archive files is tricky. You may specify the same |
| 85 | You may specify the same archive file multiple times to | 88 | archive file multiple times to let the linker visit it more than once. Or, |
| 86 | let the linker visit it more than once. | 89 | you may use the special command line options, `--start-group` and |
| 87 | Or, you may use the special command line options, `--start-group` and `--end-group`, | 90 | `--end-group`, to let the linker loop over the files between the options until |
| 88 | to let the linker loop over the files between the options until | ||
| 89 | no new symbols are added to the set. | 91 | no new symbols are added to the set. |
| 90 | 92 | ||
| 91 | Visiting the same archive files multiple makes the linker slower. | 93 | Visiting the same archive files multiple makes the linker slower. |
| 92 | 94 | ||
| 93 | Here is how LLD approaches the problem. Instead of memorizing only undefined symbols, | 95 | Here is how LLD approaches the problem. Instead of memorizing only undefined |
| 94 | we program LLD so that it memorizes all symbols. | 96 | symbols, we program LLD so that it memorizes all symbols. When it sees an |
| 95 | When it sees an undefined symbol that can be resolved by extracting an object file | 97 | undefined symbol that can be resolved by extracting an object file from an |
| 96 | from an archive file it previously visited, it immediately extracts the file and link it. | 98 | archive file it previously visited, it immediately extracts the file and link |
| 97 | It is doable because LLD does not forget symbols it have seen in archive files. | 99 | it. It is doable because LLD does not forget symbols it have seen in archive |
| 100 | files. | ||
| 98 | 101 | ||
| 99 | We believe that the LLD's way is efficient and easy to justify. | 102 | We believe that the LLD's way is efficient and easy to justify. |
| 100 | 103 | ||
| 101 | The semantics of LLD's archive handling is different from the traditional Unix's. | 104 | The semantics of LLD's archive handling is different from the traditional |
| 102 | You can observe it if you carefully craft archive files to exploit it. | 105 | Unix's. You can observe it if you carefully craft archive files to exploit |
| 103 | However, in reality, we don't know any program that cannot link | 106 | it. However, in reality, we don't know any program that cannot link with our |
| 104 | with our algorithm so far, so it's not going to cause trouble. | 107 | algorithm so far, so it's not going to cause trouble. |
| 105 | 108 | ||
| 106 | Numbers You Want to Know | 109 | Numbers You Want to Know |
| 107 | ------------------------ | 110 | ------------------------ |
| 108 | 111 | ||
| 109 | To give you intuition about what kinds of data the linker is mainly working on, | 112 | To give you intuition about what kinds of data the linker is mainly working on, |
| 110 | I'll give you the list of objects and their numbers LLD has to read and process | 113 | I'll give you the list of objects and their numbers LLD has to read and process |
| 111 | in order to link a very large executable. In order to link Chrome with debug info, | 114 | in order to link a very large executable. In order to link Chrome with debug |
| 112 | which is roughly 2 GB in output size, LLD reads | 115 | info, which is roughly 2 GB in output size, LLD reads |
| 113 | 116 | ||
| 114 | - 17,000 files, | 117 | - 17,000 files, |
| 115 | - 1,800,000 sections, | 118 | - 1,800,000 sections, |
| ... | @@ -136,17 +139,17 @@ when handling files. | ... | @@ -136,17 +139,17 @@ when handling files. |
| 136 | Important Data Structures | 139 | Important Data Structures |
| 137 | ------------------------- | 140 | ------------------------- |
| 138 | 141 | ||
| 139 | We will describe the key data structures in LLD in this section. | 142 | We will describe the key data structures in LLD in this section. The linker can |
| 140 | The linker can be understood as the interactions between them. | 143 | be understood as the interactions between them. Once you understand their |
| 141 | Once you understand their functions, the code of the linker should look obvious to you. | 144 | functions, the code of the linker should look obvious to you. |
| 142 | 145 | ||
| 143 | * SymbolBody | 146 | * Symbol |
| 144 | 147 | ||
| 145 | SymbolBody is a class to represent symbols. | 148 | This class represents a symbol. |
| 146 | They are created for symbols in object files or archive files. | 149 | They are created for symbols in object files or archive files. |
| 147 | The linker creates linker-defined symbols as well. | 150 | The linker creates linker-defined symbols as well. |
| 148 | 151 | ||
| 149 | There are basically three types of SymbolBodies: Defined, Undefined, or Lazy. | 152 | There are basically three types of Symbols: Defined, Undefined, or Lazy. |
| 150 | 153 | ||
| 151 | - Defined symbols are for all symbols that are considered as "resolved", | 154 | - Defined symbols are for all symbols that are considered as "resolved", |
| 152 | including real defined symbols, COMDAT symbols, common symbols, | 155 | including real defined symbols, COMDAT symbols, common symbols, |
| ... | @@ -156,33 +159,25 @@ Once you understand their functions, the code of the linker should look obvious | ... | @@ -156,33 +159,25 @@ Once you understand their functions, the code of the linker should look obvious |
| 156 | - Lazy symbols represent symbols we found in archive file headers | 159 | - Lazy symbols represent symbols we found in archive file headers |
| 157 | which can turn into Defined if we read archieve members. | 160 | which can turn into Defined if we read archieve members. |
| 158 | 161 | ||
| 159 | * Symbol | 162 | There's only one Symbol instance for each unique symbol name. This uniqueness |
| 163 | is guaranteed by the symbol table. As the resolver reads symbols from input | ||
| 164 | files, it replaces an existing Symbol with the "best" Symbol for its symbol | ||
| 165 | name using the placement new. | ||
| 160 | 166 | ||
| 161 | A Symbol is a container for a SymbolBody. There's only one Symbol for each | 167 | The above mechanism allows you to use pointers to Symbols as a very cheap way |
| 162 | unique symbol name (this uniqueness is guaranteed by the symbol table). | 168 | to access name resolution results. Assume for example that you have a pointer |
| 163 | Each global symbol has only one SymbolBody at any one time, which is | 169 | to an undefined symbol before name resolution. If the symbol is resolved to a |
| 164 | the SymbolBody stored within a memory region of the Symbol large enough | 170 | defined symbol by the resolver, the pointer will "automatically" point to the |
| 165 | to store any SymbolBody. | 171 | defined symbol, because the undefined symbol the pointer pointed to will have |
| 166 | 172 | been replaced by the defined symbol in-place. | |
| 167 | As the resolver reads symbols from input files, it replaces the Symbol's | ||
| 168 | SymbolBody with the "best" SymbolBody for its symbol name by constructing | ||
| 169 | the new SymbolBody in place on top of the existing SymbolBody. For example, | ||
| 170 | if the resolver is given a defined symbol, and the SymbolBody with its name | ||
| 171 | is undefined, it will construct a Defined SymbolBody over the Undefined | ||
| 172 | SymbolBody. | ||
| 173 | |||
| 174 | This means that each SymbolBody pointer always points to the best SymbolBody, | ||
| 175 | and it is possible to get from a SymbolBody to a Symbol, or vice versa, | ||
| 176 | by adding or subtracting a fixed offset. This memory layout helps reduce | ||
| 177 | the cache miss rate through high locality and a small number of required | ||
| 178 | pointer indirections. | ||
| 179 | 173 | ||
| 180 | * SymbolTable | 174 | * SymbolTable |
| 181 | 175 | ||
| 182 | SymbolTable is basically a hash table from strings to Symbols | 176 | SymbolTable is basically a hash table from strings to Symbols |
| 183 | with logic to resolve symbol conflicts. It resolves conflicts by symbol type. | 177 | with logic to resolve symbol conflicts. It resolves conflicts by symbol type. |
| 184 | 178 | ||
| 185 | - If we add Defined and Undefined symbols, the symbol table will keep the former. | 179 | - If we add Defined and Undefined symbols, the symbol table will keep the |
| 180 | former. | ||
| 186 | - If we add Defined and Lazy symbols, it will keep the former. | 181 | - If we add Defined and Lazy symbols, it will keep the former. |
| 187 | - If we add Lazy and Undefined, it will keep the former, | 182 | - If we add Lazy and Undefined, it will keep the former, |
| 188 | but it will also trigger the Lazy symbol to load the archive member | 183 | but it will also trigger the Lazy symbol to load the archive member |
| ... | @@ -221,15 +216,14 @@ There are mainly three actors in this linker. | ... | @@ -221,15 +216,14 @@ There are mainly three actors in this linker. |
| 221 | InputFile is a superclass of file readers. | 216 | InputFile is a superclass of file readers. |
| 222 | We have a different subclass for each input file type, | 217 | We have a different subclass for each input file type, |
| 223 | such as regular object file, archive file, etc. | 218 | such as regular object file, archive file, etc. |
| 224 | They are responsible for creating and owning SymbolBodies and | 219 | They are responsible for creating and owning Symbols and InputSections/Chunks. |
| 225 | InputSections/Chunks. | ||
| 226 | 220 | ||
| 227 | * Writer | 221 | * Writer |
| 228 | 222 | ||
| 229 | The writer is responsible for writing file headers and InputSections/Chunks to a file. | 223 | The writer is responsible for writing file headers and InputSections/Chunks to |
| 230 | It creates OutputSections, put all InputSections/Chunks into them, | 224 | a file. It creates OutputSections, put all InputSections/Chunks into them, |
| 231 | assign unique, non-overlapping addresses and file offsets to them, | 225 | assign unique, non-overlapping addresses and file offsets to them, and then |
| 232 | and then write them down to a file. | 226 | write them down to a file. |
| 233 | 227 | ||
| 234 | * Driver | 228 | * Driver |
| 235 | 229 | ||
| ... | @@ -237,7 +231,8 @@ There are mainly three actors in this linker. | ... | @@ -237,7 +231,8 @@ There are mainly three actors in this linker. |
| 237 | 231 | ||
| 238 | - processes command line options, | 232 | - processes command line options, |
| 239 | - creates a symbol table, | 233 | - creates a symbol table, |
| 240 | - creates an InputFile for each input file and puts all symbols within into the symbol table, | 234 | - creates an InputFile for each input file and puts all symbols within into |
| 235 | the symbol table, | ||
| 241 | - checks if there's no remaining undefined symbols, | 236 | - checks if there's no remaining undefined symbols, |
| 242 | - creates a writer, | 237 | - creates a writer, |
| 243 | - and passes the symbol table to the writer to write the result to a file. | 238 | - and passes the symbol table to the writer to write the result to a file. |
| ... | @@ -301,7 +296,7 @@ Glossary | ... | @@ -301,7 +296,7 @@ Glossary |
| 301 | they are merged by ICF. It is known as an effective technique, | 296 | they are merged by ICF. It is known as an effective technique, |
| 302 | and it usually reduces C++ program's size by a few percent or more. | 297 | and it usually reduces C++ program's size by a few percent or more. |
| 303 | 298 | ||
| 304 | Note that this is not entirely sound optimization. C/C++ require | 299 | Note that this is not an entirely sound optimization. C/C++ require |
| 305 | different functions have different addresses. If a program depends on | 300 | different functions have different addresses. If a program depends on |
| 306 | that property, it would fail at runtime. | 301 | that property, it would fail at runtime. |
| 307 | 302 |
deps/lld/docs/ReleaseNotes.rst+22-151| ... | @@ -1,23 +1,22 @@ | ... | @@ -1,23 +1,22 @@ |
| 1 | ======================= | 1 | ======================= |
| 2 | lld 5.0.0 Release Notes | 2 | LLD 6.0.0 Release Notes |
| 3 | ======================= | 3 | ======================= |
| 4 | 4 | ||
| 5 | .. contents:: | 5 | .. contents:: |
| 6 | :local: | 6 | :local: |
| 7 | 7 | ||
| 8 | .. warning:: | ||
| 9 | These are in-progress notes for the upcoming LLVM 6.0.0 release. | ||
| 10 | Release notes for previous releases can be found on | ||
| 11 | `the Download Page <http://releases.llvm.org/download.html>`_. | ||
| 12 | |||
| 8 | Introduction | 13 | Introduction |
| 9 | ============ | 14 | ============ |
| 10 | 15 | ||
| 11 | lld is a linker from the LLVM project. It supports ELF (Unix), COFF (Windows) | 16 | This document contains the release notes for the LLD linker, release 6.0.0. |
| 12 | and Mach-O (macOS), and it is generally faster than the GNU bfd or gold linkers | 17 | Here we describe the status of LLD, including major improvements |
| 13 | or the MSVC linker. | 18 | from the previous release. All LLD releases may be downloaded |
| 14 | 19 | from the `LLVM releases web site <http://llvm.org/releases/>`_. | |
| 15 | lld is designed to be a drop-in replacement for the system linkers, so that | ||
| 16 | users don't need to change their build systems other than swapping the linker | ||
| 17 | command. | ||
| 18 | |||
| 19 | All lld releases may be downloaded from the `LLVM releases web site | ||
| 20 | <http://llvm.org/releases/>`_. | ||
| 21 | 20 | ||
| 22 | Non-comprehensive list of changes in this release | 21 | Non-comprehensive list of changes in this release |
| 23 | ================================================= | 22 | ================================================= |
| ... | @@ -25,148 +24,20 @@ Non-comprehensive list of changes in this release | ... | @@ -25,148 +24,20 @@ Non-comprehensive list of changes in this release |
| 25 | ELF Improvements | 24 | ELF Improvements |
| 26 | ---------------- | 25 | ---------------- |
| 27 | 26 | ||
| 28 | * First and foremost, a lot of compatibility issues and bugs have been fixed. | 27 | * Item 1. |
| 29 | Linker script support has significantly improved. As a result, we believe you | ||
| 30 | are very likely to be able to link your programs with lld without experiencing | ||
| 31 | any problem now. | ||
| 32 | |||
| 33 | * Error message format has changed in order to improve readability. | ||
| 34 | Traditionally, linker's error messages are concise and arguably too terse. | ||
| 35 | This is an example of lld 4.0.0's error message (they are actually in one line):: | ||
| 36 | |||
| 37 | /ssd/clang/bin/ld.lld: error: /ssd/llvm-project/lld/ELF/Writer.cpp:207: | ||
| 38 | undefined symbol 'lld::elf::EhFrameSection::addSection()' | ||
| 39 | |||
| 40 | It is not easy to read because too much information is packed into a single line | ||
| 41 | and the embedded text, particularly a symbol name, is sometimes too long. | ||
| 42 | In lld 5.0.0, we use more vertical space to print out error messages in a more | ||
| 43 | structured manner like this:: | ||
| 44 | |||
| 45 | bin/ld.lld: error: undefined symbol: lld::elf::EhFrameSection::addSection() | ||
| 46 | >>> Referenced by Writer.cpp:207 (/ssd/llvm-project/lld/ELF/Writer.cpp:207) | ||
| 47 | >>> Writer.cpp.o in archive lib/liblldELF.a | ||
| 48 | |||
| 49 | As a bonus, the new error message contains source code location of the error | ||
| 50 | if it is available from debug info. | ||
| 51 | |||
| 52 | * ``./configure`` scripts generated by GNU autoconf determines whether a linker | ||
| 53 | supports modern GNU-compatible features or not by searching for "GNU" in the | ||
| 54 | ``--help`` message. To be compatible with the scripts, we decided to add a | ||
| 55 | string "(compatible with GNU linkers)" to our ``--help`` message. This is a | ||
| 56 | hack, but just like the web browser's User-Agent string (which everyone still | ||
| 57 | claim they are "Mozilla/5.0"), we had no choice other than doing this to claim | ||
| 58 | that we accept GNU-compatible options. | ||
| 59 | 28 | ||
| 60 | * The ``-Map`` option is added. The option is to make the linker to print out how | 29 | COFF Improvements |
| 61 | input files are mapped to the output file. Here is an example:: | 30 | ----------------- |
| 62 | 31 | ||
| 63 | Address Size Align Out In Symbol | 32 | * A GNU ld style frontend for the COFF linker has been added for MinGW. |
| 64 | 00000000016d84d8 00000000008f8f50 8 .eh_frame | 33 | In MinGW environments, the linker is invoked with GNU ld style parameters; |
| 65 | 00000000016d84d8 00000000008f8f50 8 <internal>:(.eh_frame) | 34 | which LLD previously only supported when used as an ELF linker. When |
| 66 | 0000000001fd2000 00000000034b3bd0 16 .text | 35 | a PE/COFF target is chosen, those parameters are rewritten into the |
| 67 | 0000000001fd2000 000000000000002a 1 /usr/lib/x86_64-linux-gnu/crt1.o:(.text) | 36 | lld-link style parameters and the COFF linker is invoked instead. |
| 68 | 0000000001fd2000 0000000000000000 0 _start | ||
| 69 | 0000000001fd202a 0000000000000000 1 /usr/lib/x86_64-linux-gnu/crti.o:(.text) | ||
| 70 | 0000000001fd2030 00000000000000bd 16 /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o:(.text) | ||
| 71 | 0000000001fd2030 0000000000000000 0 deregister_tm_clones | ||
| 72 | 0000000001fd2060 0000000000000000 0 register_tm_clones | ||
| 73 | 37 | ||
| 74 | This format is not the same as GNU linkers as our linker internal data | 38 | * Initial support for the ARM64 architecture has been added. |
| 75 | structure is different from them but contains the same amount of information | ||
| 76 | and should be more readable than their outputs. | ||
| 77 | |||
| 78 | As with other lld features, the ``-Map`` option is designed with speed in mind. | ||
| 79 | The option would generate a hundred megabyte text file if you link a large | ||
| 80 | program with it. lld can usually do that in a few seconds, and it is generally | ||
| 81 | a few times faster than the GNU gold's ``-Map`` option. | ||
| 82 | |||
| 83 | * lld's ``--gdb-index`` option used to be slow, but we sped it up so that it is | ||
| 84 | at least as fast as the GNU gold. | ||
| 85 | |||
| 86 | * Some nonstandard relocations, such as R_X86_64_8 or R_X86_64_16, are supported. | ||
| 87 | They are not used for 32/64-bit applications, but some 16-bit bootloaders need | ||
| 88 | them. | ||
| 89 | |||
| 90 | * Paddings in executable text sections are now filled with trap instructions | ||
| 91 | (such as INT3) instead of being left as null bytes. This change improves | ||
| 92 | disassembler outputs because it now prints out trap instructions instead of | ||
| 93 | trying to decode 0x00 as an instruction. It also makes debugging of some type | ||
| 94 | of program easier because when the control reaches a padding, the program | ||
| 95 | immediately raises an error. | ||
| 96 | |||
| 97 | * The following options are added: ``-M``, ``-Map``, | ||
| 98 | ``-compress-debug-sections``, ``-emit-relocs``, | ||
| 99 | ``-error-unresolved-symbols``, ``-exclude-libs``, ``-filter``, | ||
| 100 | ``-no-dynamic-linker``, ``-no-export-dynamic``, ``-no-fatal-warnings``, | ||
| 101 | ``-print-map``, ``-warn-unresolved-symbols``, ``-z nocopyreloc``, | ||
| 102 | ``-z notext``, ``-z rodynamic`` | ||
| 103 | |||
| 104 | |||
| 105 | Contributors to lld 5.0 | ||
| 106 | ======================= | ||
| 107 | 39 | ||
| 108 | We had 63 individuals contribute to lld 5.0. Thank you so much! | 40 | MachO Improvements |
| 41 | ------------------ | ||
| 109 | 42 | ||
| 110 | - Adrian McCarthy | 43 | * Item 1. |
| 111 | - Alberto Magni | ||
| 112 | - Alexander Richardson | ||
| 113 | - Andre Vieira | ||
| 114 | - Andrew Ng | ||
| 115 | - Anton Korobeynikov | ||
| 116 | - Bob Haarman | ||
| 117 | - David Blaikie | ||
| 118 | - Davide Italiano | ||
| 119 | - David L. Jones | ||
| 120 | - Dmitry Mikulin | ||
| 121 | - Ed Maste | ||
| 122 | - Ed Schouten | ||
| 123 | - Eric Beckmann | ||
| 124 | - Eric Fiselier | ||
| 125 | - Eugene Leviant | ||
| 126 | - Evgeniy Stepanov | ||
| 127 | - Galina Kistanova | ||
| 128 | - George Rimar | ||
| 129 | - Hans Wennborg | ||
| 130 | - Igor Kudrin | ||
| 131 | - Ismail Donmez | ||
| 132 | - Jake Ehrlich | ||
| 133 | - James Henderson | ||
| 134 | - Joel Jones | ||
| 135 | - Jon Chesterfield | ||
| 136 | - Kamil Rytarowski | ||
| 137 | - Kevin Enderby | ||
| 138 | - Konstantin Zhuravlyov | ||
| 139 | - Kyungwoo Lee | ||
| 140 | - Leslie Zhai | ||
| 141 | - Mark Kettenis | ||
| 142 | - Martell Malone | ||
| 143 | - Martin Storsjo | ||
| 144 | - Meador Inge | ||
| 145 | - Mehdi Amini | ||
| 146 | - Michal Gorny | ||
| 147 | - NAKAMURA Takumi | ||
| 148 | - Paul Robinson | ||
| 149 | - Pavel Labath | ||
| 150 | - Petar Jovanovic | ||
| 151 | - Peter Collingbourne | ||
| 152 | - Peter Smith | ||
| 153 | - Petr Hosek | ||
| 154 | - Rafael Espindola | ||
| 155 | - Reid Kleckner | ||
| 156 | - Richard Smith | ||
| 157 | - Robert Clarke | ||
| 158 | - Rui Ueyama | ||
| 159 | - Saleem Abdulrasool | ||
| 160 | - Sam Clegg | ||
| 161 | - Sean Eveson | ||
| 162 | - Sean Silva | ||
| 163 | - Shankar Easwaran | ||
| 164 | - Shoaib Meenai | ||
| 165 | - Simon Atanasyan | ||
| 166 | - Simon Dardis | ||
| 167 | - Simon Tatham | ||
| 168 | - Sylvestre Ledru | ||
| 169 | - Tom Stellard | ||
| 170 | - Vitaly Buka | ||
| 171 | - Yuka Takahashi | ||
| 172 | - Zachary Turner |
deps/lld/docs/WebAssembly.rst created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | WebAssembly lld port | ||
| 2 | ==================== | ||
| 3 | |||
| 4 | Note: The WebAssembly port is still a work in progress and is be lacking | ||
| 5 | certain features. | ||
| 6 | |||
| 7 | The WebAssembly version of lld takes WebAssembly binaries as inputs and produces | ||
| 8 | a WebAssembly binary as its output. For the most part this port tried to mimic | ||
| 9 | the behaviour of traditional ELF linkers and specifically the ELF lld port. | ||
| 10 | Where possible that command line flags and the semantics should be the same. | ||
| 11 | |||
| 12 | |||
| 13 | Object file format | ||
| 14 | ------------------ | ||
| 15 | |||
| 16 | The format the input object files that lld expects is specified as part of the | ||
| 17 | the WebAssembly tool conventions | ||
| 18 | https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md. | ||
| 19 | |||
| 20 | This is object format that the llvm will produce when run with the | ||
| 21 | ``wasm32-unknown-unknown-wasm`` target. To build llvm with WebAssembly support | ||
| 22 | currently requires enabling the experimental backed using | ||
| 23 | ``-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly``. | ||
| 24 | |||
| 25 | |||
| 26 | Missing features | ||
| 27 | ---------------- | ||
| 28 | |||
| 29 | There are several key features that are not yet implement in the WebAssembly | ||
| 30 | ports: | ||
| 31 | |||
| 32 | - COMDAT support. This means that support for C++ is still very limited. | ||
| 33 | - Function stripping. Currently there is no support for ``--gc-sections`` so | ||
| 34 | functions and data from a given object will linked as a unit. | ||
| 35 | - Section start/end symbols. The synthetic symbols that mark the start and | ||
| 36 | of data regions are not yet created in the output file. | ||
deps/lld/docs/_templates/indexsidebar.html+1-1| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | <h3>Bugs</h3> | 1 | <h3>Bugs</h3> |
| 2 | 2 | ||
| 3 | <p>lld bugs should be reported at the | 3 | <p>lld bugs should be reported at the |
| 4 | LLVM <a href="http://llvm.org/bugs">Bugzilla</a>.</p> | 4 | LLVM <a href="https://bugs.llvm.org/">Bugzilla</a>.</p> |
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. |
| 51 | version = '5' | 51 | version = '6' |
| 52 | # The full version, including alpha/beta/rc tags. | 52 | # The full version, including alpha/beta/rc tags. |
| 53 | release = '5' | 53 | release = '6' |
| 54 | 54 | ||
| 55 | # The language for content autogenerated by Sphinx. Refer to documentation | 55 | # 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/index.rst+27-28| ... | @@ -5,13 +5,14 @@ LLD is a linker from the LLVM project. That is a drop-in replacement | ... | @@ -5,13 +5,14 @@ LLD is a linker from the LLVM project. That is a drop-in replacement |
| 5 | for system linkers and runs much faster than them. It also provides | 5 | for system linkers and runs much faster than them. It also provides |
| 6 | features that are useful for toolchain developers. | 6 | features that are useful for toolchain developers. |
| 7 | 7 | ||
| 8 | The linker supports ELF (Unix), PE/COFF (Windows) and Mach-O (macOS) | 8 | The linker supports ELF (Unix), PE/COFF (Windows), Mach-O (macOS) and |
| 9 | in descending order of completeness. Internally, LLD consists of three | 9 | WebAssembly in descending order of completeness. Internally, LLD consists of |
| 10 | different linkers. The ELF port is the one that will be described in | 10 | several different linkers. The ELF port is the one that will be described in |
| 11 | this document. The PE/COFF port is almost complete except the lack of | 11 | this document. The PE/COFF port is almost complete except the lack of the |
| 12 | the Windows debug info (PDB) support. The Mach-O port is built based | 12 | Windows debug info (PDB) support. The WebAssembly port is still a work in |
| 13 | on a different architecture than the ELF or COFF ports. For the | 13 | progress (See :doc:`WebAssembly`). The Mach-O port is built based on a |
| 14 | details about Mach-O, please read :doc:`AtomLLD`. | 14 | different architecture than the others. For the details about Mach-O, please |
| 15 | read :doc:`AtomLLD`. | ||
| 15 | 16 | ||
| 16 | Features | 17 | Features |
| 17 | -------- | 18 | -------- |
| ... | @@ -71,30 +72,27 @@ Performance | ... | @@ -71,30 +72,27 @@ Performance |
| 71 | ----------- | 72 | ----------- |
| 72 | 73 | ||
| 73 | This is a link time comparison on a 2-socket 20-core 40-thread Xeon | 74 | This is a link time comparison on a 2-socket 20-core 40-thread Xeon |
| 74 | E5-2680 2.80 GHz machine with an SSD drive. | 75 | E5-2680 2.80 GHz machine with an SSD drive. We ran gold and lld with |
| 75 | 76 | or without multi-threading support. To disable multi-threading, we | |
| 76 | LLD is much faster than the GNU linkers for large programs. That's | 77 | added ``-no-threads`` to the command lines. |
| 77 | fast for small programs too, but because the link time is short | 78 | |
| 78 | anyway, the difference is not very noticeable in that case. | 79 | ============ =========== ============ ==================== ================== =============== ============= |
| 79 | 80 | Program Output size GNU ld GNU gold w/o threads GNU gold w/threads lld w/o threads lld w/threads | |
| 81 | ffmpeg dbg 92 MiB 1.72s 1.16s 1.01s 0.60s 0.35s | ||
| 82 | mysqld dbg 154 MiB 8.50s 2.96s 2.68s 1.06s 0.68s | ||
| 83 | clang dbg 1.67 GiB 104.03s 34.18s 23.49s 14.82s 5.28s | ||
| 84 | chromium dbg 1.14 GiB 209.05s [1]_ 64.70s 60.82s 27.60s 16.70s | ||
| 85 | ============ =========== ============ ==================== ================== =============== ============= | ||
| 86 | |||
| 87 | As you can see, lld is significantly faster than GNU linkers. | ||
| 80 | Note that this is just a benchmark result of our environment. | 88 | Note that this is just a benchmark result of our environment. |
| 81 | Depending on number of available cores, available amount of memory or | 89 | Depending on number of available cores, available amount of memory or |
| 82 | disk latency/throughput, your results may vary. | 90 | disk latency/throughput, your results may vary. |
| 83 | 91 | ||
| 84 | ============ =========== ============ ============= ====== | 92 | .. [1] Since GNU ld doesn't support the ``-icf=all`` and |
| 85 | Program Output size GNU ld GNU gold [1]_ LLD | 93 | ``-gdb-index`` options, we removed them from the command line |
| 86 | ffmpeg dbg 91 MiB 1.59s 1.15s 0.78s | 94 | for GNU ld. GNU ld would have been slower than this if it had |
| 87 | mysqld dbg 157 MiB 7.09s 2.49s 1.31s | 95 | these options. |
| 88 | clang dbg 1.45 GiB 86.76s 21.93s 8.38s | ||
| 89 | chromium dbg 1.52 GiB 142.30s [2]_ 40.86s 12.69s | ||
| 90 | ============ =========== ============ ============= ====== | ||
| 91 | |||
| 92 | .. [1] With the ``--threads`` option to enable multi-threading support. | ||
| 93 | |||
| 94 | .. [2] Since GNU ld doesn't support the ``-icf=all`` option, we | ||
| 95 | removed that from the command line for GNU ld. GNU ld would be | ||
| 96 | slower than this if it had that option support. For gold and | ||
| 97 | LLD, we use ``-icf=all``. | ||
| 98 | 96 | ||
| 99 | Build | 97 | Build |
| 100 | ----- | 98 | ----- |
| ... | @@ -110,7 +108,7 @@ build that tree. You need `cmake` and of course a C++ compiler. | ... | @@ -110,7 +108,7 @@ build that tree. You need `cmake` and of course a C++ compiler. |
| 110 | 108 | ||
| 111 | .. code-block:: console | 109 | .. code-block:: console |
| 112 | 110 | ||
| 113 | $ git clone https://github.com/llvm-project/llvm-project/ | 111 | $ git clone https://github.com/llvm-project/llvm-project-20170507 llvm-project |
| 114 | $ mkdir build | 112 | $ mkdir build |
| 115 | $ cd build | 113 | $ cd build |
| 116 | $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=lld -DCMAKE_INSTALL_PREFIX=/usr/local ../llvm-project/llvm | 114 | $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=lld -DCMAKE_INSTALL_PREFIX=/usr/local ../llvm-project/llvm |
| ... | @@ -175,5 +173,6 @@ document soon. | ... | @@ -175,5 +173,6 @@ document soon. |
| 175 | 173 | ||
| 176 | NewLLD | 174 | NewLLD |
| 177 | AtomLLD | 175 | AtomLLD |
| 176 | WebAssembly | ||
| 178 | windows_support | 177 | windows_support |
| 179 | ReleaseNotes | 178 | ReleaseNotes |
deps/lld/docs/sphinx_intro.rst+8-28| ... | @@ -57,41 +57,21 @@ to install it using: | ... | @@ -57,41 +57,21 @@ to install it using: |
| 57 | Building the documentation | 57 | Building the documentation |
| 58 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 58 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 59 | 59 | ||
| 60 | In order to build the documentation, all you should need to do is change to the | 60 | In order to build the documentation need to add ``-DLLVM_ENABLE_SPHINX=ON`` to |
| 61 | ``docs`` directory and invoke make as follows:: | 61 | your ``cmake`` command. Once you do this you can build the docs using |
| 62 | 62 | ``docs-lld-html`` build (``ninja`` or ``make``) target. | |
| 63 | $ cd path/to/project/docs | ||
| 64 | $ make html | ||
| 65 | |||
| 66 | Note that on Windows there is a ``make.bat`` command in the docs directory which | ||
| 67 | supplies the same interface as the ``Makefile``. | ||
| 68 | |||
| 69 | That command will invoke ``sphinx-build`` with the appropriate options for the | ||
| 70 | project, and generate the HTML documentation in a ``_build`` subdirectory. You | ||
| 71 | can browse it starting from the index page by visiting | ||
| 72 | ``_build/html/index.html``. | ||
| 73 | |||
| 74 | Sphinx supports a wide variety of generation formats (including LaTeX, man | ||
| 75 | pages, and plain text). The ``Makefile`` includes a number of convenience | ||
| 76 | targets for invoking ``sphinx-build`` appropriately, the common ones are: | ||
| 77 | |||
| 78 | make html | ||
| 79 | Generate the HTML output. | ||
| 80 | |||
| 81 | make latexpdf | ||
| 82 | Generate LaTeX documentation and convert to a PDF. | ||
| 83 | |||
| 84 | make man | ||
| 85 | Generate man pages. | ||
| 86 | 63 | ||
| 64 | That build target will invoke ``sphinx-build`` with the appropriate options for | ||
| 65 | the project, and generate the HTML documentation in a ``tools/lld/docs/html`` | ||
| 66 | subdirectory. | ||
| 87 | 67 | ||
| 88 | .. _writing_documentation: | 68 | .. _writing_documentation: |
| 89 | 69 | ||
| 90 | Writing documentation | 70 | Writing documentation |
| 91 | ~~~~~~~~~~~~~~~~~~~~~ | 71 | ~~~~~~~~~~~~~~~~~~~~~ |
| 92 | 72 | ||
| 93 | The documentation itself is written in the reStructuredText (ReST) format, and Sphinx | 73 | The documentation itself is written in the reStructuredText (ReST) format, and |
| 94 | defines additional tags to support features like cross-referencing. | 74 | Sphinx defines additional tags to support features like cross-referencing. |
| 95 | 75 | ||
| 96 | The ReST format itself is organized around documents mostly being readable | 76 | The ReST format itself is organized around documents mostly being readable |
| 97 | plaintext documents. You should generally be able to write new documentation | 77 | plaintext documents. You should generally be able to write new documentation |
deps/lld/include/lld/Common/Args.h created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | //===- Args.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_ARGS_H | ||
| 11 | #define LLD_ARGS_H | ||
| 12 | |||
| 13 | #include "lld/Common/LLVM.h" | ||
| 14 | #include "llvm/Support/MemoryBuffer.h" | ||
| 15 | #include <vector> | ||
| 16 | |||
| 17 | namespace llvm { | ||
| 18 | namespace opt { | ||
| 19 | class InputArgList; | ||
| 20 | } | ||
| 21 | } // namespace llvm | ||
| 22 | |||
| 23 | namespace lld { | ||
| 24 | namespace args { | ||
| 25 | int getInteger(llvm::opt::InputArgList &Args, unsigned Key, int Default); | ||
| 26 | std::vector<StringRef> getStrings(llvm::opt::InputArgList &Args, int Id); | ||
| 27 | |||
| 28 | uint64_t getZOptionValue(llvm::opt::InputArgList &Args, int Id, StringRef Key, | ||
| 29 | uint64_t Default); | ||
| 30 | |||
| 31 | std::vector<StringRef> getLines(MemoryBufferRef MB); | ||
| 32 | } // namespace args | ||
| 33 | } // namespace lld | ||
| 34 | |||
| 35 | #endif | ||
deps/lld/include/lld/Common/Driver.h created+43| ... | @@ -0,0 +1,43 @@ | ||
| 1 | //===- lld/Common/Driver.h - Linker Driver Emulator -----------------------===// | ||
| 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_COMMON_DRIVER_H | ||
| 11 | #define LLD_COMMON_DRIVER_H | ||
| 12 | |||
| 13 | #include "llvm/ADT/ArrayRef.h" | ||
| 14 | #include "llvm/Support/raw_ostream.h" | ||
| 15 | |||
| 16 | namespace lld { | ||
| 17 | namespace coff { | ||
| 18 | bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly, | ||
| 19 | llvm::raw_ostream &Diag = llvm::errs()); | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace mingw { | ||
| 23 | bool link(llvm::ArrayRef<const char *> Args, | ||
| 24 | llvm::raw_ostream &Diag = llvm::errs()); | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace elf { | ||
| 28 | bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly, | ||
| 29 | llvm::raw_ostream &Diag = llvm::errs()); | ||
| 30 | } | ||
| 31 | |||
| 32 | namespace mach_o { | ||
| 33 | bool link(llvm::ArrayRef<const char *> Args, | ||
| 34 | llvm::raw_ostream &Diag = llvm::errs()); | ||
| 35 | } | ||
| 36 | |||
| 37 | namespace wasm { | ||
| 38 | bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly, | ||
| 39 | llvm::raw_ostream &Diag = llvm::errs()); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | #endif | ||
deps/lld/include/lld/Common/ErrorHandler.h created+112| ... | @@ -0,0 +1,112 @@ | ||
| 1 | //===- ErrorHandler.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 | // In LLD, we have three levels of errors: fatal, error or warn. | ||
| 11 | // | ||
| 12 | // Fatal makes the program exit immediately with an error message. | ||
| 13 | // You shouldn't use it except for reporting a corrupted input file. | ||
| 14 | // | ||
| 15 | // Error prints out an error message and increment a global variable | ||
| 16 | // ErrorCount to record the fact that we met an error condition. It does | ||
| 17 | // not exit, so it is safe for a lld-as-a-library use case. It is generally | ||
| 18 | // useful because it can report more than one error in a single run. | ||
| 19 | // | ||
| 20 | // Warn doesn't do anything but printing out a given message. | ||
| 21 | // | ||
| 22 | // It is not recommended to use llvm::outs() or llvm::errs() directly | ||
| 23 | // in LLD because they are not thread-safe. The functions declared in | ||
| 24 | // this file are mutually excluded, so you want to use them instead. | ||
| 25 | // | ||
| 26 | //===----------------------------------------------------------------------===// | ||
| 27 | |||
| 28 | #ifndef LLD_COMMON_ERRORHANDLER_H | ||
| 29 | #define LLD_COMMON_ERRORHANDLER_H | ||
| 30 | |||
| 31 | #include "lld/Common/LLVM.h" | ||
| 32 | |||
| 33 | #include "llvm/ADT/STLExtras.h" | ||
| 34 | #include "llvm/Support/Error.h" | ||
| 35 | #include "llvm/Support/FileOutputBuffer.h" | ||
| 36 | |||
| 37 | namespace lld { | ||
| 38 | |||
| 39 | class ErrorHandler { | ||
| 40 | public: | ||
| 41 | uint64_t ErrorCount = 0; | ||
| 42 | uint64_t ErrorLimit = 20; | ||
| 43 | StringRef ErrorLimitExceededMsg = "too many errors emitted, stopping now"; | ||
| 44 | StringRef LogName = "lld"; | ||
| 45 | llvm::raw_ostream *ErrorOS = &llvm::errs(); | ||
| 46 | bool ColorDiagnostics = llvm::errs().has_colors(); | ||
| 47 | bool ExitEarly = true; | ||
| 48 | bool FatalWarnings = false; | ||
| 49 | bool Verbose = false; | ||
| 50 | |||
| 51 | void error(const Twine &Msg); | ||
| 52 | LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); | ||
| 53 | void log(const Twine &Msg); | ||
| 54 | void message(const Twine &Msg); | ||
| 55 | void warn(const Twine &Msg); | ||
| 56 | |||
| 57 | std::unique_ptr<llvm::FileOutputBuffer> OutputBuffer; | ||
| 58 | |||
| 59 | private: | ||
| 60 | void print(StringRef S, raw_ostream::Colors C); | ||
| 61 | }; | ||
| 62 | |||
| 63 | /// Returns the default error handler. | ||
| 64 | ErrorHandler &errorHandler(); | ||
| 65 | |||
| 66 | inline void error(const Twine &Msg) { errorHandler().error(Msg); } | ||
| 67 | inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg) { | ||
| 68 | errorHandler().fatal(Msg); | ||
| 69 | } | ||
| 70 | inline void log(const Twine &Msg) { errorHandler().log(Msg); } | ||
| 71 | inline void message(const Twine &Msg) { errorHandler().message(Msg); } | ||
| 72 | inline void warn(const Twine &Msg) { errorHandler().warn(Msg); } | ||
| 73 | inline uint64_t errorCount() { return errorHandler().ErrorCount; } | ||
| 74 | |||
| 75 | LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); | ||
| 76 | |||
| 77 | // check functions are convenient functions to strip errors | ||
| 78 | // from error-or-value objects. | ||
| 79 | template <class T> T check(ErrorOr<T> E) { | ||
| 80 | if (auto EC = E.getError()) | ||
| 81 | fatal(EC.message()); | ||
| 82 | return std::move(*E); | ||
| 83 | } | ||
| 84 | |||
| 85 | template <class T> T check(Expected<T> E) { | ||
| 86 | if (!E) | ||
| 87 | fatal(llvm::toString(E.takeError())); | ||
| 88 | return std::move(*E); | ||
| 89 | } | ||
| 90 | |||
| 91 | template <class T> | ||
| 92 | T check2(ErrorOr<T> E, llvm::function_ref<std::string()> Prefix) { | ||
| 93 | if (auto EC = E.getError()) | ||
| 94 | fatal(Prefix() + ": " + EC.message()); | ||
| 95 | return std::move(*E); | ||
| 96 | } | ||
| 97 | |||
| 98 | template <class T> | ||
| 99 | T check2(Expected<T> E, llvm::function_ref<std::string()> Prefix) { | ||
| 100 | if (!E) | ||
| 101 | fatal(Prefix() + ": " + toString(E.takeError())); | ||
| 102 | return std::move(*E); | ||
| 103 | } | ||
| 104 | |||
| 105 | inline std::string toString(const Twine &S) { return S.str(); } | ||
| 106 | |||
| 107 | // To evaluate the second argument lazily, we use C macro. | ||
| 108 | #define CHECK(E, S) check2(E, [&] { return toString(S); }) | ||
| 109 | |||
| 110 | } // namespace lld | ||
| 111 | |||
| 112 | #endif | ||
deps/lld/include/lld/Common/LLVM.h created+83| ... | @@ -0,0 +1,83 @@ | ||
| 1 | //===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===// | ||
| 2 | // | ||
| 3 | // The LLVM Compiler Infrastructure | ||
| 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 forward declares and imports various common LLVM datatypes that | ||
| 11 | // lld wants to use unqualified. | ||
| 12 | // | ||
| 13 | //===----------------------------------------------------------------------===// | ||
| 14 | |||
| 15 | #ifndef LLD_COMMON_LLVM_H | ||
| 16 | #define LLD_COMMON_LLVM_H | ||
| 17 | |||
| 18 | // This should be the only #include, force #includes of all the others on | ||
| 19 | // clients. | ||
| 20 | #include "llvm/ADT/Hashing.h" | ||
| 21 | #include "llvm/Support/Casting.h" | ||
| 22 | #include <utility> | ||
| 23 | |||
| 24 | namespace llvm { | ||
| 25 | // ADT's. | ||
| 26 | class Error; | ||
| 27 | class StringRef; | ||
| 28 | class Twine; | ||
| 29 | class MemoryBuffer; | ||
| 30 | class MemoryBufferRef; | ||
| 31 | template<typename T> class ArrayRef; | ||
| 32 | template<unsigned InternalLen> class SmallString; | ||
| 33 | template<typename T, unsigned N> class SmallVector; | ||
| 34 | template<typename T> class SmallVectorImpl; | ||
| 35 | |||
| 36 | template<typename T> | ||
| 37 | struct SaveAndRestore; | ||
| 38 | |||
| 39 | template<typename T> | ||
| 40 | class ErrorOr; | ||
| 41 | |||
| 42 | template<typename T> | ||
| 43 | class Expected; | ||
| 44 | |||
| 45 | class raw_ostream; | ||
| 46 | // TODO: DenseMap, ... | ||
| 47 | } | ||
| 48 | |||
| 49 | namespace lld { | ||
| 50 | // Casting operators. | ||
| 51 | using llvm::isa; | ||
| 52 | using llvm::cast; | ||
| 53 | using llvm::dyn_cast; | ||
| 54 | using llvm::dyn_cast_or_null; | ||
| 55 | using llvm::cast_or_null; | ||
| 56 | |||
| 57 | // ADT's. | ||
| 58 | using llvm::Error; | ||
| 59 | using llvm::StringRef; | ||
| 60 | using llvm::Twine; | ||
| 61 | using llvm::MemoryBuffer; | ||
| 62 | using llvm::MemoryBufferRef; | ||
| 63 | using llvm::ArrayRef; | ||
| 64 | using llvm::SmallString; | ||
| 65 | using llvm::SmallVector; | ||
| 66 | using llvm::SmallVectorImpl; | ||
| 67 | using llvm::SaveAndRestore; | ||
| 68 | using llvm::ErrorOr; | ||
| 69 | using llvm::Expected; | ||
| 70 | |||
| 71 | using llvm::raw_ostream; | ||
| 72 | } // end namespace lld. | ||
| 73 | |||
| 74 | namespace std { | ||
| 75 | template <> struct hash<llvm::StringRef> { | ||
| 76 | public: | ||
| 77 | size_t operator()(const llvm::StringRef &s) const { | ||
| 78 | return llvm::hash_value(s); | ||
| 79 | } | ||
| 80 | }; | ||
| 81 | } | ||
| 82 | |||
| 83 | #endif | ||
deps/lld/include/lld/Common/Memory.h created+60| ... | @@ -0,0 +1,60 @@ | ||
| 1 | //===- Memory.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 | // This file defines arena allocators. | ||
| 11 | // | ||
| 12 | // Almost all large objects, such as files, sections or symbols, are | ||
| 13 | // used for the entire lifetime of the linker once they are created. | ||
| 14 | // This usage characteristic makes arena allocator an attractive choice | ||
| 15 | // where the entire linker is one arena. With an arena, newly created | ||
| 16 | // objects belong to the arena and freed all at once when everything is done. | ||
| 17 | // Arena allocators are efficient and easy to understand. | ||
| 18 | // Most objects are allocated using the arena allocators defined by this file. | ||
| 19 | // | ||
| 20 | //===----------------------------------------------------------------------===// | ||
| 21 | |||
| 22 | #ifndef LLD_COMMON_MEMORY_H | ||
| 23 | #define LLD_COMMON_MEMORY_H | ||
| 24 | |||
| 25 | #include "llvm/Support/Allocator.h" | ||
| 26 | #include "llvm/Support/StringSaver.h" | ||
| 27 | #include <vector> | ||
| 28 | |||
| 29 | namespace lld { | ||
| 30 | |||
| 31 | // Use this arena if your object doesn't have a destructor. | ||
| 32 | extern llvm::BumpPtrAllocator BAlloc; | ||
| 33 | extern llvm::StringSaver Saver; | ||
| 34 | |||
| 35 | void freeArena(); | ||
| 36 | |||
| 37 | // These two classes are hack to keep track of all | ||
| 38 | // SpecificBumpPtrAllocator instances. | ||
| 39 | struct SpecificAllocBase { | ||
| 40 | SpecificAllocBase() { Instances.push_back(this); } | ||
| 41 | virtual ~SpecificAllocBase() = default; | ||
| 42 | virtual void reset() = 0; | ||
| 43 | static std::vector<SpecificAllocBase *> Instances; | ||
| 44 | }; | ||
| 45 | |||
| 46 | template <class T> struct SpecificAlloc : public SpecificAllocBase { | ||
| 47 | void reset() override { Alloc.DestroyAll(); } | ||
| 48 | llvm::SpecificBumpPtrAllocator<T> Alloc; | ||
| 49 | }; | ||
| 50 | |||
| 51 | // Use this arena if your object has a destructor. | ||
| 52 | // Your destructor will be invoked from freeArena(). | ||
| 53 | template <typename T, typename... U> T *make(U &&... Args) { | ||
| 54 | static SpecificAlloc<T> Alloc; | ||
| 55 | return new (Alloc.Alloc.Allocate()) T(std::forward<U>(Args)...); | ||
| 56 | } | ||
| 57 | |||
| 58 | } // namespace lld | ||
| 59 | |||
| 60 | #endif | ||
deps/lld/include/lld/Common/Reproduce.h created+39| ... | @@ -0,0 +1,39 @@ | ||
| 1 | //===- Reproduce.h - Utilities for creating reproducers ---------*- 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_COMMON_REPRODUCE_H | ||
| 11 | #define LLD_COMMON_REPRODUCE_H | ||
| 12 | |||
| 13 | #include "lld/Common/LLVM.h" | ||
| 14 | #include "llvm/ADT/StringRef.h" | ||
| 15 | #include "llvm/Support/Error.h" | ||
| 16 | |||
| 17 | namespace llvm { | ||
| 18 | namespace opt { class Arg; } | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace lld { | ||
| 22 | |||
| 23 | // Makes a given pathname an absolute path first, and then remove | ||
| 24 | // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", | ||
| 25 | // assuming that the current directory is "/home/john/bar". | ||
| 26 | std::string relativeToRoot(StringRef Path); | ||
| 27 | |||
| 28 | // Quote a given string if it contains a space character. | ||
| 29 | std::string quote(StringRef S); | ||
| 30 | |||
| 31 | // Rewrite the given path if a file exists with that pathname, otherwise | ||
| 32 | // returns the original path. | ||
| 33 | std::string rewritePath(StringRef S); | ||
| 34 | |||
| 35 | // Returns the string form of the given argument. | ||
| 36 | std::string toString(const llvm::opt::Arg &Arg); | ||
| 37 | } | ||
| 38 | |||
| 39 | #endif | ||
deps/lld/include/lld/Common/Strings.h created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | //===- Strings.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_STRINGS_H | ||
| 11 | #define LLD_STRINGS_H | ||
| 12 | |||
| 13 | #include "llvm/ADT/Optional.h" | ||
| 14 | #include "llvm/ADT/StringRef.h" | ||
| 15 | #include <string> | ||
| 16 | |||
| 17 | namespace lld { | ||
| 18 | // Returns a demangled C++ symbol name. If Name is not a mangled | ||
| 19 | // name, it returns Optional::None. | ||
| 20 | llvm::Optional<std::string> demangleItanium(llvm::StringRef Name); | ||
| 21 | } | ||
| 22 | |||
| 23 | #endif | ||
deps/lld/include/lld/Common/TargetOptionsCommandFlags.h created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | //===-- TargetOptionsCommandFlags.h ----------------------------*- C++ -*-===// | ||
| 2 | // | ||
| 3 | // The LLVM Compiler Infrastructure | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | // | ||
| 10 | // Helper to create TargetOptions from command line flags. | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #include "llvm/ADT/Optional.h" | ||
| 15 | #include "llvm/Support/CodeGen.h" | ||
| 16 | #include "llvm/Target/TargetOptions.h" | ||
| 17 | |||
| 18 | namespace lld { | ||
| 19 | llvm::TargetOptions InitTargetOptionsFromCodeGenFlags(); | ||
| 20 | llvm::Optional<llvm::CodeModel::Model> GetCodeModelFromCMModel(); | ||
| 21 | } | ||
deps/lld/include/lld/Common/Threads.h created+86| ... | @@ -0,0 +1,86 @@ | ||
| 1 | //===- Threads.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 | // LLD supports threads to distribute workloads to multiple cores. Using | ||
| 11 | // multicore is most effective when more than one core are idle. At the | ||
| 12 | // last step of a build, it is often the case that a linker is the only | ||
| 13 | // active process on a computer. So, we are naturally interested in using | ||
| 14 | // threads wisely to reduce latency to deliver results to users. | ||
| 15 | // | ||
| 16 | // That said, we don't want to do "too clever" things using threads. | ||
| 17 | // Complex multi-threaded algorithms are sometimes extremely hard to | ||
| 18 | // reason about and can easily mess up the entire design. | ||
| 19 | // | ||
| 20 | // Fortunately, when a linker links large programs (when the link time is | ||
| 21 | // most critical), it spends most of the time to work on massive number of | ||
| 22 | // small pieces of data of the same kind, and there are opportunities for | ||
| 23 | // large parallelism there. Here are examples: | ||
| 24 | // | ||
| 25 | // - We have hundreds of thousands of input sections that need to be | ||
| 26 | // copied to a result file at the last step of link. Once we fix a file | ||
| 27 | // layout, each section can be copied to its destination and its | ||
| 28 | // relocations can be applied independently. | ||
| 29 | // | ||
| 30 | // - We have tens of millions of small strings when constructing a | ||
| 31 | // mergeable string section. | ||
| 32 | // | ||
| 33 | // For the cases such as the former, we can just use parallelForEach | ||
| 34 | // instead of std::for_each (or a plain for loop). Because tasks are | ||
| 35 | // completely independent from each other, we can run them in parallel | ||
| 36 | // without any coordination between them. That's very easy to understand | ||
| 37 | // and reason about. | ||
| 38 | // | ||
| 39 | // For the cases such as the latter, we can use parallel algorithms to | ||
| 40 | // deal with massive data. We have to write code for a tailored algorithm | ||
| 41 | // for each problem, but the complexity of multi-threading is isolated in | ||
| 42 | // a single pass and doesn't affect the linker's overall design. | ||
| 43 | // | ||
| 44 | // The above approach seems to be working fairly well. As an example, when | ||
| 45 | // linking Chromium (output size 1.6 GB), using 4 cores reduces latency to | ||
| 46 | // 75% compared to single core (from 12.66 seconds to 9.55 seconds) on my | ||
| 47 | // Ivy Bridge Xeon 2.8 GHz machine. Using 40 cores reduces it to 63% (from | ||
| 48 | // 12.66 seconds to 7.95 seconds). Because of the Amdahl's law, the | ||
| 49 | // speedup is not linear, but as you add more cores, it gets faster. | ||
| 50 | // | ||
| 51 | // On a final note, if you are trying to optimize, keep the axiom "don't | ||
| 52 | // guess, measure!" in mind. Some important passes of the linker are not | ||
| 53 | // that slow. For example, resolving all symbols is not a very heavy pass, | ||
| 54 | // although it would be very hard to parallelize it. You want to first | ||
| 55 | // identify a slow pass and then optimize it. | ||
| 56 | // | ||
| 57 | //===----------------------------------------------------------------------===// | ||
| 58 | |||
| 59 | #ifndef LLD_COMMON_THREADS_H | ||
| 60 | #define LLD_COMMON_THREADS_H | ||
| 61 | |||
| 62 | #include "llvm/Support/Parallel.h" | ||
| 63 | #include <functional> | ||
| 64 | |||
| 65 | namespace lld { | ||
| 66 | |||
| 67 | extern bool ThreadsEnabled; | ||
| 68 | |||
| 69 | template <typename R, class FuncTy> void parallelForEach(R &&Range, FuncTy Fn) { | ||
| 70 | if (ThreadsEnabled) | ||
| 71 | for_each(llvm::parallel::par, std::begin(Range), std::end(Range), Fn); | ||
| 72 | else | ||
| 73 | for_each(llvm::parallel::seq, std::begin(Range), std::end(Range), Fn); | ||
| 74 | } | ||
| 75 | |||
| 76 | inline void parallelForEachN(size_t Begin, size_t End, | ||
| 77 | std::function<void(size_t)> Fn) { | ||
| 78 | if (ThreadsEnabled) | ||
| 79 | for_each_n(llvm::parallel::par, Begin, End, Fn); | ||
| 80 | else | ||
| 81 | for_each_n(llvm::parallel::seq, Begin, End, Fn); | ||
| 82 | } | ||
| 83 | |||
| 84 | } // namespace lld | ||
| 85 | |||
| 86 | #endif | ||
deps/lld/include/lld/Common/Version.h created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | //===- lld/Common/Version.h - LLD Version Number ----------------*- C++ -*-===// | ||
| 2 | // | ||
| 3 | // The LLVM Compiler Infrastructure | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | // | ||
| 10 | // Defines a version-related utility function. | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #ifndef LLD_VERSION_H | ||
| 15 | #define LLD_VERSION_H | ||
| 16 | |||
| 17 | #include "lld/Common/Version.inc" | ||
| 18 | #include "llvm/ADT/StringRef.h" | ||
| 19 | |||
| 20 | namespace lld { | ||
| 21 | /// \brief Retrieves a string representing the complete lld version. | ||
| 22 | std::string getLLDVersion(); | ||
| 23 | } | ||
| 24 | |||
| 25 | #endif // LLD_VERSION_H | ||
deps/lld/include/lld/Common/Version.inc.in created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | #define LLD_VERSION @LLD_VERSION@ | ||
| 2 | #define LLD_VERSION_STRING "@LLD_VERSION@" | ||
| 3 | #define LLD_VERSION_MAJOR @LLD_VERSION_MAJOR@ | ||
| 4 | #define LLD_VERSION_MINOR @LLD_VERSION_MINOR@ | ||
| 5 | #define LLD_REVISION_STRING "@LLD_REVISION@" | ||
| 6 | #define LLD_REPOSITORY_STRING "@LLD_REPOSITORY@" | ||
deps/lld/include/lld/Config/Version.h deleted-25| ... | @@ -1,25 +0,0 @@ | ||
| 1 | //===- lld/Config/Version.h - LLD Version Number ----------------*- C++ -*-===// | ||
| 2 | // | ||
| 3 | // The LLVM Compiler Infrastructure | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | // | ||
| 10 | // Defines a version-related utility function. | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #ifndef LLD_VERSION_H | ||
| 15 | #define LLD_VERSION_H | ||
| 16 | |||
| 17 | #include "lld/Config/Version.inc" | ||
| 18 | #include "llvm/ADT/StringRef.h" | ||
| 19 | |||
| 20 | namespace lld { | ||
| 21 | /// \brief Retrieves a string representing the complete lld version. | ||
| 22 | std::string getLLDVersion(); | ||
| 23 | } | ||
| 24 | |||
| 25 | #endif // LLD_VERSION_H | ||
deps/lld/include/lld/Config/Version.inc.in deleted-6| ... | @@ -1,6 +0,0 @@ | ||
| 1 | #define LLD_VERSION @LLD_VERSION@ | ||
| 2 | #define LLD_VERSION_STRING "@LLD_VERSION@" | ||
| 3 | #define LLD_VERSION_MAJOR @LLD_VERSION_MAJOR@ | ||
| 4 | #define LLD_VERSION_MINOR @LLD_VERSION_MINOR@ | ||
| 5 | #define LLD_REVISION_STRING "@LLD_REVISION@" | ||
| 6 | #define LLD_REPOSITORY_STRING "@LLD_REPOSITORY@" | ||
deps/lld/include/lld/Core/Atom.h+1-1| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_CORE_ATOM_H | 10 | #ifndef LLD_CORE_ATOM_H |
| 11 | #define LLD_CORE_ATOM_H | 11 | #define LLD_CORE_ATOM_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "llvm/ADT/StringRef.h" | 14 | #include "llvm/ADT/StringRef.h" |
| 15 | 15 | ||
| 16 | namespace lld { | 16 | namespace lld { |
deps/lld/include/lld/Core/DefinedAtom.h+1-1| ... | @@ -10,9 +10,9 @@ | ... | @@ -10,9 +10,9 @@ |
| 10 | #ifndef LLD_CORE_DEFINED_ATOM_H | 10 | #ifndef LLD_CORE_DEFINED_ATOM_H |
| 11 | #define LLD_CORE_DEFINED_ATOM_H | 11 | #define LLD_CORE_DEFINED_ATOM_H |
| 12 | 12 | ||
| 13 | #include "lld/Common/LLVM.h" | ||
| 13 | #include "lld/Core/Atom.h" | 14 | #include "lld/Core/Atom.h" |
| 14 | #include "lld/Core/Reference.h" | 15 | #include "lld/Core/Reference.h" |
| 15 | #include "lld/Core/LLVM.h" | ||
| 16 | #include "llvm/Support/ErrorHandling.h" | 16 | #include "llvm/Support/ErrorHandling.h" |
| 17 | 17 | ||
| 18 | namespace lld { | 18 | namespace lld { |
deps/lld/include/lld/Core/Error.h+1-1| ... | @@ -14,7 +14,7 @@ | ... | @@ -14,7 +14,7 @@ |
| 14 | #ifndef LLD_CORE_ERROR_H | 14 | #ifndef LLD_CORE_ERROR_H |
| 15 | #define LLD_CORE_ERROR_H | 15 | #define LLD_CORE_ERROR_H |
| 16 | 16 | ||
| 17 | #include "lld/Core/LLVM.h" | 17 | #include "lld/Common/LLVM.h" |
| 18 | #include "llvm/ADT/Twine.h" | 18 | #include "llvm/ADT/Twine.h" |
| 19 | #include "llvm/Support/Error.h" | 19 | #include "llvm/Support/Error.h" |
| 20 | #include <system_error> | 20 | #include <system_error> |
deps/lld/include/lld/Core/LLVM.h deleted-83| ... | @@ -1,83 +0,0 @@ | ||
| 1 | //===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===// | ||
| 2 | // | ||
| 3 | // The LLVM Compiler Infrastructure | ||
| 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 forward declares and imports various common LLVM datatypes that | ||
| 11 | // lld wants to use unqualified. | ||
| 12 | // | ||
| 13 | //===----------------------------------------------------------------------===// | ||
| 14 | |||
| 15 | #ifndef LLD_CORE_LLVM_H | ||
| 16 | #define LLD_CORE_LLVM_H | ||
| 17 | |||
| 18 | // This should be the only #include, force #includes of all the others on | ||
| 19 | // clients. | ||
| 20 | #include "llvm/ADT/Hashing.h" | ||
| 21 | #include "llvm/Support/Casting.h" | ||
| 22 | #include <utility> | ||
| 23 | |||
| 24 | namespace llvm { | ||
| 25 | // ADT's. | ||
| 26 | class Error; | ||
| 27 | class StringRef; | ||
| 28 | class Twine; | ||
| 29 | class MemoryBuffer; | ||
| 30 | class MemoryBufferRef; | ||
| 31 | template<typename T> class ArrayRef; | ||
| 32 | template<unsigned InternalLen> class SmallString; | ||
| 33 | template<typename T, unsigned N> class SmallVector; | ||
| 34 | template<typename T> class SmallVectorImpl; | ||
| 35 | |||
| 36 | template<typename T> | ||
| 37 | struct SaveAndRestore; | ||
| 38 | |||
| 39 | template<typename T> | ||
| 40 | class ErrorOr; | ||
| 41 | |||
| 42 | template<typename T> | ||
| 43 | class Expected; | ||
| 44 | |||
| 45 | class raw_ostream; | ||
| 46 | // TODO: DenseMap, ... | ||
| 47 | } | ||
| 48 | |||
| 49 | namespace lld { | ||
| 50 | // Casting operators. | ||
| 51 | using llvm::isa; | ||
| 52 | using llvm::cast; | ||
| 53 | using llvm::dyn_cast; | ||
| 54 | using llvm::dyn_cast_or_null; | ||
| 55 | using llvm::cast_or_null; | ||
| 56 | |||
| 57 | // ADT's. | ||
| 58 | using llvm::Error; | ||
| 59 | using llvm::StringRef; | ||
| 60 | using llvm::Twine; | ||
| 61 | using llvm::MemoryBuffer; | ||
| 62 | using llvm::MemoryBufferRef; | ||
| 63 | using llvm::ArrayRef; | ||
| 64 | using llvm::SmallString; | ||
| 65 | using llvm::SmallVector; | ||
| 66 | using llvm::SmallVectorImpl; | ||
| 67 | using llvm::SaveAndRestore; | ||
| 68 | using llvm::ErrorOr; | ||
| 69 | using llvm::Expected; | ||
| 70 | |||
| 71 | using llvm::raw_ostream; | ||
| 72 | } // end namespace lld. | ||
| 73 | |||
| 74 | namespace std { | ||
| 75 | template <> struct hash<llvm::StringRef> { | ||
| 76 | public: | ||
| 77 | size_t operator()(const llvm::StringRef &s) const { | ||
| 78 | return llvm::hash_value(s); | ||
| 79 | } | ||
| 80 | }; | ||
| 81 | } | ||
| 82 | |||
| 83 | #endif | ||
deps/lld/include/lld/Core/LinkingContext.h+2-2| ... | @@ -62,7 +62,7 @@ public: | ... | @@ -62,7 +62,7 @@ public: |
| 62 | /// of DefinedAtoms that should be marked live (along with all Atoms they | 62 | /// of DefinedAtoms that should be marked live (along with all Atoms they |
| 63 | /// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can | 63 | /// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can |
| 64 | /// be kept live using this method. | 64 | /// be kept live using this method. |
| 65 | const std::vector<StringRef> &deadStripRoots() const { | 65 | ArrayRef<StringRef> deadStripRoots() const { |
| 66 | return _deadStripRoots; | 66 | return _deadStripRoots; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| ... | @@ -106,7 +106,7 @@ public: | ... | @@ -106,7 +106,7 @@ public: |
| 106 | /// options which are used to configure LLVM's command line settings. | 106 | /// options which are used to configure LLVM's command line settings. |
| 107 | /// For instance the -debug-only XXX option can be used to dynamically | 107 | /// For instance the -debug-only XXX option can be used to dynamically |
| 108 | /// trace different parts of LLVM and lld. | 108 | /// trace different parts of LLVM and lld. |
| 109 | const std::vector<const char *> &llvmOptions() const { return _llvmOptions; } | 109 | ArrayRef<const char *> llvmOptions() const { return _llvmOptions; } |
| 110 | 110 | ||
| 111 | /// \name Methods used by Drivers to configure TargetInfo | 111 | /// \name Methods used by Drivers to configure TargetInfo |
| 112 | /// @{ | 112 | /// @{ |
deps/lld/include/lld/Core/PassManager.h+1-1| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_CORE_PASS_MANAGER_H | 10 | #ifndef LLD_CORE_PASS_MANAGER_H |
| 11 | #define LLD_CORE_PASS_MANAGER_H | 11 | #define LLD_CORE_PASS_MANAGER_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "lld/Core/Pass.h" | 14 | #include "lld/Core/Pass.h" |
| 15 | #include "llvm/Support/Error.h" | 15 | #include "llvm/Support/Error.h" |
| 16 | #include <memory> | 16 | #include <memory> |
deps/lld/include/lld/Core/Reader.h+1-1| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_CORE_READER_H | 10 | #ifndef LLD_CORE_READER_H |
| 11 | #define LLD_CORE_READER_H | 11 | #define LLD_CORE_READER_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "lld/Core/Reference.h" | 14 | #include "lld/Core/Reference.h" |
| 15 | #include "llvm/ADT/StringRef.h" | 15 | #include "llvm/ADT/StringRef.h" |
| 16 | #include "llvm/BinaryFormat/Magic.h" | 16 | #include "llvm/BinaryFormat/Magic.h" |
deps/lld/include/lld/Core/Reproduce.h deleted-39| ... | @@ -1,39 +0,0 @@ | ||
| 1 | //===- Reproduce.h - Utilities for creating reproducers ---------*- 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_CORE_REPRODUCE_H | ||
| 11 | #define LLD_CORE_REPRODUCE_H | ||
| 12 | |||
| 13 | #include "lld/Core/LLVM.h" | ||
| 14 | #include "llvm/ADT/StringRef.h" | ||
| 15 | #include "llvm/Support/Error.h" | ||
| 16 | |||
| 17 | namespace llvm { | ||
| 18 | namespace opt { class Arg; } | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace lld { | ||
| 22 | |||
| 23 | // Makes a given pathname an absolute path first, and then remove | ||
| 24 | // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", | ||
| 25 | // assuming that the current directory is "/home/john/bar". | ||
| 26 | std::string relativeToRoot(StringRef Path); | ||
| 27 | |||
| 28 | // Quote a given string if it contains a space character. | ||
| 29 | std::string quote(StringRef S); | ||
| 30 | |||
| 31 | // Rewrite the given path if a file exists with that pathname, otherwise | ||
| 32 | // returns the original path. | ||
| 33 | std::string rewritePath(StringRef S); | ||
| 34 | |||
| 35 | // Returns the string form of the given argument. | ||
| 36 | std::string toString(llvm::opt::Arg *Arg); | ||
| 37 | } | ||
| 38 | |||
| 39 | #endif | ||
deps/lld/include/lld/Core/SymbolTable.h+1-1| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_CORE_SYMBOL_TABLE_H | 10 | #ifndef LLD_CORE_SYMBOL_TABLE_H |
| 11 | #define LLD_CORE_SYMBOL_TABLE_H | 11 | #define LLD_CORE_SYMBOL_TABLE_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "llvm/ADT/DenseSet.h" | 14 | #include "llvm/ADT/DenseSet.h" |
| 15 | #include "llvm/ADT/StringExtras.h" | 15 | #include "llvm/ADT/StringExtras.h" |
| 16 | #include <cstring> | 16 | #include <cstring> |
deps/lld/include/lld/Core/TargetOptionsCommandFlags.h deleted-20| ... | @@ -1,20 +0,0 @@ | ||
| 1 | //===-- TargetOptionsCommandFlags.h ----------------------------*- C++ -*-===// | ||
| 2 | // | ||
| 3 | // The LLVM Compiler Infrastructure | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | // | ||
| 10 | // Helper to create TargetOptions from command line flags. | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #include "llvm/Support/CodeGen.h" | ||
| 15 | #include "llvm/Target/TargetOptions.h" | ||
| 16 | |||
| 17 | namespace lld { | ||
| 18 | llvm::TargetOptions InitTargetOptionsFromCodeGenFlags(); | ||
| 19 | llvm::CodeModel::Model GetCodeModelFromCMModel(); | ||
| 20 | } | ||
deps/lld/include/lld/Core/Writer.h+1-1| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_CORE_WRITER_H | 10 | #ifndef LLD_CORE_WRITER_H |
| 11 | #define LLD_CORE_WRITER_H | 11 | #define LLD_CORE_WRITER_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include "llvm/Support/Error.h" | 14 | #include "llvm/Support/Error.h" |
| 15 | #include <memory> | 15 | #include <memory> |
| 16 | #include <vector> | 16 | #include <vector> |
deps/lld/include/lld/Driver/Driver.h deleted-33| ... | @@ -1,33 +0,0 @@ | ||
| 1 | //===- lld/Driver/Driver.h - Linker Driver Emulator -----------------------===// | ||
| 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_DRIVER_DRIVER_H | ||
| 11 | #define LLD_DRIVER_DRIVER_H | ||
| 12 | |||
| 13 | #include "llvm/ADT/ArrayRef.h" | ||
| 14 | #include "llvm/Support/raw_ostream.h" | ||
| 15 | |||
| 16 | namespace lld { | ||
| 17 | namespace coff { | ||
| 18 | bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly, | ||
| 19 | llvm::raw_ostream &Diag = llvm::errs()); | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace elf { | ||
| 23 | bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly, | ||
| 24 | llvm::raw_ostream &Diag = llvm::errs()); | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace mach_o { | ||
| 28 | bool link(llvm::ArrayRef<const char *> Args, | ||
| 29 | llvm::raw_ostream &Diag = llvm::errs()); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | #endif | ||
deps/lld/include/lld/ReaderWriter/YamlContext.h+2-1| ... | @@ -10,7 +10,7 @@ | ... | @@ -10,7 +10,7 @@ |
| 10 | #ifndef LLD_READER_WRITER_YAML_CONTEXT_H | 10 | #ifndef LLD_READER_WRITER_YAML_CONTEXT_H |
| 11 | #define LLD_READER_WRITER_YAML_CONTEXT_H | 11 | #define LLD_READER_WRITER_YAML_CONTEXT_H |
| 12 | 12 | ||
| 13 | #include "lld/Core/LLVM.h" | 13 | #include "lld/Common/LLVM.h" |
| 14 | #include <functional> | 14 | #include <functional> |
| 15 | #include <memory> | 15 | #include <memory> |
| 16 | #include <vector> | 16 | #include <vector> |
| ... | @@ -18,6 +18,7 @@ | ... | @@ -18,6 +18,7 @@ |
| 18 | namespace lld { | 18 | namespace lld { |
| 19 | class File; | 19 | class File; |
| 20 | class LinkingContext; | 20 | class LinkingContext; |
| 21 | class Registry; | ||
| 21 | namespace mach_o { | 22 | namespace mach_o { |
| 22 | namespace normalized { | 23 | namespace normalized { |
| 23 | struct NormalizedFile; | 24 | struct NormalizedFile; |
deps/lld/lib/CMakeLists.txt-1| ... | @@ -1,4 +1,3 @@ | ... | @@ -1,4 +1,3 @@ |
| 1 | add_subdirectory(Config) | ||
| 2 | add_subdirectory(Core) | 1 | add_subdirectory(Core) |
| 3 | add_subdirectory(Driver) | 2 | add_subdirectory(Driver) |
| 4 | add_subdirectory(ReaderWriter) | 3 | add_subdirectory(ReaderWriter) |
deps/lld/lib/Config/CMakeLists.txt deleted-9| ... | @@ -1,9 +0,0 @@ | ||
| 1 | add_lld_library(lldConfig | ||
| 2 | Version.cpp | ||
| 3 | |||
| 4 | ADDITIONAL_HEADER_DIRS | ||
| 5 | ${LLD_INCLUDE_DIR}/lld/Config | ||
| 6 | |||
| 7 | LINK_COMPONENTS | ||
| 8 | Support | ||
| 9 | ) | ||
deps/lld/lib/Config/Version.cpp deleted-43| ... | @@ -1,43 +0,0 @@ | ||
| 1 | //===- lib/Config/Version.cpp - LLD Version Number ---------------*- C++-=====// | ||
| 2 | // | ||
| 3 | // The LLVM Compiler Infrastructure | ||
| 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 defines several version-related utility functions for LLD. | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #include "lld/Config/Version.h" | ||
| 15 | |||
| 16 | using namespace llvm; | ||
| 17 | |||
| 18 | // Returns an SVN repository path, which is usually "trunk". | ||
| 19 | static 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. | ||
| 29 | static 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 | } | ||
| 39 | |||
| 40 | // Returns a version string, e.g., "LLD 4.0 (lld/trunk 284614)". | ||
| 41 | std::string lld::getLLDVersion() { | ||
| 42 | return "LLD " + std::string(LLD_VERSION_STRING) + getRepository(); | ||
| 43 | } | ||
deps/lld/lib/Core/CMakeLists.txt-2| ... | @@ -8,10 +8,8 @@ add_lld_library(lldCore | ... | @@ -8,10 +8,8 @@ add_lld_library(lldCore |
| 8 | File.cpp | 8 | File.cpp |
| 9 | LinkingContext.cpp | 9 | LinkingContext.cpp |
| 10 | Reader.cpp | 10 | Reader.cpp |
| 11 | Reproduce.cpp | ||
| 12 | Resolver.cpp | 11 | Resolver.cpp |
| 13 | SymbolTable.cpp | 12 | SymbolTable.cpp |
| 14 | TargetOptionsCommandFlags.cpp | ||
| 15 | Writer.cpp | 13 | Writer.cpp |
| 16 | 14 | ||
| 17 | ADDITIONAL_HEADER_DIRS | 15 | ADDITIONAL_HEADER_DIRS |
deps/lld/lib/Core/Reproduce.cpp deleted-66| ... | @@ -1,66 +0,0 @@ | ||
| 1 | //===- Reproduce.cpp - Utilities for creating reproducers -----------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "lld/Core/Reproduce.h" | ||
| 11 | #include "llvm/Option/Arg.h" | ||
| 12 | #include "llvm/Support/Error.h" | ||
| 13 | #include "llvm/Support/FileSystem.h" | ||
| 14 | #include "llvm/Support/Path.h" | ||
| 15 | |||
| 16 | using namespace lld; | ||
| 17 | using namespace llvm; | ||
| 18 | using namespace llvm::sys; | ||
| 19 | |||
| 20 | // Makes a given pathname an absolute path first, and then remove | ||
| 21 | // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", | ||
| 22 | // assuming that the current directory is "/home/john/bar". | ||
| 23 | // 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. | ||
| 25 | std::string lld::relativeToRoot(StringRef Path) { | ||
| 26 | SmallString<128> Abs = Path; | ||
| 27 | if (fs::make_absolute(Abs)) | ||
| 28 | return Path; | ||
| 29 | path::remove_dots(Abs, /*remove_dot_dot=*/true); | ||
| 30 | |||
| 31 | // 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 part | ||
| 33 | // of the result. | ||
| 34 | SmallString<128> Res; | ||
| 35 | StringRef Root = path::root_name(Abs); | ||
| 36 | if (Root.endswith(":")) | ||
| 37 | Res = Root.drop_back(); | ||
| 38 | else if (Root.startswith("//")) | ||
| 39 | Res = Root.substr(2); | ||
| 40 | |||
| 41 | path::append(Res, path::relative_path(Abs)); | ||
| 42 | return path::convert_to_slash(Res); | ||
| 43 | } | ||
| 44 | |||
| 45 | // Quote a given string if it contains a space character. | ||
| 46 | std::string lld::quote(StringRef S) { | ||
| 47 | if (S.find(' ') == StringRef::npos) | ||
| 48 | return S; | ||
| 49 | return ("\"" + S + "\"").str(); | ||
| 50 | } | ||
| 51 | |||
| 52 | std::string lld::rewritePath(StringRef S) { | ||
| 53 | if (fs::exists(S)) | ||
| 54 | return relativeToRoot(S); | ||
| 55 | return S; | ||
| 56 | } | ||
| 57 | |||
| 58 | std::string lld::toString(opt::Arg *Arg) { | ||
| 59 | std::string K = Arg->getSpelling(); | ||
| 60 | if (Arg->getNumValues() == 0) | ||
| 61 | return K; | ||
| 62 | std::string V = quote(Arg->getValue()); | ||
| 63 | if (Arg->getOption().getRenderStyle() == opt::Option::RenderJoinedStyle) | ||
| 64 | return K + V; | ||
| 65 | return K + " " + V; | ||
| 66 | } | ||
deps/lld/lib/Core/Resolver.cpp+3-3| ... | @@ -7,13 +7,13 @@ | ... | @@ -7,13 +7,13 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "lld/Core/Atom.h" | 10 | #include "lld/Core/Resolver.h" |
| 11 | #include "lld/Common/LLVM.h" | ||
| 11 | #include "lld/Core/ArchiveLibraryFile.h" | 12 | #include "lld/Core/ArchiveLibraryFile.h" |
| 13 | #include "lld/Core/Atom.h" | ||
| 12 | #include "lld/Core/File.h" | 14 | #include "lld/Core/File.h" |
| 13 | #include "lld/Core/Instrumentation.h" | 15 | #include "lld/Core/Instrumentation.h" |
| 14 | #include "lld/Core/LLVM.h" | ||
| 15 | #include "lld/Core/LinkingContext.h" | 16 | #include "lld/Core/LinkingContext.h" |
| 16 | #include "lld/Core/Resolver.h" | ||
| 17 | #include "lld/Core/SharedLibraryFile.h" | 17 | #include "lld/Core/SharedLibraryFile.h" |
| 18 | #include "lld/Core/SymbolTable.h" | 18 | #include "lld/Core/SymbolTable.h" |
| 19 | #include "lld/Core/UndefinedAtom.h" | 19 | #include "lld/Core/UndefinedAtom.h" |
deps/lld/lib/Core/SymbolTable.cpp+1-1| ... | @@ -8,11 +8,11 @@ | ... | @@ -8,11 +8,11 @@ |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "lld/Core/SymbolTable.h" | 10 | #include "lld/Core/SymbolTable.h" |
| 11 | #include "lld/Common/LLVM.h" | ||
| 11 | #include "lld/Core/AbsoluteAtom.h" | 12 | #include "lld/Core/AbsoluteAtom.h" |
| 12 | #include "lld/Core/Atom.h" | 13 | #include "lld/Core/Atom.h" |
| 13 | #include "lld/Core/DefinedAtom.h" | 14 | #include "lld/Core/DefinedAtom.h" |
| 14 | #include "lld/Core/File.h" | 15 | #include "lld/Core/File.h" |
| 15 | #include "lld/Core/LLVM.h" | ||
| 16 | #include "lld/Core/LinkingContext.h" | 16 | #include "lld/Core/LinkingContext.h" |
| 17 | #include "lld/Core/Resolver.h" | 17 | #include "lld/Core/Resolver.h" |
| 18 | #include "lld/Core/SharedLibraryAtom.h" | 18 | #include "lld/Core/SharedLibraryAtom.h" |
deps/lld/lib/Core/TargetOptionsCommandFlags.cpp deleted-32| ... | @@ -1,32 +0,0 @@ | ||
| 1 | //===-- TargetOptionsCommandFlags.cpp ---------------------------*- 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 | // This file exists as a place for global variables defined in LLVM's | ||
| 11 | // CodeGen/CommandFlags.h. By putting the resulting object file in | ||
| 12 | // an archive and linking with it, the definitions will automatically be | ||
| 13 | // included when needed and skipped when already present. | ||
| 14 | // | ||
| 15 | //===----------------------------------------------------------------------===// | ||
| 16 | |||
| 17 | #include "lld/Core/TargetOptionsCommandFlags.h" | ||
| 18 | |||
| 19 | #include "llvm/CodeGen/CommandFlags.h" | ||
| 20 | #include "llvm/Target/TargetOptions.h" | ||
| 21 | |||
| 22 | // Define an externally visible version of | ||
| 23 | // InitTargetOptionsFromCodeGenFlags, so that its functionality can be | ||
| 24 | // used without having to include llvm/CodeGen/CommandFlags.h, which | ||
| 25 | // would lead to multiple definitions of the command line flags. | ||
| 26 | llvm::TargetOptions lld::InitTargetOptionsFromCodeGenFlags() { | ||
| 27 | return ::InitTargetOptionsFromCodeGenFlags(); | ||
| 28 | } | ||
| 29 | |||
| 30 | llvm::CodeModel::Model lld::GetCodeModelFromCMModel() { | ||
| 31 | return CMModel; | ||
| 32 | } | ||
deps/lld/lib/Driver/CMakeLists.txt+1-3| ... | @@ -9,14 +9,12 @@ add_lld_library(lldDriver | ... | @@ -9,14 +9,12 @@ add_lld_library(lldDriver |
| 9 | ${LLD_INCLUDE_DIR}/lld/Driver | 9 | ${LLD_INCLUDE_DIR}/lld/Driver |
| 10 | 10 | ||
| 11 | LINK_COMPONENTS | 11 | LINK_COMPONENTS |
| 12 | Object | ||
| 13 | Option | 12 | Option |
| 14 | Support | 13 | Support |
| 15 | 14 | ||
| 16 | LINK_LIBS | 15 | LINK_LIBS |
| 17 | lldConfig | ||
| 18 | lldMachO | ||
| 19 | lldCore | 16 | lldCore |
| 17 | lldMachO | ||
| 20 | lldReaderWriter | 18 | lldReaderWriter |
| 21 | lldYAML | 19 | lldYAML |
| 22 | ) | 20 | ) |
deps/lld/lib/Driver/DarwinLdDriver.cpp+3-3| ... | @@ -13,11 +13,11 @@ | ... | @@ -13,11 +13,11 @@ |
| 13 | /// | 13 | /// |
| 14 | //===----------------------------------------------------------------------===// | 14 | //===----------------------------------------------------------------------===// |
| 15 | 15 | ||
| 16 | #include "lld/Common/LLVM.h" | ||
| 16 | #include "lld/Core/ArchiveLibraryFile.h" | 17 | #include "lld/Core/ArchiveLibraryFile.h" |
| 17 | #include "lld/Core/Error.h" | 18 | #include "lld/Core/Error.h" |
| 18 | #include "lld/Core/File.h" | 19 | #include "lld/Core/File.h" |
| 19 | #include "lld/Core/Instrumentation.h" | 20 | #include "lld/Core/Instrumentation.h" |
| 20 | #include "lld/Core/LLVM.h" | ||
| 21 | #include "lld/Core/LinkingContext.h" | 21 | #include "lld/Core/LinkingContext.h" |
| 22 | #include "lld/Core/Node.h" | 22 | #include "lld/Core/Node.h" |
| 23 | #include "lld/Core/PassManager.h" | 23 | #include "lld/Core/PassManager.h" |
| ... | @@ -74,7 +74,7 @@ enum { | ... | @@ -74,7 +74,7 @@ enum { |
| 74 | #undef PREFIX | 74 | #undef PREFIX |
| 75 | 75 | ||
| 76 | // Create table mapping all options defined in DarwinLdOptions.td | 76 | // Create table mapping all options defined in DarwinLdOptions.td |
| 77 | static const llvm::opt::OptTable::Info infoTable[] = { | 77 | static const llvm::opt::OptTable::Info InfoTable[] = { |
| 78 | #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ | 78 | #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ |
| 79 | HELPTEXT, METAVAR, VALUES) \ | 79 | HELPTEXT, METAVAR, VALUES) \ |
| 80 | {PREFIX, NAME, HELPTEXT, \ | 80 | {PREFIX, NAME, HELPTEXT, \ |
| ... | @@ -88,7 +88,7 @@ static const llvm::opt::OptTable::Info infoTable[] = { | ... | @@ -88,7 +88,7 @@ static const llvm::opt::OptTable::Info infoTable[] = { |
| 88 | // Create OptTable class for parsing actual command line arguments | 88 | // Create OptTable class for parsing actual command line arguments |
| 89 | class DarwinLdOptTable : public llvm::opt::OptTable { | 89 | class DarwinLdOptTable : public llvm::opt::OptTable { |
| 90 | public: | 90 | public: |
| 91 | DarwinLdOptTable() : OptTable(infoTable) {} | 91 | DarwinLdOptTable() : OptTable(InfoTable) {} |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | static std::vector<std::unique_ptr<File>> | 94 | static std::vector<std::unique_ptr<File>> |
deps/lld/lib/ReaderWriter/CMakeLists.txt-1| ... | @@ -17,5 +17,4 @@ add_lld_library(lldReaderWriter | ... | @@ -17,5 +17,4 @@ add_lld_library(lldReaderWriter |
| 17 | 17 | ||
| 18 | LINK_LIBS | 18 | LINK_LIBS |
| 19 | lldCore | 19 | lldCore |
| 20 | lldYAML | ||
| 21 | ) | 20 | ) |
deps/lld/lib/ReaderWriter/FileArchive.cpp+1-1| ... | @@ -7,9 +7,9 @@ | ... | @@ -7,9 +7,9 @@ |
| 7 | // | 7 | // |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "lld/Common/LLVM.h" | ||
| 10 | #include "lld/Core/ArchiveLibraryFile.h" | 11 | #include "lld/Core/ArchiveLibraryFile.h" |
| 11 | #include "lld/Core/File.h" | 12 | #include "lld/Core/File.h" |
| 12 | #include "lld/Core/LLVM.h" | ||
| 13 | #include "lld/Core/Reader.h" | 13 | #include "lld/Core/Reader.h" |
| 14 | #include "llvm/ADT/STLExtras.h" | 14 | #include "llvm/ADT/STLExtras.h" |
| 15 | #include "llvm/ADT/StringRef.h" | 15 | #include "llvm/ADT/StringRef.h" |
deps/lld/lib/ReaderWriter/MachO/ArchHandler.h+1-1| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | #include "Atoms.h" | 13 | #include "Atoms.h" |
| 14 | #include "File.h" | 14 | #include "File.h" |
| 15 | #include "MachONormalizedFile.h" | 15 | #include "MachONormalizedFile.h" |
| 16 | #include "lld/Core/LLVM.h" | 16 | #include "lld/Common/LLVM.h" |
| 17 | #include "lld/Core/Error.h" | 17 | #include "lld/Core/Error.h" |
| 18 | #include "lld/Core/Reference.h" | 18 | #include "lld/Core/Reference.h" |
| 19 | #include "lld/Core/Simple.h" | 19 | #include "lld/Core/Simple.h" |
deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp+1| ... | @@ -621,6 +621,7 @@ void ArchHandler_x86_64::applyFixupFinal( | ... | @@ -621,6 +621,7 @@ void ArchHandler_x86_64::applyFixupFinal( |
| 621 | // Fall into llvm_unreachable(). | 621 | // Fall into llvm_unreachable(). |
| 622 | break; | 622 | break; |
| 623 | } | 623 | } |
| 624 | llvm_unreachable("invalid x86_64 Reference Kind"); | ||
| 624 | } | 625 | } |
| 625 | 626 | ||
| 626 | void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, | 627 | void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, |
deps/lld/lib/ReaderWriter/MachO/CMakeLists.txt+1-1| ... | @@ -21,9 +21,9 @@ add_lld_library(lldMachO | ... | @@ -21,9 +21,9 @@ add_lld_library(lldMachO |
| 21 | 21 | ||
| 22 | LINK_COMPONENTS | 22 | LINK_COMPONENTS |
| 23 | DebugInfoDWARF | 23 | DebugInfoDWARF |
| 24 | Demangle | ||
| 24 | Object | 25 | Object |
| 25 | Support | 26 | Support |
| 26 | Demangle | ||
| 27 | 27 | ||
| 28 | LINK_LIBS | 28 | LINK_LIBS |
| 29 | lldCore | 29 | lldCore |
deps/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp+1-1| ... | @@ -17,9 +17,9 @@ | ... | @@ -17,9 +17,9 @@ |
| 17 | #include "File.h" | 17 | #include "File.h" |
| 18 | #include "MachONormalizedFileBinaryUtils.h" | 18 | #include "MachONormalizedFileBinaryUtils.h" |
| 19 | #include "MachOPasses.h" | 19 | #include "MachOPasses.h" |
| 20 | #include "lld/Common/LLVM.h" | ||
| 20 | #include "lld/Core/DefinedAtom.h" | 21 | #include "lld/Core/DefinedAtom.h" |
| 21 | #include "lld/Core/File.h" | 22 | #include "lld/Core/File.h" |
| 22 | #include "lld/Core/LLVM.h" | ||
| 23 | #include "lld/Core/Reference.h" | 23 | #include "lld/Core/Reference.h" |
| 24 | #include "lld/Core/Simple.h" | 24 | #include "lld/Core/Simple.h" |
| 25 | #include "llvm/ADT/DenseMap.h" | 25 | #include "llvm/ADT/DenseMap.h" |
deps/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h+2| ... | @@ -10,7 +10,9 @@ | ... | @@ -10,7 +10,9 @@ |
| 10 | #ifndef LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H | 10 | #ifndef LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H |
| 11 | #define LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H | 11 | #define LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H |
| 12 | 12 | ||
| 13 | #include "Atoms.h" | ||
| 13 | #include "lld/Core/SharedLibraryFile.h" | 14 | #include "lld/Core/SharedLibraryFile.h" |
| 15 | #include "lld/ReaderWriter/MachOLinkingContext.h" | ||
| 14 | #include "llvm/Support/Debug.h" | 16 | #include "llvm/Support/Debug.h" |
| 15 | 17 | ||
| 16 | namespace lld { | 18 | namespace lld { |
deps/lld/lib/ReaderWriter/MachO/GOTPass.cpp+1-1| ... | @@ -35,9 +35,9 @@ | ... | @@ -35,9 +35,9 @@ |
| 35 | #include "ArchHandler.h" | 35 | #include "ArchHandler.h" |
| 36 | #include "File.h" | 36 | #include "File.h" |
| 37 | #include "MachOPasses.h" | 37 | #include "MachOPasses.h" |
| 38 | #include "lld/Common/LLVM.h" | ||
| 38 | #include "lld/Core/DefinedAtom.h" | 39 | #include "lld/Core/DefinedAtom.h" |
| 39 | #include "lld/Core/File.h" | 40 | #include "lld/Core/File.h" |
| 40 | #include "lld/Core/LLVM.h" | ||
| 41 | #include "lld/Core/Reference.h" | 41 | #include "lld/Core/Reference.h" |
| 42 | #include "lld/Core/Simple.h" | 42 | #include "lld/Core/Simple.h" |
| 43 | #include "llvm/ADT/DenseMap.h" | 43 | #include "llvm/ADT/DenseMap.h" |
deps/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp+1-1| ... | @@ -14,11 +14,11 @@ | ... | @@ -14,11 +14,11 @@ |
| 14 | #include "MachONormalizedFile.h" | 14 | #include "MachONormalizedFile.h" |
| 15 | #include "MachOPasses.h" | 15 | #include "MachOPasses.h" |
| 16 | #include "SectCreateFile.h" | 16 | #include "SectCreateFile.h" |
| 17 | #include "lld/Common/Driver.h" | ||
| 17 | #include "lld/Core/ArchiveLibraryFile.h" | 18 | #include "lld/Core/ArchiveLibraryFile.h" |
| 18 | #include "lld/Core/PassManager.h" | 19 | #include "lld/Core/PassManager.h" |
| 19 | #include "lld/Core/Reader.h" | 20 | #include "lld/Core/Reader.h" |
| 20 | #include "lld/Core/Writer.h" | 21 | #include "lld/Core/Writer.h" |
| 21 | #include "lld/Driver/Driver.h" | ||
| 22 | #include "llvm/ADT/STLExtras.h" | 22 | #include "llvm/ADT/STLExtras.h" |
| 23 | #include "llvm/ADT/StringExtras.h" | 23 | #include "llvm/ADT/StringExtras.h" |
| 24 | #include "llvm/ADT/Triple.h" | 24 | #include "llvm/ADT/Triple.h" |
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h+1-10| ... | @@ -43,8 +43,8 @@ | ... | @@ -43,8 +43,8 @@ |
| 43 | #define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H | 43 | #define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H |
| 44 | 44 | ||
| 45 | #include "DebugInfo.h" | 45 | #include "DebugInfo.h" |
| 46 | #include "lld/Common/LLVM.h" | ||
| 46 | #include "lld/Core/Error.h" | 47 | #include "lld/Core/Error.h" |
| 47 | #include "lld/Core/LLVM.h" | ||
| 48 | #include "lld/ReaderWriter/MachOLinkingContext.h" | 48 | #include "lld/ReaderWriter/MachOLinkingContext.h" |
| 49 | #include "llvm/ADT/SmallString.h" | 49 | #include "llvm/ADT/SmallString.h" |
| 50 | #include "llvm/ADT/StringRef.h" | 50 | #include "llvm/ADT/StringRef.h" |
| ... | @@ -124,15 +124,6 @@ struct Section { | ... | @@ -124,15 +124,6 @@ struct Section { |
| 124 | ArrayRef<uint8_t> content; | 124 | ArrayRef<uint8_t> content; |
| 125 | Relocations relocations; | 125 | Relocations relocations; |
| 126 | IndirectSymbols indirectSymbols; | 126 | IndirectSymbols indirectSymbols; |
| 127 | |||
| 128 | #ifndef NDEBUG | ||
| 129 | raw_ostream& operator<<(raw_ostream &OS) const { | ||
| 130 | dump(OS); | ||
| 131 | return OS; | ||
| 132 | } | ||
| 133 | |||
| 134 | void dump(raw_ostream &OS = llvm::dbgs()) const; | ||
| 135 | #endif | ||
| 136 | }; | 127 | }; |
| 137 | 128 | ||
| 138 | 129 |
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp+5-2| ... | @@ -24,8 +24,8 @@ | ... | @@ -24,8 +24,8 @@ |
| 24 | #include "ArchHandler.h" | 24 | #include "ArchHandler.h" |
| 25 | #include "MachONormalizedFile.h" | 25 | #include "MachONormalizedFile.h" |
| 26 | #include "MachONormalizedFileBinaryUtils.h" | 26 | #include "MachONormalizedFileBinaryUtils.h" |
| 27 | #include "lld/Common/LLVM.h" | ||
| 27 | #include "lld/Core/Error.h" | 28 | #include "lld/Core/Error.h" |
| 28 | #include "lld/Core/LLVM.h" | ||
| 29 | #include "lld/Core/SharedLibraryFile.h" | 29 | #include "lld/Core/SharedLibraryFile.h" |
| 30 | #include "llvm/ADT/STLExtras.h" | 30 | #include "llvm/ADT/STLExtras.h" |
| 31 | #include "llvm/ADT/SmallString.h" | 31 | #include "llvm/ADT/SmallString.h" |
| ... | @@ -511,7 +511,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, | ... | @@ -511,7 +511,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, |
| 511 | const uint8_t *trieStart = reinterpret_cast<const uint8_t *>( | 511 | const uint8_t *trieStart = reinterpret_cast<const uint8_t *>( |
| 512 | start + read32(&dyldInfo->export_off, isBig)); | 512 | start + read32(&dyldInfo->export_off, isBig)); |
| 513 | ArrayRef<uint8_t> trie(trieStart, read32(&dyldInfo->export_size, isBig)); | 513 | ArrayRef<uint8_t> trie(trieStart, read32(&dyldInfo->export_size, isBig)); |
| 514 | for (const ExportEntry &trieExport : MachOObjectFile::exports(trie)) { | 514 | Error Err = Error::success(); |
| 515 | for (const ExportEntry &trieExport : MachOObjectFile::exports(Err, trie)) { | ||
| 515 | Export normExport; | 516 | Export normExport; |
| 516 | normExport.name = trieExport.name().copy(f->ownedAllocations); | 517 | normExport.name = trieExport.name().copy(f->ownedAllocations); |
| 517 | normExport.offset = trieExport.address(); | 518 | normExport.offset = trieExport.address(); |
| ... | @@ -522,6 +523,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, | ... | @@ -522,6 +523,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, |
| 522 | normExport.otherName = trieExport.otherName().copy(f->ownedAllocations); | 523 | normExport.otherName = trieExport.otherName().copy(f->ownedAllocations); |
| 523 | f->exportInfo.push_back(normExport); | 524 | f->exportInfo.push_back(normExport); |
| 524 | } | 525 | } |
| 526 | if (Err) | ||
| 527 | return std::move(Err); | ||
| 525 | } | 528 | } |
| 526 | } | 529 | } |
| 527 | 530 |
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h+1-1| ... | @@ -11,8 +11,8 @@ | ... | @@ -11,8 +11,8 @@ |
| 11 | #define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H | 11 | #define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H |
| 12 | 12 | ||
| 13 | #include "MachONormalizedFile.h" | 13 | #include "MachONormalizedFile.h" |
| 14 | #include "lld/Common/LLVM.h" | ||
| 14 | #include "lld/Core/Error.h" | 15 | #include "lld/Core/Error.h" |
| 15 | #include "lld/Core/LLVM.h" | ||
| 16 | #include "llvm/ADT/StringRef.h" | 16 | #include "llvm/ADT/StringRef.h" |
| 17 | #include "llvm/BinaryFormat/MachO.h" | 17 | #include "llvm/BinaryFormat/MachO.h" |
| 18 | #include "llvm/Support/Casting.h" | 18 | #include "llvm/Support/Casting.h" |
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp+6-5| ... | @@ -23,8 +23,8 @@ | ... | @@ -23,8 +23,8 @@ |
| 23 | 23 | ||
| 24 | #include "MachONormalizedFile.h" | 24 | #include "MachONormalizedFile.h" |
| 25 | #include "MachONormalizedFileBinaryUtils.h" | 25 | #include "MachONormalizedFileBinaryUtils.h" |
| 26 | #include "lld/Common/LLVM.h" | ||
| 26 | #include "lld/Core/Error.h" | 27 | #include "lld/Core/Error.h" |
| 27 | #include "lld/Core/LLVM.h" | ||
| 28 | #include "llvm/ADT/SmallString.h" | 28 | #include "llvm/ADT/SmallString.h" |
| 29 | #include "llvm/ADT/SmallVector.h" | 29 | #include "llvm/ADT/SmallVector.h" |
| 30 | #include "llvm/ADT/StringRef.h" | 30 | #include "llvm/ADT/StringRef.h" |
| ... | @@ -1523,10 +1523,10 @@ llvm::Error MachOFileLayout::writeBinary(StringRef path) { | ... | @@ -1523,10 +1523,10 @@ llvm::Error MachOFileLayout::writeBinary(StringRef path) { |
| 1523 | unsigned flags = 0; | 1523 | unsigned flags = 0; |
| 1524 | if (_file.fileType != llvm::MachO::MH_OBJECT) | 1524 | if (_file.fileType != llvm::MachO::MH_OBJECT) |
| 1525 | flags = llvm::FileOutputBuffer::F_executable; | 1525 | flags = llvm::FileOutputBuffer::F_executable; |
| 1526 | ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr = | 1526 | Expected<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr = |
| 1527 | llvm::FileOutputBuffer::create(path, size(), flags); | 1527 | llvm::FileOutputBuffer::create(path, size(), flags); |
| 1528 | if (std::error_code ec = fobOrErr.getError()) | 1528 | if (Error E = fobOrErr.takeError()) |
| 1529 | return llvm::errorCodeToError(ec); | 1529 | return E; |
| 1530 | std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr; | 1530 | std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr; |
| 1531 | // Write content. | 1531 | // Write content. |
| 1532 | _buffer = fob->getBufferStart(); | 1532 | _buffer = fob->getBufferStart(); |
| ... | @@ -1535,7 +1535,8 @@ llvm::Error MachOFileLayout::writeBinary(StringRef path) { | ... | @@ -1535,7 +1535,8 @@ llvm::Error MachOFileLayout::writeBinary(StringRef path) { |
| 1535 | return ec; | 1535 | return ec; |
| 1536 | writeSectionContent(); | 1536 | writeSectionContent(); |
| 1537 | writeLinkEditContent(); | 1537 | writeLinkEditContent(); |
| 1538 | fob->commit(); | 1538 | if (Error E = fob->commit()) |
| 1539 | return E; | ||
| 1539 | 1540 | ||
| 1540 | return llvm::Error::success(); | 1541 | return llvm::Error::success(); |
| 1541 | } | 1542 | } |
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp+1-1| ... | @@ -24,8 +24,8 @@ | ... | @@ -24,8 +24,8 @@ |
| 24 | #include "DebugInfo.h" | 24 | #include "DebugInfo.h" |
| 25 | #include "MachONormalizedFile.h" | 25 | #include "MachONormalizedFile.h" |
| 26 | #include "MachONormalizedFileBinaryUtils.h" | 26 | #include "MachONormalizedFileBinaryUtils.h" |
| 27 | #include "lld/Common/LLVM.h" | ||
| 27 | #include "lld/Core/Error.h" | 28 | #include "lld/Core/Error.h" |
| 28 | #include "lld/Core/LLVM.h" | ||
| 29 | #include "llvm/ADT/StringRef.h" | 29 | #include "llvm/ADT/StringRef.h" |
| 30 | #include "llvm/ADT/StringSwitch.h" | 30 | #include "llvm/ADT/StringSwitch.h" |
| 31 | #include "llvm/BinaryFormat/MachO.h" | 31 | #include "llvm/BinaryFormat/MachO.h" |
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp+1-1| ... | @@ -25,8 +25,8 @@ | ... | @@ -25,8 +25,8 @@ |
| 25 | #include "File.h" | 25 | #include "File.h" |
| 26 | #include "MachONormalizedFile.h" | 26 | #include "MachONormalizedFile.h" |
| 27 | #include "MachONormalizedFileBinaryUtils.h" | 27 | #include "MachONormalizedFileBinaryUtils.h" |
| 28 | #include "lld/Common/LLVM.h" | ||
| 28 | #include "lld/Core/Error.h" | 29 | #include "lld/Core/Error.h" |
| 29 | #include "lld/Core/LLVM.h" | ||
| 30 | #include "llvm/BinaryFormat/Dwarf.h" | 30 | #include "llvm/BinaryFormat/Dwarf.h" |
| 31 | #include "llvm/BinaryFormat/MachO.h" | 31 | #include "llvm/BinaryFormat/MachO.h" |
| 32 | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" | 32 | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" |
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp+4-4| ... | @@ -16,8 +16,8 @@ | ... | @@ -16,8 +16,8 @@ |
| 16 | /// +------------+ +------+ | 16 | /// +------------+ +------+ |
| 17 | 17 | ||
| 18 | #include "MachONormalizedFile.h" | 18 | #include "MachONormalizedFile.h" |
| 19 | #include "lld/Common/LLVM.h" | ||
| 19 | #include "lld/Core/Error.h" | 20 | #include "lld/Core/Error.h" |
| 20 | #include "lld/Core/LLVM.h" | ||
| 21 | #include "lld/ReaderWriter/YamlContext.h" | 21 | #include "lld/ReaderWriter/YamlContext.h" |
| 22 | #include "llvm/ADT/SmallString.h" | 22 | #include "llvm/ADT/SmallString.h" |
| 23 | #include "llvm/ADT/StringRef.h" | 23 | #include "llvm/ADT/StringRef.h" |
| ... | @@ -257,7 +257,7 @@ template <> struct ScalarTraits<SectionAlignment> { | ... | @@ -257,7 +257,7 @@ template <> struct ScalarTraits<SectionAlignment> { |
| 257 | return StringRef(); // returning empty string means success | 257 | return StringRef(); // returning empty string means success |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static bool mustQuote(StringRef) { return false; } | 260 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
| 261 | }; | 261 | }; |
| 262 | 262 | ||
| 263 | template <> | 263 | template <> |
| ... | @@ -522,7 +522,7 @@ struct ScalarTraits<VMProtect> { | ... | @@ -522,7 +522,7 @@ struct ScalarTraits<VMProtect> { |
| 522 | // Return the empty string on success, | 522 | // Return the empty string on success, |
| 523 | return StringRef(); | 523 | return StringRef(); |
| 524 | } | 524 | } |
| 525 | static bool mustQuote(StringRef) { return false; } | 525 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
| 526 | }; | 526 | }; |
| 527 | 527 | ||
| 528 | 528 | ||
| ... | @@ -706,7 +706,7 @@ struct ScalarTraits<PackedVersion> { | ... | @@ -706,7 +706,7 @@ struct ScalarTraits<PackedVersion> { |
| 706 | // Return the empty string on success, | 706 | // Return the empty string on success, |
| 707 | return StringRef(); | 707 | return StringRef(); |
| 708 | } | 708 | } |
| 709 | static bool mustQuote(StringRef) { return false; } | 709 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
| 710 | }; | 710 | }; |
| 711 | 711 | ||
| 712 | template <> | 712 | template <> |
deps/lld/lib/ReaderWriter/MachO/ObjCPass.cpp+1-1| ... | @@ -13,9 +13,9 @@ | ... | @@ -13,9 +13,9 @@ |
| 13 | #include "File.h" | 13 | #include "File.h" |
| 14 | #include "MachONormalizedFileBinaryUtils.h" | 14 | #include "MachONormalizedFileBinaryUtils.h" |
| 15 | #include "MachOPasses.h" | 15 | #include "MachOPasses.h" |
| 16 | #include "lld/Common/LLVM.h" | ||
| 16 | #include "lld/Core/DefinedAtom.h" | 17 | #include "lld/Core/DefinedAtom.h" |
| 17 | #include "lld/Core/File.h" | 18 | #include "lld/Core/File.h" |
| 18 | #include "lld/Core/LLVM.h" | ||
| 19 | #include "lld/Core/Reference.h" | 19 | #include "lld/Core/Reference.h" |
| 20 | #include "lld/Core/Simple.h" | 20 | #include "lld/Core/Simple.h" |
| 21 | #include "lld/ReaderWriter/MachOLinkingContext.h" | 21 | #include "lld/ReaderWriter/MachOLinkingContext.h" |
deps/lld/lib/ReaderWriter/MachO/ShimPass.cpp+1-1| ... | @@ -26,9 +26,9 @@ | ... | @@ -26,9 +26,9 @@ |
| 26 | #include "ArchHandler.h" | 26 | #include "ArchHandler.h" |
| 27 | #include "File.h" | 27 | #include "File.h" |
| 28 | #include "MachOPasses.h" | 28 | #include "MachOPasses.h" |
| 29 | #include "lld/Common/LLVM.h" | ||
| 29 | #include "lld/Core/DefinedAtom.h" | 30 | #include "lld/Core/DefinedAtom.h" |
| 30 | #include "lld/Core/File.h" | 31 | #include "lld/Core/File.h" |
| 31 | #include "lld/Core/LLVM.h" | ||
| 32 | #include "lld/Core/Reference.h" | 32 | #include "lld/Core/Reference.h" |
| 33 | #include "lld/Core/Simple.h" | 33 | #include "lld/Core/Simple.h" |
| 34 | #include "lld/ReaderWriter/MachOLinkingContext.h" | 34 | #include "lld/ReaderWriter/MachOLinkingContext.h" |
deps/lld/lib/ReaderWriter/MachO/StubsPass.cpp+1-1| ... | @@ -17,9 +17,9 @@ | ... | @@ -17,9 +17,9 @@ |
| 17 | #include "ArchHandler.h" | 17 | #include "ArchHandler.h" |
| 18 | #include "File.h" | 18 | #include "File.h" |
| 19 | #include "MachOPasses.h" | 19 | #include "MachOPasses.h" |
| 20 | #include "lld/Common/LLVM.h" | ||
| 20 | #include "lld/Core/DefinedAtom.h" | 21 | #include "lld/Core/DefinedAtom.h" |
| 21 | #include "lld/Core/File.h" | 22 | #include "lld/Core/File.h" |
| 22 | #include "lld/Core/LLVM.h" | ||
| 23 | #include "lld/Core/Reference.h" | 23 | #include "lld/Core/Reference.h" |
| 24 | #include "lld/Core/Simple.h" | 24 | #include "lld/Core/Simple.h" |
| 25 | #include "lld/ReaderWriter/MachOLinkingContext.h" | 25 | #include "lld/ReaderWriter/MachOLinkingContext.h" |
deps/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp+3-3| ... | @@ -280,7 +280,7 @@ template <> struct ScalarTraits<RefKind> { | ... | @@ -280,7 +280,7 @@ template <> struct ScalarTraits<RefKind> { |
| 280 | return StringRef("unknown reference kind"); | 280 | return StringRef("unknown reference kind"); |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static bool mustQuote(StringRef) { return false; } | 283 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
| 284 | }; | 284 | }; |
| 285 | 285 | ||
| 286 | template <> struct ScalarEnumerationTraits<lld::File::Kind> { | 286 | template <> struct ScalarEnumerationTraits<lld::File::Kind> { |
| ... | @@ -495,7 +495,7 @@ template <> struct ScalarTraits<lld::DefinedAtom::Alignment> { | ... | @@ -495,7 +495,7 @@ template <> struct ScalarTraits<lld::DefinedAtom::Alignment> { |
| 495 | return StringRef(); // returning empty string means success | 495 | return StringRef(); // returning empty string means success |
| 496 | } | 496 | } |
| 497 | 497 | ||
| 498 | static bool mustQuote(StringRef) { return false; } | 498 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
| 499 | }; | 499 | }; |
| 500 | 500 | ||
| 501 | template <> struct ScalarEnumerationTraits<FileKinds> { | 501 | template <> struct ScalarEnumerationTraits<FileKinds> { |
| ... | @@ -552,7 +552,7 @@ template <> struct ScalarTraits<ImplicitHex8> { | ... | @@ -552,7 +552,7 @@ template <> struct ScalarTraits<ImplicitHex8> { |
| 552 | return StringRef(); // returning empty string means success | 552 | return StringRef(); // returning empty string means success |
| 553 | } | 553 | } |
| 554 | 554 | ||
| 555 | static bool mustQuote(StringRef) { return false; } | 555 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
| 556 | }; | 556 | }; |
| 557 | 557 | ||
| 558 | // YAML conversion for std::vector<const lld::File*> | 558 | // YAML conversion for std::vector<const lld::File*> |
deps/lld/test/CMakeLists.txt+10-5| ... | @@ -17,18 +17,23 @@ llvm_canonicalize_cmake_booleans( | ... | @@ -17,18 +17,23 @@ llvm_canonicalize_cmake_booleans( |
| 17 | HAVE_LIBZ) | 17 | HAVE_LIBZ) |
| 18 | 18 | ||
| 19 | configure_lit_site_cfg( | 19 | configure_lit_site_cfg( |
| 20 | ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in | 20 | ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in |
| 21 | ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg) | 21 | ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py |
| 22 | MAIN_CONFIG | ||
| 23 | ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py | ||
| 24 | ) | ||
| 22 | configure_lit_site_cfg( | 25 | configure_lit_site_cfg( |
| 23 | ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in | 26 | ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in |
| 24 | ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg | 27 | ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py |
| 28 | MAIN_CONFIG | ||
| 29 | ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.cfg.py | ||
| 25 | ) | 30 | ) |
| 26 | 31 | ||
| 27 | set(LLD_TEST_DEPS lld) | 32 | set(LLD_TEST_DEPS lld) |
| 28 | if (NOT LLD_BUILT_STANDALONE) | 33 | if (NOT LLD_BUILT_STANDALONE) |
| 29 | list(APPEND LLD_TEST_DEPS | 34 | list(APPEND LLD_TEST_DEPS |
| 30 | FileCheck count not llvm-ar llvm-as llvm-dis llvm-dwarfdump llvm-nm | 35 | FileCheck count not llvm-ar llvm-as llvm-dis llvm-dwarfdump llvm-nm |
| 31 | llc llvm-config llvm-objdump llvm-readobj yaml2obj obj2yaml | 36 | llc llvm-config llvm-objdump llvm-readelf llvm-readobj yaml2obj obj2yaml |
| 32 | llvm-mc llvm-lib llvm-pdbutil opt | 37 | llvm-mc llvm-lib llvm-pdbutil opt |
| 33 | ) | 38 | ) |
| 34 | endif() | 39 | endif() |
deps/lld/test/COFF/Inputs/alpha.ll created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | define void @_DllMainCRTStartup() { | ||
| 2 | entry: | ||
| 3 | ret void | ||
| 4 | } | ||
| 5 | |||
| 6 | define dllexport void @f() local_unnamed_addr { | ||
| 7 | entry: | ||
| 8 | ret void | ||
| 9 | } | ||
deps/lld/test/COFF/Inputs/beta.ll created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | declare dllimport void @f() local_unnamed_addr | ||
| 2 | |||
| 3 | define void @g() local_unnamed_addr { | ||
| 4 | entry: | ||
| 5 | tail call void @f() | ||
| 6 | ret void | ||
| 7 | } | ||
deps/lld/test/COFF/Inputs/except_handler3.lib created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/except_handler3.lib differ | |||
deps/lld/test/COFF/Inputs/far-arm-thumb-abs20.s created+2| ... | @@ -0,0 +1,2 @@ | ||
| 1 | .global too_far20 | ||
| 2 | too_far20 = 0x501004 | ||
deps/lld/test/COFF/Inputs/gamma.ll created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | |||
| 2 | declare void @f() local_unnamed_addr | ||
| 3 | |||
| 4 | define void @__imp_f() local_unnamed_addr { | ||
| 5 | entry: | ||
| 6 | ret void | ||
| 7 | } | ||
| 8 | |||
| 9 | define void @mainCRTStartup() local_unnamed_addr { | ||
| 10 | entry: | ||
| 11 | tail call void @f() | ||
| 12 | ret void | ||
| 13 | } | ||
| 14 | |||
deps/lld/test/COFF/Inputs/library2-arm64.lib created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/library2-arm64.lib differ | |||
deps/lld/test/COFF/Inputs/library2.def created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | LIBRARY library2 | ||
| 2 | EXPORTS | ||
| 3 | function2 | ||
deps/lld/test/COFF/Inputs/locally-imported-def.s created+4| ... | @@ -0,0 +1,4 @@ | ||
| 1 | .text | ||
| 2 | .globl f | ||
| 3 | f: | ||
| 4 | 	ret | ||
deps/lld/test/COFF/Inputs/locally-imported-imp.s created+2| ... | @@ -0,0 +1,2 @@ | ||
| 1 | .text | ||
| 2 | 	call	__imp_f | ||
deps/lld/test/COFF/Inputs/lto-cache.ll created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" | ||
| 2 | target triple = "x86_64-pc-windows-msvc" | ||
| 3 | |||
| 4 | define i32 @main() { | ||
| 5 | entry: | ||
| 6 | call void (...) @globalfunc() | ||
| 7 | ret i32 0 | ||
| 8 | } | ||
| 9 | |||
| 10 | declare void @globalfunc(...) | ||
deps/lld/test/COFF/Inputs/pdb-globals.yaml created+593| ... | @@ -0,0 +1,593 @@ | ||
| 1 | # // YAML Generated from the following source code: | ||
| 2 | # // Compile with clang-cl /Z7 /GS- /c t.obj pdb-globals.cpp | ||
| 3 | # | ||
| 4 | # void *__purecall = 0; | ||
| 5 | # | ||
| 6 | # struct HelloPoint { | ||
| 7 | # int X = 3; | ||
| 8 | # int Y = 4; | ||
| 9 | # int Z = 5; | ||
| 10 | # }; | ||
| 11 | # | ||
| 12 | # // S_LPROCREF | ||
| 13 | # static int LocalFunc() { return 42; } | ||
| 14 | # | ||
| 15 | # // S_PROCREF | ||
| 16 | # int GlobalFunc() { return 43; } | ||
| 17 | # | ||
| 18 | # // S_LDATA32 | ||
| 19 | # const int ConstantVar = 17; | ||
| 20 | # | ||
| 21 | # // S_GDATA32 | ||
| 22 | # const int *GlobalVar = &ConstantVar; | ||
| 23 | # | ||
| 24 | # // S_CONSTANT | ||
| 25 | # constexpr int ConstexprVar = 18; | ||
| 26 | # | ||
| 27 | # // S_UDT | ||
| 28 | # typedef HelloPoint HelloPointTypedef; | ||
| 29 | # | ||
| 30 | # int main(int argc, char **argv) { | ||
| 31 | # HelloPointTypedef P; | ||
| 32 | # int N = P.X + P.Y + P.Z; | ||
| 33 | # N += LocalFunc() + GlobalFunc(); | ||
| 34 | # N += *GlobalVar; | ||
| 35 | # N += ConstexprVar; | ||
| 36 | # } | ||
| 37 | |||
| 38 | |||
| 39 | --- !COFF | ||
| 40 | header: | ||
| 41 | Machine: IMAGE_FILE_MACHINE_I386 | ||
| 42 | Characteristics: [ ] | ||
| 43 | sections: | ||
| 44 | - Name: .text | ||
| 45 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 46 | Alignment: 16 | ||
| 47 | SectionData: 5589E5B82B0000005DC3660F1F4400005589E583EC208B450C8B4D088D55F4894DEC89D18945E8E8000000008B4DF4034DF8034DFC894DF08945E4E8000000008945E0E80000000031C98B55E001C20355F08955F0A1000000008B000345F08945F08B45F083C0128945F089C883C4205DC366666666662E0F1F8400000000005589E5B82A0000005DC3 | ||
| 48 | Relocations: | ||
| 49 | - VirtualAddress: 40 | ||
| 50 | SymbolName: '??0HelloPoint@@QAE@XZ' | ||
| 51 | Type: IMAGE_REL_I386_REL32 | ||
| 52 | - VirtualAddress: 60 | ||
| 53 | SymbolName: '?LocalFunc@@YAHXZ' | ||
| 54 | Type: IMAGE_REL_I386_REL32 | ||
| 55 | - VirtualAddress: 68 | ||
| 56 | SymbolName: '?GlobalFunc@@YAHXZ' | ||
| 57 | Type: IMAGE_REL_I386_REL32 | ||
| 58 | - VirtualAddress: 86 | ||
| 59 | SymbolName: '?GlobalVar@@3PBHB' | ||
| 60 | Type: IMAGE_REL_I386_DIR32 | ||
| 61 | - Name: .data | ||
| 62 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 63 | Alignment: 4 | ||
| 64 | SectionData: '00000000' | ||
| 65 | Relocations: | ||
| 66 | - VirtualAddress: 0 | ||
| 67 | SymbolName: _ConstantVar | ||
| 68 | Type: IMAGE_REL_I386_DIR32 | ||
| 69 | - Name: .bss | ||
| 70 | Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 71 | Alignment: 4 | ||
| 72 | SectionData: '' | ||
| 73 | - Name: .text | ||
| 74 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 75 | Alignment: 16 | ||
| 76 | SectionData: 5589E550894DFC8B4DFCC70103000000C7410404000000C741080500000089C883C4045DC3 | ||
| 77 | - Name: .rdata | ||
| 78 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | ||
| 79 | Alignment: 4 | ||
| 80 | SectionData: '11000000' | ||
| 81 | - Name: .drectve | ||
| 82 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 83 | Alignment: 1 | ||
| 84 | SectionData: 202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962 | ||
| 85 | - Name: '.debug$S' | ||
| 86 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 87 | Alignment: 4 | ||
| 88 | SectionData: 04000000F10000002F0000002D003C1101000000070006000000000000007017000000000000636C616E672076657273696F6E20362E302E30200000F100000036000000300047110000000000000000000000000A00000000000000000000000210000000000000000000476C6F62616C46756E630002004F110000F20000002000000000000000000000000A0000000000000001000000140000000000000010000000F1000000B60000002A00471100000000000000000000000062000000000000000000000006100000000000000000006D61696E000D003E1174000000010061726763001200451116000000080000001F000000000053000D003E11031000000100617267760012004511160000000C0000001F000000000053000A003E1107100000000050001200451116000000F4FFFFFF1F000000000053000A003E117400000000004E001200451116000000F0FFFFFF1F0000000000530002004F110000F200000050000000000000000000000062000000000000000700000044000000000000001E0000000F0000001F0000001C000000200000002800000021000000450000002200000052000000230000005B00000024000000F1000000350000002F0046110000000000000000000000000A00000000000000000000000F100000000000000000004C6F63616C46756E630002004F11000000F20000002000000000000000000000000A000000000000000100000014000000000000000D000000F10000004B00000017000D11030400000000000000005F5F7075726563616C6C0016000D1111100000000000000000476C6F62616C5661720018000C1110100000000000000000436F6E7374616E745661720000F10000002D000000180008110710000048656C6C6F506F696E745479706564656600110008110910000048656C6C6F506F696E7400000000F4000000080000000100000000000000F30000003800000000643A5C7372635C6C6C766D2D6D6F6E6F5C6C6C645C746573745C636F66665C696E707574735C7064622D676C6F62616C732E6370700000 | ||
| 89 | Subsections: | ||
| 90 | - !Symbols | ||
| 91 | Records: | ||
| 92 | - Kind: S_COMPILE3 | ||
| 93 | Compile3Sym: | ||
| 94 | Flags: [ ] | ||
| 95 | Machine: Pentium3 | ||
| 96 | FrontendMajor: 6 | ||
| 97 | FrontendMinor: 0 | ||
| 98 | FrontendBuild: 0 | ||
| 99 | FrontendQFE: 0 | ||
| 100 | BackendMajor: 6000 | ||
| 101 | BackendMinor: 0 | ||
| 102 | BackendBuild: 0 | ||
| 103 | BackendQFE: 0 | ||
| 104 | Version: 'clang version 6.0.0 ' | ||
| 105 | - Kind: S_GPROC32_ID | ||
| 106 | ProcSym: | ||
| 107 | CodeSize: 10 | ||
| 108 | DbgStart: 0 | ||
| 109 | DbgEnd: 0 | ||
| 110 | FunctionType: 4098 | ||
| 111 | Flags: [ ] | ||
| 112 | DisplayName: GlobalFunc | ||
| 113 | - Kind: S_PROC_ID_END | ||
| 114 | ScopeEndSym: | ||
| 115 | - Kind: S_GPROC32_ID | ||
| 116 | ProcSym: | ||
| 117 | CodeSize: 98 | ||
| 118 | DbgStart: 0 | ||
| 119 | DbgEnd: 0 | ||
| 120 | FunctionType: 4102 | ||
| 121 | Flags: [ ] | ||
| 122 | DisplayName: main | ||
| 123 | - Kind: S_LOCAL | ||
| 124 | LocalSym: | ||
| 125 | Type: 116 | ||
| 126 | Flags: [ IsParameter ] | ||
| 127 | VarName: argc | ||
| 128 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 129 | DefRangeRegisterRelSym: | ||
| 130 | - Kind: S_LOCAL | ||
| 131 | LocalSym: | ||
| 132 | Type: 4099 | ||
| 133 | Flags: [ IsParameter ] | ||
| 134 | VarName: argv | ||
| 135 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 136 | DefRangeRegisterRelSym: | ||
| 137 | - Kind: S_LOCAL | ||
| 138 | LocalSym: | ||
| 139 | Type: 4103 | ||
| 140 | Flags: [ ] | ||
| 141 | VarName: P | ||
| 142 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 143 | DefRangeRegisterRelSym: | ||
| 144 | - Kind: S_LOCAL | ||
| 145 | LocalSym: | ||
| 146 | Type: 116 | ||
| 147 | Flags: [ ] | ||
| 148 | VarName: N | ||
| 149 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 150 | DefRangeRegisterRelSym: | ||
| 151 | - Kind: S_PROC_ID_END | ||
| 152 | ScopeEndSym: | ||
| 153 | - Kind: S_LPROC32_ID | ||
| 154 | ProcSym: | ||
| 155 | CodeSize: 10 | ||
| 156 | DbgStart: 0 | ||
| 157 | DbgEnd: 0 | ||
| 158 | FunctionType: 4111 | ||
| 159 | Flags: [ ] | ||
| 160 | DisplayName: LocalFunc | ||
| 161 | - Kind: S_PROC_ID_END | ||
| 162 | ScopeEndSym: | ||
| 163 | - Kind: S_GDATA32 | ||
| 164 | DataSym: | ||
| 165 | Type: 1027 | ||
| 166 | DisplayName: __purecall | ||
| 167 | - Kind: S_GDATA32 | ||
| 168 | DataSym: | ||
| 169 | Type: 4113 | ||
| 170 | DisplayName: GlobalVar | ||
| 171 | - Kind: S_LDATA32 | ||
| 172 | DataSym: | ||
| 173 | Type: 4112 | ||
| 174 | DisplayName: ConstantVar | ||
| 175 | - Kind: S_UDT | ||
| 176 | UDTSym: | ||
| 177 | Type: 4103 | ||
| 178 | UDTName: HelloPointTypedef | ||
| 179 | - Kind: S_UDT | ||
| 180 | UDTSym: | ||
| 181 | Type: 4105 | ||
| 182 | UDTName: HelloPoint | ||
| 183 | - !FileChecksums | ||
| 184 | Checksums: | ||
| 185 | - FileName: 'd:\src\llvm-mono\lld\test\coff\inputs\pdb-globals.cpp' | ||
| 186 | Kind: None | ||
| 187 | Checksum: '' | ||
| 188 | - !StringTable | ||
| 189 | Strings: | ||
| 190 | - 'd:\src\llvm-mono\lld\test\coff\inputs\pdb-globals.cpp' | ||
| 191 | - '' | ||
| 192 | Relocations: | ||
| 193 | - VirtualAddress: 100 | ||
| 194 | SymbolName: '?GlobalFunc@@YAHXZ' | ||
| 195 | Type: IMAGE_REL_I386_SECREL | ||
| 196 | - VirtualAddress: 104 | ||
| 197 | SymbolName: '?GlobalFunc@@YAHXZ' | ||
| 198 | Type: IMAGE_REL_I386_SECTION | ||
| 199 | - VirtualAddress: 132 | ||
| 200 | SymbolName: '?GlobalFunc@@YAHXZ' | ||
| 201 | Type: IMAGE_REL_I386_SECREL | ||
| 202 | - VirtualAddress: 136 | ||
| 203 | SymbolName: '?GlobalFunc@@YAHXZ' | ||
| 204 | Type: IMAGE_REL_I386_SECTION | ||
| 205 | - VirtualAddress: 204 | ||
| 206 | SymbolName: _main | ||
| 207 | Type: IMAGE_REL_I386_SECREL | ||
| 208 | - VirtualAddress: 208 | ||
| 209 | SymbolName: _main | ||
| 210 | Type: IMAGE_REL_I386_SECTION | ||
| 211 | - VirtualAddress: 243 | ||
| 212 | SymbolName: .text | ||
| 213 | Type: IMAGE_REL_I386_SECREL | ||
| 214 | - VirtualAddress: 247 | ||
| 215 | SymbolName: .text | ||
| 216 | Type: IMAGE_REL_I386_SECTION | ||
| 217 | - VirtualAddress: 278 | ||
| 218 | SymbolName: .text | ||
| 219 | Type: IMAGE_REL_I386_SECREL | ||
| 220 | - VirtualAddress: 282 | ||
| 221 | SymbolName: .text | ||
| 222 | Type: IMAGE_REL_I386_SECTION | ||
| 223 | - VirtualAddress: 310 | ||
| 224 | SymbolName: .text | ||
| 225 | Type: IMAGE_REL_I386_SECREL | ||
| 226 | - VirtualAddress: 314 | ||
| 227 | SymbolName: .text | ||
| 228 | Type: IMAGE_REL_I386_SECTION | ||
| 229 | - VirtualAddress: 342 | ||
| 230 | SymbolName: .text | ||
| 231 | Type: IMAGE_REL_I386_SECREL | ||
| 232 | - VirtualAddress: 346 | ||
| 233 | SymbolName: .text | ||
| 234 | Type: IMAGE_REL_I386_SECTION | ||
| 235 | - VirtualAddress: 364 | ||
| 236 | SymbolName: _main | ||
| 237 | Type: IMAGE_REL_I386_SECREL | ||
| 238 | - VirtualAddress: 368 | ||
| 239 | SymbolName: _main | ||
| 240 | Type: IMAGE_REL_I386_SECTION | ||
| 241 | - VirtualAddress: 484 | ||
| 242 | SymbolName: '?LocalFunc@@YAHXZ' | ||
| 243 | Type: IMAGE_REL_I386_SECREL | ||
| 244 | - VirtualAddress: 488 | ||
| 245 | SymbolName: '?LocalFunc@@YAHXZ' | ||
| 246 | Type: IMAGE_REL_I386_SECTION | ||
| 247 | - VirtualAddress: 516 | ||
| 248 | SymbolName: '?LocalFunc@@YAHXZ' | ||
| 249 | Type: IMAGE_REL_I386_SECREL | ||
| 250 | - VirtualAddress: 520 | ||
| 251 | SymbolName: '?LocalFunc@@YAHXZ' | ||
| 252 | Type: IMAGE_REL_I386_SECTION | ||
| 253 | - VirtualAddress: 564 | ||
| 254 | SymbolName: '?__purecall@@3PAXA' | ||
| 255 | Type: IMAGE_REL_I386_SECREL | ||
| 256 | - VirtualAddress: 568 | ||
| 257 | SymbolName: '?__purecall@@3PAXA' | ||
| 258 | Type: IMAGE_REL_I386_SECTION | ||
| 259 | - VirtualAddress: 589 | ||
| 260 | SymbolName: '?GlobalVar@@3PBHB' | ||
| 261 | Type: IMAGE_REL_I386_SECREL | ||
| 262 | - VirtualAddress: 593 | ||
| 263 | SymbolName: '?GlobalVar@@3PBHB' | ||
| 264 | Type: IMAGE_REL_I386_SECTION | ||
| 265 | - VirtualAddress: 613 | ||
| 266 | SymbolName: _ConstantVar | ||
| 267 | Type: IMAGE_REL_I386_SECREL | ||
| 268 | - VirtualAddress: 617 | ||
| 269 | SymbolName: _ConstantVar | ||
| 270 | Type: IMAGE_REL_I386_SECTION | ||
| 271 | - Name: '.debug$T' | ||
| 272 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 273 | Alignment: 4 | ||
| 274 | SectionData: 0400000006000112000000000E000810740000000000000000100000160001160000000001100000476C6F62616C46756E6300F10A000210700400000A8000000E0001120200000074000000031000000E0008107400000000000200041000001200011600000000051000006D61696E00F3F2F13200051500008002000000000000000000000000000048656C6C6F506F696E74002E3F415548656C6C6F506F696E74404000F2F1260003120D15030074000000000058000D15030074000000040059000D1503007400000008005A0032000515030000020810000000000000000000000C0048656C6C6F506F696E74002E3F415548656C6C6F506F696E74404000F2F13E00051600000000643A5C7372635C6C6C766D2D6D6F6E6F5C6C6C645C746573745C636F66665C696E707574735C7064622D676C6F62616C732E63707000F2F10E000616091000000A100000060000000A000210071000000A8000001A00091003000000071000000C1000000B000000001000000000000016000216071000000D10000048656C6C6F506F696E7400F11600011600000000011000004C6F63616C46756E6300F2F10A000110740000000100F2F10A000210101000000A800000 | ||
| 275 | Types: | ||
| 276 | - Kind: LF_ARGLIST | ||
| 277 | ArgList: | ||
| 278 | ArgIndices: [ ] | ||
| 279 | - Kind: LF_PROCEDURE | ||
| 280 | Procedure: | ||
| 281 | ReturnType: 116 | ||
| 282 | CallConv: NearC | ||
| 283 | Options: [ None ] | ||
| 284 | ParameterCount: 0 | ||
| 285 | ArgumentList: 4096 | ||
| 286 | - Kind: LF_FUNC_ID | ||
| 287 | FuncId: | ||
| 288 | ParentScope: 0 | ||
| 289 | FunctionType: 4097 | ||
| 290 | Name: GlobalFunc | ||
| 291 | - Kind: LF_POINTER | ||
| 292 | Pointer: | ||
| 293 | ReferentType: 1136 | ||
| 294 | Attrs: 32778 | ||
| 295 | - Kind: LF_ARGLIST | ||
| 296 | ArgList: | ||
| 297 | ArgIndices: [ 116, 4099 ] | ||
| 298 | - Kind: LF_PROCEDURE | ||
| 299 | Procedure: | ||
| 300 | ReturnType: 116 | ||
| 301 | CallConv: NearC | ||
| 302 | Options: [ None ] | ||
| 303 | ParameterCount: 2 | ||
| 304 | ArgumentList: 4100 | ||
| 305 | - Kind: LF_FUNC_ID | ||
| 306 | FuncId: | ||
| 307 | ParentScope: 0 | ||
| 308 | FunctionType: 4101 | ||
| 309 | Name: main | ||
| 310 | - Kind: LF_STRUCTURE | ||
| 311 | Class: | ||
| 312 | MemberCount: 0 | ||
| 313 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 314 | FieldList: 0 | ||
| 315 | Name: HelloPoint | ||
| 316 | UniqueName: '.?AUHelloPoint@@' | ||
| 317 | DerivationList: 0 | ||
| 318 | VTableShape: 0 | ||
| 319 | Size: 0 | ||
| 320 | - Kind: LF_FIELDLIST | ||
| 321 | FieldList: | ||
| 322 | - Kind: LF_MEMBER | ||
| 323 | DataMember: | ||
| 324 | Attrs: 3 | ||
| 325 | Type: 116 | ||
| 326 | FieldOffset: 0 | ||
| 327 | Name: X | ||
| 328 | - Kind: LF_MEMBER | ||
| 329 | DataMember: | ||
| 330 | Attrs: 3 | ||
| 331 | Type: 116 | ||
| 332 | FieldOffset: 4 | ||
| 333 | Name: Y | ||
| 334 | - Kind: LF_MEMBER | ||
| 335 | DataMember: | ||
| 336 | Attrs: 3 | ||
| 337 | Type: 116 | ||
| 338 | FieldOffset: 8 | ||
| 339 | Name: Z | ||
| 340 | - Kind: LF_STRUCTURE | ||
| 341 | Class: | ||
| 342 | MemberCount: 3 | ||
| 343 | Options: [ None, HasUniqueName ] | ||
| 344 | FieldList: 4104 | ||
| 345 | Name: HelloPoint | ||
| 346 | UniqueName: '.?AUHelloPoint@@' | ||
| 347 | DerivationList: 0 | ||
| 348 | VTableShape: 0 | ||
| 349 | Size: 12 | ||
| 350 | - Kind: LF_STRING_ID | ||
| 351 | StringId: | ||
| 352 | Id: 0 | ||
| 353 | String: 'd:\src\llvm-mono\lld\test\coff\inputs\pdb-globals.cpp' | ||
| 354 | - Kind: LF_UDT_SRC_LINE | ||
| 355 | UdtSourceLine: | ||
| 356 | UDT: 4105 | ||
| 357 | SourceFile: 4106 | ||
| 358 | LineNumber: 6 | ||
| 359 | - Kind: LF_POINTER | ||
| 360 | Pointer: | ||
| 361 | ReferentType: 4103 | ||
| 362 | Attrs: 32778 | ||
| 363 | - Kind: LF_MFUNCTION | ||
| 364 | MemberFunction: | ||
| 365 | ReturnType: 3 | ||
| 366 | ClassType: 4103 | ||
| 367 | ThisType: 4108 | ||
| 368 | CallConv: ThisCall | ||
| 369 | Options: [ None ] | ||
| 370 | ParameterCount: 0 | ||
| 371 | ArgumentList: 4096 | ||
| 372 | ThisPointerAdjustment: 0 | ||
| 373 | - Kind: LF_MFUNC_ID | ||
| 374 | MemberFuncId: | ||
| 375 | ClassType: 4103 | ||
| 376 | FunctionType: 4109 | ||
| 377 | Name: HelloPoint | ||
| 378 | - Kind: LF_FUNC_ID | ||
| 379 | FuncId: | ||
| 380 | ParentScope: 0 | ||
| 381 | FunctionType: 4097 | ||
| 382 | Name: LocalFunc | ||
| 383 | - Kind: LF_MODIFIER | ||
| 384 | Modifier: | ||
| 385 | ModifiedType: 116 | ||
| 386 | Modifiers: [ None, Const ] | ||
| 387 | - Kind: LF_POINTER | ||
| 388 | Pointer: | ||
| 389 | ReferentType: 4112 | ||
| 390 | Attrs: 32778 | ||
| 391 | - Name: '.debug$S' | ||
| 392 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 393 | Alignment: 4 | ||
| 394 | SectionData: 04000000F1000000650000003C0047110000000000000000000000002500000000000000000000000E1000000000000000000048656C6C6F506F696E743A3A48656C6C6F506F696E74000D003E110C100000010074686973001200451116000000FCFFFFFF0A00000000001B0002004F11000000F20000004000000000000000000000002500000000000000050000003400000000000000060000000A00000007000000100000000800000017000000090000001E00000006000000 | ||
| 395 | Subsections: | ||
| 396 | - !Symbols | ||
| 397 | Records: | ||
| 398 | - Kind: S_GPROC32_ID | ||
| 399 | ProcSym: | ||
| 400 | CodeSize: 37 | ||
| 401 | DbgStart: 0 | ||
| 402 | DbgEnd: 0 | ||
| 403 | FunctionType: 4110 | ||
| 404 | Flags: [ ] | ||
| 405 | DisplayName: 'HelloPoint::HelloPoint' | ||
| 406 | - Kind: S_LOCAL | ||
| 407 | LocalSym: | ||
| 408 | Type: 4108 | ||
| 409 | Flags: [ IsParameter ] | ||
| 410 | VarName: this | ||
| 411 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 412 | DefRangeRegisterRelSym: | ||
| 413 | - Kind: S_PROC_ID_END | ||
| 414 | ScopeEndSym: | ||
| 415 | Relocations: | ||
| 416 | - VirtualAddress: 44 | ||
| 417 | SymbolName: '??0HelloPoint@@QAE@XZ' | ||
| 418 | Type: IMAGE_REL_I386_SECREL | ||
| 419 | - VirtualAddress: 48 | ||
| 420 | SymbolName: '??0HelloPoint@@QAE@XZ' | ||
| 421 | Type: IMAGE_REL_I386_SECTION | ||
| 422 | - VirtualAddress: 101 | ||
| 423 | SymbolName: .text | ||
| 424 | Type: IMAGE_REL_I386_SECREL | ||
| 425 | - VirtualAddress: 105 | ||
| 426 | SymbolName: .text | ||
| 427 | Type: IMAGE_REL_I386_SECTION | ||
| 428 | - VirtualAddress: 124 | ||
| 429 | SymbolName: '??0HelloPoint@@QAE@XZ' | ||
| 430 | Type: IMAGE_REL_I386_SECREL | ||
| 431 | - VirtualAddress: 128 | ||
| 432 | SymbolName: '??0HelloPoint@@QAE@XZ' | ||
| 433 | Type: IMAGE_REL_I386_SECTION | ||
| 434 | symbols: | ||
| 435 | - Name: .text | ||
| 436 | Value: 0 | ||
| 437 | SectionNumber: 1 | ||
| 438 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 439 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 440 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 441 | SectionDefinition: | ||
| 442 | Length: 138 | ||
| 443 | NumberOfRelocations: 4 | ||
| 444 | NumberOfLinenumbers: 0 | ||
| 445 | CheckSum: 3215092891 | ||
| 446 | Number: 1 | ||
| 447 | - Name: .data | ||
| 448 | Value: 0 | ||
| 449 | SectionNumber: 2 | ||
| 450 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 451 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 452 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 453 | SectionDefinition: | ||
| 454 | Length: 4 | ||
| 455 | NumberOfRelocations: 1 | ||
| 456 | NumberOfLinenumbers: 0 | ||
| 457 | CheckSum: 0 | ||
| 458 | Number: 2 | ||
| 459 | - Name: .bss | ||
| 460 | Value: 0 | ||
| 461 | SectionNumber: 3 | ||
| 462 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 463 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 464 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 465 | SectionDefinition: | ||
| 466 | Length: 4 | ||
| 467 | NumberOfRelocations: 0 | ||
| 468 | NumberOfLinenumbers: 0 | ||
| 469 | CheckSum: 0 | ||
| 470 | Number: 3 | ||
| 471 | - Name: .text | ||
| 472 | Value: 0 | ||
| 473 | SectionNumber: 4 | ||
| 474 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 475 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 476 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 477 | SectionDefinition: | ||
| 478 | Length: 37 | ||
| 479 | NumberOfRelocations: 0 | ||
| 480 | NumberOfLinenumbers: 0 | ||
| 481 | CheckSum: 77530982 | ||
| 482 | Number: 4 | ||
| 483 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 484 | - Name: '??0HelloPoint@@QAE@XZ' | ||
| 485 | Value: 0 | ||
| 486 | SectionNumber: 4 | ||
| 487 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 488 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 489 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 490 | - Name: .rdata | ||
| 491 | Value: 0 | ||
| 492 | SectionNumber: 5 | ||
| 493 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 494 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 495 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 496 | SectionDefinition: | ||
| 497 | Length: 4 | ||
| 498 | NumberOfRelocations: 0 | ||
| 499 | NumberOfLinenumbers: 0 | ||
| 500 | CheckSum: 3903140090 | ||
| 501 | Number: 5 | ||
| 502 | - Name: .drectve | ||
| 503 | Value: 0 | ||
| 504 | SectionNumber: 6 | ||
| 505 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 506 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 507 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 508 | SectionDefinition: | ||
| 509 | Length: 48 | ||
| 510 | NumberOfRelocations: 0 | ||
| 511 | NumberOfLinenumbers: 0 | ||
| 512 | CheckSum: 149686238 | ||
| 513 | Number: 6 | ||
| 514 | - Name: '.debug$S' | ||
| 515 | Value: 0 | ||
| 516 | SectionNumber: 7 | ||
| 517 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 518 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 519 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 520 | SectionDefinition: | ||
| 521 | Length: 768 | ||
| 522 | NumberOfRelocations: 26 | ||
| 523 | NumberOfLinenumbers: 0 | ||
| 524 | CheckSum: 2940884584 | ||
| 525 | Number: 7 | ||
| 526 | - Name: '.debug$S' | ||
| 527 | Value: 0 | ||
| 528 | SectionNumber: 9 | ||
| 529 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 530 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 531 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 532 | SectionDefinition: | ||
| 533 | Length: 188 | ||
| 534 | NumberOfRelocations: 6 | ||
| 535 | NumberOfLinenumbers: 0 | ||
| 536 | CheckSum: 1246640575 | ||
| 537 | Number: 4 | ||
| 538 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 539 | - Name: '.debug$T' | ||
| 540 | Value: 0 | ||
| 541 | SectionNumber: 8 | ||
| 542 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 543 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 544 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 545 | SectionDefinition: | ||
| 546 | Length: 452 | ||
| 547 | NumberOfRelocations: 0 | ||
| 548 | NumberOfLinenumbers: 0 | ||
| 549 | CheckSum: 2561906059 | ||
| 550 | Number: 8 | ||
| 551 | - Name: '@feat.00' | ||
| 552 | Value: 1 | ||
| 553 | SectionNumber: -1 | ||
| 554 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 555 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 556 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 557 | - Name: '?GlobalFunc@@YAHXZ' | ||
| 558 | Value: 0 | ||
| 559 | SectionNumber: 1 | ||
| 560 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 561 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 562 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 563 | - Name: _main | ||
| 564 | Value: 16 | ||
| 565 | SectionNumber: 1 | ||
| 566 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 567 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 568 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 569 | - Name: '?LocalFunc@@YAHXZ' | ||
| 570 | Value: 128 | ||
| 571 | SectionNumber: 1 | ||
| 572 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 573 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 574 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 575 | - Name: '?GlobalVar@@3PBHB' | ||
| 576 | Value: 0 | ||
| 577 | SectionNumber: 2 | ||
| 578 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 579 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 580 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 581 | - Name: '?__purecall@@3PAXA' | ||
| 582 | Value: 0 | ||
| 583 | SectionNumber: 3 | ||
| 584 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 585 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 586 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 587 | - Name: _ConstantVar | ||
| 588 | Value: 0 | ||
| 589 | SectionNumber: 5 | ||
| 590 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 591 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 592 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 593 | ... | ||
deps/lld/test/COFF/Inputs/pdb-hashes-1.yaml created+540| ... | @@ -0,0 +1,540 @@ | ||
| 1 | --- !COFF | ||
| 2 | header: | ||
| 3 | Machine: IMAGE_FILE_MACHINE_I386 | ||
| 4 | Characteristics: [ ] | ||
| 5 | sections: | ||
| 6 | - Name: .text | ||
| 7 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 8 | Alignment: 16 | ||
| 9 | SectionData: 5589E55683EC188B450C8B4D088D55F4C745F8000000008B7508894DF089D18934248945ECE80000000083EC048D4DF4890C248945E8E80000000083C4185E5DC3 | ||
| 10 | Relocations: | ||
| 11 | - VirtualAddress: 38 | ||
| 12 | SymbolName: '??0Foo@NS@@QAE@H@Z' | ||
| 13 | Type: IMAGE_REL_I386_REL32 | ||
| 14 | - VirtualAddress: 55 | ||
| 15 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 16 | Type: IMAGE_REL_I386_REL32 | ||
| 17 | - Name: .data | ||
| 18 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 19 | Alignment: 4 | ||
| 20 | SectionData: '' | ||
| 21 | - Name: .bss | ||
| 22 | Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 23 | Alignment: 4 | ||
| 24 | SectionData: '' | ||
| 25 | - Name: .text | ||
| 26 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 27 | Alignment: 16 | ||
| 28 | SectionData: 5589E583EC088B4508894DFC8B4DFC8B550889118945F889C883C4085DC20400 | ||
| 29 | - Name: .drectve | ||
| 30 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 31 | Alignment: 1 | ||
| 32 | SectionData: 202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962 | ||
| 33 | - Name: '.debug$S' | ||
| 34 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 35 | Alignment: 4 | ||
| 36 | SectionData: 04000000F10000002F0000002D003C1101000000070006000000000000007017000000000000636C616E672076657273696F6E20362E302E30200000F50000008400000000000000000000004100000000000000080000000000000052000000070000000400000001000000400000000000000008000000000000007F0000000600040000000000030000003E000000000000000800000000000000BD0000000400040000000000040000003D000000000000000800000000000000FA0000000300080000000000F1000000960000002A00471100000000000000000000000041000000000000000000000003100000000000000000006D61696E000D003E1174000000010061726763001200451116000000080000001700000000002A000D003E11001000000100617267760012004511160000000C0000001700000000002A000A003E1109100000000066001200451116000000F4FFFFFF1700000000002A0002004F110000F200000030000000000000000000000041000000000000000300000024000000000000000300000017000000040000003000000005000000F1000000100000000E000811091000004E533A3A466F6F00F40000003000000001000000100165C9E387F88362A8EB2B49539DD5A65500002B00000010019303CF100D518DAF59C31DA01FEF4AFC0000F30000004801000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A312E63707000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A2E6800245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200024543020246562702034202B203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200024543020246562702034202B203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D2024657369202454302038202D205E203D2000 | ||
| 37 | Subsections: | ||
| 38 | - !Symbols | ||
| 39 | Records: | ||
| 40 | - Kind: S_COMPILE3 | ||
| 41 | Compile3Sym: | ||
| 42 | Flags: [ ] | ||
| 43 | Machine: Pentium3 | ||
| 44 | FrontendMajor: 6 | ||
| 45 | FrontendMinor: 0 | ||
| 46 | FrontendBuild: 0 | ||
| 47 | FrontendQFE: 0 | ||
| 48 | BackendMajor: 6000 | ||
| 49 | BackendMinor: 0 | ||
| 50 | BackendBuild: 0 | ||
| 51 | BackendQFE: 0 | ||
| 52 | Version: 'clang version 6.0.0 ' | ||
| 53 | - !FrameData | ||
| 54 | Frames: | ||
| 55 | - CodeSize: 65 | ||
| 56 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | ||
| 57 | LocalSize: 0 | ||
| 58 | MaxStackSize: 0 | ||
| 59 | ParamsSize: 8 | ||
| 60 | PrologSize: 7 | ||
| 61 | RvaStart: 0 | ||
| 62 | SavedRegsSize: 0 | ||
| 63 | - CodeSize: 64 | ||
| 64 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 65 | LocalSize: 0 | ||
| 66 | MaxStackSize: 0 | ||
| 67 | ParamsSize: 8 | ||
| 68 | PrologSize: 6 | ||
| 69 | RvaStart: 1 | ||
| 70 | SavedRegsSize: 4 | ||
| 71 | - CodeSize: 62 | ||
| 72 | FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 73 | LocalSize: 0 | ||
| 74 | MaxStackSize: 0 | ||
| 75 | ParamsSize: 8 | ||
| 76 | PrologSize: 4 | ||
| 77 | RvaStart: 3 | ||
| 78 | SavedRegsSize: 4 | ||
| 79 | - CodeSize: 61 | ||
| 80 | FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $esi $T0 8 - ^ = ' | ||
| 81 | LocalSize: 0 | ||
| 82 | MaxStackSize: 0 | ||
| 83 | ParamsSize: 8 | ||
| 84 | PrologSize: 3 | ||
| 85 | RvaStart: 4 | ||
| 86 | SavedRegsSize: 8 | ||
| 87 | - !Symbols | ||
| 88 | Records: | ||
| 89 | - Kind: S_GPROC32_ID | ||
| 90 | ProcSym: | ||
| 91 | CodeSize: 65 | ||
| 92 | DbgStart: 0 | ||
| 93 | DbgEnd: 0 | ||
| 94 | FunctionType: 4099 | ||
| 95 | Flags: [ ] | ||
| 96 | DisplayName: main | ||
| 97 | - Kind: S_LOCAL | ||
| 98 | LocalSym: | ||
| 99 | Type: 116 | ||
| 100 | Flags: [ IsParameter ] | ||
| 101 | VarName: argc | ||
| 102 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 103 | DefRangeRegisterRelSym: | ||
| 104 | - Kind: S_LOCAL | ||
| 105 | LocalSym: | ||
| 106 | Type: 4096 | ||
| 107 | Flags: [ IsParameter ] | ||
| 108 | VarName: argv | ||
| 109 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 110 | DefRangeRegisterRelSym: | ||
| 111 | - Kind: S_LOCAL | ||
| 112 | LocalSym: | ||
| 113 | Type: 4105 | ||
| 114 | Flags: [ ] | ||
| 115 | VarName: f | ||
| 116 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 117 | DefRangeRegisterRelSym: | ||
| 118 | - Kind: S_PROC_ID_END | ||
| 119 | ScopeEndSym: | ||
| 120 | - !Lines | ||
| 121 | CodeSize: 65 | ||
| 122 | Flags: [ ] | ||
| 123 | RelocOffset: 0 | ||
| 124 | RelocSegment: 0 | ||
| 125 | Blocks: | ||
| 126 | - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj1.cpp' | ||
| 127 | Lines: | ||
| 128 | - Offset: 0 | ||
| 129 | LineStart: 3 | ||
| 130 | IsStatement: false | ||
| 131 | EndDelta: 0 | ||
| 132 | - Offset: 23 | ||
| 133 | LineStart: 4 | ||
| 134 | IsStatement: false | ||
| 135 | EndDelta: 0 | ||
| 136 | - Offset: 48 | ||
| 137 | LineStart: 5 | ||
| 138 | IsStatement: false | ||
| 139 | EndDelta: 0 | ||
| 140 | Columns: | ||
| 141 | - !Symbols | ||
| 142 | Records: | ||
| 143 | - Kind: S_UDT | ||
| 144 | UDTSym: | ||
| 145 | Type: 4105 | ||
| 146 | UDTName: 'NS::Foo' | ||
| 147 | - !FileChecksums | ||
| 148 | Checksums: | ||
| 149 | - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj1.cpp' | ||
| 150 | Kind: MD5 | ||
| 151 | Checksum: 65C9E387F88362A8EB2B49539DD5A655 | ||
| 152 | - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj.h' | ||
| 153 | Kind: MD5 | ||
| 154 | Checksum: 9303CF100D518DAF59C31DA01FEF4AFC | ||
| 155 | - !StringTable | ||
| 156 | Strings: | ||
| 157 | - 'D:\src\llvmbuild\clang\Debug\x86\obj1.cpp' | ||
| 158 | - 'D:\src\llvmbuild\clang\Debug\x86\obj.h' | ||
| 159 | - '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | ||
| 160 | - '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 161 | - '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 162 | - '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $esi $T0 8 - ^ = ' | ||
| 163 | Relocations: | ||
| 164 | - VirtualAddress: 68 | ||
| 165 | SymbolName: _main | ||
| 166 | Type: IMAGE_REL_I386_DIR32NB | ||
| 167 | - VirtualAddress: 240 | ||
| 168 | SymbolName: _main | ||
| 169 | Type: IMAGE_REL_I386_SECREL | ||
| 170 | - VirtualAddress: 244 | ||
| 171 | SymbolName: _main | ||
| 172 | Type: IMAGE_REL_I386_SECTION | ||
| 173 | - VirtualAddress: 279 | ||
| 174 | SymbolName: .text | ||
| 175 | Type: IMAGE_REL_I386_SECREL | ||
| 176 | - VirtualAddress: 283 | ||
| 177 | SymbolName: .text | ||
| 178 | Type: IMAGE_REL_I386_SECTION | ||
| 179 | - VirtualAddress: 314 | ||
| 180 | SymbolName: .text | ||
| 181 | Type: IMAGE_REL_I386_SECREL | ||
| 182 | - VirtualAddress: 318 | ||
| 183 | SymbolName: .text | ||
| 184 | Type: IMAGE_REL_I386_SECTION | ||
| 185 | - VirtualAddress: 346 | ||
| 186 | SymbolName: .text | ||
| 187 | Type: IMAGE_REL_I386_SECREL | ||
| 188 | - VirtualAddress: 350 | ||
| 189 | SymbolName: .text | ||
| 190 | Type: IMAGE_REL_I386_SECTION | ||
| 191 | - VirtualAddress: 368 | ||
| 192 | SymbolName: _main | ||
| 193 | Type: IMAGE_REL_I386_SECREL | ||
| 194 | - VirtualAddress: 372 | ||
| 195 | SymbolName: _main | ||
| 196 | Type: IMAGE_REL_I386_SECTION | ||
| 197 | - Name: '.debug$T' | ||
| 198 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 199 | Alignment: 4 | ||
| 200 | SectionData: 040000000A000210700400000A8000000E0001120200000074000000001000000E0008107400000000000200011000001200011600000000021000006D61696E00F3F2F12A0005150000800200000000000000000000000000004E533A3A466F6F002E3F4155466F6F404E53404000F10A000210041000000A8000000A00011201000000740000001A0009100300000004100000051000000B00010006100000000000001A0003120D15030074000000000058001115030007100000466F6F002A0005150200000208100000000000000000000004004E533A3A466F6F002E3F4155466F6F404E53404000F12E00051600000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A2E6800F10E000616091000000A100000020000000E0002160410000007100000466F6F00 | ||
| 201 | Types: | ||
| 202 | - Kind: LF_POINTER | ||
| 203 | Pointer: | ||
| 204 | ReferentType: 1136 | ||
| 205 | Attrs: 32778 | ||
| 206 | - Kind: LF_ARGLIST | ||
| 207 | ArgList: | ||
| 208 | ArgIndices: [ 116, 4096 ] | ||
| 209 | - Kind: LF_PROCEDURE | ||
| 210 | Procedure: | ||
| 211 | ReturnType: 116 | ||
| 212 | CallConv: NearC | ||
| 213 | Options: [ None ] | ||
| 214 | ParameterCount: 2 | ||
| 215 | ArgumentList: 4097 | ||
| 216 | - Kind: LF_FUNC_ID | ||
| 217 | FuncId: | ||
| 218 | ParentScope: 0 | ||
| 219 | FunctionType: 4098 | ||
| 220 | Name: main | ||
| 221 | - Kind: LF_STRUCTURE | ||
| 222 | Class: | ||
| 223 | MemberCount: 0 | ||
| 224 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 225 | FieldList: 0 | ||
| 226 | Name: 'NS::Foo' | ||
| 227 | UniqueName: '.?AUFoo@NS@@' | ||
| 228 | DerivationList: 0 | ||
| 229 | VTableShape: 0 | ||
| 230 | Size: 0 | ||
| 231 | - Kind: LF_POINTER | ||
| 232 | Pointer: | ||
| 233 | ReferentType: 4100 | ||
| 234 | Attrs: 32778 | ||
| 235 | - Kind: LF_ARGLIST | ||
| 236 | ArgList: | ||
| 237 | ArgIndices: [ 116 ] | ||
| 238 | - Kind: LF_MFUNCTION | ||
| 239 | MemberFunction: | ||
| 240 | ReturnType: 3 | ||
| 241 | ClassType: 4100 | ||
| 242 | ThisType: 4101 | ||
| 243 | CallConv: ThisCall | ||
| 244 | Options: [ None ] | ||
| 245 | ParameterCount: 1 | ||
| 246 | ArgumentList: 4102 | ||
| 247 | ThisPointerAdjustment: 0 | ||
| 248 | - Kind: LF_FIELDLIST | ||
| 249 | FieldList: | ||
| 250 | - Kind: LF_MEMBER | ||
| 251 | DataMember: | ||
| 252 | Attrs: 3 | ||
| 253 | Type: 116 | ||
| 254 | FieldOffset: 0 | ||
| 255 | Name: X | ||
| 256 | - Kind: LF_ONEMETHOD | ||
| 257 | OneMethod: | ||
| 258 | Type: 4103 | ||
| 259 | Attrs: 3 | ||
| 260 | VFTableOffset: -1 | ||
| 261 | Name: Foo | ||
| 262 | - Kind: LF_STRUCTURE | ||
| 263 | Class: | ||
| 264 | MemberCount: 2 | ||
| 265 | Options: [ None, HasUniqueName ] | ||
| 266 | FieldList: 4104 | ||
| 267 | Name: 'NS::Foo' | ||
| 268 | UniqueName: '.?AUFoo@NS@@' | ||
| 269 | DerivationList: 0 | ||
| 270 | VTableShape: 0 | ||
| 271 | Size: 4 | ||
| 272 | - Kind: LF_STRING_ID | ||
| 273 | StringId: | ||
| 274 | Id: 0 | ||
| 275 | String: 'D:\src\llvmbuild\clang\Debug\x86\obj.h' | ||
| 276 | - Kind: LF_UDT_SRC_LINE | ||
| 277 | UdtSourceLine: | ||
| 278 | UDT: 4105 | ||
| 279 | SourceFile: 4106 | ||
| 280 | LineNumber: 2 | ||
| 281 | - Kind: LF_MFUNC_ID | ||
| 282 | MemberFuncId: | ||
| 283 | ClassType: 4100 | ||
| 284 | FunctionType: 4103 | ||
| 285 | Name: Foo | ||
| 286 | - Name: '.debug$H' | ||
| 287 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 288 | Alignment: 4 | ||
| 289 | SectionData: C5C93301000000009E56666824DC4B12E25261D4E09E6E9DA0F4EE31FDEC3D2D96287486127C66070B248ED52E421F55074AE5CC2D68AF9F0A3BEF23993968F7FD82CA84BF0439C1A64C9070C6A6ADB0A34D21DAD0FFC3E99E616EF06A14EA74A2420F9062A1FB04917E5975E3A50EABE5E8FE3945468547C19DC681D0BFB3B797DD91CA4D7F1953C314442D5549419E78044E38A0BF16BFFAA5EE9C0103E7DBFE9941E63379C0B0C0A9021B711ACC4F67008974EBF441031BDD653F6935DFF3112C6A5346EF2AC94B9B7EB56EF55CFA0AF6C1846743F43D846BB19517E12E8873BBA90CC41DD1BEAC89CBA8897AC1BA46762E2557A82D894CEAE81AEF8680D723D403D9A4481F0E28683A98 | ||
| 290 | GlobalHashes: | ||
| 291 | Version: 0 | ||
| 292 | HashAlgorithm: 0 | ||
| 293 | HashValues: | ||
| 294 | - 9E56666824DC4B12E25261D4E09E6E9DA0F4EE31 | ||
| 295 | - FDEC3D2D96287486127C66070B248ED52E421F55 | ||
| 296 | - 074AE5CC2D68AF9F0A3BEF23993968F7FD82CA84 | ||
| 297 | - BF0439C1A64C9070C6A6ADB0A34D21DAD0FFC3E9 | ||
| 298 | - 9E616EF06A14EA74A2420F9062A1FB04917E5975 | ||
| 299 | - E3A50EABE5E8FE3945468547C19DC681D0BFB3B7 | ||
| 300 | - 97DD91CA4D7F1953C314442D5549419E78044E38 | ||
| 301 | - A0BF16BFFAA5EE9C0103E7DBFE9941E63379C0B0 | ||
| 302 | - C0A9021B711ACC4F67008974EBF441031BDD653F | ||
| 303 | - 6935DFF3112C6A5346EF2AC94B9B7EB56EF55CFA | ||
| 304 | - 0AF6C1846743F43D846BB19517E12E8873BBA90C | ||
| 305 | - C41DD1BEAC89CBA8897AC1BA46762E2557A82D89 | ||
| 306 | - 4CEAE81AEF8680D723D403D9A4481F0E28683A98 | ||
| 307 | - Name: '.debug$S' | ||
| 308 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 309 | Alignment: 4 | ||
| 310 | SectionData: 04000000F500000064000000000000000000000020000000000000000400000000000000520000000600000004000000010000001F0000000000000004000000000000007F0000000500040000000000030000001D000000000000000400000000000000BD0000000300040000000000F10000007B000000320047110000000000000000000000002000000000000000000000000C100000000000000000004E533A3A466F6F3A3A466F6F000D003E1105100000010074686973001200451116000000FCFFFFFF0F000000000011000A003E1174000000010078001200451116000000080000000F0000000000110002004F1100F2000000200000000000000000000000200000001800000001000000140000000000000003000000 | ||
| 311 | Subsections: | ||
| 312 | - !FrameData | ||
| 313 | Frames: | ||
| 314 | - CodeSize: 32 | ||
| 315 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | ||
| 316 | LocalSize: 0 | ||
| 317 | MaxStackSize: 0 | ||
| 318 | ParamsSize: 4 | ||
| 319 | PrologSize: 6 | ||
| 320 | RvaStart: 0 | ||
| 321 | SavedRegsSize: 0 | ||
| 322 | - CodeSize: 31 | ||
| 323 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 324 | LocalSize: 0 | ||
| 325 | MaxStackSize: 0 | ||
| 326 | ParamsSize: 4 | ||
| 327 | PrologSize: 5 | ||
| 328 | RvaStart: 1 | ||
| 329 | SavedRegsSize: 4 | ||
| 330 | - CodeSize: 29 | ||
| 331 | FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 332 | LocalSize: 0 | ||
| 333 | MaxStackSize: 0 | ||
| 334 | ParamsSize: 4 | ||
| 335 | PrologSize: 3 | ||
| 336 | RvaStart: 3 | ||
| 337 | SavedRegsSize: 4 | ||
| 338 | - !Symbols | ||
| 339 | Records: | ||
| 340 | - Kind: S_GPROC32_ID | ||
| 341 | ProcSym: | ||
| 342 | CodeSize: 32 | ||
| 343 | DbgStart: 0 | ||
| 344 | DbgEnd: 0 | ||
| 345 | FunctionType: 4108 | ||
| 346 | Flags: [ ] | ||
| 347 | DisplayName: 'NS::Foo::Foo' | ||
| 348 | - Kind: S_LOCAL | ||
| 349 | LocalSym: | ||
| 350 | Type: 4101 | ||
| 351 | Flags: [ IsParameter ] | ||
| 352 | VarName: this | ||
| 353 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 354 | DefRangeRegisterRelSym: | ||
| 355 | - Kind: S_LOCAL | ||
| 356 | LocalSym: | ||
| 357 | Type: 116 | ||
| 358 | Flags: [ IsParameter ] | ||
| 359 | VarName: x | ||
| 360 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 361 | DefRangeRegisterRelSym: | ||
| 362 | - Kind: S_PROC_ID_END | ||
| 363 | ScopeEndSym: | ||
| 364 | - !Lines | ||
| 365 | CodeSize: 32 | ||
| 366 | Flags: [ ] | ||
| 367 | RelocOffset: 0 | ||
| 368 | RelocSegment: 0 | ||
| 369 | Blocks: | ||
| 370 | - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj.h' | ||
| 371 | Lines: | ||
| 372 | - Offset: 0 | ||
| 373 | LineStart: 3 | ||
| 374 | IsStatement: false | ||
| 375 | EndDelta: 0 | ||
| 376 | Columns: | ||
| 377 | Relocations: | ||
| 378 | - VirtualAddress: 12 | ||
| 379 | SymbolName: '??0Foo@NS@@QAE@H@Z' | ||
| 380 | Type: IMAGE_REL_I386_DIR32NB | ||
| 381 | - VirtualAddress: 152 | ||
| 382 | SymbolName: '??0Foo@NS@@QAE@H@Z' | ||
| 383 | Type: IMAGE_REL_I386_SECREL | ||
| 384 | - VirtualAddress: 156 | ||
| 385 | SymbolName: '??0Foo@NS@@QAE@H@Z' | ||
| 386 | Type: IMAGE_REL_I386_SECTION | ||
| 387 | - VirtualAddress: 199 | ||
| 388 | SymbolName: .text | ||
| 389 | Type: IMAGE_REL_I386_SECREL | ||
| 390 | - VirtualAddress: 203 | ||
| 391 | SymbolName: .text | ||
| 392 | Type: IMAGE_REL_I386_SECTION | ||
| 393 | - VirtualAddress: 231 | ||
| 394 | SymbolName: .text | ||
| 395 | Type: IMAGE_REL_I386_SECREL | ||
| 396 | - VirtualAddress: 235 | ||
| 397 | SymbolName: .text | ||
| 398 | Type: IMAGE_REL_I386_SECTION | ||
| 399 | - VirtualAddress: 252 | ||
| 400 | SymbolName: '??0Foo@NS@@QAE@H@Z' | ||
| 401 | Type: IMAGE_REL_I386_SECREL | ||
| 402 | - VirtualAddress: 256 | ||
| 403 | SymbolName: '??0Foo@NS@@QAE@H@Z' | ||
| 404 | Type: IMAGE_REL_I386_SECTION | ||
| 405 | symbols: | ||
| 406 | - Name: .text | ||
| 407 | Value: 0 | ||
| 408 | SectionNumber: 1 | ||
| 409 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 410 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 411 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 412 | SectionDefinition: | ||
| 413 | Length: 65 | ||
| 414 | NumberOfRelocations: 2 | ||
| 415 | NumberOfLinenumbers: 0 | ||
| 416 | CheckSum: 4176946275 | ||
| 417 | Number: 1 | ||
| 418 | - Name: .data | ||
| 419 | Value: 0 | ||
| 420 | SectionNumber: 2 | ||
| 421 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 422 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 423 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 424 | SectionDefinition: | ||
| 425 | Length: 0 | ||
| 426 | NumberOfRelocations: 0 | ||
| 427 | NumberOfLinenumbers: 0 | ||
| 428 | CheckSum: 0 | ||
| 429 | Number: 2 | ||
| 430 | - Name: .bss | ||
| 431 | Value: 0 | ||
| 432 | SectionNumber: 3 | ||
| 433 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 434 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 435 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 436 | SectionDefinition: | ||
| 437 | Length: 0 | ||
| 438 | NumberOfRelocations: 0 | ||
| 439 | NumberOfLinenumbers: 0 | ||
| 440 | CheckSum: 0 | ||
| 441 | Number: 3 | ||
| 442 | - Name: .text | ||
| 443 | Value: 0 | ||
| 444 | SectionNumber: 4 | ||
| 445 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 446 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 447 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 448 | SectionDefinition: | ||
| 449 | Length: 32 | ||
| 450 | NumberOfRelocations: 0 | ||
| 451 | NumberOfLinenumbers: 0 | ||
| 452 | CheckSum: 1438182552 | ||
| 453 | Number: 4 | ||
| 454 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 455 | - Name: '??0Foo@NS@@QAE@H@Z' | ||
| 456 | Value: 0 | ||
| 457 | SectionNumber: 4 | ||
| 458 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 459 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 460 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 461 | - Name: .drectve | ||
| 462 | Value: 0 | ||
| 463 | SectionNumber: 5 | ||
| 464 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 465 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 466 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 467 | SectionDefinition: | ||
| 468 | Length: 48 | ||
| 469 | NumberOfRelocations: 0 | ||
| 470 | NumberOfLinenumbers: 0 | ||
| 471 | CheckSum: 149686238 | ||
| 472 | Number: 5 | ||
| 473 | - Name: '.debug$S' | ||
| 474 | Value: 0 | ||
| 475 | SectionNumber: 6 | ||
| 476 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 477 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 478 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 479 | SectionDefinition: | ||
| 480 | Length: 832 | ||
| 481 | NumberOfRelocations: 11 | ||
| 482 | NumberOfLinenumbers: 0 | ||
| 483 | CheckSum: 4106171226 | ||
| 484 | Number: 6 | ||
| 485 | - Name: '.debug$S' | ||
| 486 | Value: 0 | ||
| 487 | SectionNumber: 9 | ||
| 488 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 489 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 490 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 491 | SectionDefinition: | ||
| 492 | Length: 284 | ||
| 493 | NumberOfRelocations: 9 | ||
| 494 | NumberOfLinenumbers: 0 | ||
| 495 | CheckSum: 1378739251 | ||
| 496 | Number: 4 | ||
| 497 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 498 | - Name: '.debug$T' | ||
| 499 | Value: 0 | ||
| 500 | SectionNumber: 7 | ||
| 501 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 502 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 503 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 504 | SectionDefinition: | ||
| 505 | Length: 316 | ||
| 506 | NumberOfRelocations: 0 | ||
| 507 | NumberOfLinenumbers: 0 | ||
| 508 | CheckSum: 3343977630 | ||
| 509 | Number: 7 | ||
| 510 | - Name: '.debug$H' | ||
| 511 | Value: 0 | ||
| 512 | SectionNumber: 8 | ||
| 513 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 514 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 515 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 516 | SectionDefinition: | ||
| 517 | Length: 268 | ||
| 518 | NumberOfRelocations: 0 | ||
| 519 | NumberOfLinenumbers: 0 | ||
| 520 | CheckSum: 3965031229 | ||
| 521 | Number: 8 | ||
| 522 | - Name: '@feat.00' | ||
| 523 | Value: 1 | ||
| 524 | SectionNumber: -1 | ||
| 525 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 526 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 527 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 528 | - Name: _main | ||
| 529 | Value: 0 | ||
| 530 | SectionNumber: 1 | ||
| 531 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 532 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 533 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 534 | - Name: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 535 | Value: 0 | ||
| 536 | SectionNumber: 0 | ||
| 537 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 538 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 539 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 540 | ... | ||
deps/lld/test/COFF/Inputs/pdb-hashes-2-missing.yaml created+321| ... | @@ -0,0 +1,321 @@ | ||
| 1 | --- !COFF | ||
| 2 | header: | ||
| 3 | Machine: IMAGE_FILE_MACHINE_I386 | ||
| 4 | Characteristics: [ ] | ||
| 5 | sections: | ||
| 6 | - Name: .text | ||
| 7 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 8 | Alignment: 16 | ||
| 9 | SectionData: 5589E5508B45088B4D088B09C1E1018945FC89C883C4045DC3 | ||
| 10 | - Name: .data | ||
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 12 | Alignment: 4 | ||
| 13 | SectionData: '' | ||
| 14 | - Name: .bss | ||
| 15 | Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 16 | Alignment: 4 | ||
| 17 | SectionData: '' | ||
| 18 | - Name: .drectve | ||
| 19 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 20 | Alignment: 1 | ||
| 21 | SectionData: 202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962 | ||
| 22 | - Name: '.debug$S' | ||
| 23 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 24 | Alignment: 4 | ||
| 25 | SectionData: 04000000F10000002F0000002D003C1101000000070006000000000000007017000000000000636C616E672076657273696F6E20362E302E30200000F5000000640000000000000000000000190000000000000004000000000000002B000000040000000400000001000000180000000000000004000000000000005800000003000400000000000300000016000000000000000400000000000000960000000100040000000000F1000000540000002E0047110000000000000000000000001900000000000000000000000D100000000000000000004E533A3A66756E63000A003E110310000001006600120045111600000008000000070000000000120002004F11F20000002800000000000000000000001900000000000000020000001C00000000000000030000000700000004000000F1000000100000000E0008110A1000004E533A3A466F6F00F40000001800000001000000100159DFAC75D18675AED1AD169FE316317E0000F3000000D400000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A322E63707000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200024543020246562702034202B203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200000 | ||
| 26 | Subsections: | ||
| 27 | - !Symbols | ||
| 28 | Records: | ||
| 29 | - Kind: S_COMPILE3 | ||
| 30 | Compile3Sym: | ||
| 31 | Flags: [ ] | ||
| 32 | Machine: Pentium3 | ||
| 33 | FrontendMajor: 6 | ||
| 34 | FrontendMinor: 0 | ||
| 35 | FrontendBuild: 0 | ||
| 36 | FrontendQFE: 0 | ||
| 37 | BackendMajor: 6000 | ||
| 38 | BackendMinor: 0 | ||
| 39 | BackendBuild: 0 | ||
| 40 | BackendQFE: 0 | ||
| 41 | Version: 'clang version 6.0.0 ' | ||
| 42 | - !FrameData | ||
| 43 | Frames: | ||
| 44 | - CodeSize: 25 | ||
| 45 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | ||
| 46 | LocalSize: 0 | ||
| 47 | MaxStackSize: 0 | ||
| 48 | ParamsSize: 4 | ||
| 49 | PrologSize: 4 | ||
| 50 | RvaStart: 0 | ||
| 51 | SavedRegsSize: 0 | ||
| 52 | - CodeSize: 24 | ||
| 53 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 54 | LocalSize: 0 | ||
| 55 | MaxStackSize: 0 | ||
| 56 | ParamsSize: 4 | ||
| 57 | PrologSize: 3 | ||
| 58 | RvaStart: 1 | ||
| 59 | SavedRegsSize: 4 | ||
| 60 | - CodeSize: 22 | ||
| 61 | FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 62 | LocalSize: 0 | ||
| 63 | MaxStackSize: 0 | ||
| 64 | ParamsSize: 4 | ||
| 65 | PrologSize: 1 | ||
| 66 | RvaStart: 3 | ||
| 67 | SavedRegsSize: 4 | ||
| 68 | - !Symbols | ||
| 69 | Records: | ||
| 70 | - Kind: S_GPROC32_ID | ||
| 71 | ProcSym: | ||
| 72 | CodeSize: 25 | ||
| 73 | DbgStart: 0 | ||
| 74 | DbgEnd: 0 | ||
| 75 | FunctionType: 4109 | ||
| 76 | Flags: [ ] | ||
| 77 | DisplayName: 'NS::func' | ||
| 78 | - Kind: S_LOCAL | ||
| 79 | LocalSym: | ||
| 80 | Type: 4099 | ||
| 81 | Flags: [ IsParameter ] | ||
| 82 | VarName: f | ||
| 83 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 84 | DefRangeRegisterRelSym: | ||
| 85 | - Kind: S_PROC_ID_END | ||
| 86 | ScopeEndSym: | ||
| 87 | - !Lines | ||
| 88 | CodeSize: 25 | ||
| 89 | Flags: [ ] | ||
| 90 | RelocOffset: 0 | ||
| 91 | RelocSegment: 0 | ||
| 92 | Blocks: | ||
| 93 | - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp' | ||
| 94 | Lines: | ||
| 95 | - Offset: 0 | ||
| 96 | LineStart: 3 | ||
| 97 | IsStatement: false | ||
| 98 | EndDelta: 0 | ||
| 99 | - Offset: 7 | ||
| 100 | LineStart: 4 | ||
| 101 | IsStatement: false | ||
| 102 | EndDelta: 0 | ||
| 103 | Columns: | ||
| 104 | - !Symbols | ||
| 105 | Records: | ||
| 106 | - Kind: S_UDT | ||
| 107 | UDTSym: | ||
| 108 | Type: 4106 | ||
| 109 | UDTName: 'NS::Foo' | ||
| 110 | - !FileChecksums | ||
| 111 | Checksums: | ||
| 112 | - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp' | ||
| 113 | Kind: MD5 | ||
| 114 | Checksum: 59DFAC75D18675AED1AD169FE316317E | ||
| 115 | - !StringTable | ||
| 116 | Strings: | ||
| 117 | - 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp' | ||
| 118 | - '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | ||
| 119 | - '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 120 | - '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 121 | - '' | ||
| 122 | Relocations: | ||
| 123 | - VirtualAddress: 68 | ||
| 124 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 125 | Type: IMAGE_REL_I386_DIR32NB | ||
| 126 | - VirtualAddress: 208 | ||
| 127 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 128 | Type: IMAGE_REL_I386_SECREL | ||
| 129 | - VirtualAddress: 212 | ||
| 130 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 131 | Type: IMAGE_REL_I386_SECTION | ||
| 132 | - VirtualAddress: 248 | ||
| 133 | SymbolName: .text | ||
| 134 | Type: IMAGE_REL_I386_SECREL | ||
| 135 | - VirtualAddress: 252 | ||
| 136 | SymbolName: .text | ||
| 137 | Type: IMAGE_REL_I386_SECTION | ||
| 138 | - VirtualAddress: 268 | ||
| 139 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 140 | Type: IMAGE_REL_I386_SECREL | ||
| 141 | - VirtualAddress: 272 | ||
| 142 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 143 | Type: IMAGE_REL_I386_SECTION | ||
| 144 | - Name: '.debug$T' | ||
| 145 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 146 | Alignment: 4 | ||
| 147 | SectionData: 040000000A000516000000004E5300F12A0005150000800200000000000000000000000000004E533A3A466F6F002E3F4155466F6F404E53404000F10A000110011000000100F2F10A000210021000002A8000000A00011201000000031000000E0008107400000000000100041000000A000210011000000A8000000A00011201000000740000001A0009100300000001100000061000000B00010007100000000000001A0003120D15030074000000000058001115030008100000466F6F002A0005150200000209100000000000000000000004004E533A3A466F6F002E3F4155466F6F404E53404000F12E00051600000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A2E6800F10E0006160A1000000B1000000200000012000116001000000510000066756E6300F3F2F1 | ||
| 148 | Types: | ||
| 149 | - Kind: LF_STRING_ID | ||
| 150 | StringId: | ||
| 151 | Id: 0 | ||
| 152 | String: NS | ||
| 153 | - Kind: LF_STRUCTURE | ||
| 154 | Class: | ||
| 155 | MemberCount: 0 | ||
| 156 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 157 | FieldList: 0 | ||
| 158 | Name: 'NS::Foo' | ||
| 159 | UniqueName: '.?AUFoo@NS@@' | ||
| 160 | DerivationList: 0 | ||
| 161 | VTableShape: 0 | ||
| 162 | Size: 0 | ||
| 163 | - Kind: LF_MODIFIER | ||
| 164 | Modifier: | ||
| 165 | ModifiedType: 4097 | ||
| 166 | Modifiers: [ None, Const ] | ||
| 167 | - Kind: LF_POINTER | ||
| 168 | Pointer: | ||
| 169 | ReferentType: 4098 | ||
| 170 | Attrs: 32810 | ||
| 171 | - Kind: LF_ARGLIST | ||
| 172 | ArgList: | ||
| 173 | ArgIndices: [ 4099 ] | ||
| 174 | - Kind: LF_PROCEDURE | ||
| 175 | Procedure: | ||
| 176 | ReturnType: 116 | ||
| 177 | CallConv: NearC | ||
| 178 | Options: [ None ] | ||
| 179 | ParameterCount: 1 | ||
| 180 | ArgumentList: 4100 | ||
| 181 | - Kind: LF_POINTER | ||
| 182 | Pointer: | ||
| 183 | ReferentType: 4097 | ||
| 184 | Attrs: 32778 | ||
| 185 | - Kind: LF_ARGLIST | ||
| 186 | ArgList: | ||
| 187 | ArgIndices: [ 116 ] | ||
| 188 | - Kind: LF_MFUNCTION | ||
| 189 | MemberFunction: | ||
| 190 | ReturnType: 3 | ||
| 191 | ClassType: 4097 | ||
| 192 | ThisType: 4102 | ||
| 193 | CallConv: ThisCall | ||
| 194 | Options: [ None ] | ||
| 195 | ParameterCount: 1 | ||
| 196 | ArgumentList: 4103 | ||
| 197 | ThisPointerAdjustment: 0 | ||
| 198 | - Kind: LF_FIELDLIST | ||
| 199 | FieldList: | ||
| 200 | - Kind: LF_MEMBER | ||
| 201 | DataMember: | ||
| 202 | Attrs: 3 | ||
| 203 | Type: 116 | ||
| 204 | FieldOffset: 0 | ||
| 205 | Name: X | ||
| 206 | - Kind: LF_ONEMETHOD | ||
| 207 | OneMethod: | ||
| 208 | Type: 4104 | ||
| 209 | Attrs: 3 | ||
| 210 | VFTableOffset: -1 | ||
| 211 | Name: Foo | ||
| 212 | - Kind: LF_STRUCTURE | ||
| 213 | Class: | ||
| 214 | MemberCount: 2 | ||
| 215 | Options: [ None, HasUniqueName ] | ||
| 216 | FieldList: 4105 | ||
| 217 | Name: 'NS::Foo' | ||
| 218 | UniqueName: '.?AUFoo@NS@@' | ||
| 219 | DerivationList: 0 | ||
| 220 | VTableShape: 0 | ||
| 221 | Size: 4 | ||
| 222 | - Kind: LF_STRING_ID | ||
| 223 | StringId: | ||
| 224 | Id: 0 | ||
| 225 | String: 'D:\src\llvmbuild\clang\Debug\x86\obj.h' | ||
| 226 | - Kind: LF_UDT_SRC_LINE | ||
| 227 | UdtSourceLine: | ||
| 228 | UDT: 4106 | ||
| 229 | SourceFile: 4107 | ||
| 230 | LineNumber: 2 | ||
| 231 | - Kind: LF_FUNC_ID | ||
| 232 | FuncId: | ||
| 233 | ParentScope: 4096 | ||
| 234 | FunctionType: 4101 | ||
| 235 | Name: func | ||
| 236 | symbols: | ||
| 237 | - Name: .text | ||
| 238 | Value: 0 | ||
| 239 | SectionNumber: 1 | ||
| 240 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 241 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 242 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 243 | SectionDefinition: | ||
| 244 | Length: 25 | ||
| 245 | NumberOfRelocations: 0 | ||
| 246 | NumberOfLinenumbers: 0 | ||
| 247 | CheckSum: 1820185021 | ||
| 248 | Number: 1 | ||
| 249 | - Name: .data | ||
| 250 | Value: 0 | ||
| 251 | SectionNumber: 2 | ||
| 252 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 253 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 254 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 255 | SectionDefinition: | ||
| 256 | Length: 0 | ||
| 257 | NumberOfRelocations: 0 | ||
| 258 | NumberOfLinenumbers: 0 | ||
| 259 | CheckSum: 0 | ||
| 260 | Number: 2 | ||
| 261 | - Name: .bss | ||
| 262 | Value: 0 | ||
| 263 | SectionNumber: 3 | ||
| 264 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 265 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 266 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 267 | SectionDefinition: | ||
| 268 | Length: 0 | ||
| 269 | NumberOfRelocations: 0 | ||
| 270 | NumberOfLinenumbers: 0 | ||
| 271 | CheckSum: 0 | ||
| 272 | Number: 3 | ||
| 273 | - Name: .drectve | ||
| 274 | Value: 0 | ||
| 275 | SectionNumber: 4 | ||
| 276 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 277 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 278 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 279 | SectionDefinition: | ||
| 280 | Length: 48 | ||
| 281 | NumberOfRelocations: 0 | ||
| 282 | NumberOfLinenumbers: 0 | ||
| 283 | CheckSum: 149686238 | ||
| 284 | Number: 4 | ||
| 285 | - Name: '.debug$S' | ||
| 286 | Value: 0 | ||
| 287 | SectionNumber: 5 | ||
| 288 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 289 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 290 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 291 | SectionDefinition: | ||
| 292 | Length: 584 | ||
| 293 | NumberOfRelocations: 7 | ||
| 294 | NumberOfLinenumbers: 0 | ||
| 295 | CheckSum: 2847177244 | ||
| 296 | Number: 5 | ||
| 297 | - Name: '.debug$T' | ||
| 298 | Value: 0 | ||
| 299 | SectionNumber: 6 | ||
| 300 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 301 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 302 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 303 | SectionDefinition: | ||
| 304 | Length: 320 | ||
| 305 | NumberOfRelocations: 0 | ||
| 306 | NumberOfLinenumbers: 0 | ||
| 307 | CheckSum: 2684556216 | ||
| 308 | Number: 6 | ||
| 309 | - Name: '@feat.00' | ||
| 310 | Value: 1 | ||
| 311 | SectionNumber: -1 | ||
| 312 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 313 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 314 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 315 | - Name: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 316 | Value: 0 | ||
| 317 | SectionNumber: 1 | ||
| 318 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 319 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 320 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 321 | ... | ||
deps/lld/test/COFF/Inputs/pdb-hashes-2.yaml created+355| ... | @@ -0,0 +1,355 @@ | ||
| 1 | --- !COFF | ||
| 2 | header: | ||
| 3 | Machine: IMAGE_FILE_MACHINE_I386 | ||
| 4 | Characteristics: [ ] | ||
| 5 | sections: | ||
| 6 | - Name: .text | ||
| 7 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 8 | Alignment: 16 | ||
| 9 | SectionData: 5589E5508B45088B4D088B09C1E1018945FC89C883C4045DC3 | ||
| 10 | - Name: .data | ||
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 12 | Alignment: 4 | ||
| 13 | SectionData: '' | ||
| 14 | - Name: .bss | ||
| 15 | Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 16 | Alignment: 4 | ||
| 17 | SectionData: '' | ||
| 18 | - Name: .drectve | ||
| 19 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 20 | Alignment: 1 | ||
| 21 | SectionData: 202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962 | ||
| 22 | - Name: '.debug$S' | ||
| 23 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 24 | Alignment: 4 | ||
| 25 | SectionData: 04000000F10000002F0000002D003C1101000000070006000000000000007017000000000000636C616E672076657273696F6E20362E302E30200000F5000000640000000000000000000000190000000000000004000000000000002B000000040000000400000001000000180000000000000004000000000000005800000003000400000000000300000016000000000000000400000000000000960000000100040000000000F1000000540000002E0047110000000000000000000000001900000000000000000000000D100000000000000000004E533A3A66756E63000A003E110310000001006600120045111600000008000000070000000000120002004F11F20000002800000000000000000000001900000000000000020000001C00000000000000030000000700000004000000F1000000100000000E0008110A1000004E533A3A466F6F00F40000001800000001000000100159DFAC75D18675AED1AD169FE316317E0000F3000000D400000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A322E63707000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2000245430202E7261536561726368203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200024543020246562702034202B203D202465697020245430205E203D2024657370202454302034202B203D2024656270202454302034202D205E203D200000 | ||
| 26 | Subsections: | ||
| 27 | - !Symbols | ||
| 28 | Records: | ||
| 29 | - Kind: S_COMPILE3 | ||
| 30 | Compile3Sym: | ||
| 31 | Flags: [ ] | ||
| 32 | Machine: Pentium3 | ||
| 33 | FrontendMajor: 6 | ||
| 34 | FrontendMinor: 0 | ||
| 35 | FrontendBuild: 0 | ||
| 36 | FrontendQFE: 0 | ||
| 37 | BackendMajor: 6000 | ||
| 38 | BackendMinor: 0 | ||
| 39 | BackendBuild: 0 | ||
| 40 | BackendQFE: 0 | ||
| 41 | Version: 'clang version 6.0.0 ' | ||
| 42 | - !FrameData | ||
| 43 | Frames: | ||
| 44 | - CodeSize: 25 | ||
| 45 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | ||
| 46 | LocalSize: 0 | ||
| 47 | MaxStackSize: 0 | ||
| 48 | ParamsSize: 4 | ||
| 49 | PrologSize: 4 | ||
| 50 | RvaStart: 0 | ||
| 51 | SavedRegsSize: 0 | ||
| 52 | - CodeSize: 24 | ||
| 53 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 54 | LocalSize: 0 | ||
| 55 | MaxStackSize: 0 | ||
| 56 | ParamsSize: 4 | ||
| 57 | PrologSize: 3 | ||
| 58 | RvaStart: 1 | ||
| 59 | SavedRegsSize: 4 | ||
| 60 | - CodeSize: 22 | ||
| 61 | FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 62 | LocalSize: 0 | ||
| 63 | MaxStackSize: 0 | ||
| 64 | ParamsSize: 4 | ||
| 65 | PrologSize: 1 | ||
| 66 | RvaStart: 3 | ||
| 67 | SavedRegsSize: 4 | ||
| 68 | - !Symbols | ||
| 69 | Records: | ||
| 70 | - Kind: S_GPROC32_ID | ||
| 71 | ProcSym: | ||
| 72 | CodeSize: 25 | ||
| 73 | DbgStart: 0 | ||
| 74 | DbgEnd: 0 | ||
| 75 | FunctionType: 4109 | ||
| 76 | Flags: [ ] | ||
| 77 | DisplayName: 'NS::func' | ||
| 78 | - Kind: S_LOCAL | ||
| 79 | LocalSym: | ||
| 80 | Type: 4099 | ||
| 81 | Flags: [ IsParameter ] | ||
| 82 | VarName: f | ||
| 83 | - Kind: S_DEFRANGE_REGISTER_REL | ||
| 84 | DefRangeRegisterRelSym: | ||
| 85 | - Kind: S_PROC_ID_END | ||
| 86 | ScopeEndSym: | ||
| 87 | - !Lines | ||
| 88 | CodeSize: 25 | ||
| 89 | Flags: [ ] | ||
| 90 | RelocOffset: 0 | ||
| 91 | RelocSegment: 0 | ||
| 92 | Blocks: | ||
| 93 | - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp' | ||
| 94 | Lines: | ||
| 95 | - Offset: 0 | ||
| 96 | LineStart: 3 | ||
| 97 | IsStatement: false | ||
| 98 | EndDelta: 0 | ||
| 99 | - Offset: 7 | ||
| 100 | LineStart: 4 | ||
| 101 | IsStatement: false | ||
| 102 | EndDelta: 0 | ||
| 103 | Columns: | ||
| 104 | - !Symbols | ||
| 105 | Records: | ||
| 106 | - Kind: S_UDT | ||
| 107 | UDTSym: | ||
| 108 | Type: 4106 | ||
| 109 | UDTName: 'NS::Foo' | ||
| 110 | - !FileChecksums | ||
| 111 | Checksums: | ||
| 112 | - FileName: 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp' | ||
| 113 | Kind: MD5 | ||
| 114 | Checksum: 59DFAC75D18675AED1AD169FE316317E | ||
| 115 | - !StringTable | ||
| 116 | Strings: | ||
| 117 | - 'D:\src\llvmbuild\clang\Debug\x86\obj2.cpp' | ||
| 118 | - '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | ||
| 119 | - '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 120 | - '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | ||
| 121 | - '' | ||
| 122 | Relocations: | ||
| 123 | - VirtualAddress: 68 | ||
| 124 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 125 | Type: IMAGE_REL_I386_DIR32NB | ||
| 126 | - VirtualAddress: 208 | ||
| 127 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 128 | Type: IMAGE_REL_I386_SECREL | ||
| 129 | - VirtualAddress: 212 | ||
| 130 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 131 | Type: IMAGE_REL_I386_SECTION | ||
| 132 | - VirtualAddress: 248 | ||
| 133 | SymbolName: .text | ||
| 134 | Type: IMAGE_REL_I386_SECREL | ||
| 135 | - VirtualAddress: 252 | ||
| 136 | SymbolName: .text | ||
| 137 | Type: IMAGE_REL_I386_SECTION | ||
| 138 | - VirtualAddress: 268 | ||
| 139 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 140 | Type: IMAGE_REL_I386_SECREL | ||
| 141 | - VirtualAddress: 272 | ||
| 142 | SymbolName: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 143 | Type: IMAGE_REL_I386_SECTION | ||
| 144 | - Name: '.debug$T' | ||
| 145 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 146 | Alignment: 4 | ||
| 147 | SectionData: 040000000A000516000000004E5300F12A0005150000800200000000000000000000000000004E533A3A466F6F002E3F4155466F6F404E53404000F10A000110011000000100F2F10A000210021000002A8000000A00011201000000031000000E0008107400000000000100041000000A000210011000000A8000000A00011201000000740000001A0009100300000001100000061000000B00010007100000000000001A0003120D15030074000000000058001115030008100000466F6F002A0005150200000209100000000000000000000004004E533A3A466F6F002E3F4155466F6F404E53404000F12E00051600000000443A5C7372635C6C6C766D6275696C645C636C616E675C44656275675C7838365C6F626A2E6800F10E0006160A1000000B1000000200000012000116001000000510000066756E6300F3F2F1 | ||
| 148 | Types: | ||
| 149 | - Kind: LF_STRING_ID | ||
| 150 | StringId: | ||
| 151 | Id: 0 | ||
| 152 | String: NS | ||
| 153 | - Kind: LF_STRUCTURE | ||
| 154 | Class: | ||
| 155 | MemberCount: 0 | ||
| 156 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 157 | FieldList: 0 | ||
| 158 | Name: 'NS::Foo' | ||
| 159 | UniqueName: '.?AUFoo@NS@@' | ||
| 160 | DerivationList: 0 | ||
| 161 | VTableShape: 0 | ||
| 162 | Size: 0 | ||
| 163 | - Kind: LF_MODIFIER | ||
| 164 | Modifier: | ||
| 165 | ModifiedType: 4097 | ||
| 166 | Modifiers: [ None, Const ] | ||
| 167 | - Kind: LF_POINTER | ||
| 168 | Pointer: | ||
| 169 | ReferentType: 4098 | ||
| 170 | Attrs: 32810 | ||
| 171 | - Kind: LF_ARGLIST | ||
| 172 | ArgList: | ||
| 173 | ArgIndices: [ 4099 ] | ||
| 174 | - Kind: LF_PROCEDURE | ||
| 175 | Procedure: | ||
| 176 | ReturnType: 116 | ||
| 177 | CallConv: NearC | ||
| 178 | Options: [ None ] | ||
| 179 | ParameterCount: 1 | ||
| 180 | ArgumentList: 4100 | ||
| 181 | - Kind: LF_POINTER | ||
| 182 | Pointer: | ||
| 183 | ReferentType: 4097 | ||
| 184 | Attrs: 32778 | ||
| 185 | - Kind: LF_ARGLIST | ||
| 186 | ArgList: | ||
| 187 | ArgIndices: [ 116 ] | ||
| 188 | - Kind: LF_MFUNCTION | ||
| 189 | MemberFunction: | ||
| 190 | ReturnType: 3 | ||
| 191 | ClassType: 4097 | ||
| 192 | ThisType: 4102 | ||
| 193 | CallConv: ThisCall | ||
| 194 | Options: [ None ] | ||
| 195 | ParameterCount: 1 | ||
| 196 | ArgumentList: 4103 | ||
| 197 | ThisPointerAdjustment: 0 | ||
| 198 | - Kind: LF_FIELDLIST | ||
| 199 | FieldList: | ||
| 200 | - Kind: LF_MEMBER | ||
| 201 | DataMember: | ||
| 202 | Attrs: 3 | ||
| 203 | Type: 116 | ||
| 204 | FieldOffset: 0 | ||
| 205 | Name: X | ||
| 206 | - Kind: LF_ONEMETHOD | ||
| 207 | OneMethod: | ||
| 208 | Type: 4104 | ||
| 209 | Attrs: 3 | ||
| 210 | VFTableOffset: -1 | ||
| 211 | Name: Foo | ||
| 212 | - Kind: LF_STRUCTURE | ||
| 213 | Class: | ||
| 214 | MemberCount: 2 | ||
| 215 | Options: [ None, HasUniqueName ] | ||
| 216 | FieldList: 4105 | ||
| 217 | Name: 'NS::Foo' | ||
| 218 | UniqueName: '.?AUFoo@NS@@' | ||
| 219 | DerivationList: 0 | ||
| 220 | VTableShape: 0 | ||
| 221 | Size: 4 | ||
| 222 | - Kind: LF_STRING_ID | ||
| 223 | StringId: | ||
| 224 | Id: 0 | ||
| 225 | String: 'D:\src\llvmbuild\clang\Debug\x86\obj.h' | ||
| 226 | - Kind: LF_UDT_SRC_LINE | ||
| 227 | UdtSourceLine: | ||
| 228 | UDT: 4106 | ||
| 229 | SourceFile: 4107 | ||
| 230 | LineNumber: 2 | ||
| 231 | - Kind: LF_FUNC_ID | ||
| 232 | FuncId: | ||
| 233 | ParentScope: 4096 | ||
| 234 | FunctionType: 4101 | ||
| 235 | Name: func | ||
| 236 | - Name: '.debug$H' | ||
| 237 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 238 | Alignment: 4 | ||
| 239 | SectionData: C5C9330100000000EC145CD76AEFE74E78880D531132B3BB8FFACEF79E616EF06A14EA74A2420F9062A1FB04917E59759949E334BA18509ED692F3C65CE242D8450EBC78B81B63AF8316DC324562EB9F0D4A0D708E8A25C263DB05943C19B84A36719E1E414DDA3EDBDF005322238D70F9058EEDC5C50EF11BC849618B51FD89E3A50EABE5E8FE3945468547C19DC681D0BFB3B797DD91CA4D7F1953C314442D5549419E78044E38A0BF16BFFAA5EE9C0103E7DBFE9941E63379C0B0C0A9021B711ACC4F67008974EBF441031BDD653F6935DFF3112C6A5346EF2AC94B9B7EB56EF55CFA0AF6C1846743F43D846BB19517E12E8873BBA90CC41DD1BEAC89CBA8897AC1BA46762E2557A82D89DCBC783AF285D9DBB672F67A81E36906B2038B57 | ||
| 240 | GlobalHashes: | ||
| 241 | Version: 0 | ||
| 242 | HashAlgorithm: 0 | ||
| 243 | HashValues: | ||
| 244 | - EC145CD76AEFE74E78880D531132B3BB8FFACEF7 | ||
| 245 | - 9E616EF06A14EA74A2420F9062A1FB04917E5975 | ||
| 246 | - 9949E334BA18509ED692F3C65CE242D8450EBC78 | ||
| 247 | - B81B63AF8316DC324562EB9F0D4A0D708E8A25C2 | ||
| 248 | - 63DB05943C19B84A36719E1E414DDA3EDBDF0053 | ||
| 249 | - 22238D70F9058EEDC5C50EF11BC849618B51FD89 | ||
| 250 | - E3A50EABE5E8FE3945468547C19DC681D0BFB3B7 | ||
| 251 | - 97DD91CA4D7F1953C314442D5549419E78044E38 | ||
| 252 | - A0BF16BFFAA5EE9C0103E7DBFE9941E63379C0B0 | ||
| 253 | - C0A9021B711ACC4F67008974EBF441031BDD653F | ||
| 254 | - 6935DFF3112C6A5346EF2AC94B9B7EB56EF55CFA | ||
| 255 | - 0AF6C1846743F43D846BB19517E12E8873BBA90C | ||
| 256 | - C41DD1BEAC89CBA8897AC1BA46762E2557A82D89 | ||
| 257 | - DCBC783AF285D9DBB672F67A81E36906B2038B57 | ||
| 258 | symbols: | ||
| 259 | - Name: .text | ||
| 260 | Value: 0 | ||
| 261 | SectionNumber: 1 | ||
| 262 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 263 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 264 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 265 | SectionDefinition: | ||
| 266 | Length: 25 | ||
| 267 | NumberOfRelocations: 0 | ||
| 268 | NumberOfLinenumbers: 0 | ||
| 269 | CheckSum: 1820185021 | ||
| 270 | Number: 1 | ||
| 271 | - Name: .data | ||
| 272 | Value: 0 | ||
| 273 | SectionNumber: 2 | ||
| 274 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 275 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 276 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 277 | SectionDefinition: | ||
| 278 | Length: 0 | ||
| 279 | NumberOfRelocations: 0 | ||
| 280 | NumberOfLinenumbers: 0 | ||
| 281 | CheckSum: 0 | ||
| 282 | Number: 2 | ||
| 283 | - Name: .bss | ||
| 284 | Value: 0 | ||
| 285 | SectionNumber: 3 | ||
| 286 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 287 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 288 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 289 | SectionDefinition: | ||
| 290 | Length: 0 | ||
| 291 | NumberOfRelocations: 0 | ||
| 292 | NumberOfLinenumbers: 0 | ||
| 293 | CheckSum: 0 | ||
| 294 | Number: 3 | ||
| 295 | - Name: .drectve | ||
| 296 | Value: 0 | ||
| 297 | SectionNumber: 4 | ||
| 298 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 299 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 300 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 301 | SectionDefinition: | ||
| 302 | Length: 48 | ||
| 303 | NumberOfRelocations: 0 | ||
| 304 | NumberOfLinenumbers: 0 | ||
| 305 | CheckSum: 149686238 | ||
| 306 | Number: 4 | ||
| 307 | - Name: '.debug$S' | ||
| 308 | Value: 0 | ||
| 309 | SectionNumber: 5 | ||
| 310 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 311 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 312 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 313 | SectionDefinition: | ||
| 314 | Length: 584 | ||
| 315 | NumberOfRelocations: 7 | ||
| 316 | NumberOfLinenumbers: 0 | ||
| 317 | CheckSum: 2847177244 | ||
| 318 | Number: 5 | ||
| 319 | - Name: '.debug$T' | ||
| 320 | Value: 0 | ||
| 321 | SectionNumber: 6 | ||
| 322 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 323 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 324 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 325 | SectionDefinition: | ||
| 326 | Length: 320 | ||
| 327 | NumberOfRelocations: 0 | ||
| 328 | NumberOfLinenumbers: 0 | ||
| 329 | CheckSum: 2684556216 | ||
| 330 | Number: 6 | ||
| 331 | - Name: '.debug$H' | ||
| 332 | Value: 0 | ||
| 333 | SectionNumber: 7 | ||
| 334 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 335 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 336 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 337 | SectionDefinition: | ||
| 338 | Length: 288 | ||
| 339 | NumberOfRelocations: 0 | ||
| 340 | NumberOfLinenumbers: 0 | ||
| 341 | CheckSum: 2348181452 | ||
| 342 | Number: 7 | ||
| 343 | - Name: '@feat.00' | ||
| 344 | Value: 1 | ||
| 345 | SectionNumber: -1 | ||
| 346 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 347 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 348 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 349 | - Name: '?func@NS@@YAHABUFoo@1@@Z' | ||
| 350 | Value: 0 | ||
| 351 | SectionNumber: 1 | ||
| 352 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 353 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 354 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 355 | ... | ||
deps/lld/test/COFF/Inputs/pdb-scopes-a.yaml+58-58| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | --- !COFF | 1 | --- !COFF |
| 2 | header: | 2 | header: |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | 3 | Machine: IMAGE_FILE_MACHINE_AMD64 |
| 4 | Characteristics: [ ] | 4 | Characteristics: [ ] |
| 5 | sections: | 5 | sections: |
| 6 | - Name: .drectve | 6 | - Name: .drectve |
| 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] |
| 8 | Alignment: 1 | 8 | Alignment: 1 |
| ... | @@ -10,15 +10,15 @@ sections: | ... | @@ -10,15 +10,15 @@ sections: |
| 10 | - Name: '.debug$S' | 10 | - Name: '.debug$S' |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 12 | Alignment: 1 | 12 | Alignment: 1 |
| 13 | Subsections: | 13 | Subsections: |
| 14 | - !Symbols | 14 | - !Symbols |
| 15 | Records: | 15 | Records: |
| 16 | - Kind: S_OBJNAME | 16 | - Kind: S_OBJNAME |
| 17 | ObjNameSym: | 17 | ObjNameSym: |
| 18 | Signature: 0 | 18 | Signature: 0 |
| 19 | ObjectName: 'C:\src\llvm-project\build\a.obj' | 19 | ObjectName: 'C:\src\llvm-project\build\a.obj' |
| 20 | - Kind: S_COMPILE3 | 20 | - Kind: S_COMPILE3 |
| 21 | Compile3Sym: | 21 | Compile3Sym: |
| 22 | Flags: [ SecurityChecks, HotPatch ] | 22 | Flags: [ SecurityChecks, HotPatch ] |
| 23 | Machine: X64 | 23 | Machine: X64 |
| 24 | FrontendMajor: 19 | 24 | FrontendMajor: 19 |
| ... | @@ -31,9 +31,9 @@ sections: | ... | @@ -31,9 +31,9 @@ sections: |
| 31 | BackendQFE: 1 | 31 | BackendQFE: 1 |
| 32 | Version: 'Microsoft (R) Optimizing Compiler' | 32 | Version: 'Microsoft (R) Optimizing Compiler' |
| 33 | - !Symbols | 33 | - !Symbols |
| 34 | Records: | 34 | Records: |
| 35 | - Kind: S_GPROC32_ID | 35 | - Kind: S_GPROC32_ID |
| 36 | ProcSym: | 36 | ProcSym: |
| 37 | CodeSize: 5 | 37 | CodeSize: 5 |
| 38 | DbgStart: 4 | 38 | DbgStart: 4 |
| 39 | DbgEnd: 4 | 39 | DbgEnd: 4 |
| ... | @@ -41,7 +41,7 @@ sections: | ... | @@ -41,7 +41,7 @@ sections: |
| 41 | Flags: [ ] | 41 | Flags: [ ] |
| 42 | DisplayName: g | 42 | DisplayName: g |
| 43 | - Kind: S_FRAMEPROC | 43 | - Kind: S_FRAMEPROC |
| 44 | FrameProcSym: | 44 | FrameProcSym: |
| 45 | TotalFrameBytes: 0 | 45 | TotalFrameBytes: 0 |
| 46 | PaddingFrameBytes: 0 | 46 | PaddingFrameBytes: 0 |
| 47 | OffsetToPadding: 0 | 47 | OffsetToPadding: 0 |
| ... | @@ -50,30 +50,30 @@ sections: | ... | @@ -50,30 +50,30 @@ sections: |
| 50 | SectionIdOfExceptionHandler: 0 | 50 | SectionIdOfExceptionHandler: 0 |
| 51 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | 51 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 52 | - Kind: S_REGREL32 | 52 | - Kind: S_REGREL32 |
| 53 | RegRelativeSym: | 53 | RegRelativeSym: |
| 54 | Offset: 8 | 54 | Offset: 8 |
| 55 | Type: 116 | 55 | Type: 116 |
| 56 | Register: RSP | 56 | Register: RSP |
| 57 | VarName: x | 57 | VarName: x |
| 58 | - Kind: S_PROC_ID_END | 58 | - Kind: S_PROC_ID_END |
| 59 | ScopeEndSym: | 59 | ScopeEndSym: |
| 60 | - !Lines | 60 | - !Lines |
| 61 | CodeSize: 5 | 61 | CodeSize: 5 |
| 62 | Flags: [ ] | 62 | Flags: [ ] |
| 63 | RelocOffset: 0 | 63 | RelocOffset: 0 |
| 64 | RelocSegment: 0 | 64 | RelocSegment: 0 |
| 65 | Blocks: | 65 | Blocks: |
| 66 | - FileName: 'c:\src\llvm-project\build\a.c' | 66 | - FileName: 'c:\src\llvm-project\build\a.c' |
| 67 | Lines: | 67 | Lines: |
| 68 | - Offset: 0 | 68 | - Offset: 0 |
| 69 | LineStart: 1 | 69 | LineStart: 1 |
| 70 | IsStatement: true | 70 | IsStatement: true |
| 71 | EndDelta: 0 | 71 | EndDelta: 0 |
| 72 | Columns: | 72 | Columns: |
| 73 | - !Symbols | 73 | - !Symbols |
| 74 | Records: | 74 | Records: |
| 75 | - Kind: S_GPROC32_ID | 75 | - Kind: S_GPROC32_ID |
| 76 | ProcSym: | 76 | ProcSym: |
| 77 | CodeSize: 58 | 77 | CodeSize: 58 |
| 78 | DbgStart: 8 | 78 | DbgStart: 8 |
| 79 | DbgEnd: 53 | 79 | DbgEnd: 53 |
| ... | @@ -81,7 +81,7 @@ sections: | ... | @@ -81,7 +81,7 @@ sections: |
| 81 | Flags: [ ] | 81 | Flags: [ ] |
| 82 | DisplayName: main | 82 | DisplayName: main |
| 83 | - Kind: S_FRAMEPROC | 83 | - Kind: S_FRAMEPROC |
| 84 | FrameProcSym: | 84 | FrameProcSym: |
| 85 | TotalFrameBytes: 56 | 85 | TotalFrameBytes: 56 |
| 86 | PaddingFrameBytes: 0 | 86 | PaddingFrameBytes: 0 |
| 87 | OffsetToPadding: 0 | 87 | OffsetToPadding: 0 |
| ... | @@ -90,47 +90,47 @@ sections: | ... | @@ -90,47 +90,47 @@ sections: |
| 90 | SectionIdOfExceptionHandler: 0 | 90 | SectionIdOfExceptionHandler: 0 |
| 91 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | 91 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 92 | - Kind: S_REGREL32 | 92 | - Kind: S_REGREL32 |
| 93 | RegRelativeSym: | 93 | RegRelativeSym: |
| 94 | Offset: 64 | 94 | Offset: 64 |
| 95 | Type: 116 | 95 | Type: 116 |
| 96 | Register: RSP | 96 | Register: RSP |
| 97 | VarName: argc | 97 | VarName: argc |
| 98 | - Kind: S_BLOCK32 | 98 | - Kind: S_BLOCK32 |
| 99 | BlockSym: | 99 | BlockSym: |
| 100 | CodeSize: 17 | 100 | CodeSize: 17 |
| 101 | Offset: 15 | 101 | Offset: 15 |
| 102 | BlockName: '' | 102 | BlockName: '' |
| 103 | - Kind: S_REGREL32 | 103 | - Kind: S_REGREL32 |
| 104 | RegRelativeSym: | 104 | RegRelativeSym: |
| 105 | Offset: 32 | 105 | Offset: 32 |
| 106 | Type: 116 | 106 | Type: 116 |
| 107 | Register: RSP | 107 | Register: RSP |
| 108 | VarName: x | 108 | VarName: x |
| 109 | - Kind: S_END | 109 | - Kind: S_END |
| 110 | ScopeEndSym: | 110 | ScopeEndSym: |
| 111 | - Kind: S_BLOCK32 | 111 | - Kind: S_BLOCK32 |
| 112 | BlockSym: | 112 | BlockSym: |
| 113 | CodeSize: 17 | 113 | CodeSize: 17 |
| 114 | Offset: 34 | 114 | Offset: 34 |
| 115 | BlockName: '' | 115 | BlockName: '' |
| 116 | - Kind: S_REGREL32 | 116 | - Kind: S_REGREL32 |
| 117 | RegRelativeSym: | 117 | RegRelativeSym: |
| 118 | Offset: 36 | 118 | Offset: 36 |
| 119 | Type: 116 | 119 | Type: 116 |
| 120 | Register: RSP | 120 | Register: RSP |
| 121 | VarName: y | 121 | VarName: y |
| 122 | - Kind: S_END | 122 | - Kind: S_END |
| 123 | ScopeEndSym: | 123 | ScopeEndSym: |
| 124 | - Kind: S_PROC_ID_END | 124 | - Kind: S_PROC_ID_END |
| 125 | ScopeEndSym: | 125 | ScopeEndSym: |
| 126 | - !Lines | 126 | - !Lines |
| 127 | CodeSize: 58 | 127 | CodeSize: 58 |
| 128 | Flags: [ ] | 128 | Flags: [ ] |
| 129 | RelocOffset: 0 | 129 | RelocOffset: 0 |
| 130 | RelocSegment: 0 | 130 | RelocSegment: 0 |
| 131 | Blocks: | 131 | Blocks: |
| 132 | - FileName: 'c:\src\llvm-project\build\a.c' | 132 | - FileName: 'c:\src\llvm-project\build\a.c' |
| 133 | Lines: | 133 | Lines: |
| 134 | - Offset: 0 | 134 | - Offset: 0 |
| 135 | LineStart: 3 | 135 | LineStart: 3 |
| 136 | IsStatement: true | 136 | IsStatement: true |
| ... | @@ -163,21 +163,21 @@ sections: | ... | @@ -163,21 +163,21 @@ sections: |
| 163 | LineStart: 11 | 163 | LineStart: 11 |
| 164 | IsStatement: true | 164 | IsStatement: true |
| 165 | EndDelta: 0 | 165 | EndDelta: 0 |
| 166 | Columns: | 166 | Columns: |
| 167 | - !FileChecksums | 167 | - !FileChecksums |
| 168 | Checksums: | 168 | Checksums: |
| 169 | - FileName: 'c:\src\llvm-project\build\a.c' | 169 | - FileName: 'c:\src\llvm-project\build\a.c' |
| 170 | Kind: MD5 | 170 | Kind: MD5 |
| 171 | Checksum: 7FA72225C3F5630316383BD8BCC3EF72 | 171 | Checksum: 7FA72225C3F5630316383BD8BCC3EF72 |
| 172 | - !StringTable | 172 | - !StringTable |
| 173 | Strings: | 173 | Strings: |
| 174 | - 'c:\src\llvm-project\build\a.c' | 174 | - 'c:\src\llvm-project\build\a.c' |
| 175 | - !Symbols | 175 | - !Symbols |
| 176 | Records: | 176 | Records: |
| 177 | - Kind: S_BUILDINFO | 177 | - Kind: S_BUILDINFO |
| 178 | BuildInfoSym: | 178 | BuildInfoSym: |
| 179 | BuildId: 4110 | 179 | BuildId: 4110 |
| 180 | Relocations: | 180 | Relocations: |
| 181 | - VirtualAddress: 152 | 181 | - VirtualAddress: 152 |
| 182 | SymbolName: g | 182 | SymbolName: g |
| 183 | Type: IMAGE_REL_AMD64_SECREL | 183 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -217,78 +217,78 @@ sections: | ... | @@ -217,78 +217,78 @@ sections: |
| 217 | - Name: '.debug$T' | 217 | - Name: '.debug$T' |
| 218 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 218 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 219 | Alignment: 1 | 219 | Alignment: 1 |
| 220 | Types: | 220 | Types: |
| 221 | - Kind: LF_ARGLIST | 221 | - Kind: LF_ARGLIST |
| 222 | ArgList: | 222 | ArgList: |
| 223 | ArgIndices: [ 116 ] | 223 | ArgIndices: [ 116 ] |
| 224 | - Kind: LF_PROCEDURE | 224 | - Kind: LF_PROCEDURE |
| 225 | Procedure: | 225 | Procedure: |
| 226 | ReturnType: 3 | 226 | ReturnType: 3 |
| 227 | CallConv: NearC | 227 | CallConv: NearC |
| 228 | Options: [ None ] | 228 | Options: [ None ] |
| 229 | ParameterCount: 1 | 229 | ParameterCount: 1 |
| 230 | ArgumentList: 4096 | 230 | ArgumentList: 4096 |
| 231 | - Kind: LF_POINTER | 231 | - Kind: LF_POINTER |
| 232 | Pointer: | 232 | Pointer: |
| 233 | ReferentType: 4097 | 233 | ReferentType: 4097 |
| 234 | Attrs: 65548 | 234 | Attrs: 65548 |
| 235 | - Kind: LF_FUNC_ID | 235 | - Kind: LF_FUNC_ID |
| 236 | FuncId: | 236 | FuncId: |
| 237 | ParentScope: 0 | 237 | ParentScope: 0 |
| 238 | FunctionType: 4097 | 238 | FunctionType: 4097 |
| 239 | Name: g | 239 | Name: g |
| 240 | - Kind: LF_PROCEDURE | 240 | - Kind: LF_PROCEDURE |
| 241 | Procedure: | 241 | Procedure: |
| 242 | ReturnType: 116 | 242 | ReturnType: 116 |
| 243 | CallConv: NearC | 243 | CallConv: NearC |
| 244 | Options: [ None ] | 244 | Options: [ None ] |
| 245 | ParameterCount: 1 | 245 | ParameterCount: 1 |
| 246 | ArgumentList: 4096 | 246 | ArgumentList: 4096 |
| 247 | - Kind: LF_FUNC_ID | 247 | - Kind: LF_FUNC_ID |
| 248 | FuncId: | 248 | FuncId: |
| 249 | ParentScope: 0 | 249 | ParentScope: 0 |
| 250 | FunctionType: 4100 | 250 | FunctionType: 4100 |
| 251 | Name: main | 251 | Name: main |
| 252 | - Kind: LF_FUNC_ID | 252 | - Kind: LF_FUNC_ID |
| 253 | FuncId: | 253 | FuncId: |
| 254 | ParentScope: 0 | 254 | ParentScope: 0 |
| 255 | FunctionType: 4097 | 255 | FunctionType: 4097 |
| 256 | Name: f | 256 | Name: f |
| 257 | - Kind: LF_STRING_ID | 257 | - Kind: LF_STRING_ID |
| 258 | StringId: | 258 | StringId: |
| 259 | Id: 0 | 259 | Id: 0 |
| 260 | String: 'C:\src\llvm-project\build' | 260 | String: 'C:\src\llvm-project\build' |
| 261 | - Kind: LF_STRING_ID | 261 | - Kind: LF_STRING_ID |
| 262 | StringId: | 262 | StringId: |
| 263 | Id: 0 | 263 | Id: 0 |
| 264 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' | 264 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' |
| 265 | - Kind: LF_STRING_ID | 265 | - Kind: LF_STRING_ID |
| 266 | StringId: | 266 | StringId: |
| 267 | Id: 0 | 267 | Id: 0 |
| 268 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' | 268 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' |
| 269 | - Kind: LF_SUBSTR_LIST | 269 | - Kind: LF_SUBSTR_LIST |
| 270 | StringList: | 270 | StringList: |
| 271 | StringIndices: [ 4105 ] | 271 | StringIndices: [ 4105 ] |
| 272 | - Kind: LF_STRING_ID | 272 | - Kind: LF_STRING_ID |
| 273 | StringId: | 273 | StringId: |
| 274 | Id: 4106 | 274 | Id: 4106 |
| 275 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' | 275 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' |
| 276 | - Kind: LF_STRING_ID | 276 | - Kind: LF_STRING_ID |
| 277 | StringId: | 277 | StringId: |
| 278 | Id: 0 | 278 | Id: 0 |
| 279 | String: a.c | 279 | String: a.c |
| 280 | - Kind: LF_STRING_ID | 280 | - Kind: LF_STRING_ID |
| 281 | StringId: | 281 | StringId: |
| 282 | Id: 0 | 282 | Id: 0 |
| 283 | String: 'C:\src\llvm-project\build\vc140.pdb' | 283 | String: 'C:\src\llvm-project\build\vc140.pdb' |
| 284 | - Kind: LF_BUILDINFO | 284 | - Kind: LF_BUILDINFO |
| 285 | BuildInfo: | 285 | BuildInfo: |
| 286 | ArgIndices: [ 4103, 4104, 4108, 4109, 4107 ] | 286 | ArgIndices: [ 4103, 4104, 4108, 4109, 4107 ] |
| 287 | - Name: '.text$mn' | 287 | - Name: '.text$mn' |
| 288 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 288 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 289 | Alignment: 16 | 289 | Alignment: 16 |
| 290 | SectionData: 894C2408C3CCCCCCCCCCCCCCCCCCCCCC894C24084883EC38837C2440007413C74424202A0000008B4C2420E800000000EB11C74424240D0000008B4C2424E80000000033C04883C438C3 | 290 | SectionData: 894C2408C3CCCCCCCCCCCCCCCCCCCCCC894C24084883EC38837C2440007413C74424202A0000008B4C2420E800000000EB11C74424240D0000008B4C2424E80000000033C04883C438C3 |
| 291 | Relocations: | 291 | Relocations: |
| 292 | - VirtualAddress: 44 | 292 | - VirtualAddress: 44 |
| 293 | SymbolName: f | 293 | SymbolName: f |
| 294 | Type: IMAGE_REL_AMD64_REL32 | 294 | Type: IMAGE_REL_AMD64_REL32 |
| ... | @@ -303,7 +303,7 @@ sections: | ... | @@ -303,7 +303,7 @@ sections: |
| 303 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | 303 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] |
| 304 | Alignment: 4 | 304 | Alignment: 4 |
| 305 | SectionData: 000000003A00000000000000 | 305 | SectionData: 000000003A00000000000000 |
| 306 | Relocations: | 306 | Relocations: |
| 307 | - VirtualAddress: 0 | 307 | - VirtualAddress: 0 |
| 308 | SymbolName: '$LN5' | 308 | SymbolName: '$LN5' |
| 309 | Type: IMAGE_REL_AMD64_ADDR32NB | 309 | Type: IMAGE_REL_AMD64_ADDR32NB |
| ... | @@ -313,14 +313,14 @@ sections: | ... | @@ -313,14 +313,14 @@ sections: |
| 313 | - VirtualAddress: 8 | 313 | - VirtualAddress: 8 |
| 314 | SymbolName: '$unwind$main' | 314 | SymbolName: '$unwind$main' |
| 315 | Type: IMAGE_REL_AMD64_ADDR32NB | 315 | Type: IMAGE_REL_AMD64_ADDR32NB |
| 316 | symbols: | 316 | symbols: |
| 317 | - Name: .drectve | 317 | - Name: .drectve |
| 318 | Value: 0 | 318 | Value: 0 |
| 319 | SectionNumber: 1 | 319 | SectionNumber: 1 |
| 320 | SimpleType: IMAGE_SYM_TYPE_NULL | 320 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 321 | ComplexType: IMAGE_SYM_DTYPE_NULL | 321 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 322 | StorageClass: IMAGE_SYM_CLASS_STATIC | 322 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 323 | SectionDefinition: | 323 | SectionDefinition: |
| 324 | Length: 47 | 324 | Length: 47 |
| 325 | NumberOfRelocations: 0 | 325 | NumberOfRelocations: 0 |
| 326 | NumberOfLinenumbers: 0 | 326 | NumberOfLinenumbers: 0 |
| ... | @@ -332,7 +332,7 @@ symbols: | ... | @@ -332,7 +332,7 @@ symbols: |
| 332 | SimpleType: IMAGE_SYM_TYPE_NULL | 332 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 333 | ComplexType: IMAGE_SYM_DTYPE_NULL | 333 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 334 | StorageClass: IMAGE_SYM_CLASS_STATIC | 334 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 335 | SectionDefinition: | 335 | SectionDefinition: |
| 336 | Length: 628 | 336 | Length: 628 |
| 337 | NumberOfRelocations: 12 | 337 | NumberOfRelocations: 12 |
| 338 | NumberOfLinenumbers: 0 | 338 | NumberOfLinenumbers: 0 |
| ... | @@ -344,7 +344,7 @@ symbols: | ... | @@ -344,7 +344,7 @@ symbols: |
| 344 | SimpleType: IMAGE_SYM_TYPE_NULL | 344 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 345 | ComplexType: IMAGE_SYM_DTYPE_NULL | 345 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 346 | StorageClass: IMAGE_SYM_CLASS_STATIC | 346 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 347 | SectionDefinition: | 347 | SectionDefinition: |
| 348 | Length: 624 | 348 | Length: 624 |
| 349 | NumberOfRelocations: 0 | 349 | NumberOfRelocations: 0 |
| 350 | NumberOfLinenumbers: 0 | 350 | NumberOfLinenumbers: 0 |
| ... | @@ -356,7 +356,7 @@ symbols: | ... | @@ -356,7 +356,7 @@ symbols: |
| 356 | SimpleType: IMAGE_SYM_TYPE_NULL | 356 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 357 | ComplexType: IMAGE_SYM_DTYPE_NULL | 357 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 358 | StorageClass: IMAGE_SYM_CLASS_STATIC | 358 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 359 | SectionDefinition: | 359 | SectionDefinition: |
| 360 | Length: 74 | 360 | Length: 74 |
| 361 | NumberOfRelocations: 2 | 361 | NumberOfRelocations: 2 |
| 362 | NumberOfLinenumbers: 0 | 362 | NumberOfLinenumbers: 0 |
| ... | @@ -392,7 +392,7 @@ symbols: | ... | @@ -392,7 +392,7 @@ symbols: |
| 392 | SimpleType: IMAGE_SYM_TYPE_NULL | 392 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 393 | ComplexType: IMAGE_SYM_DTYPE_NULL | 393 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 394 | StorageClass: IMAGE_SYM_CLASS_STATIC | 394 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 395 | SectionDefinition: | 395 | SectionDefinition: |
| 396 | Length: 8 | 396 | Length: 8 |
| 397 | NumberOfRelocations: 0 | 397 | NumberOfRelocations: 0 |
| 398 | NumberOfLinenumbers: 0 | 398 | NumberOfLinenumbers: 0 |
| ... | @@ -410,7 +410,7 @@ symbols: | ... | @@ -410,7 +410,7 @@ symbols: |
| 410 | SimpleType: IMAGE_SYM_TYPE_NULL | 410 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 411 | ComplexType: IMAGE_SYM_DTYPE_NULL | 411 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 412 | StorageClass: IMAGE_SYM_CLASS_STATIC | 412 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 413 | SectionDefinition: | 413 | SectionDefinition: |
| 414 | Length: 12 | 414 | Length: 12 |
| 415 | NumberOfRelocations: 3 | 415 | NumberOfRelocations: 3 |
| 416 | NumberOfLinenumbers: 0 | 416 | NumberOfLinenumbers: 0 |
deps/lld/test/COFF/Inputs/pdb-scopes-b.yaml+50-50| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | --- !COFF | 1 | --- !COFF |
| 2 | header: | 2 | header: |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | 3 | Machine: IMAGE_FILE_MACHINE_AMD64 |
| 4 | Characteristics: [ ] | 4 | Characteristics: [ ] |
| 5 | sections: | 5 | sections: |
| 6 | - Name: .drectve | 6 | - Name: .drectve |
| 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] |
| 8 | Alignment: 1 | 8 | Alignment: 1 |
| ... | @@ -10,15 +10,15 @@ sections: | ... | @@ -10,15 +10,15 @@ sections: |
| 10 | - Name: '.debug$S' | 10 | - Name: '.debug$S' |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 12 | Alignment: 1 | 12 | Alignment: 1 |
| 13 | Subsections: | 13 | Subsections: |
| 14 | - !Symbols | 14 | - !Symbols |
| 15 | Records: | 15 | Records: |
| 16 | - Kind: S_OBJNAME | 16 | - Kind: S_OBJNAME |
| 17 | ObjNameSym: | 17 | ObjNameSym: |
| 18 | Signature: 0 | 18 | Signature: 0 |
| 19 | ObjectName: 'C:\src\llvm-project\build\b.obj' | 19 | ObjectName: 'C:\src\llvm-project\build\b.obj' |
| 20 | - Kind: S_COMPILE3 | 20 | - Kind: S_COMPILE3 |
| 21 | Compile3Sym: | 21 | Compile3Sym: |
| 22 | Flags: [ SecurityChecks, HotPatch ] | 22 | Flags: [ SecurityChecks, HotPatch ] |
| 23 | Machine: X64 | 23 | Machine: X64 |
| 24 | FrontendMajor: 19 | 24 | FrontendMajor: 19 |
| ... | @@ -31,9 +31,9 @@ sections: | ... | @@ -31,9 +31,9 @@ sections: |
| 31 | BackendQFE: 1 | 31 | BackendQFE: 1 |
| 32 | Version: 'Microsoft (R) Optimizing Compiler' | 32 | Version: 'Microsoft (R) Optimizing Compiler' |
| 33 | - !Symbols | 33 | - !Symbols |
| 34 | Records: | 34 | Records: |
| 35 | - Kind: S_GPROC32_ID | 35 | - Kind: S_GPROC32_ID |
| 36 | ProcSym: | 36 | ProcSym: |
| 37 | CodeSize: 62 | 37 | CodeSize: 62 |
| 38 | DbgStart: 8 | 38 | DbgStart: 8 |
| 39 | DbgEnd: 57 | 39 | DbgEnd: 57 |
| ... | @@ -41,7 +41,7 @@ sections: | ... | @@ -41,7 +41,7 @@ sections: |
| 41 | Flags: [ ] | 41 | Flags: [ ] |
| 42 | DisplayName: f | 42 | DisplayName: f |
| 43 | - Kind: S_FRAMEPROC | 43 | - Kind: S_FRAMEPROC |
| 44 | FrameProcSym: | 44 | FrameProcSym: |
| 45 | TotalFrameBytes: 56 | 45 | TotalFrameBytes: 56 |
| 46 | PaddingFrameBytes: 0 | 46 | PaddingFrameBytes: 0 |
| 47 | OffsetToPadding: 0 | 47 | OffsetToPadding: 0 |
| ... | @@ -50,47 +50,47 @@ sections: | ... | @@ -50,47 +50,47 @@ sections: |
| 50 | SectionIdOfExceptionHandler: 0 | 50 | SectionIdOfExceptionHandler: 0 |
| 51 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | 51 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 52 | - Kind: S_REGREL32 | 52 | - Kind: S_REGREL32 |
| 53 | RegRelativeSym: | 53 | RegRelativeSym: |
| 54 | Offset: 64 | 54 | Offset: 64 |
| 55 | Type: 116 | 55 | Type: 116 |
| 56 | Register: RSP | 56 | Register: RSP |
| 57 | VarName: x | 57 | VarName: x |
| 58 | - Kind: S_BLOCK32 | 58 | - Kind: S_BLOCK32 |
| 59 | BlockSym: | 59 | BlockSym: |
| 60 | CodeSize: 20 | 60 | CodeSize: 20 |
| 61 | Offset: 15 | 61 | Offset: 15 |
| 62 | BlockName: '' | 62 | BlockName: '' |
| 63 | - Kind: S_REGREL32 | 63 | - Kind: S_REGREL32 |
| 64 | RegRelativeSym: | 64 | RegRelativeSym: |
| 65 | Offset: 32 | 65 | Offset: 32 |
| 66 | Type: 116 | 66 | Type: 116 |
| 67 | Register: RSP | 67 | Register: RSP |
| 68 | VarName: y | 68 | VarName: y |
| 69 | - Kind: S_END | 69 | - Kind: S_END |
| 70 | ScopeEndSym: | 70 | ScopeEndSym: |
| 71 | - Kind: S_BLOCK32 | 71 | - Kind: S_BLOCK32 |
| 72 | BlockSym: | 72 | BlockSym: |
| 73 | CodeSize: 20 | 73 | CodeSize: 20 |
| 74 | Offset: 37 | 74 | Offset: 37 |
| 75 | BlockName: '' | 75 | BlockName: '' |
| 76 | - Kind: S_REGREL32 | 76 | - Kind: S_REGREL32 |
| 77 | RegRelativeSym: | 77 | RegRelativeSym: |
| 78 | Offset: 36 | 78 | Offset: 36 |
| 79 | Type: 116 | 79 | Type: 116 |
| 80 | Register: RSP | 80 | Register: RSP |
| 81 | VarName: w | 81 | VarName: w |
| 82 | - Kind: S_END | 82 | - Kind: S_END |
| 83 | ScopeEndSym: | 83 | ScopeEndSym: |
| 84 | - Kind: S_PROC_ID_END | 84 | - Kind: S_PROC_ID_END |
| 85 | ScopeEndSym: | 85 | ScopeEndSym: |
| 86 | - !Lines | 86 | - !Lines |
| 87 | CodeSize: 62 | 87 | CodeSize: 62 |
| 88 | Flags: [ ] | 88 | Flags: [ ] |
| 89 | RelocOffset: 0 | 89 | RelocOffset: 0 |
| 90 | RelocSegment: 0 | 90 | RelocSegment: 0 |
| 91 | Blocks: | 91 | Blocks: |
| 92 | - FileName: 'c:\src\llvm-project\build\b.c' | 92 | - FileName: 'c:\src\llvm-project\build\b.c' |
| 93 | Lines: | 93 | Lines: |
| 94 | - Offset: 0 | 94 | - Offset: 0 |
| 95 | LineStart: 2 | 95 | LineStart: 2 |
| 96 | IsStatement: true | 96 | IsStatement: true |
| ... | @@ -123,21 +123,21 @@ sections: | ... | @@ -123,21 +123,21 @@ sections: |
| 123 | LineStart: 10 | 123 | LineStart: 10 |
| 124 | IsStatement: true | 124 | IsStatement: true |
| 125 | EndDelta: 0 | 125 | EndDelta: 0 |
| 126 | Columns: | 126 | Columns: |
| 127 | - !FileChecksums | 127 | - !FileChecksums |
| 128 | Checksums: | 128 | Checksums: |
| 129 | - FileName: 'c:\src\llvm-project\build\b.c' | 129 | - FileName: 'c:\src\llvm-project\build\b.c' |
| 130 | Kind: MD5 | 130 | Kind: MD5 |
| 131 | Checksum: 8E8C92DB46478902EBEAEBFCFF15A6E0 | 131 | Checksum: 8E8C92DB46478902EBEAEBFCFF15A6E0 |
| 132 | - !StringTable | 132 | - !StringTable |
| 133 | Strings: | 133 | Strings: |
| 134 | - 'c:\src\llvm-project\build\b.c' | 134 | - 'c:\src\llvm-project\build\b.c' |
| 135 | - !Symbols | 135 | - !Symbols |
| 136 | Records: | 136 | Records: |
| 137 | - Kind: S_BUILDINFO | 137 | - Kind: S_BUILDINFO |
| 138 | BuildInfoSym: | 138 | BuildInfoSym: |
| 139 | BuildId: 4110 | 139 | BuildId: 4110 |
| 140 | Relocations: | 140 | Relocations: |
| 141 | - VirtualAddress: 152 | 141 | - VirtualAddress: 152 |
| 142 | SymbolName: f | 142 | SymbolName: f |
| 143 | Type: IMAGE_REL_AMD64_SECREL | 143 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -165,76 +165,76 @@ sections: | ... | @@ -165,76 +165,76 @@ sections: |
| 165 | - Name: '.debug$T' | 165 | - Name: '.debug$T' |
| 166 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 166 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 167 | Alignment: 1 | 167 | Alignment: 1 |
| 168 | Types: | 168 | Types: |
| 169 | - Kind: LF_ARGLIST | 169 | - Kind: LF_ARGLIST |
| 170 | ArgList: | 170 | ArgList: |
| 171 | ArgIndices: [ 0 ] | 171 | ArgIndices: [ 0 ] |
| 172 | - Kind: LF_PROCEDURE | 172 | - Kind: LF_PROCEDURE |
| 173 | Procedure: | 173 | Procedure: |
| 174 | ReturnType: 3 | 174 | ReturnType: 3 |
| 175 | CallConv: NearC | 175 | CallConv: NearC |
| 176 | Options: [ None ] | 176 | Options: [ None ] |
| 177 | ParameterCount: 0 | 177 | ParameterCount: 0 |
| 178 | ArgumentList: 4096 | 178 | ArgumentList: 4096 |
| 179 | - Kind: LF_POINTER | 179 | - Kind: LF_POINTER |
| 180 | Pointer: | 180 | Pointer: |
| 181 | ReferentType: 4097 | 181 | ReferentType: 4097 |
| 182 | Attrs: 65548 | 182 | Attrs: 65548 |
| 183 | - Kind: LF_ARGLIST | 183 | - Kind: LF_ARGLIST |
| 184 | ArgList: | 184 | ArgList: |
| 185 | ArgIndices: [ 116 ] | 185 | ArgIndices: [ 116 ] |
| 186 | - Kind: LF_PROCEDURE | 186 | - Kind: LF_PROCEDURE |
| 187 | Procedure: | 187 | Procedure: |
| 188 | ReturnType: 3 | 188 | ReturnType: 3 |
| 189 | CallConv: NearC | 189 | CallConv: NearC |
| 190 | Options: [ None ] | 190 | Options: [ None ] |
| 191 | ParameterCount: 1 | 191 | ParameterCount: 1 |
| 192 | ArgumentList: 4099 | 192 | ArgumentList: 4099 |
| 193 | - Kind: LF_FUNC_ID | 193 | - Kind: LF_FUNC_ID |
| 194 | FuncId: | 194 | FuncId: |
| 195 | ParentScope: 0 | 195 | ParentScope: 0 |
| 196 | FunctionType: 4100 | 196 | FunctionType: 4100 |
| 197 | Name: f | 197 | Name: f |
| 198 | - Kind: LF_FUNC_ID | 198 | - Kind: LF_FUNC_ID |
| 199 | FuncId: | 199 | FuncId: |
| 200 | ParentScope: 0 | 200 | ParentScope: 0 |
| 201 | FunctionType: 4097 | 201 | FunctionType: 4097 |
| 202 | Name: g | 202 | Name: g |
| 203 | - Kind: LF_STRING_ID | 203 | - Kind: LF_STRING_ID |
| 204 | StringId: | 204 | StringId: |
| 205 | Id: 0 | 205 | Id: 0 |
| 206 | String: 'C:\src\llvm-project\build' | 206 | String: 'C:\src\llvm-project\build' |
| 207 | - Kind: LF_STRING_ID | 207 | - Kind: LF_STRING_ID |
| 208 | StringId: | 208 | StringId: |
| 209 | Id: 0 | 209 | Id: 0 |
| 210 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' | 210 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' |
| 211 | - Kind: LF_STRING_ID | 211 | - Kind: LF_STRING_ID |
| 212 | StringId: | 212 | StringId: |
| 213 | Id: 0 | 213 | Id: 0 |
| 214 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' | 214 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' |
| 215 | - Kind: LF_SUBSTR_LIST | 215 | - Kind: LF_SUBSTR_LIST |
| 216 | StringList: | 216 | StringList: |
| 217 | StringIndices: [ 4105 ] | 217 | StringIndices: [ 4105 ] |
| 218 | - Kind: LF_STRING_ID | 218 | - Kind: LF_STRING_ID |
| 219 | StringId: | 219 | StringId: |
| 220 | Id: 4106 | 220 | Id: 4106 |
| 221 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' | 221 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' |
| 222 | - Kind: LF_STRING_ID | 222 | - Kind: LF_STRING_ID |
| 223 | StringId: | 223 | StringId: |
| 224 | Id: 0 | 224 | Id: 0 |
| 225 | String: b.c | 225 | String: b.c |
| 226 | - Kind: LF_STRING_ID | 226 | - Kind: LF_STRING_ID |
| 227 | StringId: | 227 | StringId: |
| 228 | Id: 0 | 228 | Id: 0 |
| 229 | String: 'C:\src\llvm-project\build\vc140.pdb' | 229 | String: 'C:\src\llvm-project\build\vc140.pdb' |
| 230 | - Kind: LF_BUILDINFO | 230 | - Kind: LF_BUILDINFO |
| 231 | BuildInfo: | 231 | BuildInfo: |
| 232 | ArgIndices: [ 4103, 4104, 4108, 4109, 4107 ] | 232 | ArgIndices: [ 4103, 4104, 4108, 4109, 4107 ] |
| 233 | - Name: '.text$mn' | 233 | - Name: '.text$mn' |
| 234 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 234 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 235 | Alignment: 16 | 235 | Alignment: 16 |
| 236 | SectionData: 894C24084883EC38837C24400074168B44244083C003894424208B4C2420E800000000EB148B44244083C004894424248B4C2424E8000000004883C438C3 | 236 | SectionData: 894C24084883EC38837C24400074168B44244083C003894424208B4C2420E800000000EB148B44244083C004894424248B4C2424E8000000004883C438C3 |
| 237 | Relocations: | 237 | Relocations: |
| 238 | - VirtualAddress: 31 | 238 | - VirtualAddress: 31 |
| 239 | SymbolName: g | 239 | SymbolName: g |
| 240 | Type: IMAGE_REL_AMD64_REL32 | 240 | Type: IMAGE_REL_AMD64_REL32 |
| ... | @@ -249,7 +249,7 @@ sections: | ... | @@ -249,7 +249,7 @@ sections: |
| 249 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | 249 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] |
| 250 | Alignment: 4 | 250 | Alignment: 4 |
| 251 | SectionData: '000000003E00000000000000' | 251 | SectionData: '000000003E00000000000000' |
| 252 | Relocations: | 252 | Relocations: |
| 253 | - VirtualAddress: 0 | 253 | - VirtualAddress: 0 |
| 254 | SymbolName: '$LN5' | 254 | SymbolName: '$LN5' |
| 255 | Type: IMAGE_REL_AMD64_ADDR32NB | 255 | Type: IMAGE_REL_AMD64_ADDR32NB |
| ... | @@ -259,14 +259,14 @@ sections: | ... | @@ -259,14 +259,14 @@ sections: |
| 259 | - VirtualAddress: 8 | 259 | - VirtualAddress: 8 |
| 260 | SymbolName: '$unwind$f' | 260 | SymbolName: '$unwind$f' |
| 261 | Type: IMAGE_REL_AMD64_ADDR32NB | 261 | Type: IMAGE_REL_AMD64_ADDR32NB |
| 262 | symbols: | 262 | symbols: |
| 263 | - Name: .drectve | 263 | - Name: .drectve |
| 264 | Value: 0 | 264 | Value: 0 |
| 265 | SectionNumber: 1 | 265 | SectionNumber: 1 |
| 266 | SimpleType: IMAGE_SYM_TYPE_NULL | 266 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 267 | ComplexType: IMAGE_SYM_DTYPE_NULL | 267 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 268 | StorageClass: IMAGE_SYM_CLASS_STATIC | 268 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 269 | SectionDefinition: | 269 | SectionDefinition: |
| 270 | Length: 47 | 270 | Length: 47 |
| 271 | NumberOfRelocations: 0 | 271 | NumberOfRelocations: 0 |
| 272 | NumberOfLinenumbers: 0 | 272 | NumberOfLinenumbers: 0 |
| ... | @@ -278,7 +278,7 @@ symbols: | ... | @@ -278,7 +278,7 @@ symbols: |
| 278 | SimpleType: IMAGE_SYM_TYPE_NULL | 278 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 279 | ComplexType: IMAGE_SYM_DTYPE_NULL | 279 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 280 | StorageClass: IMAGE_SYM_CLASS_STATIC | 280 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 281 | SectionDefinition: | 281 | SectionDefinition: |
| 282 | Length: 484 | 282 | Length: 484 |
| 283 | NumberOfRelocations: 8 | 283 | NumberOfRelocations: 8 |
| 284 | NumberOfLinenumbers: 0 | 284 | NumberOfLinenumbers: 0 |
| ... | @@ -290,7 +290,7 @@ symbols: | ... | @@ -290,7 +290,7 @@ symbols: |
| 290 | SimpleType: IMAGE_SYM_TYPE_NULL | 290 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 291 | ComplexType: IMAGE_SYM_DTYPE_NULL | 291 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 292 | StorageClass: IMAGE_SYM_CLASS_STATIC | 292 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 293 | SectionDefinition: | 293 | SectionDefinition: |
| 294 | Length: 616 | 294 | Length: 616 |
| 295 | NumberOfRelocations: 0 | 295 | NumberOfRelocations: 0 |
| 296 | NumberOfLinenumbers: 0 | 296 | NumberOfLinenumbers: 0 |
| ... | @@ -302,7 +302,7 @@ symbols: | ... | @@ -302,7 +302,7 @@ symbols: |
| 302 | SimpleType: IMAGE_SYM_TYPE_NULL | 302 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 303 | ComplexType: IMAGE_SYM_DTYPE_NULL | 303 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 304 | StorageClass: IMAGE_SYM_CLASS_STATIC | 304 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 305 | SectionDefinition: | 305 | SectionDefinition: |
| 306 | Length: 62 | 306 | Length: 62 |
| 307 | NumberOfRelocations: 2 | 307 | NumberOfRelocations: 2 |
| 308 | NumberOfLinenumbers: 0 | 308 | NumberOfLinenumbers: 0 |
| ... | @@ -332,7 +332,7 @@ symbols: | ... | @@ -332,7 +332,7 @@ symbols: |
| 332 | SimpleType: IMAGE_SYM_TYPE_NULL | 332 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 333 | ComplexType: IMAGE_SYM_DTYPE_NULL | 333 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 334 | StorageClass: IMAGE_SYM_CLASS_STATIC | 334 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 335 | SectionDefinition: | 335 | SectionDefinition: |
| 336 | Length: 8 | 336 | Length: 8 |
| 337 | NumberOfRelocations: 0 | 337 | NumberOfRelocations: 0 |
| 338 | NumberOfLinenumbers: 0 | 338 | NumberOfLinenumbers: 0 |
| ... | @@ -350,7 +350,7 @@ symbols: | ... | @@ -350,7 +350,7 @@ symbols: |
| 350 | SimpleType: IMAGE_SYM_TYPE_NULL | 350 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 351 | ComplexType: IMAGE_SYM_DTYPE_NULL | 351 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 352 | StorageClass: IMAGE_SYM_CLASS_STATIC | 352 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 353 | SectionDefinition: | 353 | SectionDefinition: |
| 354 | Length: 12 | 354 | Length: 12 |
| 355 | NumberOfRelocations: 3 | 355 | NumberOfRelocations: 3 |
| 356 | NumberOfLinenumbers: 0 | 356 | NumberOfLinenumbers: 0 |
deps/lld/test/COFF/Inputs/pdb_comdat_bar.yaml+58-58| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | --- !COFF | 1 | --- !COFF |
| 2 | header: | 2 | header: |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | 3 | Machine: IMAGE_FILE_MACHINE_AMD64 |
| 4 | Characteristics: [ ] | 4 | Characteristics: [ ] |
| 5 | sections: | 5 | sections: |
| 6 | - Name: .drectve | 6 | - Name: .drectve |
| 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] |
| 8 | Alignment: 1 | 8 | Alignment: 1 |
| ... | @@ -10,15 +10,15 @@ sections: | ... | @@ -10,15 +10,15 @@ sections: |
| 10 | - Name: '.debug$S' | 10 | - Name: '.debug$S' |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 12 | Alignment: 1 | 12 | Alignment: 1 |
| 13 | Subsections: | 13 | Subsections: |
| 14 | - !Symbols | 14 | - !Symbols |
| 15 | Records: | 15 | Records: |
| 16 | - Kind: S_OBJNAME | 16 | - Kind: S_OBJNAME |
| 17 | ObjNameSym: | 17 | ObjNameSym: |
| 18 | Signature: 0 | 18 | Signature: 0 |
| 19 | ObjectName: 'C:\src\llvm-project\build\pdb_comdat_bar.obj' | 19 | ObjectName: 'C:\src\llvm-project\build\pdb_comdat_bar.obj' |
| 20 | - Kind: S_COMPILE3 | 20 | - Kind: S_COMPILE3 |
| 21 | Compile3Sym: | 21 | Compile3Sym: |
| 22 | Flags: [ SecurityChecks, HotPatch ] | 22 | Flags: [ SecurityChecks, HotPatch ] |
| 23 | Machine: X64 | 23 | Machine: X64 |
| 24 | FrontendMajor: 19 | 24 | FrontendMajor: 19 |
| ... | @@ -31,9 +31,9 @@ sections: | ... | @@ -31,9 +31,9 @@ sections: |
| 31 | BackendQFE: 1 | 31 | BackendQFE: 1 |
| 32 | Version: 'Microsoft (R) Optimizing Compiler' | 32 | Version: 'Microsoft (R) Optimizing Compiler' |
| 33 | - !Symbols | 33 | - !Symbols |
| 34 | Records: | 34 | Records: |
| 35 | - Kind: S_GPROC32_ID | 35 | - Kind: S_GPROC32_ID |
| 36 | ProcSym: | 36 | ProcSym: |
| 37 | PtrParent: 0 | 37 | PtrParent: 0 |
| 38 | PtrEnd: 0 | 38 | PtrEnd: 0 |
| 39 | PtrNext: 0 | 39 | PtrNext: 0 |
| ... | @@ -45,7 +45,7 @@ sections: | ... | @@ -45,7 +45,7 @@ sections: |
| 45 | Flags: [ ] | 45 | Flags: [ ] |
| 46 | DisplayName: bar | 46 | DisplayName: bar |
| 47 | - Kind: S_FRAMEPROC | 47 | - Kind: S_FRAMEPROC |
| 48 | FrameProcSym: | 48 | FrameProcSym: |
| 49 | TotalFrameBytes: 40 | 49 | TotalFrameBytes: 40 |
| 50 | PaddingFrameBytes: 0 | 50 | PaddingFrameBytes: 0 |
| 51 | OffsetToPadding: 0 | 51 | OffsetToPadding: 0 |
| ... | @@ -54,15 +54,15 @@ sections: | ... | @@ -54,15 +54,15 @@ sections: |
| 54 | SectionIdOfExceptionHandler: 0 | 54 | SectionIdOfExceptionHandler: 0 |
| 55 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | 55 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 56 | - Kind: S_PROC_ID_END | 56 | - Kind: S_PROC_ID_END |
| 57 | ScopeEndSym: | 57 | ScopeEndSym: |
| 58 | - !Lines | 58 | - !Lines |
| 59 | CodeSize: 14 | 59 | CodeSize: 14 |
| 60 | Flags: [ ] | 60 | Flags: [ ] |
| 61 | RelocOffset: 0 | 61 | RelocOffset: 0 |
| 62 | RelocSegment: 0 | 62 | RelocSegment: 0 |
| 63 | Blocks: | 63 | Blocks: |
| 64 | - FileName: 'c:\src\llvm-project\build\pdb_comdat_bar.c' | 64 | - FileName: 'c:\src\llvm-project\build\pdb_comdat_bar.c' |
| 65 | Lines: | 65 | Lines: |
| 66 | - Offset: 0 | 66 | - Offset: 0 |
| 67 | LineStart: 3 | 67 | LineStart: 3 |
| 68 | IsStatement: true | 68 | IsStatement: true |
| ... | @@ -75,15 +75,15 @@ sections: | ... | @@ -75,15 +75,15 @@ sections: |
| 75 | LineStart: 5 | 75 | LineStart: 5 |
| 76 | IsStatement: true | 76 | IsStatement: true |
| 77 | EndDelta: 0 | 77 | EndDelta: 0 |
| 78 | Columns: | 78 | Columns: |
| 79 | - !Symbols | 79 | - !Symbols |
| 80 | Records: | 80 | Records: |
| 81 | - Kind: S_GDATA32 | 81 | - Kind: S_GDATA32 |
| 82 | DataSym: | 82 | DataSym: |
| 83 | Type: 116 | 83 | Type: 116 |
| 84 | DisplayName: global | 84 | DisplayName: global |
| 85 | - !FileChecksums | 85 | - !FileChecksums |
| 86 | Checksums: | 86 | Checksums: |
| 87 | - FileName: 'c:\src\llvm-project\build\pdb_comdat_bar.c' | 87 | - FileName: 'c:\src\llvm-project\build\pdb_comdat_bar.c' |
| 88 | Kind: MD5 | 88 | Kind: MD5 |
| 89 | Checksum: 365279DB4FCBEDD721BBFC3B14A953C2 | 89 | Checksum: 365279DB4FCBEDD721BBFC3B14A953C2 |
| ... | @@ -91,15 +91,15 @@ sections: | ... | @@ -91,15 +91,15 @@ sections: |
| 91 | Kind: MD5 | 91 | Kind: MD5 |
| 92 | Checksum: D74D834EFAC3AE2B45E606A8320B1D5C | 92 | Checksum: D74D834EFAC3AE2B45E606A8320B1D5C |
| 93 | - !StringTable | 93 | - !StringTable |
| 94 | Strings: | 94 | Strings: |
| 95 | - 'c:\src\llvm-project\build\pdb_comdat_bar.c' | 95 | - 'c:\src\llvm-project\build\pdb_comdat_bar.c' |
| 96 | - 'c:\src\llvm-project\build\foo.h' | 96 | - 'c:\src\llvm-project\build\foo.h' |
| 97 | - !Symbols | 97 | - !Symbols |
| 98 | Records: | 98 | Records: |
| 99 | - Kind: S_BUILDINFO | 99 | - Kind: S_BUILDINFO |
| 100 | BuildInfoSym: | 100 | BuildInfoSym: |
| 101 | BuildId: 4110 | 101 | BuildId: 4110 |
| 102 | Relocations: | 102 | Relocations: |
| 103 | - VirtualAddress: 168 | 103 | - VirtualAddress: 168 |
| 104 | SymbolName: bar | 104 | SymbolName: bar |
| 105 | Type: IMAGE_REL_AMD64_SECREL | 105 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -121,70 +121,70 @@ sections: | ... | @@ -121,70 +121,70 @@ sections: |
| 121 | - Name: '.debug$T' | 121 | - Name: '.debug$T' |
| 122 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 122 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 123 | Alignment: 1 | 123 | Alignment: 1 |
| 124 | Types: | 124 | Types: |
| 125 | - Kind: LF_ARGLIST | 125 | - Kind: LF_ARGLIST |
| 126 | ArgList: | 126 | ArgList: |
| 127 | ArgIndices: [ 0 ] | 127 | ArgIndices: [ 0 ] |
| 128 | - Kind: LF_PROCEDURE | 128 | - Kind: LF_PROCEDURE |
| 129 | Procedure: | 129 | Procedure: |
| 130 | ReturnType: 3 | 130 | ReturnType: 3 |
| 131 | CallConv: NearC | 131 | CallConv: NearC |
| 132 | Options: [ None ] | 132 | Options: [ None ] |
| 133 | ParameterCount: 0 | 133 | ParameterCount: 0 |
| 134 | ArgumentList: 4096 | 134 | ArgumentList: 4096 |
| 135 | - Kind: LF_POINTER | 135 | - Kind: LF_POINTER |
| 136 | Pointer: | 136 | Pointer: |
| 137 | ReferentType: 4097 | 137 | ReferentType: 4097 |
| 138 | Attrs: 65548 | 138 | Attrs: 65548 |
| 139 | - Kind: LF_FUNC_ID | 139 | - Kind: LF_FUNC_ID |
| 140 | FuncId: | 140 | FuncId: |
| 141 | ParentScope: 0 | 141 | ParentScope: 0 |
| 142 | FunctionType: 4097 | 142 | FunctionType: 4097 |
| 143 | Name: foo | 143 | Name: foo |
| 144 | - Kind: LF_ARGLIST | 144 | - Kind: LF_ARGLIST |
| 145 | ArgList: | 145 | ArgList: |
| 146 | ArgIndices: [ ] | 146 | ArgIndices: [ ] |
| 147 | - Kind: LF_PROCEDURE | 147 | - Kind: LF_PROCEDURE |
| 148 | Procedure: | 148 | Procedure: |
| 149 | ReturnType: 3 | 149 | ReturnType: 3 |
| 150 | CallConv: NearC | 150 | CallConv: NearC |
| 151 | Options: [ None ] | 151 | Options: [ None ] |
| 152 | ParameterCount: 0 | 152 | ParameterCount: 0 |
| 153 | ArgumentList: 4100 | 153 | ArgumentList: 4100 |
| 154 | - Kind: LF_FUNC_ID | 154 | - Kind: LF_FUNC_ID |
| 155 | FuncId: | 155 | FuncId: |
| 156 | ParentScope: 0 | 156 | ParentScope: 0 |
| 157 | FunctionType: 4101 | 157 | FunctionType: 4101 |
| 158 | Name: bar | 158 | Name: bar |
| 159 | - Kind: LF_STRING_ID | 159 | - Kind: LF_STRING_ID |
| 160 | StringId: | 160 | StringId: |
| 161 | Id: 0 | 161 | Id: 0 |
| 162 | String: 'C:\src\llvm-project\build' | 162 | String: 'C:\src\llvm-project\build' |
| 163 | - Kind: LF_STRING_ID | 163 | - Kind: LF_STRING_ID |
| 164 | StringId: | 164 | StringId: |
| 165 | Id: 0 | 165 | Id: 0 |
| 166 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' | 166 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' |
| 167 | - Kind: LF_STRING_ID | 167 | - Kind: LF_STRING_ID |
| 168 | StringId: | 168 | StringId: |
| 169 | Id: 0 | 169 | Id: 0 |
| 170 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' | 170 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' |
| 171 | - Kind: LF_SUBSTR_LIST | 171 | - Kind: LF_SUBSTR_LIST |
| 172 | StringList: | 172 | StringList: |
| 173 | StringIndices: [ 4105 ] | 173 | StringIndices: [ 4105 ] |
| 174 | - Kind: LF_STRING_ID | 174 | - Kind: LF_STRING_ID |
| 175 | StringId: | 175 | StringId: |
| 176 | Id: 4106 | 176 | Id: 4106 |
| 177 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' | 177 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' |
| 178 | - Kind: LF_STRING_ID | 178 | - Kind: LF_STRING_ID |
| 179 | StringId: | 179 | StringId: |
| 180 | Id: 0 | 180 | Id: 0 |
| 181 | String: pdb_comdat_bar.c | 181 | String: pdb_comdat_bar.c |
| 182 | - Kind: LF_STRING_ID | 182 | - Kind: LF_STRING_ID |
| 183 | StringId: | 183 | StringId: |
| 184 | Id: 0 | 184 | Id: 0 |
| 185 | String: 'C:\src\llvm-project\build\vc140.pdb' | 185 | String: 'C:\src\llvm-project\build\vc140.pdb' |
| 186 | - Kind: LF_BUILDINFO | 186 | - Kind: LF_BUILDINFO |
| 187 | BuildInfo: | 187 | BuildInfo: |
| 188 | ArgIndices: [ 4103, 4104, 4108, 4109, 4107 ] | 188 | ArgIndices: [ 4103, 4104, 4108, 4109, 4107 ] |
| 189 | - Name: .bss | 189 | - Name: .bss |
| 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 ] |
| ... | @@ -194,7 +194,7 @@ sections: | ... | @@ -194,7 +194,7 @@ sections: |
| 194 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 194 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 195 | Alignment: 16 | 195 | Alignment: 16 |
| 196 | SectionData: 4883EC28E8000000004883C428C3 | 196 | SectionData: 4883EC28E8000000004883C428C3 |
| 197 | Relocations: | 197 | Relocations: |
| 198 | - VirtualAddress: 5 | 198 | - VirtualAddress: 5 |
| 199 | SymbolName: foo | 199 | SymbolName: foo |
| 200 | Type: IMAGE_REL_AMD64_REL32 | 200 | Type: IMAGE_REL_AMD64_REL32 |
| ... | @@ -202,7 +202,7 @@ sections: | ... | @@ -202,7 +202,7 @@ sections: |
| 202 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 202 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 203 | Alignment: 16 | 203 | Alignment: 16 |
| 204 | SectionData: 8B0500000000FFC0890500000000C3 | 204 | SectionData: 8B0500000000FFC0890500000000C3 |
| 205 | Relocations: | 205 | Relocations: |
| 206 | - VirtualAddress: 2 | 206 | - VirtualAddress: 2 |
| 207 | SymbolName: global | 207 | SymbolName: global |
| 208 | Type: IMAGE_REL_AMD64_REL32 | 208 | Type: IMAGE_REL_AMD64_REL32 |
| ... | @@ -212,11 +212,11 @@ sections: | ... | @@ -212,11 +212,11 @@ sections: |
| 212 | - Name: '.debug$S' | 212 | - Name: '.debug$S' |
| 213 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 213 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 214 | Alignment: 1 | 214 | Alignment: 1 |
| 215 | Subsections: | 215 | Subsections: |
| 216 | - !Symbols | 216 | - !Symbols |
| 217 | Records: | 217 | Records: |
| 218 | - Kind: S_GPROC32_ID | 218 | - Kind: S_GPROC32_ID |
| 219 | ProcSym: | 219 | ProcSym: |
| 220 | PtrParent: 0 | 220 | PtrParent: 0 |
| 221 | PtrEnd: 0 | 221 | PtrEnd: 0 |
| 222 | PtrNext: 0 | 222 | PtrNext: 0 |
| ... | @@ -228,7 +228,7 @@ sections: | ... | @@ -228,7 +228,7 @@ sections: |
| 228 | Flags: [ ] | 228 | Flags: [ ] |
| 229 | DisplayName: foo | 229 | DisplayName: foo |
| 230 | - Kind: S_FRAMEPROC | 230 | - Kind: S_FRAMEPROC |
| 231 | FrameProcSym: | 231 | FrameProcSym: |
| 232 | TotalFrameBytes: 0 | 232 | TotalFrameBytes: 0 |
| 233 | PaddingFrameBytes: 0 | 233 | PaddingFrameBytes: 0 |
| 234 | OffsetToPadding: 0 | 234 | OffsetToPadding: 0 |
| ... | @@ -237,15 +237,15 @@ sections: | ... | @@ -237,15 +237,15 @@ sections: |
| 237 | SectionIdOfExceptionHandler: 0 | 237 | SectionIdOfExceptionHandler: 0 |
| 238 | Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] | 238 | Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 239 | - Kind: S_PROC_ID_END | 239 | - Kind: S_PROC_ID_END |
| 240 | ScopeEndSym: | 240 | ScopeEndSym: |
| 241 | - !Lines | 241 | - !Lines |
| 242 | CodeSize: 15 | 242 | CodeSize: 15 |
| 243 | Flags: [ ] | 243 | Flags: [ ] |
| 244 | RelocOffset: 0 | 244 | RelocOffset: 0 |
| 245 | RelocSegment: 0 | 245 | RelocSegment: 0 |
| 246 | Blocks: | 246 | Blocks: |
| 247 | - FileName: 'c:\src\llvm-project\build\foo.h' | 247 | - FileName: 'c:\src\llvm-project\build\foo.h' |
| 248 | Lines: | 248 | Lines: |
| 249 | - Offset: 0 | 249 | - Offset: 0 |
| 250 | LineStart: 2 | 250 | LineStart: 2 |
| 251 | IsStatement: true | 251 | IsStatement: true |
| ... | @@ -258,8 +258,8 @@ sections: | ... | @@ -258,8 +258,8 @@ sections: |
| 258 | LineStart: 4 | 258 | LineStart: 4 |
| 259 | IsStatement: true | 259 | IsStatement: true |
| 260 | EndDelta: 0 | 260 | EndDelta: 0 |
| 261 | Columns: | 261 | Columns: |
| 262 | Relocations: | 262 | Relocations: |
| 263 | - VirtualAddress: 44 | 263 | - VirtualAddress: 44 |
| 264 | SymbolName: foo | 264 | SymbolName: foo |
| 265 | Type: IMAGE_REL_AMD64_SECREL | 265 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -280,7 +280,7 @@ sections: | ... | @@ -280,7 +280,7 @@ sections: |
| 280 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | 280 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] |
| 281 | Alignment: 4 | 281 | Alignment: 4 |
| 282 | SectionData: '000000000E00000000000000' | 282 | SectionData: '000000000E00000000000000' |
| 283 | Relocations: | 283 | Relocations: |
| 284 | - VirtualAddress: 0 | 284 | - VirtualAddress: 0 |
| 285 | SymbolName: '$LN3' | 285 | SymbolName: '$LN3' |
| 286 | Type: IMAGE_REL_AMD64_ADDR32NB | 286 | Type: IMAGE_REL_AMD64_ADDR32NB |
| ... | @@ -290,14 +290,14 @@ sections: | ... | @@ -290,14 +290,14 @@ sections: |
| 290 | - VirtualAddress: 8 | 290 | - VirtualAddress: 8 |
| 291 | SymbolName: '$unwind$bar' | 291 | SymbolName: '$unwind$bar' |
| 292 | Type: IMAGE_REL_AMD64_ADDR32NB | 292 | Type: IMAGE_REL_AMD64_ADDR32NB |
| 293 | symbols: | 293 | symbols: |
| 294 | - Name: .drectve | 294 | - Name: .drectve |
| 295 | Value: 0 | 295 | Value: 0 |
| 296 | SectionNumber: 1 | 296 | SectionNumber: 1 |
| 297 | SimpleType: IMAGE_SYM_TYPE_NULL | 297 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 298 | ComplexType: IMAGE_SYM_DTYPE_NULL | 298 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 299 | StorageClass: IMAGE_SYM_CLASS_STATIC | 299 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 300 | SectionDefinition: | 300 | SectionDefinition: |
| 301 | Length: 47 | 301 | Length: 47 |
| 302 | NumberOfRelocations: 0 | 302 | NumberOfRelocations: 0 |
| 303 | NumberOfLinenumbers: 0 | 303 | NumberOfLinenumbers: 0 |
| ... | @@ -309,7 +309,7 @@ symbols: | ... | @@ -309,7 +309,7 @@ symbols: |
| 309 | SimpleType: IMAGE_SYM_TYPE_NULL | 309 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 310 | ComplexType: IMAGE_SYM_DTYPE_NULL | 310 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 311 | StorageClass: IMAGE_SYM_CLASS_STATIC | 311 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 312 | SectionDefinition: | 312 | SectionDefinition: |
| 313 | Length: 460 | 313 | Length: 460 |
| 314 | NumberOfRelocations: 6 | 314 | NumberOfRelocations: 6 |
| 315 | NumberOfLinenumbers: 0 | 315 | NumberOfLinenumbers: 0 |
| ... | @@ -321,7 +321,7 @@ symbols: | ... | @@ -321,7 +321,7 @@ symbols: |
| 321 | SimpleType: IMAGE_SYM_TYPE_NULL | 321 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 322 | ComplexType: IMAGE_SYM_DTYPE_NULL | 322 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 323 | StorageClass: IMAGE_SYM_CLASS_STATIC | 323 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 324 | SectionDefinition: | 324 | SectionDefinition: |
| 325 | Length: 628 | 325 | Length: 628 |
| 326 | NumberOfRelocations: 0 | 326 | NumberOfRelocations: 0 |
| 327 | NumberOfLinenumbers: 0 | 327 | NumberOfLinenumbers: 0 |
| ... | @@ -333,7 +333,7 @@ symbols: | ... | @@ -333,7 +333,7 @@ symbols: |
| 333 | SimpleType: IMAGE_SYM_TYPE_NULL | 333 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 334 | ComplexType: IMAGE_SYM_DTYPE_NULL | 334 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 335 | StorageClass: IMAGE_SYM_CLASS_STATIC | 335 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 336 | SectionDefinition: | 336 | SectionDefinition: |
| 337 | Length: 4 | 337 | Length: 4 |
| 338 | NumberOfRelocations: 0 | 338 | NumberOfRelocations: 0 |
| 339 | NumberOfLinenumbers: 0 | 339 | NumberOfLinenumbers: 0 |
| ... | @@ -351,7 +351,7 @@ symbols: | ... | @@ -351,7 +351,7 @@ symbols: |
| 351 | SimpleType: IMAGE_SYM_TYPE_NULL | 351 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 352 | ComplexType: IMAGE_SYM_DTYPE_NULL | 352 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 353 | StorageClass: IMAGE_SYM_CLASS_STATIC | 353 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 354 | SectionDefinition: | 354 | SectionDefinition: |
| 355 | Length: 14 | 355 | Length: 14 |
| 356 | NumberOfRelocations: 1 | 356 | NumberOfRelocations: 1 |
| 357 | NumberOfLinenumbers: 0 | 357 | NumberOfLinenumbers: 0 |
| ... | @@ -363,7 +363,7 @@ symbols: | ... | @@ -363,7 +363,7 @@ symbols: |
| 363 | SimpleType: IMAGE_SYM_TYPE_NULL | 363 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 364 | ComplexType: IMAGE_SYM_DTYPE_NULL | 364 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 365 | StorageClass: IMAGE_SYM_CLASS_STATIC | 365 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 366 | SectionDefinition: | 366 | SectionDefinition: |
| 367 | Length: 15 | 367 | Length: 15 |
| 368 | NumberOfRelocations: 2 | 368 | NumberOfRelocations: 2 |
| 369 | NumberOfLinenumbers: 0 | 369 | NumberOfLinenumbers: 0 |
| ... | @@ -376,7 +376,7 @@ symbols: | ... | @@ -376,7 +376,7 @@ symbols: |
| 376 | SimpleType: IMAGE_SYM_TYPE_NULL | 376 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 377 | ComplexType: IMAGE_SYM_DTYPE_NULL | 377 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 378 | StorageClass: IMAGE_SYM_CLASS_STATIC | 378 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 379 | SectionDefinition: | 379 | SectionDefinition: |
| 380 | Length: 148 | 380 | Length: 148 |
| 381 | NumberOfRelocations: 4 | 381 | NumberOfRelocations: 4 |
| 382 | NumberOfLinenumbers: 0 | 382 | NumberOfLinenumbers: 0 |
| ... | @@ -407,7 +407,7 @@ symbols: | ... | @@ -407,7 +407,7 @@ symbols: |
| 407 | SimpleType: IMAGE_SYM_TYPE_NULL | 407 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 408 | ComplexType: IMAGE_SYM_DTYPE_NULL | 408 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 409 | StorageClass: IMAGE_SYM_CLASS_STATIC | 409 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 410 | SectionDefinition: | 410 | SectionDefinition: |
| 411 | Length: 8 | 411 | Length: 8 |
| 412 | NumberOfRelocations: 0 | 412 | NumberOfRelocations: 0 |
| 413 | NumberOfLinenumbers: 0 | 413 | NumberOfLinenumbers: 0 |
| ... | @@ -425,7 +425,7 @@ symbols: | ... | @@ -425,7 +425,7 @@ symbols: |
| 425 | SimpleType: IMAGE_SYM_TYPE_NULL | 425 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 426 | ComplexType: IMAGE_SYM_DTYPE_NULL | 426 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 427 | StorageClass: IMAGE_SYM_CLASS_STATIC | 427 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 428 | SectionDefinition: | 428 | SectionDefinition: |
| 429 | Length: 12 | 429 | Length: 12 |
| 430 | NumberOfRelocations: 3 | 430 | NumberOfRelocations: 3 |
| 431 | NumberOfLinenumbers: 0 | 431 | NumberOfLinenumbers: 0 |
deps/lld/test/COFF/Inputs/pdb_comdat_main.yaml+58-58| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | --- !COFF | 1 | --- !COFF |
| 2 | header: | 2 | header: |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | 3 | Machine: IMAGE_FILE_MACHINE_AMD64 |
| 4 | Characteristics: [ ] | 4 | Characteristics: [ ] |
| 5 | sections: | 5 | sections: |
| 6 | - Name: .drectve | 6 | - Name: .drectve |
| 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] |
| 8 | Alignment: 1 | 8 | Alignment: 1 |
| ... | @@ -10,15 +10,15 @@ sections: | ... | @@ -10,15 +10,15 @@ sections: |
| 10 | - Name: '.debug$S' | 10 | - Name: '.debug$S' |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 12 | Alignment: 1 | 12 | Alignment: 1 |
| 13 | Subsections: | 13 | Subsections: |
| 14 | - !Symbols | 14 | - !Symbols |
| 15 | Records: | 15 | Records: |
| 16 | - Kind: S_OBJNAME | 16 | - Kind: S_OBJNAME |
| 17 | ObjNameSym: | 17 | ObjNameSym: |
| 18 | Signature: 0 | 18 | Signature: 0 |
| 19 | ObjectName: 'C:\src\llvm-project\build\pdb_comdat_main.obj' | 19 | ObjectName: 'C:\src\llvm-project\build\pdb_comdat_main.obj' |
| 20 | - Kind: S_COMPILE3 | 20 | - Kind: S_COMPILE3 |
| 21 | Compile3Sym: | 21 | Compile3Sym: |
| 22 | Flags: [ SecurityChecks, HotPatch ] | 22 | Flags: [ SecurityChecks, HotPatch ] |
| 23 | Machine: X64 | 23 | Machine: X64 |
| 24 | FrontendMajor: 19 | 24 | FrontendMajor: 19 |
| ... | @@ -31,9 +31,9 @@ sections: | ... | @@ -31,9 +31,9 @@ sections: |
| 31 | BackendQFE: 1 | 31 | BackendQFE: 1 |
| 32 | Version: 'Microsoft (R) Optimizing Compiler' | 32 | Version: 'Microsoft (R) Optimizing Compiler' |
| 33 | - !Symbols | 33 | - !Symbols |
| 34 | Records: | 34 | Records: |
| 35 | - Kind: S_GPROC32_ID | 35 | - Kind: S_GPROC32_ID |
| 36 | ProcSym: | 36 | ProcSym: |
| 37 | PtrParent: 0 | 37 | PtrParent: 0 |
| 38 | PtrEnd: 0 | 38 | PtrEnd: 0 |
| 39 | PtrNext: 0 | 39 | PtrNext: 0 |
| ... | @@ -45,7 +45,7 @@ sections: | ... | @@ -45,7 +45,7 @@ sections: |
| 45 | Flags: [ ] | 45 | Flags: [ ] |
| 46 | DisplayName: main | 46 | DisplayName: main |
| 47 | - Kind: S_FRAMEPROC | 47 | - Kind: S_FRAMEPROC |
| 48 | FrameProcSym: | 48 | FrameProcSym: |
| 49 | TotalFrameBytes: 40 | 49 | TotalFrameBytes: 40 |
| 50 | PaddingFrameBytes: 0 | 50 | PaddingFrameBytes: 0 |
| 51 | OffsetToPadding: 0 | 51 | OffsetToPadding: 0 |
| ... | @@ -54,15 +54,15 @@ sections: | ... | @@ -54,15 +54,15 @@ sections: |
| 54 | SectionIdOfExceptionHandler: 0 | 54 | SectionIdOfExceptionHandler: 0 |
| 55 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | 55 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 56 | - Kind: S_PROC_ID_END | 56 | - Kind: S_PROC_ID_END |
| 57 | ScopeEndSym: | 57 | ScopeEndSym: |
| 58 | - !Lines | 58 | - !Lines |
| 59 | CodeSize: 24 | 59 | CodeSize: 24 |
| 60 | Flags: [ ] | 60 | Flags: [ ] |
| 61 | RelocOffset: 0 | 61 | RelocOffset: 0 |
| 62 | RelocSegment: 0 | 62 | RelocSegment: 0 |
| 63 | Blocks: | 63 | Blocks: |
| 64 | - FileName: 'c:\src\llvm-project\build\pdb_comdat_main.c' | 64 | - FileName: 'c:\src\llvm-project\build\pdb_comdat_main.c' |
| 65 | Lines: | 65 | Lines: |
| 66 | - Offset: 0 | 66 | - Offset: 0 |
| 67 | LineStart: 2 | 67 | LineStart: 2 |
| 68 | IsStatement: true | 68 | IsStatement: true |
| ... | @@ -83,15 +83,15 @@ sections: | ... | @@ -83,15 +83,15 @@ sections: |
| 83 | LineStart: 6 | 83 | LineStart: 6 |
| 84 | IsStatement: true | 84 | IsStatement: true |
| 85 | EndDelta: 0 | 85 | EndDelta: 0 |
| 86 | Columns: | 86 | Columns: |
| 87 | - !Symbols | 87 | - !Symbols |
| 88 | Records: | 88 | Records: |
| 89 | - Kind: S_GDATA32 | 89 | - Kind: S_GDATA32 |
| 90 | DataSym: | 90 | DataSym: |
| 91 | Type: 116 | 91 | Type: 116 |
| 92 | DisplayName: global | 92 | DisplayName: global |
| 93 | - !FileChecksums | 93 | - !FileChecksums |
| 94 | Checksums: | 94 | Checksums: |
| 95 | - FileName: 'c:\src\llvm-project\build\pdb_comdat_main.c' | 95 | - FileName: 'c:\src\llvm-project\build\pdb_comdat_main.c' |
| 96 | Kind: MD5 | 96 | Kind: MD5 |
| 97 | Checksum: F969E51BBE373436D81492EB61387F36 | 97 | Checksum: F969E51BBE373436D81492EB61387F36 |
| ... | @@ -99,15 +99,15 @@ sections: | ... | @@ -99,15 +99,15 @@ sections: |
| 99 | Kind: MD5 | 99 | Kind: MD5 |
| 100 | Checksum: D74D834EFAC3AE2B45E606A8320B1D5C | 100 | Checksum: D74D834EFAC3AE2B45E606A8320B1D5C |
| 101 | - !StringTable | 101 | - !StringTable |
| 102 | Strings: | 102 | Strings: |
| 103 | - 'c:\src\llvm-project\build\pdb_comdat_main.c' | 103 | - 'c:\src\llvm-project\build\pdb_comdat_main.c' |
| 104 | - 'c:\src\llvm-project\build\foo.h' | 104 | - 'c:\src\llvm-project\build\foo.h' |
| 105 | - !Symbols | 105 | - !Symbols |
| 106 | Records: | 106 | Records: |
| 107 | - Kind: S_BUILDINFO | 107 | - Kind: S_BUILDINFO |
| 108 | BuildInfoSym: | 108 | BuildInfoSym: |
| 109 | BuildId: 4111 | 109 | BuildId: 4111 |
| 110 | Relocations: | 110 | Relocations: |
| 111 | - VirtualAddress: 168 | 111 | - VirtualAddress: 168 |
| 112 | SymbolName: main | 112 | SymbolName: main |
| 113 | Type: IMAGE_REL_AMD64_SECREL | 113 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -129,81 +129,81 @@ sections: | ... | @@ -129,81 +129,81 @@ sections: |
| 129 | - Name: '.debug$T' | 129 | - Name: '.debug$T' |
| 130 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 130 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 131 | Alignment: 1 | 131 | Alignment: 1 |
| 132 | Types: | 132 | Types: |
| 133 | - Kind: LF_ARGLIST | 133 | - Kind: LF_ARGLIST |
| 134 | ArgList: | 134 | ArgList: |
| 135 | ArgIndices: [ 0 ] | 135 | ArgIndices: [ 0 ] |
| 136 | - Kind: LF_PROCEDURE | 136 | - Kind: LF_PROCEDURE |
| 137 | Procedure: | 137 | Procedure: |
| 138 | ReturnType: 3 | 138 | ReturnType: 3 |
| 139 | CallConv: NearC | 139 | CallConv: NearC |
| 140 | Options: [ None ] | 140 | Options: [ None ] |
| 141 | ParameterCount: 0 | 141 | ParameterCount: 0 |
| 142 | ArgumentList: 4096 | 142 | ArgumentList: 4096 |
| 143 | - Kind: LF_POINTER | 143 | - Kind: LF_POINTER |
| 144 | Pointer: | 144 | Pointer: |
| 145 | ReferentType: 4097 | 145 | ReferentType: 4097 |
| 146 | Attrs: 65548 | 146 | Attrs: 65548 |
| 147 | - Kind: LF_FUNC_ID | 147 | - Kind: LF_FUNC_ID |
| 148 | FuncId: | 148 | FuncId: |
| 149 | ParentScope: 0 | 149 | ParentScope: 0 |
| 150 | FunctionType: 4097 | 150 | FunctionType: 4097 |
| 151 | Name: foo | 151 | Name: foo |
| 152 | - Kind: LF_ARGLIST | 152 | - Kind: LF_ARGLIST |
| 153 | ArgList: | 153 | ArgList: |
| 154 | ArgIndices: [ ] | 154 | ArgIndices: [ ] |
| 155 | - Kind: LF_PROCEDURE | 155 | - Kind: LF_PROCEDURE |
| 156 | Procedure: | 156 | Procedure: |
| 157 | ReturnType: 116 | 157 | ReturnType: 116 |
| 158 | CallConv: NearC | 158 | CallConv: NearC |
| 159 | Options: [ None ] | 159 | Options: [ None ] |
| 160 | ParameterCount: 0 | 160 | ParameterCount: 0 |
| 161 | ArgumentList: 4100 | 161 | ArgumentList: 4100 |
| 162 | - Kind: LF_FUNC_ID | 162 | - Kind: LF_FUNC_ID |
| 163 | FuncId: | 163 | FuncId: |
| 164 | ParentScope: 0 | 164 | ParentScope: 0 |
| 165 | FunctionType: 4101 | 165 | FunctionType: 4101 |
| 166 | Name: main | 166 | Name: main |
| 167 | - Kind: LF_FUNC_ID | 167 | - Kind: LF_FUNC_ID |
| 168 | FuncId: | 168 | FuncId: |
| 169 | ParentScope: 0 | 169 | ParentScope: 0 |
| 170 | FunctionType: 4097 | 170 | FunctionType: 4097 |
| 171 | Name: bar | 171 | Name: bar |
| 172 | - Kind: LF_STRING_ID | 172 | - Kind: LF_STRING_ID |
| 173 | StringId: | 173 | StringId: |
| 174 | Id: 0 | 174 | Id: 0 |
| 175 | String: 'C:\src\llvm-project\build' | 175 | String: 'C:\src\llvm-project\build' |
| 176 | - Kind: LF_STRING_ID | 176 | - Kind: LF_STRING_ID |
| 177 | StringId: | 177 | StringId: |
| 178 | Id: 0 | 178 | Id: 0 |
| 179 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' | 179 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' |
| 180 | - Kind: LF_STRING_ID | 180 | - Kind: LF_STRING_ID |
| 181 | StringId: | 181 | StringId: |
| 182 | Id: 0 | 182 | Id: 0 |
| 183 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' | 183 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' |
| 184 | - Kind: LF_SUBSTR_LIST | 184 | - Kind: LF_SUBSTR_LIST |
| 185 | StringList: | 185 | StringList: |
| 186 | StringIndices: [ 4106 ] | 186 | StringIndices: [ 4106 ] |
| 187 | - Kind: LF_STRING_ID | 187 | - Kind: LF_STRING_ID |
| 188 | StringId: | 188 | StringId: |
| 189 | Id: 4107 | 189 | Id: 4107 |
| 190 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' | 190 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' |
| 191 | - Kind: LF_STRING_ID | 191 | - Kind: LF_STRING_ID |
| 192 | StringId: | 192 | StringId: |
| 193 | Id: 0 | 193 | Id: 0 |
| 194 | String: pdb_comdat_main.c | 194 | String: pdb_comdat_main.c |
| 195 | - Kind: LF_STRING_ID | 195 | - Kind: LF_STRING_ID |
| 196 | StringId: | 196 | StringId: |
| 197 | Id: 0 | 197 | Id: 0 |
| 198 | String: 'C:\src\llvm-project\build\vc140.pdb' | 198 | String: 'C:\src\llvm-project\build\vc140.pdb' |
| 199 | - Kind: LF_BUILDINFO | 199 | - Kind: LF_BUILDINFO |
| 200 | BuildInfo: | 200 | BuildInfo: |
| 201 | ArgIndices: [ 4104, 4105, 4109, 4110, 4108 ] | 201 | ArgIndices: [ 4104, 4105, 4109, 4110, 4108 ] |
| 202 | - Name: '.text$mn' | 202 | - Name: '.text$mn' |
| 203 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 203 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 204 | Alignment: 16 | 204 | Alignment: 16 |
| 205 | SectionData: 4883EC28E800000000E800000000B82A0000004883C428C3 | 205 | SectionData: 4883EC28E800000000E800000000B82A0000004883C428C3 |
| 206 | Relocations: | 206 | Relocations: |
| 207 | - VirtualAddress: 5 | 207 | - VirtualAddress: 5 |
| 208 | SymbolName: foo | 208 | SymbolName: foo |
| 209 | Type: IMAGE_REL_AMD64_REL32 | 209 | Type: IMAGE_REL_AMD64_REL32 |
| ... | @@ -214,7 +214,7 @@ sections: | ... | @@ -214,7 +214,7 @@ sections: |
| 214 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 214 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 215 | Alignment: 16 | 215 | Alignment: 16 |
| 216 | SectionData: 8B0500000000FFC0890500000000C3 | 216 | SectionData: 8B0500000000FFC0890500000000C3 |
| 217 | Relocations: | 217 | Relocations: |
| 218 | - VirtualAddress: 2 | 218 | - VirtualAddress: 2 |
| 219 | SymbolName: global | 219 | SymbolName: global |
| 220 | Type: IMAGE_REL_AMD64_REL32 | 220 | Type: IMAGE_REL_AMD64_REL32 |
| ... | @@ -224,11 +224,11 @@ sections: | ... | @@ -224,11 +224,11 @@ sections: |
| 224 | - Name: '.debug$S' | 224 | - Name: '.debug$S' |
| 225 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 225 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 226 | Alignment: 1 | 226 | Alignment: 1 |
| 227 | Subsections: | 227 | Subsections: |
| 228 | - !Symbols | 228 | - !Symbols |
| 229 | Records: | 229 | Records: |
| 230 | - Kind: S_GPROC32_ID | 230 | - Kind: S_GPROC32_ID |
| 231 | ProcSym: | 231 | ProcSym: |
| 232 | PtrParent: 0 | 232 | PtrParent: 0 |
| 233 | PtrEnd: 0 | 233 | PtrEnd: 0 |
| 234 | PtrNext: 0 | 234 | PtrNext: 0 |
| ... | @@ -240,7 +240,7 @@ sections: | ... | @@ -240,7 +240,7 @@ sections: |
| 240 | Flags: [ ] | 240 | Flags: [ ] |
| 241 | DisplayName: foo | 241 | DisplayName: foo |
| 242 | - Kind: S_FRAMEPROC | 242 | - Kind: S_FRAMEPROC |
| 243 | FrameProcSym: | 243 | FrameProcSym: |
| 244 | TotalFrameBytes: 0 | 244 | TotalFrameBytes: 0 |
| 245 | PaddingFrameBytes: 0 | 245 | PaddingFrameBytes: 0 |
| 246 | OffsetToPadding: 0 | 246 | OffsetToPadding: 0 |
| ... | @@ -249,15 +249,15 @@ sections: | ... | @@ -249,15 +249,15 @@ sections: |
| 249 | SectionIdOfExceptionHandler: 0 | 249 | SectionIdOfExceptionHandler: 0 |
| 250 | Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] | 250 | Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 251 | - Kind: S_PROC_ID_END | 251 | - Kind: S_PROC_ID_END |
| 252 | ScopeEndSym: | 252 | ScopeEndSym: |
| 253 | - !Lines | 253 | - !Lines |
| 254 | CodeSize: 15 | 254 | CodeSize: 15 |
| 255 | Flags: [ ] | 255 | Flags: [ ] |
| 256 | RelocOffset: 0 | 256 | RelocOffset: 0 |
| 257 | RelocSegment: 0 | 257 | RelocSegment: 0 |
| 258 | Blocks: | 258 | Blocks: |
| 259 | - FileName: 'c:\src\llvm-project\build\foo.h' | 259 | - FileName: 'c:\src\llvm-project\build\foo.h' |
| 260 | Lines: | 260 | Lines: |
| 261 | - Offset: 0 | 261 | - Offset: 0 |
| 262 | LineStart: 2 | 262 | LineStart: 2 |
| 263 | IsStatement: true | 263 | IsStatement: true |
| ... | @@ -270,8 +270,8 @@ sections: | ... | @@ -270,8 +270,8 @@ sections: |
| 270 | LineStart: 4 | 270 | LineStart: 4 |
| 271 | IsStatement: true | 271 | IsStatement: true |
| 272 | EndDelta: 0 | 272 | EndDelta: 0 |
| 273 | Columns: | 273 | Columns: |
| 274 | Relocations: | 274 | Relocations: |
| 275 | - VirtualAddress: 44 | 275 | - VirtualAddress: 44 |
| 276 | SymbolName: foo | 276 | SymbolName: foo |
| 277 | Type: IMAGE_REL_AMD64_SECREL | 277 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -292,7 +292,7 @@ sections: | ... | @@ -292,7 +292,7 @@ sections: |
| 292 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | 292 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] |
| 293 | Alignment: 4 | 293 | Alignment: 4 |
| 294 | SectionData: '000000001800000000000000' | 294 | SectionData: '000000001800000000000000' |
| 295 | Relocations: | 295 | Relocations: |
| 296 | - VirtualAddress: 0 | 296 | - VirtualAddress: 0 |
| 297 | SymbolName: '$LN3' | 297 | SymbolName: '$LN3' |
| 298 | Type: IMAGE_REL_AMD64_ADDR32NB | 298 | Type: IMAGE_REL_AMD64_ADDR32NB |
| ... | @@ -302,14 +302,14 @@ sections: | ... | @@ -302,14 +302,14 @@ sections: |
| 302 | - VirtualAddress: 8 | 302 | - VirtualAddress: 8 |
| 303 | SymbolName: '$unwind$main' | 303 | SymbolName: '$unwind$main' |
| 304 | Type: IMAGE_REL_AMD64_ADDR32NB | 304 | Type: IMAGE_REL_AMD64_ADDR32NB |
| 305 | symbols: | 305 | symbols: |
| 306 | - Name: .drectve | 306 | - Name: .drectve |
| 307 | Value: 0 | 307 | Value: 0 |
| 308 | SectionNumber: 1 | 308 | SectionNumber: 1 |
| 309 | SimpleType: IMAGE_SYM_TYPE_NULL | 309 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 310 | ComplexType: IMAGE_SYM_DTYPE_NULL | 310 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 311 | StorageClass: IMAGE_SYM_CLASS_STATIC | 311 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 312 | SectionDefinition: | 312 | SectionDefinition: |
| 313 | Length: 47 | 313 | Length: 47 |
| 314 | NumberOfRelocations: 0 | 314 | NumberOfRelocations: 0 |
| 315 | NumberOfLinenumbers: 0 | 315 | NumberOfLinenumbers: 0 |
| ... | @@ -321,7 +321,7 @@ symbols: | ... | @@ -321,7 +321,7 @@ symbols: |
| 321 | SimpleType: IMAGE_SYM_TYPE_NULL | 321 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 322 | ComplexType: IMAGE_SYM_DTYPE_NULL | 322 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 323 | StorageClass: IMAGE_SYM_CLASS_STATIC | 323 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 324 | SectionDefinition: | 324 | SectionDefinition: |
| 325 | Length: 480 | 325 | Length: 480 |
| 326 | NumberOfRelocations: 6 | 326 | NumberOfRelocations: 6 |
| 327 | NumberOfLinenumbers: 0 | 327 | NumberOfLinenumbers: 0 |
| ... | @@ -333,7 +333,7 @@ symbols: | ... | @@ -333,7 +333,7 @@ symbols: |
| 333 | SimpleType: IMAGE_SYM_TYPE_NULL | 333 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 334 | ComplexType: IMAGE_SYM_DTYPE_NULL | 334 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 335 | StorageClass: IMAGE_SYM_CLASS_STATIC | 335 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 336 | SectionDefinition: | 336 | SectionDefinition: |
| 337 | Length: 648 | 337 | Length: 648 |
| 338 | NumberOfRelocations: 0 | 338 | NumberOfRelocations: 0 |
| 339 | NumberOfLinenumbers: 0 | 339 | NumberOfLinenumbers: 0 |
| ... | @@ -345,7 +345,7 @@ symbols: | ... | @@ -345,7 +345,7 @@ symbols: |
| 345 | SimpleType: IMAGE_SYM_TYPE_NULL | 345 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 346 | ComplexType: IMAGE_SYM_DTYPE_NULL | 346 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 347 | StorageClass: IMAGE_SYM_CLASS_STATIC | 347 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 348 | SectionDefinition: | 348 | SectionDefinition: |
| 349 | Length: 24 | 349 | Length: 24 |
| 350 | NumberOfRelocations: 2 | 350 | NumberOfRelocations: 2 |
| 351 | NumberOfLinenumbers: 0 | 351 | NumberOfLinenumbers: 0 |
| ... | @@ -357,7 +357,7 @@ symbols: | ... | @@ -357,7 +357,7 @@ symbols: |
| 357 | SimpleType: IMAGE_SYM_TYPE_NULL | 357 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 358 | ComplexType: IMAGE_SYM_DTYPE_NULL | 358 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 359 | StorageClass: IMAGE_SYM_CLASS_STATIC | 359 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 360 | SectionDefinition: | 360 | SectionDefinition: |
| 361 | Length: 15 | 361 | Length: 15 |
| 362 | NumberOfRelocations: 2 | 362 | NumberOfRelocations: 2 |
| 363 | NumberOfLinenumbers: 0 | 363 | NumberOfLinenumbers: 0 |
| ... | @@ -370,7 +370,7 @@ symbols: | ... | @@ -370,7 +370,7 @@ symbols: |
| 370 | SimpleType: IMAGE_SYM_TYPE_NULL | 370 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 371 | ComplexType: IMAGE_SYM_DTYPE_NULL | 371 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 372 | StorageClass: IMAGE_SYM_CLASS_STATIC | 372 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 373 | SectionDefinition: | 373 | SectionDefinition: |
| 374 | Length: 148 | 374 | Length: 148 |
| 375 | NumberOfRelocations: 4 | 375 | NumberOfRelocations: 4 |
| 376 | NumberOfLinenumbers: 0 | 376 | NumberOfLinenumbers: 0 |
| ... | @@ -407,7 +407,7 @@ symbols: | ... | @@ -407,7 +407,7 @@ symbols: |
| 407 | SimpleType: IMAGE_SYM_TYPE_NULL | 407 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 408 | ComplexType: IMAGE_SYM_DTYPE_NULL | 408 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 409 | StorageClass: IMAGE_SYM_CLASS_STATIC | 409 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 410 | SectionDefinition: | 410 | SectionDefinition: |
| 411 | Length: 8 | 411 | Length: 8 |
| 412 | NumberOfRelocations: 0 | 412 | NumberOfRelocations: 0 |
| 413 | NumberOfLinenumbers: 0 | 413 | NumberOfLinenumbers: 0 |
| ... | @@ -425,7 +425,7 @@ symbols: | ... | @@ -425,7 +425,7 @@ symbols: |
| 425 | SimpleType: IMAGE_SYM_TYPE_NULL | 425 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 426 | ComplexType: IMAGE_SYM_DTYPE_NULL | 426 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 427 | StorageClass: IMAGE_SYM_CLASS_STATIC | 427 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 428 | SectionDefinition: | 428 | SectionDefinition: |
| 429 | Length: 12 | 429 | Length: 12 |
| 430 | NumberOfRelocations: 3 | 430 | NumberOfRelocations: 3 |
| 431 | NumberOfLinenumbers: 0 | 431 | NumberOfLinenumbers: 0 |
deps/lld/test/COFF/Inputs/pdb_lines_1.yaml+59-59| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | --- !COFF | 1 | --- !COFF |
| 2 | header: | 2 | header: |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | 3 | Machine: IMAGE_FILE_MACHINE_AMD64 |
| 4 | Characteristics: [ ] | 4 | Characteristics: [ ] |
| 5 | sections: | 5 | sections: |
| 6 | - Name: .drectve | 6 | - Name: .drectve |
| 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] |
| 8 | Alignment: 1 | 8 | Alignment: 1 |
| ... | @@ -10,15 +10,15 @@ sections: | ... | @@ -10,15 +10,15 @@ sections: |
| 10 | - Name: '.debug$S' | 10 | - Name: '.debug$S' |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 12 | Alignment: 1 | 12 | Alignment: 1 |
| 13 | Subsections: | 13 | Subsections: |
| 14 | - !Symbols | 14 | - !Symbols |
| 15 | Records: | 15 | Records: |
| 16 | - Kind: S_OBJNAME | 16 | - Kind: S_OBJNAME |
| 17 | ObjNameSym: | 17 | ObjNameSym: |
| 18 | Signature: 0 | 18 | Signature: 0 |
| 19 | ObjectName: 'C:\src\llvm-project\build\pdb_lines_1.obj' | 19 | ObjectName: 'C:\src\llvm-project\build\pdb_lines_1.obj' |
| 20 | - Kind: S_COMPILE3 | 20 | - Kind: S_COMPILE3 |
| 21 | Compile3Sym: | 21 | Compile3Sym: |
| 22 | Flags: [ SecurityChecks, HotPatch ] | 22 | Flags: [ SecurityChecks, HotPatch ] |
| 23 | Machine: X64 | 23 | Machine: X64 |
| 24 | FrontendMajor: 19 | 24 | FrontendMajor: 19 |
| ... | @@ -31,9 +31,9 @@ sections: | ... | @@ -31,9 +31,9 @@ sections: |
| 31 | BackendQFE: 1 | 31 | BackendQFE: 1 |
| 32 | Version: 'Microsoft (R) Optimizing Compiler' | 32 | Version: 'Microsoft (R) Optimizing Compiler' |
| 33 | - !Symbols | 33 | - !Symbols |
| 34 | Records: | 34 | Records: |
| 35 | - Kind: S_GPROC32_ID | 35 | - Kind: S_GPROC32_ID |
| 36 | ProcSym: | 36 | ProcSym: |
| 37 | PtrParent: 0 | 37 | PtrParent: 0 |
| 38 | PtrEnd: 0 | 38 | PtrEnd: 0 |
| 39 | PtrNext: 0 | 39 | PtrNext: 0 |
| ... | @@ -45,7 +45,7 @@ sections: | ... | @@ -45,7 +45,7 @@ sections: |
| 45 | Flags: [ ] | 45 | Flags: [ ] |
| 46 | DisplayName: main | 46 | DisplayName: main |
| 47 | - Kind: S_FRAMEPROC | 47 | - Kind: S_FRAMEPROC |
| 48 | FrameProcSym: | 48 | FrameProcSym: |
| 49 | TotalFrameBytes: 40 | 49 | TotalFrameBytes: 40 |
| 50 | PaddingFrameBytes: 0 | 50 | PaddingFrameBytes: 0 |
| 51 | OffsetToPadding: 0 | 51 | OffsetToPadding: 0 |
| ... | @@ -54,15 +54,15 @@ sections: | ... | @@ -54,15 +54,15 @@ sections: |
| 54 | SectionIdOfExceptionHandler: 0 | 54 | SectionIdOfExceptionHandler: 0 |
| 55 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | 55 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 56 | - Kind: S_PROC_ID_END | 56 | - Kind: S_PROC_ID_END |
| 57 | ScopeEndSym: | 57 | ScopeEndSym: |
| 58 | - !Lines | 58 | - !Lines |
| 59 | CodeSize: 19 | 59 | CodeSize: 19 |
| 60 | Flags: [ ] | 60 | Flags: [ ] |
| 61 | RelocOffset: 0 | 61 | RelocOffset: 0 |
| 62 | RelocSegment: 0 | 62 | RelocSegment: 0 |
| 63 | Blocks: | 63 | Blocks: |
| 64 | - FileName: 'c:\src\llvm-project\build\pdb_lines_1.c' | 64 | - FileName: 'c:\src\llvm-project\build\pdb_lines_1.c' |
| 65 | Lines: | 65 | Lines: |
| 66 | - Offset: 0 | 66 | - Offset: 0 |
| 67 | LineStart: 2 | 67 | LineStart: 2 |
| 68 | IsStatement: true | 68 | IsStatement: true |
| ... | @@ -79,9 +79,9 @@ sections: | ... | @@ -79,9 +79,9 @@ sections: |
| 79 | LineStart: 5 | 79 | LineStart: 5 |
| 80 | IsStatement: true | 80 | IsStatement: true |
| 81 | EndDelta: 0 | 81 | EndDelta: 0 |
| 82 | Columns: | 82 | Columns: |
| 83 | - !FileChecksums | 83 | - !FileChecksums |
| 84 | Checksums: | 84 | Checksums: |
| 85 | - FileName: 'c:\src\llvm-project\build\pdb_lines_1.c' | 85 | - FileName: 'c:\src\llvm-project\build\pdb_lines_1.c' |
| 86 | Kind: MD5 | 86 | Kind: MD5 |
| 87 | Checksum: 4EB19DCD86C3BA2238A255C718572E7B | 87 | Checksum: 4EB19DCD86C3BA2238A255C718572E7B |
| ... | @@ -89,15 +89,15 @@ sections: | ... | @@ -89,15 +89,15 @@ sections: |
| 89 | Kind: MD5 | 89 | Kind: MD5 |
| 90 | Checksum: 061EB73ABB642532857A4F1D9CBAC323 | 90 | Checksum: 061EB73ABB642532857A4F1D9CBAC323 |
| 91 | - !StringTable | 91 | - !StringTable |
| 92 | Strings: | 92 | Strings: |
| 93 | - 'c:\src\llvm-project\build\pdb_lines_1.c' | 93 | - 'c:\src\llvm-project\build\pdb_lines_1.c' |
| 94 | - 'c:\src\llvm-project\build\foo.h' | 94 | - 'c:\src\llvm-project\build\foo.h' |
| 95 | - !Symbols | 95 | - !Symbols |
| 96 | Records: | 96 | Records: |
| 97 | - Kind: S_BUILDINFO | 97 | - Kind: S_BUILDINFO |
| 98 | BuildInfoSym: | 98 | BuildInfoSym: |
| 99 | BuildId: 4111 | 99 | BuildId: 4111 |
| 100 | Relocations: | 100 | Relocations: |
| 101 | - VirtualAddress: 164 | 101 | - VirtualAddress: 164 |
| 102 | SymbolName: main | 102 | SymbolName: main |
| 103 | Type: IMAGE_REL_AMD64_SECREL | 103 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -113,81 +113,81 @@ sections: | ... | @@ -113,81 +113,81 @@ sections: |
| 113 | - Name: '.debug$T' | 113 | - Name: '.debug$T' |
| 114 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 114 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 115 | Alignment: 1 | 115 | Alignment: 1 |
| 116 | Types: | 116 | Types: |
| 117 | - Kind: LF_ARGLIST | 117 | - Kind: LF_ARGLIST |
| 118 | ArgList: | 118 | ArgList: |
| 119 | ArgIndices: [ ] | 119 | ArgIndices: [ ] |
| 120 | - Kind: LF_PROCEDURE | 120 | - Kind: LF_PROCEDURE |
| 121 | Procedure: | 121 | Procedure: |
| 122 | ReturnType: 3 | 122 | ReturnType: 3 |
| 123 | CallConv: NearC | 123 | CallConv: NearC |
| 124 | Options: [ None ] | 124 | Options: [ None ] |
| 125 | ParameterCount: 0 | 125 | ParameterCount: 0 |
| 126 | ArgumentList: 4096 | 126 | ArgumentList: 4096 |
| 127 | - Kind: LF_POINTER | 127 | - Kind: LF_POINTER |
| 128 | Pointer: | 128 | Pointer: |
| 129 | ReferentType: 4097 | 129 | ReferentType: 4097 |
| 130 | Attrs: 65548 | 130 | Attrs: 65548 |
| 131 | - Kind: LF_FUNC_ID | 131 | - Kind: LF_FUNC_ID |
| 132 | FuncId: | 132 | FuncId: |
| 133 | ParentScope: 0 | 133 | ParentScope: 0 |
| 134 | FunctionType: 4097 | 134 | FunctionType: 4097 |
| 135 | Name: foo | 135 | Name: foo |
| 136 | - Kind: LF_ARGLIST | 136 | - Kind: LF_ARGLIST |
| 137 | ArgList: | 137 | ArgList: |
| 138 | ArgIndices: [ 0 ] | 138 | ArgIndices: [ 0 ] |
| 139 | - Kind: LF_PROCEDURE | 139 | - Kind: LF_PROCEDURE |
| 140 | Procedure: | 140 | Procedure: |
| 141 | ReturnType: 116 | 141 | ReturnType: 116 |
| 142 | CallConv: NearC | 142 | CallConv: NearC |
| 143 | Options: [ None ] | 143 | Options: [ None ] |
| 144 | ParameterCount: 0 | 144 | ParameterCount: 0 |
| 145 | ArgumentList: 4100 | 145 | ArgumentList: 4100 |
| 146 | - Kind: LF_FUNC_ID | 146 | - Kind: LF_FUNC_ID |
| 147 | FuncId: | 147 | FuncId: |
| 148 | ParentScope: 0 | 148 | ParentScope: 0 |
| 149 | FunctionType: 4101 | 149 | FunctionType: 4101 |
| 150 | Name: main | 150 | Name: main |
| 151 | - Kind: LF_FUNC_ID | 151 | - Kind: LF_FUNC_ID |
| 152 | FuncId: | 152 | FuncId: |
| 153 | ParentScope: 0 | 153 | ParentScope: 0 |
| 154 | FunctionType: 4097 | 154 | FunctionType: 4097 |
| 155 | Name: bar | 155 | Name: bar |
| 156 | - Kind: LF_STRING_ID | 156 | - Kind: LF_STRING_ID |
| 157 | StringId: | 157 | StringId: |
| 158 | Id: 0 | 158 | Id: 0 |
| 159 | String: 'C:\src\llvm-project\build' | 159 | String: 'C:\src\llvm-project\build' |
| 160 | - Kind: LF_STRING_ID | 160 | - Kind: LF_STRING_ID |
| 161 | StringId: | 161 | StringId: |
| 162 | Id: 0 | 162 | Id: 0 |
| 163 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' | 163 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' |
| 164 | - Kind: LF_STRING_ID | 164 | - Kind: LF_STRING_ID |
| 165 | StringId: | 165 | StringId: |
| 166 | Id: 0 | 166 | Id: 0 |
| 167 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' | 167 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' |
| 168 | - Kind: LF_SUBSTR_LIST | 168 | - Kind: LF_SUBSTR_LIST |
| 169 | StringList: | 169 | StringList: |
| 170 | StringIndices: [ 4106 ] | 170 | StringIndices: [ 4106 ] |
| 171 | - Kind: LF_STRING_ID | 171 | - Kind: LF_STRING_ID |
| 172 | StringId: | 172 | StringId: |
| 173 | Id: 4107 | 173 | Id: 4107 |
| 174 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' | 174 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' |
| 175 | - Kind: LF_STRING_ID | 175 | - Kind: LF_STRING_ID |
| 176 | StringId: | 176 | StringId: |
| 177 | Id: 0 | 177 | Id: 0 |
| 178 | String: pdb_lines_1.c | 178 | String: pdb_lines_1.c |
| 179 | - Kind: LF_STRING_ID | 179 | - Kind: LF_STRING_ID |
| 180 | StringId: | 180 | StringId: |
| 181 | Id: 0 | 181 | Id: 0 |
| 182 | String: 'C:\src\llvm-project\build\vc140.pdb' | 182 | String: 'C:\src\llvm-project\build\vc140.pdb' |
| 183 | - Kind: LF_BUILDINFO | 183 | - Kind: LF_BUILDINFO |
| 184 | BuildInfo: | 184 | BuildInfo: |
| 185 | ArgIndices: [ 4104, 4105, 4109, 4110, 4108 ] | 185 | ArgIndices: [ 4104, 4105, 4109, 4110, 4108 ] |
| 186 | - Name: '.text$mn' | 186 | - Name: '.text$mn' |
| 187 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 187 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 188 | Alignment: 16 | 188 | Alignment: 16 |
| 189 | SectionData: 4883EC28E800000000B82A0000004883C428C3 | 189 | SectionData: 4883EC28E800000000B82A0000004883C428C3 |
| 190 | Relocations: | 190 | Relocations: |
| 191 | - VirtualAddress: 5 | 191 | - VirtualAddress: 5 |
| 192 | SymbolName: foo | 192 | SymbolName: foo |
| 193 | Type: IMAGE_REL_AMD64_REL32 | 193 | Type: IMAGE_REL_AMD64_REL32 |
| ... | @@ -195,18 +195,18 @@ sections: | ... | @@ -195,18 +195,18 @@ sections: |
| 195 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 195 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 196 | Alignment: 16 | 196 | Alignment: 16 |
| 197 | SectionData: 4883EC28E8000000004883C428C3 | 197 | SectionData: 4883EC28E8000000004883C428C3 |
| 198 | Relocations: | 198 | Relocations: |
| 199 | - VirtualAddress: 5 | 199 | - VirtualAddress: 5 |
| 200 | SymbolName: bar | 200 | SymbolName: bar |
| 201 | Type: IMAGE_REL_AMD64_REL32 | 201 | Type: IMAGE_REL_AMD64_REL32 |
| 202 | - Name: '.debug$S' | 202 | - Name: '.debug$S' |
| 203 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 203 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 204 | Alignment: 1 | 204 | Alignment: 1 |
| 205 | Subsections: | 205 | Subsections: |
| 206 | - !Symbols | 206 | - !Symbols |
| 207 | Records: | 207 | Records: |
| 208 | - Kind: S_GPROC32_ID | 208 | - Kind: S_GPROC32_ID |
| 209 | ProcSym: | 209 | ProcSym: |
| 210 | PtrParent: 0 | 210 | PtrParent: 0 |
| 211 | PtrEnd: 0 | 211 | PtrEnd: 0 |
| 212 | PtrNext: 0 | 212 | PtrNext: 0 |
| ... | @@ -218,7 +218,7 @@ sections: | ... | @@ -218,7 +218,7 @@ sections: |
| 218 | Flags: [ ] | 218 | Flags: [ ] |
| 219 | DisplayName: foo | 219 | DisplayName: foo |
| 220 | - Kind: S_FRAMEPROC | 220 | - Kind: S_FRAMEPROC |
| 221 | FrameProcSym: | 221 | FrameProcSym: |
| 222 | TotalFrameBytes: 40 | 222 | TotalFrameBytes: 40 |
| 223 | PaddingFrameBytes: 0 | 223 | PaddingFrameBytes: 0 |
| 224 | OffsetToPadding: 0 | 224 | OffsetToPadding: 0 |
| ... | @@ -227,15 +227,15 @@ sections: | ... | @@ -227,15 +227,15 @@ sections: |
| 227 | SectionIdOfExceptionHandler: 0 | 227 | SectionIdOfExceptionHandler: 0 |
| 228 | Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] | 228 | Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 229 | - Kind: S_PROC_ID_END | 229 | - Kind: S_PROC_ID_END |
| 230 | ScopeEndSym: | 230 | ScopeEndSym: |
| 231 | - !Lines | 231 | - !Lines |
| 232 | CodeSize: 14 | 232 | CodeSize: 14 |
| 233 | Flags: [ ] | 233 | Flags: [ ] |
| 234 | RelocOffset: 0 | 234 | RelocOffset: 0 |
| 235 | RelocSegment: 0 | 235 | RelocSegment: 0 |
| 236 | Blocks: | 236 | Blocks: |
| 237 | - FileName: 'c:\src\llvm-project\build\foo.h' | 237 | - FileName: 'c:\src\llvm-project\build\foo.h' |
| 238 | Lines: | 238 | Lines: |
| 239 | - Offset: 0 | 239 | - Offset: 0 |
| 240 | LineStart: 2 | 240 | LineStart: 2 |
| 241 | IsStatement: true | 241 | IsStatement: true |
| ... | @@ -248,8 +248,8 @@ sections: | ... | @@ -248,8 +248,8 @@ sections: |
| 248 | LineStart: 4 | 248 | LineStart: 4 |
| 249 | IsStatement: true | 249 | IsStatement: true |
| 250 | EndDelta: 0 | 250 | EndDelta: 0 |
| 251 | Columns: | 251 | Columns: |
| 252 | Relocations: | 252 | Relocations: |
| 253 | - VirtualAddress: 44 | 253 | - VirtualAddress: 44 |
| 254 | SymbolName: foo | 254 | SymbolName: foo |
| 255 | Type: IMAGE_REL_AMD64_SECREL | 255 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -270,7 +270,7 @@ sections: | ... | @@ -270,7 +270,7 @@ sections: |
| 270 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] | 270 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] |
| 271 | Alignment: 4 | 271 | Alignment: 4 |
| 272 | SectionData: '000000000E00000000000000' | 272 | SectionData: '000000000E00000000000000' |
| 273 | Relocations: | 273 | Relocations: |
| 274 | - VirtualAddress: 0 | 274 | - VirtualAddress: 0 |
| 275 | SymbolName: '$LN3' | 275 | SymbolName: '$LN3' |
| 276 | Type: IMAGE_REL_AMD64_ADDR32NB | 276 | Type: IMAGE_REL_AMD64_ADDR32NB |
| ... | @@ -288,7 +288,7 @@ sections: | ... | @@ -288,7 +288,7 @@ sections: |
| 288 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | 288 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] |
| 289 | Alignment: 4 | 289 | Alignment: 4 |
| 290 | SectionData: '000000001300000000000000' | 290 | SectionData: '000000001300000000000000' |
| 291 | Relocations: | 291 | Relocations: |
| 292 | - VirtualAddress: 0 | 292 | - VirtualAddress: 0 |
| 293 | SymbolName: '$LN3' | 293 | SymbolName: '$LN3' |
| 294 | Type: IMAGE_REL_AMD64_ADDR32NB | 294 | Type: IMAGE_REL_AMD64_ADDR32NB |
| ... | @@ -298,14 +298,14 @@ sections: | ... | @@ -298,14 +298,14 @@ sections: |
| 298 | - VirtualAddress: 8 | 298 | - VirtualAddress: 8 |
| 299 | SymbolName: '$unwind$main' | 299 | SymbolName: '$unwind$main' |
| 300 | Type: IMAGE_REL_AMD64_ADDR32NB | 300 | Type: IMAGE_REL_AMD64_ADDR32NB |
| 301 | symbols: | 301 | symbols: |
| 302 | - Name: .drectve | 302 | - Name: .drectve |
| 303 | Value: 0 | 303 | Value: 0 |
| 304 | SectionNumber: 1 | 304 | SectionNumber: 1 |
| 305 | SimpleType: IMAGE_SYM_TYPE_NULL | 305 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 306 | ComplexType: IMAGE_SYM_DTYPE_NULL | 306 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 307 | StorageClass: IMAGE_SYM_CLASS_STATIC | 307 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 308 | SectionDefinition: | 308 | SectionDefinition: |
| 309 | Length: 47 | 309 | Length: 47 |
| 310 | NumberOfRelocations: 0 | 310 | NumberOfRelocations: 0 |
| 311 | NumberOfLinenumbers: 0 | 311 | NumberOfLinenumbers: 0 |
| ... | @@ -317,7 +317,7 @@ symbols: | ... | @@ -317,7 +317,7 @@ symbols: |
| 317 | SimpleType: IMAGE_SYM_TYPE_NULL | 317 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 318 | ComplexType: IMAGE_SYM_DTYPE_NULL | 318 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 319 | StorageClass: IMAGE_SYM_CLASS_STATIC | 319 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 320 | SectionDefinition: | 320 | SectionDefinition: |
| 321 | Length: 432 | 321 | Length: 432 |
| 322 | NumberOfRelocations: 4 | 322 | NumberOfRelocations: 4 |
| 323 | NumberOfLinenumbers: 0 | 323 | NumberOfLinenumbers: 0 |
| ... | @@ -329,7 +329,7 @@ symbols: | ... | @@ -329,7 +329,7 @@ symbols: |
| 329 | SimpleType: IMAGE_SYM_TYPE_NULL | 329 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 330 | ComplexType: IMAGE_SYM_DTYPE_NULL | 330 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 331 | StorageClass: IMAGE_SYM_CLASS_STATIC | 331 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 332 | SectionDefinition: | 332 | SectionDefinition: |
| 333 | Length: 644 | 333 | Length: 644 |
| 334 | NumberOfRelocations: 0 | 334 | NumberOfRelocations: 0 |
| 335 | NumberOfLinenumbers: 0 | 335 | NumberOfLinenumbers: 0 |
| ... | @@ -341,7 +341,7 @@ symbols: | ... | @@ -341,7 +341,7 @@ symbols: |
| 341 | SimpleType: IMAGE_SYM_TYPE_NULL | 341 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 342 | ComplexType: IMAGE_SYM_DTYPE_NULL | 342 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 343 | StorageClass: IMAGE_SYM_CLASS_STATIC | 343 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 344 | SectionDefinition: | 344 | SectionDefinition: |
| 345 | Length: 19 | 345 | Length: 19 |
| 346 | NumberOfRelocations: 1 | 346 | NumberOfRelocations: 1 |
| 347 | NumberOfLinenumbers: 0 | 347 | NumberOfLinenumbers: 0 |
| ... | @@ -353,7 +353,7 @@ symbols: | ... | @@ -353,7 +353,7 @@ symbols: |
| 353 | SimpleType: IMAGE_SYM_TYPE_NULL | 353 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 354 | ComplexType: IMAGE_SYM_DTYPE_NULL | 354 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 355 | StorageClass: IMAGE_SYM_CLASS_STATIC | 355 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 356 | SectionDefinition: | 356 | SectionDefinition: |
| 357 | Length: 14 | 357 | Length: 14 |
| 358 | NumberOfRelocations: 1 | 358 | NumberOfRelocations: 1 |
| 359 | NumberOfLinenumbers: 0 | 359 | NumberOfLinenumbers: 0 |
| ... | @@ -366,7 +366,7 @@ symbols: | ... | @@ -366,7 +366,7 @@ symbols: |
| 366 | SimpleType: IMAGE_SYM_TYPE_NULL | 366 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 367 | ComplexType: IMAGE_SYM_DTYPE_NULL | 367 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 368 | StorageClass: IMAGE_SYM_CLASS_STATIC | 368 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 369 | SectionDefinition: | 369 | SectionDefinition: |
| 370 | Length: 148 | 370 | Length: 148 |
| 371 | NumberOfRelocations: 4 | 371 | NumberOfRelocations: 4 |
| 372 | NumberOfLinenumbers: 0 | 372 | NumberOfLinenumbers: 0 |
| ... | @@ -409,7 +409,7 @@ symbols: | ... | @@ -409,7 +409,7 @@ symbols: |
| 409 | SimpleType: IMAGE_SYM_TYPE_NULL | 409 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 410 | ComplexType: IMAGE_SYM_DTYPE_NULL | 410 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 411 | StorageClass: IMAGE_SYM_CLASS_STATIC | 411 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 412 | SectionDefinition: | 412 | SectionDefinition: |
| 413 | Length: 8 | 413 | Length: 8 |
| 414 | NumberOfRelocations: 0 | 414 | NumberOfRelocations: 0 |
| 415 | NumberOfLinenumbers: 0 | 415 | NumberOfLinenumbers: 0 |
| ... | @@ -428,7 +428,7 @@ symbols: | ... | @@ -428,7 +428,7 @@ symbols: |
| 428 | SimpleType: IMAGE_SYM_TYPE_NULL | 428 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 429 | ComplexType: IMAGE_SYM_DTYPE_NULL | 429 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 430 | StorageClass: IMAGE_SYM_CLASS_STATIC | 430 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 431 | SectionDefinition: | 431 | SectionDefinition: |
| 432 | Length: 12 | 432 | Length: 12 |
| 433 | NumberOfRelocations: 3 | 433 | NumberOfRelocations: 3 |
| 434 | NumberOfLinenumbers: 0 | 434 | NumberOfLinenumbers: 0 |
| ... | @@ -447,7 +447,7 @@ symbols: | ... | @@ -447,7 +447,7 @@ symbols: |
| 447 | SimpleType: IMAGE_SYM_TYPE_NULL | 447 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 448 | ComplexType: IMAGE_SYM_DTYPE_NULL | 448 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 449 | StorageClass: IMAGE_SYM_CLASS_STATIC | 449 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 450 | SectionDefinition: | 450 | SectionDefinition: |
| 451 | Length: 8 | 451 | Length: 8 |
| 452 | NumberOfRelocations: 0 | 452 | NumberOfRelocations: 0 |
| 453 | NumberOfLinenumbers: 0 | 453 | NumberOfLinenumbers: 0 |
| ... | @@ -465,7 +465,7 @@ symbols: | ... | @@ -465,7 +465,7 @@ symbols: |
| 465 | SimpleType: IMAGE_SYM_TYPE_NULL | 465 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 466 | ComplexType: IMAGE_SYM_DTYPE_NULL | 466 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 467 | StorageClass: IMAGE_SYM_CLASS_STATIC | 467 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 468 | SectionDefinition: | 468 | SectionDefinition: |
| 469 | Length: 12 | 469 | Length: 12 |
| 470 | NumberOfRelocations: 3 | 470 | NumberOfRelocations: 3 |
| 471 | NumberOfLinenumbers: 0 | 471 | NumberOfLinenumbers: 0 |
deps/lld/test/COFF/Inputs/pdb_lines_2.yaml+35-35| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | --- !COFF | 1 | --- !COFF |
| 2 | header: | 2 | header: |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | 3 | Machine: IMAGE_FILE_MACHINE_AMD64 |
| 4 | Characteristics: [ ] | 4 | Characteristics: [ ] |
| 5 | sections: | 5 | sections: |
| 6 | - Name: .drectve | 6 | - Name: .drectve |
| 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | 7 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] |
| 8 | Alignment: 1 | 8 | Alignment: 1 |
| ... | @@ -10,15 +10,15 @@ sections: | ... | @@ -10,15 +10,15 @@ sections: |
| 10 | - Name: '.debug$S' | 10 | - Name: '.debug$S' |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 12 | Alignment: 1 | 12 | Alignment: 1 |
| 13 | Subsections: | 13 | Subsections: |
| 14 | - !Symbols | 14 | - !Symbols |
| 15 | Records: | 15 | Records: |
| 16 | - Kind: S_OBJNAME | 16 | - Kind: S_OBJNAME |
| 17 | ObjNameSym: | 17 | ObjNameSym: |
| 18 | Signature: 0 | 18 | Signature: 0 |
| 19 | ObjectName: 'C:\src\llvm-project\build\pdb_lines_2.obj' | 19 | ObjectName: 'C:\src\llvm-project\build\pdb_lines_2.obj' |
| 20 | - Kind: S_COMPILE3 | 20 | - Kind: S_COMPILE3 |
| 21 | Compile3Sym: | 21 | Compile3Sym: |
| 22 | Flags: [ SecurityChecks, HotPatch ] | 22 | Flags: [ SecurityChecks, HotPatch ] |
| 23 | Machine: X64 | 23 | Machine: X64 |
| 24 | FrontendMajor: 19 | 24 | FrontendMajor: 19 |
| ... | @@ -31,9 +31,9 @@ sections: | ... | @@ -31,9 +31,9 @@ sections: |
| 31 | BackendQFE: 1 | 31 | BackendQFE: 1 |
| 32 | Version: 'Microsoft (R) Optimizing Compiler' | 32 | Version: 'Microsoft (R) Optimizing Compiler' |
| 33 | - !Symbols | 33 | - !Symbols |
| 34 | Records: | 34 | Records: |
| 35 | - Kind: S_GPROC32_ID | 35 | - Kind: S_GPROC32_ID |
| 36 | ProcSym: | 36 | ProcSym: |
| 37 | PtrParent: 0 | 37 | PtrParent: 0 |
| 38 | PtrEnd: 0 | 38 | PtrEnd: 0 |
| 39 | PtrNext: 0 | 39 | PtrNext: 0 |
| ... | @@ -45,7 +45,7 @@ sections: | ... | @@ -45,7 +45,7 @@ sections: |
| 45 | Flags: [ ] | 45 | Flags: [ ] |
| 46 | DisplayName: bar | 46 | DisplayName: bar |
| 47 | - Kind: S_FRAMEPROC | 47 | - Kind: S_FRAMEPROC |
| 48 | FrameProcSym: | 48 | FrameProcSym: |
| 49 | TotalFrameBytes: 0 | 49 | TotalFrameBytes: 0 |
| 50 | PaddingFrameBytes: 0 | 50 | PaddingFrameBytes: 0 |
| 51 | OffsetToPadding: 0 | 51 | OffsetToPadding: 0 |
| ... | @@ -54,15 +54,15 @@ sections: | ... | @@ -54,15 +54,15 @@ sections: |
| 54 | SectionIdOfExceptionHandler: 0 | 54 | SectionIdOfExceptionHandler: 0 |
| 55 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | 55 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] |
| 56 | - Kind: S_PROC_ID_END | 56 | - Kind: S_PROC_ID_END |
| 57 | ScopeEndSym: | 57 | ScopeEndSym: |
| 58 | - !Lines | 58 | - !Lines |
| 59 | CodeSize: 1 | 59 | CodeSize: 1 |
| 60 | Flags: [ ] | 60 | Flags: [ ] |
| 61 | RelocOffset: 0 | 61 | RelocOffset: 0 |
| 62 | RelocSegment: 0 | 62 | RelocSegment: 0 |
| 63 | Blocks: | 63 | Blocks: |
| 64 | - FileName: 'c:\src\llvm-project\build\pdb_lines_2.c' | 64 | - FileName: 'c:\src\llvm-project\build\pdb_lines_2.c' |
| 65 | Lines: | 65 | Lines: |
| 66 | - Offset: 0 | 66 | - Offset: 0 |
| 67 | LineStart: 1 | 67 | LineStart: 1 |
| 68 | IsStatement: true | 68 | IsStatement: true |
| ... | @@ -71,21 +71,21 @@ sections: | ... | @@ -71,21 +71,21 @@ sections: |
| 71 | LineStart: 2 | 71 | LineStart: 2 |
| 72 | IsStatement: true | 72 | IsStatement: true |
| 73 | EndDelta: 0 | 73 | EndDelta: 0 |
| 74 | Columns: | 74 | Columns: |
| 75 | - !FileChecksums | 75 | - !FileChecksums |
| 76 | Checksums: | 76 | Checksums: |
| 77 | - FileName: 'c:\src\llvm-project\build\pdb_lines_2.c' | 77 | - FileName: 'c:\src\llvm-project\build\pdb_lines_2.c' |
| 78 | Kind: MD5 | 78 | Kind: MD5 |
| 79 | Checksum: DF91CB3A2B8D917486574BB50CAC4CC7 | 79 | Checksum: DF91CB3A2B8D917486574BB50CAC4CC7 |
| 80 | - !StringTable | 80 | - !StringTable |
| 81 | Strings: | 81 | Strings: |
| 82 | - 'c:\src\llvm-project\build\pdb_lines_2.c' | 82 | - 'c:\src\llvm-project\build\pdb_lines_2.c' |
| 83 | - !Symbols | 83 | - !Symbols |
| 84 | Records: | 84 | Records: |
| 85 | - Kind: S_BUILDINFO | 85 | - Kind: S_BUILDINFO |
| 86 | BuildInfoSym: | 86 | BuildInfoSym: |
| 87 | BuildId: 4106 | 87 | BuildId: 4106 |
| 88 | Relocations: | 88 | Relocations: |
| 89 | - VirtualAddress: 164 | 89 | - VirtualAddress: 164 |
| 90 | SymbolName: bar | 90 | SymbolName: bar |
| 91 | Type: IMAGE_REL_AMD64_SECREL | 91 | Type: IMAGE_REL_AMD64_SECREL |
| ... | @@ -101,64 +101,64 @@ sections: | ... | @@ -101,64 +101,64 @@ sections: |
| 101 | - Name: '.debug$T' | 101 | - Name: '.debug$T' |
| 102 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | 102 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] |
| 103 | Alignment: 1 | 103 | Alignment: 1 |
| 104 | Types: | 104 | Types: |
| 105 | - Kind: LF_ARGLIST | 105 | - Kind: LF_ARGLIST |
| 106 | ArgList: | 106 | ArgList: |
| 107 | ArgIndices: [ ] | 107 | ArgIndices: [ ] |
| 108 | - Kind: LF_PROCEDURE | 108 | - Kind: LF_PROCEDURE |
| 109 | Procedure: | 109 | Procedure: |
| 110 | ReturnType: 3 | 110 | ReturnType: 3 |
| 111 | CallConv: NearC | 111 | CallConv: NearC |
| 112 | Options: [ None ] | 112 | Options: [ None ] |
| 113 | ParameterCount: 0 | 113 | ParameterCount: 0 |
| 114 | ArgumentList: 4096 | 114 | ArgumentList: 4096 |
| 115 | - Kind: LF_FUNC_ID | 115 | - Kind: LF_FUNC_ID |
| 116 | FuncId: | 116 | FuncId: |
| 117 | ParentScope: 0 | 117 | ParentScope: 0 |
| 118 | FunctionType: 4097 | 118 | FunctionType: 4097 |
| 119 | Name: bar | 119 | Name: bar |
| 120 | - Kind: LF_STRING_ID | 120 | - Kind: LF_STRING_ID |
| 121 | StringId: | 121 | StringId: |
| 122 | Id: 0 | 122 | Id: 0 |
| 123 | String: 'C:\src\llvm-project\build' | 123 | String: 'C:\src\llvm-project\build' |
| 124 | - Kind: LF_STRING_ID | 124 | - Kind: LF_STRING_ID |
| 125 | StringId: | 125 | StringId: |
| 126 | Id: 0 | 126 | Id: 0 |
| 127 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' | 127 | String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' |
| 128 | - Kind: LF_STRING_ID | 128 | - Kind: LF_STRING_ID |
| 129 | StringId: | 129 | StringId: |
| 130 | Id: 0 | 130 | Id: 0 |
| 131 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' | 131 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' |
| 132 | - Kind: LF_SUBSTR_LIST | 132 | - Kind: LF_SUBSTR_LIST |
| 133 | StringList: | 133 | StringList: |
| 134 | StringIndices: [ 4101 ] | 134 | StringIndices: [ 4101 ] |
| 135 | - Kind: LF_STRING_ID | 135 | - Kind: LF_STRING_ID |
| 136 | StringId: | 136 | StringId: |
| 137 | Id: 4102 | 137 | Id: 4102 |
| 138 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' | 138 | String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' |
| 139 | - Kind: LF_STRING_ID | 139 | - Kind: LF_STRING_ID |
| 140 | StringId: | 140 | StringId: |
| 141 | Id: 0 | 141 | Id: 0 |
| 142 | String: pdb_lines_2.c | 142 | String: pdb_lines_2.c |
| 143 | - Kind: LF_STRING_ID | 143 | - Kind: LF_STRING_ID |
| 144 | StringId: | 144 | StringId: |
| 145 | Id: 0 | 145 | Id: 0 |
| 146 | String: 'C:\src\llvm-project\build\vc140.pdb' | 146 | String: 'C:\src\llvm-project\build\vc140.pdb' |
| 147 | - Kind: LF_BUILDINFO | 147 | - Kind: LF_BUILDINFO |
| 148 | BuildInfo: | 148 | BuildInfo: |
| 149 | ArgIndices: [ 4099, 4100, 4104, 4105, 4103 ] | 149 | ArgIndices: [ 4099, 4100, 4104, 4105, 4103 ] |
| 150 | - Name: '.text$mn' | 150 | - Name: '.text$mn' |
| 151 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 151 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 152 | Alignment: 16 | 152 | Alignment: 16 |
| 153 | SectionData: C3 | 153 | SectionData: C3 |
| 154 | symbols: | 154 | symbols: |
| 155 | - Name: .drectve | 155 | - Name: .drectve |
| 156 | Value: 0 | 156 | Value: 0 |
| 157 | SectionNumber: 1 | 157 | SectionNumber: 1 |
| 158 | SimpleType: IMAGE_SYM_TYPE_NULL | 158 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 159 | ComplexType: IMAGE_SYM_DTYPE_NULL | 159 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 160 | StorageClass: IMAGE_SYM_CLASS_STATIC | 160 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 161 | SectionDefinition: | 161 | SectionDefinition: |
| 162 | Length: 47 | 162 | Length: 47 |
| 163 | NumberOfRelocations: 0 | 163 | NumberOfRelocations: 0 |
| 164 | NumberOfLinenumbers: 0 | 164 | NumberOfLinenumbers: 0 |
| ... | @@ -170,7 +170,7 @@ symbols: | ... | @@ -170,7 +170,7 @@ symbols: |
| 170 | SimpleType: IMAGE_SYM_TYPE_NULL | 170 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 171 | ComplexType: IMAGE_SYM_DTYPE_NULL | 171 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 172 | StorageClass: IMAGE_SYM_CLASS_STATIC | 172 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 173 | SectionDefinition: | 173 | SectionDefinition: |
| 174 | Length: 360 | 174 | Length: 360 |
| 175 | NumberOfRelocations: 4 | 175 | NumberOfRelocations: 4 |
| 176 | NumberOfLinenumbers: 0 | 176 | NumberOfLinenumbers: 0 |
| ... | @@ -182,7 +182,7 @@ symbols: | ... | @@ -182,7 +182,7 @@ symbols: |
| 182 | SimpleType: IMAGE_SYM_TYPE_NULL | 182 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 183 | ComplexType: IMAGE_SYM_DTYPE_NULL | 183 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 184 | StorageClass: IMAGE_SYM_CLASS_STATIC | 184 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 185 | SectionDefinition: | 185 | SectionDefinition: |
| 186 | Length: 568 | 186 | Length: 568 |
| 187 | NumberOfRelocations: 0 | 187 | NumberOfRelocations: 0 |
| 188 | NumberOfLinenumbers: 0 | 188 | NumberOfLinenumbers: 0 |
| ... | @@ -194,7 +194,7 @@ symbols: | ... | @@ -194,7 +194,7 @@ symbols: |
| 194 | SimpleType: IMAGE_SYM_TYPE_NULL | 194 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 195 | ComplexType: IMAGE_SYM_DTYPE_NULL | 195 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 196 | StorageClass: IMAGE_SYM_CLASS_STATIC | 196 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 197 | SectionDefinition: | 197 | SectionDefinition: |
| 198 | Length: 1 | 198 | Length: 1 |
| 199 | NumberOfRelocations: 0 | 199 | NumberOfRelocations: 0 |
| 200 | NumberOfLinenumbers: 0 | 200 | NumberOfLinenumbers: 0 |
deps/lld/test/COFF/arm-thumb-branch20-error.s created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %s -o %t.obj | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %S/Inputs/far-arm-thumb-abs20.s -o %t.far.obj | ||
| 4 | // RUN: not lld-link -entry:_start -subsystem:console %t.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s | ||
| 5 | .syntax unified | ||
| 6 | .globl _start | ||
| 7 | _start: | ||
| 8 | bne too_far20 | ||
| 9 | |||
| 10 | // CHECK: relocation out of range | ||
deps/lld/test/COFF/arm64-dynamicbase.s created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | // REQUIRES: aarch64 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-windows %s -o %t.obj | ||
| 3 | // RUN: not lld-link -entry:_start -subsystem:console %t.obj -out:%t.exe -dynamicbase:no 2>&1 | FileCheck %s | ||
| 4 | .globl _start | ||
| 5 | _start: | ||
| 6 | ret | ||
| 7 | |||
| 8 | # CHECK: dynamicbase:no is not compatible with arm64 | ||
deps/lld/test/COFF/arm64-import2.test created+85| ... | @@ -0,0 +1,85 @@ | ||
| 1 | # REQUIRES: aarch64 | ||
| 2 | |||
| 3 | # RUN: yaml2obj < %s > %t.obj | ||
| 4 | # 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.lib | ||
| 6 | # RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER | ||
| 7 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s -check-prefix IMPORTS | ||
| 8 | |||
| 9 | # BEFORE: Disassembly of section .text: | ||
| 10 | # BEFORE: 0: 00 00 00 94 bl #0 | ||
| 11 | # BEFORE: 4: 00 00 00 94 bl #0 | ||
| 12 | # BEFORE: 8: c0 03 5f d6 ret | ||
| 13 | |||
| 14 | # AFTER: Disassembly of section .text: | ||
| 15 | # AFTER: 140001000: 03 00 00 94 bl #12 | ||
| 16 | # AFTER: 140001004: 05 00 00 94 bl #20 | ||
| 17 | # AFTER: 140001008: c0 03 5f d6 ret | ||
| 18 | # AFTER: 14000100c: 10 00 00 b0 adrp x16, #4096 | ||
| 19 | # AFTER: 140001010: 10 32 40 f9 ldr x16, [x16, #96] | ||
| 20 | # AFTER: 140001014: 00 02 1f d6 br x16 | ||
| 21 | # AFTER: 140001018: 10 00 00 b0 adrp x16, #4096 | ||
| 22 | # AFTER: 14000101c: 10 3a 40 f9 ldr x16, [x16, #112] | ||
| 23 | # AFTER: 140001020: 00 02 1f d6 br x16 | ||
| 24 | |||
| 25 | # IMPORTS: Import { | ||
| 26 | # IMPORTS: Name: library.dll | ||
| 27 | # IMPORTS: ImportLookupTableRVA: 0x2040 | ||
| 28 | # IMPORTS: ImportAddressTableRVA: 0x2060 | ||
| 29 | # IMPORTS: Symbol: function (2) | ||
| 30 | # IMPORTS: } | ||
| 31 | # IMPORTS: Import { | ||
| 32 | # IMPORTS: Name: library2.dll | ||
| 33 | # IMPORTS: ImportLookupTableRVA: 0x2050 | ||
| 34 | # IMPORTS: ImportAddressTableRVA: 0x2070 | ||
| 35 | # IMPORTS: Symbol: function2 (0) | ||
| 36 | # IMPORTS: } | ||
| 37 | |||
| 38 | --- !COFF | ||
| 39 | header: | ||
| 40 | Machine: IMAGE_FILE_MACHINE_ARM64 | ||
| 41 | Characteristics: [ ] | ||
| 42 | sections: | ||
| 43 | - Name: .text | ||
| 44 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 45 | Alignment: 4 | ||
| 46 | SectionData: 0000009400000094C0035FD6 | ||
| 47 | Relocations: | ||
| 48 | - VirtualAddress: 0 | ||
| 49 | SymbolName: function | ||
| 50 | Type: IMAGE_REL_ARM64_BRANCH26 | ||
| 51 | - VirtualAddress: 4 | ||
| 52 | SymbolName: function2 | ||
| 53 | Type: IMAGE_REL_ARM64_BRANCH26 | ||
| 54 | symbols: | ||
| 55 | - Name: .text | ||
| 56 | Value: 0 | ||
| 57 | SectionNumber: 1 | ||
| 58 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 59 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 60 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 61 | SectionDefinition: | ||
| 62 | Length: 12 | ||
| 63 | NumberOfRelocations: 2 | ||
| 64 | NumberOfLinenumbers: 0 | ||
| 65 | CheckSum: 1438860354 | ||
| 66 | Number: 1 | ||
| 67 | - Name: main | ||
| 68 | Value: 0 | ||
| 69 | SectionNumber: 1 | ||
| 70 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 71 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 72 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 73 | - Name: function | ||
| 74 | Value: 0 | ||
| 75 | SectionNumber: 0 | ||
| 76 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 77 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 78 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 79 | - Name: function2 | ||
| 80 | Value: 0 | ||
| 81 | SectionNumber: 0 | ||
| 82 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 83 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 84 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 85 | ... | ||
deps/lld/test/COFF/arm64-relocs-imports.test+130-23| ... | @@ -14,29 +14,67 @@ | ... | @@ -14,29 +14,67 @@ |
| 14 | # BEFORE: 14: 00 01 40 79 ldrh w0, [x8] | 14 | # BEFORE: 14: 00 01 40 79 ldrh w0, [x8] |
| 15 | # BEFORE: 18: 00 01 40 b9 ldr w0, [x8] | 15 | # BEFORE: 18: 00 01 40 b9 ldr w0, [x8] |
| 16 | # BEFORE: 1c: 00 01 40 f9 ldr x0, [x8] | 16 | # BEFORE: 1c: 00 01 40 f9 ldr x0, [x8] |
| 17 | # BEFORE: 20: e0 03 1f 2a mov w0, wzr | 17 | # BEFORE: 20: 00 01 00 39 strb w0, [x8] |
| 18 | # BEFORE: 24: fe 07 41 f8 ldr x30, [sp], #16 | 18 | # BEFORE: 24: 00 01 00 79 strh w0, [x8] |
| 19 | # BEFORE: 28: c0 03 5f d6 ret | 19 | # BEFORE: 28: 00 01 00 b9 str w0, [x8] |
| 20 | # BEFORE: 2c: 08 00 00 00 <unknown> | 20 | # BEFORE: 2c: 00 01 00 f9 str x0, [x8] |
| 21 | # BEFORE: 30: 00 00 00 00 <unknown> | 21 | # BEFORE: 30: 00 01 40 3d ldr b0, [x8] |
| 22 | # BEFORE: 34: 00 01 40 7d ldr h0, [x8] | ||
| 23 | # BEFORE: 38: 00 01 40 bd ldr s0, [x8] | ||
| 24 | # BEFORE: 3c: 00 01 40 fd ldr d0, [x8] | ||
| 25 | # BEFORE: 40: 00 01 c0 3d ldr q0, [x8] | ||
| 26 | # BEFORE: 44: 00 01 00 3d str b0, [x8] | ||
| 27 | # BEFORE: 48: 00 01 00 7d str h0, [x8] | ||
| 28 | # BEFORE: 4c: 00 01 00 bd str s0, [x8] | ||
| 29 | # BEFORE: 50: 00 01 00 fd str d0, [x8] | ||
| 30 | # BEFORE: 54: 00 01 80 3d str q0, [x8] | ||
| 31 | # BEFORE: 58: 00 05 40 f9 ldr x0, [x8, #8] | ||
| 32 | # BEFORE: 5c: 20 1a 01 b0 adrp x0, #36982784 | ||
| 33 | # BEFORE: 60: 00 fc 4f f9 ldr x0, [x0, #8184] | ||
| 34 | # BEFORE: 64: e0 03 1f 2a mov w0, wzr | ||
| 35 | # BEFORE: 68: fe 07 41 f8 ldr x30, [sp], #16 | ||
| 36 | # BEFORE: 6c: c0 03 5f d6 ret | ||
| 37 | # BEFORE: 70: 08 00 00 00 <unknown> | ||
| 38 | # BEFORE: 74: 00 00 00 00 <unknown> | ||
| 39 | # BEFORE: 78: 01 00 00 00 <unknown> | ||
| 40 | # BEFORE: 7c: 01 00 00 00 <unknown> | ||
| 22 | 41 | ||
| 23 | # AFTER: Disassembly of section .text: | 42 | # AFTER: Disassembly of section .text: |
| 24 | # AFTER: 140002000: fe 0f 1f f8 str x30, [sp, #-16]! | 43 | # AFTER: 140002000: fe 0f 1f f8 str x30, [sp, #-16]! |
| 25 | # AFTER: 140002004: e0 ff ff f0 adrp x0, #-4096 | 44 | # AFTER: 140002004: e0 ff ff f0 adrp x0, #-4096 |
| 26 | # AFTER: 140002008: 00 18 00 91 add x0, x0, #6 | 45 | # AFTER: 140002008: 00 18 00 91 add x0, x0, #6 |
| 27 | # AFTER: 14000200c: 0a 00 00 94 bl #40 | 46 | # AFTER: 14000200c: 1d 00 00 94 bl #116 |
| 28 | # AFTER: 140002010: 00 21 40 39 ldrb w0, [x8, #8] | 47 | # AFTER: 140002010: 00 21 40 39 ldrb w0, [x8, #8] |
| 29 | # AFTER: 140002014: 00 11 40 79 ldrh w0, [x8, #8] | 48 | # AFTER: 140002014: 00 11 40 79 ldrh w0, [x8, #8] |
| 30 | # AFTER: 140002018: 00 09 40 b9 ldr w0, [x8, #8] | 49 | # AFTER: 140002018: 00 09 40 b9 ldr w0, [x8, #8] |
| 31 | # AFTER: 14000201c: 00 05 40 f9 ldr x0, [x8, #8] | 50 | # AFTER: 14000201c: 00 05 40 f9 ldr x0, [x8, #8] |
| 32 | # AFTER: 140002020: e0 03 1f 2a mov w0, wzr | 51 | # AFTER: 140002020: 00 21 00 39 strb w0, [x8, #8] |
| 33 | # AFTER: 140002024: fe 07 41 f8 ldr x30, [sp], #16 | 52 | # AFTER: 140002024: 00 11 00 79 strh w0, [x8, #8] |
| 34 | # AFTER: 140002028: c0 03 5f d6 ret | 53 | # AFTER: 140002028: 00 09 00 b9 str w0, [x8, #8] |
| 35 | # AFTER: 14000202c: 10 10 00 40 <unknown> | 54 | # AFTER: 14000202c: 00 05 00 f9 str x0, [x8, #8] |
| 36 | # AFTER: 140002030: 01 00 00 00 <unknown> | 55 | # AFTER: 140002030: 00 41 40 3d ldr b0, [x8, #16] |
| 37 | # AFTER: 140002034: 10 00 00 b0 adrp x16, #4096 | 56 | # AFTER: 140002034: 00 21 40 7d ldr h0, [x8, #16] |
| 38 | # AFTER: 140002038: 10 1e 40 f9 ldr x16, [x16, #56] | 57 | # AFTER: 140002038: 00 11 40 bd ldr s0, [x8, #16] |
| 39 | # AFTER: 14000203c: 00 02 1f d6 br x16 | 58 | # AFTER: 14000203c: 00 09 40 fd ldr d0, [x8, #16] |
| 59 | # AFTER: 140002040: 00 05 c0 3d ldr q0, [x8, #16] | ||
| 60 | # AFTER: 140002044: 00 41 00 3d str b0, [x8, #16] | ||
| 61 | # AFTER: 140002048: 00 21 00 7d str h0, [x8, #16] | ||
| 62 | # AFTER: 14000204c: 00 11 00 bd str s0, [x8, #16] | ||
| 63 | # AFTER: 140002050: 00 09 00 fd str d0, [x8, #16] | ||
| 64 | # AFTER: 140002054: 00 05 80 3d str q0, [x8, #16] | ||
| 65 | # AFTER: 140002058: 00 09 40 f9 ldr x0, [x8, #16] | ||
| 66 | # AFTER: 14000205c: 00 00 00 b0 adrp x0, #4096 | ||
| 67 | # AFTER: 140002060: 00 fc 47 f9 ldr x0, [x0, #4088] | ||
| 68 | # AFTER: 140002064: e0 03 1f 2a mov w0, wzr | ||
| 69 | # AFTER: 140002068: fe 07 41 f8 ldr x30, [sp], #16 | ||
| 70 | # AFTER: 14000206c: c0 03 5f d6 ret | ||
| 71 | # AFTER: 140002070: 10 10 00 40 <unknown> | ||
| 72 | # AFTER: 140002074: 01 00 00 00 <unknown> | ||
| 73 | # AFTER: 140002078: 09 10 00 00 <unknown> | ||
| 74 | # AFTER: 14000207c: 09 00 00 00 <unknown> | ||
| 75 | # AFTER: 140002080: 10 00 00 b0 adrp x16, #4096 | ||
| 76 | # AFTER: 140002084: 10 1e 40 f9 ldr x16, [x16, #56] | ||
| 77 | # AFTER: 140002088: 00 02 1f d6 br x16 | ||
| 40 | 78 | ||
| 41 | --- !COFF | 79 | --- !COFF |
| 42 | header: | 80 | header: |
| ... | @@ -46,32 +84,89 @@ sections: | ... | @@ -46,32 +84,89 @@ sections: |
| 46 | - Name: .text | 84 | - Name: .text |
| 47 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 85 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 48 | Alignment: 4 | 86 | Alignment: 4 |
| 49 | SectionData: FE0F1FF80000009000080091000000940001403900014079000140B9000140F9E0031F2AFE0741F8C0035FD60800000000000000 | 87 | SectionData: FE0F1FF80000009000080091000000940001403900014079000140B9000140F90001003900010079000100B9000100F90001403D0001407D000140BD000140FD0001C03D0001003D0001007D000100BD000100FD0001803D000540F9201A01B000FC4FF9E0031F2AFE0741F8C0035FD608000000000000000100000001000000 |
| 50 | Relocations: | 88 | Relocations: |
| 51 | - VirtualAddress: 4 | 89 | - VirtualAddress: 4 |
| 52 | SymbolName: .Lstr | 90 | SymbolName: .Lstr |
| 53 | Type: 4 | 91 | Type: IMAGE_REL_ARM64_PAGEBASE_REL21 |
| 54 | - VirtualAddress: 8 | 92 | - VirtualAddress: 8 |
| 55 | SymbolName: .Lstr | 93 | SymbolName: .Lstr |
| 56 | Type: 6 | 94 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12A |
| 57 | - VirtualAddress: 12 | 95 | - VirtualAddress: 12 |
| 58 | SymbolName: function | 96 | SymbolName: function |
| 59 | Type: 3 | 97 | Type: IMAGE_REL_ARM64_BRANCH26 |
| 60 | - VirtualAddress: 16 | 98 | - VirtualAddress: 16 |
| 61 | SymbolName: .Lglobal | 99 | SymbolName: .Lglobal |
| 62 | Type: 7 | 100 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L |
| 63 | - VirtualAddress: 20 | 101 | - VirtualAddress: 20 |
| 64 | SymbolName: .Lglobal | 102 | SymbolName: .Lglobal |
| 65 | Type: 7 | 103 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L |
| 66 | - VirtualAddress: 24 | 104 | - VirtualAddress: 24 |
| 67 | SymbolName: .Lglobal | 105 | SymbolName: .Lglobal |
| 68 | Type: 7 | 106 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L |
| 69 | - VirtualAddress: 28 | 107 | - VirtualAddress: 28 |
| 70 | SymbolName: .Lglobal | 108 | SymbolName: .Lglobal |
| 71 | Type: 7 | 109 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L |
| 110 | - VirtualAddress: 32 | ||
| 111 | SymbolName: .Lglobal | ||
| 112 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 113 | - VirtualAddress: 36 | ||
| 114 | SymbolName: .Lglobal | ||
| 115 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 116 | - VirtualAddress: 40 | ||
| 117 | SymbolName: .Lglobal | ||
| 118 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 72 | - VirtualAddress: 44 | 119 | - VirtualAddress: 44 |
| 73 | SymbolName: .Lglobal | 120 | SymbolName: .Lglobal |
| 74 | Type: 14 | 121 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L |
| 122 | - VirtualAddress: 48 | ||
| 123 | SymbolName: .Lglobal16 | ||
| 124 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 125 | - VirtualAddress: 52 | ||
| 126 | SymbolName: .Lglobal16 | ||
| 127 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 128 | - VirtualAddress: 56 | ||
| 129 | SymbolName: .Lglobal16 | ||
| 130 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 131 | - VirtualAddress: 60 | ||
| 132 | SymbolName: .Lglobal16 | ||
| 133 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 134 | - VirtualAddress: 64 | ||
| 135 | SymbolName: .Lglobal16 | ||
| 136 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 137 | - VirtualAddress: 68 | ||
| 138 | SymbolName: .Lglobal16 | ||
| 139 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 140 | - VirtualAddress: 72 | ||
| 141 | SymbolName: .Lglobal16 | ||
| 142 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 143 | - VirtualAddress: 76 | ||
| 144 | SymbolName: .Lglobal16 | ||
| 145 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 146 | - VirtualAddress: 80 | ||
| 147 | SymbolName: .Lglobal16 | ||
| 148 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 149 | - VirtualAddress: 84 | ||
| 150 | SymbolName: .Lglobal16 | ||
| 151 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 152 | - VirtualAddress: 88 | ||
| 153 | SymbolName: .Lglobal | ||
| 154 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 155 | - VirtualAddress: 92 | ||
| 156 | SymbolName: .Lglobal16 | ||
| 157 | Type: IMAGE_REL_ARM64_PAGEBASE_REL21 | ||
| 158 | - VirtualAddress: 96 | ||
| 159 | SymbolName: .Lglobal0 | ||
| 160 | Type: IMAGE_REL_ARM64_PAGEOFFSET_12L | ||
| 161 | - VirtualAddress: 112 | ||
| 162 | SymbolName: .Lglobal | ||
| 163 | Type: IMAGE_REL_ARM64_ADDR64 | ||
| 164 | - VirtualAddress: 120 | ||
| 165 | SymbolName: .Lglobal | ||
| 166 | Type: IMAGE_REL_ARM64_ADDR32NB | ||
| 167 | - VirtualAddress: 124 | ||
| 168 | SymbolName: .Lglobal | ||
| 169 | Type: IMAGE_REL_ARM64_SECREL | ||
| 75 | - Name: .data | 170 | - Name: .data |
| 76 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | 171 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] |
| 77 | Alignment: 4 | 172 | Alignment: 4 |
| ... | @@ -127,6 +222,18 @@ symbols: | ... | @@ -127,6 +222,18 @@ symbols: |
| 127 | SimpleType: IMAGE_SYM_TYPE_NULL | 222 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 128 | ComplexType: IMAGE_SYM_DTYPE_NULL | 223 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 129 | StorageClass: IMAGE_SYM_CLASS_STATIC | 224 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| 225 | - Name: .Lglobal16 | ||
| 226 | Value: 16 | ||
| 227 | SectionNumber: 4 | ||
| 228 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 229 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 230 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 231 | - Name: .Lglobal0 | ||
| 232 | Value: 0 | ||
| 233 | SectionNumber: 4 | ||
| 234 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 235 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 236 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 130 | - Name: function | 237 | - Name: function |
| 131 | Value: 0 | 238 | Value: 0 |
| 132 | SectionNumber: 0 | 239 | SectionNumber: 0 |
deps/lld/test/COFF/armnt-blx23t.test+1-1| ... | @@ -37,7 +37,7 @@ sections: | ... | @@ -37,7 +37,7 @@ sections: |
| 37 | Relocations: | 37 | Relocations: |
| 38 | - VirtualAddress: 12 | 38 | - VirtualAddress: 12 |
| 39 | SymbolName: identity | 39 | SymbolName: identity |
| 40 | Type: 21 | 40 | Type: IMAGE_REL_ARM_BLX23T |
| 41 | symbols: | 41 | symbols: |
| 42 | - Name: .text | 42 | - Name: .text |
| 43 | Value: 0 | 43 | Value: 0 |
deps/lld/test/COFF/armnt-branch24t.test+1-1| ... | @@ -30,7 +30,7 @@ sections: | ... | @@ -30,7 +30,7 @@ sections: |
| 30 | Relocations: | 30 | Relocations: |
| 31 | - VirtualAddress: 6 | 31 | - VirtualAddress: 6 |
| 32 | SymbolName: identity | 32 | SymbolName: identity |
| 33 | Type: 20 | 33 | Type: IMAGE_REL_ARM_BRANCH24T |
| 34 | symbols: | 34 | symbols: |
| 35 | - Name: .text | 35 | - Name: .text |
| 36 | Value: 0 | 36 | Value: 0 |
deps/lld/test/COFF/armnt-dynamicbase.test created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | # RUN: yaml2obj < %p/Inputs/armnt-executable.obj.yaml > %t.obj | ||
| 2 | # RUN: not lld-link /out:%t.exe /entry:mainCRTStartup /subsystem:console %t.obj /dynamicbase:no 2>&1 | FileCheck %s | ||
| 3 | # CHECK: dynamicbase:no is not compatible with arm | ||
deps/lld/test/COFF/armnt-imports.test+1-1| ... | @@ -22,7 +22,7 @@ sections: | ... | @@ -22,7 +22,7 @@ sections: |
| 22 | Relocations: | 22 | Relocations: |
| 23 | - VirtualAddress: 0 | 23 | - VirtualAddress: 0 |
| 24 | SymbolName: __imp_function | 24 | SymbolName: __imp_function |
| 25 | Type: 17 | 25 | Type: IMAGE_REL_ARM_MOV32T |
| 26 | symbols: | 26 | symbols: |
| 27 | - Name: .text | 27 | - Name: .text |
| 28 | Value: 0 | 28 | Value: 0 |
deps/lld/test/COFF/armnt-mov32t-exec.test+1-1| ... | @@ -31,7 +31,7 @@ sections: | ... | @@ -31,7 +31,7 @@ sections: |
| 31 | Relocations: | 31 | Relocations: |
| 32 | - VirtualAddress: 4 | 32 | - VirtualAddress: 4 |
| 33 | SymbolName: function | 33 | SymbolName: function |
| 34 | Type: 17 | 34 | Type: IMAGE_REL_ARM_MOV32T |
| 35 | symbols: | 35 | symbols: |
| 36 | - Name: .text | 36 | - Name: .text |
| 37 | Value: 0 | 37 | Value: 0 |
deps/lld/test/COFF/armnt-movt32t.test+1-1| ... | @@ -27,7 +27,7 @@ sections: | ... | @@ -27,7 +27,7 @@ sections: |
| 27 | Relocations: | 27 | Relocations: |
| 28 | - VirtualAddress: 0 | 28 | - VirtualAddress: 0 |
| 29 | SymbolName: buffer | 29 | SymbolName: buffer |
| 30 | Type: 17 | 30 | Type: IMAGE_REL_ARM_MOV32T |
| 31 | - Name: .rdata | 31 | - Name: .rdata |
| 32 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | 32 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] |
| 33 | Alignment: 1 | 33 | Alignment: 1 |
deps/lld/test/COFF/common-alignment.test created+78| ... | @@ -0,0 +1,78 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: yaml2obj %s > %t.obj | ||
| 3 | # RUN: lld-link /out:%t.exe /entry:main %t.obj %t.obj | ||
| 4 | # RUN: llvm-objdump -d %t.exe | FileCheck %s | ||
| 5 | |||
| 6 | # Operands of B8 (MOV EAX) are common symbols | ||
| 7 | # CHECK: 3000: b8 00 10 00 40 | ||
| 8 | # CHECK: 3005: b8 10 10 00 40 | ||
| 9 | |||
| 10 | --- !COFF | ||
| 11 | header: | ||
| 12 | Machine: IMAGE_FILE_MACHINE_AMD64 | ||
| 13 | Characteristics: [] | ||
| 14 | sections: | ||
| 15 | - Name: .text | ||
| 16 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 17 | Alignment: 4 | ||
| 18 | SectionData: b800000000b800000000 | ||
| 19 | Relocations: | ||
| 20 | - VirtualAddress: 1 | ||
| 21 | SymbolName: bssdata4 | ||
| 22 | Type: IMAGE_REL_AMD64_ADDR32 | ||
| 23 | - VirtualAddress: 6 | ||
| 24 | SymbolName: bssdata4_align16 | ||
| 25 | Type: IMAGE_REL_AMD64_ADDR32 | ||
| 26 | - Name: .data | ||
| 27 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 28 | Alignment: 4 | ||
| 29 | SectionData: 03000000 | ||
| 30 | - Name: .drectve | ||
| 31 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 32 | Alignment: 1 | ||
| 33 | SectionData: 202d616c69676e636f6d6d3a62737364617461345f616c69676e31362c340a # -aligncomm:bssdata4_align16,4 | ||
| 34 | |||
| 35 | symbols: | ||
| 36 | - Name: .text | ||
| 37 | Value: 0 | ||
| 38 | SectionNumber: 1 | ||
| 39 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 40 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 41 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 42 | SectionDefinition: | ||
| 43 | Length: 0 | ||
| 44 | NumberOfRelocations: 5 | ||
| 45 | NumberOfLinenumbers: 0 | ||
| 46 | CheckSum: 0 | ||
| 47 | Number: 0 | ||
| 48 | - Name: .data | ||
| 49 | Value: 0 | ||
| 50 | SectionNumber: 2 | ||
| 51 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 52 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 53 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 54 | SectionDefinition: | ||
| 55 | Length: 4 | ||
| 56 | NumberOfRelocations: 0 | ||
| 57 | NumberOfLinenumbers: 0 | ||
| 58 | CheckSum: 0 | ||
| 59 | Number: 0 | ||
| 60 | - Name: main | ||
| 61 | Value: 0 | ||
| 62 | SectionNumber: 1 | ||
| 63 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 64 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 65 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 66 | - Name: bssdata4 | ||
| 67 | Value: 4 | ||
| 68 | SectionNumber: 0 | ||
| 69 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 70 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 71 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 72 | - Name: bssdata4_align16 | ||
| 73 | Value: 4 | ||
| 74 | SectionNumber: 0 | ||
| 75 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 76 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 77 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 78 | ... | ||
deps/lld/test/COFF/ctors_dtors_priority.s created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -triple=x86_64-windows-gnu -filetype=obj -o %t.obj %s | ||
| 3 | # RUN: lld-link -entry:main %t.obj -out:%t.exe | ||
| 4 | # RUN: llvm-objdump -s %t.exe | FileCheck %s | ||
| 5 | |||
| 6 | .globl main | ||
| 7 | main: | ||
| 8 | nop | ||
| 9 | |||
| 10 | .section .ctors.00005, "w" | ||
| 11 | .quad 2 | ||
| 12 | .section .ctors, "w" | ||
| 13 | .quad 1 | ||
| 14 | .section .ctors.00100, "w" | ||
| 15 | .quad 3 | ||
| 16 | |||
| 17 | .section .dtors, "w" | ||
| 18 | .quad 1 | ||
| 19 | .section .dtors.00100, "w" | ||
| 20 | .quad 3 | ||
| 21 | .section .dtors.00005, "w" | ||
| 22 | .quad 2 | ||
| 23 | |||
| 24 | # CHECK: Contents of section .ctors: | ||
| 25 | # CHECK-NEXT: 140001000 01000000 00000000 02000000 00000000 | ||
| 26 | # CHECK-NEXT: 140001010 03000000 00000000 | ||
| 27 | |||
| 28 | # CHECK: Contents of section .dtors: | ||
| 29 | # CHECK-NEXT: 140002000 01000000 00000000 02000000 00000000 | ||
| 30 | # CHECK-NEXT: 140002010 03000000 00000000 | ||
deps/lld/test/COFF/debug-dwarf.test created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | # Check that /debug creates %t.pdb. | ||
| 2 | # RUN: rm -f %t.pdb | ||
| 3 | # RUN: lld-link /debug /entry:main /out:%t.exe %p/Inputs/ret42.obj | ||
| 4 | # RUN: ls %t.pdb | ||
| 5 | |||
| 6 | # Check that /debug:dwarf does not create %t.pdb. | ||
| 7 | # RUN: rm -f %t.pdb | ||
| 8 | # RUN: lld-link /debug:dwarf /entry:main /out:%t.exe %p/Inputs/ret42.obj | ||
| 9 | # RUN: not ls %t.pdb | ||
| 10 | |||
| 11 | # Check that /debug:dwarf /debug creates %t.pdb. | ||
| 12 | # RUN: rm -f %t.pdb | ||
| 13 | # RUN: lld-link /debug:dwarf /debug /entry:main /out:%t.exe %p/Inputs/ret42.obj | ||
| 14 | # RUN: ls %t.pdb | ||
| 15 | |||
| 16 | # Check that /debug:dwarf /pdb:%t.pdb does not create %t.pdb. | ||
| 17 | # RUN: rm -f %t.pdb | ||
| 18 | # RUN: lld-link /debug:dwarf /pdb:%t.pdb /entry:main /out:%t.exe %p/Inputs/ret42.obj | ||
| 19 | # RUN: not ls %t.pdb | ||
deps/lld/test/COFF/def-export-stdcall.s+73-5| ... | @@ -1,21 +1,89 @@ | ... | @@ -1,21 +1,89 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj | 2 | # RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj |
| 3 | # RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall" > %t.def | 3 | # 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.lib | 4 | # RUN: lld-link -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib |
| 5 | # RUN: llvm-readobj %t.lib | FileCheck %s | 5 | # RUN: llvm-readobj %t.lib | FileCheck -check-prefix UNDECORATED-IMPLIB %s |
| 6 | # CHECK: Name type: undecorate | 6 | # RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix UNDECORATED-EXPORTS %s |
| 7 | # CHECK: __imp__stdcall@8 | 7 | |
| 8 | # CHECK: _stdcall@8 | 8 | # UNDECORATED-IMPLIB: Name type: noprefix |
| 9 | # UNDECORATED-IMPLIB-NEXT: __imp___underscored | ||
| 10 | # UNDECORATED-IMPLIB-NEXT: __underscored | ||
| 11 | # UNDECORATED-IMPLIB: Name type: undecorate | ||
| 12 | # UNDECORATED-IMPLIB-NEXT: __imp_@fastcall@8 | ||
| 13 | # UNDECORATED-IMPLIB-NEXT: fastcall@8 | ||
| 14 | # UNDECORATED-IMPLIB: Name type: undecorate | ||
| 15 | # UNDECORATED-IMPLIB-NEXT: __imp__stdcall@8 | ||
| 16 | # UNDECORATED-IMPLIB-NEXT: _stdcall@8 | ||
| 17 | # UNDECORATED-IMPLIB: Name type: undecorate | ||
| 18 | # UNDECORATED-IMPLIB-NEXT: __imp_vectorcall@@8 | ||
| 19 | # UNDECORATED-IMPLIB-NEXT: vectorcall@@8 | ||
| 20 | |||
| 21 | # UNDECORATED-EXPORTS: Name: _underscored | ||
| 22 | # UNDECORATED-EXPORTS: Name: fastcall | ||
| 23 | # UNDECORATED-EXPORTS: Name: stdcall | ||
| 24 | # UNDECORATED-EXPORTS: Name: vectorcall | ||
| 25 | |||
| 26 | |||
| 27 | # 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.lib | ||
| 29 | # RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-IMPLIB %s | ||
| 30 | # RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix DECORATED-EXPORTS %s | ||
| 31 | |||
| 32 | # DECORATED-IMPLIB: Name type: name | ||
| 33 | # DECORATED-IMPLIB-NEXT: __imp_@fastcall@8 | ||
| 34 | # DECORATED-IMPLIB-NEXT: @fastcall@8 | ||
| 35 | # TODO: To match link.exe, this one should also be Name type: name. | ||
| 36 | # DECORATED-IMPLIB: Name type: noprefix | ||
| 37 | # DECORATED-IMPLIB-NEXT: __imp__stdcall@8 | ||
| 38 | # DECORATED-IMPLIB-NEXT: _stdcall@8 | ||
| 39 | # DECORATED-IMPLIB: Name type: name | ||
| 40 | # DECORATED-IMPLIB-NEXT: __imp_vectorcall@@8 | ||
| 41 | # DECORATED-IMPLIB-NEXT: vectorcall@@8 | ||
| 42 | |||
| 43 | # DECORATED-EXPORTS: Name: @fastcall@8 | ||
| 44 | # TODO: To match link.exe, this one should actually be _stdcall@8 | ||
| 45 | # DECORATED-EXPORTS: Name: stdcall@8 | ||
| 46 | # DECORATED-EXPORTS: Name: vectorcall@@8 | ||
| 47 | |||
| 48 | |||
| 49 | # RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall@8\n @fastcall@8" > %t.def | ||
| 50 | # RUN: lld-link -lldmingw -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib | ||
| 51 | # RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-MINGW-IMPLIB %s | ||
| 52 | # RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix DECORATED-MINGW-EXPORTS %s | ||
| 53 | |||
| 54 | # DECORATED-MINGW-IMPLIB: Name type: name | ||
| 55 | # DECORATED-MINGW-IMPLIB-NEXT: __imp_@fastcall@8 | ||
| 56 | # DECORATED-MINGW-IMPLIB-NEXT: fastcall@8 | ||
| 57 | # DECORATED-MINGW-IMPLIB: Name type: noprefix | ||
| 58 | # DECORATED-MINGW-IMPLIB-NEXT: __imp__stdcall@8 | ||
| 59 | # DECORATED-MINGW-IMPLIB-NEXT: _stdcall@8 | ||
| 60 | |||
| 61 | # DECORATED-MINGW-EXPORTS: Name: @fastcall@8 | ||
| 62 | # DECORATED-MINGW-EXPORTS: Name: stdcall@8 | ||
| 63 | |||
| 9 | 64 | ||
| 10 | .def _stdcall@8; | 65 | .def _stdcall@8; |
| 11 | .scl 2; | 66 | .scl 2; |
| 12 | .type 32; | 67 | .type 32; |
| 13 | .endef | 68 | .endef |
| 14 | .globl _stdcall@8 | 69 | .globl _stdcall@8 |
| 70 | .globl @fastcall@8 | ||
| 71 | .globl vectorcall@@8 | ||
| 72 | .globl __underscored | ||
| 15 | _stdcall@8: | 73 | _stdcall@8: |
| 16 | movl 8(%esp), %eax | 74 | movl 8(%esp), %eax |
| 17 | addl 4(%esp), %eax | 75 | addl 4(%esp), %eax |
| 18 | retl $8 | 76 | retl $8 |
| 77 | @fastcall@8: | ||
| 78 | movl 8(%esp), %eax | ||
| 79 | addl 4(%esp), %eax | ||
| 80 | retl $8 | ||
| 81 | vectorcall@@8: | ||
| 82 | movl 8(%esp), %eax | ||
| 83 | addl 4(%esp), %eax | ||
| 84 | retl $8 | ||
| 85 | __underscored: | ||
| 86 | ret | ||
| 19 | 87 | ||
| 20 | .def _dllmain; | 88 | .def _dllmain; |
| 21 | .scl 2; | 89 | .scl 2; |
deps/lld/test/COFF/delayimports-armnt.yaml created+106| ... | @@ -0,0 +1,106 @@ | ||
| 1 | # REQUIRES: arm | ||
| 2 | # RUN: yaml2obj < %s > %t.obj | ||
| 3 | # RUN: lld-link %t.obj %p/Inputs/library.lib /subsystem:console \ | ||
| 4 | # RUN: /entry:mainCRTStartup /alternatename:__delayLoadHelper2=mainCRTStartup \ | ||
| 5 | # RUN: /delayload:library.dll /out:%t.exe | ||
| 6 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s | ||
| 7 | # RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s | ||
| 8 | # RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s | ||
| 9 | |||
| 10 | # IMPORT: Format: COFF-ARM | ||
| 11 | # IMPORT-NEXT: Arch: thumb | ||
| 12 | # IMPORT-NEXT: AddressSize: 32bit | ||
| 13 | # IMPORT-NEXT: DelayImport { | ||
| 14 | # IMPORT-NEXT: Name: library.dll | ||
| 15 | # IMPORT-NEXT: Attributes: 0x1 | ||
| 16 | # IMPORT-NEXT: ModuleHandle: 0x3000 | ||
| 17 | # IMPORT-NEXT: ImportAddressTable: 0x3008 | ||
| 18 | # IMPORT-NEXT: ImportNameTable: 0x2040 | ||
| 19 | # IMPORT-NEXT: BoundDelayImportTable: 0x0 | ||
| 20 | # IMPORT-NEXT: UnloadDelayImportTable: 0x0 | ||
| 21 | # IMPORT-NEXT: Import { | ||
| 22 | # IMPORT-NEXT: Symbol: function (0) | ||
| 23 | # IMPORT-NEXT: Address: 0x401019 | ||
| 24 | # IMPORT-NEXT: } | ||
| 25 | # IMPORT-NEXT: } | ||
| 26 | # | ||
| 27 | # BASEREL: BaseReloc [ | ||
| 28 | # BASEREL-NEXT: Entry { | ||
| 29 | # BASEREL-NEXT: Type: ARM_MOV32(T) | ||
| 30 | # BASEREL-NEXT: Address: 0x1000 | ||
| 31 | # BASEREL-NEXT: } | ||
| 32 | # BASEREL-NEXT: Entry { | ||
| 33 | # BASEREL-NEXT: Type: ARM_MOV32(T) | ||
| 34 | # BASEREL-NEXT: Address: 0x100C | ||
| 35 | # BASEREL-NEXT: } | ||
| 36 | # BASEREL-NEXT: Entry { | ||
| 37 | # BASEREL-NEXT: Type: ARM_MOV32(T) | ||
| 38 | # BASEREL-NEXT: Address: 0x1018 | ||
| 39 | # BASEREL-NEXT: } | ||
| 40 | # BASEREL-NEXT: Entry { | ||
| 41 | # BASEREL-NEXT: Type: ARM_MOV32(T) | ||
| 42 | # BASEREL-NEXT: Address: 0x102E | ||
| 43 | # BASEREL-NEXT: } | ||
| 44 | # BASEREL-NEXT: Entry { | ||
| 45 | # BASEREL-NEXT: Type: HIGHLOW | ||
| 46 | # BASEREL-NEXT: Address: 0x3008 | ||
| 47 | # BASEREL-NEXT: } | ||
| 48 | # BASEREL-NEXT: Entry { | ||
| 49 | # BASEREL-NEXT: Type: ABSOLUTE | ||
| 50 | # BASEREL-NEXT: Address: 0x3000 | ||
| 51 | # BASEREL-NEXT: } | ||
| 52 | # BASEREL-NEXT: ] | ||
| 53 | # | ||
| 54 | # DISASM: 401018: 43 f2 08 0c movw r12, #12296 | ||
| 55 | # DISASM-NEXT: 40101c: c0 f2 40 0c movt r12, #64 | ||
| 56 | # DISASM-NEXT: 401020: 2d e9 0f 48 push.w {r0, r1, r2, r3, r11, lr} | ||
| 57 | # DISASM-NEXT: 401024: 0d f2 10 0b addw r11, sp, #16 | ||
| 58 | # DISASM-NEXT: 401028: 2d ed 10 0b vpush {d0, d1, d2, d3, d4, d5, d6, d7} | ||
| 59 | # DISASM-NEXT: 40102c: 61 46 mov r1, r12 | ||
| 60 | # DISASM-NEXT: 40102e: 42 f2 00 00 movw r0, #8192 | ||
| 61 | # DISASM-NEXT: 401032: c0 f2 40 00 movt r0, #64 | ||
| 62 | # DISASM-NEXT: 401036: ff f7 e3 ff bl #-58 | ||
| 63 | # DISASM-NEXT: 40103a: 84 46 mov r12, r0 | ||
| 64 | # DISASM-NEXT: 40103c: bd ec 10 0b vpop {d0, d1, d2, d3, d4, d5, d6, d7} | ||
| 65 | # DISASM-NEXT: 401040: bd e8 0f 48 pop.w {r0, r1, r2, r3, r11, lr} | ||
| 66 | # DISASM-NEXT: 401044: 60 47 bx r12 | ||
| 67 | |||
| 68 | --- !COFF | ||
| 69 | header: | ||
| 70 | Machine: IMAGE_FILE_MACHINE_ARMNT | ||
| 71 | Characteristics: [ ] | ||
| 72 | sections: | ||
| 73 | - Name: .text | ||
| 74 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 75 | Alignment: 4 | ||
| 76 | SectionData: 40F20000C0F2000000680047 | ||
| 77 | Relocations: | ||
| 78 | - VirtualAddress: 0 | ||
| 79 | SymbolName: __imp_function | ||
| 80 | Type: IMAGE_REL_ARM_MOV32T | ||
| 81 | symbols: | ||
| 82 | - Name: .text | ||
| 83 | Value: 0 | ||
| 84 | SectionNumber: 1 | ||
| 85 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 86 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 87 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 88 | SectionDefinition: | ||
| 89 | Length: 12 | ||
| 90 | NumberOfRelocations: 1 | ||
| 91 | NumberOfLinenumbers: 0 | ||
| 92 | CheckSum: 0 | ||
| 93 | Number: 1 | ||
| 94 | - Name: mainCRTStartup | ||
| 95 | Value: 0 | ||
| 96 | SectionNumber: 1 | ||
| 97 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 98 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 99 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 100 | - Name: __imp_function | ||
| 101 | Value: 0 | ||
| 102 | SectionNumber: 0 | ||
| 103 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 104 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 105 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 106 | ... | ||
deps/lld/test/COFF/delayimports32.test+2-2| ... | @@ -73,7 +73,7 @@ BASEREL-NEXT: ] | ... | @@ -73,7 +73,7 @@ BASEREL-NEXT: ] |
| 73 | 73 | ||
| 74 | DISASM: 202b: 68 20 10 40 00 pushl $4198432 | 74 | DISASM: 202b: 68 20 10 40 00 pushl $4198432 |
| 75 | DISASM-NEXT: 2030: 68 00 40 40 00 pushl $4210688 | 75 | DISASM-NEXT: 2030: 68 00 40 40 00 pushl $4210688 |
| 76 | DISASM-NEXT: 2035: e8 c6 ff ff ff calll -58 <_main@0> | 76 | DISASM-NEXT: 2035: e8 c6 ff ff ff calll -58 <.text> |
| 77 | DISASM-NEXT: 203a: 5a popl %edx | 77 | DISASM-NEXT: 203a: 5a popl %edx |
| 78 | DISASM-NEXT: 203b: 59 popl %ecx | 78 | DISASM-NEXT: 203b: 59 popl %ecx |
| 79 | DISASM-NEXT: 203c: ff e0 jmpl *%eax | 79 | DISASM-NEXT: 203c: ff e0 jmpl *%eax |
| ... | @@ -81,7 +81,7 @@ DISASM-NEXT: 203e: 51 pushl %ecx | ... | @@ -81,7 +81,7 @@ DISASM-NEXT: 203e: 51 pushl %ecx |
| 81 | DISASM-NEXT: 203f: 52 pushl %edx | 81 | DISASM-NEXT: 203f: 52 pushl %edx |
| 82 | DISASM-NEXT: 2040: 68 24 10 40 00 pushl $4198436 | 82 | DISASM-NEXT: 2040: 68 24 10 40 00 pushl $4198436 |
| 83 | DISASM-NEXT: 2045: 68 00 40 40 00 pushl $4210688 | 83 | DISASM-NEXT: 2045: 68 00 40 40 00 pushl $4210688 |
| 84 | DISASM-NEXT: 204a: e8 b1 ff ff ff calll -79 <_main@0> | 84 | DISASM-NEXT: 204a: e8 b1 ff ff ff calll -79 <.text> |
| 85 | DISASM-NEXT: 204f: 5a popl %edx | 85 | DISASM-NEXT: 204f: 5a popl %edx |
| 86 | DISASM-NEXT: 2050: 59 popl %ecx | 86 | DISASM-NEXT: 2050: 59 popl %ecx |
| 87 | DISASM-NEXT: 2051: ff e0 jmpl *%eax | 87 | DISASM-NEXT: 2051: ff e0 jmpl *%eax |
deps/lld/test/COFF/dllexport-mingw.s created+24| ... | @@ -0,0 +1,24 @@ | ||
| 1 | # REQEUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj | ||
| 4 | |||
| 5 | # RUN: lld-link -lldmingw -dll -out:%t.dll -entry:main %t.obj -implib:%t.lib | ||
| 6 | # RUN: llvm-readobj %t.lib | FileCheck %s | ||
| 7 | |||
| 8 | # CHECK: Symbol: __imp___underscoredFunc | ||
| 9 | # CHECK: Symbol: __underscoredFunc | ||
| 10 | # CHECK: Symbol: __imp__func | ||
| 11 | # CHECK: Symbol: _func | ||
| 12 | |||
| 13 | .global _main | ||
| 14 | .global _func | ||
| 15 | .global __underscoredFunc | ||
| 16 | .text | ||
| 17 | _main: | ||
| 18 | ret | ||
| 19 | _func: | ||
| 20 | ret | ||
| 21 | __underscoredFunc: | ||
| 22 | ret | ||
| 23 | .section .drectve | ||
| 24 | .ascii "-export:func -export:_underscoredFunc" | ||
deps/lld/test/COFF/driver.test+3| ... | @@ -1,3 +1,6 @@ | ... | @@ -1,3 +1,6 @@ |
| 1 | # RUN: not lld-link nosuchfile.obj >& %t.log | 1 | # RUN: not lld-link nosuchfile.obj >& %t.log |
| 2 | # RUN: FileCheck -check-prefix=MISSING %s < %t.log | 2 | # RUN: FileCheck -check-prefix=MISSING %s < %t.log |
| 3 | MISSING: nosuchfile.obj: {{[Nn]}}o such file or directory | 3 | MISSING: nosuchfile.obj: {{[Nn]}}o such file or directory |
| 4 | |||
| 5 | # RUN: lld-link --version | FileCheck -check-prefix=VERSION %s | ||
| 6 | VERSION: {{LLD [0-9]+\.[0-9]+}} |
deps/lld/test/COFF/duplicate.test created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | RUN: llc -mtriple x86_64-windows-msvc -filetype obj -o alpha.obj %S/Inputs/alpha.ll | ||
| 2 | RUN: llc -mtriple x86_64-windows-msvc -filetype obj -o beta.obj %S/Inputs/beta.ll | ||
| 3 | RUN: lld-link /out:alpha.dll /dll alpha.obj /implib:alpha.lib | ||
| 4 | RUN: not lld-link /out:beta.dll /dll alpha.obj beta.obj alpha.lib 2>&1 | FileCheck %s -check-prefix CHECK-ALPHA | ||
| 5 | |||
| 6 | CHECK-ALPHA: error: duplicate symbol: f in {{.*}}alpha.obj and in alpha.dll | ||
| 7 | |||
| 8 | RUN: llc -mtriple x86_64-windows-msvc -filetype obj -o gamma.obj %S/Inputs/gamma.ll | ||
| 9 | RUN: not lld-link /out:gamma.exe /subsystem:console /entry:mainCRTStartup gamma.obj alpha.lib 2>&1 | FileCheck %s -check-prefix CHECK-GAMMA | ||
| 10 | |||
| 11 | CHECK-GAMMA: error: duplicate symbol: __imp_f in {{.*}}gamma.obj and in alpha.dll | ||
| 12 | |||
deps/lld/test/COFF/entry-drectve.test created+24| ... | @@ -0,0 +1,24 @@ | ||
| 1 | # RUN: yaml2obj < %s > %t.obj | ||
| 2 | # RUN: lld-link /subsystem:console /out:%t.exe %t.obj | ||
| 3 | |||
| 4 | --- !COFF | ||
| 5 | header: | ||
| 6 | Machine: IMAGE_FILE_MACHINE_I386 | ||
| 7 | Characteristics: [] | ||
| 8 | sections: | ||
| 9 | - Name: .text | ||
| 10 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 11 | Alignment: 4 | ||
| 12 | SectionData: B800000000506800000000680000000050E80000000050E800000000 | ||
| 13 | - Name: .drectve | ||
| 14 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 15 | Alignment: 1 | ||
| 16 | SectionData: 2f656e7472793a437573746f6d456e74727900 # /entry:CustomEntry | ||
| 17 | symbols: | ||
| 18 | - Name: _CustomEntry | ||
| 19 | Value: 0 | ||
| 20 | SectionNumber: 1 | ||
| 21 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 22 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 23 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 24 | ... | ||
deps/lld/test/COFF/entry-inference.test+4-4| ... | @@ -14,10 +14,10 @@ | ... | @@ -14,10 +14,10 @@ |
| 14 | # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 | 14 | # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 |
| 15 | # RUN: FileCheck -check-prefix=WWINMAIN %s < %t.log | 15 | # RUN: FileCheck -check-prefix=WWINMAIN %s < %t.log |
| 16 | 16 | ||
| 17 | # MAIN: <root>: undefined symbol: mainCRTStartup | 17 | # MAIN: error: <root>: undefined symbol: mainCRTStartup |
| 18 | # WMAIN: <root>: undefined symbol: wmainCRTStartup | 18 | # WMAIN: error: <root>: undefined symbol: wmainCRTStartup |
| 19 | # WINMAIN: <root>: undefined symbol: WinMainCRTStartup | 19 | # WINMAIN: error: <root>: undefined symbol: WinMainCRTStartup |
| 20 | # WWINMAIN: <root>: undefined symbol: wWinMainCRTStartup | 20 | # WWINMAIN: error: <root>: undefined symbol: wWinMainCRTStartup |
| 21 | 21 | ||
| 22 | --- !COFF | 22 | --- !COFF |
| 23 | header: | 23 | header: |
deps/lld/test/COFF/export-all.s created+86| ... | @@ -0,0 +1,86 @@ | ||
| 1 | # REQEUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj | ||
| 4 | |||
| 5 | # RUN: lld-link -lldmingw -dll -out:%t.dll -entry:DllMainCRTStartup@12 %t.obj -implib:%t.lib | ||
| 6 | # RUN: llvm-readobj -coff-exports %t.dll | FileCheck %s | ||
| 7 | # RUN: llvm-readobj %t.lib | FileCheck -check-prefix=IMPLIB %s | ||
| 8 | |||
| 9 | # CHECK-NOT: Name: DllMainCRTStartup | ||
| 10 | # CHECK-NOT: Name: _imp__unexported | ||
| 11 | # CHECK: Name: dataSym | ||
| 12 | # CHECK: Name: foobar | ||
| 13 | # CHECK-NOT: Name: unexported | ||
| 14 | |||
| 15 | # IMPLIB: Symbol: __imp__dataSym | ||
| 16 | # IMPLIB-NOT: Symbol: _dataSym | ||
| 17 | # IMPLIB: Symbol: __imp__foobar | ||
| 18 | # IMPLIB: Symbol: _foobar | ||
| 19 | |||
| 20 | .global _foobar | ||
| 21 | .global _DllMainCRTStartup@12 | ||
| 22 | .global _dataSym | ||
| 23 | .global _unexported | ||
| 24 | .global __imp__unexported | ||
| 25 | .text | ||
| 26 | _DllMainCRTStartup@12: | ||
| 27 | ret | ||
| 28 | _foobar: | ||
| 29 | ret | ||
| 30 | _unexported: | ||
| 31 | ret | ||
| 32 | .data | ||
| 33 | _dataSym: | ||
| 34 | .int 4 | ||
| 35 | __imp__unexported: | ||
| 36 | .int _unexported | ||
| 37 | |||
| 38 | # Test specifying -export-all-symbols, on an object file that contains | ||
| 39 | # dllexport directive for some of the symbols. | ||
| 40 | |||
| 41 | # RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj | ||
| 42 | # | ||
| 43 | # RUN: lld-link -out:%t.dll -dll %t.obj -lldmingw -export-all-symbols -output-def:%t.def | ||
| 44 | # RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix=CHECK2 %s | ||
| 45 | # RUN: cat %t.def | FileCheck -check-prefix=CHECK2-DEF %s | ||
| 46 | |||
| 47 | # Note, this will actually export _DllMainCRTStartup as well, since | ||
| 48 | # it uses the standard spelling in this object file, not the MinGW one. | ||
| 49 | |||
| 50 | # CHECK2: Name: exportfn1 | ||
| 51 | # CHECK2: Name: exportfn2 | ||
| 52 | # CHECK2: Name: exportfn3 | ||
| 53 | |||
| 54 | # CHECK2-DEF: EXPORTS | ||
| 55 | # CHECK2-DEF: exportfn1 @3 | ||
| 56 | # CHECK2-DEF: exportfn2 @4 | ||
| 57 | # CHECK2-DEF: exportfn3 @5 | ||
| 58 | |||
| 59 | # Test ignoring certain object files and libs. | ||
| 60 | |||
| 61 | # RUN: echo -e ".global foobar\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\nfoobar:\ncall mingwfunc\ncall crtfunc\nret\n" > %t.main.s | ||
| 62 | # RUN: llvm-mc -triple=x86_64-windows-gnu %t.main.s -filetype=obj -o %t.main.obj | ||
| 63 | # RUN: mkdir -p %T/libs | ||
| 64 | # RUN: echo -e ".global mingwfunc\n.text\nmingwfunc:\nret\n" > %T/libs/mingwfunc.s | ||
| 65 | # RUN: llvm-mc -triple=x86_64-windows-gnu %T/libs/mingwfunc.s -filetype=obj -o %T/libs/mingwfunc.o | ||
| 66 | # RUN: llvm-ar rcs %T/libs/libmingwex.a %T/libs/mingwfunc.o | ||
| 67 | # RUN: echo -e ".global crtfunc\n.text\ncrtfunc:\nret\n" > %T/libs/crtfunc.s | ||
| 68 | # RUN: llvm-mc -triple=x86_64-windows-gnu %T/libs/crtfunc.s -filetype=obj -o %T/libs/crt2.o | ||
| 69 | # RUN: lld-link -out:%t.dll -dll -entry:DllMainCRTStartup %t.main.obj -lldmingw %T/libs/crt2.o %T/libs/libmingwex.a -output-def:%t.def | ||
| 70 | # RUN: echo "EOF" >> %t.def | ||
| 71 | # RUN: cat %t.def | FileCheck -check-prefix=CHECK-EXCLUDE %s | ||
| 72 | |||
| 73 | # CHECK-EXCLUDE: EXPORTS | ||
| 74 | # CHECK-EXCLUDE-NEXT: foobar @1 | ||
| 75 | # CHECK-EXCLUDE-NEXT: EOF | ||
| 76 | |||
| 77 | # Test that we handle import libraries together with -opt:noref. | ||
| 78 | |||
| 79 | # RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj | ||
| 80 | # RUN: lld-link -lldmingw -dll -out:%t.dll -entry:main@0 %t.obj -implib:%t.lib -opt:noref %p/Inputs/std32.lib -output-def:%t.def | ||
| 81 | # RUN: echo "EOF" >> %t.def | ||
| 82 | # RUN: cat %t.def | FileCheck -check-prefix=CHECK-IMPLIB %s | ||
| 83 | |||
| 84 | # CHECK-IMPLIB: EXPORTS | ||
| 85 | # CHECK-IMPLIB-NEXT: main@0 @1 | ||
| 86 | # CHECK-IMPLIB-NEXT: EOF | ||
deps/lld/test/COFF/export-arm64.yaml created+70| ... | @@ -0,0 +1,70 @@ | ||
| 1 | # REQUIRES: aarch64 | ||
| 2 | |||
| 3 | # RUN: yaml2obj < %s > %t.obj | ||
| 4 | # RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 /implib:%t.lib | ||
| 5 | # RUN: llvm-objdump -p %t.dll | FileCheck %s | ||
| 6 | # RUN: llvm-objdump -r %t.lib | FileCheck %s -check-prefix=RELOCS | ||
| 7 | |||
| 8 | # CHECK: Export Table: | ||
| 9 | # CHECK: DLL name: export-arm64.yaml.tmp.dll | ||
| 10 | # CHECK: Ordinal RVA Name | ||
| 11 | # CHECK-NEXT: 0 0 | ||
| 12 | # CHECK-NEXT: 1 0x1008 exportfn1 | ||
| 13 | # CHECK-NEXT: 2 0x1010 exportfn2 | ||
| 14 | # CHECK-NEXT: 3 0x1018 exportfn3 | ||
| 15 | |||
| 16 | # RELOCS: IMAGE_REL_ARM64_ADDR32NB .idata$6 | ||
| 17 | # RELOCS: IMAGE_REL_ARM64_ADDR32NB .idata$4 | ||
| 18 | # RELOCS: IMAGE_REL_ARM64_ADDR32NB .idata$5 | ||
| 19 | |||
| 20 | --- !COFF | ||
| 21 | header: | ||
| 22 | Machine: IMAGE_FILE_MACHINE_ARM64 | ||
| 23 | Characteristics: [] | ||
| 24 | sections: | ||
| 25 | - Name: .text | ||
| 26 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 27 | Alignment: 4 | ||
| 28 | SectionData: e0031f2ac0035fd6e0031f2ac0035fd6e0031f2ac0035fd6e0031f2ac0035fd6 | ||
| 29 | - Name: .drectve | ||
| 30 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 31 | Alignment: 1 | ||
| 32 | SectionData: 2f6578706f72743a6578706f7274666e3300 # /export:exportfn3 | ||
| 33 | symbols: | ||
| 34 | - Name: .text | ||
| 35 | Value: 0 | ||
| 36 | SectionNumber: 1 | ||
| 37 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 38 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 39 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 40 | SectionDefinition: | ||
| 41 | Length: 32 | ||
| 42 | NumberOfRelocations: 0 | ||
| 43 | NumberOfLinenumbers: 0 | ||
| 44 | CheckSum: 0 | ||
| 45 | Number: 1 | ||
| 46 | - Name: _DllMainCRTStartup | ||
| 47 | Value: 0 | ||
| 48 | SectionNumber: 1 | ||
| 49 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 50 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 51 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 52 | - Name: exportfn1 | ||
| 53 | Value: 8 | ||
| 54 | SectionNumber: 1 | ||
| 55 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 56 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 57 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 58 | - Name: exportfn2 | ||
| 59 | Value: 16 | ||
| 60 | SectionNumber: 1 | ||
| 61 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 62 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 63 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 64 | - Name: exportfn3 | ||
| 65 | Value: 24 | ||
| 66 | SectionNumber: 1 | ||
| 67 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 68 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 69 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 70 | ... | ||
deps/lld/test/COFF/export-armnt.yaml created+95| ... | @@ -0,0 +1,95 @@ | ||
| 1 | # REQUIRES: arm | ||
| 2 | |||
| 3 | # RUN: yaml2obj < %s > %t.obj | ||
| 4 | # | ||
| 5 | # RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 /export:exportdata,data | ||
| 6 | # RUN: llvm-objdump -p %t.dll | FileCheck %s | ||
| 7 | |||
| 8 | # CHECK: Export Table: | ||
| 9 | # CHECK: DLL name: export-armnt.yaml.tmp.dll | ||
| 10 | # CHECK: Ordinal RVA Name | ||
| 11 | # CHECK-NEXT: 0 0 | ||
| 12 | # CHECK-NEXT: 1 0x1000 exportdata | ||
| 13 | # CHECK-NEXT: 2 0x2005 exportfn1 | ||
| 14 | # CHECK-NEXT: 3 0x2009 exportfn2 | ||
| 15 | # CHECK-NEXT: 4 0x2009 exportfn3 | ||
| 16 | |||
| 17 | --- !COFF | ||
| 18 | header: | ||
| 19 | Machine: IMAGE_FILE_MACHINE_ARMNT | ||
| 20 | Characteristics: [] | ||
| 21 | sections: | ||
| 22 | - Name: .text | ||
| 23 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 24 | Alignment: 4 | ||
| 25 | SectionData: 704700bf704700bf704700bf | ||
| 26 | - Name: .data | ||
| 27 | Characteristics: [ IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 28 | Alignment: 4 | ||
| 29 | SectionData: 00000000 | ||
| 30 | - Name: .drectve | ||
| 31 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 32 | Alignment: 1 | ||
| 33 | SectionData: 2f6578706f72743a6578706f7274666e3300 # /export:exportfn3 | ||
| 34 | symbols: | ||
| 35 | - Name: .text | ||
| 36 | Value: 0 | ||
| 37 | SectionNumber: 1 | ||
| 38 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 39 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 40 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 41 | SectionDefinition: | ||
| 42 | Length: 12 | ||
| 43 | NumberOfRelocations: 0 | ||
| 44 | NumberOfLinenumbers: 0 | ||
| 45 | CheckSum: 0 | ||
| 46 | Number: 0 | ||
| 47 | - Name: .data | ||
| 48 | Value: 0 | ||
| 49 | SectionNumber: 2 | ||
| 50 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 51 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 52 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 53 | SectionDefinition: | ||
| 54 | Length: 4 | ||
| 55 | NumberOfRelocations: 0 | ||
| 56 | NumberOfLinenumbers: 0 | ||
| 57 | CheckSum: 0 | ||
| 58 | Number: 0 | ||
| 59 | - Name: _DllMainCRTStartup | ||
| 60 | Value: 0 | ||
| 61 | SectionNumber: 1 | ||
| 62 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 63 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 64 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 65 | - Name: exportfn1 | ||
| 66 | Value: 4 | ||
| 67 | SectionNumber: 1 | ||
| 68 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 69 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 70 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 71 | - Name: exportfn2 | ||
| 72 | Value: 8 | ||
| 73 | SectionNumber: 1 | ||
| 74 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 75 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 76 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 77 | - Name: exportfn3 | ||
| 78 | Value: 8 | ||
| 79 | SectionNumber: 1 | ||
| 80 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 81 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 82 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 83 | - Name: exportdata | ||
| 84 | Value: 0 | ||
| 85 | SectionNumber: 2 | ||
| 86 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 87 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 88 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 89 | - Name: '?mangled@@YAHXZ' | ||
| 90 | Value: 8 | ||
| 91 | SectionNumber: 1 | ||
| 92 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 93 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 94 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 95 | ... | ||
deps/lld/test/COFF/export32.test+5| ... | @@ -57,6 +57,11 @@ | ... | @@ -57,6 +57,11 @@ |
| 57 | # RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def | 57 | # RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def |
| 58 | # RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s | 58 | # RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s |
| 59 | 59 | ||
| 60 | # RUN: echo "EXPORTS exportfn1 @ 3" > %t.def | ||
| 61 | # RUN: echo "fn2=exportfn2 @ 2" >> %t.def | ||
| 62 | # RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def | ||
| 63 | # RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s | ||
| 64 | |||
| 60 | # CHECK5: Export Table: | 65 | # CHECK5: Export Table: |
| 61 | # CHECK5: DLL name: export32.test.tmp.dll | 66 | # CHECK5: DLL name: export32.test.tmp.dll |
| 62 | # CHECK5: Ordinal RVA Name | 67 | # CHECK5: Ordinal RVA Name |
deps/lld/test/COFF/filename-casing.s created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %T/MixedCase.obj %s | ||
| 4 | # RUN: not lld-link /entry:main %T/MixedCase.obj 2>&1 | FileCheck -check-prefix=OBJECT %s | ||
| 5 | |||
| 6 | # RUN: llvm-lib /out:%T/MixedCase.lib %T/MixedCase.obj | ||
| 7 | # RUN: not lld-link /machine:x64 /entry:main %T/MixedCase.lib 2>&1 | FileCheck -check-prefix=ARCHIVE %s | ||
| 8 | |||
| 9 | # OBJECT: MixedCase.obj: undefined symbol: f | ||
| 10 | # ARCHIVE: MixedCase.lib(MixedCase.obj): undefined symbol: f | ||
| 11 | |||
| 12 | .globl main | ||
| 13 | main: | ||
| 14 | 	callq	f | ||
deps/lld/test/COFF/force.test+4-3| ... | @@ -1,10 +1,11 @@ | ... | @@ -1,10 +1,11 @@ |
| 1 | # RUN: yaml2obj < %s > %t.obj | 1 | # RUN: yaml2obj < %s > %t.obj |
| 2 | # RUN: not lld-link /out:%t.exe /entry:main %t.obj >& %t.log | 2 | # RUN: not lld-link /out:%t.exe /entry:main %t.obj >& %t.log |
| 3 | # RUN: FileCheck %s < %t.log | 3 | # RUN: FileCheck -check-prefix=ERROR %s < %t.log |
| 4 | # RUN: lld-link /out:%t.exe /entry:main %t.obj /force >& %t.log | 4 | # RUN: lld-link /out:%t.exe /entry:main %t.obj /force >& %t.log |
| 5 | # RUN: FileCheck %s < %t.log | 5 | # RUN: FileCheck -check-prefix=WARN %s < %t.log |
| 6 | 6 | ||
| 7 | # CHECK: .obj: undefined symbol: foo | 7 | # ERROR: error: {{.*}}.obj: undefined symbol: foo |
| 8 | # WARN: warning: {{.*}}.obj: undefined symbol: foo | ||
| 8 | 9 | ||
| 9 | --- !COFF | 10 | --- !COFF |
| 10 | header: | 11 | header: |
deps/lld/test/COFF/guardcf.test+6| ... | @@ -71,4 +71,10 @@ symbols: | ... | @@ -71,4 +71,10 @@ symbols: |
| 71 | SimpleType: IMAGE_SYM_TYPE_NULL | 71 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 72 | ComplexType: IMAGE_SYM_DTYPE_NULL | 72 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 73 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | 73 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL |
| 74 | - Name: __enclave_config | ||
| 75 | Value: 0 | ||
| 76 | SectionNumber: 0 | ||
| 77 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 78 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 79 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 74 | ... | 80 | ... |
deps/lld/test/COFF/hello32.test+3-3| ... | @@ -39,13 +39,13 @@ HEADER-NEXT: MajorImageVersion: 0 | ... | @@ -39,13 +39,13 @@ HEADER-NEXT: MajorImageVersion: 0 |
| 39 | HEADER-NEXT: MinorImageVersion: 0 | 39 | HEADER-NEXT: MinorImageVersion: 0 |
| 40 | HEADER-NEXT: MajorSubsystemVersion: 6 | 40 | HEADER-NEXT: MajorSubsystemVersion: 6 |
| 41 | HEADER-NEXT: MinorSubsystemVersion: 0 | 41 | HEADER-NEXT: MinorSubsystemVersion: 0 |
| 42 | HEADER-NEXT: SizeOfImage: 16896 | 42 | HEADER-NEXT: SizeOfImage: 20480 |
| 43 | HEADER-NEXT: SizeOfHeaders: 512 | 43 | HEADER-NEXT: SizeOfHeaders: 512 |
| 44 | HEADER-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3) | 44 | HEADER-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3) |
| 45 | HEADER-NEXT: Characteristics [ (0x9940) | 45 | HEADER-NEXT: Characteristics [ (0x9540) |
| 46 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_APPCONTAINER (0x1000) | 46 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_APPCONTAINER (0x1000) |
| 47 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40) | 47 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40) |
| 48 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NO_BIND (0x800) | 48 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NO_SEH (0x400) |
| 49 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100) | 49 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100) |
| 50 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000) | 50 | HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000) |
| 51 | HEADER-NEXT: ] | 51 | HEADER-NEXT: ] |
deps/lld/test/COFF/icf-associative.test+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | # RUN: yaml2obj < %s > %t.obj | 1 | # RUN: yaml2obj < %s > %t.obj |
| 2 | # RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \ | 2 | # RUN: lld-link /opt:icf /entry:foo /out:%t.exe /subsystem:console /include:bar \ |
| 3 | # RUN: /debug /verbose %t.obj > %t.log 2>&1 | 3 | # RUN: /debug /verbose %t.obj > %t.log 2>&1 |
| 4 | # RUN: FileCheck %s < %t.log | 4 | # RUN: FileCheck %s < %t.log |
| 5 | 5 |
deps/lld/test/COFF/icf-executable.s created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | # RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t.obj | ||
| 2 | # RUN: lld-link -entry:main %t.obj -out:%t.exe -verbose 2>&1 | FileCheck %s | ||
| 3 | |||
| 4 | # CHECK: Selected internal | ||
| 5 | # CHECK: Removed f2 | ||
| 6 | |||
| 7 | .section .text,"xr",one_only,internal | ||
| 8 | internal: | ||
| 9 | .globl main | ||
| 10 | main: | ||
| 11 | call f2 | ||
| 12 | ret | ||
| 13 | |||
| 14 | .section .text,"xr",one_only,f2 | ||
| 15 | .globl f2 | ||
| 16 | f2: | ||
| 17 | call main | ||
| 18 | ret | ||
deps/lld/test/COFF/icf-simple.test+26-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | # RUN: yaml2obj < %s > %t.obj | 1 | # RUN: yaml2obj < %s > %t.obj |
| 2 | # RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \ | 2 | # RUN: lld-link /opt:icf /entry:foo /out:%t.exe /subsystem:console /include:bar \ |
| 3 | # RUN: /verbose %t.obj > %t.log 2>&1 | 3 | # RUN: /verbose %t.obj > %t.log 2>&1 |
| 4 | # RUN: FileCheck -check-prefix=ICF %s < %t.log | 4 | # RUN: FileCheck -check-prefix=ICF %s < %t.log |
| 5 | 5 | ||
| ... | @@ -13,6 +13,31 @@ | ... | @@ -13,6 +13,31 @@ |
| 13 | # RUN: /verbose /opt:noref,noicf %t.obj > %t.log 2>&1 | 13 | # RUN: /verbose /opt:noref,noicf %t.obj > %t.log 2>&1 |
| 14 | # RUN: FileCheck -check-prefix=NOICF %s < %t.log | 14 | # RUN: FileCheck -check-prefix=NOICF %s < %t.log |
| 15 | 15 | ||
| 16 | # ICF is on by default (no /opt: flags). | ||
| 17 | # RUN: lld-link /entry:foo /out:%t.exe /subsystem:console \ | ||
| 18 | # RUN: /include:bar /verbose %t.obj > %t.log 2>&1 | ||
| 19 | # RUN: FileCheck -check-prefix=ICF %s < %t.log | ||
| 20 | |||
| 21 | # /debug disables ICF. | ||
| 22 | # RUN: lld-link /debug /entry:foo /out:%t.exe /subsystem:console \ | ||
| 23 | # RUN: /include:bar /verbose %t.obj > %t.log 2>&1 | ||
| 24 | # RUN: FileCheck -check-prefix=NOICF %s < %t.log | ||
| 25 | |||
| 26 | # /opt:noref disables ICF. | ||
| 27 | # RUN: lld-link /opt:noref /entry:foo /out:%t.exe /subsystem:console \ | ||
| 28 | # RUN: /include:bar /verbose %t.obj > %t.log 2>&1 | ||
| 29 | # RUN: FileCheck -check-prefix=NOICF %s < %t.log | ||
| 30 | |||
| 31 | # /debug /opt:ref enables ICF. | ||
| 32 | # RUN: lld-link /debug /opt:ref /entry:foo /out:%t.exe /subsystem:console \ | ||
| 33 | # RUN: /include:bar /verbose %t.obj > %t.log 2>&1 | ||
| 34 | # RUN: FileCheck -check-prefix=ICF %s < %t.log | ||
| 35 | |||
| 36 | # /debug /opt:noicf,ref disables ICF. | ||
| 37 | # RUN: lld-link /debug /opt:noicf,ref /entry:foo /out:%t.exe /subsystem:console \ | ||
| 38 | # RUN: /include:bar /verbose %t.obj > %t.log 2>&1 | ||
| 39 | # RUN: FileCheck -check-prefix=NOICF %s < %t.log | ||
| 40 | |||
| 16 | # NOICF-NOT: Removed foo | 41 | # NOICF-NOT: Removed foo |
| 17 | # NOICF-NOT: Removed bar | 42 | # NOICF-NOT: Removed bar |
| 18 | 43 |
deps/lld/test/COFF/icf-xdata.s created+86| ... | @@ -0,0 +1,86 @@ | ||
| 1 | # RUN: llvm-mc %s -triple x86_64-windows-msvc -filetype=obj -o %t.obj | ||
| 2 | # RUN: lld-link %t.obj -dll -noentry -out:%t.dll | ||
| 3 | # RUN: llvm-readobj -sections %t.dll | FileCheck %s | ||
| 4 | |||
| 5 | # There shouldn't be much xdata, because all three .pdata entries (12 bytes | ||
| 6 | # each) should use the same .xdata unwind info. | ||
| 7 | # CHECK: Name: .pdata | ||
| 8 | # CHECK-NEXT: VirtualSize: 0x24 | ||
| 9 | # CHECK: Name: .xdata | ||
| 10 | # CHECK-NEXT: VirtualSize: 0x8 | ||
| 11 | |||
| 12 | 	.text | ||
| 13 | callee: | ||
| 14 | 	ret | ||
| 15 | |||
| 16 | 	.def	 xdata1; | ||
| 17 | 	.scl	2; | ||
| 18 | 	.type	32; | ||
| 19 | 	.endef | ||
| 20 | 	.section	.text,"xr",one_only,xdata1 | ||
| 21 | 	.globl	xdata1 # -- Begin function xdata1 | ||
| 22 | 	.p2align	4, 0x90 | ||
| 23 | xdata1: # @xdata1 | ||
| 24 | .seh_proc xdata1 | ||
| 25 | # BB#0: # %entry | ||
| 26 | 	subq	$40, %rsp | ||
| 27 | 	.seh_stackalloc 40 | ||
| 28 | 	.seh_endprologue | ||
| 29 | 	callq	callee | ||
| 30 | 	nop | ||
| 31 | 	addq	$40, %rsp | ||
| 32 | 	jmp	callee # TAILCALL | ||
| 33 | 	.seh_handlerdata | ||
| 34 | 	.section	.text,"xr",one_only,xdata1 | ||
| 35 | 	.seh_endproc | ||
| 36 | # -- End function | ||
| 37 | 	.def	 xdata2; | ||
| 38 | 	.scl	2; | ||
| 39 | 	.type	32; | ||
| 40 | 	.endef | ||
| 41 | 	.section	.text,"xr",one_only,xdata2 | ||
| 42 | 	.globl	xdata2 # -- Begin function xdata2 | ||
| 43 | 	.p2align	4, 0x90 | ||
| 44 | xdata2: # @xdata2 | ||
| 45 | .seh_proc xdata2 | ||
| 46 | # BB#0: # %entry | ||
| 47 | 	subq	$40, %rsp | ||
| 48 | 	.seh_stackalloc 40 | ||
| 49 | 	.seh_endprologue | ||
| 50 | 	callq	callee | ||
| 51 | 	callq	callee | ||
| 52 | 	nop | ||
| 53 | 	addq	$40, %rsp | ||
| 54 | 	jmp	callee # TAILCALL | ||
| 55 | 	.seh_handlerdata | ||
| 56 | 	.section	.text,"xr",one_only,xdata2 | ||
| 57 | 	.seh_endproc | ||
| 58 | # -- End function | ||
| 59 | 	.def	 xdata3; | ||
| 60 | 	.scl	2; | ||
| 61 | 	.type	32; | ||
| 62 | 	.endef | ||
| 63 | 	.section	.text,"xr",one_only,xdata3 | ||
| 64 | 	.globl	xdata3 # -- Begin function xdata3 | ||
| 65 | 	.p2align	4, 0x90 | ||
| 66 | xdata3: # @xdata3 | ||
| 67 | .seh_proc xdata3 | ||
| 68 | # BB#0: # %entry | ||
| 69 | 	subq	$40, %rsp | ||
| 70 | 	.seh_stackalloc 40 | ||
| 71 | 	.seh_endprologue | ||
| 72 | 	callq	callee | ||
| 73 | 	callq	callee | ||
| 74 | 	callq	callee | ||
| 75 | 	nop | ||
| 76 | 	addq	$40, %rsp | ||
| 77 | 	jmp	callee # TAILCALL | ||
| 78 | 	.seh_handlerdata | ||
| 79 | 	.section	.text,"xr",one_only,xdata3 | ||
| 80 | 	.seh_endproc | ||
| 81 | # -- End function | ||
| 82 | 	.section	.drectve,"yn" | ||
| 83 | 	.ascii	" -export:xdata1" | ||
| 84 | 	.ascii	" -export:xdata2" | ||
| 85 | 	.ascii	" -export:xdata3" | ||
| 86 | |||
deps/lld/test/COFF/ignore4217.yaml created+72| ... | @@ -0,0 +1,72 @@ | ||
| 1 | # Tests that /ignore:4217 suppresses "locally defined symbol imported" warnings. | ||
| 2 | # RUN: yaml2obj < %s > %t.obj | ||
| 3 | |||
| 4 | # RUN: lld-link -entry:main -out:%t.exe %t.obj 2>&1 \ | ||
| 5 | # RUN: | FileCheck -check-prefix=WARNINGS %s | ||
| 6 | # RUN: lld-link -ignore:4217 -entry:main -out:%t.exe %t.obj 2>&1 \ | ||
| 7 | # RUN: | FileCheck -allow-empty -check-prefix=SUPPRESSED %s | ||
| 8 | |||
| 9 | # WARNINGS: locally defined symbol imported | ||
| 10 | # SUPPRESSED-NOT: locally defined symbol imported | ||
| 11 | |||
| 12 | --- !COFF | ||
| 13 | header: | ||
| 14 | Machine: IMAGE_FILE_MACHINE_AMD64 | ||
| 15 | Characteristics: [ ] | ||
| 16 | sections: | ||
| 17 | - Name: .text | ||
| 18 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 19 | Alignment: 16 | ||
| 20 | SectionData: B82A000000C3662E0F1F8400000000004883EC28C744242400000000E800000000904883C428C3 | ||
| 21 | Relocations: | ||
| 22 | - VirtualAddress: 29 | ||
| 23 | SymbolName: __imp_foo | ||
| 24 | Type: IMAGE_REL_AMD64_REL32 | ||
| 25 | - Name: .data | ||
| 26 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | ||
| 27 | Alignment: 4 | ||
| 28 | SectionData: '' | ||
| 29 | symbols: | ||
| 30 | - Name: .text | ||
| 31 | Value: 0 | ||
| 32 | SectionNumber: 1 | ||
| 33 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 34 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 35 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 36 | SectionDefinition: | ||
| 37 | Length: 39 | ||
| 38 | NumberOfRelocations: 1 | ||
| 39 | NumberOfLinenumbers: 0 | ||
| 40 | CheckSum: 3087210877 | ||
| 41 | Number: 1 | ||
| 42 | - Name: .data | ||
| 43 | Value: 0 | ||
| 44 | SectionNumber: 2 | ||
| 45 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 46 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 47 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 48 | SectionDefinition: | ||
| 49 | Length: 0 | ||
| 50 | NumberOfRelocations: 0 | ||
| 51 | NumberOfLinenumbers: 0 | ||
| 52 | CheckSum: 0 | ||
| 53 | Number: 2 | ||
| 54 | - Name: foo | ||
| 55 | Value: 0 | ||
| 56 | SectionNumber: 1 | ||
| 57 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 58 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 59 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 60 | - Name: main | ||
| 61 | Value: 16 | ||
| 62 | SectionNumber: 1 | ||
| 63 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 64 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 65 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 66 | - Name: __imp_foo | ||
| 67 | Value: 0 | ||
| 68 | SectionNumber: 0 | ||
| 69 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 70 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 71 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 72 | ... | ||
deps/lld/test/COFF/include.test+13| ... | @@ -62,6 +62,19 @@ symbols: | ... | @@ -62,6 +62,19 @@ symbols: |
| 62 | CheckSum: 0 | 62 | CheckSum: 0 |
| 63 | Number: 0 | 63 | Number: 0 |
| 64 | Selection: IMAGE_COMDAT_SELECT_ANY | 64 | Selection: IMAGE_COMDAT_SELECT_ANY |
| 65 | - Name: '.text$mn' | ||
| 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: 6 | ||
| 73 | NumberOfRelocations: 0 | ||
| 74 | NumberOfLinenumbers: 0 | ||
| 75 | CheckSum: 0 | ||
| 76 | Number: 0 | ||
| 77 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 65 | - Name: main | 78 | - Name: main |
| 66 | Value: 0 | 79 | Value: 0 |
| 67 | SectionNumber: 1 | 80 | SectionNumber: 1 |
deps/lld/test/COFF/libpath.test+10-2| ... | @@ -5,14 +5,22 @@ | ... | @@ -5,14 +5,22 @@ |
| 5 | 5 | ||
| 6 | # RUN: env LIB=%t/a lld-link /out:%t.exe /entry:main /verbose \ | 6 | # RUN: env LIB=%t/a lld-link /out:%t.exe /entry:main /verbose \ |
| 7 | # RUN: std64.lib /subsystem:console %p/Inputs/hello64.obj \ | 7 | # RUN: std64.lib /subsystem:console %p/Inputs/hello64.obj \ |
| 8 | # RUN: /libpath:%t/b /libpath:%t/c > %t.log | 8 | # RUN: /libpath:%t/b /libpath:%t/c 2> %t.log |
| 9 | # RUN: FileCheck -check-prefix=CHECK1 %s < %t.log | 9 | # RUN: FileCheck -check-prefix=CHECK1 %s < %t.log |
| 10 | 10 | ||
| 11 | CHECK1: b{{[/\\]}}std64.lib | 11 | CHECK1: b{{[/\\]}}std64.lib |
| 12 | 12 | ||
| 13 | # RUN: lld-link /out:%t.exe /entry:main /verbose \ | 13 | # RUN: lld-link /out:%t.exe /entry:main /verbose \ |
| 14 | # RUN: std64.lib /subsystem:console %p/Inputs/hello64.obj \ | 14 | # RUN: std64.lib /subsystem:console %p/Inputs/hello64.obj \ |
| 15 | # RUN: /libpath:%t/a /libpath:%t/b /libpath:%t/c > %t.log | 15 | # RUN: /libpath:%t/a /libpath:%t/b /libpath:%t/c 2> %t.log |
| 16 | # RUN: FileCheck -check-prefix=CHECK2 %s < %t.log | 16 | # RUN: FileCheck -check-prefix=CHECK2 %s < %t.log |
| 17 | 17 | ||
| 18 | CHECK2: a{{[/\\]}}std64.lib | 18 | CHECK2: a{{[/\\]}}std64.lib |
| 19 | |||
| 20 | # RUN: lld-link /out:%t.exe /entry:main /verbose \ | ||
| 21 | # RUN: %t/a/std64.lib /subsystem:console %p/Inputs/hello64.obj \ | ||
| 22 | # RUN: /libpath:%t/b /verbose > %t.log 2>&1 | ||
| 23 | # RUN: FileCheck -check-prefix=CHECK3 %s < %t.log | ||
| 24 | |||
| 25 | CHECK3: Reading {{.*}}a/std64.lib | ||
| 26 | CHECK3-NOT: Reading {{.*}}b/std64.lib |
deps/lld/test/COFF/linkrepro-manifest.test created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | REQUIRES: x86, gnutar, manifest_tool | ||
| 2 | |||
| 3 | RUN: rm -rf %t && mkdir %t && cd %t | ||
| 4 | RUN: lld-link -entry:__ImageBase -nodefaultlib -linkrepro:%t -manifest:embed %p/Inputs/std32.lib -subsystem:console | ||
| 5 | RUN: tar tf repro.tar | FileCheck --check-prefix=LIST %s | ||
| 6 | RUN: tar xOf repro.tar repro/response.txt | FileCheck %s | ||
| 7 | |||
| 8 | LIST: manifest.res | ||
| 9 | |||
| 10 | CHECK-NOT: -manifest: | ||
| 11 | CHECK: .manifest.res | ||
| 12 | CHECK-NOT: -manifest: | ||
deps/lld/test/COFF/linkrepro-pdb.test created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | REQUIRES: x86, gnutar | ||
| 2 | |||
| 3 | RUN: rm -rf %t && mkdir -p %t && cd %t | ||
| 4 | RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj | ||
| 5 | RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj | ||
| 6 | RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb | ||
| 7 | RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib -linkrepro:. | ||
| 8 | RUN: tar xOf repro.tar repro/%:t/ts.pdb > repro-ts.pdb | ||
| 9 | RUN: diff ts.pdb repro-ts.pdb | ||
deps/lld/test/COFF/linkrepro-res.test created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | # REQUIRES: x86, shell | ||
| 2 | |||
| 3 | # RUN: rm -rf %t.dir | ||
| 4 | # RUN: mkdir -p %t.dir/build | ||
| 5 | # RUN: cd %t.dir/build | ||
| 6 | # RUN: lld-link %p/Inputs/resource.res /subsystem:console /machine:x64 \ | ||
| 7 | # RUN: /entry:__ImageBase /linkrepro:. /out:%t.exe | ||
| 8 | # RUN: tar xf repro.tar | ||
| 9 | # RUN: diff %p/Inputs/resource.res repro/%:p/Inputs/resource.res | ||
| 10 | # RUN: FileCheck %s --check-prefix=RSP < repro/response.txt | ||
| 11 | |||
| 12 | # RSP: resource.res | ||
deps/lld/test/COFF/loadcfg.test+2-19| ... | @@ -14,10 +14,6 @@ sections: | ... | @@ -14,10 +14,6 @@ sections: |
| 14 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 14 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] |
| 15 | Alignment: 4 | 15 | Alignment: 4 |
| 16 | SectionData: B82A000000C3 | 16 | SectionData: B82A000000C3 |
| 17 | - Name: .text | ||
| 18 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 19 | Alignment: 4 | ||
| 20 | SectionData: B82A000000C3 | ||
| 21 | - Name: .rdata | 17 | - Name: .rdata |
| 22 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | 18 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] |
| 23 | Alignment: 16 | 19 | Alignment: 16 |
| ... | @@ -35,19 +31,6 @@ symbols: | ... | @@ -35,19 +31,6 @@ symbols: |
| 35 | NumberOfLinenumbers: 0 | 31 | NumberOfLinenumbers: 0 |
| 36 | CheckSum: 0 | 32 | CheckSum: 0 |
| 37 | Number: 0 | 33 | Number: 0 |
| 38 | - Name: .text | ||
| 39 | Value: 0 | ||
| 40 | SectionNumber: 2 | ||
| 41 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 42 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 43 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 44 | SectionDefinition: | ||
| 45 | Length: 6 | ||
| 46 | NumberOfRelocations: 0 | ||
| 47 | NumberOfLinenumbers: 0 | ||
| 48 | CheckSum: 0 | ||
| 49 | Number: 0 | ||
| 50 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 51 | - Name: main | 34 | - Name: main |
| 52 | Value: 0 | 35 | Value: 0 |
| 53 | SectionNumber: 1 | 36 | SectionNumber: 1 |
| ... | @@ -56,7 +39,7 @@ symbols: | ... | @@ -56,7 +39,7 @@ symbols: |
| 56 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | 39 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL |
| 57 | - Name: .rdata | 40 | - Name: .rdata |
| 58 | Value: 0 | 41 | Value: 0 |
| 59 | SectionNumber: 3 | 42 | SectionNumber: 2 |
| 60 | SimpleType: IMAGE_SYM_TYPE_NULL | 43 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 61 | ComplexType: IMAGE_SYM_DTYPE_NULL | 44 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 62 | StorageClass: IMAGE_SYM_CLASS_STATIC | 45 | StorageClass: IMAGE_SYM_CLASS_STATIC |
| ... | @@ -68,7 +51,7 @@ symbols: | ... | @@ -68,7 +51,7 @@ symbols: |
| 68 | Number: 3 | 51 | Number: 3 |
| 69 | - Name: _load_config_used | 52 | - Name: _load_config_used |
| 70 | Value: 0 | 53 | Value: 0 |
| 71 | SectionNumber: 3 | 54 | SectionNumber: 2 |
| 72 | SimpleType: IMAGE_SYM_TYPE_NULL | 55 | SimpleType: IMAGE_SYM_TYPE_NULL |
| 73 | ComplexType: IMAGE_SYM_DTYPE_NULL | 56 | ComplexType: IMAGE_SYM_DTYPE_NULL |
| 74 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | 57 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL |
deps/lld/test/COFF/locally-imported-arm64.test created+61| ... | @@ -0,0 +1,61 @@ | ||
| 1 | # RUN: yaml2obj < %s > %t.obj | ||
| 2 | # RUN: lld-link /out:%t.exe /entry:main %t.obj | ||
| 3 | # RUN: llvm-objdump -s %t.exe | FileCheck %s | ||
| 4 | # RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s | ||
| 5 | |||
| 6 | # CHECK: Contents of section .text: | ||
| 7 | # CHECK-NEXT: 1000 00200000 | ||
| 8 | # CHECK: Contents of section .rdata: | ||
| 9 | # CHECK-NEXT: 2000 04100040 01000000 | ||
| 10 | |||
| 11 | # BASEREL: BaseReloc [ | ||
| 12 | # BASEREL-NEXT: Entry { | ||
| 13 | # BASEREL-NEXT: Type: DIR64 | ||
| 14 | # BASEREL-NEXT: Address: 0x2000 | ||
| 15 | # BASEREL-NEXT: } | ||
| 16 | # BASEREL-NEXT: Entry { | ||
| 17 | # BASEREL-NEXT: Type: ABSOLUTE | ||
| 18 | # BASEREL-NEXT: Address: 0x2000 | ||
| 19 | # BASEREL-NEXT: } | ||
| 20 | # BASEREL-NEXT: ] | ||
| 21 | |||
| 22 | --- !COFF | ||
| 23 | header: | ||
| 24 | Machine: IMAGE_FILE_MACHINE_ARM64 | ||
| 25 | Characteristics: [] | ||
| 26 | sections: | ||
| 27 | - Name: .text | ||
| 28 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 29 | Alignment: 4 | ||
| 30 | SectionData: 00000000 | ||
| 31 | Relocations: | ||
| 32 | - VirtualAddress: 0 | ||
| 33 | SymbolName: __imp_main | ||
| 34 | Type: IMAGE_REL_ARM64_ADDR32NB | ||
| 35 | symbols: | ||
| 36 | - Name: .text | ||
| 37 | Value: 0 | ||
| 38 | SectionNumber: 1 | ||
| 39 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 40 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 41 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 42 | SectionDefinition: | ||
| 43 | Length: 4 | ||
| 44 | NumberOfRelocations: 1 | ||
| 45 | NumberOfLinenumbers: 0 | ||
| 46 | CheckSum: 0 | ||
| 47 | Number: 0 | ||
| 48 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 49 | - Name: main | ||
| 50 | Value: 4 | ||
| 51 | SectionNumber: 1 | ||
| 52 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 53 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 54 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 55 | - Name: __imp_main | ||
| 56 | Value: 0 | ||
| 57 | SectionNumber: 0 | ||
| 58 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 59 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 60 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 61 | ... | ||
deps/lld/test/COFF/locally-imported-warn-multiple.s created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %T/locally-imported-def.obj %S/Inputs/locally-imported-def.s | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %T/locally-imported-imp1.obj %S/Inputs/locally-imported-imp.s | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %T/locally-imported-imp2.obj %S/Inputs/locally-imported-imp.s | ||
| 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %t.obj %s | ||
| 7 | # RUN: lld-link /entry:main %T/locally-imported-def.obj %T/locally-imported-imp1.obj %T/locally-imported-imp2.obj %t.obj 2>&1 | FileCheck %s | ||
| 8 | |||
| 9 | # CHECK: warning: [[TESTDIR:.+]]locally-imported-imp1.obj: locally defined symbol imported: f (defined in [[TESTDIR]]locally-imported-def.obj) | ||
| 10 | # CHECK-NEXT: warning: [[TESTDIR:.+]]locally-imported-imp2.obj: locally defined symbol imported: f (defined in [[TESTDIR]]locally-imported-def.obj) | ||
| 11 | |||
| 12 | .globl main | ||
| 13 | main: | ||
| 14 | 	ret | ||
deps/lld/test/COFF/locally-imported.test+3-1| ... | @@ -1,8 +1,10 @@ | ... | @@ -1,8 +1,10 @@ |
| 1 | # RUN: yaml2obj < %s > %t.obj | 1 | # RUN: yaml2obj < %s > %t.obj |
| 2 | # RUN: lld-link /out:%t.exe /entry:main %t.obj | 2 | # 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 %s | 3 | # RUN: llvm-objdump -s %t.exe | FileCheck %s |
| 4 | # RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s | 4 | # RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s |
| 5 | 5 | ||
| 6 | # WARN: warning: [[INPUT:.+]]: locally defined symbol imported: main (defined in [[INPUT]]) | ||
| 7 | |||
| 6 | # CHECK: Contents of section .text: | 8 | # CHECK: Contents of section .text: |
| 7 | # CHECK-NEXT: 1000 00200000 | 9 | # CHECK-NEXT: 1000 00200000 |
| 8 | # CHECK: Contents of section .rdata: | 10 | # CHECK: Contents of section .rdata: |
deps/lld/test/COFF/long-section-name.test+21-2| ... | @@ -1,7 +1,10 @@ | ... | @@ -1,7 +1,10 @@ |
| 1 | # RUN: yaml2obj < %s > %t.obj | 1 | # RUN: yaml2obj < %s > %t.obj |
| 2 | # RUN: lld-link /debug /out:%t.exe /entry:main %t.obj | 2 | # RUN: lld-link /out:%t.exe /entry:main %t.obj |
| 3 | # RUN: llvm-readobj -sections %t.exe | FileCheck %s | 3 | # RUN: llvm-readobj -sections %t.exe | FileCheck %s |
| 4 | # RUN: lld-link /debug /out:%t2.exe /entry:main %t.obj | ||
| 5 | # RUN: llvm-readobj -sections %t2.exe | FileCheck %s | ||
| 4 | 6 | ||
| 7 | # CHECK: Name: .eh_fram ( | ||
| 5 | # CHECK: Name: .data_long_section_name | 8 | # CHECK: Name: .data_long_section_name |
| 6 | # CHECK: Name: .text_long_section_name | 9 | # CHECK: Name: .text_long_section_name |
| 7 | 10 | ||
| ... | @@ -11,10 +14,14 @@ header: | ... | @@ -11,10 +14,14 @@ header: |
| 11 | Characteristics: [ ] | 14 | Characteristics: [ ] |
| 12 | sections: | 15 | sections: |
| 13 | - Name: .text_long_section_name | 16 | - Name: .text_long_section_name |
| 14 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | 17 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_DISCARDABLE ] |
| 15 | Alignment: 4 | 18 | Alignment: 4 |
| 16 | SectionData: B82A000000C3 | 19 | SectionData: B82A000000C3 |
| 17 | - Name: .data_long_section_name | 20 | - Name: .data_long_section_name |
| 21 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE, IMAGE_SCN_MEM_DISCARDABLE ] | ||
| 22 | Alignment: 4 | ||
| 23 | SectionData: "00" | ||
| 24 | - Name: .eh_frame | ||
| 18 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | 25 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] |
| 19 | Alignment: 4 | 26 | Alignment: 4 |
| 20 | SectionData: "00" | 27 | SectionData: "00" |
| ... | @@ -49,6 +56,18 @@ symbols: | ... | @@ -49,6 +56,18 @@ symbols: |
| 49 | NumberOfLinenumbers: 0 | 56 | NumberOfLinenumbers: 0 |
| 50 | CheckSum: 0 | 57 | CheckSum: 0 |
| 51 | Number: 0 | 58 | Number: 0 |
| 59 | - Name: .eh_frame | ||
| 60 | Value: 0 | ||
| 61 | SectionNumber: 3 | ||
| 62 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 63 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 64 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 65 | SectionDefinition: | ||
| 66 | Length: 0 | ||
| 67 | NumberOfRelocations: 0 | ||
| 68 | NumberOfLinenumbers: 0 | ||
| 69 | CheckSum: 0 | ||
| 70 | Number: 0 | ||
| 52 | - Name: main | 71 | - Name: main |
| 53 | Value: 0 | 72 | Value: 0 |
| 54 | SectionNumber: 1 | 73 | SectionNumber: 1 |
deps/lld/test/COFF/lto-cache.ll created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | ; REQUIRES: x86 | ||
| 2 | |||
| 3 | ; RUN: opt -module-hash -module-summary %s -o %t.o | ||
| 4 | ; RUN: opt -module-hash -module-summary %p/Inputs/lto-cache.ll -o %t2.o | ||
| 5 | |||
| 6 | ; RUN: rm -Rf %t.cache && mkdir %t.cache | ||
| 7 | ; Create two files that would be removed by cache pruning due to age. | ||
| 8 | ; We should only remove files matching the pattern "llvmcache-*". | ||
| 9 | ; RUN: touch -t 197001011200 %t.cache/llvmcache-foo %t.cache/foo | ||
| 10 | ; RUN: lld-link /lldltocache:%t.cache /lldltocachepolicy:prune_after=1h /out:%t3 /entry:main %t2.o %t.o | ||
| 11 | |||
| 12 | ; Two cached objects, plus a timestamp file and "foo", minus the file we removed. | ||
| 13 | ; RUN: ls %t.cache | count 4 | ||
| 14 | |||
| 15 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" | ||
| 16 | target triple = "x86_64-pc-windows-msvc" | ||
| 17 | |||
| 18 | define void @globalfunc() #0 { | ||
| 19 | entry: | ||
| 20 | ret void | ||
| 21 | } | ||
deps/lld/test/COFF/lto-opt-level.ll+6-6| ... | @@ -1,10 +1,10 @@ | ... | @@ -1,10 +1,10 @@ |
| 1 | ; RUN: llvm-as -o %t.obj %s | 1 | ; RUN: llvm-as -o %t.obj %s |
| 2 | ; RUN: lld-link /out:%t0.exe /entry:main /subsystem:console /opt:lldlto=0 /debug %t.obj | 2 | ; RUN: lld-link /out:%t0.exe /entry:main /subsystem:console /opt:lldlto=0 /lldmap:%t0.map %t.obj |
| 3 | ; RUN: llvm-nm %t0.exe | FileCheck --check-prefix=CHECK-O0 %s | 3 | ; RUN: FileCheck --check-prefix=CHECK-O0 %s < %t0.map |
| 4 | ; RUN: lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=2 /debug %t.obj | 4 | ; RUN: lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=2 /lldmap:%t2.map %t.obj |
| 5 | ; RUN: llvm-nm %t2.exe | FileCheck --check-prefix=CHECK-O2 %s | 5 | ; RUN: FileCheck --check-prefix=CHECK-O2 %s < %t2.map |
| 6 | ; RUN: lld-link /out:%t2a.exe /entry:main /subsystem:console /debug %t.obj | 6 | ; RUN: lld-link /out:%t2a.exe /entry:main /subsystem:console /lldmap:%t2a.map %t.obj |
| 7 | ; RUN: llvm-nm %t2a.exe | FileCheck --check-prefix=CHECK-O2 %s | 7 | ; RUN: FileCheck --check-prefix=CHECK-O2 %s < %t2a.map |
| 8 | 8 | ||
| 9 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" | 9 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" |
| 10 | target triple = "x86_64-pc-windows-msvc" | 10 | target triple = "x86_64-pc-windows-msvc" |
deps/lld/test/COFF/lto-reloc-model.ll created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | ; RUN: llvm-as -o %t %s | ||
| 2 | ; RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t | ||
| 3 | ; RUN: llvm-objdump -d %t.exe | FileCheck %s | ||
| 4 | |||
| 5 | target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" | ||
| 6 | target triple = "i686-pc-windows-msvc" | ||
| 7 | |||
| 8 | @foo = thread_local global i8 0 | ||
| 9 | |||
| 10 | module asm "__tls_index = 1" | ||
| 11 | module asm "__tls_array = 2" | ||
| 12 | |||
| 13 | define i8* @main() { | ||
| 14 | ; CHECK: movl 1, %eax | ||
| 15 | ; CHECK: movl %fs:2, %ecx | ||
| 16 | ; CHECK: movl (%ecx,%eax,4), %eax | ||
| 17 | ; CHECK: leal (%eax), %eax | ||
| 18 | ret i8* @foo | ||
| 19 | } | ||
deps/lld/test/COFF/lto.ll+15-1| ... | @@ -82,7 +82,21 @@ | ... | @@ -82,7 +82,21 @@ |
| 82 | ; TEXT-10: Disassembly of section .text: | 82 | ; TEXT-10: Disassembly of section .text: |
| 83 | ; TEXT-10-NEXT: .text: | 83 | ; TEXT-10-NEXT: .text: |
| 84 | ; TEXT-10-NEXT: retq | 84 | ; TEXT-10-NEXT: retq |
| 85 | ; TEXT-10-NEXT: nopw %cs:(%rax,%rax) | 85 | ; TEXT-10-NEXT: nop |
| 86 | ; TEXT-10-NEXT: nop | ||
| 87 | ; TEXT-10-NEXT: nop | ||
| 88 | ; TEXT-10-NEXT: nop | ||
| 89 | ; TEXT-10-NEXT: nop | ||
| 90 | ; TEXT-10-NEXT: nop | ||
| 91 | ; TEXT-10-NEXT: nop | ||
| 92 | ; TEXT-10-NEXT: nop | ||
| 93 | ; TEXT-10-NEXT: nop | ||
| 94 | ; TEXT-10-NEXT: nop | ||
| 95 | ; TEXT-10-NEXT: nop | ||
| 96 | ; TEXT-10-NEXT: nop | ||
| 97 | ; TEXT-10-NEXT: nop | ||
| 98 | ; TEXT-10-NEXT: nop | ||
| 99 | ; TEXT-10-NEXT: nop | ||
| 86 | ; TEXT-10-NEXT: retq | 100 | ; TEXT-10-NEXT: retq |
| 87 | ; TEXT-10-NEXT: int3 | 101 | ; TEXT-10-NEXT: int3 |
| 88 | ; TEXT-10-NEXT: int3 | 102 | ; TEXT-10-NEXT: int3 |
deps/lld/test/COFF/manifest.test+15-1| ... | @@ -57,10 +57,24 @@ DEPENDENCY: </dependentAssembly> | ... | @@ -57,10 +57,24 @@ DEPENDENCY: </dependentAssembly> |
| 57 | DEPENDENCY: </dependency> | 57 | DEPENDENCY: </dependency> |
| 58 | DEPENDENCY: </assembly> | 58 | DEPENDENCY: </assembly> |
| 59 | 59 | ||
| 60 | # RUN: lld-link /manifest /out:%t.exe /entry:main /manifestuac:no %t.obj | 60 | # RUN: lld-link /manifest /out:%t.exe /entry:main /manifestuac:no \ |
| 61 | # RUN: /manifestdependency:"foo='bar'" %t.obj | ||
| 61 | # RUN: FileCheck -check-prefix=NOUAC %s < %t.exe.manifest | 62 | # RUN: FileCheck -check-prefix=NOUAC %s < %t.exe.manifest |
| 62 | 63 | ||
| 63 | NOUAC: <?xml version="1.0" standalone="yes"?> | 64 | NOUAC: <?xml version="1.0" standalone="yes"?> |
| 64 | NOUAC: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" | 65 | NOUAC: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" |
| 65 | NOUAC: manifestVersion="1.0"> | 66 | NOUAC: manifestVersion="1.0"> |
| 67 | NOUAC: <dependency> | ||
| 68 | NOUAC: <dependentAssembly> | ||
| 69 | NOUAC: <assemblyIdentity foo='bar' /> | ||
| 70 | NOUAC: </dependentAssembly> | ||
| 71 | NOUAC: </dependency> | ||
| 66 | NOUAC: </assembly> | 72 | NOUAC: </assembly> |
| 73 | |||
| 74 | # RUN: lld-link /manifest /out:%t.exe /entry:main /manifestuac:no %t.obj | ||
| 75 | # RUN: FileCheck -check-prefix=NOUACNODEP %s < %t.exe.manifest | ||
| 76 | |||
| 77 | NOUACNODEP: <?xml version="1.0" standalone="yes"?> | ||
| 78 | NOUACNODEP: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" | ||
| 79 | NOUACNODEP: manifestVersion="1.0"> | ||
| 80 | NOUACNODEP: </assembly> |
deps/lld/test/COFF/manifestinput-error.test created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | # UNSUPPORTED: manifest_tool | ||
| 2 | # UNSUPPORTED: libxml2 | ||
| 3 | |||
| 4 | # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj | ||
| 5 | # RUN: not lld-link /out:%t.exe /entry:main \ | ||
| 6 | # RUN: /manifest:embed \ | ||
| 7 | # RUN: /manifestuac:"level='requireAdministrator'" \ | ||
| 8 | # RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj 2>&1 | FileCheck %s | ||
| 9 | |||
| 10 | # CHECK: error: unable to find mt.exe in PATH: No such file or directory | ||
deps/lld/test/COFF/manifestinput-nowarning.test created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | # UNSUPPORTED: libxml2 | ||
| 2 | # REQUIRES: manifest_tool | ||
| 3 | |||
| 4 | # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj | ||
| 5 | # RUN: lld-link /out:%t.exe /entry:main \ | ||
| 6 | # RUN: /manifest:embed \ | ||
| 7 | # RUN: /manifestuac:"level='requireAdministrator'" \ | ||
| 8 | # RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj | \ | ||
| 9 | # RUN:	 FileCheck -allow-empty %s | ||
| 10 | |||
| 11 | # CHECK-NOT: warning: error with internal manifest tool: no libxml2 | ||
deps/lld/test/COFF/manifestinput.test+2-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | # REQUIRES: win_mt | 1 | # REQUIRES: manifest_tool |
| 2 | 2 | ||
| 3 | # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj | 3 | # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj |
| 4 | # RUN: lld-link /out:%t.exe /entry:main \ | 4 | # RUN: lld-link /out:%t.exe /entry:main \ |
| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | TEST_EMBED: ResourceTableRVA: 0x1000 | 11 | TEST_EMBED: ResourceTableRVA: 0x1000 |
| 12 | TEST_EMBED-NEXT: ResourceTableSize: 0x298 | 12 | TEST_EMBED-NEXT: ResourceTableSize: 0x298 |
| 13 | TEST_EMBED-DAG: Resources [ | 13 | TEST_EMBED-DAG: Resources [ |
| 14 | TEST_EMBED-NEXT: Total Number of Resources: 1 | 14 | TEST_EMBED-NEXT: Total Number of Resources: 1 |
| 15 | TEST_EMBED-DAG: Number of String Entries: 0 | 15 | TEST_EMBED-DAG: Number of String Entries: 0 |
| 16 | TEST_EMBED-NEXT: Number of ID Entries: 1 | 16 | TEST_EMBED-NEXT: Number of ID Entries: 1 |
| 17 | TEST_EMBED-NEXT: Type: kRT_MANIFEST (ID 24) [ | 17 | TEST_EMBED-NEXT: Type: kRT_MANIFEST (ID 24) [ |
deps/lld/test/COFF/msvclto-archive.ll+3-3| ... | @@ -9,14 +9,14 @@ | ... | @@ -9,14 +9,14 @@ |
| 9 | ; RUN: mkdir -p %t.dir | 9 | ; RUN: mkdir -p %t.dir |
| 10 | ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t.dir/bitcode.obj %p/Inputs/msvclto.s | 10 | ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t.dir/bitcode.obj %p/Inputs/msvclto.s |
| 11 | ; RUN: lld-link %t-main1.a %t.dir/bitcode.obj /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ | 11 | ; RUN: lld-link %t-main1.a %t.dir/bitcode.obj /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ |
| 12 | ; RUN: /entry:main /verbose > %t.log || true | 12 | ; RUN: /entry:main /verbose 2> %t.log || true |
| 13 | ; RUN: FileCheck -check-prefix=BC %s < %t.log | 13 | ; RUN: FileCheck -check-prefix=BC %s < %t.log |
| 14 | ; BC-NOT: Creating a temporary archive for | 14 | ; BC-NOT: Creating a temporary archive for |
| 15 | 15 | ||
| 16 | ; RUN: rm -f %t-main2.a | 16 | ; RUN: rm -f %t-main2.a |
| 17 | ; RUN: llvm-ar cru %t-main2.a %t.dir/bitcode.obj | 17 | ; RUN: llvm-ar cru %t-main2.a %t.dir/bitcode.obj |
| 18 | ; RUN: lld-link %t.obj %t-main2.a /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ | 18 | ; RUN: lld-link %t.obj %t-main2.a /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ |
| 19 | ; RUN: /entry:main /verbose > %t.log || true | 19 | ; RUN: /entry:main /verbose 2> %t.log || true |
| 20 | ; RUN: FileCheck -check-prefix=OBJ %s < %t.log | 20 | ; RUN: FileCheck -check-prefix=OBJ %s < %t.log |
| 21 | ; OBJ-NOT: Creating a temporary archive | 21 | ; OBJ-NOT: Creating a temporary archive |
| 22 | 22 | ||
| ... | @@ -25,7 +25,7 @@ | ... | @@ -25,7 +25,7 @@ |
| 25 | ; RUN: rm -f %t-main3.a | 25 | ; RUN: rm -f %t-main3.a |
| 26 | ; RUN: llvm-ar cruT %t-main3.a %t.dir/bitcode.obj | 26 | ; RUN: llvm-ar cruT %t-main3.a %t.dir/bitcode.obj |
| 27 | ; RUN: lld-link %t.obj %t-main3.a /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ | 27 | ; RUN: lld-link %t.obj %t-main3.a /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ |
| 28 | ; RUN: /entry:main /verbose > %t.log || true | 28 | ; RUN: /entry:main /verbose 2> %t.log || true |
| 29 | ; RUN: FileCheck -check-prefix=THIN %s < %t.log | 29 | ; RUN: FileCheck -check-prefix=THIN %s < %t.log |
| 30 | ; THIN: Creating a temporary archive | 30 | ; THIN: Creating a temporary archive |
| 31 | 31 |
deps/lld/test/COFF/msvclto-order.ll+1-1| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | ; RUN: llc -filetype=obj %S/Inputs/msvclto-order-b.ll -o %T/msvclto-order-b.obj | 5 | ; RUN: llc -filetype=obj %S/Inputs/msvclto-order-b.ll -o %T/msvclto-order-b.obj |
| 6 | ; RUN: llvm-ar crs %T/msvclto-order-b.lib %T/msvclto-order-b.obj | 6 | ; RUN: llvm-ar crs %T/msvclto-order-b.lib %T/msvclto-order-b.obj |
| 7 | ; RUN: lld-link /verbose /msvclto /out:%t.exe /entry:main %t.obj \ | 7 | ; RUN: lld-link /verbose /msvclto /out:%t.exe /entry:main %t.obj \ |
| 8 | ; RUN: %T/msvclto-order-a.lib %T/msvclto-order-b.lib > %t.log || true | 8 | ; RUN: %T/msvclto-order-a.lib %T/msvclto-order-b.lib 2> %t.log || true |
| 9 | ; RUN: FileCheck %s < %t.log | 9 | ; RUN: FileCheck %s < %t.log |
| 10 | 10 | ||
| 11 | ; CHECK: : link.exe | 11 | ; CHECK: : link.exe |
deps/lld/test/COFF/msvclto.ll+1-1| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 | ; RUN: mkdir -p %t.dir | 3 | ; RUN: mkdir -p %t.dir |
| 4 | ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t.dir/bitcode.obj %p/Inputs/msvclto.s | 4 | ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t.dir/bitcode.obj %p/Inputs/msvclto.s |
| 5 | ; RUN: lld-link %t.obj %t.dir/bitcode.obj /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ | 5 | ; RUN: lld-link %t.obj %t.dir/bitcode.obj /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ |
| 6 | ; RUN: /entry:main /verbose > %t.log || true | 6 | ; RUN: /entry:main /verbose 2> %t.log || true |
| 7 | ; RUN: FileCheck %s < %t.log | 7 | ; RUN: FileCheck %s < %t.log |
| 8 | 8 | ||
| 9 | ; CHECK: /opt:icf /entry:main | 9 | ; CHECK: /opt:icf /entry:main |
deps/lld/test/COFF/nodefaultlib.test+3-3| ... | @@ -19,9 +19,9 @@ | ... | @@ -19,9 +19,9 @@ |
| 19 | # RUN: /nodefaultlib:std64.lib >& %t.log || true | 19 | # RUN: /nodefaultlib:std64.lib >& %t.log || true |
| 20 | # RUN: FileCheck -check-prefix=CHECK3 %s < %t.log | 20 | # RUN: FileCheck -check-prefix=CHECK3 %s < %t.log |
| 21 | 21 | ||
| 22 | CHECK1: hello64.obj: {{[Nn]}}o such file or directory | 22 | CHECK1: error: could not open hello64.obj: {{[Nn]}}o such file or directory |
| 23 | CHECK2: hello64: {{[Nn]}}o such file or directory | 23 | CHECK2: error: could not open hello64: {{[Nn]}}o such file or directory |
| 24 | CHECK3: hello64.obj: undefined symbol: MessageBoxA | 24 | CHECK3: error: {{.*}}hello64.obj: undefined symbol: MessageBoxA |
| 25 | 25 | ||
| 26 | # RUN: lld-link /libpath:%T /out:%t.exe /entry:main \ | 26 | # RUN: lld-link /libpath:%T /out:%t.exe /entry:main \ |
| 27 | # RUN: /subsystem:console hello64.obj /defaultlib:std64.lib | 27 | # RUN: /subsystem:console hello64.obj /defaultlib:std64.lib |
deps/lld/test/COFF/nopdb.test deleted-14| ... | @@ -1,14 +0,0 @@ | ||
| 1 | # Check that /debug creates %t.pdb. | ||
| 2 | # RUN: rm -f %t.pdb | ||
| 3 | # RUN: lld-link /debug /entry:main /out:%t.exe %p/Inputs/ret42.obj | ||
| 4 | # RUN: ls %t.pdb | ||
| 5 | |||
| 6 | # Check that /debug /nopdb does not create %t.pdb. | ||
| 7 | # RUN: rm -f %t.pdb | ||
| 8 | # RUN: lld-link /debug /nopdb /entry:main /out:%t.exe %p/Inputs/ret42.obj | ||
| 9 | # RUN: not ls %t.pdb | ||
| 10 | |||
| 11 | # Check that /debug /nopdb /pdb:%t.pdb does not create %t.pdb. | ||
| 12 | # RUN: rm -f %t.pdb | ||
| 13 | # RUN: lld-link /debug /nopdb /pdb:%t.pdb /entry:main /out:%t.exe %p/Inputs/ret42.obj | ||
| 14 | # RUN: not ls %t.pdb | ||
deps/lld/test/COFF/options.test+7-1| ... | @@ -2,7 +2,13 @@ | ... | @@ -2,7 +2,13 @@ |
| 2 | 2 | ||
| 3 | # RUN: lld-link /out:%t.exe /entry:main %t.obj | 3 | # RUN: lld-link /out:%t.exe /entry:main %t.obj |
| 4 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BIND %s | 4 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BIND %s |
| 5 | BIND: IMAGE_DLL_CHARACTERISTICS_NO_BIND | 5 | # RUN: lld-link /allowbind /out:%t.exe /entry:main %t.obj |
| 6 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BIND %s | ||
| 7 | BIND-NOT: IMAGE_DLL_CHARACTERISTICS_NO_BIND | ||
| 8 | |||
| 9 | # RUN: lld-link /allowbind:no /out:%t.exe /entry:main %t.obj | ||
| 10 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOBIND %s | ||
| 11 | NOBIND: IMAGE_DLL_CHARACTERISTICS_NO_BIND | ||
| 6 | 12 | ||
| 7 | # RUN: lld-link /out:%t.exe /entry:main %t.obj | 13 | # RUN: lld-link /out:%t.exe /entry:main %t.obj |
| 8 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ISO %s | 14 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ISO %s |
deps/lld/test/COFF/pdata-arm64.yaml created+87| ... | @@ -0,0 +1,87 @@ | ||
| 1 | # RUN: yaml2obj < %s > %t.obj | ||
| 2 | # | ||
| 3 | # RUN: lld-link /out:%t.exe /entry:func1 /subsystem:console %t.obj | ||
| 4 | # RUN: llvm-objdump -s -section=.pdata %t.exe | FileCheck -check-prefix=PDATA %s | ||
| 5 | |||
| 6 | # PDATA: 00200000 2500a100 24200000 31002201 | ||
| 7 | |||
| 8 | --- !COFF | ||
| 9 | header: | ||
| 10 | Machine: IMAGE_FILE_MACHINE_ARM64 | ||
| 11 | Characteristics: [ ] | ||
| 12 | sections: | ||
| 13 | - Name: .text | ||
| 14 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 15 | Alignment: 4 | ||
| 16 | SectionData: ff4300d1f37b00a9f303012a00000094e003132a00000094f37b40a9ff430091c0035fd6f353bea9fe0b00f9f303012af403022a00000094e003132a00000094e003142a00000094fe0b40f9f353c2a8c0035fd6c0035fd6 | ||
| 17 | Relocations: | ||
| 18 | - VirtualAddress: 12 | ||
| 19 | SymbolName: func3 | ||
| 20 | Type: IMAGE_REL_ARM64_BRANCH26 | ||
| 21 | - VirtualAddress: 20 | ||
| 22 | SymbolName: func3 | ||
| 23 | Type: IMAGE_REL_ARM64_BRANCH26 | ||
| 24 | - VirtualAddress: 52 | ||
| 25 | SymbolName: func3 | ||
| 26 | Type: IMAGE_REL_ARM64_BRANCH26 | ||
| 27 | - VirtualAddress: 60 | ||
| 28 | SymbolName: func3 | ||
| 29 | Type: IMAGE_REL_ARM64_BRANCH26 | ||
| 30 | - VirtualAddress: 68 | ||
| 31 | SymbolName: func3 | ||
| 32 | Type: IMAGE_REL_ARM64_BRANCH26 | ||
| 33 | - Name: .pdata | ||
| 34 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | ||
| 35 | Alignment: 4 | ||
| 36 | SectionData: 0000000031002201000000002500a100 | ||
| 37 | Relocations: | ||
| 38 | - VirtualAddress: 0 | ||
| 39 | SymbolName: func2 | ||
| 40 | Type: IMAGE_REL_ARM64_ADDR32NB | ||
| 41 | - VirtualAddress: 8 | ||
| 42 | SymbolName: func1 | ||
| 43 | Type: IMAGE_REL_ARM64_ADDR32NB | ||
| 44 | symbols: | ||
| 45 | - Name: .text | ||
| 46 | Value: 0 | ||
| 47 | SectionNumber: 1 | ||
| 48 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 49 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 50 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 51 | SectionDefinition: | ||
| 52 | Length: 57 | ||
| 53 | NumberOfRelocations: 0 | ||
| 54 | NumberOfLinenumbers: 0 | ||
| 55 | CheckSum: 0 | ||
| 56 | Number: 1 | ||
| 57 | - Name: .pdata | ||
| 58 | Value: 0 | ||
| 59 | SectionNumber: 2 | ||
| 60 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 61 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 62 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 63 | SectionDefinition: | ||
| 64 | Length: 16 | ||
| 65 | NumberOfRelocations: 2 | ||
| 66 | NumberOfLinenumbers: 0 | ||
| 67 | CheckSum: 0 | ||
| 68 | Number: 2 | ||
| 69 | - Name: func1 | ||
| 70 | Value: 0 | ||
| 71 | SectionNumber: 1 | ||
| 72 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 73 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 74 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 75 | - Name: func2 | ||
| 76 | Value: 36 | ||
| 77 | SectionNumber: 1 | ||
| 78 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 79 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 80 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 81 | - Name: func3 | ||
| 82 | Value: 84 | ||
| 83 | SectionNumber: 1 | ||
| 84 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 85 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 86 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 87 | ... | ||
deps/lld/test/COFF/pdb-comdat.test+28-15| ... | @@ -25,8 +25,8 @@ pdb_comdat_main.obj should be included in the PDB. | ... | @@ -25,8 +25,8 @@ pdb_comdat_main.obj should be included in the PDB. |
| 25 | RUN: rm -rf %t && mkdir -p %t && cd %t | 25 | RUN: rm -rf %t && mkdir -p %t && cd %t |
| 26 | RUN: yaml2obj %S/Inputs/pdb_comdat_main.yaml -o pdb_comdat_main.obj | 26 | RUN: yaml2obj %S/Inputs/pdb_comdat_main.yaml -o pdb_comdat_main.obj |
| 27 | RUN: yaml2obj %S/Inputs/pdb_comdat_bar.yaml -o pdb_comdat_bar.obj | 27 | RUN: yaml2obj %S/Inputs/pdb_comdat_bar.yaml -o pdb_comdat_bar.obj |
| 28 | RUN: lld-link pdb_comdat_main.obj pdb_comdat_bar.obj -out:t.exe -debug -pdb:t.pdb -nodefaultlib -entry:main | 28 | RUN: lld-link pdb_comdat_main.obj pdb_comdat_bar.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main |
| 29 | RUN: llvm-pdbutil dump -l -symbols t.pdb | FileCheck %s | 29 | RUN: llvm-pdbutil dump -l -symbols -globals %t.pdb | FileCheck %s |
| 30 | 30 | ||
| 31 | CHECK: Lines | 31 | CHECK: Lines |
| 32 | CHECK: ============================================================ | 32 | CHECK: ============================================================ |
| ... | @@ -38,6 +38,20 @@ CHECK: c:\src\llvm-project\build\pdb_comdat_bar.c (MD5: 365279DB4FCBEDD721 | ... | @@ -38,6 +38,20 @@ CHECK: c:\src\llvm-project\build\pdb_comdat_bar.c (MD5: 365279DB4FCBEDD721 |
| 38 | CHECK-NOT: c:\src\llvm-project\build\foo.h | 38 | CHECK-NOT: c:\src\llvm-project\build\foo.h |
| 39 | CHECK-LABEL: Mod 0002 | `* Linker *`: | 39 | CHECK-LABEL: Mod 0002 | `* Linker *`: |
| 40 | 40 | ||
| 41 | CHECK-LABEL: Global Symbols | ||
| 42 | CHECK-NEXT: ============================================================ | ||
| 43 | CHECK-NEXT: Records | ||
| 44 | CHECK-NEXT: 84 | S_PROCREF [size = 20] `main` | ||
| 45 | CHECK-NEXT: module = 1, sum name = 0, offset = 120 | ||
| 46 | CHECK-NEXT: 128 | S_PROCREF [size = 20] `foo` | ||
| 47 | CHECK-NEXT: module = 1, sum name = 0, offset = 208 | ||
| 48 | CHECK-NEXT: 148 | S_PROCREF [size = 20] `bar` | ||
| 49 | CHECK-NEXT: module = 2, sum name = 0, offset = 120 | ||
| 50 | CHECK-NEXT: 104 | S_GDATA32 [size = 24] `global` | ||
| 51 | CHECK-NEXT: type = 0x0074 (int), addr = 0000:0000 | ||
| 52 | CHECK-NEXT: 168 | S_GDATA32 [size = 24] `global` | ||
| 53 | CHECK-NEXT: type = 0x0074 (int), addr = 0000:0000 | ||
| 54 | |||
| 41 | CHECK: Symbols | 55 | CHECK: Symbols |
| 42 | CHECK: ============================================================ | 56 | CHECK: ============================================================ |
| 43 | CHECK-LABEL: Mod 0000 | `{{.*}}pdb_comdat_main.obj`: | 57 | CHECK-LABEL: Mod 0000 | `{{.*}}pdb_comdat_main.obj`: |
| ... | @@ -46,7 +60,7 @@ CHECK: 60 | S_COMPILE3 [size = 60] | ... | @@ -46,7 +60,7 @@ CHECK: 60 | S_COMPILE3 [size = 60] |
| 46 | CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c | 60 | CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c |
| 47 | CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 | 61 | CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 |
| 48 | CHECK: flags = security checks | hot patchable | 62 | CHECK: flags = security checks | hot patchable |
| 49 | CHECK: 120 | S_GPROC32_ID [size = 44] `main` | 63 | CHECK: 120 | S_GPROC32 [size = 44] `main` |
| 50 | CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 24 | 64 | CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 24 |
| 51 | CHECK: debug start = 4, debug end = 19, flags = none | 65 | CHECK: debug start = 4, debug end = 19, flags = none |
| 52 | CHECK: 164 | S_FRAMEPROC [size = 32] | 66 | CHECK: 164 | S_FRAMEPROC [size = 32] |
| ... | @@ -54,24 +68,22 @@ CHECK: size = 40, padding size = 0, offset to padding = 0 | ... | @@ -54,24 +68,22 @@ CHECK: size = 40, padding size = 0, offset to padding = 0 |
| 54 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 | 68 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 |
| 55 | CHECK: flags = has async eh | opt speed | 69 | CHECK: flags = has async eh | opt speed |
| 56 | CHECK: 196 | S_END [size = 4] | 70 | CHECK: 196 | S_END [size = 4] |
| 57 | CHECK: 200 | S_GDATA32 [size = 24] `global` | 71 | CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `0x100A` |
| 58 | CHECK: type = 0x0074 (int), addr = 0000:0000 | 72 | CHECK: 208 | S_GPROC32 [size = 44] `foo` |
| 59 | CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100A` | 73 | CHECK: parent = 0, end = 284, addr = 0002:0032, code size = 15 |
| 60 | CHECK: 232 | S_GPROC32_ID [size = 44] `foo` | ||
| 61 | CHECK: parent = 0, end = 308, addr = 0002:0032, code size = 15 | ||
| 62 | CHECK: debug start = 0, debug end = 14, flags = none | 74 | CHECK: debug start = 0, debug end = 14, flags = none |
| 63 | CHECK: 276 | S_FRAMEPROC [size = 32] | 75 | CHECK: 252 | S_FRAMEPROC [size = 32] |
| 64 | CHECK: size = 0, padding size = 0, offset to padding = 0 | 76 | CHECK: size = 0, padding size = 0, offset to padding = 0 |
| 65 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 | 77 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 |
| 66 | CHECK: flags = marked inline | has async eh | opt speed | 78 | CHECK: flags = marked inline | has async eh | opt speed |
| 67 | CHECK: 308 | S_END [size = 4] | 79 | CHECK: 284 | S_END [size = 4] |
| 68 | CHECK-LABEL: Mod 0001 | `{{.*}}pdb_comdat_bar.obj`: | 80 | CHECK-LABEL: Mod 0001 | `{{.*}}pdb_comdat_bar.obj`: |
| 69 | CHECK: 4 | S_OBJNAME [size = 56] sig=0, `C:\src\llvm-project\build\pdb_comdat_bar.obj` | 81 | CHECK: 4 | S_OBJNAME [size = 56] sig=0, `C:\src\llvm-project\build\pdb_comdat_bar.obj` |
| 70 | CHECK: 60 | S_COMPILE3 [size = 60] | 82 | CHECK: 60 | S_COMPILE3 [size = 60] |
| 71 | CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c | 83 | CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c |
| 72 | CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 | 84 | CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 |
| 73 | CHECK: flags = security checks | hot patchable | 85 | CHECK: flags = security checks | hot patchable |
| 74 | CHECK: 120 | S_GPROC32_ID [size = 44] `bar` | 86 | CHECK: 120 | S_GPROC32 [size = 44] `bar` |
| 75 | CHECK: parent = 0, end = 196, addr = 0002:0048, code size = 14 | 87 | CHECK: parent = 0, end = 196, addr = 0002:0048, code size = 14 |
| 76 | CHECK: debug start = 4, debug end = 9, flags = none | 88 | CHECK: debug start = 4, debug end = 9, flags = none |
| 77 | CHECK: 164 | S_FRAMEPROC [size = 32] | 89 | CHECK: 164 | S_FRAMEPROC [size = 32] |
| ... | @@ -79,10 +91,8 @@ CHECK: size = 40, padding size = 0, offset to padding = 0 | ... | @@ -79,10 +91,8 @@ CHECK: size = 40, padding size = 0, offset to padding = 0 |
| 79 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 | 91 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 |
| 80 | CHECK: flags = has async eh | opt speed | 92 | CHECK: flags = has async eh | opt speed |
| 81 | CHECK: 196 | S_END [size = 4] | 93 | CHECK: 196 | S_END [size = 4] |
| 82 | CHECK: 200 | S_GDATA32 [size = 24] `global` | 94 | CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `0x100D` |
| 83 | CHECK: type = 0x0074 (int), addr = 0000:0000 | 95 | CHECK-NOT: S_GPROC32 {{.*}} `foo` |
| 84 | CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100D` | ||
| 85 | CHECK-NOT: S_GPROC32_ID {{.*}} `foo` | ||
| 86 | CHECK-LABEL: Mod 0002 | `* Linker *`: | 96 | CHECK-LABEL: Mod 0002 | `* Linker *`: |
| 87 | 97 | ||
| 88 | Reorder the object files and verify that the other table is selected. | 98 | Reorder the object files and verify that the other table is selected. |
| ... | @@ -97,3 +107,6 @@ REORDER-LABEL: Mod 0001 | `{{.*}}pdb_comdat_main.obj`: | ... | @@ -97,3 +107,6 @@ REORDER-LABEL: Mod 0001 | `{{.*}}pdb_comdat_main.obj`: |
| 97 | REORDER: c:\src\llvm-project\build\pdb_comdat_main.c | 107 | REORDER: c:\src\llvm-project\build\pdb_comdat_main.c |
| 98 | REORDER-NOT: c:\src\llvm-project\build\foo.h | 108 | REORDER-NOT: c:\src\llvm-project\build\foo.h |
| 99 | REORDER-LABEL: Mod 0002 | `* Linker *`: | 109 | REORDER-LABEL: Mod 0002 | `* Linker *`: |
| 110 | |||
| 111 | Make sure that we don't crash on non-prevailing debug sections if -debug is not enabled. | ||
| 112 | RUN: lld-link pdb_comdat_main.obj pdb_comdat_bar.obj -out:%t.exe -nodefaultlib -entry:main |
deps/lld/test/COFF/pdb-diff.test+10-7| ... | @@ -4,8 +4,11 @@ as the "baseline" for us to measure against. Then we link the same object | ... | @@ -4,8 +4,11 @@ as the "baseline" for us to measure against. Then we link the same object |
| 4 | file with LLD and compare the two PDBs. Since the baseline object file and | 4 | file with LLD and compare the two PDBs. Since the baseline object file and |
| 5 | PDB are already checked in, we just run LLD on the object file. | 5 | PDB are already checked in, we just run LLD on the object file. |
| 6 | 6 | ||
| 7 | RUN: lld-link /debug /pdb:%T/pdb-diff-lld.pdb /nodefaultlib /entry:main %S/Inputs/pdb-diff.obj | 7 | RUN: rm -f %T/pdb-diff-lld.pdb %T/pdb-diff-lld.exe |
| 8 | RUN: llvm-pdbutil diff -result -values=false -left-bin-root=%S -right-bin-root=D:/src/llvm-mono/lld/test/COFF/ %T/pdb-diff-lld.pdb %S/Inputs/pdb-diff-cl.pdb | FileCheck %s | 8 | RUN: lld-link /debug /pdb:%T/pdb-diff-lld.pdb /out:%T/pdb-diff-lld.exe /nodefaultlib \ |
| 9 | RUN: /entry:main %S/Inputs/pdb-diff.obj | ||
| 10 | RUN: llvm-pdbutil diff -result -values=false -left-bin-root=%S -right-bin-root=D:/src/llvm-mono/lld/test/COFF/ \ | ||
| 11 | RUN: %T/pdb-diff-lld.pdb %S/Inputs/pdb-diff-cl.pdb | FileCheck %s | ||
| 9 | 12 | ||
| 10 | CHECK: ---------------------- | 13 | CHECK: ---------------------- |
| 11 | CHECK-NEXT: | MSF Super Block | | 14 | CHECK-NEXT: | MSF Super Block | |
| ... | @@ -25,7 +28,7 @@ CHECK-NEXT: | Stream Directory | | ... | @@ -25,7 +28,7 @@ CHECK-NEXT: | Stream Directory | |
| 25 | CHECK-NEXT: |------------------------------+---| | 28 | CHECK-NEXT: |------------------------------+---| |
| 26 | CHECK-NEXT: | File | | | 29 | CHECK-NEXT: | File | | |
| 27 | CHECK-NEXT: |------------------------------+---| | 30 | CHECK-NEXT: |------------------------------+---| |
| 28 | CHECK-NEXT: | Stream Count | D | | 31 | CHECK-NEXT: | Stream Count | I | |
| 29 | CHECK-NEXT: |------------------------------+---| | 32 | CHECK-NEXT: |------------------------------+---| |
| 30 | CHECK-NEXT: | Old MSF Directory | I | | 33 | CHECK-NEXT: | Old MSF Directory | I | |
| 31 | CHECK-NEXT: |------------------------------+---| | 34 | CHECK-NEXT: |------------------------------+---| |
| ... | @@ -55,9 +58,9 @@ CHECK-NEXT: | IPI Hash | {{[EI]}} | | ... | @@ -55,9 +58,9 @@ CHECK-NEXT: | IPI Hash | {{[EI]}} | |
| 55 | CHECK-NEXT: |------------------------------+---| | 58 | CHECK-NEXT: |------------------------------+---| |
| 56 | CHECK-NEXT: | Public Symbol Hash | {{[EI]}} | | 59 | CHECK-NEXT: | Public Symbol Hash | {{[EI]}} | |
| 57 | CHECK-NEXT: |------------------------------+---| | 60 | CHECK-NEXT: |------------------------------+---| |
| 58 | CHECK-NEXT: | Public Symbol Records | {{[EI]}} | | 61 | CHECK-NEXT: | Global Symbol Hash | {{[EI]}} | |
| 59 | CHECK-NEXT: |------------------------------+---| | 62 | CHECK-NEXT: |------------------------------+---| |
| 60 | CHECK-NEXT: | Global Symbol Hash | D | | 63 | CHECK-NEXT: | Symbol Records | {{[EI]}} | |
| 61 | CHECK-NEXT: |------------------------------+---| | 64 | CHECK-NEXT: |------------------------------+---| |
| 62 | CHECK-NEXT: ------------------------------------ | 65 | CHECK-NEXT: ------------------------------------ |
| 63 | CHECK-NEXT: | String Table | | 66 | CHECK-NEXT: | String Table | |
| ... | @@ -152,7 +155,7 @@ CHECK-NEXT: | DBG (NewFPO) | {{[EI]}} | | ... | @@ -152,7 +155,7 @@ CHECK-NEXT: | DBG (NewFPO) | {{[EI]}} | |
| 152 | CHECK-NEXT: |----------------------------------------+---| | 155 | CHECK-NEXT: |----------------------------------------+---| |
| 153 | CHECK-NEXT: | DBG (SectionHdrOrig) | I | | 156 | CHECK-NEXT: | DBG (SectionHdrOrig) | I | |
| 154 | CHECK-NEXT: |----------------------------------------+---| | 157 | CHECK-NEXT: |----------------------------------------+---| |
| 155 | CHECK-NEXT: | Globals Stream | D | | 158 | CHECK-NEXT: | Globals Stream | {{[EI]}} | |
| 156 | CHECK-NEXT: |----------------------------------------+---| | 159 | CHECK-NEXT: |----------------------------------------+---| |
| 157 | CHECK-NEXT: | Publics Stream | {{[EI]}} | | 160 | CHECK-NEXT: | Publics Stream | {{[EI]}} | |
| 158 | CHECK-NEXT: |----------------------------------------+---| | 161 | CHECK-NEXT: |----------------------------------------+---| |
| ... | @@ -186,7 +189,7 @@ CHECK-NEXT: | - Pdb File Path Index | I | | ... | @@ -186,7 +189,7 @@ CHECK-NEXT: | - Pdb File Path Index | I | |
| 186 | CHECK-NEXT: |----------------------------------------+---| | 189 | CHECK-NEXT: |----------------------------------------+---| |
| 187 | CHECK-NEXT: | - Source File Name Index | I | | 190 | CHECK-NEXT: | - Source File Name Index | I | |
| 188 | CHECK-NEXT: |----------------------------------------+---| | 191 | CHECK-NEXT: |----------------------------------------+---| |
| 189 | CHECK-NEXT: | - Symbol Byte Size | D | | 192 | CHECK-NEXT: | - Symbol Byte Size | |
| 190 | CHECK-NEXT: |----------------------------------------+---| | 193 | CHECK-NEXT: |----------------------------------------+---| |
| 191 | CHECK-NEXT: | Module "* Linker *" | | 194 | CHECK-NEXT: | Module "* Linker *" | |
| 192 | CHECK-NEXT: |----------------------------------------+---| | 195 | CHECK-NEXT: |----------------------------------------+---| |
deps/lld/test/COFF/pdb-global-gc.yaml+13-9| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | # RUN: yaml2obj %s -o %t.obj | 1 | # RUN: yaml2obj %s -o %t.obj |
| 2 | # RUN: llvm-mc %S/Inputs/pdb-global-gc.s -triple x86_64-windows-msvc -filetype=obj -o %t2.obj | 2 | # RUN: llvm-mc %S/Inputs/pdb-global-gc.s -triple x86_64-windows-msvc -filetype=obj -o %t2.obj |
| 3 | # RUN: lld-link %t.obj %t2.obj -debug -entry:main \ | 3 | # RUN: lld-link %t.obj %t2.obj -debug -entry:main \ |
| 4 | # RUN: -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb -verbose | 4 | # RUN: -nodefaultlib -opt:ref -out:%t.exe -pdb:%t.pdb -verbose |
| 5 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | 5 | # RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s |
| 6 | 6 | ||
| 7 | # This tests the case where an __imp_ chunk is discarded by linker GC. The debug | 7 | # This tests the case where an __imp_ chunk is discarded by linker GC. The debug |
| 8 | # info may refer to the __imp_ symbol still. | 8 | # info may refer to the __imp_ symbol still. |
| ... | @@ -12,13 +12,17 @@ | ... | @@ -12,13 +12,17 @@ |
| 12 | # int discarded() { return __wc_mb_cur; } | 12 | # int discarded() { return __wc_mb_cur; } |
| 13 | # int main() { return g2; } | 13 | # int main() { return g2; } |
| 14 | 14 | ||
| 15 | # CHECK: Symbols | 15 | # CHECK: Global Symbols |
| 16 | # CHECK: ============================================================ | 16 | # CHECK-NEXT: ============================================================ |
| 17 | # CHECK: Mod 0000 | `{{.*}}pdb-global-gc.yaml.tmp.obj`: | 17 | # CHECK-NEXT: Records |
| 18 | # CHECK: 4 | S_GDATA32 [size = 28] `__wc_mb_cur` | 18 | # CHECK-NEXT: 20 | S_GDATA32 [size = 28] `__wc_mb_cur` |
| 19 | # CHECK-NEXT: type = 0x0070 (char), addr = 0000:0000 | 19 | # CHECK-NEXT: type = 0x0070 (char), addr = 0000:0000 |
| 20 | # CHECK: Mod 0001 | `{{.*}}pdb-global-gc.yaml.tmp2.obj`: | 20 | |
| 21 | # CHECK: Mod 0002 | `* Linker *`: | 21 | # CHECK: Symbols |
| 22 | # CHECK: ============================================================ | ||
| 23 | # CHECK-NEXT: Mod 0000 | `{{.*}}pdb-global-gc.yaml.tmp.obj`: | ||
| 24 | # CHECK-NEXT: Mod 0001 | `{{.*}}pdb-global-gc.yaml.tmp2.obj`: | ||
| 25 | # CHECK-NEXT: Mod 0002 | `* Linker *`: | ||
| 22 | 26 | ||
| 23 | --- !COFF | 27 | --- !COFF |
| 24 | header: | 28 | header: |
deps/lld/test/COFF/pdb-global-hashes.test created+93| ... | @@ -0,0 +1,93 @@ | ||
| 1 | RUN: yaml2obj %p/Inputs/pdb-hashes-1.yaml > %t.1.obj | ||
| 2 | RUN: yaml2obj %p/Inputs/pdb-hashes-2.yaml > %t.2.obj | ||
| 3 | RUN: yaml2obj %p/Inputs/pdb-hashes-2-missing.yaml > %t.2.missing.obj | ||
| 4 | RUN: lld-link /debug %t.1.obj %t.2.obj /entry:main /nodefaultlib /PDB:%t.nohash.pdb | ||
| 5 | RUN: lld-link /debug:ghash %t.1.obj %t.2.obj /entry:main /nodefaultlib /PDB:%t.hash.pdb | ||
| 6 | RUN: lld-link /debug:ghash %t.1.obj %t.2.missing.obj /entry:main /nodefaultlib /PDB:%t.mixed.pdb | ||
| 7 | RUN: llvm-pdbutil dump -types -ids %t.nohash.pdb | FileCheck %s | ||
| 8 | RUN: llvm-pdbutil dump -types -ids %t.hash.pdb | FileCheck %s | ||
| 9 | RUN: llvm-pdbutil dump -types -ids %t.mixed.pdb | FileCheck %s | ||
| 10 | |||
| 11 | ; These object files were generated via the following inputs and commands: | ||
| 12 | ; ---------------------------------------------- | ||
| 13 | ; // obj.h | ||
| 14 | ; namespace NS { | ||
| 15 | ; struct Foo { | ||
| 16 | ; explicit Foo(int x) : X(x) {} | ||
| 17 | ; int X; | ||
| 18 | ; }; | ||
| 19 | ; | ||
| 20 | ; int func(const Foo &f); | ||
| 21 | ; } | ||
| 22 | ; ---------------------------------------------- | ||
| 23 | ; // obj1.cpp | ||
| 24 | ; #include "obj.h" | ||
| 25 | ; | ||
| 26 | ; int main(int argc, char **argv) { | ||
| 27 | ; NS::Foo f(argc); | ||
| 28 | ; return NS::func(f); | ||
| 29 | ; } | ||
| 30 | ; ---------------------------------------------- | ||
| 31 | ; // obj2.cpp | ||
| 32 | ; #include "obj.h" | ||
| 33 | ; | ||
| 34 | ; int NS::func(const Foo &f) { | ||
| 35 | ; return 2 * f.X; | ||
| 36 | ; } | ||
| 37 | ; ---------------------------------------------- | ||
| 38 | ; $ clang-cl /Z7 /GS- obj1.cpp /c /o obj1.obj | ||
| 39 | ; $ clang-cl /Z7 /GS- obj2.cpp /c /o obj2.obj | ||
| 40 | |||
| 41 | CHECK: Types (TPI Stream) | ||
| 42 | CHECK-NEXT: ============================================================ | ||
| 43 | CHECK-NEXT: Showing 13 records | ||
| 44 | CHECK-NEXT: 0x1000 | LF_POINTER [size = 12] | ||
| 45 | CHECK-NEXT: referent = 0x0470 (char*), mode = pointer, opts = None, kind = ptr32 | ||
| 46 | CHECK-NEXT: 0x1001 | LF_ARGLIST [size = 16] | ||
| 47 | CHECK-NEXT: 0x0074 (int): `int` | ||
| 48 | CHECK-NEXT: 0x1000: `char**` | ||
| 49 | CHECK-NEXT: 0x1002 | LF_PROCEDURE [size = 16] | ||
| 50 | CHECK-NEXT: return type = 0x0074 (int), # args = 2, param list = 0x1001 | ||
| 51 | CHECK-NEXT: calling conv = cdecl, options = None | ||
| 52 | CHECK-NEXT: 0x1003 | LF_STRUCTURE [size = 44] `NS::Foo` | ||
| 53 | CHECK-NEXT: unique name: `.?AUFoo@NS@@` | ||
| 54 | CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: <no type> | ||
| 55 | CHECK-NEXT: options: forward ref | has unique name | ||
| 56 | CHECK-NEXT: 0x1004 | LF_POINTER [size = 12] | ||
| 57 | CHECK-NEXT: referent = 0x1003, mode = pointer, opts = None, kind = ptr32 | ||
| 58 | CHECK-NEXT: 0x1005 | LF_ARGLIST [size = 12] | ||
| 59 | CHECK-NEXT: 0x0074 (int): `int` | ||
| 60 | CHECK-NEXT: 0x1006 | LF_MFUNCTION [size = 28] | ||
| 61 | CHECK-NEXT: return type = 0x0003 (void), # args = 1, param list = 0x1005 | ||
| 62 | CHECK-NEXT: class type = 0x1003, this type = 0x1004, this adjust = 0 | ||
| 63 | CHECK-NEXT: calling conv = thiscall, options = None | ||
| 64 | CHECK-NEXT: 0x1007 | LF_FIELDLIST [size = 28] | ||
| 65 | CHECK-NEXT: - LF_MEMBER [name = `X`, Type = 0x0074 (int), offset = 0, attrs = public] | ||
| 66 | CHECK-NEXT: - LF_ONEMETHOD [name = `Foo`] | ||
| 67 | CHECK-NEXT: type = 0x1006, vftable offset = -1, attrs = public | ||
| 68 | CHECK-NEXT: 0x1008 | LF_STRUCTURE [size = 44] `NS::Foo` | ||
| 69 | CHECK-NEXT: unique name: `.?AUFoo@NS@@` | ||
| 70 | CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1007 | ||
| 71 | CHECK-NEXT: options: has unique name | ||
| 72 | CHECK-NEXT: 0x1009 | LF_MODIFIER [size = 12] | ||
| 73 | CHECK-NEXT: referent = 0x1003, modifiers = const | ||
| 74 | CHECK-NEXT: 0x100A | LF_POINTER [size = 12] | ||
| 75 | CHECK-NEXT: referent = 0x1009, mode = ref, opts = None, kind = ptr32 | ||
| 76 | CHECK-NEXT: 0x100B | LF_ARGLIST [size = 12] | ||
| 77 | CHECK-NEXT: 0x100A: `const NS::Foo&` | ||
| 78 | CHECK-NEXT: 0x100C | LF_PROCEDURE [size = 16] | ||
| 79 | CHECK-NEXT: return type = 0x0074 (int), # args = 1, param list = 0x100B | ||
| 80 | CHECK-NEXT: calling conv = cdecl, options = None | ||
| 81 | CHECK: Types (IPI Stream) | ||
| 82 | CHECK-NEXT: ============================================================ | ||
| 83 | CHECK-NEXT: Showing 6 records | ||
| 84 | CHECK-NEXT: 0x1000 | LF_FUNC_ID [size = 20] | ||
| 85 | CHECK-NEXT: name = main, type = 0x1002, parent scope = <no type> | ||
| 86 | CHECK-NEXT: 0x1001 | LF_STRING_ID [size = 48] ID: <no type>, String: D:\src\llvmbuild\clang\Debug\x86\obj.h | ||
| 87 | CHECK-NEXT: 0x1002 | LF_UDT_SRC_LINE [size = 16] | ||
| 88 | CHECK-NEXT: udt = 0x1008, file = 4097, line = 2 | ||
| 89 | CHECK-NEXT: 0x1003 | LF_MFUNC_ID [size = 16] | ||
| 90 | CHECK-NEXT: name = Foo, type = 0x1006, class type = 0x1003 | ||
| 91 | CHECK-NEXT: 0x1004 | LF_STRING_ID [size = 12] ID: <no type>, String: NS | ||
| 92 | CHECK-NEXT: 0x1005 | LF_FUNC_ID [size = 20] | ||
| 93 | CHECK-NEXT: name = func, type = 0x100C, parent scope = 0x1004 | ||
deps/lld/test/COFF/pdb-globals.test created+42| ... | @@ -0,0 +1,42 @@ | ||
| 1 | RUN: yaml2obj %S/Inputs/pdb-globals.yaml > %t.obj | ||
| 2 | RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj | ||
| 3 | RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s | ||
| 4 | |||
| 5 | # Test that we correctly distribute symbols between the globals and module | ||
| 6 | # symbol streams. Specifically: | ||
| 7 | # * S_UDT, S_GDATA32, and S_CONSTANT end up in the globals stream, and are | ||
| 8 | # omitted from the module stream. | ||
| 9 | # * S_GPROC32 and S_LPROC32 end up in the symbols stream, but S_PROCREF and | ||
| 10 | # S_LPROCREF are added to the globals stream that refer to the module | ||
| 11 | # stream. | ||
| 12 | # * S_LDATA32 is copied byte for byte into both streams. | ||
| 13 | |||
| 14 | |||
| 15 | CHECK-LABEL: Global Symbols | ||
| 16 | CHECK-NEXT: ============================================================ | ||
| 17 | CHECK-NEXT: Records | ||
| 18 | CHECK-NEXT: 160 | S_PROCREF [size = 28] `GlobalFunc` | ||
| 19 | CHECK-NEXT: module = 1, sum name = 0, offset = 52 | ||
| 20 | CHECK-NEXT: 188 | S_PROCREF [size = 20] `main` | ||
| 21 | CHECK-NEXT: module = 1, sum name = 0, offset = 108 | ||
| 22 | CHECK-NEXT: 208 | S_LPROCREF [size = 24] `LocalFunc` | ||
| 23 | CHECK-NEXT: module = 1, sum name = 0, offset = 292 | ||
| 24 | CHECK-NEXT: 312 | S_PROCREF [size = 40] `HelloPoint::HelloPoint` | ||
| 25 | CHECK-NEXT: module = 1, sum name = 0, offset = 376 | ||
| 26 | CHECK-NEXT: 232 | S_GDATA32 [size = 28] `__purecall` | ||
| 27 | CHECK-NEXT: type = 0x0403 (void*), addr = 0000:0000 | ||
| 28 | CHECK-NEXT: 260 | S_GDATA32 [size = 24] `GlobalVar` | ||
| 29 | CHECK-NEXT: type = 0x100B (const int*), addr = 0001:0000 | ||
| 30 | CHECK-NEXT: 284 | S_LDATA32 [size = 28] `ConstantVar` | ||
| 31 | CHECK-NEXT: type = 0x100A (const int), addr = 0002:0000 | ||
| 32 | |||
| 33 | CHECK-LABEL: Symbols | ||
| 34 | CHECK-NEXT: ============================================================ | ||
| 35 | CHECK-NEXT: Mod 0000 | ||
| 36 | CHECK-NOT: | S_GDATA32 | ||
| 37 | CHECK-NOT: | S_UDT | ||
| 38 | CHECK: 52 | S_GPROC32 [size = 52] `GlobalFunc` | ||
| 39 | CHECK: 108 | S_GPROC32 [size = 44] `main` | ||
| 40 | CHECK: 292 | S_LPROC32 [size = 52] `LocalFunc` | ||
| 41 | CHECK: 348 | S_LDATA32 [size = 28] `ConstantVar` | ||
| 42 | CHECK: 376 | S_GPROC32 [size = 64] `HelloPoint::HelloPoint` | ||
deps/lld/test/COFF/pdb-heapsite.yaml created+1561| ... | @@ -0,0 +1,1561 @@ | ||
| 1 | # RUN: yaml2obj %s -o %t.obj | ||
| 2 | # RUN: lld-link %t.obj -dll -debug -noentry -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb | ||
| 3 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | ||
| 4 | |||
| 5 | # This object generated from this C++ source: | ||
| 6 | # // t.cpp | ||
| 7 | # void *operator new(size_t) { return nullptr; } | ||
| 8 | # struct Foo { int x; }; | ||
| 9 | # extern "C" __declspec(dllexport) Foo *f() { return new Foo; } | ||
| 10 | |||
| 11 | # Compile as: | ||
| 12 | # $ cl -c -Z7 t.cpp | ||
| 13 | |||
| 14 | # CHECK: S_HEAPALLOCSITE [size = 16] | ||
| 15 | # CHECK-NEXT: type = 0x1000 (Foo), addr = {{.*}} call size = 5 | ||
| 16 | |||
| 17 | --- !COFF | ||
| 18 | header: | ||
| 19 | Machine: IMAGE_FILE_MACHINE_AMD64 | ||
| 20 | Characteristics: [ ] | ||
| 21 | sections: | ||
| 22 | - Name: .drectve | ||
| 23 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 24 | Alignment: 1 | ||
| 25 | SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D455322202F4558504F52543A6620 | ||
| 26 | - Name: '.debug$S' | ||
| 27 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 28 | Alignment: 1 | ||
| 29 | Subsections: | ||
| 30 | - !Symbols | ||
| 31 | Records: | ||
| 32 | - Kind: S_OBJNAME | ||
| 33 | ObjNameSym: | ||
| 34 | Signature: 0 | ||
| 35 | ObjectName: 'C:\src\llvm-project\build\t.obj' | ||
| 36 | - Kind: S_COMPILE3 | ||
| 37 | Compile3Sym: | ||
| 38 | Flags: [ SecurityChecks, HotPatch ] | ||
| 39 | Machine: X64 | ||
| 40 | FrontendMajor: 19 | ||
| 41 | FrontendMinor: 11 | ||
| 42 | FrontendBuild: 25508 | ||
| 43 | FrontendQFE: 2 | ||
| 44 | BackendMajor: 19 | ||
| 45 | BackendMinor: 11 | ||
| 46 | BackendBuild: 25508 | ||
| 47 | BackendQFE: 2 | ||
| 48 | Version: 'Microsoft (R) Optimizing Compiler' | ||
| 49 | - !Symbols | ||
| 50 | Records: | ||
| 51 | - Kind: S_GPROC32_ID | ||
| 52 | ProcSym: | ||
| 53 | CodeSize: 8 | ||
| 54 | DbgStart: 5 | ||
| 55 | DbgEnd: 7 | ||
| 56 | FunctionType: 4104 | ||
| 57 | Flags: [ ] | ||
| 58 | DisplayName: operator new | ||
| 59 | - Kind: S_FRAMEPROC | ||
| 60 | FrameProcSym: | ||
| 61 | TotalFrameBytes: 0 | ||
| 62 | PaddingFrameBytes: 0 | ||
| 63 | OffsetToPadding: 0 | ||
| 64 | BytesOfCalleeSavedRegisters: 0 | ||
| 65 | OffsetOfExceptionHandler: 0 | ||
| 66 | SectionIdOfExceptionHandler: 0 | ||
| 67 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | ||
| 68 | - Kind: S_REGREL32 | ||
| 69 | RegRelativeSym: | ||
| 70 | Offset: 8 | ||
| 71 | Type: 35 | ||
| 72 | Register: RSP | ||
| 73 | VarName: __formal | ||
| 74 | - Kind: S_PROC_ID_END | ||
| 75 | ScopeEndSym: | ||
| 76 | - !Lines | ||
| 77 | CodeSize: 8 | ||
| 78 | Flags: [ ] | ||
| 79 | RelocOffset: 0 | ||
| 80 | RelocSegment: 0 | ||
| 81 | Blocks: | ||
| 82 | - FileName: 'c:\src\llvm-project\build\t.cpp' | ||
| 83 | Lines: | ||
| 84 | - Offset: 0 | ||
| 85 | LineStart: 1 | ||
| 86 | IsStatement: true | ||
| 87 | EndDelta: 0 | ||
| 88 | Columns: | ||
| 89 | - !Symbols | ||
| 90 | Records: | ||
| 91 | - Kind: S_GPROC32_ID | ||
| 92 | ProcSym: | ||
| 93 | CodeSize: 29 | ||
| 94 | DbgStart: 4 | ||
| 95 | DbgEnd: 24 | ||
| 96 | FunctionType: 4107 | ||
| 97 | Flags: [ ] | ||
| 98 | DisplayName: f | ||
| 99 | - Kind: S_FRAMEPROC | ||
| 100 | FrameProcSym: | ||
| 101 | TotalFrameBytes: 56 | ||
| 102 | PaddingFrameBytes: 0 | ||
| 103 | OffsetToPadding: 0 | ||
| 104 | BytesOfCalleeSavedRegisters: 0 | ||
| 105 | OffsetOfExceptionHandler: 0 | ||
| 106 | SectionIdOfExceptionHandler: 0 | ||
| 107 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | ||
| 108 | - Kind: S_HEAPALLOCSITE | ||
| 109 | HeapAllocationSiteSym: | ||
| 110 | Offset: 9 | ||
| 111 | CallInstructionSize: 5 | ||
| 112 | Type: 4096 | ||
| 113 | - Kind: S_PROC_ID_END | ||
| 114 | ScopeEndSym: | ||
| 115 | - !Lines | ||
| 116 | CodeSize: 29 | ||
| 117 | Flags: [ ] | ||
| 118 | RelocOffset: 0 | ||
| 119 | RelocSegment: 0 | ||
| 120 | Blocks: | ||
| 121 | - FileName: 'c:\src\llvm-project\build\t.cpp' | ||
| 122 | Lines: | ||
| 123 | - Offset: 0 | ||
| 124 | LineStart: 3 | ||
| 125 | IsStatement: true | ||
| 126 | EndDelta: 0 | ||
| 127 | Columns: | ||
| 128 | - !Symbols | ||
| 129 | Records: | ||
| 130 | - Kind: S_UDT | ||
| 131 | UDTSym: | ||
| 132 | Type: 4098 | ||
| 133 | UDTName: Foo | ||
| 134 | - Kind: S_UDT | ||
| 135 | UDTSym: | ||
| 136 | Type: 4196 | ||
| 137 | UDTName: '__vc_attributes::event_sourceAttribute' | ||
| 138 | - Kind: S_UDT | ||
| 139 | UDTSym: | ||
| 140 | Type: 4188 | ||
| 141 | UDTName: '__vc_attributes::event_sourceAttribute::optimize_e' | ||
| 142 | - Kind: S_UDT | ||
| 143 | UDTSym: | ||
| 144 | Type: 4185 | ||
| 145 | UDTName: '__vc_attributes::event_sourceAttribute::type_e' | ||
| 146 | - Kind: S_UDT | ||
| 147 | UDTSym: | ||
| 148 | Type: 4181 | ||
| 149 | UDTName: '__vc_attributes::helper_attributes::v1_alttypeAttribute' | ||
| 150 | - Kind: S_UDT | ||
| 151 | UDTSym: | ||
| 152 | Type: 4175 | ||
| 153 | UDTName: '__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e' | ||
| 154 | - Kind: S_UDT | ||
| 155 | UDTSym: | ||
| 156 | Type: 4171 | ||
| 157 | UDTName: '__vc_attributes::helper_attributes::usageAttribute' | ||
| 158 | - Kind: S_UDT | ||
| 159 | UDTSym: | ||
| 160 | Type: 4165 | ||
| 161 | UDTName: '__vc_attributes::helper_attributes::usageAttribute::usage_e' | ||
| 162 | - Kind: S_UDT | ||
| 163 | UDTSym: | ||
| 164 | Type: 4161 | ||
| 165 | UDTName: '__vc_attributes::threadingAttribute' | ||
| 166 | - Kind: S_UDT | ||
| 167 | UDTSym: | ||
| 168 | Type: 4153 | ||
| 169 | UDTName: '__vc_attributes::threadingAttribute::threading_e' | ||
| 170 | - Kind: S_UDT | ||
| 171 | UDTSym: | ||
| 172 | Type: 4149 | ||
| 173 | UDTName: '__vc_attributes::aggregatableAttribute' | ||
| 174 | - Kind: S_UDT | ||
| 175 | UDTSym: | ||
| 176 | Type: 4141 | ||
| 177 | UDTName: '__vc_attributes::aggregatableAttribute::type_e' | ||
| 178 | - Kind: S_UDT | ||
| 179 | UDTSym: | ||
| 180 | Type: 4137 | ||
| 181 | UDTName: '__vc_attributes::event_receiverAttribute' | ||
| 182 | - Kind: S_UDT | ||
| 183 | UDTSym: | ||
| 184 | Type: 4127 | ||
| 185 | UDTName: '__vc_attributes::event_receiverAttribute::type_e' | ||
| 186 | - Kind: S_UDT | ||
| 187 | UDTSym: | ||
| 188 | Type: 4123 | ||
| 189 | UDTName: '__vc_attributes::moduleAttribute' | ||
| 190 | - Kind: S_UDT | ||
| 191 | UDTSym: | ||
| 192 | Type: 4110 | ||
| 193 | UDTName: '__vc_attributes::moduleAttribute::type_e' | ||
| 194 | - Kind: S_UDT | ||
| 195 | UDTSym: | ||
| 196 | Type: 35 | ||
| 197 | UDTName: size_t | ||
| 198 | - !FileChecksums | ||
| 199 | Checksums: | ||
| 200 | - FileName: 'c:\src\llvm-project\build\t.cpp' | ||
| 201 | Kind: MD5 | ||
| 202 | Checksum: 3C4D132707FA572FA0869E4E4DAA7F85 | ||
| 203 | - !StringTable | ||
| 204 | Strings: | ||
| 205 | - 'c:\src\llvm-project\build\t.cpp' | ||
| 206 | - !Symbols | ||
| 207 | Records: | ||
| 208 | - Kind: S_BUILDINFO | ||
| 209 | BuildInfoSym: | ||
| 210 | BuildId: 4205 | ||
| 211 | Relocations: | ||
| 212 | - VirtualAddress: 152 | ||
| 213 | SymbolName: '??2@YAPEAX_K@Z' | ||
| 214 | Type: IMAGE_REL_AMD64_SECREL | ||
| 215 | - VirtualAddress: 156 | ||
| 216 | SymbolName: '??2@YAPEAX_K@Z' | ||
| 217 | Type: IMAGE_REL_AMD64_SECTION | ||
| 218 | - VirtualAddress: 240 | ||
| 219 | SymbolName: '??2@YAPEAX_K@Z' | ||
| 220 | Type: IMAGE_REL_AMD64_SECREL | ||
| 221 | - VirtualAddress: 244 | ||
| 222 | SymbolName: '??2@YAPEAX_K@Z' | ||
| 223 | Type: IMAGE_REL_AMD64_SECTION | ||
| 224 | - VirtualAddress: 312 | ||
| 225 | SymbolName: f | ||
| 226 | Type: IMAGE_REL_AMD64_SECREL | ||
| 227 | - VirtualAddress: 316 | ||
| 228 | SymbolName: f | ||
| 229 | Type: IMAGE_REL_AMD64_SECTION | ||
| 230 | - VirtualAddress: 355 | ||
| 231 | SymbolName: f | ||
| 232 | Type: IMAGE_REL_AMD64_SECREL | ||
| 233 | - VirtualAddress: 359 | ||
| 234 | SymbolName: f | ||
| 235 | Type: IMAGE_REL_AMD64_SECTION | ||
| 236 | - VirtualAddress: 380 | ||
| 237 | SymbolName: f | ||
| 238 | Type: IMAGE_REL_AMD64_SECREL | ||
| 239 | - VirtualAddress: 384 | ||
| 240 | SymbolName: f | ||
| 241 | Type: IMAGE_REL_AMD64_SECTION | ||
| 242 | - Name: '.debug$T' | ||
| 243 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 244 | Alignment: 1 | ||
| 245 | Types: | ||
| 246 | - Kind: LF_STRUCTURE | ||
| 247 | Class: | ||
| 248 | MemberCount: 0 | ||
| 249 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 250 | FieldList: 0 | ||
| 251 | Name: Foo | ||
| 252 | UniqueName: '.?AUFoo@@' | ||
| 253 | DerivationList: 0 | ||
| 254 | VTableShape: 0 | ||
| 255 | Size: 0 | ||
| 256 | - Kind: LF_FIELDLIST | ||
| 257 | FieldList: | ||
| 258 | - Kind: LF_MEMBER | ||
| 259 | DataMember: | ||
| 260 | Attrs: 3 | ||
| 261 | Type: 116 | ||
| 262 | FieldOffset: 0 | ||
| 263 | Name: x | ||
| 264 | - Kind: LF_STRUCTURE | ||
| 265 | Class: | ||
| 266 | MemberCount: 1 | ||
| 267 | Options: [ None, HasUniqueName ] | ||
| 268 | FieldList: 4097 | ||
| 269 | Name: Foo | ||
| 270 | UniqueName: '.?AUFoo@@' | ||
| 271 | DerivationList: 0 | ||
| 272 | VTableShape: 0 | ||
| 273 | Size: 4 | ||
| 274 | - Kind: LF_STRING_ID | ||
| 275 | StringId: | ||
| 276 | Id: 0 | ||
| 277 | String: 'c:\src\llvm-project\build\t.cpp' | ||
| 278 | - Kind: LF_UDT_SRC_LINE | ||
| 279 | UdtSourceLine: | ||
| 280 | UDT: 4098 | ||
| 281 | SourceFile: 4099 | ||
| 282 | LineNumber: 2 | ||
| 283 | - Kind: LF_POINTER | ||
| 284 | Pointer: | ||
| 285 | ReferentType: 4096 | ||
| 286 | Attrs: 65548 | ||
| 287 | - Kind: LF_ARGLIST | ||
| 288 | ArgList: | ||
| 289 | ArgIndices: [ 35 ] | ||
| 290 | - Kind: LF_PROCEDURE | ||
| 291 | Procedure: | ||
| 292 | ReturnType: 1539 | ||
| 293 | CallConv: NearC | ||
| 294 | Options: [ None ] | ||
| 295 | ParameterCount: 1 | ||
| 296 | ArgumentList: 4102 | ||
| 297 | - Kind: LF_FUNC_ID | ||
| 298 | FuncId: | ||
| 299 | ParentScope: 0 | ||
| 300 | FunctionType: 4103 | ||
| 301 | Name: operator new | ||
| 302 | - Kind: LF_ARGLIST | ||
| 303 | ArgList: | ||
| 304 | ArgIndices: [ ] | ||
| 305 | - Kind: LF_PROCEDURE | ||
| 306 | Procedure: | ||
| 307 | ReturnType: 4101 | ||
| 308 | CallConv: NearC | ||
| 309 | Options: [ None ] | ||
| 310 | ParameterCount: 0 | ||
| 311 | ArgumentList: 4105 | ||
| 312 | - Kind: LF_FUNC_ID | ||
| 313 | FuncId: | ||
| 314 | ParentScope: 0 | ||
| 315 | FunctionType: 4106 | ||
| 316 | Name: f | ||
| 317 | - Kind: LF_STRUCTURE | ||
| 318 | Class: | ||
| 319 | MemberCount: 0 | ||
| 320 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 321 | FieldList: 0 | ||
| 322 | Name: '__vc_attributes::moduleAttribute' | ||
| 323 | UniqueName: '.?AUmoduleAttribute@__vc_attributes@@' | ||
| 324 | DerivationList: 0 | ||
| 325 | VTableShape: 0 | ||
| 326 | Size: 0 | ||
| 327 | - Kind: LF_FIELDLIST | ||
| 328 | FieldList: | ||
| 329 | - Kind: LF_ENUMERATE | ||
| 330 | Enumerator: | ||
| 331 | Attrs: 3 | ||
| 332 | Value: 1 | ||
| 333 | Name: dll | ||
| 334 | - Kind: LF_ENUMERATE | ||
| 335 | Enumerator: | ||
| 336 | Attrs: 3 | ||
| 337 | Value: 2 | ||
| 338 | Name: exe | ||
| 339 | - Kind: LF_ENUMERATE | ||
| 340 | Enumerator: | ||
| 341 | Attrs: 3 | ||
| 342 | Value: 3 | ||
| 343 | Name: service | ||
| 344 | - Kind: LF_ENUMERATE | ||
| 345 | Enumerator: | ||
| 346 | Attrs: 3 | ||
| 347 | Value: 4 | ||
| 348 | Name: unspecified | ||
| 349 | - Kind: LF_ENUMERATE | ||
| 350 | Enumerator: | ||
| 351 | Attrs: 3 | ||
| 352 | Value: 2 | ||
| 353 | Name: EXE | ||
| 354 | - Kind: LF_ENUMERATE | ||
| 355 | Enumerator: | ||
| 356 | Attrs: 3 | ||
| 357 | Value: 3 | ||
| 358 | Name: SERVICE | ||
| 359 | - Kind: LF_ENUM | ||
| 360 | Enum: | ||
| 361 | NumEnumerators: 6 | ||
| 362 | Options: [ None, Nested, HasUniqueName ] | ||
| 363 | FieldList: 4109 | ||
| 364 | Name: '__vc_attributes::moduleAttribute::type_e' | ||
| 365 | UniqueName: '.?AW4type_e@moduleAttribute@__vc_attributes@@' | ||
| 366 | UnderlyingType: 116 | ||
| 367 | - Kind: LF_STRING_ID | ||
| 368 | StringId: | ||
| 369 | Id: 0 | ||
| 370 | String: 'c:\src\llvm-project\build\predefined c++ attributes (compiler internal)' | ||
| 371 | - Kind: LF_UDT_SRC_LINE | ||
| 372 | UdtSourceLine: | ||
| 373 | UDT: 4110 | ||
| 374 | SourceFile: 4111 | ||
| 375 | LineNumber: 482 | ||
| 376 | - Kind: LF_MODIFIER | ||
| 377 | Modifier: | ||
| 378 | ModifiedType: 112 | ||
| 379 | Modifiers: [ None, Const ] | ||
| 380 | - Kind: LF_POINTER | ||
| 381 | Pointer: | ||
| 382 | ReferentType: 4113 | ||
| 383 | Attrs: 65548 | ||
| 384 | - Kind: LF_ARGLIST | ||
| 385 | ArgList: | ||
| 386 | ArgIndices: [ 4110, 4114, 4114, 4114, 116, 48, 4114, 116, | ||
| 387 | 4114, 4114, 116, 48, 48, 4114, 4114 ] | ||
| 388 | - Kind: LF_POINTER | ||
| 389 | Pointer: | ||
| 390 | ReferentType: 4108 | ||
| 391 | Attrs: 66572 | ||
| 392 | - Kind: LF_MFUNCTION | ||
| 393 | MemberFunction: | ||
| 394 | ReturnType: 3 | ||
| 395 | ClassType: 4108 | ||
| 396 | ThisType: 4116 | ||
| 397 | CallConv: NearC | ||
| 398 | Options: [ None, Constructor ] | ||
| 399 | ParameterCount: 15 | ||
| 400 | ArgumentList: 4115 | ||
| 401 | ThisPointerAdjustment: 0 | ||
| 402 | - Kind: LF_ARGLIST | ||
| 403 | ArgList: | ||
| 404 | ArgIndices: [ 4110 ] | ||
| 405 | - Kind: LF_MFUNCTION | ||
| 406 | MemberFunction: | ||
| 407 | ReturnType: 3 | ||
| 408 | ClassType: 4108 | ||
| 409 | ThisType: 4116 | ||
| 410 | CallConv: NearC | ||
| 411 | Options: [ None, Constructor ] | ||
| 412 | ParameterCount: 1 | ||
| 413 | ArgumentList: 4118 | ||
| 414 | ThisPointerAdjustment: 0 | ||
| 415 | - Kind: LF_MFUNCTION | ||
| 416 | MemberFunction: | ||
| 417 | ReturnType: 3 | ||
| 418 | ClassType: 4108 | ||
| 419 | ThisType: 4116 | ||
| 420 | CallConv: NearC | ||
| 421 | Options: [ None, Constructor ] | ||
| 422 | ParameterCount: 0 | ||
| 423 | ArgumentList: 4105 | ||
| 424 | ThisPointerAdjustment: 0 | ||
| 425 | - Kind: LF_METHODLIST | ||
| 426 | MethodOverloadList: | ||
| 427 | Methods: | ||
| 428 | - Type: 4117 | ||
| 429 | Attrs: 3 | ||
| 430 | VFTableOffset: -1 | ||
| 431 | Name: '' | ||
| 432 | - Type: 4119 | ||
| 433 | Attrs: 3 | ||
| 434 | VFTableOffset: -1 | ||
| 435 | Name: '' | ||
| 436 | - Type: 4120 | ||
| 437 | Attrs: 3 | ||
| 438 | VFTableOffset: -1 | ||
| 439 | Name: '' | ||
| 440 | - Kind: LF_FIELDLIST | ||
| 441 | FieldList: | ||
| 442 | - Kind: LF_NESTTYPE | ||
| 443 | NestedType: | ||
| 444 | Type: 4110 | ||
| 445 | Name: type_e | ||
| 446 | - Kind: LF_METHOD | ||
| 447 | OverloadedMethod: | ||
| 448 | NumOverloads: 3 | ||
| 449 | MethodList: 4121 | ||
| 450 | Name: moduleAttribute | ||
| 451 | - Kind: LF_MEMBER | ||
| 452 | DataMember: | ||
| 453 | Attrs: 3 | ||
| 454 | Type: 4110 | ||
| 455 | FieldOffset: 0 | ||
| 456 | Name: type | ||
| 457 | - Kind: LF_MEMBER | ||
| 458 | DataMember: | ||
| 459 | Attrs: 3 | ||
| 460 | Type: 4114 | ||
| 461 | FieldOffset: 8 | ||
| 462 | Name: name | ||
| 463 | - Kind: LF_MEMBER | ||
| 464 | DataMember: | ||
| 465 | Attrs: 3 | ||
| 466 | Type: 4114 | ||
| 467 | FieldOffset: 16 | ||
| 468 | Name: version | ||
| 469 | - Kind: LF_MEMBER | ||
| 470 | DataMember: | ||
| 471 | Attrs: 3 | ||
| 472 | Type: 4114 | ||
| 473 | FieldOffset: 24 | ||
| 474 | Name: uuid | ||
| 475 | - Kind: LF_MEMBER | ||
| 476 | DataMember: | ||
| 477 | Attrs: 3 | ||
| 478 | Type: 116 | ||
| 479 | FieldOffset: 32 | ||
| 480 | Name: lcid | ||
| 481 | - Kind: LF_MEMBER | ||
| 482 | DataMember: | ||
| 483 | Attrs: 3 | ||
| 484 | Type: 48 | ||
| 485 | FieldOffset: 36 | ||
| 486 | Name: control | ||
| 487 | - Kind: LF_MEMBER | ||
| 488 | DataMember: | ||
| 489 | Attrs: 3 | ||
| 490 | Type: 4114 | ||
| 491 | FieldOffset: 40 | ||
| 492 | Name: helpstring | ||
| 493 | - Kind: LF_MEMBER | ||
| 494 | DataMember: | ||
| 495 | Attrs: 3 | ||
| 496 | Type: 116 | ||
| 497 | FieldOffset: 48 | ||
| 498 | Name: helpstringcontext | ||
| 499 | - Kind: LF_MEMBER | ||
| 500 | DataMember: | ||
| 501 | Attrs: 3 | ||
| 502 | Type: 4114 | ||
| 503 | FieldOffset: 56 | ||
| 504 | Name: helpstringdll | ||
| 505 | - Kind: LF_MEMBER | ||
| 506 | DataMember: | ||
| 507 | Attrs: 3 | ||
| 508 | Type: 4114 | ||
| 509 | FieldOffset: 64 | ||
| 510 | Name: helpfile | ||
| 511 | - Kind: LF_MEMBER | ||
| 512 | DataMember: | ||
| 513 | Attrs: 3 | ||
| 514 | Type: 116 | ||
| 515 | FieldOffset: 72 | ||
| 516 | Name: helpcontext | ||
| 517 | - Kind: LF_MEMBER | ||
| 518 | DataMember: | ||
| 519 | Attrs: 3 | ||
| 520 | Type: 48 | ||
| 521 | FieldOffset: 76 | ||
| 522 | Name: hidden | ||
| 523 | - Kind: LF_MEMBER | ||
| 524 | DataMember: | ||
| 525 | Attrs: 3 | ||
| 526 | Type: 48 | ||
| 527 | FieldOffset: 77 | ||
| 528 | Name: restricted | ||
| 529 | - Kind: LF_MEMBER | ||
| 530 | DataMember: | ||
| 531 | Attrs: 3 | ||
| 532 | Type: 4114 | ||
| 533 | FieldOffset: 80 | ||
| 534 | Name: custom | ||
| 535 | - Kind: LF_MEMBER | ||
| 536 | DataMember: | ||
| 537 | Attrs: 3 | ||
| 538 | Type: 4114 | ||
| 539 | FieldOffset: 88 | ||
| 540 | Name: resource_name | ||
| 541 | - Kind: LF_STRUCTURE | ||
| 542 | Class: | ||
| 543 | MemberCount: 19 | ||
| 544 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 545 | FieldList: 4122 | ||
| 546 | Name: '__vc_attributes::moduleAttribute' | ||
| 547 | UniqueName: '.?AUmoduleAttribute@__vc_attributes@@' | ||
| 548 | DerivationList: 0 | ||
| 549 | VTableShape: 0 | ||
| 550 | Size: 96 | ||
| 551 | - Kind: LF_UDT_SRC_LINE | ||
| 552 | UdtSourceLine: | ||
| 553 | UDT: 4123 | ||
| 554 | SourceFile: 4111 | ||
| 555 | LineNumber: 481 | ||
| 556 | - Kind: LF_STRUCTURE | ||
| 557 | Class: | ||
| 558 | MemberCount: 0 | ||
| 559 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 560 | FieldList: 0 | ||
| 561 | Name: '__vc_attributes::event_receiverAttribute' | ||
| 562 | UniqueName: '.?AUevent_receiverAttribute@__vc_attributes@@' | ||
| 563 | DerivationList: 0 | ||
| 564 | VTableShape: 0 | ||
| 565 | Size: 0 | ||
| 566 | - Kind: LF_FIELDLIST | ||
| 567 | FieldList: | ||
| 568 | - Kind: LF_ENUMERATE | ||
| 569 | Enumerator: | ||
| 570 | Attrs: 3 | ||
| 571 | Value: 0 | ||
| 572 | Name: native | ||
| 573 | - Kind: LF_ENUMERATE | ||
| 574 | Enumerator: | ||
| 575 | Attrs: 3 | ||
| 576 | Value: 1 | ||
| 577 | Name: com | ||
| 578 | - Kind: LF_ENUMERATE | ||
| 579 | Enumerator: | ||
| 580 | Attrs: 3 | ||
| 581 | Value: 2 | ||
| 582 | Name: managed | ||
| 583 | - Kind: LF_ENUM | ||
| 584 | Enum: | ||
| 585 | NumEnumerators: 3 | ||
| 586 | Options: [ None, Nested, HasUniqueName ] | ||
| 587 | FieldList: 4126 | ||
| 588 | Name: '__vc_attributes::event_receiverAttribute::type_e' | ||
| 589 | UniqueName: '.?AW4type_e@event_receiverAttribute@__vc_attributes@@' | ||
| 590 | UnderlyingType: 116 | ||
| 591 | - Kind: LF_UDT_SRC_LINE | ||
| 592 | UdtSourceLine: | ||
| 593 | UDT: 4127 | ||
| 594 | SourceFile: 4111 | ||
| 595 | LineNumber: 136 | ||
| 596 | - Kind: LF_ARGLIST | ||
| 597 | ArgList: | ||
| 598 | ArgIndices: [ 4127, 48 ] | ||
| 599 | - Kind: LF_POINTER | ||
| 600 | Pointer: | ||
| 601 | ReferentType: 4125 | ||
| 602 | Attrs: 66572 | ||
| 603 | - Kind: LF_MFUNCTION | ||
| 604 | MemberFunction: | ||
| 605 | ReturnType: 3 | ||
| 606 | ClassType: 4125 | ||
| 607 | ThisType: 4130 | ||
| 608 | CallConv: NearC | ||
| 609 | Options: [ None, Constructor ] | ||
| 610 | ParameterCount: 2 | ||
| 611 | ArgumentList: 4129 | ||
| 612 | ThisPointerAdjustment: 0 | ||
| 613 | - Kind: LF_ARGLIST | ||
| 614 | ArgList: | ||
| 615 | ArgIndices: [ 4127 ] | ||
| 616 | - Kind: LF_MFUNCTION | ||
| 617 | MemberFunction: | ||
| 618 | ReturnType: 3 | ||
| 619 | ClassType: 4125 | ||
| 620 | ThisType: 4130 | ||
| 621 | CallConv: NearC | ||
| 622 | Options: [ None, Constructor ] | ||
| 623 | ParameterCount: 1 | ||
| 624 | ArgumentList: 4132 | ||
| 625 | ThisPointerAdjustment: 0 | ||
| 626 | - Kind: LF_MFUNCTION | ||
| 627 | MemberFunction: | ||
| 628 | ReturnType: 3 | ||
| 629 | ClassType: 4125 | ||
| 630 | ThisType: 4130 | ||
| 631 | CallConv: NearC | ||
| 632 | Options: [ None, Constructor ] | ||
| 633 | ParameterCount: 0 | ||
| 634 | ArgumentList: 4105 | ||
| 635 | ThisPointerAdjustment: 0 | ||
| 636 | - Kind: LF_METHODLIST | ||
| 637 | MethodOverloadList: | ||
| 638 | Methods: | ||
| 639 | - Type: 4131 | ||
| 640 | Attrs: 3 | ||
| 641 | VFTableOffset: -1 | ||
| 642 | Name: '' | ||
| 643 | - Type: 4133 | ||
| 644 | Attrs: 3 | ||
| 645 | VFTableOffset: -1 | ||
| 646 | Name: '' | ||
| 647 | - Type: 4134 | ||
| 648 | Attrs: 3 | ||
| 649 | VFTableOffset: -1 | ||
| 650 | Name: '' | ||
| 651 | - Kind: LF_FIELDLIST | ||
| 652 | FieldList: | ||
| 653 | - Kind: LF_NESTTYPE | ||
| 654 | NestedType: | ||
| 655 | Type: 4127 | ||
| 656 | Name: type_e | ||
| 657 | - Kind: LF_METHOD | ||
| 658 | OverloadedMethod: | ||
| 659 | NumOverloads: 3 | ||
| 660 | MethodList: 4135 | ||
| 661 | Name: event_receiverAttribute | ||
| 662 | - Kind: LF_MEMBER | ||
| 663 | DataMember: | ||
| 664 | Attrs: 3 | ||
| 665 | Type: 4127 | ||
| 666 | FieldOffset: 0 | ||
| 667 | Name: type | ||
| 668 | - Kind: LF_MEMBER | ||
| 669 | DataMember: | ||
| 670 | Attrs: 3 | ||
| 671 | Type: 48 | ||
| 672 | FieldOffset: 4 | ||
| 673 | Name: layout_dependent | ||
| 674 | - Kind: LF_STRUCTURE | ||
| 675 | Class: | ||
| 676 | MemberCount: 6 | ||
| 677 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 678 | FieldList: 4136 | ||
| 679 | Name: '__vc_attributes::event_receiverAttribute' | ||
| 680 | UniqueName: '.?AUevent_receiverAttribute@__vc_attributes@@' | ||
| 681 | DerivationList: 0 | ||
| 682 | VTableShape: 0 | ||
| 683 | Size: 8 | ||
| 684 | - Kind: LF_UDT_SRC_LINE | ||
| 685 | UdtSourceLine: | ||
| 686 | UDT: 4137 | ||
| 687 | SourceFile: 4111 | ||
| 688 | LineNumber: 135 | ||
| 689 | - Kind: LF_STRUCTURE | ||
| 690 | Class: | ||
| 691 | MemberCount: 0 | ||
| 692 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 693 | FieldList: 0 | ||
| 694 | Name: '__vc_attributes::aggregatableAttribute' | ||
| 695 | UniqueName: '.?AUaggregatableAttribute@__vc_attributes@@' | ||
| 696 | DerivationList: 0 | ||
| 697 | VTableShape: 0 | ||
| 698 | Size: 0 | ||
| 699 | - Kind: LF_FIELDLIST | ||
| 700 | FieldList: | ||
| 701 | - Kind: LF_ENUMERATE | ||
| 702 | Enumerator: | ||
| 703 | Attrs: 3 | ||
| 704 | Value: 0 | ||
| 705 | Name: never | ||
| 706 | - Kind: LF_ENUMERATE | ||
| 707 | Enumerator: | ||
| 708 | Attrs: 3 | ||
| 709 | Value: 1 | ||
| 710 | Name: allowed | ||
| 711 | - Kind: LF_ENUMERATE | ||
| 712 | Enumerator: | ||
| 713 | Attrs: 3 | ||
| 714 | Value: 2 | ||
| 715 | Name: always | ||
| 716 | - Kind: LF_ENUM | ||
| 717 | Enum: | ||
| 718 | NumEnumerators: 3 | ||
| 719 | Options: [ None, Nested, HasUniqueName ] | ||
| 720 | FieldList: 4140 | ||
| 721 | Name: '__vc_attributes::aggregatableAttribute::type_e' | ||
| 722 | UniqueName: '.?AW4type_e@aggregatableAttribute@__vc_attributes@@' | ||
| 723 | UnderlyingType: 116 | ||
| 724 | - Kind: LF_UDT_SRC_LINE | ||
| 725 | UdtSourceLine: | ||
| 726 | UDT: 4141 | ||
| 727 | SourceFile: 4111 | ||
| 728 | LineNumber: 545 | ||
| 729 | - Kind: LF_ARGLIST | ||
| 730 | ArgList: | ||
| 731 | ArgIndices: [ 4141 ] | ||
| 732 | - Kind: LF_POINTER | ||
| 733 | Pointer: | ||
| 734 | ReferentType: 4139 | ||
| 735 | Attrs: 66572 | ||
| 736 | - Kind: LF_MFUNCTION | ||
| 737 | MemberFunction: | ||
| 738 | ReturnType: 3 | ||
| 739 | ClassType: 4139 | ||
| 740 | ThisType: 4144 | ||
| 741 | CallConv: NearC | ||
| 742 | Options: [ None, Constructor ] | ||
| 743 | ParameterCount: 1 | ||
| 744 | ArgumentList: 4143 | ||
| 745 | ThisPointerAdjustment: 0 | ||
| 746 | - Kind: LF_MFUNCTION | ||
| 747 | MemberFunction: | ||
| 748 | ReturnType: 3 | ||
| 749 | ClassType: 4139 | ||
| 750 | ThisType: 4144 | ||
| 751 | CallConv: NearC | ||
| 752 | Options: [ None, Constructor ] | ||
| 753 | ParameterCount: 0 | ||
| 754 | ArgumentList: 4105 | ||
| 755 | ThisPointerAdjustment: 0 | ||
| 756 | - Kind: LF_METHODLIST | ||
| 757 | MethodOverloadList: | ||
| 758 | Methods: | ||
| 759 | - Type: 4145 | ||
| 760 | Attrs: 3 | ||
| 761 | VFTableOffset: -1 | ||
| 762 | Name: '' | ||
| 763 | - Type: 4146 | ||
| 764 | Attrs: 3 | ||
| 765 | VFTableOffset: -1 | ||
| 766 | Name: '' | ||
| 767 | - Kind: LF_FIELDLIST | ||
| 768 | FieldList: | ||
| 769 | - Kind: LF_NESTTYPE | ||
| 770 | NestedType: | ||
| 771 | Type: 4141 | ||
| 772 | Name: type_e | ||
| 773 | - Kind: LF_METHOD | ||
| 774 | OverloadedMethod: | ||
| 775 | NumOverloads: 2 | ||
| 776 | MethodList: 4147 | ||
| 777 | Name: aggregatableAttribute | ||
| 778 | - Kind: LF_MEMBER | ||
| 779 | DataMember: | ||
| 780 | Attrs: 3 | ||
| 781 | Type: 4141 | ||
| 782 | FieldOffset: 0 | ||
| 783 | Name: type | ||
| 784 | - Kind: LF_STRUCTURE | ||
| 785 | Class: | ||
| 786 | MemberCount: 4 | ||
| 787 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 788 | FieldList: 4148 | ||
| 789 | Name: '__vc_attributes::aggregatableAttribute' | ||
| 790 | UniqueName: '.?AUaggregatableAttribute@__vc_attributes@@' | ||
| 791 | DerivationList: 0 | ||
| 792 | VTableShape: 0 | ||
| 793 | Size: 4 | ||
| 794 | - Kind: LF_UDT_SRC_LINE | ||
| 795 | UdtSourceLine: | ||
| 796 | UDT: 4149 | ||
| 797 | SourceFile: 4111 | ||
| 798 | LineNumber: 544 | ||
| 799 | - Kind: LF_STRUCTURE | ||
| 800 | Class: | ||
| 801 | MemberCount: 0 | ||
| 802 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 803 | FieldList: 0 | ||
| 804 | Name: '__vc_attributes::threadingAttribute' | ||
| 805 | UniqueName: '.?AUthreadingAttribute@__vc_attributes@@' | ||
| 806 | DerivationList: 0 | ||
| 807 | VTableShape: 0 | ||
| 808 | Size: 0 | ||
| 809 | - Kind: LF_FIELDLIST | ||
| 810 | FieldList: | ||
| 811 | - Kind: LF_ENUMERATE | ||
| 812 | Enumerator: | ||
| 813 | Attrs: 3 | ||
| 814 | Value: 1 | ||
| 815 | Name: apartment | ||
| 816 | - Kind: LF_ENUMERATE | ||
| 817 | Enumerator: | ||
| 818 | Attrs: 3 | ||
| 819 | Value: 2 | ||
| 820 | Name: single | ||
| 821 | - Kind: LF_ENUMERATE | ||
| 822 | Enumerator: | ||
| 823 | Attrs: 3 | ||
| 824 | Value: 3 | ||
| 825 | Name: free | ||
| 826 | - Kind: LF_ENUMERATE | ||
| 827 | Enumerator: | ||
| 828 | Attrs: 3 | ||
| 829 | Value: 4 | ||
| 830 | Name: neutral | ||
| 831 | - Kind: LF_ENUMERATE | ||
| 832 | Enumerator: | ||
| 833 | Attrs: 3 | ||
| 834 | Value: 5 | ||
| 835 | Name: both | ||
| 836 | - Kind: LF_ENUM | ||
| 837 | Enum: | ||
| 838 | NumEnumerators: 5 | ||
| 839 | Options: [ None, Nested, HasUniqueName ] | ||
| 840 | FieldList: 4152 | ||
| 841 | Name: '__vc_attributes::threadingAttribute::threading_e' | ||
| 842 | UniqueName: '.?AW4threading_e@threadingAttribute@__vc_attributes@@' | ||
| 843 | UnderlyingType: 116 | ||
| 844 | - Kind: LF_UDT_SRC_LINE | ||
| 845 | UdtSourceLine: | ||
| 846 | UDT: 4153 | ||
| 847 | SourceFile: 4111 | ||
| 848 | LineNumber: 423 | ||
| 849 | - Kind: LF_ARGLIST | ||
| 850 | ArgList: | ||
| 851 | ArgIndices: [ 4153 ] | ||
| 852 | - Kind: LF_POINTER | ||
| 853 | Pointer: | ||
| 854 | ReferentType: 4151 | ||
| 855 | Attrs: 66572 | ||
| 856 | - Kind: LF_MFUNCTION | ||
| 857 | MemberFunction: | ||
| 858 | ReturnType: 3 | ||
| 859 | ClassType: 4151 | ||
| 860 | ThisType: 4156 | ||
| 861 | CallConv: NearC | ||
| 862 | Options: [ None, Constructor ] | ||
| 863 | ParameterCount: 1 | ||
| 864 | ArgumentList: 4155 | ||
| 865 | ThisPointerAdjustment: 0 | ||
| 866 | - Kind: LF_MFUNCTION | ||
| 867 | MemberFunction: | ||
| 868 | ReturnType: 3 | ||
| 869 | ClassType: 4151 | ||
| 870 | ThisType: 4156 | ||
| 871 | CallConv: NearC | ||
| 872 | Options: [ None, Constructor ] | ||
| 873 | ParameterCount: 0 | ||
| 874 | ArgumentList: 4105 | ||
| 875 | ThisPointerAdjustment: 0 | ||
| 876 | - Kind: LF_METHODLIST | ||
| 877 | MethodOverloadList: | ||
| 878 | Methods: | ||
| 879 | - Type: 4157 | ||
| 880 | Attrs: 3 | ||
| 881 | VFTableOffset: -1 | ||
| 882 | Name: '' | ||
| 883 | - Type: 4158 | ||
| 884 | Attrs: 3 | ||
| 885 | VFTableOffset: -1 | ||
| 886 | Name: '' | ||
| 887 | - Kind: LF_FIELDLIST | ||
| 888 | FieldList: | ||
| 889 | - Kind: LF_NESTTYPE | ||
| 890 | NestedType: | ||
| 891 | Type: 4153 | ||
| 892 | Name: threading_e | ||
| 893 | - Kind: LF_METHOD | ||
| 894 | OverloadedMethod: | ||
| 895 | NumOverloads: 2 | ||
| 896 | MethodList: 4159 | ||
| 897 | Name: threadingAttribute | ||
| 898 | - Kind: LF_MEMBER | ||
| 899 | DataMember: | ||
| 900 | Attrs: 3 | ||
| 901 | Type: 4153 | ||
| 902 | FieldOffset: 0 | ||
| 903 | Name: value | ||
| 904 | - Kind: LF_STRUCTURE | ||
| 905 | Class: | ||
| 906 | MemberCount: 4 | ||
| 907 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 908 | FieldList: 4160 | ||
| 909 | Name: '__vc_attributes::threadingAttribute' | ||
| 910 | UniqueName: '.?AUthreadingAttribute@__vc_attributes@@' | ||
| 911 | DerivationList: 0 | ||
| 912 | VTableShape: 0 | ||
| 913 | Size: 4 | ||
| 914 | - Kind: LF_UDT_SRC_LINE | ||
| 915 | UdtSourceLine: | ||
| 916 | UDT: 4161 | ||
| 917 | SourceFile: 4111 | ||
| 918 | LineNumber: 422 | ||
| 919 | - Kind: LF_STRUCTURE | ||
| 920 | Class: | ||
| 921 | MemberCount: 0 | ||
| 922 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 923 | FieldList: 0 | ||
| 924 | Name: '__vc_attributes::helper_attributes::usageAttribute' | ||
| 925 | UniqueName: '.?AUusageAttribute@helper_attributes@__vc_attributes@@' | ||
| 926 | DerivationList: 0 | ||
| 927 | VTableShape: 0 | ||
| 928 | Size: 0 | ||
| 929 | - Kind: LF_FIELDLIST | ||
| 930 | FieldList: | ||
| 931 | - Kind: LF_ENUMERATE | ||
| 932 | Enumerator: | ||
| 933 | Attrs: 3 | ||
| 934 | Value: 0 | ||
| 935 | Name: eAnyUsage | ||
| 936 | - Kind: LF_ENUMERATE | ||
| 937 | Enumerator: | ||
| 938 | Attrs: 3 | ||
| 939 | Value: 1 | ||
| 940 | Name: eCoClassUsage | ||
| 941 | - Kind: LF_ENUMERATE | ||
| 942 | Enumerator: | ||
| 943 | Attrs: 3 | ||
| 944 | Value: 2 | ||
| 945 | Name: eCOMInterfaceUsage | ||
| 946 | - Kind: LF_ENUMERATE | ||
| 947 | Enumerator: | ||
| 948 | Attrs: 3 | ||
| 949 | Value: 6 | ||
| 950 | Name: eInterfaceUsage | ||
| 951 | - Kind: LF_ENUMERATE | ||
| 952 | Enumerator: | ||
| 953 | Attrs: 3 | ||
| 954 | Value: 8 | ||
| 955 | Name: eMemberUsage | ||
| 956 | - Kind: LF_ENUMERATE | ||
| 957 | Enumerator: | ||
| 958 | Attrs: 3 | ||
| 959 | Value: 16 | ||
| 960 | Name: eMethodUsage | ||
| 961 | - Kind: LF_ENUMERATE | ||
| 962 | Enumerator: | ||
| 963 | Attrs: 3 | ||
| 964 | Value: 32 | ||
| 965 | Name: eInterfaceMethodUsage | ||
| 966 | - Kind: LF_ENUMERATE | ||
| 967 | Enumerator: | ||
| 968 | Attrs: 3 | ||
| 969 | Value: 64 | ||
| 970 | Name: eInterfaceMemberUsage | ||
| 971 | - Kind: LF_ENUMERATE | ||
| 972 | Enumerator: | ||
| 973 | Attrs: 3 | ||
| 974 | Value: 128 | ||
| 975 | Name: eCoClassMemberUsage | ||
| 976 | - Kind: LF_ENUMERATE | ||
| 977 | Enumerator: | ||
| 978 | Attrs: 3 | ||
| 979 | Value: 256 | ||
| 980 | Name: eCoClassMethodUsage | ||
| 981 | - Kind: LF_ENUMERATE | ||
| 982 | Enumerator: | ||
| 983 | Attrs: 3 | ||
| 984 | Value: 768 | ||
| 985 | Name: eGlobalMethodUsage | ||
| 986 | - Kind: LF_ENUMERATE | ||
| 987 | Enumerator: | ||
| 988 | Attrs: 3 | ||
| 989 | Value: 1024 | ||
| 990 | Name: eGlobalDataUsage | ||
| 991 | - Kind: LF_ENUMERATE | ||
| 992 | Enumerator: | ||
| 993 | Attrs: 3 | ||
| 994 | Value: 2048 | ||
| 995 | Name: eClassUsage | ||
| 996 | - Kind: LF_ENUMERATE | ||
| 997 | Enumerator: | ||
| 998 | Attrs: 3 | ||
| 999 | Value: 4096 | ||
| 1000 | Name: eInterfaceParameterUsage | ||
| 1001 | - Kind: LF_ENUMERATE | ||
| 1002 | Enumerator: | ||
| 1003 | Attrs: 3 | ||
| 1004 | Value: 12288 | ||
| 1005 | Name: eMethodParameterUsage | ||
| 1006 | - Kind: LF_ENUMERATE | ||
| 1007 | Enumerator: | ||
| 1008 | Attrs: 3 | ||
| 1009 | Value: 16384 | ||
| 1010 | Name: eIDLModuleUsage | ||
| 1011 | - Kind: LF_ENUMERATE | ||
| 1012 | Enumerator: | ||
| 1013 | Attrs: 3 | ||
| 1014 | Value: 32768 | ||
| 1015 | Name: eAnonymousUsage | ||
| 1016 | - Kind: LF_ENUMERATE | ||
| 1017 | Enumerator: | ||
| 1018 | Attrs: 3 | ||
| 1019 | Value: 65536 | ||
| 1020 | Name: eTypedefUsage | ||
| 1021 | - Kind: LF_ENUMERATE | ||
| 1022 | Enumerator: | ||
| 1023 | Attrs: 3 | ||
| 1024 | Value: 131072 | ||
| 1025 | Name: eUnionUsage | ||
| 1026 | - Kind: LF_ENUMERATE | ||
| 1027 | Enumerator: | ||
| 1028 | Attrs: 3 | ||
| 1029 | Value: 262144 | ||
| 1030 | Name: eEnumUsage | ||
| 1031 | - Kind: LF_ENUMERATE | ||
| 1032 | Enumerator: | ||
| 1033 | Attrs: 3 | ||
| 1034 | Value: 524288 | ||
| 1035 | Name: eDefineTagUsage | ||
| 1036 | - Kind: LF_ENUMERATE | ||
| 1037 | Enumerator: | ||
| 1038 | Attrs: 3 | ||
| 1039 | Value: 1048576 | ||
| 1040 | Name: eStructUsage | ||
| 1041 | - Kind: LF_ENUMERATE | ||
| 1042 | Enumerator: | ||
| 1043 | Attrs: 3 | ||
| 1044 | Value: 2097152 | ||
| 1045 | Name: eLocalUsage | ||
| 1046 | - Kind: LF_ENUMERATE | ||
| 1047 | Enumerator: | ||
| 1048 | Attrs: 3 | ||
| 1049 | Value: 4194304 | ||
| 1050 | Name: ePropertyUsage | ||
| 1051 | - Kind: LF_ENUMERATE | ||
| 1052 | Enumerator: | ||
| 1053 | Attrs: 3 | ||
| 1054 | Value: 8388608 | ||
| 1055 | Name: eEventUsage | ||
| 1056 | - Kind: LF_ENUMERATE | ||
| 1057 | Enumerator: | ||
| 1058 | Attrs: 3 | ||
| 1059 | Value: 16777216 | ||
| 1060 | Name: eTemplateUsage | ||
| 1061 | - Kind: LF_ENUMERATE | ||
| 1062 | Enumerator: | ||
| 1063 | Attrs: 3 | ||
| 1064 | Value: 16777216 | ||
| 1065 | Name: eModuleUsage | ||
| 1066 | - Kind: LF_ENUMERATE | ||
| 1067 | Enumerator: | ||
| 1068 | Attrs: 3 | ||
| 1069 | Value: 33554432 | ||
| 1070 | Name: eIllegalUsage | ||
| 1071 | - Kind: LF_ENUMERATE | ||
| 1072 | Enumerator: | ||
| 1073 | Attrs: 3 | ||
| 1074 | Value: 67108864 | ||
| 1075 | Name: eAsynchronousUsage | ||
| 1076 | - Kind: LF_ENUMERATE | ||
| 1077 | Enumerator: | ||
| 1078 | Attrs: 3 | ||
| 1079 | Value: 4161535 | ||
| 1080 | Name: eAnyIDLUsage | ||
| 1081 | - Kind: LF_ENUM | ||
| 1082 | Enum: | ||
| 1083 | NumEnumerators: 30 | ||
| 1084 | Options: [ None, Nested, HasUniqueName ] | ||
| 1085 | FieldList: 4164 | ||
| 1086 | Name: '__vc_attributes::helper_attributes::usageAttribute::usage_e' | ||
| 1087 | UniqueName: '.?AW4usage_e@usageAttribute@helper_attributes@__vc_attributes@@' | ||
| 1088 | UnderlyingType: 116 | ||
| 1089 | - Kind: LF_UDT_SRC_LINE | ||
| 1090 | UdtSourceLine: | ||
| 1091 | UDT: 4165 | ||
| 1092 | SourceFile: 4111 | ||
| 1093 | LineNumber: 51 | ||
| 1094 | - Kind: LF_ARGLIST | ||
| 1095 | ArgList: | ||
| 1096 | ArgIndices: [ 117 ] | ||
| 1097 | - Kind: LF_POINTER | ||
| 1098 | Pointer: | ||
| 1099 | ReferentType: 4163 | ||
| 1100 | Attrs: 66572 | ||
| 1101 | - Kind: LF_MFUNCTION | ||
| 1102 | MemberFunction: | ||
| 1103 | ReturnType: 3 | ||
| 1104 | ClassType: 4163 | ||
| 1105 | ThisType: 4168 | ||
| 1106 | CallConv: NearC | ||
| 1107 | Options: [ None, Constructor ] | ||
| 1108 | ParameterCount: 1 | ||
| 1109 | ArgumentList: 4167 | ||
| 1110 | ThisPointerAdjustment: 0 | ||
| 1111 | - Kind: LF_FIELDLIST | ||
| 1112 | FieldList: | ||
| 1113 | - Kind: LF_NESTTYPE | ||
| 1114 | NestedType: | ||
| 1115 | Type: 4165 | ||
| 1116 | Name: usage_e | ||
| 1117 | - Kind: LF_ONEMETHOD | ||
| 1118 | OneMethod: | ||
| 1119 | Type: 4169 | ||
| 1120 | Attrs: 3 | ||
| 1121 | VFTableOffset: -1 | ||
| 1122 | Name: usageAttribute | ||
| 1123 | - Kind: LF_MEMBER | ||
| 1124 | DataMember: | ||
| 1125 | Attrs: 3 | ||
| 1126 | Type: 117 | ||
| 1127 | FieldOffset: 0 | ||
| 1128 | Name: value | ||
| 1129 | - Kind: LF_STRUCTURE | ||
| 1130 | Class: | ||
| 1131 | MemberCount: 3 | ||
| 1132 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1133 | FieldList: 4170 | ||
| 1134 | Name: '__vc_attributes::helper_attributes::usageAttribute' | ||
| 1135 | UniqueName: '.?AUusageAttribute@helper_attributes@__vc_attributes@@' | ||
| 1136 | DerivationList: 0 | ||
| 1137 | VTableShape: 0 | ||
| 1138 | Size: 4 | ||
| 1139 | - Kind: LF_UDT_SRC_LINE | ||
| 1140 | UdtSourceLine: | ||
| 1141 | UDT: 4171 | ||
| 1142 | SourceFile: 4111 | ||
| 1143 | LineNumber: 49 | ||
| 1144 | - Kind: LF_STRUCTURE | ||
| 1145 | Class: | ||
| 1146 | MemberCount: 0 | ||
| 1147 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 1148 | FieldList: 0 | ||
| 1149 | Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute' | ||
| 1150 | UniqueName: '.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@' | ||
| 1151 | DerivationList: 0 | ||
| 1152 | VTableShape: 0 | ||
| 1153 | Size: 0 | ||
| 1154 | - Kind: LF_FIELDLIST | ||
| 1155 | FieldList: | ||
| 1156 | - Kind: LF_ENUMERATE | ||
| 1157 | Enumerator: | ||
| 1158 | Attrs: 3 | ||
| 1159 | Value: 0 | ||
| 1160 | Name: eBoolean | ||
| 1161 | - Kind: LF_ENUMERATE | ||
| 1162 | Enumerator: | ||
| 1163 | Attrs: 3 | ||
| 1164 | Value: 1 | ||
| 1165 | Name: eInteger | ||
| 1166 | - Kind: LF_ENUMERATE | ||
| 1167 | Enumerator: | ||
| 1168 | Attrs: 3 | ||
| 1169 | Value: 2 | ||
| 1170 | Name: eFloat | ||
| 1171 | - Kind: LF_ENUMERATE | ||
| 1172 | Enumerator: | ||
| 1173 | Attrs: 3 | ||
| 1174 | Value: 3 | ||
| 1175 | Name: eDouble | ||
| 1176 | - Kind: LF_ENUM | ||
| 1177 | Enum: | ||
| 1178 | NumEnumerators: 4 | ||
| 1179 | Options: [ None, Nested, HasUniqueName ] | ||
| 1180 | FieldList: 4174 | ||
| 1181 | Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e' | ||
| 1182 | UniqueName: '.?AW4type_e@v1_alttypeAttribute@helper_attributes@__vc_attributes@@' | ||
| 1183 | UnderlyingType: 116 | ||
| 1184 | - Kind: LF_UDT_SRC_LINE | ||
| 1185 | UdtSourceLine: | ||
| 1186 | UDT: 4175 | ||
| 1187 | SourceFile: 4111 | ||
| 1188 | LineNumber: 38 | ||
| 1189 | - Kind: LF_ARGLIST | ||
| 1190 | ArgList: | ||
| 1191 | ArgIndices: [ 4175 ] | ||
| 1192 | - Kind: LF_POINTER | ||
| 1193 | Pointer: | ||
| 1194 | ReferentType: 4173 | ||
| 1195 | Attrs: 66572 | ||
| 1196 | - Kind: LF_MFUNCTION | ||
| 1197 | MemberFunction: | ||
| 1198 | ReturnType: 3 | ||
| 1199 | ClassType: 4173 | ||
| 1200 | ThisType: 4178 | ||
| 1201 | CallConv: NearC | ||
| 1202 | Options: [ None, Constructor ] | ||
| 1203 | ParameterCount: 1 | ||
| 1204 | ArgumentList: 4177 | ||
| 1205 | ThisPointerAdjustment: 0 | ||
| 1206 | - Kind: LF_FIELDLIST | ||
| 1207 | FieldList: | ||
| 1208 | - Kind: LF_NESTTYPE | ||
| 1209 | NestedType: | ||
| 1210 | Type: 4175 | ||
| 1211 | Name: type_e | ||
| 1212 | - Kind: LF_ONEMETHOD | ||
| 1213 | OneMethod: | ||
| 1214 | Type: 4179 | ||
| 1215 | Attrs: 3 | ||
| 1216 | VFTableOffset: -1 | ||
| 1217 | Name: v1_alttypeAttribute | ||
| 1218 | - Kind: LF_MEMBER | ||
| 1219 | DataMember: | ||
| 1220 | Attrs: 3 | ||
| 1221 | Type: 4175 | ||
| 1222 | FieldOffset: 0 | ||
| 1223 | Name: type | ||
| 1224 | - Kind: LF_STRUCTURE | ||
| 1225 | Class: | ||
| 1226 | MemberCount: 3 | ||
| 1227 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1228 | FieldList: 4180 | ||
| 1229 | Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute' | ||
| 1230 | UniqueName: '.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@' | ||
| 1231 | DerivationList: 0 | ||
| 1232 | VTableShape: 0 | ||
| 1233 | Size: 4 | ||
| 1234 | - Kind: LF_UDT_SRC_LINE | ||
| 1235 | UdtSourceLine: | ||
| 1236 | UDT: 4181 | ||
| 1237 | SourceFile: 4111 | ||
| 1238 | LineNumber: 37 | ||
| 1239 | - Kind: LF_STRUCTURE | ||
| 1240 | Class: | ||
| 1241 | MemberCount: 0 | ||
| 1242 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 1243 | FieldList: 0 | ||
| 1244 | Name: '__vc_attributes::event_sourceAttribute' | ||
| 1245 | UniqueName: '.?AUevent_sourceAttribute@__vc_attributes@@' | ||
| 1246 | DerivationList: 0 | ||
| 1247 | VTableShape: 0 | ||
| 1248 | Size: 0 | ||
| 1249 | - Kind: LF_FIELDLIST | ||
| 1250 | FieldList: | ||
| 1251 | - Kind: LF_ENUMERATE | ||
| 1252 | Enumerator: | ||
| 1253 | Attrs: 3 | ||
| 1254 | Value: 0 | ||
| 1255 | Name: native | ||
| 1256 | - Kind: LF_ENUMERATE | ||
| 1257 | Enumerator: | ||
| 1258 | Attrs: 3 | ||
| 1259 | Value: 1 | ||
| 1260 | Name: com | ||
| 1261 | - Kind: LF_ENUMERATE | ||
| 1262 | Enumerator: | ||
| 1263 | Attrs: 3 | ||
| 1264 | Value: 2 | ||
| 1265 | Name: managed | ||
| 1266 | - Kind: LF_ENUM | ||
| 1267 | Enum: | ||
| 1268 | NumEnumerators: 3 | ||
| 1269 | Options: [ None, Nested, HasUniqueName ] | ||
| 1270 | FieldList: 4184 | ||
| 1271 | Name: '__vc_attributes::event_sourceAttribute::type_e' | ||
| 1272 | UniqueName: '.?AW4type_e@event_sourceAttribute@__vc_attributes@@' | ||
| 1273 | UnderlyingType: 116 | ||
| 1274 | - Kind: LF_UDT_SRC_LINE | ||
| 1275 | UdtSourceLine: | ||
| 1276 | UDT: 4185 | ||
| 1277 | SourceFile: 4111 | ||
| 1278 | LineNumber: 1142 | ||
| 1279 | - Kind: LF_FIELDLIST | ||
| 1280 | FieldList: | ||
| 1281 | - Kind: LF_ENUMERATE | ||
| 1282 | Enumerator: | ||
| 1283 | Attrs: 3 | ||
| 1284 | Value: 0 | ||
| 1285 | Name: speed | ||
| 1286 | - Kind: LF_ENUMERATE | ||
| 1287 | Enumerator: | ||
| 1288 | Attrs: 3 | ||
| 1289 | Value: 1 | ||
| 1290 | Name: size | ||
| 1291 | - Kind: LF_ENUM | ||
| 1292 | Enum: | ||
| 1293 | NumEnumerators: 2 | ||
| 1294 | Options: [ None, Nested, HasUniqueName ] | ||
| 1295 | FieldList: 4187 | ||
| 1296 | Name: '__vc_attributes::event_sourceAttribute::optimize_e' | ||
| 1297 | UniqueName: '.?AW4optimize_e@event_sourceAttribute@__vc_attributes@@' | ||
| 1298 | UnderlyingType: 116 | ||
| 1299 | - Kind: LF_UDT_SRC_LINE | ||
| 1300 | UdtSourceLine: | ||
| 1301 | UDT: 4188 | ||
| 1302 | SourceFile: 4111 | ||
| 1303 | LineNumber: 1145 | ||
| 1304 | - Kind: LF_ARGLIST | ||
| 1305 | ArgList: | ||
| 1306 | ArgIndices: [ 4185 ] | ||
| 1307 | - Kind: LF_POINTER | ||
| 1308 | Pointer: | ||
| 1309 | ReferentType: 4183 | ||
| 1310 | Attrs: 66572 | ||
| 1311 | - Kind: LF_MFUNCTION | ||
| 1312 | MemberFunction: | ||
| 1313 | ReturnType: 3 | ||
| 1314 | ClassType: 4183 | ||
| 1315 | ThisType: 4191 | ||
| 1316 | CallConv: NearC | ||
| 1317 | Options: [ None, Constructor ] | ||
| 1318 | ParameterCount: 1 | ||
| 1319 | ArgumentList: 4190 | ||
| 1320 | ThisPointerAdjustment: 0 | ||
| 1321 | - Kind: LF_MFUNCTION | ||
| 1322 | MemberFunction: | ||
| 1323 | ReturnType: 3 | ||
| 1324 | ClassType: 4183 | ||
| 1325 | ThisType: 4191 | ||
| 1326 | CallConv: NearC | ||
| 1327 | Options: [ None, Constructor ] | ||
| 1328 | ParameterCount: 0 | ||
| 1329 | ArgumentList: 4105 | ||
| 1330 | ThisPointerAdjustment: 0 | ||
| 1331 | - Kind: LF_METHODLIST | ||
| 1332 | MethodOverloadList: | ||
| 1333 | Methods: | ||
| 1334 | - Type: 4192 | ||
| 1335 | Attrs: 3 | ||
| 1336 | VFTableOffset: -1 | ||
| 1337 | Name: '' | ||
| 1338 | - Type: 4193 | ||
| 1339 | Attrs: 3 | ||
| 1340 | VFTableOffset: -1 | ||
| 1341 | Name: '' | ||
| 1342 | - Kind: LF_FIELDLIST | ||
| 1343 | FieldList: | ||
| 1344 | - Kind: LF_NESTTYPE | ||
| 1345 | NestedType: | ||
| 1346 | Type: 4185 | ||
| 1347 | Name: type_e | ||
| 1348 | - Kind: LF_NESTTYPE | ||
| 1349 | NestedType: | ||
| 1350 | Type: 4188 | ||
| 1351 | Name: optimize_e | ||
| 1352 | - Kind: LF_METHOD | ||
| 1353 | OverloadedMethod: | ||
| 1354 | NumOverloads: 2 | ||
| 1355 | MethodList: 4194 | ||
| 1356 | Name: event_sourceAttribute | ||
| 1357 | - Kind: LF_MEMBER | ||
| 1358 | DataMember: | ||
| 1359 | Attrs: 3 | ||
| 1360 | Type: 4185 | ||
| 1361 | FieldOffset: 0 | ||
| 1362 | Name: type | ||
| 1363 | - Kind: LF_MEMBER | ||
| 1364 | DataMember: | ||
| 1365 | Attrs: 3 | ||
| 1366 | Type: 4188 | ||
| 1367 | FieldOffset: 4 | ||
| 1368 | Name: optimize | ||
| 1369 | - Kind: LF_MEMBER | ||
| 1370 | DataMember: | ||
| 1371 | Attrs: 3 | ||
| 1372 | Type: 48 | ||
| 1373 | FieldOffset: 8 | ||
| 1374 | Name: decorate | ||
| 1375 | - Kind: LF_STRUCTURE | ||
| 1376 | Class: | ||
| 1377 | MemberCount: 7 | ||
| 1378 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1379 | FieldList: 4195 | ||
| 1380 | Name: '__vc_attributes::event_sourceAttribute' | ||
| 1381 | UniqueName: '.?AUevent_sourceAttribute@__vc_attributes@@' | ||
| 1382 | DerivationList: 0 | ||
| 1383 | VTableShape: 0 | ||
| 1384 | Size: 12 | ||
| 1385 | - Kind: LF_UDT_SRC_LINE | ||
| 1386 | UdtSourceLine: | ||
| 1387 | UDT: 4196 | ||
| 1388 | SourceFile: 4111 | ||
| 1389 | LineNumber: 1141 | ||
| 1390 | - Kind: LF_STRING_ID | ||
| 1391 | StringId: | ||
| 1392 | Id: 0 | ||
| 1393 | String: 'C:\src\llvm-project\build' | ||
| 1394 | - Kind: LF_STRING_ID | ||
| 1395 | StringId: | ||
| 1396 | Id: 0 | ||
| 1397 | String: 'C:\PROGRA~2\MICROS~1\2017\PROFES~1\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\cl.exe' | ||
| 1398 | - Kind: LF_STRING_ID | ||
| 1399 | StringId: | ||
| 1400 | Id: 0 | ||
| 1401 | String: '-c -Z7 -MT -IC:\PROGRA~2\MICROS~1\2017\PROFES~1\VC\Tools\MSVC\14.11.25503\ATLMFC\include -IC:\PROGRA~2\MICROS~1\2017\PROFES~1\VC\Tools\MSVC\14.11.25503\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.16299.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.16299.0\' | ||
| 1402 | - Kind: LF_SUBSTR_LIST | ||
| 1403 | StringList: | ||
| 1404 | StringIndices: [ 4200 ] | ||
| 1405 | - Kind: LF_STRING_ID | ||
| 1406 | StringId: | ||
| 1407 | Id: 4201 | ||
| 1408 | String: 'shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.16299.0\um -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.16299.0\winrt -TP -X' | ||
| 1409 | - Kind: LF_STRING_ID | ||
| 1410 | StringId: | ||
| 1411 | Id: 0 | ||
| 1412 | String: t.cpp | ||
| 1413 | - Kind: LF_STRING_ID | ||
| 1414 | StringId: | ||
| 1415 | Id: 0 | ||
| 1416 | String: 'C:\src\llvm-project\build\vc140.pdb' | ||
| 1417 | - Kind: LF_BUILDINFO | ||
| 1418 | BuildInfo: | ||
| 1419 | ArgIndices: [ 4198, 4199, 4203, 4204, 4202 ] | ||
| 1420 | - Name: '.text$mn' | ||
| 1421 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 1422 | Alignment: 16 | ||
| 1423 | SectionData: 48894C240833C0C3CCCCCCCCCCCCCCCC4883EC38B904000000E8000000004889442420488B4424204883C438C3 | ||
| 1424 | Relocations: | ||
| 1425 | - VirtualAddress: 26 | ||
| 1426 | SymbolName: '??2@YAPEAX_K@Z' | ||
| 1427 | Type: IMAGE_REL_AMD64_REL32 | ||
| 1428 | - Name: .xdata | ||
| 1429 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | ||
| 1430 | Alignment: 4 | ||
| 1431 | SectionData: '0104010004620000' | ||
| 1432 | - Name: .pdata | ||
| 1433 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | ||
| 1434 | Alignment: 4 | ||
| 1435 | SectionData: 000000001D00000000000000 | ||
| 1436 | Relocations: | ||
| 1437 | - VirtualAddress: 0 | ||
| 1438 | SymbolName: '$LN3' | ||
| 1439 | Type: IMAGE_REL_AMD64_ADDR32NB | ||
| 1440 | - VirtualAddress: 4 | ||
| 1441 | SymbolName: '$LN3' | ||
| 1442 | Type: IMAGE_REL_AMD64_ADDR32NB | ||
| 1443 | - VirtualAddress: 8 | ||
| 1444 | SymbolName: '$unwind$f' | ||
| 1445 | Type: IMAGE_REL_AMD64_ADDR32NB | ||
| 1446 | symbols: | ||
| 1447 | - Name: '@comp.id' | ||
| 1448 | Value: 17130404 | ||
| 1449 | SectionNumber: -1 | ||
| 1450 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1451 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1452 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1453 | - Name: '@feat.00' | ||
| 1454 | Value: 2147484048 | ||
| 1455 | SectionNumber: -1 | ||
| 1456 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1457 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1458 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1459 | - Name: .drectve | ||
| 1460 | Value: 0 | ||
| 1461 | SectionNumber: 1 | ||
| 1462 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1463 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1464 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1465 | SectionDefinition: | ||
| 1466 | Length: 57 | ||
| 1467 | NumberOfRelocations: 0 | ||
| 1468 | NumberOfLinenumbers: 0 | ||
| 1469 | CheckSum: 1455566745 | ||
| 1470 | Number: 0 | ||
| 1471 | - Name: '.debug$S' | ||
| 1472 | Value: 0 | ||
| 1473 | SectionNumber: 2 | ||
| 1474 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1475 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1476 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1477 | SectionDefinition: | ||
| 1478 | Length: 1364 | ||
| 1479 | NumberOfRelocations: 10 | ||
| 1480 | NumberOfLinenumbers: 0 | ||
| 1481 | CheckSum: 0 | ||
| 1482 | Number: 0 | ||
| 1483 | - Name: '.debug$T' | ||
| 1484 | Value: 0 | ||
| 1485 | SectionNumber: 3 | ||
| 1486 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1487 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1488 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1489 | SectionDefinition: | ||
| 1490 | Length: 6560 | ||
| 1491 | NumberOfRelocations: 0 | ||
| 1492 | NumberOfLinenumbers: 0 | ||
| 1493 | CheckSum: 0 | ||
| 1494 | Number: 0 | ||
| 1495 | - Name: '.text$mn' | ||
| 1496 | Value: 0 | ||
| 1497 | SectionNumber: 4 | ||
| 1498 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1499 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1500 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1501 | SectionDefinition: | ||
| 1502 | Length: 45 | ||
| 1503 | NumberOfRelocations: 1 | ||
| 1504 | NumberOfLinenumbers: 0 | ||
| 1505 | CheckSum: 1509507051 | ||
| 1506 | Number: 0 | ||
| 1507 | - Name: '??2@YAPEAX_K@Z' | ||
| 1508 | Value: 0 | ||
| 1509 | SectionNumber: 4 | ||
| 1510 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1511 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 1512 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 1513 | - Name: f | ||
| 1514 | Value: 16 | ||
| 1515 | SectionNumber: 4 | ||
| 1516 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1517 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 1518 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 1519 | - Name: '$LN3' | ||
| 1520 | Value: 16 | ||
| 1521 | SectionNumber: 4 | ||
| 1522 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1523 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1524 | StorageClass: IMAGE_SYM_CLASS_LABEL | ||
| 1525 | - Name: .xdata | ||
| 1526 | Value: 0 | ||
| 1527 | SectionNumber: 5 | ||
| 1528 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1529 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1530 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1531 | SectionDefinition: | ||
| 1532 | Length: 8 | ||
| 1533 | NumberOfRelocations: 0 | ||
| 1534 | NumberOfLinenumbers: 0 | ||
| 1535 | CheckSum: 931692337 | ||
| 1536 | Number: 0 | ||
| 1537 | - Name: '$unwind$f' | ||
| 1538 | Value: 0 | ||
| 1539 | SectionNumber: 5 | ||
| 1540 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1541 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1542 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1543 | - Name: .pdata | ||
| 1544 | Value: 0 | ||
| 1545 | SectionNumber: 6 | ||
| 1546 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1547 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1548 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1549 | SectionDefinition: | ||
| 1550 | Length: 12 | ||
| 1551 | NumberOfRelocations: 3 | ||
| 1552 | NumberOfLinenumbers: 0 | ||
| 1553 | CheckSum: 3887998202 | ||
| 1554 | Number: 0 | ||
| 1555 | - Name: '$pdata$f' | ||
| 1556 | Value: 0 | ||
| 1557 | SectionNumber: 6 | ||
| 1558 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 1559 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 1560 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 1561 | ... | ||
deps/lld/test/COFF/pdb-import-gc.yaml+12-8| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # RUN: yaml2obj %s -o %t.obj | 1 | # RUN: yaml2obj %s -o %t.obj |
| 2 | # RUN: lld-link %t.obj %S/Inputs/pdb-import-gc.lib -debug -entry:main \ | 2 | # RUN: lld-link %t.obj %S/Inputs/pdb-import-gc.lib -debug -entry:main \ |
| 3 | # RUN: -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb | 3 | # RUN: -nodefaultlib -opt:ref -out:%t.exe -pdb:%t.pdb |
| 4 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | 4 | # RUN: llvm-pdbutil dump -globals -symbols %t.pdb | FileCheck %s |
| 5 | 5 | ||
| 6 | # This tests the case where an __imp_ chunk is discarded by linker GC. The debug | 6 | # This tests the case where an __imp_ chunk is discarded by linker GC. The debug |
| 7 | # info may refer to the __imp_ symbol still. | 7 | # info may refer to the __imp_ symbol still. |
| ... | @@ -11,12 +11,16 @@ | ... | @@ -11,12 +11,16 @@ |
| 11 | # int discarded() { return __wc_mb_cur; } | 11 | # int discarded() { return __wc_mb_cur; } |
| 12 | # int main() { return g2; } | 12 | # int main() { return g2; } |
| 13 | 13 | ||
| 14 | # CHECK: Symbols | 14 | # CHECK: Global Symbols |
| 15 | # CHECK: ============================================================ | 15 | # CHECK-NEXT: ============================================================ |
| 16 | # CHECK: Mod 0000 | `{{.*}}pdb-import-gc.yaml.tmp.obj`: | 16 | # CHECK-NEXT: Records |
| 17 | # CHECK: 4 | S_GDATA32 [size = 32] `__imp___wc_mb_cur` | 17 | # CHECK-NEXT: 20 | S_GDATA32 [size = 32] `__imp___wc_mb_cur` |
| 18 | # CHECK-NEXT: type = 0x0070 (char), addr = 0000:0000 | 18 | # CHECK-NEXT: type = 0x0070 (char), addr = 0000:0000 |
| 19 | # CHECK: Mod 0001 | `* Linker *`: | 19 | |
| 20 | # CHECK: Symbols | ||
| 21 | # CHECK-NEXT: ============================================================ | ||
| 22 | # CHECK-NEXT: Mod 0000 | `{{.*}}pdb-import-gc.yaml.tmp.obj`: | ||
| 23 | # CHECK-NEXT: Mod 0001 | `* Linker *`: | ||
| 20 | 24 | ||
| 21 | --- !COFF | 25 | --- !COFF |
| 22 | header: | 26 | header: |
deps/lld/test/COFF/pdb-invalid-func-type.yaml+1-1| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | 7 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s |
| 8 | 8 | ||
| 9 | # CHECK: Mod 0000 | `{{.*}}pdb-invalid-func-type.yaml.tmp.obj`: | 9 | # CHECK: Mod 0000 | `{{.*}}pdb-invalid-func-type.yaml.tmp.obj`: |
| 10 | # CHECK: 4 | S_GPROC32_ID [size = 44] `main` | 10 | # CHECK: 4 | S_GPROC32 [size = 44] `main` |
| 11 | # CHECK: parent = 0, end = 80, addr = 0001:0000, code size = 3 | 11 | # CHECK: parent = 0, end = 80, addr = 0001:0000, code size = 3 |
| 12 | # CHECK: 48 | S_FRAMEPROC [size = 32] | 12 | # CHECK: 48 | S_FRAMEPROC [size = 32] |
| 13 | # CHECK: 80 | S_END [size = 4] | 13 | # CHECK: 80 | S_END [size = 4] |
deps/lld/test/COFF/pdb-lib.s+3-3| ... | @@ -11,15 +11,15 @@ | ... | @@ -11,15 +11,15 @@ |
| 11 | 11 | ||
| 12 | # CHECK: Modules | 12 | # CHECK: Modules |
| 13 | # CHECK-NEXT: ============================================================ | 13 | # CHECK-NEXT: ============================================================ |
| 14 | # CHECK-NEXT: Mod 0000 | Name: `{{.*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: 9, # files: 0, has ec info: false | 16 | # CHECK-NEXT: debug stream: 9, # 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 | Name: `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: 10, # files: 0, has ec info: false | 20 | # CHECK-NEXT: debug stream: 10, # 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 | Name: `* Linker *`: | 22 | # CHECK-NEXT: Mod 0002 | `* Linker *`: |
| 23 | # CHECK-NEXT: Obj: ``: | 23 | # CHECK-NEXT: Obj: ``: |
| 24 | # CHECK-NEXT: debug stream: 11, # files: 0, has ec info: false | 24 | # CHECK-NEXT: debug stream: 11, # 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 `` |
deps/lld/test/COFF/pdb-linker-module.test+22-16| ... | @@ -1,18 +1,24 @@ | ... | @@ -1,18 +1,24 @@ |
| 1 | RUN: lld-link /debug /pdb:%t.pdb /nodefaultlib /entry:main %S/Inputs/pdb-diff.obj | 1 | RUN: lld-link /debug /pdb:%t.pdb /nodefaultlib /entry:main %S/Inputs/pdb-diff.obj |
| 2 | RUN: llvm-pdbutil dump -modules -symbols %t.pdb | FileCheck %s | 2 | RUN: llvm-pdbutil dump -modules %t.pdb | FileCheck --check-prefix=MODS %s |
| 3 | RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck --check-prefix=SYMS %s | ||
| 3 | 4 | ||
| 4 | CHECK: Mod 0001 | `* Linker *`: | 5 | MODS: Mod 0001 | `* Linker *` |
| 5 | CHECK-NEXT: 4 | S_OBJNAME [size = 20] sig=0, `* Linker *` | 6 | MODS-NEXT: Obj: ``: |
| 6 | CHECK-NEXT: 24 | S_COMPILE3 [size = 40] | 7 | MODS-NEXT: debug stream: 10, # files: 0, has ec info: false |
| 7 | CHECK-NEXT: machine = intel 80386, Ver = LLVM Linker, language = link | 8 | MODS-NEXT: pdb file ni: 1 `{{.*}}pdb-linker-module.test.tmp.pdb`, src file ni: 0 `` |
| 8 | CHECK-NEXT: frontend = 0.0.0.0, backend = 0.0.0.0 | 9 | |
| 9 | CHECK-NEXT: flags = none | 10 | SYMS: Mod 0001 | `* Linker *` |
| 10 | CHECK-NEXT: 64 | S_ENVBLOCK | 11 | SYMS-NEXT: 4 | S_OBJNAME [size = 20] sig=0, `* Linker *` |
| 11 | CHECK-NEXT: - cwd | 12 | SYMS-NEXT: 24 | S_COMPILE3 [size = 40] |
| 12 | CHECK-NEXT: - | 13 | SYMS-NEXT: machine = intel 80386, Ver = LLVM Linker, language = link |
| 13 | CHECK-NEXT: - exe | 14 | SYMS-NEXT: frontend = 0.0.0.0, backend = 14.10.25019.0 |
| 14 | CHECK-NEXT: - {{.*}}lld-link | 15 | SYMS-NEXT: flags = none |
| 15 | CHECK-NEXT: - pdb | 16 | SYMS-NEXT: 64 | S_ENVBLOCK |
| 16 | CHECK-NEXT: - {{.*}}pdb-linker-module{{.*}}pdb | 17 | SYMS-NEXT: - cwd |
| 17 | CHECK-NEXT: - cmd | 18 | SYMS-NEXT: - |
| 18 | CHECK-NEXT: - /debug /pdb:{{.*}}pdb-linker-module{{.*}}pdb /nodefaultlib /entry:main {{.*}}pdb-diff.obj | 19 | SYMS-NEXT: - exe |
| 20 | SYMS-NEXT: - {{.*}}lld-link | ||
| 21 | SYMS-NEXT: - pdb | ||
| 22 | SYMS-NEXT: - {{.*}}pdb-linker-module{{.*}}pdb | ||
| 23 | SYMS-NEXT: - cmd | ||
| 24 | SYMS-NEXT: - /debug /pdb:{{.*}}pdb-linker-module{{.*}}pdb /nodefaultlib /entry:main {{.*}}pdb-diff.obj |
deps/lld/test/COFF/pdb-none.test+2-1| ... | @@ -1,12 +1,13 @@ | ... | @@ -1,12 +1,13 @@ |
| 1 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj | 1 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj |
| 2 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj | 2 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj |
| 3 | # RUN: rm -f %t.pdb %t.dll | ||
| 3 | # RUN: lld-link /debug /debugtype:pdata /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ | 4 | # RUN: lld-link /debug /debugtype:pdata /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ |
| 4 | # RUN: %t1.obj %t2.obj | 5 | # RUN: %t1.obj %t2.obj |
| 5 | 6 | ||
| 6 | # RUN: llvm-pdbutil pdb2yaml -pdb-stream %t.pdb | FileCheck %s | 7 | # RUN: llvm-pdbutil pdb2yaml -pdb-stream %t.pdb | FileCheck %s |
| 7 | 8 | ||
| 8 | # CHECK: PdbStream: | 9 | # CHECK: PdbStream: |
| 9 | # CHECK-NEXT: Age: 0 | 10 | # CHECK-NEXT: Age: 1 |
| 10 | # CHECK-NEXT: Guid: | 11 | # CHECK-NEXT: Guid: |
| 11 | # CHECK-NEXT: Signature: | 12 | # CHECK-NEXT: Signature: |
| 12 | # CHECK-NEXT: Features: [ VC140 ] | 13 | # CHECK-NEXT: Features: [ VC140 ] |
deps/lld/test/COFF/pdb-options.test+1-1| ... | @@ -18,4 +18,4 @@ | ... | @@ -18,4 +18,4 @@ |
| 18 | # RUN: lld-link /DEBUG /entry:main /nodefaultlib %t1.obj %t2.obj | 18 | # RUN: lld-link /DEBUG /entry:main /nodefaultlib %t1.obj %t2.obj |
| 19 | # RUN: ls %t1.pdb | 19 | # RUN: ls %t1.pdb |
| 20 | # RUN: rm %t* | 20 | # RUN: rm %t* |
| 21 | # RUN: cd %T/.. | 21 | # RUN: cd %T/.. |
deps/lld/test/COFF/pdb-procid-remapping.test created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj | ||
| 2 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj | ||
| 3 | # RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ | ||
| 4 | # RUN: %t1.obj %t2.obj | ||
| 5 | |||
| 6 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | ||
| 7 | |||
| 8 | CHECK: Symbols | ||
| 9 | CHECK-NEXT: ============================================================ | ||
| 10 | CHECK-LABEL: Mod 0000 | | ||
| 11 | CHECK: 92 | S_GPROC32 [size = 44] `main` | ||
| 12 | CHECK-NEXT: parent = 0, end = 168, addr = 0002:0000, code size = 14 | ||
| 13 | CHECK-NEXT: type = `0x1004 (int (<no type>))`, debug start = 4, debug end = 9, flags = none | ||
| 14 | CHECK-NEXT: 136 | S_FRAMEPROC [size = 32] | ||
| 15 | CHECK-NEXT: size = 40, padding size = 0, offset to padding = 0 | ||
| 16 | CHECK-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000 | ||
| 17 | CHECK-NEXT: flags = has async eh | opt speed | ||
| 18 | CHECK-NEXT: 168 | S_END [size = 4] | ||
| 19 | CHECK-LABEL: Mod 0001 | | ||
| 20 | CHECK: 92 | S_GPROC32 [size = 44] `foo` | ||
| 21 | CHECK-NEXT: parent = 0, end = 168, addr = 0002:0016, code size = 6 | ||
| 22 | CHECK-NEXT: type = `0x1001 (int ())`, debug start = 0, debug end = 5, flags = none | ||
| 23 | CHECK-NEXT: 136 | S_FRAMEPROC [size = 32] | ||
| 24 | CHECK-NEXT: size = 0, padding size = 0, offset to padding = 0 | ||
| 25 | CHECK-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000 | ||
| 26 | CHECK-NEXT: flags = has async eh | opt speed | ||
| 27 | CHECK-NEXT: 168 | S_END [size = 4] | ||
| 28 | CHECK-LABEL: Mod 0002 | | ||
| 29 | CHECK: 4 | S_OBJNAME [size = 20] sig=0, `* Linker *` | ||
deps/lld/test/COFF/pdb-publics-import.test created+42| ... | @@ -0,0 +1,42 @@ | ||
| 1 | Make a DLL that exports a few functions, then make a DLL with PDBs that imports | ||
| 2 | them. Check that the __imp_ pointer and the generated thunks appear in the | ||
| 3 | publics stream. | ||
| 4 | |||
| 5 | RUN: yaml2obj < %p/Inputs/export.yaml > %t1.obj | ||
| 6 | RUN: lld-link /out:%t1.dll /dll %t1.obj /implib:%t1.lib \ | ||
| 7 | RUN: /export:exportfn1 /export:exportfn2 | ||
| 8 | RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj | ||
| 9 | RUN: lld-link /out:%t2.exe /pdb:%t2.pdb /debug /entry:main %t2.obj %t1.lib | ||
| 10 | RUN: llvm-pdbutil dump %t2.pdb -publics -section-contribs | FileCheck %s | ||
| 11 | |||
| 12 | CHECK: Public Symbols | ||
| 13 | CHECK-NEXT: ============================================================ | ||
| 14 | CHECK-NEXT: Records | ||
| 15 | CHECK-NEXT: 112 | S_PUB32 [size = 20] `main` | ||
| 16 | CHECK-NEXT: flags = function, addr = 0001:0000 | ||
| 17 | CHECK-NEXT: 64 | S_PUB32 [size = 24] `exportfn1` | ||
| 18 | CHECK-NEXT: flags = function, addr = 0001:0016 | ||
| 19 | CHECK-NEXT: 88 | S_PUB32 [size = 24] `exportfn2` | ||
| 20 | CHECK-NEXT: flags = function, addr = 0001:0032 | ||
| 21 | CHECK-NEXT: 32 | S_PUB32 [size = 32] `__imp_exportfn2` | ||
| 22 | CHECK-NEXT: flags = none, addr = 0003:0072 | ||
| 23 | CHECK-NEXT: 0 | S_PUB32 [size = 32] `__imp_exportfn1` | ||
| 24 | CHECK-NEXT: flags = none, addr = 0003:0064 | ||
| 25 | |||
| 26 | CHECK: Section Contributions | ||
| 27 | CHECK-NEXT: ============================================================ | ||
| 28 | main | ||
| 29 | CHECK-NEXT: SC[.text] | mod = 0, 0001:0000, size = 8, data crc = 0, reloc crc = 0 | ||
| 30 | CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_EXECUTE | | ||
| 31 | CHECK-NEXT: IMAGE_SCN_MEM_READ | ||
| 32 | exportfn1 thunk | ||
| 33 | CHECK-NEXT: SC[.text] | mod = 1, 0001:0016, size = 6, data crc = 0, reloc crc = 0 | ||
| 34 | CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | ||
| 35 | exportfn2 thunk | ||
| 36 | CHECK-NEXT: SC[.text] | mod = 1, 0001:0032, size = 6, data crc = 0, reloc crc = 0 | ||
| 37 | CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | ||
| 38 | .rdata debug directory data chunks | ||
| 39 | CHECK-NEXT: SC[.rdata] | mod = 1, 0002:0000, size = 28, data crc = 0, reloc crc = 0 | ||
| 40 | CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | ||
| 41 | CHECK-NEXT: SC[.rdata] | mod = 1, 0002:0028, size = {{.*}}, data crc = 0, reloc crc = 0 | ||
| 42 | CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | ||
deps/lld/test/COFF/pdb-safeseh.yaml+6-5| ... | @@ -1,16 +1,17 @@ | ... | @@ -1,16 +1,17 @@ |
| 1 | # RUN: yaml2obj %s -o %t.obj | 1 | # RUN: yaml2obj %s -o %t.obj |
| 2 | # RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj | 2 | # RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj |
| 3 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | 3 | # RUN: llvm-pdbutil dump -globals %t.pdb | FileCheck %s |
| 4 | 4 | ||
| 5 | # There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in | 5 | # There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in |
| 6 | # it in this debug info. This is similar to the relocations in the loadcfg.obj | 6 | # it in this debug info. This is similar to the relocations in the loadcfg.obj |
| 7 | # file in the MSVC CRT. We need to make sure that our relocation logic matches | 7 | # file in the MSVC CRT. We need to make sure that our relocation logic matches |
| 8 | # MSVC's for these absolute, linker-provided symbols. | 8 | # MSVC's for these absolute, linker-provided symbols. |
| 9 | 9 | ||
| 10 | # CHECK: Mod 0000 | | 10 | # CHECK: Global Symbols |
| 11 | # CHECK-NEXT: 4 | S_GDATA32 [size = 40] `___safe_se_handler_table` | 11 | # CHECK-NEXT: ============================================================ |
| 12 | # CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 | 12 | # CHECK-NEXT: Records |
| 13 | # CHECK-NEXT: Mod 0001 | `* Linker *`: | 13 | # CHECK-NEXT: 20 | S_GDATA32 [size = 40] `___safe_se_handler_table` |
| 14 | # CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 | ||
| 14 | 15 | ||
| 15 | --- !COFF | 16 | --- !COFF |
| 16 | header: | 17 | header: |
deps/lld/test/COFF/pdb-same-name.test created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | # RUN: rm -rf %t1 %t2 | ||
| 2 | # RUN: mkdir %t1 %t2 | ||
| 3 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1/foo.obj | ||
| 4 | # RUN: llvm-ar cru %t1/foo.lib %t1/foo.obj | ||
| 5 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2/foo.obj | ||
| 6 | # RUN: llvm-ar cru %t2/foo.lib %t2/foo.obj | ||
| 7 | |||
| 8 | # RUN: rm -f %t.dll %t.pdb | ||
| 9 | # RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ | ||
| 10 | # RUN: %t1/foo.lib %t2/foo.lib | ||
| 11 | |||
| 12 | # RUN: llvm-pdbutil dump -modules %t.pdb | FileCheck -check-prefix RAW %s | ||
| 13 | |||
| 14 | RAW: Modules | ||
| 15 | RAW-NEXT: ============================================================ | ||
| 16 | RAW-NEXT: Mod 0000 | `foo.obj`: | ||
| 17 | RAW-NEXT: Obj: `{{.*}}1\foo.lib`: | ||
| 18 | RAW-NEXT: debug stream: 9, # files: 1, has ec info: false | ||
| 19 | RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` | ||
| 20 | RAW-NEXT: Mod 0001 | `foo.obj`: | ||
| 21 | RAW-NEXT: Obj: `{{.*}}2\foo.lib`: | ||
| 22 | RAW-NEXT: debug stream: 10, # files: 1, has ec info: false | ||
| 23 | RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` | ||
deps/lld/test/COFF/pdb-scopes.test+3-3| ... | @@ -34,12 +34,12 @@ RUN: lld-link %t-a.obj %t-b.obj -debug -entry:main -nodefaultlib -out:%t.exe -pd | ... | @@ -34,12 +34,12 @@ RUN: lld-link %t-a.obj %t-b.obj -debug -entry:main -nodefaultlib -out:%t.exe -pd |
| 34 | RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | 34 | RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s |
| 35 | 35 | ||
| 36 | CHECK-LABEL: Mod 0000 | `{{.*}}pdb-scopes.test.tmp-a.obj`: | 36 | CHECK-LABEL: Mod 0000 | `{{.*}}pdb-scopes.test.tmp-a.obj`: |
| 37 | CHECK: 104 | S_GPROC32_ID [size = 44] `g` | 37 | CHECK: 104 | S_GPROC32 [size = 44] `g` |
| 38 | CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 5 | 38 | CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 5 |
| 39 | CHECK: debug start = 4, debug end = 4, flags = none | 39 | CHECK: debug start = 4, debug end = 4, flags = none |
| 40 | CHECK: 180 | S_REGREL32 [size = 16] `x` | 40 | CHECK: 180 | S_REGREL32 [size = 16] `x` |
| 41 | CHECK: 196 | S_END [size = 4] | 41 | CHECK: 196 | S_END [size = 4] |
| 42 | CHECK: 200 | S_GPROC32_ID [size = 44] `main` | 42 | CHECK: 200 | S_GPROC32 [size = 44] `main` |
| 43 | CHECK: parent = 0, end = 384, addr = 0002:0016, code size = 58 | 43 | CHECK: parent = 0, end = 384, addr = 0002:0016, code size = 58 |
| 44 | CHECK: debug start = 8, debug end = 53, flags = none | 44 | CHECK: debug start = 8, debug end = 53, flags = none |
| 45 | CHECK: 276 | S_REGREL32 [size = 20] `argc` | 45 | CHECK: 276 | S_REGREL32 [size = 20] `argc` |
| ... | @@ -56,7 +56,7 @@ CHECK: 380 | S_END [size = 4] | ... | @@ -56,7 +56,7 @@ CHECK: 380 | S_END [size = 4] |
| 56 | CHECK: 384 | S_END [size = 4] | 56 | CHECK: 384 | S_END [size = 4] |
| 57 | 57 | ||
| 58 | CHECK-LABEL: Mod 0001 | `{{.*}}pdb-scopes.test.tmp-b.obj`: | 58 | CHECK-LABEL: Mod 0001 | `{{.*}}pdb-scopes.test.tmp-b.obj`: |
| 59 | CHECK: 104 | S_GPROC32_ID [size = 44] `f` | 59 | CHECK: 104 | S_GPROC32 [size = 44] `f` |
| 60 | CHECK: parent = 0, end = 284, addr = 0002:0080, code size = 62 | 60 | CHECK: parent = 0, end = 284, addr = 0002:0080, code size = 62 |
| 61 | CHECK: debug start = 8, debug end = 57, flags = none | 61 | CHECK: debug start = 8, debug end = 57, flags = none |
| 62 | CHECK: 180 | S_REGREL32 [size = 16] `x` | 62 | CHECK: 180 | S_REGREL32 [size = 16] `x` |
deps/lld/test/COFF/pdb-secrel-absolute.yaml+6-5| ... | @@ -1,16 +1,17 @@ | ... | @@ -1,16 +1,17 @@ |
| 1 | # RUN: yaml2obj %s -o %t.obj | 1 | # RUN: yaml2obj %s -o %t.obj |
| 2 | # RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj | 2 | # RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj |
| 3 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | 3 | # RUN: llvm-pdbutil dump -globals %t.pdb | FileCheck %s |
| 4 | 4 | ||
| 5 | # There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in | 5 | # There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in |
| 6 | # it in this debug info. This is similar to the relocations in the loadcfg.obj | 6 | # it in this debug info. This is similar to the relocations in the loadcfg.obj |
| 7 | # file in the MSVC CRT. We need to make sure that our relocation logic matches | 7 | # file in the MSVC CRT. We need to make sure that our relocation logic matches |
| 8 | # MSVC's for these absolute, linker-provided symbols. | 8 | # MSVC's for these absolute, linker-provided symbols. |
| 9 | 9 | ||
| 10 | # CHECK: Mod 0000 | | 10 | # CHECK: Global Symbols |
| 11 | # CHECK-NEXT: 4 | S_GDATA32 [size = 36] `__guard_fids_table` | 11 | # CHECK-NEXT: ============================================================ |
| 12 | # CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 | 12 | # CHECK-NEXT: Records |
| 13 | # CHECK-NEXT: Mod 0001 | `* Linker *`: | 13 | # CHECK-NEXT: 20 | S_GDATA32 [size = 36] `__guard_fids_table` |
| 14 | # CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 | ||
| 14 | 15 | ||
| 15 | --- !COFF | 16 | --- !COFF |
| 16 | header: | 17 | header: |
deps/lld/test/COFF/pdb-source-lines.test+18-17| ... | @@ -19,10 +19,11 @@ $ cl -c -Z7 pdb_lines*.c | ... | @@ -19,10 +19,11 @@ $ cl -c -Z7 pdb_lines*.c |
| 19 | 19 | ||
| 20 | RUN: yaml2obj %S/Inputs/pdb_lines_1.yaml -o %t.pdb_lines_1.obj | 20 | RUN: yaml2obj %S/Inputs/pdb_lines_1.yaml -o %t.pdb_lines_1.obj |
| 21 | RUN: yaml2obj %S/Inputs/pdb_lines_2.yaml -o %t.pdb_lines_2.obj | 21 | RUN: yaml2obj %S/Inputs/pdb_lines_2.yaml -o %t.pdb_lines_2.obj |
| 22 | RUN: rm -f %t.exe %t.pdb | ||
| 22 | RUN: lld-link -debug -entry:main -nodefaultlib -out:%t.exe -pdb:%t.pdb %t.pdb_lines_1.obj %t.pdb_lines_2.obj | 23 | RUN: lld-link -debug -entry:main -nodefaultlib -out:%t.exe -pdb:%t.pdb %t.pdb_lines_1.obj %t.pdb_lines_2.obj |
| 23 | RUN: llvm-pdbutil pdb2yaml -modules -module-files -subsections=lines,fc %t.pdb | FileCheck %s | 24 | RUN: llvm-pdbutil pdb2yaml -modules -module-files -subsections=lines,fc %t.pdb | FileCheck %s |
| 24 | 25 | ||
| 25 | CHECK-LABEL: DbiStream: | 26 | CHECK-LABEL: DbiStream: |
| 26 | CHECK-NEXT: VerHeader: V70 | 27 | CHECK-NEXT: VerHeader: V70 |
| 27 | CHECK-NEXT: Age: 1 | 28 | CHECK-NEXT: Age: 1 |
| 28 | CHECK-NEXT: BuildNumber: 0 | 29 | CHECK-NEXT: BuildNumber: 0 |
| ... | @@ -30,22 +31,22 @@ CHECK-NEXT: PdbDllVersion: 0 | ... | @@ -30,22 +31,22 @@ CHECK-NEXT: PdbDllVersion: 0 |
| 30 | CHECK-NEXT: PdbDllRbld: 0 | 31 | CHECK-NEXT: PdbDllRbld: 0 |
| 31 | CHECK-NEXT: Flags: 0 | 32 | CHECK-NEXT: Flags: 0 |
| 32 | CHECK-NEXT: MachineType: x86 | 33 | CHECK-NEXT: MachineType: x86 |
| 33 | CHECK-NEXT: Modules: | 34 | CHECK-NEXT: Modules: |
| 34 | 35 | ||
| 35 | CHECK-LABEL: - Module: {{.*}}pdb_lines_1.obj | 36 | CHECK-LABEL: - Module: {{.*}}pdb_lines_1.obj |
| 36 | CHECK-NEXT: ObjFile: {{.*}}pdb_lines_1.obj | 37 | CHECK-NEXT: ObjFile: {{.*}}pdb_lines_1.obj |
| 37 | CHECK-NEXT: SourceFiles: | 38 | CHECK-NEXT: SourceFiles: |
| 38 | CHECK-NEXT: - '{{.*}}pdb_lines_1.c' | 39 | CHECK-NEXT: - '{{.*}}pdb_lines_1.c' |
| 39 | CHECK-NEXT: - '{{.*}}foo.h' | 40 | CHECK-NEXT: - '{{.*}}foo.h' |
| 40 | CHECK-NEXT: Subsections: | 41 | CHECK-NEXT: Subsections: |
| 41 | CHECK-NEXT: - !Lines | 42 | CHECK-NEXT: - !Lines |
| 42 | CHECK-NEXT: CodeSize: 19 | 43 | CHECK-NEXT: CodeSize: 19 |
| 43 | CHECK-NEXT: Flags: [ ] | 44 | CHECK-NEXT: Flags: [ ] |
| 44 | CHECK-NEXT: RelocOffset: 0 | 45 | CHECK-NEXT: RelocOffset: 0 |
| 45 | CHECK-NEXT: RelocSegment: 2 | 46 | CHECK-NEXT: RelocSegment: 2 |
| 46 | CHECK-NEXT: Blocks: | 47 | CHECK-NEXT: Blocks: |
| 47 | CHECK-NEXT: - FileName: '{{.*}}pdb_lines_1.c' | 48 | CHECK-NEXT: - FileName: '{{.*}}pdb_lines_1.c' |
| 48 | CHECK-NEXT: Lines: | 49 | CHECK-NEXT: Lines: |
| 49 | CHECK-NEXT: - Offset: 0 | 50 | CHECK-NEXT: - Offset: 0 |
| 50 | CHECK-NEXT: LineStart: 2 | 51 | CHECK-NEXT: LineStart: 2 |
| 51 | CHECK-NEXT: IsStatement: true | 52 | CHECK-NEXT: IsStatement: true |
| ... | @@ -62,9 +63,9 @@ CHECK-NEXT: - Offset: 14 | ... | @@ -62,9 +63,9 @@ CHECK-NEXT: - Offset: 14 |
| 62 | CHECK-NEXT: LineStart: 5 | 63 | CHECK-NEXT: LineStart: 5 |
| 63 | CHECK-NEXT: IsStatement: true | 64 | CHECK-NEXT: IsStatement: true |
| 64 | CHECK-NEXT: EndDelta: 0 | 65 | CHECK-NEXT: EndDelta: 0 |
| 65 | CHECK-NEXT: Columns: | 66 | CHECK-NEXT: Columns: |
| 66 | CHECK-NEXT: - !FileChecksums | 67 | CHECK-NEXT: - !FileChecksums |
| 67 | CHECK-NEXT: Checksums: | 68 | CHECK-NEXT: Checksums: |
| 68 | CHECK-NEXT: - FileName: '{{.*}}pdb_lines_1.c' | 69 | CHECK-NEXT: - FileName: '{{.*}}pdb_lines_1.c' |
| 69 | CHECK-NEXT: Kind: MD5 | 70 | CHECK-NEXT: Kind: MD5 |
| 70 | CHECK-NEXT: Checksum: 4EB19DCD86C3BA2238A255C718572E7B | 71 | CHECK-NEXT: Checksum: 4EB19DCD86C3BA2238A255C718572E7B |
| ... | @@ -76,9 +77,9 @@ CHECK-NEXT: CodeSize: 14 | ... | @@ -76,9 +77,9 @@ CHECK-NEXT: CodeSize: 14 |
| 76 | CHECK-NEXT: Flags: [ ] | 77 | CHECK-NEXT: Flags: [ ] |
| 77 | CHECK-NEXT: RelocOffset: 32 | 78 | CHECK-NEXT: RelocOffset: 32 |
| 78 | CHECK-NEXT: RelocSegment: 2 | 79 | CHECK-NEXT: RelocSegment: 2 |
| 79 | CHECK-NEXT: Blocks: | 80 | CHECK-NEXT: Blocks: |
| 80 | CHECK-NEXT: - FileName: '{{.*}}foo.h' | 81 | CHECK-NEXT: - FileName: '{{.*}}foo.h' |
| 81 | CHECK-NEXT: Lines: | 82 | CHECK-NEXT: Lines: |
| 82 | CHECK-NEXT: - Offset: 0 | 83 | CHECK-NEXT: - Offset: 0 |
| 83 | CHECK-NEXT: LineStart: 2 | 84 | CHECK-NEXT: LineStart: 2 |
| 84 | CHECK-NEXT: IsStatement: true | 85 | CHECK-NEXT: IsStatement: true |
| ... | @@ -91,21 +92,21 @@ CHECK-NEXT: - Offset: 9 | ... | @@ -91,21 +92,21 @@ CHECK-NEXT: - Offset: 9 |
| 91 | CHECK-NEXT: LineStart: 4 | 92 | CHECK-NEXT: LineStart: 4 |
| 92 | CHECK-NEXT: IsStatement: true | 93 | CHECK-NEXT: IsStatement: true |
| 93 | CHECK-NEXT: EndDelta: 0 | 94 | CHECK-NEXT: EndDelta: 0 |
| 94 | CHECK-NEXT: Columns: | 95 | CHECK-NEXT: Columns: |
| 95 | 96 | ||
| 96 | CHECK-LABEL: - Module: {{.*}}pdb_lines_2.obj | 97 | CHECK-LABEL: - Module: {{.*}}pdb_lines_2.obj |
| 97 | CHECK-NEXT: ObjFile: {{.*}}pdb_lines_2.obj | 98 | CHECK-NEXT: ObjFile: {{.*}}pdb_lines_2.obj |
| 98 | CHECK-NEXT: SourceFiles: | 99 | CHECK-NEXT: SourceFiles: |
| 99 | CHECK-NEXT: - '{{.*}}pdb_lines_2.c' | 100 | CHECK-NEXT: - '{{.*}}pdb_lines_2.c' |
| 100 | CHECK-NEXT: Subsections: | 101 | CHECK-NEXT: Subsections: |
| 101 | CHECK-NEXT: - !Lines | 102 | CHECK-NEXT: - !Lines |
| 102 | CHECK-NEXT: CodeSize: 1 | 103 | CHECK-NEXT: CodeSize: 1 |
| 103 | CHECK-NEXT: Flags: [ ] | 104 | CHECK-NEXT: Flags: [ ] |
| 104 | CHECK-NEXT: RelocOffset: 48 | 105 | CHECK-NEXT: RelocOffset: 48 |
| 105 | CHECK-NEXT: RelocSegment: 2 | 106 | CHECK-NEXT: RelocSegment: 2 |
| 106 | CHECK-NEXT: Blocks: | 107 | CHECK-NEXT: Blocks: |
| 107 | CHECK-NEXT: - FileName: '{{.*}}pdb_lines_2.c' | 108 | CHECK-NEXT: - FileName: '{{.*}}pdb_lines_2.c' |
| 108 | CHECK-NEXT: Lines: | 109 | CHECK-NEXT: Lines: |
| 109 | CHECK-NEXT: - Offset: 0 | 110 | CHECK-NEXT: - Offset: 0 |
| 110 | CHECK-NEXT: LineStart: 1 | 111 | CHECK-NEXT: LineStart: 1 |
| 111 | CHECK-NEXT: IsStatement: true | 112 | CHECK-NEXT: IsStatement: true |
| ... | @@ -114,9 +115,9 @@ CHECK-NEXT: - Offset: 0 | ... | @@ -114,9 +115,9 @@ CHECK-NEXT: - Offset: 0 |
| 114 | CHECK-NEXT: LineStart: 2 | 115 | CHECK-NEXT: LineStart: 2 |
| 115 | CHECK-NEXT: IsStatement: true | 116 | CHECK-NEXT: IsStatement: true |
| 116 | CHECK-NEXT: EndDelta: 0 | 117 | CHECK-NEXT: EndDelta: 0 |
| 117 | CHECK-NEXT: Columns: | 118 | CHECK-NEXT: Columns: |
| 118 | CHECK-NEXT: - !FileChecksums | 119 | CHECK-NEXT: - !FileChecksums |
| 119 | CHECK-NEXT: Checksums: | 120 | CHECK-NEXT: Checksums: |
| 120 | CHECK-NEXT: - FileName: '{{.*}}pdb_lines_2.c' | 121 | CHECK-NEXT: - FileName: '{{.*}}pdb_lines_2.c' |
| 121 | CHECK-NEXT: Kind: MD5 | 122 | CHECK-NEXT: Kind: MD5 |
| 122 | CHECK-NEXT: Checksum: DF91CB3A2B8D917486574BB50CAC4CC7 | 123 | CHECK-NEXT: Checksum: DF91CB3A2B8D917486574BB50CAC4CC7 |
deps/lld/test/COFF/pdb-symbol-types.yaml+11-9| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | # RUN: yaml2obj %s -o %t.obj | 1 | # RUN: yaml2obj %s -o %t.obj |
| 2 | # RUN: lld-link %t.obj -nodefaultlib -entry:main -debug -out:%t.exe -pdb:%t.pdb | 2 | # RUN: lld-link %t.obj -nodefaultlib -entry:main -debug -out:%t.exe -pdb:%t.pdb |
| 3 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | 3 | # RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s |
| 4 | 4 | ||
| 5 | # To regenerate the object file: | 5 | # To regenerate the object file: |
| 6 | # $ cat symbol-types.c | 6 | # $ cat symbol-types.c |
| ... | @@ -13,6 +13,14 @@ | ... | @@ -13,6 +13,14 @@ |
| 13 | # Note that the type of 'global' goes from 0x1005 in the object file to 0x1004 | 13 | # Note that the type of 'global' goes from 0x1005 in the object file to 0x1004 |
| 14 | # in the PDB because the LF_FUNC_ID is moved to the id stream. | 14 | # in the PDB because the LF_FUNC_ID is moved to the id stream. |
| 15 | 15 | ||
| 16 | # CHECK-LABEL: Global Symbols | ||
| 17 | # CHECK-NEXT: ============================================================ | ||
| 18 | # CHECK-NEXT: Records | ||
| 19 | # CHECK-NEXT: 48 | S_PROCREF [size = 20] `main` | ||
| 20 | # CHECK-NEXT: module = 1, sum name = 0, offset = 116 | ||
| 21 | # CHECK-NEXT: 68 | S_GDATA32 [size = 28] `global_foo` | ||
| 22 | # CHECK-NEXT: type = 0x1004 (Foo), addr = 0001:0000 | ||
| 23 | |||
| 16 | # CHECK: Symbols | 24 | # CHECK: Symbols |
| 17 | # CHECK: ============================================================ | 25 | # CHECK: ============================================================ |
| 18 | # CHECK-LABEL: Mod 0000 | `{{.*}}pdb-symbol-types.yaml.tmp.obj`: | 26 | # CHECK-LABEL: Mod 0000 | `{{.*}}pdb-symbol-types.yaml.tmp.obj`: |
| ... | @@ -21,7 +29,7 @@ | ... | @@ -21,7 +29,7 @@ |
| 21 | # CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c | 29 | # CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c |
| 22 | # CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 | 30 | # CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 |
| 23 | # CHECK: flags = security checks | hot patchable | 31 | # CHECK: flags = security checks | hot patchable |
| 24 | # CHECK: 116 | S_GPROC32_ID [size = 44] `main` | 32 | # CHECK: 116 | S_GPROC32 [size = 44] `main` |
| 25 | # CHECK: parent = 0, end = 192, addr = 0002:0000, code size = 7 | 33 | # CHECK: parent = 0, end = 192, addr = 0002:0000, code size = 7 |
| 26 | # CHECK: debug start = 0, debug end = 6, flags = none | 34 | # CHECK: debug start = 0, debug end = 6, flags = none |
| 27 | # CHECK: 160 | S_FRAMEPROC [size = 32] | 35 | # CHECK: 160 | S_FRAMEPROC [size = 32] |
| ... | @@ -29,13 +37,7 @@ | ... | @@ -29,13 +37,7 @@ |
| 29 | # CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 | 37 | # CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 |
| 30 | # CHECK: flags = has async eh | opt speed | 38 | # CHECK: flags = has async eh | opt speed |
| 31 | # CHECK: 192 | S_END [size = 4] | 39 | # CHECK: 192 | S_END [size = 4] |
| 32 | # CHECK: 196 | S_GDATA32 [size = 28] `global_foo` | 40 | # CHECK: 196 | S_BUILDINFO [size = 8] BuildId = `0x100A` |
| 33 | # CHECK: type = 0x1004 (Foo), addr = 0001:0000 | ||
| 34 | # CHECK: 224 | S_UDT [size = 16] `UDT_Foo` | ||
| 35 | # CHECK: original type = 0x1004 | ||
| 36 | # CHECK: 240 | S_UDT [size = 12] `Foo` | ||
| 37 | # CHECK: original type = 0x1004 | ||
| 38 | # CHECK: 252 | S_BUILDINFO [size = 8] BuildId = `0x100A` | ||
| 39 | # CHECK-LABEL: Mod 0001 | `* Linker *`: | 41 | # CHECK-LABEL: Mod 0001 | `* Linker *`: |
| 40 | 42 | ||
| 41 | --- !COFF | 43 | --- !COFF |
deps/lld/test/COFF/pdb-thunk.yaml created+2747| ... | @@ -0,0 +1,2747 @@ | ||
| 1 | # RUN: yaml2obj %s -o %t.obj | ||
| 2 | # RUN: lld-link %t.obj -dll -debug -noentry -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb | ||
| 3 | # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s | ||
| 4 | |||
| 5 | # We used to skip vtable thunk symbol records, leading to symbol scope stack | ||
| 6 | # imbalances (PR35014). Test that they survive the object file into the PDB. | ||
| 7 | |||
| 8 | # This object generated from this C++ source: | ||
| 9 | # // t.cpp | ||
| 10 | # struct A { | ||
| 11 | # virtual int f(); | ||
| 12 | # }; | ||
| 13 | # struct B { | ||
| 14 | # virtual int f(); | ||
| 15 | # }; | ||
| 16 | # struct C : A, B { | ||
| 17 | # __declspec(dllexport) C(); | ||
| 18 | # int f() override; | ||
| 19 | # int c; | ||
| 20 | # }; | ||
| 21 | # int A::f() { return 0; } | ||
| 22 | # int B::f() { return 0; } | ||
| 23 | # int C::f() { return c; } | ||
| 24 | # C::C() : c(42) {} | ||
| 25 | |||
| 26 | # Compile as: | ||
| 27 | # $ cl -GR- -Z7 -c t.cpp | ||
| 28 | |||
| 29 | # CHECK: S_THUNK32 | ||
| 30 | # CHECK: S_END | ||
| 31 | |||
| 32 | --- !COFF | ||
| 33 | header: | ||
| 34 | Machine: IMAGE_FILE_MACHINE_AMD64 | ||
| 35 | Characteristics: [ ] | ||
| 36 | sections: | ||
| 37 | - Name: .drectve | ||
| 38 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 39 | Alignment: 1 | ||
| 40 | SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D455322202F4558504F52543A3F3F304340405145414140585A20 | ||
| 41 | - Name: '.debug$S' | ||
| 42 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 43 | Alignment: 1 | ||
| 44 | Subsections: | ||
| 45 | - !Symbols | ||
| 46 | Records: | ||
| 47 | - Kind: S_OBJNAME | ||
| 48 | ObjNameSym: | ||
| 49 | Signature: 0 | ||
| 50 | ObjectName: 'C:\src\llvm-project\build\t.obj' | ||
| 51 | - Kind: S_COMPILE3 | ||
| 52 | Compile3Sym: | ||
| 53 | Flags: [ SecurityChecks, HotPatch ] | ||
| 54 | Machine: X64 | ||
| 55 | FrontendMajor: 19 | ||
| 56 | FrontendMinor: 11 | ||
| 57 | FrontendBuild: 25508 | ||
| 58 | FrontendQFE: 2 | ||
| 59 | BackendMajor: 19 | ||
| 60 | BackendMinor: 11 | ||
| 61 | BackendBuild: 25508 | ||
| 62 | BackendQFE: 2 | ||
| 63 | Version: 'Microsoft (R) Optimizing Compiler' | ||
| 64 | - !Symbols | ||
| 65 | Records: | ||
| 66 | - Kind: S_GPROC32_ID | ||
| 67 | ProcSym: | ||
| 68 | CodeSize: 8 | ||
| 69 | DbgStart: 5 | ||
| 70 | DbgEnd: 7 | ||
| 71 | FunctionType: 4172 | ||
| 72 | Flags: [ ] | ||
| 73 | DisplayName: 'A::f' | ||
| 74 | - Kind: S_FRAMEPROC | ||
| 75 | FrameProcSym: | ||
| 76 | TotalFrameBytes: 0 | ||
| 77 | PaddingFrameBytes: 0 | ||
| 78 | OffsetToPadding: 0 | ||
| 79 | BytesOfCalleeSavedRegisters: 0 | ||
| 80 | OffsetOfExceptionHandler: 0 | ||
| 81 | SectionIdOfExceptionHandler: 0 | ||
| 82 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | ||
| 83 | - Kind: S_REGREL32 | ||
| 84 | RegRelativeSym: | ||
| 85 | Offset: 8 | ||
| 86 | Type: 4097 | ||
| 87 | Register: RSP | ||
| 88 | VarName: this | ||
| 89 | - Kind: S_PROC_ID_END | ||
| 90 | ScopeEndSym: | ||
| 91 | - !Lines | ||
| 92 | CodeSize: 8 | ||
| 93 | Flags: [ ] | ||
| 94 | RelocOffset: 0 | ||
| 95 | RelocSegment: 0 | ||
| 96 | Blocks: | ||
| 97 | - FileName: 'c:\src\llvm-project\build\t.cpp' | ||
| 98 | Lines: | ||
| 99 | - Offset: 0 | ||
| 100 | LineStart: 12 | ||
| 101 | IsStatement: true | ||
| 102 | EndDelta: 0 | ||
| 103 | Columns: | ||
| 104 | - !Symbols | ||
| 105 | Records: | ||
| 106 | - Kind: S_GPROC32_ID | ||
| 107 | ProcSym: | ||
| 108 | CodeSize: 8 | ||
| 109 | DbgStart: 5 | ||
| 110 | DbgEnd: 7 | ||
| 111 | FunctionType: 4173 | ||
| 112 | Flags: [ ] | ||
| 113 | DisplayName: 'B::f' | ||
| 114 | - Kind: S_FRAMEPROC | ||
| 115 | FrameProcSym: | ||
| 116 | TotalFrameBytes: 0 | ||
| 117 | PaddingFrameBytes: 0 | ||
| 118 | OffsetToPadding: 0 | ||
| 119 | BytesOfCalleeSavedRegisters: 0 | ||
| 120 | OffsetOfExceptionHandler: 0 | ||
| 121 | SectionIdOfExceptionHandler: 0 | ||
| 122 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | ||
| 123 | - Kind: S_REGREL32 | ||
| 124 | RegRelativeSym: | ||
| 125 | Offset: 8 | ||
| 126 | Type: 4121 | ||
| 127 | Register: RSP | ||
| 128 | VarName: this | ||
| 129 | - Kind: S_PROC_ID_END | ||
| 130 | ScopeEndSym: | ||
| 131 | - !Lines | ||
| 132 | CodeSize: 8 | ||
| 133 | Flags: [ ] | ||
| 134 | RelocOffset: 0 | ||
| 135 | RelocSegment: 0 | ||
| 136 | Blocks: | ||
| 137 | - FileName: 'c:\src\llvm-project\build\t.cpp' | ||
| 138 | Lines: | ||
| 139 | - Offset: 0 | ||
| 140 | LineStart: 13 | ||
| 141 | IsStatement: true | ||
| 142 | EndDelta: 0 | ||
| 143 | Columns: | ||
| 144 | - !Symbols | ||
| 145 | Records: | ||
| 146 | - Kind: S_GPROC32_ID | ||
| 147 | ProcSym: | ||
| 148 | CodeSize: 89 | ||
| 149 | DbgStart: 9 | ||
| 150 | DbgEnd: 84 | ||
| 151 | FunctionType: 4175 | ||
| 152 | Flags: [ ] | ||
| 153 | DisplayName: 'C::C' | ||
| 154 | - Kind: S_FRAMEPROC | ||
| 155 | FrameProcSym: | ||
| 156 | TotalFrameBytes: 40 | ||
| 157 | PaddingFrameBytes: 0 | ||
| 158 | OffsetToPadding: 0 | ||
| 159 | BytesOfCalleeSavedRegisters: 0 | ||
| 160 | OffsetOfExceptionHandler: 0 | ||
| 161 | SectionIdOfExceptionHandler: 0 | ||
| 162 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | ||
| 163 | - Kind: S_REGREL32 | ||
| 164 | RegRelativeSym: | ||
| 165 | Offset: 48 | ||
| 166 | Type: 4143 | ||
| 167 | Register: RSP | ||
| 168 | VarName: this | ||
| 169 | - Kind: S_PROC_ID_END | ||
| 170 | ScopeEndSym: | ||
| 171 | - !Lines | ||
| 172 | CodeSize: 89 | ||
| 173 | Flags: [ ] | ||
| 174 | RelocOffset: 0 | ||
| 175 | RelocSegment: 0 | ||
| 176 | Blocks: | ||
| 177 | - FileName: 'c:\src\llvm-project\build\t.cpp' | ||
| 178 | Lines: | ||
| 179 | - Offset: 0 | ||
| 180 | LineStart: 15 | ||
| 181 | IsStatement: true | ||
| 182 | EndDelta: 0 | ||
| 183 | - Offset: 67 | ||
| 184 | LineStart: 15 | ||
| 185 | IsStatement: true | ||
| 186 | EndDelta: 0 | ||
| 187 | Columns: | ||
| 188 | - !Symbols | ||
| 189 | Records: | ||
| 190 | - Kind: S_GPROC32_ID | ||
| 191 | ProcSym: | ||
| 192 | CodeSize: 14 | ||
| 193 | DbgStart: 5 | ||
| 194 | DbgEnd: 13 | ||
| 195 | FunctionType: 4174 | ||
| 196 | Flags: [ ] | ||
| 197 | DisplayName: 'C::f' | ||
| 198 | - Kind: S_FRAMEPROC | ||
| 199 | FrameProcSym: | ||
| 200 | TotalFrameBytes: 0 | ||
| 201 | PaddingFrameBytes: 0 | ||
| 202 | OffsetToPadding: 0 | ||
| 203 | BytesOfCalleeSavedRegisters: 0 | ||
| 204 | OffsetOfExceptionHandler: 0 | ||
| 205 | SectionIdOfExceptionHandler: 0 | ||
| 206 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | ||
| 207 | - Kind: S_REGREL32 | ||
| 208 | RegRelativeSym: | ||
| 209 | Offset: 8 | ||
| 210 | Type: 4143 | ||
| 211 | Register: RSP | ||
| 212 | VarName: this | ||
| 213 | - Kind: S_PROC_ID_END | ||
| 214 | ScopeEndSym: | ||
| 215 | - !Lines | ||
| 216 | CodeSize: 14 | ||
| 217 | Flags: [ ] | ||
| 218 | RelocOffset: 0 | ||
| 219 | RelocSegment: 0 | ||
| 220 | Blocks: | ||
| 221 | - FileName: 'c:\src\llvm-project\build\t.cpp' | ||
| 222 | Lines: | ||
| 223 | - Offset: 0 | ||
| 224 | LineStart: 14 | ||
| 225 | IsStatement: true | ||
| 226 | EndDelta: 0 | ||
| 227 | Columns: | ||
| 228 | - !Symbols | ||
| 229 | Records: | ||
| 230 | - Kind: S_UDT | ||
| 231 | UDTSym: | ||
| 232 | Type: 4117 | ||
| 233 | UDTName: A | ||
| 234 | - Kind: S_UDT | ||
| 235 | UDTSym: | ||
| 236 | Type: 4268 | ||
| 237 | UDTName: '__vc_attributes::event_sourceAttribute' | ||
| 238 | - Kind: S_UDT | ||
| 239 | UDTSym: | ||
| 240 | Type: 4260 | ||
| 241 | UDTName: '__vc_attributes::event_sourceAttribute::optimize_e' | ||
| 242 | - Kind: S_UDT | ||
| 243 | UDTSym: | ||
| 244 | Type: 4257 | ||
| 245 | UDTName: '__vc_attributes::event_sourceAttribute::type_e' | ||
| 246 | - Kind: S_UDT | ||
| 247 | UDTSym: | ||
| 248 | Type: 4253 | ||
| 249 | UDTName: '__vc_attributes::helper_attributes::v1_alttypeAttribute' | ||
| 250 | - Kind: S_UDT | ||
| 251 | UDTSym: | ||
| 252 | Type: 4247 | ||
| 253 | UDTName: '__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e' | ||
| 254 | - Kind: S_UDT | ||
| 255 | UDTSym: | ||
| 256 | Type: 4243 | ||
| 257 | UDTName: '__vc_attributes::helper_attributes::usageAttribute' | ||
| 258 | - Kind: S_UDT | ||
| 259 | UDTSym: | ||
| 260 | Type: 4237 | ||
| 261 | UDTName: '__vc_attributes::helper_attributes::usageAttribute::usage_e' | ||
| 262 | - Kind: S_UDT | ||
| 263 | UDTSym: | ||
| 264 | Type: 4233 | ||
| 265 | UDTName: '__vc_attributes::threadingAttribute' | ||
| 266 | - Kind: S_UDT | ||
| 267 | UDTSym: | ||
| 268 | Type: 4225 | ||
| 269 | UDTName: '__vc_attributes::threadingAttribute::threading_e' | ||
| 270 | - Kind: S_UDT | ||
| 271 | UDTSym: | ||
| 272 | Type: 4221 | ||
| 273 | UDTName: '__vc_attributes::aggregatableAttribute' | ||
| 274 | - Kind: S_UDT | ||
| 275 | UDTSym: | ||
| 276 | Type: 4213 | ||
| 277 | UDTName: '__vc_attributes::aggregatableAttribute::type_e' | ||
| 278 | - Kind: S_UDT | ||
| 279 | UDTSym: | ||
| 280 | Type: 4209 | ||
| 281 | UDTName: '__vc_attributes::event_receiverAttribute' | ||
| 282 | - Kind: S_UDT | ||
| 283 | UDTSym: | ||
| 284 | Type: 4199 | ||
| 285 | UDTName: '__vc_attributes::event_receiverAttribute::type_e' | ||
| 286 | - Kind: S_UDT | ||
| 287 | UDTSym: | ||
| 288 | Type: 4195 | ||
| 289 | UDTName: '__vc_attributes::moduleAttribute' | ||
| 290 | - Kind: S_UDT | ||
| 291 | UDTSym: | ||
| 292 | Type: 4182 | ||
| 293 | UDTName: '__vc_attributes::moduleAttribute::type_e' | ||
| 294 | - Kind: S_UDT | ||
| 295 | UDTSym: | ||
| 296 | Type: 4160 | ||
| 297 | UDTName: C | ||
| 298 | - Kind: S_UDT | ||
| 299 | UDTSym: | ||
| 300 | Type: 4140 | ||
| 301 | UDTName: B | ||
| 302 | - !FileChecksums | ||
| 303 | Checksums: | ||
| 304 | - FileName: 'c:\src\llvm-project\build\t.cpp' | ||
| 305 | Kind: MD5 | ||
| 306 | Checksum: 1E487A6B7D4DB0A502F8E5945CCB70D1 | ||
| 307 | - !StringTable | ||
| 308 | Strings: | ||
| 309 | - 'c:\src\llvm-project\build\t.cpp' | ||
| 310 | - !Symbols | ||
| 311 | Records: | ||
| 312 | - Kind: S_BUILDINFO | ||
| 313 | BuildInfoSym: | ||
| 314 | BuildId: 4281 | ||
| 315 | Relocations: | ||
| 316 | - VirtualAddress: 152 | ||
| 317 | SymbolName: '?f@A@@UEAAHXZ' | ||
| 318 | Type: IMAGE_REL_AMD64_SECREL | ||
| 319 | - VirtualAddress: 156 | ||
| 320 | SymbolName: '?f@A@@UEAAHXZ' | ||
| 321 | Type: IMAGE_REL_AMD64_SECTION | ||
| 322 | - VirtualAddress: 228 | ||
| 323 | SymbolName: '?f@A@@UEAAHXZ' | ||
| 324 | Type: IMAGE_REL_AMD64_SECREL | ||
| 325 | - VirtualAddress: 232 | ||
| 326 | SymbolName: '?f@A@@UEAAHXZ' | ||
| 327 | Type: IMAGE_REL_AMD64_SECTION | ||
| 328 | - VirtualAddress: 300 | ||
| 329 | SymbolName: '?f@B@@UEAAHXZ' | ||
| 330 | Type: IMAGE_REL_AMD64_SECREL | ||
| 331 | - VirtualAddress: 304 | ||
| 332 | SymbolName: '?f@B@@UEAAHXZ' | ||
| 333 | Type: IMAGE_REL_AMD64_SECTION | ||
| 334 | - VirtualAddress: 376 | ||
| 335 | SymbolName: '?f@B@@UEAAHXZ' | ||
| 336 | Type: IMAGE_REL_AMD64_SECREL | ||
| 337 | - VirtualAddress: 380 | ||
| 338 | SymbolName: '?f@B@@UEAAHXZ' | ||
| 339 | Type: IMAGE_REL_AMD64_SECTION | ||
| 340 | - VirtualAddress: 448 | ||
| 341 | SymbolName: '??0C@@QEAA@XZ' | ||
| 342 | Type: IMAGE_REL_AMD64_SECREL | ||
| 343 | - VirtualAddress: 452 | ||
| 344 | SymbolName: '??0C@@QEAA@XZ' | ||
| 345 | Type: IMAGE_REL_AMD64_SECTION | ||
| 346 | - VirtualAddress: 524 | ||
| 347 | SymbolName: '??0C@@QEAA@XZ' | ||
| 348 | Type: IMAGE_REL_AMD64_SECREL | ||
| 349 | - VirtualAddress: 528 | ||
| 350 | SymbolName: '??0C@@QEAA@XZ' | ||
| 351 | Type: IMAGE_REL_AMD64_SECTION | ||
| 352 | - VirtualAddress: 604 | ||
| 353 | SymbolName: '?f@C@@UEAAHXZ' | ||
| 354 | Type: IMAGE_REL_AMD64_SECREL | ||
| 355 | - VirtualAddress: 608 | ||
| 356 | SymbolName: '?f@C@@UEAAHXZ' | ||
| 357 | Type: IMAGE_REL_AMD64_SECTION | ||
| 358 | - VirtualAddress: 680 | ||
| 359 | SymbolName: '?f@C@@UEAAHXZ' | ||
| 360 | Type: IMAGE_REL_AMD64_SECREL | ||
| 361 | - VirtualAddress: 684 | ||
| 362 | SymbolName: '?f@C@@UEAAHXZ' | ||
| 363 | Type: IMAGE_REL_AMD64_SECTION | ||
| 364 | - Name: '.debug$T' | ||
| 365 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 366 | Alignment: 1 | ||
| 367 | Types: | ||
| 368 | - Kind: LF_STRUCTURE | ||
| 369 | Class: | ||
| 370 | MemberCount: 0 | ||
| 371 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 372 | FieldList: 0 | ||
| 373 | Name: A | ||
| 374 | UniqueName: '.?AUA@@' | ||
| 375 | DerivationList: 0 | ||
| 376 | VTableShape: 0 | ||
| 377 | Size: 0 | ||
| 378 | - Kind: LF_POINTER | ||
| 379 | Pointer: | ||
| 380 | ReferentType: 4096 | ||
| 381 | Attrs: 66572 | ||
| 382 | - Kind: LF_VTSHAPE | ||
| 383 | VFTableShape: | ||
| 384 | Slots: | ||
| 385 | - Near16 | ||
| 386 | - Kind: LF_POINTER | ||
| 387 | Pointer: | ||
| 388 | ReferentType: 4098 | ||
| 389 | Attrs: 65548 | ||
| 390 | - Kind: LF_ARGLIST | ||
| 391 | ArgList: | ||
| 392 | ArgIndices: [ ] | ||
| 393 | - Kind: LF_MFUNCTION | ||
| 394 | MemberFunction: | ||
| 395 | ReturnType: 116 | ||
| 396 | ClassType: 4096 | ||
| 397 | ThisType: 4097 | ||
| 398 | CallConv: NearC | ||
| 399 | Options: [ None ] | ||
| 400 | ParameterCount: 0 | ||
| 401 | ArgumentList: 4100 | ||
| 402 | ThisPointerAdjustment: 0 | ||
| 403 | - Kind: LF_POINTER | ||
| 404 | Pointer: | ||
| 405 | ReferentType: 4096 | ||
| 406 | Attrs: 65676 | ||
| 407 | - Kind: LF_ARGLIST | ||
| 408 | ArgList: | ||
| 409 | ArgIndices: [ 4102 ] | ||
| 410 | - Kind: LF_MFUNCTION | ||
| 411 | MemberFunction: | ||
| 412 | ReturnType: 3 | ||
| 413 | ClassType: 4096 | ||
| 414 | ThisType: 4097 | ||
| 415 | CallConv: NearC | ||
| 416 | Options: [ None, Constructor ] | ||
| 417 | ParameterCount: 1 | ||
| 418 | ArgumentList: 4103 | ||
| 419 | ThisPointerAdjustment: 0 | ||
| 420 | - Kind: LF_MODIFIER | ||
| 421 | Modifier: | ||
| 422 | ModifiedType: 4096 | ||
| 423 | Modifiers: [ None, Const ] | ||
| 424 | - Kind: LF_POINTER | ||
| 425 | Pointer: | ||
| 426 | ReferentType: 4105 | ||
| 427 | Attrs: 65580 | ||
| 428 | - Kind: LF_ARGLIST | ||
| 429 | ArgList: | ||
| 430 | ArgIndices: [ 4106 ] | ||
| 431 | - Kind: LF_MFUNCTION | ||
| 432 | MemberFunction: | ||
| 433 | ReturnType: 3 | ||
| 434 | ClassType: 4096 | ||
| 435 | ThisType: 4097 | ||
| 436 | CallConv: NearC | ||
| 437 | Options: [ None, Constructor ] | ||
| 438 | ParameterCount: 1 | ||
| 439 | ArgumentList: 4107 | ||
| 440 | ThisPointerAdjustment: 0 | ||
| 441 | - Kind: LF_MFUNCTION | ||
| 442 | MemberFunction: | ||
| 443 | ReturnType: 3 | ||
| 444 | ClassType: 4096 | ||
| 445 | ThisType: 4097 | ||
| 446 | CallConv: NearC | ||
| 447 | Options: [ None, Constructor ] | ||
| 448 | ParameterCount: 0 | ||
| 449 | ArgumentList: 4100 | ||
| 450 | ThisPointerAdjustment: 0 | ||
| 451 | - Kind: LF_METHODLIST | ||
| 452 | MethodOverloadList: | ||
| 453 | Methods: | ||
| 454 | - Type: 4104 | ||
| 455 | Attrs: 259 | ||
| 456 | VFTableOffset: -1 | ||
| 457 | Name: '' | ||
| 458 | - Type: 4108 | ||
| 459 | Attrs: 259 | ||
| 460 | VFTableOffset: -1 | ||
| 461 | Name: '' | ||
| 462 | - Type: 4109 | ||
| 463 | Attrs: 259 | ||
| 464 | VFTableOffset: -1 | ||
| 465 | Name: '' | ||
| 466 | - Kind: LF_POINTER | ||
| 467 | Pointer: | ||
| 468 | ReferentType: 4096 | ||
| 469 | Attrs: 65580 | ||
| 470 | - Kind: LF_MFUNCTION | ||
| 471 | MemberFunction: | ||
| 472 | ReturnType: 4111 | ||
| 473 | ClassType: 4096 | ||
| 474 | ThisType: 4097 | ||
| 475 | CallConv: NearC | ||
| 476 | Options: [ None ] | ||
| 477 | ParameterCount: 1 | ||
| 478 | ArgumentList: 4103 | ||
| 479 | ThisPointerAdjustment: 0 | ||
| 480 | - Kind: LF_MFUNCTION | ||
| 481 | MemberFunction: | ||
| 482 | ReturnType: 4111 | ||
| 483 | ClassType: 4096 | ||
| 484 | ThisType: 4097 | ||
| 485 | CallConv: NearC | ||
| 486 | Options: [ None ] | ||
| 487 | ParameterCount: 1 | ||
| 488 | ArgumentList: 4107 | ||
| 489 | ThisPointerAdjustment: 0 | ||
| 490 | - Kind: LF_METHODLIST | ||
| 491 | MethodOverloadList: | ||
| 492 | Methods: | ||
| 493 | - Type: 4112 | ||
| 494 | Attrs: 259 | ||
| 495 | VFTableOffset: -1 | ||
| 496 | Name: '' | ||
| 497 | - Type: 4113 | ||
| 498 | Attrs: 259 | ||
| 499 | VFTableOffset: -1 | ||
| 500 | Name: '' | ||
| 501 | - Kind: LF_FIELDLIST | ||
| 502 | FieldList: | ||
| 503 | - Kind: LF_VFUNCTAB | ||
| 504 | VFPtr: | ||
| 505 | Type: 4099 | ||
| 506 | - Kind: LF_ONEMETHOD | ||
| 507 | OneMethod: | ||
| 508 | Type: 4101 | ||
| 509 | Attrs: 19 | ||
| 510 | VFTableOffset: 0 | ||
| 511 | Name: f | ||
| 512 | - Kind: LF_METHOD | ||
| 513 | OverloadedMethod: | ||
| 514 | NumOverloads: 3 | ||
| 515 | MethodList: 4110 | ||
| 516 | Name: A | ||
| 517 | - Kind: LF_METHOD | ||
| 518 | OverloadedMethod: | ||
| 519 | NumOverloads: 2 | ||
| 520 | MethodList: 4114 | ||
| 521 | Name: 'operator=' | ||
| 522 | - Kind: LF_VTSHAPE | ||
| 523 | VFTableShape: | ||
| 524 | Slots: | ||
| 525 | - Near16 | ||
| 526 | - Kind: LF_STRUCTURE | ||
| 527 | Class: | ||
| 528 | MemberCount: 7 | ||
| 529 | Options: [ None, HasConstructorOrDestructor, HasOverloadedOperator, HasOverloadedAssignmentOperator, HasUniqueName ] | ||
| 530 | FieldList: 4115 | ||
| 531 | Name: A | ||
| 532 | UniqueName: '.?AUA@@' | ||
| 533 | DerivationList: 0 | ||
| 534 | VTableShape: 4116 | ||
| 535 | Size: 8 | ||
| 536 | - Kind: LF_STRING_ID | ||
| 537 | StringId: | ||
| 538 | Id: 0 | ||
| 539 | String: 'c:\src\llvm-project\build\t.cpp' | ||
| 540 | - Kind: LF_UDT_SRC_LINE | ||
| 541 | UdtSourceLine: | ||
| 542 | UDT: 4117 | ||
| 543 | SourceFile: 4118 | ||
| 544 | LineNumber: 1 | ||
| 545 | - Kind: LF_STRUCTURE | ||
| 546 | Class: | ||
| 547 | MemberCount: 0 | ||
| 548 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 549 | FieldList: 0 | ||
| 550 | Name: B | ||
| 551 | UniqueName: '.?AUB@@' | ||
| 552 | DerivationList: 0 | ||
| 553 | VTableShape: 0 | ||
| 554 | Size: 0 | ||
| 555 | - Kind: LF_POINTER | ||
| 556 | Pointer: | ||
| 557 | ReferentType: 4120 | ||
| 558 | Attrs: 66572 | ||
| 559 | - Kind: LF_VTSHAPE | ||
| 560 | VFTableShape: | ||
| 561 | Slots: | ||
| 562 | - Near16 | ||
| 563 | - Kind: LF_POINTER | ||
| 564 | Pointer: | ||
| 565 | ReferentType: 4122 | ||
| 566 | Attrs: 65548 | ||
| 567 | - Kind: LF_MFUNCTION | ||
| 568 | MemberFunction: | ||
| 569 | ReturnType: 116 | ||
| 570 | ClassType: 4120 | ||
| 571 | ThisType: 4121 | ||
| 572 | CallConv: NearC | ||
| 573 | Options: [ None ] | ||
| 574 | ParameterCount: 0 | ||
| 575 | ArgumentList: 4100 | ||
| 576 | ThisPointerAdjustment: 0 | ||
| 577 | - Kind: LF_POINTER | ||
| 578 | Pointer: | ||
| 579 | ReferentType: 4120 | ||
| 580 | Attrs: 65676 | ||
| 581 | - Kind: LF_ARGLIST | ||
| 582 | ArgList: | ||
| 583 | ArgIndices: [ 4125 ] | ||
| 584 | - Kind: LF_MFUNCTION | ||
| 585 | MemberFunction: | ||
| 586 | ReturnType: 3 | ||
| 587 | ClassType: 4120 | ||
| 588 | ThisType: 4121 | ||
| 589 | CallConv: NearC | ||
| 590 | Options: [ None, Constructor ] | ||
| 591 | ParameterCount: 1 | ||
| 592 | ArgumentList: 4126 | ||
| 593 | ThisPointerAdjustment: 0 | ||
| 594 | - Kind: LF_MODIFIER | ||
| 595 | Modifier: | ||
| 596 | ModifiedType: 4120 | ||
| 597 | Modifiers: [ None, Const ] | ||
| 598 | - Kind: LF_POINTER | ||
| 599 | Pointer: | ||
| 600 | ReferentType: 4128 | ||
| 601 | Attrs: 65580 | ||
| 602 | - Kind: LF_ARGLIST | ||
| 603 | ArgList: | ||
| 604 | ArgIndices: [ 4129 ] | ||
| 605 | - Kind: LF_MFUNCTION | ||
| 606 | MemberFunction: | ||
| 607 | ReturnType: 3 | ||
| 608 | ClassType: 4120 | ||
| 609 | ThisType: 4121 | ||
| 610 | CallConv: NearC | ||
| 611 | Options: [ None, Constructor ] | ||
| 612 | ParameterCount: 1 | ||
| 613 | ArgumentList: 4130 | ||
| 614 | ThisPointerAdjustment: 0 | ||
| 615 | - Kind: LF_MFUNCTION | ||
| 616 | MemberFunction: | ||
| 617 | ReturnType: 3 | ||
| 618 | ClassType: 4120 | ||
| 619 | ThisType: 4121 | ||
| 620 | CallConv: NearC | ||
| 621 | Options: [ None, Constructor ] | ||
| 622 | ParameterCount: 0 | ||
| 623 | ArgumentList: 4100 | ||
| 624 | ThisPointerAdjustment: 0 | ||
| 625 | - Kind: LF_METHODLIST | ||
| 626 | MethodOverloadList: | ||
| 627 | Methods: | ||
| 628 | - Type: 4127 | ||
| 629 | Attrs: 259 | ||
| 630 | VFTableOffset: -1 | ||
| 631 | Name: '' | ||
| 632 | - Type: 4131 | ||
| 633 | Attrs: 259 | ||
| 634 | VFTableOffset: -1 | ||
| 635 | Name: '' | ||
| 636 | - Type: 4132 | ||
| 637 | Attrs: 259 | ||
| 638 | VFTableOffset: -1 | ||
| 639 | Name: '' | ||
| 640 | - Kind: LF_POINTER | ||
| 641 | Pointer: | ||
| 642 | ReferentType: 4120 | ||
| 643 | Attrs: 65580 | ||
| 644 | - Kind: LF_MFUNCTION | ||
| 645 | MemberFunction: | ||
| 646 | ReturnType: 4134 | ||
| 647 | ClassType: 4120 | ||
| 648 | ThisType: 4121 | ||
| 649 | CallConv: NearC | ||
| 650 | Options: [ None ] | ||
| 651 | ParameterCount: 1 | ||
| 652 | ArgumentList: 4126 | ||
| 653 | ThisPointerAdjustment: 0 | ||
| 654 | - Kind: LF_MFUNCTION | ||
| 655 | MemberFunction: | ||
| 656 | ReturnType: 4134 | ||
| 657 | ClassType: 4120 | ||
| 658 | ThisType: 4121 | ||
| 659 | CallConv: NearC | ||
| 660 | Options: [ None ] | ||
| 661 | ParameterCount: 1 | ||
| 662 | ArgumentList: 4130 | ||
| 663 | ThisPointerAdjustment: 0 | ||
| 664 | - Kind: LF_METHODLIST | ||
| 665 | MethodOverloadList: | ||
| 666 | Methods: | ||
| 667 | - Type: 4135 | ||
| 668 | Attrs: 259 | ||
| 669 | VFTableOffset: -1 | ||
| 670 | Name: '' | ||
| 671 | - Type: 4136 | ||
| 672 | Attrs: 259 | ||
| 673 | VFTableOffset: -1 | ||
| 674 | Name: '' | ||
| 675 | - Kind: LF_FIELDLIST | ||
| 676 | FieldList: | ||
| 677 | - Kind: LF_VFUNCTAB | ||
| 678 | VFPtr: | ||
| 679 | Type: 4123 | ||
| 680 | - Kind: LF_ONEMETHOD | ||
| 681 | OneMethod: | ||
| 682 | Type: 4124 | ||
| 683 | Attrs: 19 | ||
| 684 | VFTableOffset: 0 | ||
| 685 | Name: f | ||
| 686 | - Kind: LF_METHOD | ||
| 687 | OverloadedMethod: | ||
| 688 | NumOverloads: 3 | ||
| 689 | MethodList: 4133 | ||
| 690 | Name: B | ||
| 691 | - Kind: LF_METHOD | ||
| 692 | OverloadedMethod: | ||
| 693 | NumOverloads: 2 | ||
| 694 | MethodList: 4137 | ||
| 695 | Name: 'operator=' | ||
| 696 | - Kind: LF_VTSHAPE | ||
| 697 | VFTableShape: | ||
| 698 | Slots: | ||
| 699 | - Near16 | ||
| 700 | - Kind: LF_STRUCTURE | ||
| 701 | Class: | ||
| 702 | MemberCount: 7 | ||
| 703 | Options: [ None, HasConstructorOrDestructor, HasOverloadedOperator, HasOverloadedAssignmentOperator, HasUniqueName ] | ||
| 704 | FieldList: 4138 | ||
| 705 | Name: B | ||
| 706 | UniqueName: '.?AUB@@' | ||
| 707 | DerivationList: 0 | ||
| 708 | VTableShape: 4139 | ||
| 709 | Size: 8 | ||
| 710 | - Kind: LF_UDT_SRC_LINE | ||
| 711 | UdtSourceLine: | ||
| 712 | UDT: 4140 | ||
| 713 | SourceFile: 4118 | ||
| 714 | LineNumber: 4 | ||
| 715 | - Kind: LF_STRUCTURE | ||
| 716 | Class: | ||
| 717 | MemberCount: 0 | ||
| 718 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 719 | FieldList: 0 | ||
| 720 | Name: C | ||
| 721 | UniqueName: '.?AUC@@' | ||
| 722 | DerivationList: 0 | ||
| 723 | VTableShape: 0 | ||
| 724 | Size: 0 | ||
| 725 | - Kind: LF_POINTER | ||
| 726 | Pointer: | ||
| 727 | ReferentType: 4142 | ||
| 728 | Attrs: 66572 | ||
| 729 | - Kind: LF_POINTER | ||
| 730 | Pointer: | ||
| 731 | ReferentType: 4142 | ||
| 732 | Attrs: 65676 | ||
| 733 | - Kind: LF_ARGLIST | ||
| 734 | ArgList: | ||
| 735 | ArgIndices: [ 4144 ] | ||
| 736 | - Kind: LF_MFUNCTION | ||
| 737 | MemberFunction: | ||
| 738 | ReturnType: 3 | ||
| 739 | ClassType: 4142 | ||
| 740 | ThisType: 4143 | ||
| 741 | CallConv: NearC | ||
| 742 | Options: [ None, Constructor ] | ||
| 743 | ParameterCount: 1 | ||
| 744 | ArgumentList: 4145 | ||
| 745 | ThisPointerAdjustment: 0 | ||
| 746 | - Kind: LF_MODIFIER | ||
| 747 | Modifier: | ||
| 748 | ModifiedType: 4142 | ||
| 749 | Modifiers: [ None, Const ] | ||
| 750 | - Kind: LF_POINTER | ||
| 751 | Pointer: | ||
| 752 | ReferentType: 4147 | ||
| 753 | Attrs: 65580 | ||
| 754 | - Kind: LF_ARGLIST | ||
| 755 | ArgList: | ||
| 756 | ArgIndices: [ 4148 ] | ||
| 757 | - Kind: LF_MFUNCTION | ||
| 758 | MemberFunction: | ||
| 759 | ReturnType: 3 | ||
| 760 | ClassType: 4142 | ||
| 761 | ThisType: 4143 | ||
| 762 | CallConv: NearC | ||
| 763 | Options: [ None, Constructor ] | ||
| 764 | ParameterCount: 1 | ||
| 765 | ArgumentList: 4149 | ||
| 766 | ThisPointerAdjustment: 0 | ||
| 767 | - Kind: LF_MFUNCTION | ||
| 768 | MemberFunction: | ||
| 769 | ReturnType: 3 | ||
| 770 | ClassType: 4142 | ||
| 771 | ThisType: 4143 | ||
| 772 | CallConv: NearC | ||
| 773 | Options: [ None, Constructor ] | ||
| 774 | ParameterCount: 0 | ||
| 775 | ArgumentList: 4100 | ||
| 776 | ThisPointerAdjustment: 0 | ||
| 777 | - Kind: LF_METHODLIST | ||
| 778 | MethodOverloadList: | ||
| 779 | Methods: | ||
| 780 | - Type: 4146 | ||
| 781 | Attrs: 259 | ||
| 782 | VFTableOffset: -1 | ||
| 783 | Name: '' | ||
| 784 | - Type: 4150 | ||
| 785 | Attrs: 259 | ||
| 786 | VFTableOffset: -1 | ||
| 787 | Name: '' | ||
| 788 | - Type: 4151 | ||
| 789 | Attrs: 3 | ||
| 790 | VFTableOffset: -1 | ||
| 791 | Name: '' | ||
| 792 | - Kind: LF_MFUNCTION | ||
| 793 | MemberFunction: | ||
| 794 | ReturnType: 116 | ||
| 795 | ClassType: 4142 | ||
| 796 | ThisType: 4143 | ||
| 797 | CallConv: NearC | ||
| 798 | Options: [ None ] | ||
| 799 | ParameterCount: 0 | ||
| 800 | ArgumentList: 4100 | ||
| 801 | ThisPointerAdjustment: 0 | ||
| 802 | - Kind: LF_POINTER | ||
| 803 | Pointer: | ||
| 804 | ReferentType: 4142 | ||
| 805 | Attrs: 65580 | ||
| 806 | - Kind: LF_MFUNCTION | ||
| 807 | MemberFunction: | ||
| 808 | ReturnType: 4154 | ||
| 809 | ClassType: 4142 | ||
| 810 | ThisType: 4143 | ||
| 811 | CallConv: NearC | ||
| 812 | Options: [ None ] | ||
| 813 | ParameterCount: 1 | ||
| 814 | ArgumentList: 4145 | ||
| 815 | ThisPointerAdjustment: 0 | ||
| 816 | - Kind: LF_MFUNCTION | ||
| 817 | MemberFunction: | ||
| 818 | ReturnType: 4154 | ||
| 819 | ClassType: 4142 | ||
| 820 | ThisType: 4143 | ||
| 821 | CallConv: NearC | ||
| 822 | Options: [ None ] | ||
| 823 | ParameterCount: 1 | ||
| 824 | ArgumentList: 4149 | ||
| 825 | ThisPointerAdjustment: 0 | ||
| 826 | - Kind: LF_METHODLIST | ||
| 827 | MethodOverloadList: | ||
| 828 | Methods: | ||
| 829 | - Type: 4155 | ||
| 830 | Attrs: 259 | ||
| 831 | VFTableOffset: -1 | ||
| 832 | Name: '' | ||
| 833 | - Type: 4156 | ||
| 834 | Attrs: 259 | ||
| 835 | VFTableOffset: -1 | ||
| 836 | Name: '' | ||
| 837 | - Kind: LF_FIELDLIST | ||
| 838 | FieldList: | ||
| 839 | - Kind: LF_BCLASS | ||
| 840 | BaseClass: | ||
| 841 | Attrs: 3 | ||
| 842 | Type: 4096 | ||
| 843 | Offset: 0 | ||
| 844 | - Kind: LF_BCLASS | ||
| 845 | BaseClass: | ||
| 846 | Attrs: 3 | ||
| 847 | Type: 4120 | ||
| 848 | Offset: 8 | ||
| 849 | - Kind: LF_METHOD | ||
| 850 | OverloadedMethod: | ||
| 851 | NumOverloads: 3 | ||
| 852 | MethodList: 4152 | ||
| 853 | Name: C | ||
| 854 | - Kind: LF_ONEMETHOD | ||
| 855 | OneMethod: | ||
| 856 | Type: 4153 | ||
| 857 | Attrs: 7 | ||
| 858 | VFTableOffset: -1 | ||
| 859 | Name: f | ||
| 860 | - Kind: LF_MEMBER | ||
| 861 | DataMember: | ||
| 862 | Attrs: 3 | ||
| 863 | Type: 116 | ||
| 864 | FieldOffset: 16 | ||
| 865 | Name: c | ||
| 866 | - Kind: LF_METHOD | ||
| 867 | OverloadedMethod: | ||
| 868 | NumOverloads: 2 | ||
| 869 | MethodList: 4157 | ||
| 870 | Name: 'operator=' | ||
| 871 | - Kind: LF_VTSHAPE | ||
| 872 | VFTableShape: | ||
| 873 | Slots: | ||
| 874 | - Near16 | ||
| 875 | - Kind: LF_STRUCTURE | ||
| 876 | Class: | ||
| 877 | MemberCount: 9 | ||
| 878 | Options: [ None, HasConstructorOrDestructor, HasOverloadedOperator, HasOverloadedAssignmentOperator, HasUniqueName ] | ||
| 879 | FieldList: 4158 | ||
| 880 | Name: C | ||
| 881 | UniqueName: '.?AUC@@' | ||
| 882 | DerivationList: 0 | ||
| 883 | VTableShape: 4159 | ||
| 884 | Size: 24 | ||
| 885 | - Kind: LF_UDT_SRC_LINE | ||
| 886 | UdtSourceLine: | ||
| 887 | UDT: 4160 | ||
| 888 | SourceFile: 4118 | ||
| 889 | LineNumber: 7 | ||
| 890 | - Kind: LF_POINTER | ||
| 891 | Pointer: | ||
| 892 | ReferentType: 4142 | ||
| 893 | Attrs: 65548 | ||
| 894 | - Kind: LF_MFUNCTION | ||
| 895 | MemberFunction: | ||
| 896 | ReturnType: 3 | ||
| 897 | ClassType: 4142 | ||
| 898 | ThisType: 4143 | ||
| 899 | CallConv: NearC | ||
| 900 | Options: [ None ] | ||
| 901 | ParameterCount: 0 | ||
| 902 | ArgumentList: 4100 | ||
| 903 | ThisPointerAdjustment: 0 | ||
| 904 | - Kind: LF_POINTER | ||
| 905 | Pointer: | ||
| 906 | ReferentType: 4096 | ||
| 907 | Attrs: 65548 | ||
| 908 | - Kind: LF_MFUNCTION | ||
| 909 | MemberFunction: | ||
| 910 | ReturnType: 3 | ||
| 911 | ClassType: 4096 | ||
| 912 | ThisType: 4097 | ||
| 913 | CallConv: NearC | ||
| 914 | Options: [ None ] | ||
| 915 | ParameterCount: 0 | ||
| 916 | ArgumentList: 4100 | ||
| 917 | ThisPointerAdjustment: 0 | ||
| 918 | - Kind: LF_POINTER | ||
| 919 | Pointer: | ||
| 920 | ReferentType: 4120 | ||
| 921 | Attrs: 65548 | ||
| 922 | - Kind: LF_MFUNCTION | ||
| 923 | MemberFunction: | ||
| 924 | ReturnType: 3 | ||
| 925 | ClassType: 4120 | ||
| 926 | ThisType: 4121 | ||
| 927 | CallConv: NearC | ||
| 928 | Options: [ None ] | ||
| 929 | ParameterCount: 0 | ||
| 930 | ArgumentList: 4100 | ||
| 931 | ThisPointerAdjustment: 0 | ||
| 932 | - Kind: LF_PROCEDURE | ||
| 933 | Procedure: | ||
| 934 | ReturnType: 3 | ||
| 935 | CallConv: NearC | ||
| 936 | Options: [ None ] | ||
| 937 | ParameterCount: 0 | ||
| 938 | ArgumentList: 4100 | ||
| 939 | - Kind: LF_POINTER | ||
| 940 | Pointer: | ||
| 941 | ReferentType: 4168 | ||
| 942 | Attrs: 66572 | ||
| 943 | - Kind: LF_POINTER | ||
| 944 | Pointer: | ||
| 945 | ReferentType: 4169 | ||
| 946 | Attrs: 65548 | ||
| 947 | - Kind: LF_POINTER | ||
| 948 | Pointer: | ||
| 949 | ReferentType: 4170 | ||
| 950 | Attrs: 65548 | ||
| 951 | - Kind: LF_MFUNC_ID | ||
| 952 | MemberFuncId: | ||
| 953 | ClassType: 4096 | ||
| 954 | FunctionType: 4101 | ||
| 955 | Name: f | ||
| 956 | - Kind: LF_MFUNC_ID | ||
| 957 | MemberFuncId: | ||
| 958 | ClassType: 4120 | ||
| 959 | FunctionType: 4124 | ||
| 960 | Name: f | ||
| 961 | - Kind: LF_MFUNC_ID | ||
| 962 | MemberFuncId: | ||
| 963 | ClassType: 4142 | ||
| 964 | FunctionType: 4153 | ||
| 965 | Name: f | ||
| 966 | - Kind: LF_MFUNC_ID | ||
| 967 | MemberFuncId: | ||
| 968 | ClassType: 4142 | ||
| 969 | FunctionType: 4151 | ||
| 970 | Name: '{ctor}' | ||
| 971 | - Kind: LF_MFUNC_ID | ||
| 972 | MemberFuncId: | ||
| 973 | ClassType: 4096 | ||
| 974 | FunctionType: 4109 | ||
| 975 | Name: '{ctor}' | ||
| 976 | - Kind: LF_MFUNC_ID | ||
| 977 | MemberFuncId: | ||
| 978 | ClassType: 4120 | ||
| 979 | FunctionType: 4132 | ||
| 980 | Name: '{ctor}' | ||
| 981 | - Kind: LF_MFUNC_ID | ||
| 982 | MemberFuncId: | ||
| 983 | ClassType: 4142 | ||
| 984 | FunctionType: 4153 | ||
| 985 | Name: f | ||
| 986 | - Kind: LF_ARRAY | ||
| 987 | Array: | ||
| 988 | ElementType: 4169 | ||
| 989 | IndexType: 35 | ||
| 990 | Size: 8 | ||
| 991 | Name: '' | ||
| 992 | - Kind: LF_STRUCTURE | ||
| 993 | Class: | ||
| 994 | MemberCount: 0 | ||
| 995 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 996 | FieldList: 0 | ||
| 997 | Name: '__vc_attributes::moduleAttribute' | ||
| 998 | UniqueName: '.?AUmoduleAttribute@__vc_attributes@@' | ||
| 999 | DerivationList: 0 | ||
| 1000 | VTableShape: 0 | ||
| 1001 | Size: 0 | ||
| 1002 | - Kind: LF_FIELDLIST | ||
| 1003 | FieldList: | ||
| 1004 | - Kind: LF_ENUMERATE | ||
| 1005 | Enumerator: | ||
| 1006 | Attrs: 3 | ||
| 1007 | Value: 1 | ||
| 1008 | Name: dll | ||
| 1009 | - Kind: LF_ENUMERATE | ||
| 1010 | Enumerator: | ||
| 1011 | Attrs: 3 | ||
| 1012 | Value: 2 | ||
| 1013 | Name: exe | ||
| 1014 | - Kind: LF_ENUMERATE | ||
| 1015 | Enumerator: | ||
| 1016 | Attrs: 3 | ||
| 1017 | Value: 3 | ||
| 1018 | Name: service | ||
| 1019 | - Kind: LF_ENUMERATE | ||
| 1020 | Enumerator: | ||
| 1021 | Attrs: 3 | ||
| 1022 | Value: 4 | ||
| 1023 | Name: unspecified | ||
| 1024 | - Kind: LF_ENUMERATE | ||
| 1025 | Enumerator: | ||
| 1026 | Attrs: 3 | ||
| 1027 | Value: 2 | ||
| 1028 | Name: EXE | ||
| 1029 | - Kind: LF_ENUMERATE | ||
| 1030 | Enumerator: | ||
| 1031 | Attrs: 3 | ||
| 1032 | Value: 3 | ||
| 1033 | Name: SERVICE | ||
| 1034 | - Kind: LF_ENUM | ||
| 1035 | Enum: | ||
| 1036 | NumEnumerators: 6 | ||
| 1037 | Options: [ None, Nested, HasUniqueName ] | ||
| 1038 | FieldList: 4181 | ||
| 1039 | Name: '__vc_attributes::moduleAttribute::type_e' | ||
| 1040 | UniqueName: '.?AW4type_e@moduleAttribute@__vc_attributes@@' | ||
| 1041 | UnderlyingType: 116 | ||
| 1042 | - Kind: LF_STRING_ID | ||
| 1043 | StringId: | ||
| 1044 | Id: 0 | ||
| 1045 | String: 'c:\src\llvm-project\build\predefined c++ attributes (compiler internal)' | ||
| 1046 | - Kind: LF_UDT_SRC_LINE | ||
| 1047 | UdtSourceLine: | ||
| 1048 | UDT: 4182 | ||
| 1049 | SourceFile: 4183 | ||
| 1050 | LineNumber: 482 | ||
| 1051 | - Kind: LF_MODIFIER | ||
| 1052 | Modifier: | ||
| 1053 | ModifiedType: 112 | ||
| 1054 | Modifiers: [ None, Const ] | ||
| 1055 | - Kind: LF_POINTER | ||
| 1056 | Pointer: | ||
| 1057 | ReferentType: 4185 | ||
| 1058 | Attrs: 65548 | ||
| 1059 | - Kind: LF_ARGLIST | ||
| 1060 | ArgList: | ||
| 1061 | ArgIndices: [ 4182, 4186, 4186, 4186, 116, 48, 4186, 116, | ||
| 1062 | 4186, 4186, 116, 48, 48, 4186, 4186 ] | ||
| 1063 | - Kind: LF_POINTER | ||
| 1064 | Pointer: | ||
| 1065 | ReferentType: 4180 | ||
| 1066 | Attrs: 66572 | ||
| 1067 | - Kind: LF_MFUNCTION | ||
| 1068 | MemberFunction: | ||
| 1069 | ReturnType: 3 | ||
| 1070 | ClassType: 4180 | ||
| 1071 | ThisType: 4188 | ||
| 1072 | CallConv: NearC | ||
| 1073 | Options: [ None, Constructor ] | ||
| 1074 | ParameterCount: 15 | ||
| 1075 | ArgumentList: 4187 | ||
| 1076 | ThisPointerAdjustment: 0 | ||
| 1077 | - Kind: LF_ARGLIST | ||
| 1078 | ArgList: | ||
| 1079 | ArgIndices: [ 4182 ] | ||
| 1080 | - Kind: LF_MFUNCTION | ||
| 1081 | MemberFunction: | ||
| 1082 | ReturnType: 3 | ||
| 1083 | ClassType: 4180 | ||
| 1084 | ThisType: 4188 | ||
| 1085 | CallConv: NearC | ||
| 1086 | Options: [ None, Constructor ] | ||
| 1087 | ParameterCount: 1 | ||
| 1088 | ArgumentList: 4190 | ||
| 1089 | ThisPointerAdjustment: 0 | ||
| 1090 | - Kind: LF_MFUNCTION | ||
| 1091 | MemberFunction: | ||
| 1092 | ReturnType: 3 | ||
| 1093 | ClassType: 4180 | ||
| 1094 | ThisType: 4188 | ||
| 1095 | CallConv: NearC | ||
| 1096 | Options: [ None, Constructor ] | ||
| 1097 | ParameterCount: 0 | ||
| 1098 | ArgumentList: 4100 | ||
| 1099 | ThisPointerAdjustment: 0 | ||
| 1100 | - Kind: LF_METHODLIST | ||
| 1101 | MethodOverloadList: | ||
| 1102 | Methods: | ||
| 1103 | - Type: 4189 | ||
| 1104 | Attrs: 3 | ||
| 1105 | VFTableOffset: -1 | ||
| 1106 | Name: '' | ||
| 1107 | - Type: 4191 | ||
| 1108 | Attrs: 3 | ||
| 1109 | VFTableOffset: -1 | ||
| 1110 | Name: '' | ||
| 1111 | - Type: 4192 | ||
| 1112 | Attrs: 3 | ||
| 1113 | VFTableOffset: -1 | ||
| 1114 | Name: '' | ||
| 1115 | - Kind: LF_FIELDLIST | ||
| 1116 | FieldList: | ||
| 1117 | - Kind: LF_NESTTYPE | ||
| 1118 | NestedType: | ||
| 1119 | Type: 4182 | ||
| 1120 | Name: type_e | ||
| 1121 | - Kind: LF_METHOD | ||
| 1122 | OverloadedMethod: | ||
| 1123 | NumOverloads: 3 | ||
| 1124 | MethodList: 4193 | ||
| 1125 | Name: moduleAttribute | ||
| 1126 | - Kind: LF_MEMBER | ||
| 1127 | DataMember: | ||
| 1128 | Attrs: 3 | ||
| 1129 | Type: 4182 | ||
| 1130 | FieldOffset: 0 | ||
| 1131 | Name: type | ||
| 1132 | - Kind: LF_MEMBER | ||
| 1133 | DataMember: | ||
| 1134 | Attrs: 3 | ||
| 1135 | Type: 4186 | ||
| 1136 | FieldOffset: 8 | ||
| 1137 | Name: name | ||
| 1138 | - Kind: LF_MEMBER | ||
| 1139 | DataMember: | ||
| 1140 | Attrs: 3 | ||
| 1141 | Type: 4186 | ||
| 1142 | FieldOffset: 16 | ||
| 1143 | Name: version | ||
| 1144 | - Kind: LF_MEMBER | ||
| 1145 | DataMember: | ||
| 1146 | Attrs: 3 | ||
| 1147 | Type: 4186 | ||
| 1148 | FieldOffset: 24 | ||
| 1149 | Name: uuid | ||
| 1150 | - Kind: LF_MEMBER | ||
| 1151 | DataMember: | ||
| 1152 | Attrs: 3 | ||
| 1153 | Type: 116 | ||
| 1154 | FieldOffset: 32 | ||
| 1155 | Name: lcid | ||
| 1156 | - Kind: LF_MEMBER | ||
| 1157 | DataMember: | ||
| 1158 | Attrs: 3 | ||
| 1159 | Type: 48 | ||
| 1160 | FieldOffset: 36 | ||
| 1161 | Name: control | ||
| 1162 | - Kind: LF_MEMBER | ||
| 1163 | DataMember: | ||
| 1164 | Attrs: 3 | ||
| 1165 | Type: 4186 | ||
| 1166 | FieldOffset: 40 | ||
| 1167 | Name: helpstring | ||
| 1168 | - Kind: LF_MEMBER | ||
| 1169 | DataMember: | ||
| 1170 | Attrs: 3 | ||
| 1171 | Type: 116 | ||
| 1172 | FieldOffset: 48 | ||
| 1173 | Name: helpstringcontext | ||
| 1174 | - Kind: LF_MEMBER | ||
| 1175 | DataMember: | ||
| 1176 | Attrs: 3 | ||
| 1177 | Type: 4186 | ||
| 1178 | FieldOffset: 56 | ||
| 1179 | Name: helpstringdll | ||
| 1180 | - Kind: LF_MEMBER | ||
| 1181 | DataMember: | ||
| 1182 | Attrs: 3 | ||
| 1183 | Type: 4186 | ||
| 1184 | FieldOffset: 64 | ||
| 1185 | Name: helpfile | ||
| 1186 | - Kind: LF_MEMBER | ||
| 1187 | DataMember: | ||
| 1188 | Attrs: 3 | ||
| 1189 | Type: 116 | ||
| 1190 | FieldOffset: 72 | ||
| 1191 | Name: helpcontext | ||
| 1192 | - Kind: LF_MEMBER | ||
| 1193 | DataMember: | ||
| 1194 | Attrs: 3 | ||
| 1195 | Type: 48 | ||
| 1196 | FieldOffset: 76 | ||
| 1197 | Name: hidden | ||
| 1198 | - Kind: LF_MEMBER | ||
| 1199 | DataMember: | ||
| 1200 | Attrs: 3 | ||
| 1201 | Type: 48 | ||
| 1202 | FieldOffset: 77 | ||
| 1203 | Name: restricted | ||
| 1204 | - Kind: LF_MEMBER | ||
| 1205 | DataMember: | ||
| 1206 | Attrs: 3 | ||
| 1207 | Type: 4186 | ||
| 1208 | FieldOffset: 80 | ||
| 1209 | Name: custom | ||
| 1210 | - Kind: LF_MEMBER | ||
| 1211 | DataMember: | ||
| 1212 | Attrs: 3 | ||
| 1213 | Type: 4186 | ||
| 1214 | FieldOffset: 88 | ||
| 1215 | Name: resource_name | ||
| 1216 | - Kind: LF_STRUCTURE | ||
| 1217 | Class: | ||
| 1218 | MemberCount: 19 | ||
| 1219 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1220 | FieldList: 4194 | ||
| 1221 | Name: '__vc_attributes::moduleAttribute' | ||
| 1222 | UniqueName: '.?AUmoduleAttribute@__vc_attributes@@' | ||
| 1223 | DerivationList: 0 | ||
| 1224 | VTableShape: 0 | ||
| 1225 | Size: 96 | ||
| 1226 | - Kind: LF_UDT_SRC_LINE | ||
| 1227 | UdtSourceLine: | ||
| 1228 | UDT: 4195 | ||
| 1229 | SourceFile: 4183 | ||
| 1230 | LineNumber: 481 | ||
| 1231 | - Kind: LF_STRUCTURE | ||
| 1232 | Class: | ||
| 1233 | MemberCount: 0 | ||
| 1234 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 1235 | FieldList: 0 | ||
| 1236 | Name: '__vc_attributes::event_receiverAttribute' | ||
| 1237 | UniqueName: '.?AUevent_receiverAttribute@__vc_attributes@@' | ||
| 1238 | DerivationList: 0 | ||
| 1239 | VTableShape: 0 | ||
| 1240 | Size: 0 | ||
| 1241 | - Kind: LF_FIELDLIST | ||
| 1242 | FieldList: | ||
| 1243 | - Kind: LF_ENUMERATE | ||
| 1244 | Enumerator: | ||
| 1245 | Attrs: 3 | ||
| 1246 | Value: 0 | ||
| 1247 | Name: native | ||
| 1248 | - Kind: LF_ENUMERATE | ||
| 1249 | Enumerator: | ||
| 1250 | Attrs: 3 | ||
| 1251 | Value: 1 | ||
| 1252 | Name: com | ||
| 1253 | - Kind: LF_ENUMERATE | ||
| 1254 | Enumerator: | ||
| 1255 | Attrs: 3 | ||
| 1256 | Value: 2 | ||
| 1257 | Name: managed | ||
| 1258 | - Kind: LF_ENUM | ||
| 1259 | Enum: | ||
| 1260 | NumEnumerators: 3 | ||
| 1261 | Options: [ None, Nested, HasUniqueName ] | ||
| 1262 | FieldList: 4198 | ||
| 1263 | Name: '__vc_attributes::event_receiverAttribute::type_e' | ||
| 1264 | UniqueName: '.?AW4type_e@event_receiverAttribute@__vc_attributes@@' | ||
| 1265 | UnderlyingType: 116 | ||
| 1266 | - Kind: LF_UDT_SRC_LINE | ||
| 1267 | UdtSourceLine: | ||
| 1268 | UDT: 4199 | ||
| 1269 | SourceFile: 4183 | ||
| 1270 | LineNumber: 136 | ||
| 1271 | - Kind: LF_ARGLIST | ||
| 1272 | ArgList: | ||
| 1273 | ArgIndices: [ 4199, 48 ] | ||
| 1274 | - Kind: LF_POINTER | ||
| 1275 | Pointer: | ||
| 1276 | ReferentType: 4197 | ||
| 1277 | Attrs: 66572 | ||
| 1278 | - Kind: LF_MFUNCTION | ||
| 1279 | MemberFunction: | ||
| 1280 | ReturnType: 3 | ||
| 1281 | ClassType: 4197 | ||
| 1282 | ThisType: 4202 | ||
| 1283 | CallConv: NearC | ||
| 1284 | Options: [ None, Constructor ] | ||
| 1285 | ParameterCount: 2 | ||
| 1286 | ArgumentList: 4201 | ||
| 1287 | ThisPointerAdjustment: 0 | ||
| 1288 | - Kind: LF_ARGLIST | ||
| 1289 | ArgList: | ||
| 1290 | ArgIndices: [ 4199 ] | ||
| 1291 | - Kind: LF_MFUNCTION | ||
| 1292 | MemberFunction: | ||
| 1293 | ReturnType: 3 | ||
| 1294 | ClassType: 4197 | ||
| 1295 | ThisType: 4202 | ||
| 1296 | CallConv: NearC | ||
| 1297 | Options: [ None, Constructor ] | ||
| 1298 | ParameterCount: 1 | ||
| 1299 | ArgumentList: 4204 | ||
| 1300 | ThisPointerAdjustment: 0 | ||
| 1301 | - Kind: LF_MFUNCTION | ||
| 1302 | MemberFunction: | ||
| 1303 | ReturnType: 3 | ||
| 1304 | ClassType: 4197 | ||
| 1305 | ThisType: 4202 | ||
| 1306 | CallConv: NearC | ||
| 1307 | Options: [ None, Constructor ] | ||
| 1308 | ParameterCount: 0 | ||
| 1309 | ArgumentList: 4100 | ||
| 1310 | ThisPointerAdjustment: 0 | ||
| 1311 | - Kind: LF_METHODLIST | ||
| 1312 | MethodOverloadList: | ||
| 1313 | Methods: | ||
| 1314 | - Type: 4203 | ||
| 1315 | Attrs: 3 | ||
| 1316 | VFTableOffset: -1 | ||
| 1317 | Name: '' | ||
| 1318 | - Type: 4205 | ||
| 1319 | Attrs: 3 | ||
| 1320 | VFTableOffset: -1 | ||
| 1321 | Name: '' | ||
| 1322 | - Type: 4206 | ||
| 1323 | Attrs: 3 | ||
| 1324 | VFTableOffset: -1 | ||
| 1325 | Name: '' | ||
| 1326 | - Kind: LF_FIELDLIST | ||
| 1327 | FieldList: | ||
| 1328 | - Kind: LF_NESTTYPE | ||
| 1329 | NestedType: | ||
| 1330 | Type: 4199 | ||
| 1331 | Name: type_e | ||
| 1332 | - Kind: LF_METHOD | ||
| 1333 | OverloadedMethod: | ||
| 1334 | NumOverloads: 3 | ||
| 1335 | MethodList: 4207 | ||
| 1336 | Name: event_receiverAttribute | ||
| 1337 | - Kind: LF_MEMBER | ||
| 1338 | DataMember: | ||
| 1339 | Attrs: 3 | ||
| 1340 | Type: 4199 | ||
| 1341 | FieldOffset: 0 | ||
| 1342 | Name: type | ||
| 1343 | - Kind: LF_MEMBER | ||
| 1344 | DataMember: | ||
| 1345 | Attrs: 3 | ||
| 1346 | Type: 48 | ||
| 1347 | FieldOffset: 4 | ||
| 1348 | Name: layout_dependent | ||
| 1349 | - Kind: LF_STRUCTURE | ||
| 1350 | Class: | ||
| 1351 | MemberCount: 6 | ||
| 1352 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1353 | FieldList: 4208 | ||
| 1354 | Name: '__vc_attributes::event_receiverAttribute' | ||
| 1355 | UniqueName: '.?AUevent_receiverAttribute@__vc_attributes@@' | ||
| 1356 | DerivationList: 0 | ||
| 1357 | VTableShape: 0 | ||
| 1358 | Size: 8 | ||
| 1359 | - Kind: LF_UDT_SRC_LINE | ||
| 1360 | UdtSourceLine: | ||
| 1361 | UDT: 4209 | ||
| 1362 | SourceFile: 4183 | ||
| 1363 | LineNumber: 135 | ||
| 1364 | - Kind: LF_STRUCTURE | ||
| 1365 | Class: | ||
| 1366 | MemberCount: 0 | ||
| 1367 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 1368 | FieldList: 0 | ||
| 1369 | Name: '__vc_attributes::aggregatableAttribute' | ||
| 1370 | UniqueName: '.?AUaggregatableAttribute@__vc_attributes@@' | ||
| 1371 | DerivationList: 0 | ||
| 1372 | VTableShape: 0 | ||
| 1373 | Size: 0 | ||
| 1374 | - Kind: LF_FIELDLIST | ||
| 1375 | FieldList: | ||
| 1376 | - Kind: LF_ENUMERATE | ||
| 1377 | Enumerator: | ||
| 1378 | Attrs: 3 | ||
| 1379 | Value: 0 | ||
| 1380 | Name: never | ||
| 1381 | - Kind: LF_ENUMERATE | ||
| 1382 | Enumerator: | ||
| 1383 | Attrs: 3 | ||
| 1384 | Value: 1 | ||
| 1385 | Name: allowed | ||
| 1386 | - Kind: LF_ENUMERATE | ||
| 1387 | Enumerator: | ||
| 1388 | Attrs: 3 | ||
| 1389 | Value: 2 | ||
| 1390 | Name: always | ||
| 1391 | - Kind: LF_ENUM | ||
| 1392 | Enum: | ||
| 1393 | NumEnumerators: 3 | ||
| 1394 | Options: [ None, Nested, HasUniqueName ] | ||
| 1395 | FieldList: 4212 | ||
| 1396 | Name: '__vc_attributes::aggregatableAttribute::type_e' | ||
| 1397 | UniqueName: '.?AW4type_e@aggregatableAttribute@__vc_attributes@@' | ||
| 1398 | UnderlyingType: 116 | ||
| 1399 | - Kind: LF_UDT_SRC_LINE | ||
| 1400 | UdtSourceLine: | ||
| 1401 | UDT: 4213 | ||
| 1402 | SourceFile: 4183 | ||
| 1403 | LineNumber: 545 | ||
| 1404 | - Kind: LF_ARGLIST | ||
| 1405 | ArgList: | ||
| 1406 | ArgIndices: [ 4213 ] | ||
| 1407 | - Kind: LF_POINTER | ||
| 1408 | Pointer: | ||
| 1409 | ReferentType: 4211 | ||
| 1410 | Attrs: 66572 | ||
| 1411 | - Kind: LF_MFUNCTION | ||
| 1412 | MemberFunction: | ||
| 1413 | ReturnType: 3 | ||
| 1414 | ClassType: 4211 | ||
| 1415 | ThisType: 4216 | ||
| 1416 | CallConv: NearC | ||
| 1417 | Options: [ None, Constructor ] | ||
| 1418 | ParameterCount: 1 | ||
| 1419 | ArgumentList: 4215 | ||
| 1420 | ThisPointerAdjustment: 0 | ||
| 1421 | - Kind: LF_MFUNCTION | ||
| 1422 | MemberFunction: | ||
| 1423 | ReturnType: 3 | ||
| 1424 | ClassType: 4211 | ||
| 1425 | ThisType: 4216 | ||
| 1426 | CallConv: NearC | ||
| 1427 | Options: [ None, Constructor ] | ||
| 1428 | ParameterCount: 0 | ||
| 1429 | ArgumentList: 4100 | ||
| 1430 | ThisPointerAdjustment: 0 | ||
| 1431 | - Kind: LF_METHODLIST | ||
| 1432 | MethodOverloadList: | ||
| 1433 | Methods: | ||
| 1434 | - Type: 4217 | ||
| 1435 | Attrs: 3 | ||
| 1436 | VFTableOffset: -1 | ||
| 1437 | Name: '' | ||
| 1438 | - Type: 4218 | ||
| 1439 | Attrs: 3 | ||
| 1440 | VFTableOffset: -1 | ||
| 1441 | Name: '' | ||
| 1442 | - Kind: LF_FIELDLIST | ||
| 1443 | FieldList: | ||
| 1444 | - Kind: LF_NESTTYPE | ||
| 1445 | NestedType: | ||
| 1446 | Type: 4213 | ||
| 1447 | Name: type_e | ||
| 1448 | - Kind: LF_METHOD | ||
| 1449 | OverloadedMethod: | ||
| 1450 | NumOverloads: 2 | ||
| 1451 | MethodList: 4219 | ||
| 1452 | Name: aggregatableAttribute | ||
| 1453 | - Kind: LF_MEMBER | ||
| 1454 | DataMember: | ||
| 1455 | Attrs: 3 | ||
| 1456 | Type: 4213 | ||
| 1457 | FieldOffset: 0 | ||
| 1458 | Name: type | ||
| 1459 | - Kind: LF_STRUCTURE | ||
| 1460 | Class: | ||
| 1461 | MemberCount: 4 | ||
| 1462 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1463 | FieldList: 4220 | ||
| 1464 | Name: '__vc_attributes::aggregatableAttribute' | ||
| 1465 | UniqueName: '.?AUaggregatableAttribute@__vc_attributes@@' | ||
| 1466 | DerivationList: 0 | ||
| 1467 | VTableShape: 0 | ||
| 1468 | Size: 4 | ||
| 1469 | - Kind: LF_UDT_SRC_LINE | ||
| 1470 | UdtSourceLine: | ||
| 1471 | UDT: 4221 | ||
| 1472 | SourceFile: 4183 | ||
| 1473 | LineNumber: 544 | ||
| 1474 | - Kind: LF_STRUCTURE | ||
| 1475 | Class: | ||
| 1476 | MemberCount: 0 | ||
| 1477 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 1478 | FieldList: 0 | ||
| 1479 | Name: '__vc_attributes::threadingAttribute' | ||
| 1480 | UniqueName: '.?AUthreadingAttribute@__vc_attributes@@' | ||
| 1481 | DerivationList: 0 | ||
| 1482 | VTableShape: 0 | ||
| 1483 | Size: 0 | ||
| 1484 | - Kind: LF_FIELDLIST | ||
| 1485 | FieldList: | ||
| 1486 | - Kind: LF_ENUMERATE | ||
| 1487 | Enumerator: | ||
| 1488 | Attrs: 3 | ||
| 1489 | Value: 1 | ||
| 1490 | Name: apartment | ||
| 1491 | - Kind: LF_ENUMERATE | ||
| 1492 | Enumerator: | ||
| 1493 | Attrs: 3 | ||
| 1494 | Value: 2 | ||
| 1495 | Name: single | ||
| 1496 | - Kind: LF_ENUMERATE | ||
| 1497 | Enumerator: | ||
| 1498 | Attrs: 3 | ||
| 1499 | Value: 3 | ||
| 1500 | Name: free | ||
| 1501 | - Kind: LF_ENUMERATE | ||
| 1502 | Enumerator: | ||
| 1503 | Attrs: 3 | ||
| 1504 | Value: 4 | ||
| 1505 | Name: neutral | ||
| 1506 | - Kind: LF_ENUMERATE | ||
| 1507 | Enumerator: | ||
| 1508 | Attrs: 3 | ||
| 1509 | Value: 5 | ||
| 1510 | Name: both | ||
| 1511 | - Kind: LF_ENUM | ||
| 1512 | Enum: | ||
| 1513 | NumEnumerators: 5 | ||
| 1514 | Options: [ None, Nested, HasUniqueName ] | ||
| 1515 | FieldList: 4224 | ||
| 1516 | Name: '__vc_attributes::threadingAttribute::threading_e' | ||
| 1517 | UniqueName: '.?AW4threading_e@threadingAttribute@__vc_attributes@@' | ||
| 1518 | UnderlyingType: 116 | ||
| 1519 | - Kind: LF_UDT_SRC_LINE | ||
| 1520 | UdtSourceLine: | ||
| 1521 | UDT: 4225 | ||
| 1522 | SourceFile: 4183 | ||
| 1523 | LineNumber: 423 | ||
| 1524 | - Kind: LF_ARGLIST | ||
| 1525 | ArgList: | ||
| 1526 | ArgIndices: [ 4225 ] | ||
| 1527 | - Kind: LF_POINTER | ||
| 1528 | Pointer: | ||
| 1529 | ReferentType: 4223 | ||
| 1530 | Attrs: 66572 | ||
| 1531 | - Kind: LF_MFUNCTION | ||
| 1532 | MemberFunction: | ||
| 1533 | ReturnType: 3 | ||
| 1534 | ClassType: 4223 | ||
| 1535 | ThisType: 4228 | ||
| 1536 | CallConv: NearC | ||
| 1537 | Options: [ None, Constructor ] | ||
| 1538 | ParameterCount: 1 | ||
| 1539 | ArgumentList: 4227 | ||
| 1540 | ThisPointerAdjustment: 0 | ||
| 1541 | - Kind: LF_MFUNCTION | ||
| 1542 | MemberFunction: | ||
| 1543 | ReturnType: 3 | ||
| 1544 | ClassType: 4223 | ||
| 1545 | ThisType: 4228 | ||
| 1546 | CallConv: NearC | ||
| 1547 | Options: [ None, Constructor ] | ||
| 1548 | ParameterCount: 0 | ||
| 1549 | ArgumentList: 4100 | ||
| 1550 | ThisPointerAdjustment: 0 | ||
| 1551 | - Kind: LF_METHODLIST | ||
| 1552 | MethodOverloadList: | ||
| 1553 | Methods: | ||
| 1554 | - Type: 4229 | ||
| 1555 | Attrs: 3 | ||
| 1556 | VFTableOffset: -1 | ||
| 1557 | Name: '' | ||
| 1558 | - Type: 4230 | ||
| 1559 | Attrs: 3 | ||
| 1560 | VFTableOffset: -1 | ||
| 1561 | Name: '' | ||
| 1562 | - Kind: LF_FIELDLIST | ||
| 1563 | FieldList: | ||
| 1564 | - Kind: LF_NESTTYPE | ||
| 1565 | NestedType: | ||
| 1566 | Type: 4225 | ||
| 1567 | Name: threading_e | ||
| 1568 | - Kind: LF_METHOD | ||
| 1569 | OverloadedMethod: | ||
| 1570 | NumOverloads: 2 | ||
| 1571 | MethodList: 4231 | ||
| 1572 | Name: threadingAttribute | ||
| 1573 | - Kind: LF_MEMBER | ||
| 1574 | DataMember: | ||
| 1575 | Attrs: 3 | ||
| 1576 | Type: 4225 | ||
| 1577 | FieldOffset: 0 | ||
| 1578 | Name: value | ||
| 1579 | - Kind: LF_STRUCTURE | ||
| 1580 | Class: | ||
| 1581 | MemberCount: 4 | ||
| 1582 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1583 | FieldList: 4232 | ||
| 1584 | Name: '__vc_attributes::threadingAttribute' | ||
| 1585 | UniqueName: '.?AUthreadingAttribute@__vc_attributes@@' | ||
| 1586 | DerivationList: 0 | ||
| 1587 | VTableShape: 0 | ||
| 1588 | Size: 4 | ||
| 1589 | - Kind: LF_UDT_SRC_LINE | ||
| 1590 | UdtSourceLine: | ||
| 1591 | UDT: 4233 | ||
| 1592 | SourceFile: 4183 | ||
| 1593 | LineNumber: 422 | ||
| 1594 | - Kind: LF_STRUCTURE | ||
| 1595 | Class: | ||
| 1596 | MemberCount: 0 | ||
| 1597 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 1598 | FieldList: 0 | ||
| 1599 | Name: '__vc_attributes::helper_attributes::usageAttribute' | ||
| 1600 | UniqueName: '.?AUusageAttribute@helper_attributes@__vc_attributes@@' | ||
| 1601 | DerivationList: 0 | ||
| 1602 | VTableShape: 0 | ||
| 1603 | Size: 0 | ||
| 1604 | - Kind: LF_FIELDLIST | ||
| 1605 | FieldList: | ||
| 1606 | - Kind: LF_ENUMERATE | ||
| 1607 | Enumerator: | ||
| 1608 | Attrs: 3 | ||
| 1609 | Value: 0 | ||
| 1610 | Name: eAnyUsage | ||
| 1611 | - Kind: LF_ENUMERATE | ||
| 1612 | Enumerator: | ||
| 1613 | Attrs: 3 | ||
| 1614 | Value: 1 | ||
| 1615 | Name: eCoClassUsage | ||
| 1616 | - Kind: LF_ENUMERATE | ||
| 1617 | Enumerator: | ||
| 1618 | Attrs: 3 | ||
| 1619 | Value: 2 | ||
| 1620 | Name: eCOMInterfaceUsage | ||
| 1621 | - Kind: LF_ENUMERATE | ||
| 1622 | Enumerator: | ||
| 1623 | Attrs: 3 | ||
| 1624 | Value: 6 | ||
| 1625 | Name: eInterfaceUsage | ||
| 1626 | - Kind: LF_ENUMERATE | ||
| 1627 | Enumerator: | ||
| 1628 | Attrs: 3 | ||
| 1629 | Value: 8 | ||
| 1630 | Name: eMemberUsage | ||
| 1631 | - Kind: LF_ENUMERATE | ||
| 1632 | Enumerator: | ||
| 1633 | Attrs: 3 | ||
| 1634 | Value: 16 | ||
| 1635 | Name: eMethodUsage | ||
| 1636 | - Kind: LF_ENUMERATE | ||
| 1637 | Enumerator: | ||
| 1638 | Attrs: 3 | ||
| 1639 | Value: 32 | ||
| 1640 | Name: eInterfaceMethodUsage | ||
| 1641 | - Kind: LF_ENUMERATE | ||
| 1642 | Enumerator: | ||
| 1643 | Attrs: 3 | ||
| 1644 | Value: 64 | ||
| 1645 | Name: eInterfaceMemberUsage | ||
| 1646 | - Kind: LF_ENUMERATE | ||
| 1647 | Enumerator: | ||
| 1648 | Attrs: 3 | ||
| 1649 | Value: 128 | ||
| 1650 | Name: eCoClassMemberUsage | ||
| 1651 | - Kind: LF_ENUMERATE | ||
| 1652 | Enumerator: | ||
| 1653 | Attrs: 3 | ||
| 1654 | Value: 256 | ||
| 1655 | Name: eCoClassMethodUsage | ||
| 1656 | - Kind: LF_ENUMERATE | ||
| 1657 | Enumerator: | ||
| 1658 | Attrs: 3 | ||
| 1659 | Value: 768 | ||
| 1660 | Name: eGlobalMethodUsage | ||
| 1661 | - Kind: LF_ENUMERATE | ||
| 1662 | Enumerator: | ||
| 1663 | Attrs: 3 | ||
| 1664 | Value: 1024 | ||
| 1665 | Name: eGlobalDataUsage | ||
| 1666 | - Kind: LF_ENUMERATE | ||
| 1667 | Enumerator: | ||
| 1668 | Attrs: 3 | ||
| 1669 | Value: 2048 | ||
| 1670 | Name: eClassUsage | ||
| 1671 | - Kind: LF_ENUMERATE | ||
| 1672 | Enumerator: | ||
| 1673 | Attrs: 3 | ||
| 1674 | Value: 4096 | ||
| 1675 | Name: eInterfaceParameterUsage | ||
| 1676 | - Kind: LF_ENUMERATE | ||
| 1677 | Enumerator: | ||
| 1678 | Attrs: 3 | ||
| 1679 | Value: 12288 | ||
| 1680 | Name: eMethodParameterUsage | ||
| 1681 | - Kind: LF_ENUMERATE | ||
| 1682 | Enumerator: | ||
| 1683 | Attrs: 3 | ||
| 1684 | Value: 16384 | ||
| 1685 | Name: eIDLModuleUsage | ||
| 1686 | - Kind: LF_ENUMERATE | ||
| 1687 | Enumerator: | ||
| 1688 | Attrs: 3 | ||
| 1689 | Value: 32768 | ||
| 1690 | Name: eAnonymousUsage | ||
| 1691 | - Kind: LF_ENUMERATE | ||
| 1692 | Enumerator: | ||
| 1693 | Attrs: 3 | ||
| 1694 | Value: 65536 | ||
| 1695 | Name: eTypedefUsage | ||
| 1696 | - Kind: LF_ENUMERATE | ||
| 1697 | Enumerator: | ||
| 1698 | Attrs: 3 | ||
| 1699 | Value: 131072 | ||
| 1700 | Name: eUnionUsage | ||
| 1701 | - Kind: LF_ENUMERATE | ||
| 1702 | Enumerator: | ||
| 1703 | Attrs: 3 | ||
| 1704 | Value: 262144 | ||
| 1705 | Name: eEnumUsage | ||
| 1706 | - Kind: LF_ENUMERATE | ||
| 1707 | Enumerator: | ||
| 1708 | Attrs: 3 | ||
| 1709 | Value: 524288 | ||
| 1710 | Name: eDefineTagUsage | ||
| 1711 | - Kind: LF_ENUMERATE | ||
| 1712 | Enumerator: | ||
| 1713 | Attrs: 3 | ||
| 1714 | Value: 1048576 | ||
| 1715 | Name: eStructUsage | ||
| 1716 | - Kind: LF_ENUMERATE | ||
| 1717 | Enumerator: | ||
| 1718 | Attrs: 3 | ||
| 1719 | Value: 2097152 | ||
| 1720 | Name: eLocalUsage | ||
| 1721 | - Kind: LF_ENUMERATE | ||
| 1722 | Enumerator: | ||
| 1723 | Attrs: 3 | ||
| 1724 | Value: 4194304 | ||
| 1725 | Name: ePropertyUsage | ||
| 1726 | - Kind: LF_ENUMERATE | ||
| 1727 | Enumerator: | ||
| 1728 | Attrs: 3 | ||
| 1729 | Value: 8388608 | ||
| 1730 | Name: eEventUsage | ||
| 1731 | - Kind: LF_ENUMERATE | ||
| 1732 | Enumerator: | ||
| 1733 | Attrs: 3 | ||
| 1734 | Value: 16777216 | ||
| 1735 | Name: eTemplateUsage | ||
| 1736 | - Kind: LF_ENUMERATE | ||
| 1737 | Enumerator: | ||
| 1738 | Attrs: 3 | ||
| 1739 | Value: 16777216 | ||
| 1740 | Name: eModuleUsage | ||
| 1741 | - Kind: LF_ENUMERATE | ||
| 1742 | Enumerator: | ||
| 1743 | Attrs: 3 | ||
| 1744 | Value: 33554432 | ||
| 1745 | Name: eIllegalUsage | ||
| 1746 | - Kind: LF_ENUMERATE | ||
| 1747 | Enumerator: | ||
| 1748 | Attrs: 3 | ||
| 1749 | Value: 67108864 | ||
| 1750 | Name: eAsynchronousUsage | ||
| 1751 | - Kind: LF_ENUMERATE | ||
| 1752 | Enumerator: | ||
| 1753 | Attrs: 3 | ||
| 1754 | Value: 4161535 | ||
| 1755 | Name: eAnyIDLUsage | ||
| 1756 | - Kind: LF_ENUM | ||
| 1757 | Enum: | ||
| 1758 | NumEnumerators: 30 | ||
| 1759 | Options: [ None, Nested, HasUniqueName ] | ||
| 1760 | FieldList: 4236 | ||
| 1761 | Name: '__vc_attributes::helper_attributes::usageAttribute::usage_e' | ||
| 1762 | UniqueName: '.?AW4usage_e@usageAttribute@helper_attributes@__vc_attributes@@' | ||
| 1763 | UnderlyingType: 116 | ||
| 1764 | - Kind: LF_UDT_SRC_LINE | ||
| 1765 | UdtSourceLine: | ||
| 1766 | UDT: 4237 | ||
| 1767 | SourceFile: 4183 | ||
| 1768 | LineNumber: 51 | ||
| 1769 | - Kind: LF_ARGLIST | ||
| 1770 | ArgList: | ||
| 1771 | ArgIndices: [ 117 ] | ||
| 1772 | - Kind: LF_POINTER | ||
| 1773 | Pointer: | ||
| 1774 | ReferentType: 4235 | ||
| 1775 | Attrs: 66572 | ||
| 1776 | - Kind: LF_MFUNCTION | ||
| 1777 | MemberFunction: | ||
| 1778 | ReturnType: 3 | ||
| 1779 | ClassType: 4235 | ||
| 1780 | ThisType: 4240 | ||
| 1781 | CallConv: NearC | ||
| 1782 | Options: [ None, Constructor ] | ||
| 1783 | ParameterCount: 1 | ||
| 1784 | ArgumentList: 4239 | ||
| 1785 | ThisPointerAdjustment: 0 | ||
| 1786 | - Kind: LF_FIELDLIST | ||
| 1787 | FieldList: | ||
| 1788 | - Kind: LF_NESTTYPE | ||
| 1789 | NestedType: | ||
| 1790 | Type: 4237 | ||
| 1791 | Name: usage_e | ||
| 1792 | - Kind: LF_ONEMETHOD | ||
| 1793 | OneMethod: | ||
| 1794 | Type: 4241 | ||
| 1795 | Attrs: 3 | ||
| 1796 | VFTableOffset: -1 | ||
| 1797 | Name: usageAttribute | ||
| 1798 | - Kind: LF_MEMBER | ||
| 1799 | DataMember: | ||
| 1800 | Attrs: 3 | ||
| 1801 | Type: 117 | ||
| 1802 | FieldOffset: 0 | ||
| 1803 | Name: value | ||
| 1804 | - Kind: LF_STRUCTURE | ||
| 1805 | Class: | ||
| 1806 | MemberCount: 3 | ||
| 1807 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1808 | FieldList: 4242 | ||
| 1809 | Name: '__vc_attributes::helper_attributes::usageAttribute' | ||
| 1810 | UniqueName: '.?AUusageAttribute@helper_attributes@__vc_attributes@@' | ||
| 1811 | DerivationList: 0 | ||
| 1812 | VTableShape: 0 | ||
| 1813 | Size: 4 | ||
| 1814 | - Kind: LF_UDT_SRC_LINE | ||
| 1815 | UdtSourceLine: | ||
| 1816 | UDT: 4243 | ||
| 1817 | SourceFile: 4183 | ||
| 1818 | LineNumber: 49 | ||
| 1819 | - Kind: LF_STRUCTURE | ||
| 1820 | Class: | ||
| 1821 | MemberCount: 0 | ||
| 1822 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 1823 | FieldList: 0 | ||
| 1824 | Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute' | ||
| 1825 | UniqueName: '.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@' | ||
| 1826 | DerivationList: 0 | ||
| 1827 | VTableShape: 0 | ||
| 1828 | Size: 0 | ||
| 1829 | - Kind: LF_FIELDLIST | ||
| 1830 | FieldList: | ||
| 1831 | - Kind: LF_ENUMERATE | ||
| 1832 | Enumerator: | ||
| 1833 | Attrs: 3 | ||
| 1834 | Value: 0 | ||
| 1835 | Name: eBoolean | ||
| 1836 | - Kind: LF_ENUMERATE | ||
| 1837 | Enumerator: | ||
| 1838 | Attrs: 3 | ||
| 1839 | Value: 1 | ||
| 1840 | Name: eInteger | ||
| 1841 | - Kind: LF_ENUMERATE | ||
| 1842 | Enumerator: | ||
| 1843 | Attrs: 3 | ||
| 1844 | Value: 2 | ||
| 1845 | Name: eFloat | ||
| 1846 | - Kind: LF_ENUMERATE | ||
| 1847 | Enumerator: | ||
| 1848 | Attrs: 3 | ||
| 1849 | Value: 3 | ||
| 1850 | Name: eDouble | ||
| 1851 | - Kind: LF_ENUM | ||
| 1852 | Enum: | ||
| 1853 | NumEnumerators: 4 | ||
| 1854 | Options: [ None, Nested, HasUniqueName ] | ||
| 1855 | FieldList: 4246 | ||
| 1856 | Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e' | ||
| 1857 | UniqueName: '.?AW4type_e@v1_alttypeAttribute@helper_attributes@__vc_attributes@@' | ||
| 1858 | UnderlyingType: 116 | ||
| 1859 | - Kind: LF_UDT_SRC_LINE | ||
| 1860 | UdtSourceLine: | ||
| 1861 | UDT: 4247 | ||
| 1862 | SourceFile: 4183 | ||
| 1863 | LineNumber: 38 | ||
| 1864 | - Kind: LF_ARGLIST | ||
| 1865 | ArgList: | ||
| 1866 | ArgIndices: [ 4247 ] | ||
| 1867 | - Kind: LF_POINTER | ||
| 1868 | Pointer: | ||
| 1869 | ReferentType: 4245 | ||
| 1870 | Attrs: 66572 | ||
| 1871 | - Kind: LF_MFUNCTION | ||
| 1872 | MemberFunction: | ||
| 1873 | ReturnType: 3 | ||
| 1874 | ClassType: 4245 | ||
| 1875 | ThisType: 4250 | ||
| 1876 | CallConv: NearC | ||
| 1877 | Options: [ None, Constructor ] | ||
| 1878 | ParameterCount: 1 | ||
| 1879 | ArgumentList: 4249 | ||
| 1880 | ThisPointerAdjustment: 0 | ||
| 1881 | - Kind: LF_FIELDLIST | ||
| 1882 | FieldList: | ||
| 1883 | - Kind: LF_NESTTYPE | ||
| 1884 | NestedType: | ||
| 1885 | Type: 4247 | ||
| 1886 | Name: type_e | ||
| 1887 | - Kind: LF_ONEMETHOD | ||
| 1888 | OneMethod: | ||
| 1889 | Type: 4251 | ||
| 1890 | Attrs: 3 | ||
| 1891 | VFTableOffset: -1 | ||
| 1892 | Name: v1_alttypeAttribute | ||
| 1893 | - Kind: LF_MEMBER | ||
| 1894 | DataMember: | ||
| 1895 | Attrs: 3 | ||
| 1896 | Type: 4247 | ||
| 1897 | FieldOffset: 0 | ||
| 1898 | Name: type | ||
| 1899 | - Kind: LF_STRUCTURE | ||
| 1900 | Class: | ||
| 1901 | MemberCount: 3 | ||
| 1902 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 1903 | FieldList: 4252 | ||
| 1904 | Name: '__vc_attributes::helper_attributes::v1_alttypeAttribute' | ||
| 1905 | UniqueName: '.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@' | ||
| 1906 | DerivationList: 0 | ||
| 1907 | VTableShape: 0 | ||
| 1908 | Size: 4 | ||
| 1909 | - Kind: LF_UDT_SRC_LINE | ||
| 1910 | UdtSourceLine: | ||
| 1911 | UDT: 4253 | ||
| 1912 | SourceFile: 4183 | ||
| 1913 | LineNumber: 37 | ||
| 1914 | - Kind: LF_STRUCTURE | ||
| 1915 | Class: | ||
| 1916 | MemberCount: 0 | ||
| 1917 | Options: [ None, ForwardReference, HasUniqueName ] | ||
| 1918 | FieldList: 0 | ||
| 1919 | Name: '__vc_attributes::event_sourceAttribute' | ||
| 1920 | UniqueName: '.?AUevent_sourceAttribute@__vc_attributes@@' | ||
| 1921 | DerivationList: 0 | ||
| 1922 | VTableShape: 0 | ||
| 1923 | Size: 0 | ||
| 1924 | - Kind: LF_FIELDLIST | ||
| 1925 | FieldList: | ||
| 1926 | - Kind: LF_ENUMERATE | ||
| 1927 | Enumerator: | ||
| 1928 | Attrs: 3 | ||
| 1929 | Value: 0 | ||
| 1930 | Name: native | ||
| 1931 | - Kind: LF_ENUMERATE | ||
| 1932 | Enumerator: | ||
| 1933 | Attrs: 3 | ||
| 1934 | Value: 1 | ||
| 1935 | Name: com | ||
| 1936 | - Kind: LF_ENUMERATE | ||
| 1937 | Enumerator: | ||
| 1938 | Attrs: 3 | ||
| 1939 | Value: 2 | ||
| 1940 | Name: managed | ||
| 1941 | - Kind: LF_ENUM | ||
| 1942 | Enum: | ||
| 1943 | NumEnumerators: 3 | ||
| 1944 | Options: [ None, Nested, HasUniqueName ] | ||
| 1945 | FieldList: 4256 | ||
| 1946 | Name: '__vc_attributes::event_sourceAttribute::type_e' | ||
| 1947 | UniqueName: '.?AW4type_e@event_sourceAttribute@__vc_attributes@@' | ||
| 1948 | UnderlyingType: 116 | ||
| 1949 | - Kind: LF_UDT_SRC_LINE | ||
| 1950 | UdtSourceLine: | ||
| 1951 | UDT: 4257 | ||
| 1952 | SourceFile: 4183 | ||
| 1953 | LineNumber: 1142 | ||
| 1954 | - Kind: LF_FIELDLIST | ||
| 1955 | FieldList: | ||
| 1956 | - Kind: LF_ENUMERATE | ||
| 1957 | Enumerator: | ||
| 1958 | Attrs: 3 | ||
| 1959 | Value: 0 | ||
| 1960 | Name: speed | ||
| 1961 | - Kind: LF_ENUMERATE | ||
| 1962 | Enumerator: | ||
| 1963 | Attrs: 3 | ||
| 1964 | Value: 1 | ||
| 1965 | Name: size | ||
| 1966 | - Kind: LF_ENUM | ||
| 1967 | Enum: | ||
| 1968 | NumEnumerators: 2 | ||
| 1969 | Options: [ None, Nested, HasUniqueName ] | ||
| 1970 | FieldList: 4259 | ||
| 1971 | Name: '__vc_attributes::event_sourceAttribute::optimize_e' | ||
| 1972 | UniqueName: '.?AW4optimize_e@event_sourceAttribute@__vc_attributes@@' | ||
| 1973 | UnderlyingType: 116 | ||
| 1974 | - Kind: LF_UDT_SRC_LINE | ||
| 1975 | UdtSourceLine: | ||
| 1976 | UDT: 4260 | ||
| 1977 | SourceFile: 4183 | ||
| 1978 | LineNumber: 1145 | ||
| 1979 | - Kind: LF_ARGLIST | ||
| 1980 | ArgList: | ||
| 1981 | ArgIndices: [ 4257 ] | ||
| 1982 | - Kind: LF_POINTER | ||
| 1983 | Pointer: | ||
| 1984 | ReferentType: 4255 | ||
| 1985 | Attrs: 66572 | ||
| 1986 | - Kind: LF_MFUNCTION | ||
| 1987 | MemberFunction: | ||
| 1988 | ReturnType: 3 | ||
| 1989 | ClassType: 4255 | ||
| 1990 | ThisType: 4263 | ||
| 1991 | CallConv: NearC | ||
| 1992 | Options: [ None, Constructor ] | ||
| 1993 | ParameterCount: 1 | ||
| 1994 | ArgumentList: 4262 | ||
| 1995 | ThisPointerAdjustment: 0 | ||
| 1996 | - Kind: LF_MFUNCTION | ||
| 1997 | MemberFunction: | ||
| 1998 | ReturnType: 3 | ||
| 1999 | ClassType: 4255 | ||
| 2000 | ThisType: 4263 | ||
| 2001 | CallConv: NearC | ||
| 2002 | Options: [ None, Constructor ] | ||
| 2003 | ParameterCount: 0 | ||
| 2004 | ArgumentList: 4100 | ||
| 2005 | ThisPointerAdjustment: 0 | ||
| 2006 | - Kind: LF_METHODLIST | ||
| 2007 | MethodOverloadList: | ||
| 2008 | Methods: | ||
| 2009 | - Type: 4264 | ||
| 2010 | Attrs: 3 | ||
| 2011 | VFTableOffset: -1 | ||
| 2012 | Name: '' | ||
| 2013 | - Type: 4265 | ||
| 2014 | Attrs: 3 | ||
| 2015 | VFTableOffset: -1 | ||
| 2016 | Name: '' | ||
| 2017 | - Kind: LF_FIELDLIST | ||
| 2018 | FieldList: | ||
| 2019 | - Kind: LF_NESTTYPE | ||
| 2020 | NestedType: | ||
| 2021 | Type: 4257 | ||
| 2022 | Name: type_e | ||
| 2023 | - Kind: LF_NESTTYPE | ||
| 2024 | NestedType: | ||
| 2025 | Type: 4260 | ||
| 2026 | Name: optimize_e | ||
| 2027 | - Kind: LF_METHOD | ||
| 2028 | OverloadedMethod: | ||
| 2029 | NumOverloads: 2 | ||
| 2030 | MethodList: 4266 | ||
| 2031 | Name: event_sourceAttribute | ||
| 2032 | - Kind: LF_MEMBER | ||
| 2033 | DataMember: | ||
| 2034 | Attrs: 3 | ||
| 2035 | Type: 4257 | ||
| 2036 | FieldOffset: 0 | ||
| 2037 | Name: type | ||
| 2038 | - Kind: LF_MEMBER | ||
| 2039 | DataMember: | ||
| 2040 | Attrs: 3 | ||
| 2041 | Type: 4260 | ||
| 2042 | FieldOffset: 4 | ||
| 2043 | Name: optimize | ||
| 2044 | - Kind: LF_MEMBER | ||
| 2045 | DataMember: | ||
| 2046 | Attrs: 3 | ||
| 2047 | Type: 48 | ||
| 2048 | FieldOffset: 8 | ||
| 2049 | Name: decorate | ||
| 2050 | - Kind: LF_STRUCTURE | ||
| 2051 | Class: | ||
| 2052 | MemberCount: 7 | ||
| 2053 | Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] | ||
| 2054 | FieldList: 4267 | ||
| 2055 | Name: '__vc_attributes::event_sourceAttribute' | ||
| 2056 | UniqueName: '.?AUevent_sourceAttribute@__vc_attributes@@' | ||
| 2057 | DerivationList: 0 | ||
| 2058 | VTableShape: 0 | ||
| 2059 | Size: 12 | ||
| 2060 | - Kind: LF_UDT_SRC_LINE | ||
| 2061 | UdtSourceLine: | ||
| 2062 | UDT: 4268 | ||
| 2063 | SourceFile: 4183 | ||
| 2064 | LineNumber: 1141 | ||
| 2065 | - Kind: LF_VFTABLE | ||
| 2066 | VFTable: | ||
| 2067 | CompleteClass: 4117 | ||
| 2068 | OverriddenVFTable: 0 | ||
| 2069 | VFPtrOffset: 0 | ||
| 2070 | MethodNames: | ||
| 2071 | - '??_7A@@6B@' | ||
| 2072 | - '?f@A@@UEAAHXZ' | ||
| 2073 | - Kind: LF_VFTABLE | ||
| 2074 | VFTable: | ||
| 2075 | CompleteClass: 4140 | ||
| 2076 | OverriddenVFTable: 0 | ||
| 2077 | VFPtrOffset: 0 | ||
| 2078 | MethodNames: | ||
| 2079 | - '??_7B@@6B@' | ||
| 2080 | - '?f@B@@UEAAHXZ' | ||
| 2081 | - Kind: LF_VFTABLE | ||
| 2082 | VFTable: | ||
| 2083 | CompleteClass: 4160 | ||
| 2084 | OverriddenVFTable: 4270 | ||
| 2085 | VFPtrOffset: 0 | ||
| 2086 | MethodNames: | ||
| 2087 | - '??_7C@@6BA@@@' | ||
| 2088 | - '?f@C@@UEAAHXZ' | ||
| 2089 | - Kind: LF_VFTABLE | ||
| 2090 | VFTable: | ||
| 2091 | CompleteClass: 4160 | ||
| 2092 | OverriddenVFTable: 4271 | ||
| 2093 | VFPtrOffset: 8 | ||
| 2094 | MethodNames: | ||
| 2095 | - '??_7C@@6BB@@@' | ||
| 2096 | - '?f@C@@W7EAAHXZ' | ||
| 2097 | - Kind: LF_STRING_ID | ||
| 2098 | StringId: | ||
| 2099 | Id: 0 | ||
| 2100 | String: 'C:\src\llvm-project\build' | ||
| 2101 | - Kind: LF_STRING_ID | ||
| 2102 | StringId: | ||
| 2103 | Id: 0 | ||
| 2104 | String: 'C:\PROGRA~2\MICROS~1\2017\PROFES~1\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\cl.exe' | ||
| 2105 | - Kind: LF_STRING_ID | ||
| 2106 | StringId: | ||
| 2107 | Id: 0 | ||
| 2108 | String: '-GR- -Z7 -c -MT -IC:\PROGRA~2\MICROS~1\2017\PROFES~1\VC\Tools\MSVC\14.11.25503\ATLMFC\include -IC:\PROGRA~2\MICROS~1\2017\PROFES~1\VC\Tools\MSVC\14.11.25503\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.16299.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.162' | ||
| 2109 | - Kind: LF_SUBSTR_LIST | ||
| 2110 | StringList: | ||
| 2111 | StringIndices: [ 4276 ] | ||
| 2112 | - Kind: LF_STRING_ID | ||
| 2113 | StringId: | ||
| 2114 | Id: 4277 | ||
| 2115 | String: '99.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.16299.0\um -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.16299.0\winrt -TP -X' | ||
| 2116 | - Kind: LF_STRING_ID | ||
| 2117 | StringId: | ||
| 2118 | Id: 0 | ||
| 2119 | String: t.cpp | ||
| 2120 | - Kind: LF_STRING_ID | ||
| 2121 | StringId: | ||
| 2122 | Id: 0 | ||
| 2123 | String: 'C:\src\llvm-project\build\vc140.pdb' | ||
| 2124 | - Kind: LF_BUILDINFO | ||
| 2125 | BuildInfo: | ||
| 2126 | ArgIndices: [ 4274, 4275, 4279, 4280, 4278 ] | ||
| 2127 | - Name: '.text$mn' | ||
| 2128 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 2129 | Alignment: 16 | ||
| 2130 | SectionData: 48894C240833C0C3CCCCCCCCCCCCCCCC48894C240833C0C3CCCCCCCCCCCCCCCC48894C24084883EC28488B4C2430E800000000488B4424304883C008488BC8E800000000488B442430488D0D00000000488908488B442430488D0D0000000048894808488B442430C740102A000000488B4424304883C428C3CCCCCCCCCCCCCC48894C2408488B4424088B4010C3 | ||
| 2131 | Relocations: | ||
| 2132 | - VirtualAddress: 47 | ||
| 2133 | SymbolName: '??0A@@QEAA@XZ' | ||
| 2134 | Type: IMAGE_REL_AMD64_REL32 | ||
| 2135 | - VirtualAddress: 64 | ||
| 2136 | SymbolName: '??0B@@QEAA@XZ' | ||
| 2137 | Type: IMAGE_REL_AMD64_REL32 | ||
| 2138 | - VirtualAddress: 76 | ||
| 2139 | SymbolName: '??_7C@@6BA@@@' | ||
| 2140 | Type: IMAGE_REL_AMD64_REL32 | ||
| 2141 | - VirtualAddress: 91 | ||
| 2142 | SymbolName: '??_7C@@6BB@@@' | ||
| 2143 | Type: IMAGE_REL_AMD64_REL32 | ||
| 2144 | - Name: '.text$mn' | ||
| 2145 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 2146 | Alignment: 16 | ||
| 2147 | SectionData: 48894C2408488B442408488D0D00000000488908488B442408C3 | ||
| 2148 | Relocations: | ||
| 2149 | - VirtualAddress: 13 | ||
| 2150 | SymbolName: '??_7A@@6B@' | ||
| 2151 | Type: IMAGE_REL_AMD64_REL32 | ||
| 2152 | - Name: '.debug$S' | ||
| 2153 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 2154 | Alignment: 1 | ||
| 2155 | Subsections: | ||
| 2156 | - !Symbols | ||
| 2157 | Records: | ||
| 2158 | - Kind: S_GPROC32_ID | ||
| 2159 | ProcSym: | ||
| 2160 | CodeSize: 26 | ||
| 2161 | DbgStart: 5 | ||
| 2162 | DbgEnd: 25 | ||
| 2163 | FunctionType: 4176 | ||
| 2164 | Flags: [ ] | ||
| 2165 | DisplayName: 'A::A' | ||
| 2166 | - Kind: S_FRAMEPROC | ||
| 2167 | FrameProcSym: | ||
| 2168 | TotalFrameBytes: 0 | ||
| 2169 | PaddingFrameBytes: 0 | ||
| 2170 | OffsetToPadding: 0 | ||
| 2171 | BytesOfCalleeSavedRegisters: 0 | ||
| 2172 | OffsetOfExceptionHandler: 0 | ||
| 2173 | SectionIdOfExceptionHandler: 0 | ||
| 2174 | Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] | ||
| 2175 | - Kind: S_REGREL32 | ||
| 2176 | RegRelativeSym: | ||
| 2177 | Offset: 8 | ||
| 2178 | Type: 4097 | ||
| 2179 | Register: RSP | ||
| 2180 | VarName: this | ||
| 2181 | - Kind: S_PROC_ID_END | ||
| 2182 | ScopeEndSym: | ||
| 2183 | Relocations: | ||
| 2184 | - VirtualAddress: 44 | ||
| 2185 | SymbolName: '??0A@@QEAA@XZ' | ||
| 2186 | Type: IMAGE_REL_AMD64_SECREL | ||
| 2187 | - VirtualAddress: 48 | ||
| 2188 | SymbolName: '??0A@@QEAA@XZ' | ||
| 2189 | Type: IMAGE_REL_AMD64_SECTION | ||
| 2190 | - Name: '.text$mn' | ||
| 2191 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 2192 | Alignment: 16 | ||
| 2193 | SectionData: 48894C2408488B442408488D0D00000000488908488B442408C3 | ||
| 2194 | Relocations: | ||
| 2195 | - VirtualAddress: 13 | ||
| 2196 | SymbolName: '??_7B@@6B@' | ||
| 2197 | Type: IMAGE_REL_AMD64_REL32 | ||
| 2198 | - Name: '.debug$S' | ||
| 2199 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 2200 | Alignment: 1 | ||
| 2201 | Subsections: | ||
| 2202 | - !Symbols | ||
| 2203 | Records: | ||
| 2204 | - Kind: S_GPROC32_ID | ||
| 2205 | ProcSym: | ||
| 2206 | CodeSize: 26 | ||
| 2207 | DbgStart: 5 | ||
| 2208 | DbgEnd: 25 | ||
| 2209 | FunctionType: 4177 | ||
| 2210 | Flags: [ ] | ||
| 2211 | DisplayName: 'B::B' | ||
| 2212 | - Kind: S_FRAMEPROC | ||
| 2213 | FrameProcSym: | ||
| 2214 | TotalFrameBytes: 0 | ||
| 2215 | PaddingFrameBytes: 0 | ||
| 2216 | OffsetToPadding: 0 | ||
| 2217 | BytesOfCalleeSavedRegisters: 0 | ||
| 2218 | OffsetOfExceptionHandler: 0 | ||
| 2219 | SectionIdOfExceptionHandler: 0 | ||
| 2220 | Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] | ||
| 2221 | - Kind: S_REGREL32 | ||
| 2222 | RegRelativeSym: | ||
| 2223 | Offset: 8 | ||
| 2224 | Type: 4121 | ||
| 2225 | Register: RSP | ||
| 2226 | VarName: this | ||
| 2227 | - Kind: S_PROC_ID_END | ||
| 2228 | ScopeEndSym: | ||
| 2229 | Relocations: | ||
| 2230 | - VirtualAddress: 44 | ||
| 2231 | SymbolName: '??0B@@QEAA@XZ' | ||
| 2232 | Type: IMAGE_REL_AMD64_SECREL | ||
| 2233 | - VirtualAddress: 48 | ||
| 2234 | SymbolName: '??0B@@QEAA@XZ' | ||
| 2235 | Type: IMAGE_REL_AMD64_SECTION | ||
| 2236 | - Name: '.text$mn' | ||
| 2237 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
| 2238 | Alignment: 4 | ||
| 2239 | SectionData: 4883E908E900000000 | ||
| 2240 | Relocations: | ||
| 2241 | - VirtualAddress: 5 | ||
| 2242 | SymbolName: '?f@C@@UEAAHXZ' | ||
| 2243 | Type: IMAGE_REL_AMD64_REL32 | ||
| 2244 | - Name: '.debug$S' | ||
| 2245 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 2246 | Alignment: 1 | ||
| 2247 | Subsections: | ||
| 2248 | - !Symbols | ||
| 2249 | Records: | ||
| 2250 | - Kind: S_THUNK32 | ||
| 2251 | Thunk32Sym: | ||
| 2252 | Parent: 0 | ||
| 2253 | End: 0 | ||
| 2254 | Next: 0 | ||
| 2255 | Off: 0 | ||
| 2256 | Seg: 0 | ||
| 2257 | Len: 9 | ||
| 2258 | Ordinal: Pcode | ||
| 2259 | - Kind: S_FRAMEPROC | ||
| 2260 | FrameProcSym: | ||
| 2261 | TotalFrameBytes: 0 | ||
| 2262 | PaddingFrameBytes: 0 | ||
| 2263 | OffsetToPadding: 0 | ||
| 2264 | BytesOfCalleeSavedRegisters: 0 | ||
| 2265 | OffsetOfExceptionHandler: 0 | ||
| 2266 | SectionIdOfExceptionHandler: 0 | ||
| 2267 | Flags: [ MarkedInline, Naked, AsynchronousExceptionHandling ] | ||
| 2268 | - Kind: S_PROC_ID_END | ||
| 2269 | ScopeEndSym: | ||
| 2270 | Relocations: | ||
| 2271 | - VirtualAddress: 28 | ||
| 2272 | SymbolName: '?f@C@@W7EAAHXZ' | ||
| 2273 | Type: IMAGE_REL_AMD64_SECREL | ||
| 2274 | - VirtualAddress: 32 | ||
| 2275 | SymbolName: '?f@C@@W7EAAHXZ' | ||
| 2276 | Type: IMAGE_REL_AMD64_SECTION | ||
| 2277 | - Name: .xdata | ||
| 2278 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | ||
| 2279 | Alignment: 4 | ||
| 2280 | SectionData: '0109010009420000' | ||
| 2281 | - Name: .pdata | ||
| 2282 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | ||
| 2283 | Alignment: 4 | ||
| 2284 | SectionData: '000000005900000000000000' | ||
| 2285 | Relocations: | ||
| 2286 | - VirtualAddress: 0 | ||
| 2287 | SymbolName: '$LN3' | ||
| 2288 | Type: IMAGE_REL_AMD64_ADDR32NB | ||
| 2289 | - VirtualAddress: 4 | ||
| 2290 | SymbolName: '$LN3' | ||
| 2291 | Type: IMAGE_REL_AMD64_ADDR32NB | ||
| 2292 | - VirtualAddress: 8 | ||
| 2293 | SymbolName: '$unwind$??0C@@QEAA@XZ' | ||
| 2294 | Type: IMAGE_REL_AMD64_ADDR32NB | ||
| 2295 | - Name: .rdata | ||
| 2296 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] | ||
| 2297 | Alignment: 8 | ||
| 2298 | SectionData: '0000000000000000' | ||
| 2299 | Relocations: | ||
| 2300 | - VirtualAddress: 0 | ||
| 2301 | SymbolName: '?f@A@@UEAAHXZ' | ||
| 2302 | Type: IMAGE_REL_AMD64_ADDR64 | ||
| 2303 | - Name: .rdata | ||
| 2304 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] | ||
| 2305 | Alignment: 8 | ||
| 2306 | SectionData: '0000000000000000' | ||
| 2307 | Relocations: | ||
| 2308 | - VirtualAddress: 0 | ||
| 2309 | SymbolName: '?f@B@@UEAAHXZ' | ||
| 2310 | Type: IMAGE_REL_AMD64_ADDR64 | ||
| 2311 | - Name: .rdata | ||
| 2312 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] | ||
| 2313 | Alignment: 8 | ||
| 2314 | SectionData: '0000000000000000' | ||
| 2315 | Relocations: | ||
| 2316 | - VirtualAddress: 0 | ||
| 2317 | SymbolName: '?f@C@@UEAAHXZ' | ||
| 2318 | Type: IMAGE_REL_AMD64_ADDR64 | ||
| 2319 | - Name: .rdata | ||
| 2320 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] | ||
| 2321 | Alignment: 8 | ||
| 2322 | SectionData: '0000000000000000' | ||
| 2323 | Relocations: | ||
| 2324 | - VirtualAddress: 0 | ||
| 2325 | SymbolName: '?f@C@@W7EAAHXZ' | ||
| 2326 | Type: IMAGE_REL_AMD64_ADDR64 | ||
| 2327 | - Name: '.debug$S' | ||
| 2328 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 2329 | Alignment: 1 | ||
| 2330 | Subsections: | ||
| 2331 | - !Symbols | ||
| 2332 | Records: | ||
| 2333 | - Kind: S_GDATA32 | ||
| 2334 | DataSym: | ||
| 2335 | Type: 4179 | ||
| 2336 | DisplayName: 'A::`vftable''' | ||
| 2337 | Relocations: | ||
| 2338 | - VirtualAddress: 20 | ||
| 2339 | SymbolName: '??_7A@@6B@' | ||
| 2340 | Type: IMAGE_REL_AMD64_SECREL | ||
| 2341 | - VirtualAddress: 24 | ||
| 2342 | SymbolName: '??_7A@@6B@' | ||
| 2343 | Type: IMAGE_REL_AMD64_SECTION | ||
| 2344 | - Name: '.debug$S' | ||
| 2345 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 2346 | Alignment: 1 | ||
| 2347 | Subsections: | ||
| 2348 | - !Symbols | ||
| 2349 | Records: | ||
| 2350 | - Kind: S_GDATA32 | ||
| 2351 | DataSym: | ||
| 2352 | Type: 4179 | ||
| 2353 | DisplayName: 'B::`vftable''' | ||
| 2354 | Relocations: | ||
| 2355 | - VirtualAddress: 20 | ||
| 2356 | SymbolName: '??_7B@@6B@' | ||
| 2357 | Type: IMAGE_REL_AMD64_SECREL | ||
| 2358 | - VirtualAddress: 24 | ||
| 2359 | SymbolName: '??_7B@@6B@' | ||
| 2360 | Type: IMAGE_REL_AMD64_SECTION | ||
| 2361 | - Name: '.debug$S' | ||
| 2362 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 2363 | Alignment: 1 | ||
| 2364 | Subsections: | ||
| 2365 | - !Symbols | ||
| 2366 | Records: | ||
| 2367 | - Kind: S_GDATA32 | ||
| 2368 | DataSym: | ||
| 2369 | Type: 4179 | ||
| 2370 | DisplayName: 'C::`vftable''' | ||
| 2371 | Relocations: | ||
| 2372 | - VirtualAddress: 20 | ||
| 2373 | SymbolName: '??_7C@@6BA@@@' | ||
| 2374 | Type: IMAGE_REL_AMD64_SECREL | ||
| 2375 | - VirtualAddress: 24 | ||
| 2376 | SymbolName: '??_7C@@6BA@@@' | ||
| 2377 | Type: IMAGE_REL_AMD64_SECTION | ||
| 2378 | - Name: '.debug$S' | ||
| 2379 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | ||
| 2380 | Alignment: 1 | ||
| 2381 | Subsections: | ||
| 2382 | - !Symbols | ||
| 2383 | Records: | ||
| 2384 | - Kind: S_GDATA32 | ||
| 2385 | DataSym: | ||
| 2386 | Type: 4179 | ||
| 2387 | DisplayName: 'C::`vftable''' | ||
| 2388 | Relocations: | ||
| 2389 | - VirtualAddress: 20 | ||
| 2390 | SymbolName: '??_7C@@6BB@@@' | ||
| 2391 | Type: IMAGE_REL_AMD64_SECREL | ||
| 2392 | - VirtualAddress: 24 | ||
| 2393 | SymbolName: '??_7C@@6BB@@@' | ||
| 2394 | Type: IMAGE_REL_AMD64_SECTION | ||
| 2395 | symbols: | ||
| 2396 | - Name: '@comp.id' | ||
| 2397 | Value: 17130404 | ||
| 2398 | SectionNumber: -1 | ||
| 2399 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2400 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2401 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2402 | - Name: '@feat.00' | ||
| 2403 | Value: 2147484048 | ||
| 2404 | SectionNumber: -1 | ||
| 2405 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2406 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2407 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2408 | - Name: .drectve | ||
| 2409 | Value: 0 | ||
| 2410 | SectionNumber: 1 | ||
| 2411 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2412 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2413 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2414 | SectionDefinition: | ||
| 2415 | Length: 69 | ||
| 2416 | NumberOfRelocations: 0 | ||
| 2417 | NumberOfLinenumbers: 0 | ||
| 2418 | CheckSum: 876125206 | ||
| 2419 | Number: 0 | ||
| 2420 | - Name: '.debug$S' | ||
| 2421 | Value: 0 | ||
| 2422 | SectionNumber: 2 | ||
| 2423 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2424 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2425 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2426 | SectionDefinition: | ||
| 2427 | Length: 1668 | ||
| 2428 | NumberOfRelocations: 16 | ||
| 2429 | NumberOfLinenumbers: 0 | ||
| 2430 | CheckSum: 0 | ||
| 2431 | Number: 0 | ||
| 2432 | - Name: '.debug$T' | ||
| 2433 | Value: 0 | ||
| 2434 | SectionNumber: 3 | ||
| 2435 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2436 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2437 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2438 | SectionDefinition: | ||
| 2439 | Length: 8276 | ||
| 2440 | NumberOfRelocations: 0 | ||
| 2441 | NumberOfLinenumbers: 0 | ||
| 2442 | CheckSum: 0 | ||
| 2443 | Number: 0 | ||
| 2444 | - Name: '.text$mn' | ||
| 2445 | Value: 0 | ||
| 2446 | SectionNumber: 4 | ||
| 2447 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2448 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2449 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2450 | SectionDefinition: | ||
| 2451 | Length: 142 | ||
| 2452 | NumberOfRelocations: 4 | ||
| 2453 | NumberOfLinenumbers: 0 | ||
| 2454 | CheckSum: 1906691115 | ||
| 2455 | Number: 0 | ||
| 2456 | - Name: '.text$mn' | ||
| 2457 | Value: 0 | ||
| 2458 | SectionNumber: 5 | ||
| 2459 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2460 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2461 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2462 | SectionDefinition: | ||
| 2463 | Length: 26 | ||
| 2464 | NumberOfRelocations: 1 | ||
| 2465 | NumberOfLinenumbers: 0 | ||
| 2466 | CheckSum: 2299407997 | ||
| 2467 | Number: 0 | ||
| 2468 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 2469 | - Name: '.debug$S' | ||
| 2470 | Value: 0 | ||
| 2471 | SectionNumber: 6 | ||
| 2472 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2473 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2474 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2475 | SectionDefinition: | ||
| 2476 | Length: 112 | ||
| 2477 | NumberOfRelocations: 2 | ||
| 2478 | NumberOfLinenumbers: 0 | ||
| 2479 | CheckSum: 0 | ||
| 2480 | Number: 5 | ||
| 2481 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 2482 | - Name: '.text$mn' | ||
| 2483 | Value: 0 | ||
| 2484 | SectionNumber: 7 | ||
| 2485 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2486 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2487 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2488 | SectionDefinition: | ||
| 2489 | Length: 26 | ||
| 2490 | NumberOfRelocations: 1 | ||
| 2491 | NumberOfLinenumbers: 0 | ||
| 2492 | CheckSum: 2299407997 | ||
| 2493 | Number: 0 | ||
| 2494 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 2495 | - Name: '.debug$S' | ||
| 2496 | Value: 0 | ||
| 2497 | SectionNumber: 8 | ||
| 2498 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2499 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2500 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2501 | SectionDefinition: | ||
| 2502 | Length: 112 | ||
| 2503 | NumberOfRelocations: 2 | ||
| 2504 | NumberOfLinenumbers: 0 | ||
| 2505 | CheckSum: 0 | ||
| 2506 | Number: 7 | ||
| 2507 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 2508 | - Name: '.text$mn' | ||
| 2509 | Value: 0 | ||
| 2510 | SectionNumber: 9 | ||
| 2511 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2512 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2513 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2514 | SectionDefinition: | ||
| 2515 | Length: 9 | ||
| 2516 | NumberOfRelocations: 1 | ||
| 2517 | NumberOfLinenumbers: 0 | ||
| 2518 | CheckSum: 3880904481 | ||
| 2519 | Number: 0 | ||
| 2520 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 2521 | - Name: '.debug$S' | ||
| 2522 | Value: 0 | ||
| 2523 | SectionNumber: 10 | ||
| 2524 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2525 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2526 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2527 | SectionDefinition: | ||
| 2528 | Length: 100 | ||
| 2529 | NumberOfRelocations: 2 | ||
| 2530 | NumberOfLinenumbers: 0 | ||
| 2531 | CheckSum: 0 | ||
| 2532 | Number: 9 | ||
| 2533 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 2534 | - Name: '?f@A@@UEAAHXZ' | ||
| 2535 | Value: 0 | ||
| 2536 | SectionNumber: 4 | ||
| 2537 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2538 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 2539 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2540 | - Name: '??0A@@QEAA@XZ' | ||
| 2541 | Value: 0 | ||
| 2542 | SectionNumber: 5 | ||
| 2543 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2544 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 2545 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2546 | - Name: '?f@B@@UEAAHXZ' | ||
| 2547 | Value: 16 | ||
| 2548 | SectionNumber: 4 | ||
| 2549 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2550 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 2551 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2552 | - Name: '??0B@@QEAA@XZ' | ||
| 2553 | Value: 0 | ||
| 2554 | SectionNumber: 7 | ||
| 2555 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2556 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 2557 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2558 | - Name: '??0C@@QEAA@XZ' | ||
| 2559 | Value: 32 | ||
| 2560 | SectionNumber: 4 | ||
| 2561 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2562 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 2563 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2564 | - Name: '?f@C@@UEAAHXZ' | ||
| 2565 | Value: 128 | ||
| 2566 | SectionNumber: 4 | ||
| 2567 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2568 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 2569 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2570 | - Name: '?f@C@@W7EAAHXZ' | ||
| 2571 | Value: 0 | ||
| 2572 | SectionNumber: 9 | ||
| 2573 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2574 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 2575 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2576 | - Name: '$LN3' | ||
| 2577 | Value: 32 | ||
| 2578 | SectionNumber: 4 | ||
| 2579 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2580 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2581 | StorageClass: IMAGE_SYM_CLASS_LABEL | ||
| 2582 | - Name: .xdata | ||
| 2583 | Value: 0 | ||
| 2584 | SectionNumber: 11 | ||
| 2585 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2586 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2587 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2588 | SectionDefinition: | ||
| 2589 | Length: 8 | ||
| 2590 | NumberOfRelocations: 0 | ||
| 2591 | NumberOfLinenumbers: 0 | ||
| 2592 | CheckSum: 2625142988 | ||
| 2593 | Number: 0 | ||
| 2594 | - Name: '$unwind$??0C@@QEAA@XZ' | ||
| 2595 | Value: 0 | ||
| 2596 | SectionNumber: 11 | ||
| 2597 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2598 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2599 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2600 | - Name: .pdata | ||
| 2601 | Value: 0 | ||
| 2602 | SectionNumber: 12 | ||
| 2603 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2604 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2605 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2606 | SectionDefinition: | ||
| 2607 | Length: 12 | ||
| 2608 | NumberOfRelocations: 3 | ||
| 2609 | NumberOfLinenumbers: 0 | ||
| 2610 | CheckSum: 1248454893 | ||
| 2611 | Number: 0 | ||
| 2612 | - Name: '$pdata$??0C@@QEAA@XZ' | ||
| 2613 | Value: 0 | ||
| 2614 | SectionNumber: 12 | ||
| 2615 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2616 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2617 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2618 | - Name: .rdata | ||
| 2619 | Value: 0 | ||
| 2620 | SectionNumber: 13 | ||
| 2621 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2622 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2623 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2624 | SectionDefinition: | ||
| 2625 | Length: 8 | ||
| 2626 | NumberOfRelocations: 1 | ||
| 2627 | NumberOfLinenumbers: 0 | ||
| 2628 | CheckSum: 0 | ||
| 2629 | Number: 0 | ||
| 2630 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 2631 | - Name: '??_7A@@6B@' | ||
| 2632 | Value: 0 | ||
| 2633 | SectionNumber: 13 | ||
| 2634 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2635 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2636 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2637 | - Name: .rdata | ||
| 2638 | Value: 0 | ||
| 2639 | SectionNumber: 14 | ||
| 2640 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2641 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2642 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2643 | SectionDefinition: | ||
| 2644 | Length: 8 | ||
| 2645 | NumberOfRelocations: 1 | ||
| 2646 | NumberOfLinenumbers: 0 | ||
| 2647 | CheckSum: 0 | ||
| 2648 | Number: 0 | ||
| 2649 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 2650 | - Name: '??_7B@@6B@' | ||
| 2651 | Value: 0 | ||
| 2652 | SectionNumber: 14 | ||
| 2653 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2654 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2655 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2656 | - Name: .rdata | ||
| 2657 | Value: 0 | ||
| 2658 | SectionNumber: 15 | ||
| 2659 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2660 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2661 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2662 | SectionDefinition: | ||
| 2663 | Length: 8 | ||
| 2664 | NumberOfRelocations: 1 | ||
| 2665 | NumberOfLinenumbers: 0 | ||
| 2666 | CheckSum: 0 | ||
| 2667 | Number: 0 | ||
| 2668 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 2669 | - Name: '??_7C@@6BA@@@' | ||
| 2670 | Value: 0 | ||
| 2671 | SectionNumber: 15 | ||
| 2672 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2673 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2674 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2675 | - Name: .rdata | ||
| 2676 | Value: 0 | ||
| 2677 | SectionNumber: 16 | ||
| 2678 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2679 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2680 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2681 | SectionDefinition: | ||
| 2682 | Length: 8 | ||
| 2683 | NumberOfRelocations: 1 | ||
| 2684 | NumberOfLinenumbers: 0 | ||
| 2685 | CheckSum: 0 | ||
| 2686 | Number: 0 | ||
| 2687 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 2688 | - Name: '??_7C@@6BB@@@' | ||
| 2689 | Value: 0 | ||
| 2690 | SectionNumber: 16 | ||
| 2691 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2692 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2693 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 2694 | - Name: '.debug$S' | ||
| 2695 | Value: 0 | ||
| 2696 | SectionNumber: 17 | ||
| 2697 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2698 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2699 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2700 | SectionDefinition: | ||
| 2701 | Length: 40 | ||
| 2702 | NumberOfRelocations: 2 | ||
| 2703 | NumberOfLinenumbers: 0 | ||
| 2704 | CheckSum: 0 | ||
| 2705 | Number: 13 | ||
| 2706 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 2707 | - Name: '.debug$S' | ||
| 2708 | Value: 0 | ||
| 2709 | SectionNumber: 18 | ||
| 2710 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2711 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2712 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2713 | SectionDefinition: | ||
| 2714 | Length: 40 | ||
| 2715 | NumberOfRelocations: 2 | ||
| 2716 | NumberOfLinenumbers: 0 | ||
| 2717 | CheckSum: 0 | ||
| 2718 | Number: 14 | ||
| 2719 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 2720 | - Name: '.debug$S' | ||
| 2721 | Value: 0 | ||
| 2722 | SectionNumber: 19 | ||
| 2723 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2724 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2725 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2726 | SectionDefinition: | ||
| 2727 | Length: 40 | ||
| 2728 | NumberOfRelocations: 2 | ||
| 2729 | NumberOfLinenumbers: 0 | ||
| 2730 | CheckSum: 0 | ||
| 2731 | Number: 15 | ||
| 2732 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 2733 | - Name: '.debug$S' | ||
| 2734 | Value: 0 | ||
| 2735 | SectionNumber: 20 | ||
| 2736 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 2737 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 2738 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 2739 | SectionDefinition: | ||
| 2740 | Length: 40 | ||
| 2741 | NumberOfRelocations: 2 | ||
| 2742 | NumberOfLinenumbers: 0 | ||
| 2743 | CheckSum: 0 | ||
| 2744 | Number: 16 | ||
| 2745 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | ||
| 2746 | ... | ||
| 2747 | |||
deps/lld/test/COFF/pdb-type-server-simple.test+14-10| ... | @@ -21,7 +21,7 @@ RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj | ... | @@ -21,7 +21,7 @@ RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj |
| 21 | RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj | 21 | RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj |
| 22 | RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb | 22 | RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb |
| 23 | RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib | 23 | RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib |
| 24 | RUN: llvm-pdbutil dump -symbols -types -ids %t/t.pdb | FileCheck %s | 24 | RUN: llvm-pdbutil dump -symbols -types -ids -globals %t/t.pdb | FileCheck %s |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | CHECK-LABEL: Types (TPI Stream) | 27 | CHECK-LABEL: Types (TPI Stream) |
| ... | @@ -59,23 +59,29 @@ CHECK: {{.*}}: `a.c` | ... | @@ -59,23 +59,29 @@ CHECK: {{.*}}: `a.c` |
| 59 | CHECK: [[B_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28] | 59 | CHECK: [[B_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28] |
| 60 | CHECK: {{.*}}: `b.c` | 60 | CHECK: {{.*}}: `b.c` |
| 61 | 61 | ||
| 62 | CHECK-LABEL: Global Symbols | ||
| 63 | CHECK: ============================================================ | ||
| 64 | CHECK-NEXT: Records | ||
| 65 | CHECK-NEXT: 36 | S_PROCREF [size = 20] `main` | ||
| 66 | CHECK-NEXT: module = 1, sum name = 0, offset = 104 | ||
| 67 | CHECK-NEXT: 56 | S_PROCREF [size = 16] `g` | ||
| 68 | CHECK-NEXT: module = 2, sum name = 0, offset = 104 | ||
| 69 | |||
| 62 | CHECK-LABEL: Symbols | 70 | CHECK-LABEL: Symbols |
| 63 | CHECK: ============================================================ | 71 | CHECK: ============================================================ |
| 64 | CHECK-LABEL: Mod 0000 | `{{.*}}a.obj`: | 72 | CHECK-LABEL: Mod 0000 | `{{.*}}a.obj`: |
| 65 | CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\a.obj` | 73 | CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\a.obj` |
| 66 | CHECK: 104 | S_GPROC32_ID [size = 44] `main` | 74 | CHECK: 104 | S_GPROC32 [size = 44] `main` |
| 67 | CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 27 | 75 | CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 27 |
| 68 | CHECK: type = {{.*}}, debug start = 4, debug end = 22, flags = none | 76 | CHECK: type = {{.*}}, debug start = 4, debug end = 22, flags = none |
| 69 | CHECK: 200 | S_UDT [size = 12] `Foo` | 77 | CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `[[A_BUILD]]` |
| 70 | CHECK: original type = [[FOO_COMPLETE]] | ||
| 71 | CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[A_BUILD]]` | ||
| 72 | CHECK-LABEL: Mod 0001 | `{{.*}}b.obj`: | 78 | CHECK-LABEL: Mod 0001 | `{{.*}}b.obj`: |
| 73 | CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\b.obj` | 79 | CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\b.obj` |
| 74 | CHECK: 44 | S_COMPILE3 [size = 60] | 80 | CHECK: 44 | S_COMPILE3 [size = 60] |
| 75 | CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c | 81 | CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c |
| 76 | CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 | 82 | CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 |
| 77 | CHECK: flags = security checks | hot patchable | 83 | CHECK: flags = security checks | hot patchable |
| 78 | CHECK: 104 | S_GPROC32_ID [size = 44] `g` | 84 | CHECK: 104 | S_GPROC32 [size = 44] `g` |
| 79 | CHECK: parent = 0, end = 196, addr = 0002:0032, code size = 13 | 85 | CHECK: parent = 0, end = 196, addr = 0002:0032, code size = 13 |
| 80 | CHECK: type = {{.*}}, debug start = 5, debug end = 12, flags = none | 86 | CHECK: type = {{.*}}, debug start = 5, debug end = 12, flags = none |
| 81 | CHECK: 148 | S_FRAMEPROC [size = 32] | 87 | CHECK: 148 | S_FRAMEPROC [size = 32] |
| ... | @@ -83,9 +89,7 @@ CHECK: size = 0, padding size = 0, offset to padding = 0 | ... | @@ -83,9 +89,7 @@ CHECK: size = 0, padding size = 0, offset to padding = 0 |
| 83 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 | 89 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 |
| 84 | CHECK: flags = has async eh | opt speed | 90 | CHECK: flags = has async eh | opt speed |
| 85 | CHECK: 180 | S_REGREL32 [size = 16] `p` | 91 | CHECK: 180 | S_REGREL32 [size = 16] `p` |
| 86 | CHECK: type = [[FOO_PTR]] (Foo*), register = rsp, offset = 8 | 92 | CHECK: type = [[FOO_PTR]] (Foo*), register = RSP, offset = 8 |
| 87 | CHECK: 196 | S_END [size = 4] | 93 | CHECK: 196 | S_END [size = 4] |
| 88 | CHECK: 200 | S_UDT [size = 12] `Foo` | 94 | CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]` |
| 89 | CHECK: original type = [[FOO_COMPLETE]] | ||
| 90 | CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]` | ||
| 91 | CHECK-LABEL: Mod 0002 | `* Linker *`: | 95 | CHECK-LABEL: Mod 0002 | `* Linker *`: |
deps/lld/test/COFF/pdb.test+123-37| ... | @@ -1,13 +1,15 @@ | ... | @@ -1,13 +1,15 @@ |
| 1 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj | 1 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj |
| 2 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj | 2 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj |
| 3 | # RUN: rm -f %t.dll %t.pdb | ||
| 3 | # RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ | 4 | # RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ |
| 4 | # RUN: %t1.obj %t2.obj | 5 | # RUN: %t1.obj %t2.obj |
| 5 | 6 | ||
| 6 | # RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -pdb-stream \ | 7 | # RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -pdb-stream \ |
| 7 | # RUN: -dbi-stream -ipi-stream -tpi-stream %t.pdb | FileCheck %s | 8 | # RUN: -dbi-stream -ipi-stream -tpi-stream %t.pdb | FileCheck %s |
| 8 | 9 | ||
| 9 | # RUN: llvm-pdbutil dump -modules -section-map -section-contribs \ | 10 | # RUN: llvm-pdbutil dump -modules -section-map -section-contribs -section-headers \ |
| 10 | # RUN: -types -ids %t.pdb | FileCheck -check-prefix RAW %s | 11 | # RUN: -publics -public-extras -types -ids -type-extras -id-extras %t.pdb \ |
| 12 | # RUN: | FileCheck -check-prefix RAW %s | ||
| 11 | 13 | ||
| 12 | # CHECK: MSF: | 14 | # CHECK: MSF: |
| 13 | # CHECK-NEXT: SuperBlock: | 15 | # CHECK-NEXT: SuperBlock: |
| ... | @@ -117,86 +119,170 @@ | ... | @@ -117,86 +119,170 @@ |
| 117 | 119 | ||
| 118 | RAW: Modules | 120 | RAW: Modules |
| 119 | RAW-NEXT: ============================================================ | 121 | RAW-NEXT: ============================================================ |
| 120 | RAW-NEXT: Mod 0000 | Name: `{{.*}}pdb.test.tmp1.obj`: | 122 | RAW-NEXT: Mod 0000 | `{{.*}}pdb.test.tmp1.obj`: |
| 121 | RAW-NEXT: Obj: `{{.*}}pdb.test.tmp1.obj`: | 123 | RAW-NEXT: Obj: `{{.*}}pdb.test.tmp1.obj`: |
| 122 | RAW-NEXT: debug stream: 9, # files: 1, has ec info: false | 124 | RAW-NEXT: debug stream: 9, # files: 1, has ec info: false |
| 123 | RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` | 125 | RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` |
| 124 | RAW-NEXT: Mod 0001 | Name: `{{.*}}pdb.test.tmp2.obj`: | 126 | RAW-NEXT: Mod 0001 | `{{.*}}pdb.test.tmp2.obj`: |
| 125 | RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`: | 127 | RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`: |
| 126 | RAW-NEXT: debug stream: 10, # files: 1, has ec info: false | 128 | RAW-NEXT: debug stream: 10, # files: 1, has ec info: false |
| 127 | RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` | 129 | RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` |
| 128 | RAW-NEXT: Mod 0002 | Name: `* Linker *`: | 130 | RAW-NEXT: Mod 0002 | `* Linker *`: |
| 129 | RAW-NEXT: Obj: ``: | 131 | RAW-NEXT: Obj: ``: |
| 130 | RAW-NEXT: debug stream: 11, # files: 0, has ec info: false | 132 | RAW-NEXT: debug stream: 11, # files: 0, has ec info: false |
| 131 | RAW-NEXT: pdb file ni: 1 `{{.*pdb.test.tmp.pdb}}`, src file ni: 0 `` | 133 | RAW-NEXT: pdb file ni: 1 `{{.*pdb.test.tmp.pdb}}`, src file ni: 0 `` |
| 132 | RAW: Types (TPI Stream) | 134 | RAW: Types (TPI Stream) |
| 133 | RAW-NEXT: ============================================================ | 135 | RAW-NEXT: ============================================================ |
| 134 | RAW-NEXT: Showing 5 records | 136 | RAW-NEXT: Showing 5 records |
| 135 | RAW-NEXT: 0x1000 | LF_ARGLIST [size = 8] | 137 | RAW-NEXT: 0x1000 | LF_ARGLIST [size = 8, hash = 0xEC0] |
| 136 | RAW-NEXT: 0x1001 | LF_PROCEDURE [size = 16] | 138 | RAW-NEXT: 0x1001 | LF_PROCEDURE [size = 16, hash = 0x7BC] |
| 137 | RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1000 | 139 | RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1000 |
| 138 | RAW-NEXT: calling conv = cdecl, options = None | 140 | RAW-NEXT: calling conv = cdecl, options = None |
| 139 | RAW-NEXT: 0x1002 | LF_POINTER [size = 12] | 141 | RAW-NEXT: 0x1002 | LF_POINTER [size = 12, hash = 0x884] |
| 140 | RAW-NEXT: referent = 0x1001, mode = pointer, opts = None, kind = ptr64 | 142 | RAW-NEXT: referent = 0x1001, mode = pointer, opts = None, kind = ptr64 |
| 141 | RAW-NEXT: 0x1003 | LF_ARGLIST [size = 12] | 143 | RAW-NEXT: 0x1003 | LF_ARGLIST [size = 12, hash = 0x936] |
| 142 | RAW-NEXT: <no type>: `` | 144 | RAW-NEXT: <no type>: `` |
| 143 | RAW-NEXT: 0x1004 | LF_PROCEDURE [size = 16] | 145 | RAW-NEXT: 0x1004 | LF_PROCEDURE [size = 16, hash = 0x852] |
| 144 | RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1003 | 146 | RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1003 |
| 145 | RAW-NEXT: calling conv = cdecl, options = None | 147 | RAW-NEXT: calling conv = cdecl, options = None |
| 146 | RAW: Types (IPI Stream) | 148 | RAW: Types (IPI Stream) |
| 147 | RAW-NEXT: ============================================================ | 149 | RAW-NEXT: ============================================================ |
| 148 | RAW-NEXT: Showing 12 records | 150 | RAW-NEXT: Showing 12 records |
| 149 | RAW-NEXT: 0x1000 | LF_FUNC_ID [size = 20] | 151 | RAW-NEXT: 0x1000 | LF_FUNC_ID [size = 20, hash = 0x330] |
| 150 | RAW-NEXT: name = main, type = 0x1004, parent scope = <no type> | 152 | RAW-NEXT: name = main, type = 0x1004, parent scope = <no type> |
| 151 | RAW-NEXT: 0x1001 | LF_FUNC_ID [size = 16] | 153 | RAW-NEXT: 0x1001 | LF_FUNC_ID [size = 16, hash = 0x120] |
| 152 | RAW-NEXT: name = foo, type = 0x1001, parent scope = <no type> | 154 | RAW-NEXT: name = foo, type = 0x1001, parent scope = <no type> |
| 153 | RAW-NEXT: 0x1002 | LF_STRING_ID [size = 16] ID: <no type>, String: D:\b | 155 | RAW-NEXT: 0x1002 | LF_STRING_ID [size = 16, hash = 0x757] ID: <no type>, String: D:\b |
| 154 | RAW-NEXT: 0x1003 | LF_STRING_ID [size = 36] ID: <no type>, String: C:\vs14\VC\BIN\amd64\cl.exe | 156 | RAW-NEXT: 0x1003 | LF_STRING_ID [size = 36, hash = 0xC3A] ID: <no type>, String: C:\vs14\VC\BIN\amd64\cl.exe |
| 155 | RAW-NEXT: 0x1004 | LF_STRING_ID [size = 260] 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" | 157 | RAW-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" |
| 156 | RAW-NEXT: 0x1005 | LF_SUBSTR_LIST [size = 12] | 158 | RAW-NEXT: 0x1005 | LF_SUBSTR_LIST [size = 12, hash = 0x759] |
| 157 | RAW-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"` | 159 | RAW-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"` |
| 158 | RAW-NEXT: 0x1006 | LF_STRING_ID [size = 132] 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 | 160 | RAW-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 -X |
| 159 | RAW-NEXT: 0x1007 | LF_STRING_ID [size = 24] ID: <no type>, String: ret42-main.c | 161 | RAW-NEXT: 0x1007 | LF_STRING_ID [size = 24, hash = 0x2D1] ID: <no type>, String: ret42-main.c |
| 160 | RAW-NEXT: 0x1008 | LF_STRING_ID [size = 24] ID: <no type>, String: D:\b\vc140.pdb | 162 | RAW-NEXT: 0x1008 | LF_STRING_ID [size = 24, hash = 0xB8B] ID: <no type>, String: D:\b\vc140.pdb |
| 161 | RAW-NEXT: 0x1009 | LF_BUILDINFO [size = 28] | 163 | RAW-NEXT: 0x1009 | LF_BUILDINFO [size = 28, hash = 0xA8C] |
| 162 | RAW-NEXT: 0x1002: `D:\b` | 164 | RAW-NEXT: 0x1002: `D:\b` |
| 163 | RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe` | 165 | RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe` |
| 164 | RAW-NEXT: 0x1007: `ret42-main.c` | 166 | RAW-NEXT: 0x1007: `ret42-main.c` |
| 165 | RAW-NEXT: 0x1008: `D:\b\vc140.pdb` | 167 | RAW-NEXT: 0x1008: `D:\b\vc140.pdb` |
| 166 | RAW-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` | 168 | RAW-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` |
| 167 | RAW-NEXT: 0x100A | LF_STRING_ID [size = 20] ID: <no type>, String: ret42-sub.c | 169 | RAW-NEXT: 0x100A | LF_STRING_ID [size = 20, hash = 0x39C] ID: <no type>, String: ret42-sub.c |
| 168 | RAW-NEXT: 0x100B | LF_BUILDINFO [size = 28] | 170 | RAW-NEXT: 0x100B | LF_BUILDINFO [size = 28, hash = 0xAD7] |
| 169 | RAW-NEXT: 0x1002: `D:\b` | 171 | RAW-NEXT: 0x1002: `D:\b` |
| 170 | RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe` | 172 | RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe` |
| 171 | RAW-NEXT: 0x100A: `ret42-sub.c` | 173 | RAW-NEXT: 0x100A: `ret42-sub.c` |
| 172 | RAW-NEXT: 0x1008: `D:\b\vc140.pdb` | 174 | RAW-NEXT: 0x1008: `D:\b\vc140.pdb` |
| 173 | RAW-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` | 175 | RAW-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` |
| 176 | RAW: Public Symbols | ||
| 177 | RAW-NEXT: ============================================================ | ||
| 178 | RAW-NEXT: Publics Header | ||
| 179 | RAW-NEXT: sym hash = 556, thunk table addr = 0000:0000 | ||
| 180 | RAW-NEXT: GSI Header | ||
| 181 | RAW-NEXT: sig = 0xFFFFFFFF, hdr = 0xF12F091A, hr size = 16, num buckets = 524 | ||
| 182 | RAW-NEXT: Records | ||
| 183 | RAW-NEXT: 20 | S_PUB32 [size = 20] `main` | ||
| 184 | RAW-NEXT: flags = function, addr = 0002:0000 | ||
| 185 | RAW-NEXT: 0 | S_PUB32 [size = 20] `foo` | ||
| 186 | RAW-NEXT: flags = function, addr = 0002:0016 | ||
| 187 | RAW-NOT: S_PUB32 | ||
| 188 | RAW-NEXT: Hash Entries | ||
| 189 | RAW-NEXT: off = 21, refcnt = 1 | ||
| 190 | RAW-NEXT: off = 1, refcnt = 1 | ||
| 191 | RAW-NEXT: Hash Buckets | ||
| 192 | RAW-NEXT: 0x00000000 | ||
| 193 | RAW-NEXT: 0x0000000c | ||
| 194 | RAW-NEXT: Address Map | ||
| 195 | RAW-NEXT: off = 20 | ||
| 196 | RAW-NEXT: off = 0 | ||
| 197 | RAW: Section Headers | ||
| 198 | RAW-NEXT: ============================================================ | ||
| 199 | RAW: SECTION HEADER #1 | ||
| 200 | RAW-NEXT: .pdata name | ||
| 201 | RAW-NEXT: virtual size | ||
| 202 | RAW-NEXT: 1000 virtual address | ||
| 203 | RAW-NEXT: 200 size of raw data | ||
| 204 | RAW-NEXT: 400 file pointer to raw data | ||
| 205 | RAW-NEXT: 0 file pointer to relocation table | ||
| 206 | RAW-NEXT: 0 file pointer to line numbers | ||
| 207 | RAW-NEXT: 0 number of relocations | ||
| 208 | RAW-NEXT: 0 number of line numbers | ||
| 209 | RAW-NEXT: 40000040 flags | ||
| 210 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | ||
| 211 | RAW-NEXT: IMAGE_SCN_MEM_READ | ||
| 212 | RAW: SECTION HEADER #2 | ||
| 213 | RAW-NEXT: .text name | ||
| 214 | RAW-NEXT: virtual size | ||
| 215 | RAW-NEXT: 2000 virtual address | ||
| 216 | RAW-NEXT: 200 size of raw data | ||
| 217 | RAW-NEXT: 600 file pointer to raw data | ||
| 218 | RAW-NEXT: 0 file pointer to relocation table | ||
| 219 | RAW-NEXT: 0 file pointer to line numbers | ||
| 220 | RAW-NEXT: 0 number of relocations | ||
| 221 | RAW-NEXT: 0 number of line numbers | ||
| 222 | RAW-NEXT: 60000020 flags | ||
| 223 | RAW-NEXT: IMAGE_SCN_CNT_CODE | ||
| 224 | RAW-NEXT: IMAGE_SCN_MEM_EXECUTE | ||
| 225 | RAW-NEXT: IMAGE_SCN_MEM_READ | ||
| 226 | RAW: SECTION HEADER #3 | ||
| 227 | RAW-NEXT: .xdata name | ||
| 228 | RAW-NEXT: virtual size | ||
| 229 | RAW-NEXT: 3000 virtual address | ||
| 230 | RAW-NEXT: 200 size of raw data | ||
| 231 | RAW-NEXT: 800 file pointer to raw data | ||
| 232 | RAW-NEXT: 0 file pointer to relocation table | ||
| 233 | RAW-NEXT: 0 file pointer to line numbers | ||
| 234 | RAW-NEXT: 0 number of relocations | ||
| 235 | RAW-NEXT: 0 number of line numbers | ||
| 236 | RAW-NEXT: 40000040 flags | ||
| 237 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | ||
| 238 | RAW-NEXT: IMAGE_SCN_MEM_READ | ||
| 239 | RAW: SECTION HEADER #4 | ||
| 240 | RAW-NEXT: .rdata name | ||
| 241 | RAW-NEXT: virtual size | ||
| 242 | RAW-NEXT: 4000 virtual address | ||
| 243 | RAW-NEXT: 200 size of raw data | ||
| 244 | RAW-NEXT: A00 file pointer to raw data | ||
| 245 | RAW-NEXT: 0 file pointer to relocation table | ||
| 246 | RAW-NEXT: 0 file pointer to line numbers | ||
| 247 | RAW-NEXT: 0 number of relocations | ||
| 248 | RAW-NEXT: 0 number of line numbers | ||
| 249 | RAW-NEXT: 40000040 flags | ||
| 250 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | ||
| 251 | RAW-NEXT: IMAGE_SCN_MEM_READ | ||
| 252 | RAW: Original Section Headers | ||
| 253 | RAW-NEXT: ============================================================ | ||
| 254 | RAW-NEXT: PDB does not contain the requested image section header type | ||
| 174 | RAW: Section Contributions | 255 | RAW: Section Contributions |
| 175 | RAW-NEXT: ============================================================ | 256 | RAW-NEXT: ============================================================ |
| 176 | RAW-NEXT: SC | mod = 0, 65535:1288, size = 14, data crc = 0, reloc crc = 0 | 257 | RAW-NEXT: SC[.pdata] | mod = 0, 0001:0000, size = 12, data crc = 361370162, reloc crc = 0 |
| 177 | RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE | | 258 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ |
| 178 | RAW-NEXT: IMAGE_SCN_MEM_READ | 259 | RAW-NEXT: SC[.text] | mod = 0, 0002:0000, size = 14, data crc = 1682752513, reloc crc = 0 |
| 179 | RAW-NEXT: SC | mod = 0, 65535:1312, size = 8, data crc = 0, reloc crc = 0 | 260 | RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE | |
| 180 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ | 261 | RAW-NEXT: IMAGE_SCN_MEM_READ |
| 181 | RAW-NEXT: SC | mod = 0, 65535:1320, size = 12, data crc = 0, reloc crc = 0 | 262 | RAW-NEXT: SC[.text] | mod = 1, 0002:0016, size = 6, data crc = 2139436471, reloc crc = 0 |
| 182 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ | 263 | RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE | |
| 183 | RAW-NEXT: SC | mod = 1, 65535:1144, size = 6, data crc = 0, reloc crc = 0 | 264 | RAW-NEXT: IMAGE_SCN_MEM_READ |
| 184 | RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE | | 265 | RAW-NEXT: SC[.xdata] | mod = 0, 0003:0000, size = 8, data crc = 264583633, reloc crc = 0 |
| 185 | RAW-NEXT: IMAGE_SCN_MEM_READ | 266 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ |
| 267 | RAW-NEXT: SC[???] | mod = 2, 0004:0000, size = {{[0-9]+}}, data crc = 0, reloc crc = 0 | ||
| 268 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | ||
| 269 | RAW-NEXT: SC[???] | mod = 2, 0004:0028, size = {{[0-9]+}}, data crc = 0, reloc crc = 0 | ||
| 270 | RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | ||
| 271 | RAW-NOT: SC[ | ||
| 186 | RAW: Section Map | 272 | RAW: Section Map |
| 187 | RAW-NEXT: ============================================================ | 273 | RAW-NEXT: ============================================================ |
| 188 | RAW-NEXT: Section 0000 | ovl = 0, group = 0, frame = 0, name = 1 | 274 | RAW-NEXT: Section 0000 | ovl = 0, group = 0, frame = 1, name = 65535 |
| 189 | RAW-NEXT: class = 65535, offset = 0, size = | 275 | RAW-NEXT: class = 65535, offset = 0, size = |
| 190 | RAW-NEXT: flags = read | 32 bit addr | selector | 276 | RAW-NEXT: flags = read | 32 bit addr | selector |
| 191 | RAW-NEXT: Section 0001 | ovl = 1, group = 0, frame = 0, name = 2 | 277 | RAW-NEXT: Section 0001 | ovl = 0, group = 0, frame = 2, name = 65535 |
| 192 | RAW-NEXT: class = 65535, offset = 0, size = | 278 | RAW-NEXT: class = 65535, offset = 0, size = |
| 193 | RAW-NEXT: flags = read | execute | 32 bit addr | selector | 279 | RAW-NEXT: flags = read | execute | 32 bit addr | selector |
| 194 | RAW-NEXT: Section 0002 | ovl = 2, group = 0, frame = 0, name = 3 | 280 | RAW-NEXT: Section 0002 | ovl = 0, group = 0, frame = 3, name = 65535 |
| 195 | RAW-NEXT: class = 65535, offset = 0, size = | 281 | RAW-NEXT: class = 65535, offset = 0, size = |
| 196 | RAW-NEXT: flags = read | 32 bit addr | selector | 282 | RAW-NEXT: flags = read | 32 bit addr | selector |
| 197 | RAW-NEXT: Section 0003 | ovl = 3, group = 0, frame = 0, name = 4 | 283 | RAW-NEXT: Section 0003 | ovl = 0, group = 0, frame = 4, name = 65535 |
| 198 | RAW-NEXT: class = 65535, offset = 0, size = | 284 | RAW-NEXT: class = 65535, offset = 0, size = |
| 199 | RAW-NEXT: flags = read | 32 bit addr | selector | 285 | RAW-NEXT: flags = read | 32 bit addr | selector |
| 200 | RAW-NEXT: Section 0004 | ovl = 4, group = 0, frame = 0, name = 5 | 286 | RAW-NEXT: Section 0004 | ovl = 0, group = 0, frame = 5, name = 65535 |
| 201 | RAW-NEXT: class = 65535, offset = 0, size = | 287 | RAW-NEXT: class = 65535, offset = 0, size = |
| 202 | RAW-NEXT: flags = 32 bit addr | absolute addr | 288 | RAW-NEXT: flags = 32 bit addr | absolute addr |
deps/lld/test/COFF/reloc-arm.test+8-8| ... | @@ -28,28 +28,28 @@ sections: | ... | @@ -28,28 +28,28 @@ sections: |
| 28 | Relocations: | 28 | Relocations: |
| 29 | - VirtualAddress: 0 | 29 | - VirtualAddress: 0 |
| 30 | SymbolName: foo | 30 | SymbolName: foo |
| 31 | Type: 1 # IMAGE_REL_ARM_ADDR32 | 31 | Type: IMAGE_REL_ARM_ADDR32 |
| 32 | - VirtualAddress: 16 | 32 | - VirtualAddress: 16 |
| 33 | SymbolName: foo | 33 | SymbolName: foo |
| 34 | Type: 2 # IMAGE_REL_ARM_ADDR32NB | 34 | Type: IMAGE_REL_ARM_ADDR32NB |
| 35 | - VirtualAddress: 32 | 35 | - VirtualAddress: 32 |
| 36 | SymbolName: foo | 36 | SymbolName: foo |
| 37 | Type: 17 # IMAGE_REL_ARM_MOV32T | 37 | Type: IMAGE_REL_ARM_MOV32T |
| 38 | - VirtualAddress: 48 | 38 | - VirtualAddress: 48 |
| 39 | SymbolName: foo | 39 | SymbolName: foo |
| 40 | Type: 20 # IMAGE_REL_ARM_BRANCH24T | 40 | Type: IMAGE_REL_ARM_BRANCH24T |
| 41 | - VirtualAddress: 64 | 41 | - VirtualAddress: 64 |
| 42 | SymbolName: foo | 42 | SymbolName: foo |
| 43 | Type: 18 # IMAGE_REL_ARM_BRANCH20T | 43 | Type: IMAGE_REL_ARM_BRANCH20T |
| 44 | - VirtualAddress: 80 | 44 | - VirtualAddress: 80 |
| 45 | SymbolName: foo | 45 | SymbolName: foo |
| 46 | Type: 21 # IMAGE_REL_ARM_BLX23T | 46 | Type: IMAGE_REL_ARM_BLX23T |
| 47 | - VirtualAddress: 96 | 47 | - VirtualAddress: 96 |
| 48 | SymbolName: bar | 48 | SymbolName: bar |
| 49 | Type: 20 # IMAGE_REL_ARM_BRANCH24T | 49 | Type: IMAGE_REL_ARM_BRANCH24T |
| 50 | - VirtualAddress: 112 | 50 | - VirtualAddress: 112 |
| 51 | SymbolName: bar | 51 | SymbolName: bar |
| 52 | Type: 15 # IMAGE_REL_ARM_SECREL | 52 | Type: IMAGE_REL_ARM_SECREL |
| 53 | symbols: | 53 | symbols: |
| 54 | - Name: .aaa | 54 | - Name: .aaa |
| 55 | Value: 0 | 55 | Value: 0 |
deps/lld/test/COFF/reloc-discarded-dwarf.s+2| ... | @@ -13,3 +13,5 @@ f: | ... | @@ -13,3 +13,5 @@ f: |
| 13 | 13 | ||
| 14 | 	.section	.debug_info,"dr" | 14 | 	.section	.debug_info,"dr" |
| 15 | 	.quad	f | 15 | 	.quad	f |
| 16 | 	.section	.eh_frame,"dr" | ||
| 17 | 	.quad	f |
deps/lld/test/COFF/reloc-discarded-early.s created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | # RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s | ||
| 2 | # RUN: lld-link -entry:__ImageBase -subsystem:console -debug %t.obj | ||
| 3 | |||
| 4 | .section .debug_info,"dr" | ||
| 5 | .quad .Ldrectve | ||
| 6 | |||
| 7 | .section .drectve | ||
| 8 | .Ldrectve: | ||
deps/lld/test/COFF/reloc-discarded-early2.s created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | # RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s | ||
| 2 | # RUN: not lld-link -entry:__ImageBase -subsystem:console %t.obj 2>&1 | FileCheck %s | ||
| 3 | |||
| 4 | .text | ||
| 5 | # CHECK: error: relocation against symbol in discarded section: .drectve | ||
| 6 | .quad .Ldrectve | ||
| 7 | |||
| 8 | .section .drectve | ||
| 9 | .Ldrectve: | ||
deps/lld/test/COFF/reloc-discarded.s-1| ... | @@ -18,7 +18,6 @@ main_global: | ... | @@ -18,7 +18,6 @@ main_global: |
| 18 | 18 | ||
| 19 | 	.section	.CRT$XCU,"dr",associative,main_global | 19 | 	.section	.CRT$XCU,"dr",associative,main_global |
| 20 | 	.p2align	3 | 20 | 	.p2align	3 |
| 21 | 	.globl assoc_global | ||
| 22 | assoc_global: | 21 | assoc_global: |
| 23 | 	.quad	main_global | 22 | 	.quad	main_global |
| 24 | 23 |
deps/lld/test/COFF/responsefile.test+19-1| ... | @@ -3,5 +3,23 @@ | ... | @@ -3,5 +3,23 @@ |
| 3 | # RUN: echo /out:%t.exe /entry:main %t.obj > %t.rsp | 3 | # RUN: echo /out:%t.exe /entry:main %t.obj > %t.rsp |
| 4 | # RUN: lld-link @%t.rsp /heap:0x3000 | 4 | # RUN: lld-link @%t.rsp /heap:0x3000 |
| 5 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s | 5 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s |
| 6 | |||
| 7 | CHECK: SizeOfHeapReserve: 12288 | 6 | CHECK: SizeOfHeapReserve: 12288 |
| 7 | |||
| 8 | # RUN: not lld-link --rsp-quoting=foobar @%t.rsp 2>&1 | \ | ||
| 9 | # RUN: FileCheck --check-prefix=INVRSP %s | ||
| 10 | INVRSP: invalid response file quoting: foobar | ||
| 11 | |||
| 12 | # RUN: echo "blah\foo" > %t.rsp | ||
| 13 | # RUN: not lld-link @%t.rsp 2>&1 | \ | ||
| 14 | # RUN: FileCheck --check-prefix=DEFRSP %s | ||
| 15 | DEFRSP: error: could not open blah\foo | ||
| 16 | |||
| 17 | # RUN: echo "blah\foo" > %t.rsp | ||
| 18 | # RUN: not lld-link --rsp-quoting=windows @%t.rsp 2>&1 | \ | ||
| 19 | # RUN: FileCheck --check-prefix=WINRSP %s | ||
| 20 | WINRSP: error: could not open blah\foo | ||
| 21 | |||
| 22 | # RUN: echo "blah\foo" > %t.rsp | ||
| 23 | # RUN: not lld-link --rsp-quoting=posix @%t.rsp 2>&1 | \ | ||
| 24 | # RUN: FileCheck --check-prefix=POSRSP %s | ||
| 25 | POSRSP: error: could not open blahfoo |
deps/lld/test/COFF/rsds.test+34-6| ... | @@ -1,11 +1,20 @@ | ... | @@ -1,11 +1,20 @@ |
| 1 | # RUN: yaml2obj %s > %t.obj | 1 | # RUN: yaml2obj %s > %t.obj |
| 2 | 2 | ||
| 3 | # RUN: rm -f %t.dll %t.pdb | ||
| 3 | # RUN: lld-link /debug /dll /out:%t.dll /entry:DllMain %t.obj | 4 | # RUN: lld-link /debug /dll /out:%t.dll /entry:DllMain %t.obj |
| 4 | # RUN: llvm-readobj -coff-debug-directory %t.dll | FileCheck %s | 5 | # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.1.txt |
| 6 | # RUN: lld-link /debug /dll /out:%t.dll /entry:DllMain %t.obj | ||
| 7 | # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.2.txt | ||
| 8 | # RUN: cat %t.1.txt %t.2.txt | FileCheck %s | ||
| 5 | 9 | ||
| 10 | # RUN: rm -f %t.dll %t.pdb | ||
| 11 | # RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:DllMain %t.obj | ||
| 12 | # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.3.txt | ||
| 6 | # RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:DllMain %t.obj | 13 | # RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:DllMain %t.obj |
| 7 | # RUN: llvm-readobj -coff-debug-directory %t.dll | FileCheck %s | 14 | # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.4.txt |
| 15 | # RUN: cat %t.3.txt %t.4.txt | FileCheck %s | ||
| 8 | 16 | ||
| 17 | # CHECK: File: [[FILE:.*]].dll | ||
| 9 | # CHECK: DebugDirectory [ | 18 | # CHECK: DebugDirectory [ |
| 10 | # CHECK: DebugEntry { | 19 | # CHECK: DebugEntry { |
| 11 | # CHECK: Characteristics: 0x0 | 20 | # CHECK: Characteristics: 0x0 |
| ... | @@ -13,17 +22,36 @@ | ... | @@ -13,17 +22,36 @@ |
| 13 | # CHECK: MajorVersion: 0x0 | 22 | # CHECK: MajorVersion: 0x0 |
| 14 | # CHECK: MinorVersion: 0x0 | 23 | # CHECK: MinorVersion: 0x0 |
| 15 | # CHECK: Type: CodeView (0x2) | 24 | # CHECK: Type: CodeView (0x2) |
| 16 | # CHECK: SizeOfData: | 25 | # CHECK: SizeOfData: 0x{{[^0]}} |
| 17 | # CHECK: AddressOfRawData: | 26 | # CHECK: AddressOfRawData: 0x{{[^0]}} |
| 18 | # CHECK: PointerToRawData: | 27 | # CHECK: PointerToRawData: 0x{{[^0]}} |
| 19 | # CHECK: PDBInfo { | 28 | # CHECK: PDBInfo { |
| 20 | # CHECK: PDBSignature: 0x53445352 | 29 | # CHECK: PDBSignature: 0x53445352 |
| 21 | # CHECK: PDBGUID: | 30 | # CHECK: PDBGUID: [[GUID:\(([A-Za-z0-9]{2} ?){16}\)]] |
| 22 | # CHECK: PDBAge: 1 | 31 | # CHECK: PDBAge: 1 |
| 23 | # CHECK: PDBFileName: {{.*}}.pdb | 32 | # CHECK: PDBFileName: {{.*}}.pdb |
| 24 | # CHECK: } | 33 | # CHECK: } |
| 25 | # CHECK: } | 34 | # CHECK: } |
| 26 | # CHECK: ] | 35 | # CHECK: ] |
| 36 | # CHECK: File: [[FILE]].dll | ||
| 37 | # CHECK: DebugDirectory [ | ||
| 38 | # CHECK: DebugEntry { | ||
| 39 | # CHECK: Characteristics: 0x0 | ||
| 40 | # CHECK: TimeDateStamp: 1970-01-01 00:00:00 (0x0) | ||
| 41 | # CHECK: MajorVersion: 0x0 | ||
| 42 | # CHECK: MinorVersion: 0x0 | ||
| 43 | # CHECK: Type: CodeView (0x2) | ||
| 44 | # CHECK: SizeOfData: 0x{{[^0]}} | ||
| 45 | # CHECK: AddressOfRawData: 0x{{[^0]}} | ||
| 46 | # CHECK: PointerToRawData: 0x{{[^0]}} | ||
| 47 | # CHECK: PDBInfo { | ||
| 48 | # CHECK: PDBSignature: 0x53445352 | ||
| 49 | # CHECK: PDBGUID: [[GUID]] | ||
| 50 | # CHECK: PDBAge: 2 | ||
| 51 | # CHECK: PDBFileName: {{.*}}.pdb | ||
| 52 | # CHECK: } | ||
| 53 | # CHECK: } | ||
| 54 | # CHECK: ] | ||
| 27 | 55 | ||
| 28 | --- !COFF | 56 | --- !COFF |
| 29 | header: | 57 | header: |
deps/lld/test/COFF/safeseh-md.s created+34| ... | @@ -0,0 +1,34 @@ | ||
| 1 | # RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj | ||
| 2 | # RUN: lld-link %t.obj %S/Inputs/except_handler3.lib -safeseh -out:%t.exe -opt:noref -entry:main | ||
| 3 | # RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s | ||
| 4 | |||
| 5 | # CHECK: SEHTable [ | ||
| 6 | # CHECK-NEXT: 0x | ||
| 7 | # CHECK-NEXT: ] | ||
| 8 | |||
| 9 | .def @feat.00; | ||
| 10 | .scl 3; | ||
| 11 | .type 0; | ||
| 12 | .endef | ||
| 13 | .globl @feat.00 | ||
| 14 | @feat.00 = 1 | ||
| 15 | |||
| 16 | .def _main; | ||
| 17 | .scl 2; | ||
| 18 | .type 32; | ||
| 19 | .endef | ||
| 20 | .section .text,"xr",one_only,_main | ||
| 21 | .globl _main | ||
| 22 | _main: | ||
| 23 | movl $42, %eax | ||
| 24 | ret | ||
| 25 | |||
| 26 | .safeseh __except_handler3 | ||
| 27 | |||
| 28 | 	.section .rdata,"dr" | ||
| 29 | .globl __load_config_used | ||
| 30 | __load_config_used: | ||
| 31 | .long 72 | ||
| 32 | .fill 60, 1, 0 | ||
| 33 | .long ___safe_se_handler_table | ||
| 34 | .long ___safe_se_handler_count | ||
deps/lld/test/COFF/safeseh.s+13-2| ... | @@ -1,9 +1,15 @@ | ... | @@ -1,9 +1,15 @@ |
| 1 | # RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj | 1 | # RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj |
| 2 | # RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:noref -entry:main | 2 | # RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:noref -entry:main |
| 3 | # RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-NOGC | 3 | # RUN: llvm-readobj -coff-basereloc -coff-load-config -file-headers %t.exe | FileCheck %s --check-prefix=CHECK-NOGC |
| 4 | # RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:ref -entry:main | 4 | # RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:ref -entry:main |
| 5 | # RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-GC | 5 | # RUN: llvm-readobj -coff-basereloc -coff-load-config -file-headers %t.exe | FileCheck %s --check-prefix=CHECK-GC |
| 6 | 6 | ||
| 7 | # __safe_se_handler_table needs to be relocated against ImageBase. | ||
| 8 | # check that the relocation is present. | ||
| 9 | # CHECK-NOGC-NOT: IMAGE_DLL_CHARACTERISTICS_NO_SEH | ||
| 10 | # CHECK-NOGC: BaseReloc [ | ||
| 11 | # CHECK-NOGC: Entry { | ||
| 12 | # CHECK-NOGC: Type: HIGHLOW | ||
| 7 | # CHECK-NOGC: LoadConfig [ | 13 | # CHECK-NOGC: LoadConfig [ |
| 8 | # CHECK-NOGC: Size: 0x48 | 14 | # CHECK-NOGC: Size: 0x48 |
| 9 | # CHECK-NOGC: SEHandlerTable: 0x401048 | 15 | # CHECK-NOGC: SEHandlerTable: 0x401048 |
| ... | @@ -13,6 +19,11 @@ | ... | @@ -13,6 +19,11 @@ |
| 13 | # CHECK-NOGC-NEXT: 0x402006 | 19 | # CHECK-NOGC-NEXT: 0x402006 |
| 14 | # CHECK-NOGC-NEXT: ] | 20 | # CHECK-NOGC-NEXT: ] |
| 15 | 21 | ||
| 22 | # Without the SEH table, the address is absolute, so check that we do | ||
| 23 | # not have a relocation for it. | ||
| 24 | # CHECK-GC-NOT: IMAGE_DLL_CHARACTERISTICS_NO_SEH | ||
| 25 | # CHECK-GC: BaseReloc [ | ||
| 26 | # CHECK-GC-NEXT: ] | ||
| 16 | # CHECK-GC: LoadConfig [ | 27 | # CHECK-GC: LoadConfig [ |
| 17 | # CHECK-GC: Size: 0x48 | 28 | # CHECK-GC: Size: 0x48 |
| 18 | # CHECK-GC: SEHandlerTable: 0x0 | 29 | # CHECK-GC: SEHandlerTable: 0x0 |
deps/lld/test/COFF/section-size.s created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc %s -o %tmain.obj | ||
| 3 | # RUN: echo '.lcomm s, 0x80000000' | llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %t1.obj | ||
| 4 | # RUN: cp %t1.obj %t2.obj | ||
| 5 | # RUN: echo '.lcomm s, 0xffffffff' | llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %t3.obj | ||
| 6 | |||
| 7 | # Run: lld-link -entry:main %tmain.obj %t3.obj -out:%t.exe | ||
| 8 | |||
| 9 | # RUN: not lld-link -entry:main %tmain.obj %t1.obj %t2.obj -out:%t.exe 2>&1 | FileCheck %s | ||
| 10 | # CHECK: error: section larger than 4 GiB: .bss | ||
| 11 | |||
| 12 | .globl main | ||
| 13 | main: | ||
| 14 | 	retq | ||
deps/lld/test/COFF/seh-comdat.test created+66| ... | @@ -0,0 +1,66 @@ | ||
| 1 | # RUN: yaml2obj < %s > %t1.obj | ||
| 2 | # RUN: yaml2obj < %s > %t2.obj | ||
| 3 | # RUN: lld-link /out:%t.exe /subsystem:console /entry:main %t1.obj %t2.obj | ||
| 4 | # RUN: llvm-objdump -s %t.exe | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: Contents of section .rdata: | ||
| 7 | # CHECK: 1000 00200000 | ||
| 8 | |||
| 9 | --- !COFF | ||
| 10 | header: | ||
| 11 | Machine: IMAGE_FILE_MACHINE_I386 | ||
| 12 | Characteristics: [ ] | ||
| 13 | sections: | ||
| 14 | - Name: .text | ||
| 15 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ, IMAGE_SCN_LNK_COMDAT ] | ||
| 16 | Alignment: 1 | ||
| 17 | SectionData: 0000000000000000 | ||
| 18 | - Name: .sxdata | ||
| 19 | Characteristics: [ IMAGE_SCN_LNK_INFO ] | ||
| 20 | Alignment: 4 | ||
| 21 | SectionData: 02000000 | ||
| 22 | symbols: | ||
| 23 | - Name: '@comp.id' | ||
| 24 | Value: 14766605 | ||
| 25 | SectionNumber: 65535 | ||
| 26 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 27 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 28 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 29 | - Name: '@feat.00' | ||
| 30 | Value: 2147484049 | ||
| 31 | SectionNumber: 65535 | ||
| 32 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 33 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 34 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 35 | - Name: .text | ||
| 36 | Value: 0 | ||
| 37 | SectionNumber: 1 | ||
| 38 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 39 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 40 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 41 | SectionDefinition: | ||
| 42 | Length: 4 | ||
| 43 | NumberOfRelocations: 0 | ||
| 44 | NumberOfLinenumbers: 0 | ||
| 45 | CheckSum: 0 | ||
| 46 | Number: 0 | ||
| 47 | Selection: IMAGE_COMDAT_SELECT_ANY | ||
| 48 | - Name: .sxdata | ||
| 49 | Value: 0 | ||
| 50 | SectionNumber: 2 | ||
| 51 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 52 | ComplexType: IMAGE_SYM_DTYPE_NULL | ||
| 53 | StorageClass: IMAGE_SYM_CLASS_STATIC | ||
| 54 | SectionDefinition: | ||
| 55 | Length: 8 | ||
| 56 | NumberOfRelocations: 0 | ||
| 57 | NumberOfLinenumbers: 0 | ||
| 58 | CheckSum: 0 | ||
| 59 | Number: 0 | ||
| 60 | - Name: _main | ||
| 61 | Value: 0 | ||
| 62 | SectionNumber: 1 | ||
| 63 | SimpleType: IMAGE_SYM_TYPE_NULL | ||
| 64 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
| 65 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
| 66 | ... | ||
deps/lld/test/COFF/strtab-size.s created+216| ... | @@ -0,0 +1,216 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # Test that the strtab size is included in the allocation even if the | ||
| 4 | # strtab itself is empty. To achieve this, we need a number of symbols N | ||
| 5 | # where alignTo(N*18, 512) < alignTo(N*18 + 4, 512), where the first | ||
| 6 | # positive N fulfilling that is 199. | ||
| 7 | |||
| 8 | # RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t.obj | ||
| 9 | # RUN: lld-link -out:%t.exe -entry:main %t.obj -debug:dwarf | ||
| 10 | |||
| 11 | # If the size of the strtab isn't allocated for, llvm-readobj would | ||
| 12 | # output SymbolCount: 0 (and dumpbin.exe would error out with "invalid file | ||
| 13 | # or disk full, cannot seek to 0x1602"). | ||
| 14 | |||
| 15 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s | ||
| 16 | # CHECK: SymbolCount: 199 | ||
| 17 | |||
| 18 | .global main | ||
| 19 | .text | ||
| 20 | main: | ||
| 21 | sym0: | ||
| 22 | sym1: | ||
| 23 | sym2: | ||
| 24 | sym3: | ||
| 25 | sym4: | ||
| 26 | sym5: | ||
| 27 | sym6: | ||
| 28 | sym7: | ||
| 29 | sym8: | ||
| 30 | sym9: | ||
| 31 | sym10: | ||
| 32 | sym11: | ||
| 33 | sym12: | ||
| 34 | sym13: | ||
| 35 | sym14: | ||
| 36 | sym15: | ||
| 37 | sym16: | ||
| 38 | sym17: | ||
| 39 | sym18: | ||
| 40 | sym19: | ||
| 41 | sym20: | ||
| 42 | sym21: | ||
| 43 | sym22: | ||
| 44 | sym23: | ||
| 45 | sym24: | ||
| 46 | sym25: | ||
| 47 | sym26: | ||
| 48 | sym27: | ||
| 49 | sym28: | ||
| 50 | sym29: | ||
| 51 | sym30: | ||
| 52 | sym31: | ||
| 53 | sym32: | ||
| 54 | sym33: | ||
| 55 | sym34: | ||
| 56 | sym35: | ||
| 57 | sym36: | ||
| 58 | sym37: | ||
| 59 | sym38: | ||
| 60 | sym39: | ||
| 61 | sym40: | ||
| 62 | sym41: | ||
| 63 | sym42: | ||
| 64 | sym43: | ||
| 65 | sym44: | ||
| 66 | sym45: | ||
| 67 | sym46: | ||
| 68 | sym47: | ||
| 69 | sym48: | ||
| 70 | sym49: | ||
| 71 | sym50: | ||
| 72 | sym51: | ||
| 73 | sym52: | ||
| 74 | sym53: | ||
| 75 | sym54: | ||
| 76 | sym55: | ||
| 77 | sym56: | ||
| 78 | sym57: | ||
| 79 | sym58: | ||
| 80 | sym59: | ||
| 81 | sym60: | ||
| 82 | sym61: | ||
| 83 | sym62: | ||
| 84 | sym63: | ||
| 85 | sym64: | ||
| 86 | sym65: | ||
| 87 | sym66: | ||
| 88 | sym67: | ||
| 89 | sym68: | ||
| 90 | sym69: | ||
| 91 | sym70: | ||
| 92 | sym71: | ||
| 93 | sym72: | ||
| 94 | sym73: | ||
| 95 | sym74: | ||
| 96 | sym75: | ||
| 97 | sym76: | ||
| 98 | sym77: | ||
| 99 | sym78: | ||
| 100 | sym79: | ||
| 101 | sym80: | ||
| 102 | sym81: | ||
| 103 | sym82: | ||
| 104 | sym83: | ||
| 105 | sym84: | ||
| 106 | sym85: | ||
| 107 | sym86: | ||
| 108 | sym87: | ||
| 109 | sym88: | ||
| 110 | sym89: | ||
| 111 | sym90: | ||
| 112 | sym91: | ||
| 113 | sym92: | ||
| 114 | sym93: | ||
| 115 | sym94: | ||
| 116 | sym95: | ||
| 117 | sym96: | ||
| 118 | sym97: | ||
| 119 | sym98: | ||
| 120 | sym99: | ||
| 121 | sym100: | ||
| 122 | sym101: | ||
| 123 | sym102: | ||
| 124 | sym103: | ||
| 125 | sym104: | ||
| 126 | sym105: | ||
| 127 | sym106: | ||
| 128 | sym107: | ||
| 129 | sym108: | ||
| 130 | sym109: | ||
| 131 | sym110: | ||
| 132 | sym111: | ||
| 133 | sym112: | ||
| 134 | sym113: | ||
| 135 | sym114: | ||
| 136 | sym115: | ||
| 137 | sym116: | ||
| 138 | sym117: | ||
| 139 | sym118: | ||
| 140 | sym119: | ||
| 141 | sym120: | ||
| 142 | sym121: | ||
| 143 | sym122: | ||
| 144 | sym123: | ||
| 145 | sym124: | ||
| 146 | sym125: | ||
| 147 | sym126: | ||
| 148 | sym127: | ||
| 149 | sym128: | ||
| 150 | sym129: | ||
| 151 | sym130: | ||
| 152 | sym131: | ||
| 153 | sym132: | ||
| 154 | sym133: | ||
| 155 | sym134: | ||
| 156 | sym135: | ||
| 157 | sym136: | ||
| 158 | sym137: | ||
| 159 | sym138: | ||
| 160 | sym139: | ||
| 161 | sym140: | ||
| 162 | sym141: | ||
| 163 | sym142: | ||
| 164 | sym143: | ||
| 165 | sym144: | ||
| 166 | sym145: | ||
| 167 | sym146: | ||
| 168 | sym147: | ||
| 169 | sym148: | ||
| 170 | sym149: | ||
| 171 | sym150: | ||
| 172 | sym151: | ||
| 173 | sym152: | ||
| 174 | sym153: | ||
| 175 | sym154: | ||
| 176 | sym155: | ||
| 177 | sym156: | ||
| 178 | sym157: | ||
| 179 | sym158: | ||
| 180 | sym159: | ||
| 181 | sym160: | ||
| 182 | sym161: | ||
| 183 | sym162: | ||
| 184 | sym163: | ||
| 185 | sym164: | ||
| 186 | sym165: | ||
| 187 | sym166: | ||
| 188 | sym167: | ||
| 189 | sym168: | ||
| 190 | sym169: | ||
| 191 | sym170: | ||
| 192 | sym171: | ||
| 193 | sym172: | ||
| 194 | sym173: | ||
| 195 | sym174: | ||
| 196 | sym175: | ||
| 197 | sym176: | ||
| 198 | sym177: | ||
| 199 | sym178: | ||
| 200 | sym179: | ||
| 201 | sym180: | ||
| 202 | sym181: | ||
| 203 | sym182: | ||
| 204 | sym183: | ||
| 205 | sym184: | ||
| 206 | sym185: | ||
| 207 | sym186: | ||
| 208 | sym187: | ||
| 209 | sym188: | ||
| 210 | sym189: | ||
| 211 | sym190: | ||
| 212 | sym191: | ||
| 213 | sym192: | ||
| 214 | sym193: | ||
| 215 | sym194: | ||
| 216 | ret | ||
deps/lld/test/COFF/subsystem-drectve.test created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | # RUN: yaml2obj < %s > %t.obj | ||
| 2 | # RUN: lld-link /dll /noentry /out:%t.dll %t.obj | ||
| 3 | # RUN: llvm-readobj -file-headers %t.dll | FileCheck %s | ||
| 4 | |||
| 5 | # CHECK: MajorOperatingSystemVersion: 42 | ||
| 6 | # CHECK: MinorOperatingSystemVersion: 43 | ||
| 7 | # CHECK: MajorSubsystemVersion: 42 | ||
| 8 | # CHECK: MinorSubsystemVersion: 43 | ||
| 9 | # CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI | ||
| 10 | |||
| 11 | --- !COFF | ||
| 12 | header: | ||
| 13 | Machine: IMAGE_FILE_MACHINE_I386 | ||
| 14 | Characteristics: [] | ||
| 15 | sections: | ||
| 16 | - Name: .drectve | ||
| 17 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | ||
| 18 | Alignment: 1 | ||
| 19 | SectionData: 2f73756273797374656d3a636f6e736f6c652c34322e343300 # /subsystem:console,42.43 | ||
| 20 | symbols: | ||
| 21 | ... | ||
deps/lld/test/COFF/symtab.test+3-3| ... | @@ -1,10 +1,10 @@ | ... | @@ -1,10 +1,10 @@ |
| 1 | # RUN: yaml2obj < %s > %t.obj | 1 | # RUN: yaml2obj < %s > %t.obj |
| 2 | # RUN: lld-link /debug /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib | 2 | # RUN: lld-link /debug:dwarf /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib |
| 3 | # RUN: llvm-readobj -symbols %t.exe | FileCheck %s | 3 | # RUN: llvm-readobj -symbols %t.exe | FileCheck %s |
| 4 | # RUN: lld-link /debug /opt:noref /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib | 4 | # 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 %s | 5 | # RUN: llvm-readobj -symbols %t.exe | FileCheck %s |
| 6 | 6 | ||
| 7 | # RUN: lld-link /debug /nosymtab /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib | 7 | # RUN: lld-link /debug /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib |
| 8 | # RUN: llvm-readobj -symbols %t.exe | FileCheck -check-prefix=NO %s | 8 | # RUN: llvm-readobj -symbols %t.exe | FileCheck -check-prefix=NO %s |
| 9 | 9 | ||
| 10 | # CHECK: Symbols [ | 10 | # CHECK: Symbols [ |
deps/lld/test/COFF/thinlto.ll+1-1| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | ; RUN: opt -thinlto-bc -o %T/thinlto/main.obj %s | 4 | ; RUN: opt -thinlto-bc -o %T/thinlto/main.obj %s |
| 5 | ; RUN: opt -thinlto-bc -o %T/thinlto/foo.obj %S/Inputs/lto-dep.ll | 5 | ; RUN: opt -thinlto-bc -o %T/thinlto/foo.obj %S/Inputs/lto-dep.ll |
| 6 | ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj | 6 | ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj |
| 7 | ; RUN: llvm-nm %T/thinlto/main.exe.lto.obj | FileCheck %s | 7 | ; RUN: llvm-nm %T/thinlto/main.exe1.lto.obj | FileCheck %s |
| 8 | 8 | ||
| 9 | ; CHECK-NOT: U foo | 9 | ; CHECK-NOT: U foo |
| 10 | 10 |
deps/lld/test/COFF/wholearchive.s created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | # REQEUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: yaml2obj < %p/Inputs/export.yaml > %t.archive.obj | ||
| 4 | # RUN: llvm-ar rcs %t.archive.lib %t.archive.obj | ||
| 5 | # RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t.main.obj | ||
| 6 | |||
| 7 | # RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj -wholearchive:%t.archive.lib -implib:%t.lib | ||
| 8 | # RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB | ||
| 9 | |||
| 10 | # RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj -wholearchive %t.archive.lib -implib:%t.lib | ||
| 11 | # RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB | ||
| 12 | |||
| 13 | # CHECK-IMPLIB: Symbol: __imp_exportfn3 | ||
| 14 | # CHECK-IMPLIB: Symbol: exportfn3 | ||
| 15 | |||
| 16 | .global main | ||
| 17 | .text | ||
| 18 | main: | ||
| 19 | ret | ||
deps/lld/test/COFF/wx.s created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # 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 | \ | ||
| 5 | # RUN: FileCheck -check-prefix=ERROR %s | ||
| 6 | # RUN: not lld-link /out:%t.exe /entry:main -notarealoption /WX:NO /WX %t.obj 2>&1 | \ | ||
| 7 | # RUN: FileCheck -check-prefix=ERROR %s | ||
| 8 | # RUN: lld-link /out:%t.exe /entry:main -notarealoption /WX /WX:NO %t.obj 2>&1 | \ | ||
| 9 | # RUN: FileCheck -check-prefix=WARNING %s | ||
| 10 | |||
| 11 | # ERROR: error: ignoring unknown argument: -notarealoption | ||
| 12 | # WARNING: warning: ignoring unknown argument: -notarealoption | ||
| 13 | |||
| 14 | .text | ||
| 15 | .global main | ||
| 16 | main: | ||
| 17 | 	ret | ||
deps/lld/test/ELF/Inputs/amdgpu-kernel-0.s created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | .text | ||
| 2 | .globl kernel_0 | ||
| 3 | .align 64 | ||
| 4 | .amdgpu_hsa_kernel kernel_0 | ||
| 5 | kernel_0: | ||
| 6 | s_endpgm | ||
deps/lld/test/ELF/Inputs/amdgpu-kernel-1.s created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | .text | ||
| 2 | .globl kernel_1 | ||
| 3 | .align 64 | ||
| 4 | .amdgpu_hsa_kernel kernel_1 | ||
| 5 | kernel_1: | ||
| 6 | s_endpgm | ||
deps/lld/test/ELF/Inputs/amdgpu-kernel-2.o created| Binary files /dev/null and b/deps/lld/test/ELF/Inputs/amdgpu-kernel-2.o differ | |||
deps/lld/test/ELF/Inputs/compress-debug.s created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | .text | ||
| 2 | .fill 0x44 | ||
| 3 | |||
| 4 | .section .debug_info,"",@progbits | ||
| 5 | .fill 0x43 | ||
deps/lld/test/ELF/Inputs/copy-rel-abs.s created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | .global foo | ||
| 2 | .type foo, @object | ||
| 3 | .size foo, 4 | ||
| 4 | foo: | ||
| 5 | .weak bar | ||
| 6 | .type bar, @object | ||
| 7 | .size bar, 4 | ||
| 8 | bar: | ||
| 9 | .long 42 | ||
| 10 | |||
| 11 | .weak zed | ||
| 12 | .type zed, @object | ||
| 13 | zed = 0x1000 | ||
deps/lld/test/ELF/Inputs/copy-rel-large.s created+4| ... | @@ -0,0 +1,4 @@ | ||
| 1 | .global foo | ||
| 2 | .type foo, @object | ||
| 3 | foo: | ||
| 4 | .size foo, 0x100000001 | ||
deps/lld/test/ELF/Inputs/copy-rel-pie.s+1| ... | @@ -9,3 +9,4 @@ foo: | ... | @@ -9,3 +9,4 @@ foo: |
| 9 | .global bar | 9 | .global bar |
| 10 | .type bar, @function | 10 | .type bar, @function |
| 11 | bar: | 11 | bar: |
| 12 | retq |
deps/lld/test/ELF/Inputs/corrupt-version-reference.so created| Binary files /dev/null and b/deps/lld/test/ELF/Inputs/corrupt-version-reference.so differ | |||
deps/lld/test/ELF/Inputs/dynamic-list-weak-archive.s created+2| ... | @@ -0,0 +1,2 @@ | ||
| 1 | .globl foo | ||
| 2 | foo: | ||
deps/lld/test/ELF/Inputs/eh-frame.s created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | .cfi_startproc | ||
| 2 | .cfi_def_cfa_offset 32 | ||
| 3 | .cfi_endproc | ||
deps/lld/test/ELF/Inputs/gc-sections-shared.s created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | .global baz | ||
| 2 | .type baz, @function | ||
| 3 | baz: | ||
deps/lld/test/ELF/Inputs/gc-sections-shared2.s created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | .global qux | ||
| 2 | .type qux, @function | ||
| 3 | qux: | ||
deps/lld/test/ELF/Inputs/local-symbol-in-dso.so created| Binary files /dev/null and b/deps/lld/test/ELF/Inputs/local-symbol-in-dso.so differ | |||
deps/lld/test/ELF/Inputs/map-file5.s created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | .bss | ||
| 2 | .type sharedFoo,@object | ||
| 3 | .globl sharedFoo | ||
| 4 | sharedFoo: | ||
| 5 | .long 0 | ||
| 6 | .size sharedFoo, 4 | ||
| 7 | |||
| 8 | .type sharedBar,@object | ||
| 9 | .globl sharedBar | ||
| 10 | sharedBar: | ||
| 11 | .quad 0 | ||
| 12 | .size sharedBar, 8 | ||
| 13 | |||
| 14 | .text | ||
| 15 | .globl sharedFunc1 | ||
| 16 | .type sharedFunc1,@function | ||
| 17 | sharedFunc1: | ||
| 18 | nop | ||
| 19 | |||
| 20 | .globl sharedFunc2 | ||
| 21 | .type sharedFunc2,@function | ||
| 22 | sharedFunc2: | ||
| 23 | nop | ||
deps/lld/test/ELF/Inputs/mips-micro.s created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | .text | ||
| 2 | .set micromips | ||
| 3 | .global foo | ||
| 4 | .type foo,@function | ||
| 5 | foo: | ||
| 6 | nop | ||
| 7 | |||
| 8 | .set nomicromips | ||
| 9 | .global bar | ||
| 10 | .type bar,@function | ||
| 11 | bar: | ||
| 12 | nop | ||
deps/lld/test/ELF/Inputs/shared3.s+1-1| ... | @@ -1,3 +1,3 @@ | ... | @@ -1,3 +1,3 @@ |
| 1 | .global baz | 1 | .global baz |
| 2 | .type barz, @function | 2 | .type baz, @function |
| 3 | baz: | 3 | baz: |
deps/lld/test/ELF/Inputs/shlib-undefined-ref.s created+4| ... | @@ -0,0 +1,4 @@ | ||
| 1 | .globl f | ||
| 2 | f: | ||
| 3 | 	call	should_not_be_exported@PLT | ||
| 4 | 	ret | ||
deps/lld/test/ELF/Inputs/undefined-error.s created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | callq fmod@PLT | ||
deps/lld/test/ELF/Inputs/verdef-defaultver.s+3| ... | @@ -1,4 +1,7 @@ | ... | @@ -1,4 +1,7 @@ |
| 1 | .global b@V1 | ||
| 1 | b@V1 = b_1 | 2 | b@V1 = b_1 |
| 3 | |||
| 4 | .global b@@V2 | ||
| 2 | b@@V2 = b_2 | 5 | b@@V2 = b_2 |
| 3 | 6 | ||
| 4 | .globl a | 7 | .globl a |
deps/lld/test/ELF/Inputs/verneed.so.sh deleted-58| ... | @@ -1,58 +0,0 @@ | ||
| 1 | #!/bin/sh -eu | ||
| 2 | |||
| 3 | # This script was used to produce the verneed{1,2}.so files. | ||
| 4 | |||
| 5 | tmp=$(mktemp -d) | ||
| 6 | |||
| 7 | echo "v1 {}; v2 {}; v3 {}; { local: *; };" > $tmp/verneed.script | ||
| 8 | |||
| 9 | cat > $tmp/verneed1.s <<eof | ||
| 10 | .globl f1_v1 | ||
| 11 | f1_v1: | ||
| 12 | ret | ||
| 13 | |||
| 14 | .globl f1_v2 | ||
| 15 | f1_v2: | ||
| 16 | ret | ||
| 17 | |||
| 18 | .globl f1_v3 | ||
| 19 | f1_v3: | ||
| 20 | ret | ||
| 21 | |||
| 22 | .symver f1_v1, f1@v1 | ||
| 23 | .symver f1_v2, f1@v2 | ||
| 24 | .symver f1_v3, f1@@v3 | ||
| 25 | |||
| 26 | .globl f2_v1 | ||
| 27 | f2_v1: | ||
| 28 | ret | ||
| 29 | |||
| 30 | .globl f2_v2 | ||
| 31 | f2_v2: | ||
| 32 | ret | ||
| 33 | |||
| 34 | .symver f2_v1, f2@v1 | ||
| 35 | .symver f2_v2, f2@@v2 | ||
| 36 | |||
| 37 | .globl f3_v1 | ||
| 38 | f3_v1: | ||
| 39 | ret | ||
| 40 | |||
| 41 | .symver f3_v1, f3@v1 | ||
| 42 | eof | ||
| 43 | |||
| 44 | as -o $tmp/verneed1.o $tmp/verneed1.s | ||
| 45 | ld.gold -shared -o verneed1.so $tmp/verneed1.o --version-script $tmp/verneed.script -soname verneed1.so.0 | ||
| 46 | |||
| 47 | cat > $tmp/verneed2.s <<eof | ||
| 48 | .globl g1_v1 | ||
| 49 | g1_v1: | ||
| 50 | ret | ||
| 51 | |||
| 52 | .symver g1_v1, g1@@v1 | ||
| 53 | eof | ||
| 54 | |||
| 55 | as -o $tmp/verneed2.o $tmp/verneed2.s | ||
| 56 | ld.gold -shared -o verneed2.so $tmp/verneed2.o --version-script $tmp/verneed.script -soname verneed2.so.0 | ||
| 57 | |||
| 58 | rm -rf $tmp | ||
deps/lld/test/ELF/Inputs/verneed1.s created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | .globl f1_v1 | ||
| 2 | f1_v1: | ||
| 3 | ret | ||
| 4 | |||
| 5 | .globl f1_v2 | ||
| 6 | f1_v2: | ||
| 7 | ret | ||
| 8 | |||
| 9 | .globl f1_v3 | ||
| 10 | f1_v3: | ||
| 11 | ret | ||
| 12 | |||
| 13 | .symver f1_v1, f1@v1 | ||
| 14 | .symver f1_v2, f1@v2 | ||
| 15 | .symver f1_v3, f1@@v3 | ||
| 16 | |||
| 17 | .globl f2_v1 | ||
| 18 | f2_v1: | ||
| 19 | ret | ||
| 20 | |||
| 21 | .globl f2_v2 | ||
| 22 | f2_v2: | ||
| 23 | ret | ||
| 24 | |||
| 25 | .symver f2_v1, f2@v1 | ||
| 26 | .symver f2_v2, f2@@v2 | ||
| 27 | |||
| 28 | .globl f3_v1 | ||
| 29 | f3_v1: | ||
| 30 | ret | ||
| 31 | |||
| 32 | .symver f3_v1, f3@v1 | ||
deps/lld/test/ELF/Inputs/verneed1.so deleted| Binary files a/deps/lld/test/ELF/Inputs/verneed1.so and /dev/null differ | |||
deps/lld/test/ELF/Inputs/verneed2.s created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | .globl g1_v1 | ||
| 2 | g1_v1: | ||
| 3 | ret | ||
| 4 | |||
| 5 | .symver g1_v1, g1@@v1 | ||
deps/lld/test/ELF/Inputs/verneed2.so deleted| Binary files a/deps/lld/test/ELF/Inputs/verneed2.so and /dev/null differ | |||
deps/lld/test/ELF/Inputs/weak-undef-lazy.s created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | .global foobar | ||
| 2 | foobar: | ||
| 3 | nop | ||
deps/lld/test/ELF/Inputs/wrap-no-real.s created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | .globl foo, __wrap_foo | ||
| 2 | foo = 0x11000 | ||
| 3 | __wrap_foo = 0x11010 | ||
deps/lld/test/ELF/Inputs/wrap-no-real2.s created+2| ... | @@ -0,0 +1,2 @@ | ||
| 1 | .globl __real_foo | ||
| 2 | __real_foo = 0x11020 | ||
deps/lld/test/ELF/Inputs/wrap.s+4-1| ... | @@ -1,4 +1,7 @@ | ... | @@ -1,4 +1,7 @@ |
| 1 | .globl foo, __wrap_foo, __real_foo | 1 | .global foo |
| 2 | .weak __wrap_foo | ||
| 3 | .protected __wrap_foo | ||
| 4 | .global __real_foo | ||
| 2 | foo = 0x11000 | 5 | foo = 0x11000 |
| 3 | __wrap_foo = 0x11010 | 6 | __wrap_foo = 0x11010 |
| 4 | __real_foo = 0x11020 | 7 | __real_foo = 0x11020 |
deps/lld/test/ELF/Inputs/writable-sec-plt-reloc.s created+4| ... | @@ -0,0 +1,4 @@ | ||
| 1 | .global foo | ||
| 2 | .type foo, @function | ||
| 3 | foo: | ||
| 4 | retq | ||
deps/lld/test/ELF/Inputs/znotext-copy-relocations.s created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | .global foo | ||
| 2 | .type foo,@object | ||
| 3 | .size foo, 8 | ||
| 4 | foo: | ||
| 5 | .quad 42 | ||
deps/lld/test/ELF/Inputs/znotext-plt-relocations-protected.s created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | .global foo | ||
| 2 | .type foo,@function | ||
| 3 | .protected foo | ||
| 4 | foo: | ||
| 5 | nop | ||
deps/lld/test/ELF/Inputs/znotext-plt-relocations.s created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | .text | ||
| 2 | .global atexit | ||
| 3 | .type atexit,@function | ||
| 4 | atexit: | ||
| 5 | nop | ||
| 6 | |||
| 7 | .global foo | ||
| 8 | .type foo,@function | ||
| 9 | foo: | ||
| 10 | nop | ||
deps/lld/test/ELF/aarch64-abs16.s+1-1| ... | @@ -24,4 +24,4 @@ _start: | ... | @@ -24,4 +24,4 @@ _start: |
| 24 | // | FileCheck %s --check-prefix=OVERFLOW | 24 | // | FileCheck %s --check-prefix=OVERFLOW |
| 25 | // RUN: not ld.lld %t.o %t257.o -o %t2 | 25 | // RUN: not ld.lld %t.o %t257.o -o %t2 |
| 26 | // | FileCheck %s --check-prefix=OVERFLOW | 26 | // | FileCheck %s --check-prefix=OVERFLOW |
| 27 | // OVERFLOW: Relocation R_AARCH64_ABS16 out of range | 27 | // OVERFLOW: Relocation R_AARCH64_ABS16 out of range: 65536 is not in [-32768, 65535] |
deps/lld/test/ELF/aarch64-abs32.s+1-1| ... | @@ -24,4 +24,4 @@ _start: | ... | @@ -24,4 +24,4 @@ _start: |
| 24 | // | FileCheck %s --check-prefix=OVERFLOW | 24 | // | FileCheck %s --check-prefix=OVERFLOW |
| 25 | // RUN: not ld.lld %t.o %t257.o -o %t2 | 25 | // RUN: not ld.lld %t.o %t257.o -o %t2 |
| 26 | // | FileCheck %s --check-prefix=OVERFLOW | 26 | // | FileCheck %s --check-prefix=OVERFLOW |
| 27 | // OVERFLOW: Relocation R_AARCH64_ABS32 out of range | 27 | // OVERFLOW: Relocation R_AARCH64_ABS32 out of range: 4294967296 is not in [-2147483648, 4294967295] |
deps/lld/test/ELF/aarch64-call26-error.s deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %S/Inputs/abs.s -o %tabs | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t | ||
| 3 | // RUN: not ld.lld %t %tabs -o %t2 2>&1 | FileCheck %s | ||
| 4 | // REQUIRES: aarch64 | ||
| 5 | |||
| 6 | .text | ||
| 7 | .globl _start | ||
| 8 | _start: | ||
| 9 | bl big | ||
| 10 | |||
| 11 | // CHECK: R_AARCH64_CALL26 out of range | ||
deps/lld/test/ELF/aarch64-call26-thunk.s created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %S/Inputs/abs.s -o %tabs | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t | ||
| 3 | // RUN: ld.lld %t %tabs -o %t2 2>&1 | ||
| 4 | // RUN: llvm-objdump -d -triple=aarch64-pc-freebsd %t2 | FileCheck %s | ||
| 5 | // REQUIRES: aarch64 | ||
| 6 | |||
| 7 | .text | ||
| 8 | .globl _start | ||
| 9 | _start: | ||
| 10 | bl big | ||
| 11 | |||
| 12 | // CHECK: Disassembly of section .text: | ||
| 13 | // CHECK-NEXT: _start: | ||
| 14 | // CHECK-NEXT: 20000: 02 00 00 94 bl #8 | ||
| 15 | // CHECK: __AArch64AbsLongThunk_big: | ||
| 16 | // CHECK-NEXT: 20008: 50 00 00 58 ldr x16, #8 | ||
| 17 | // CHECK-NEXT: 2000c: 00 02 1f d6 br x16 | ||
| 18 | // CHECK: $d: | ||
| 19 | // CHECK-NEXT: 20010: 00 00 00 00 .word 0x00000000 | ||
| 20 | // CHECK-NEXT: 20014: 10 00 00 00 .word 0x00000010 | ||
| 21 | |||
deps/lld/test/ELF/aarch64-cortex-a53-843419-address.s created+180| ... | @@ -0,0 +1,180 @@ | ||
| 1 | // REQUIRES: aarch64 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o | ||
| 3 | // RUN: echo "SECTIONS { \ | ||
| 4 | // RUN: .text : { *(.text) *(.text.*) *(.newisd) } \ | ||
| 5 | // RUN: .text2 : { *.(newos) } \ | ||
| 6 | // RUN: .data : { *(.data) } }" > %t.script | ||
| 7 | // RUN: ld.lld --script %t.script -fix-cortex-a53-843419 -verbose %t.o -o %t2 | FileCheck -check-prefix=CHECK-PRINT %s | ||
| 8 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 | FileCheck %s | ||
| 9 | |||
| 10 | // Test cases for Cortex-A53 Erratum 843419 that involve interactions | ||
| 11 | // between the generated patches and the address of sections. | ||
| 12 | |||
| 13 | // See ARM-EPM-048406 Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf | ||
| 14 | // for full erratum details. | ||
| 15 | // In Summary | ||
| 16 | // 1.) | ||
| 17 | // ADRP (0xff8 or 0xffc). | ||
| 18 | // 2.) | ||
| 19 | // - load or store single register or either integer or vector registers. | ||
| 20 | // - STP or STNP of either vector or vector registers. | ||
| 21 | // - Advanced SIMD ST1 store instruction. | ||
| 22 | // - Must not write Rn. | ||
| 23 | // 3.) optional instruction, can't be a branch, must not write Rn, may read Rn. | ||
| 24 | // 4.) A load or store instruction from the Load/Store register unsigned | ||
| 25 | // immediate class using Rn as the base register. | ||
| 26 | |||
| 27 | // An aarch64 section can contain ranges of literal data embedded within the | ||
| 28 | // code, these ranges are encoded with mapping symbols. This tests that we | ||
| 29 | // can match the erratum sequence in code, but not data. | ||
| 30 | // - We can handle more than one patch per code range (denoted by mapping | ||
| 31 | // symbols). | ||
| 32 | // - We can handle a patch in more than range of code, with literal data | ||
| 33 | // inbetween. | ||
| 34 | // - We can handle redundant mapping symbols (two or more consecutive mapping | ||
| 35 | // symbols with the same type). | ||
| 36 | // - We can ignore erratum sequences in multiple literal data ranges. | ||
| 37 | |||
| 38 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at FF8 in unpatched output. | ||
| 39 | // CHECK: t3_ff8_ldr: | ||
| 40 | // CHECK-NEXT: ff8: 20 00 00 d0 adrp x0, #24576 | ||
| 41 | // CHECK-NEXT: ffc: 21 00 40 f9 ldr x1, [x1] | ||
| 42 | // CHECK-NEXT: 1000: f9 0f 00 14 b #16356 | ||
| 43 | // CHECK-NEXT: 1004: c0 03 5f d6 ret | ||
| 44 | .section .text.01, "ax", %progbits | ||
| 45 | .balign 4096 | ||
| 46 | .space 4096 - 8 | ||
| 47 | .globl t3_ff8_ldr | ||
| 48 | .type t3_ff8_ldr, %function | ||
| 49 | t3_ff8_ldr: | ||
| 50 | adrp x0, dat | ||
| 51 | ldr x1, [x1, #0] | ||
| 52 | ldr x0, [x0, :got_lo12:dat] | ||
| 53 | ret | ||
| 54 | |||
| 55 | // create a redundant mapping symbol as we are already in a $x range | ||
| 56 | // some object producers unconditionally generate a mapping symbol on | ||
| 57 | // every symbol so we need to handle the case of $x $x. | ||
| 58 | .local $x.999 | ||
| 59 | $x.999: | ||
| 60 | // CHECK-PRINT-NEXT: detected cortex-a53-843419 erratum sequence starting at 1FFC in unpatched output. | ||
| 61 | // CHECK: t3_ffc_ldrsimd: | ||
| 62 | // CHECK-NEXT: 1ffc: 20 00 00 b0 adrp x0, #20480 | ||
| 63 | // CHECK-NEXT: 2000: 21 00 40 bd ldr s1, [x1] | ||
| 64 | // CHECK-NEXT: 2004: fa 0b 00 14 b #12264 | ||
| 65 | // CHECK-NEXT: 2008: c0 03 5f d6 ret | ||
| 66 | .globl t3_ffc_ldrsimd | ||
| 67 | .type t3_ffc_ldrsimd, %function | ||
| 68 | .space 4096 - 12 | ||
| 69 | t3_ffc_ldrsimd: | ||
| 70 | adrp x0, dat | ||
| 71 | ldr s1, [x1, #0] | ||
| 72 | ldr x2, [x0, :got_lo12:dat] | ||
| 73 | ret | ||
| 74 | |||
| 75 | // Inline data containing bit pattern of erratum sequence, expect no patch. | ||
| 76 | .globl t3_ffc_ldralldata | ||
| 77 | .type t3_ff8_ldralldata, %function | ||
| 78 | .space 4096 - 20 | ||
| 79 | t3_ff8_ldralldata: | ||
| 80 | // 0x90000000 = adrp x0, #0 | ||
| 81 | .byte 0x00 | ||
| 82 | .byte 0x00 | ||
| 83 | .byte 0x00 | ||
| 84 | .byte 0x90 | ||
| 85 | // 0xf9400021 = ldr x1, [x1] | ||
| 86 | .byte 0x21 | ||
| 87 | .byte 0x00 | ||
| 88 | .byte 0x40 | ||
| 89 | .byte 0xf9 | ||
| 90 | // 0xf9400000 = ldr x0, [x0] | ||
| 91 | .byte 0x00 | ||
| 92 | .byte 0x00 | ||
| 93 | .byte 0x40 | ||
| 94 | .byte 0xf9 | ||
| 95 | // Check that we can recognise the erratum sequence post literal data. | ||
| 96 | |||
| 97 | // CHECK-PRINT-NEXT: detected cortex-a53-843419 erratum sequence starting at 3FF8 in unpatched output. | ||
| 98 | // CHECK: t3_ffc_ldr: | ||
| 99 | // CHECK-NEXT: 3ff8: 00 00 00 f0 adrp x0, #12288 | ||
| 100 | // CHECK-NEXT: 3ffc: 21 00 40 f9 ldr x1, [x1] | ||
| 101 | // CHECK-NEXT: 4000: fd 03 00 14 b #4084 | ||
| 102 | // CHECK-NEXT: 4004: c0 03 5f d6 ret | ||
| 103 | .space 4096 - 12 | ||
| 104 | .globl t3_ffc_ldr | ||
| 105 | .type t3_ffc_ldr, %function | ||
| 106 | t3_ffc_ldr: | ||
| 107 | adrp x0, dat | ||
| 108 | ldr x1, [x1, #0] | ||
| 109 | ldr x0, [x0, :got_lo12:dat] | ||
| 110 | ret | ||
| 111 | |||
| 112 | // CHECK: __CortexA53843419_1000: | ||
| 113 | // CHECK-NEXT: 4fe4: 00 0c 40 f9 ldr x0, [x0, #24] | ||
| 114 | // CHECK-NEXT: 4fe8: 07 f0 ff 17 b #-16356 | ||
| 115 | // CHECK: __CortexA53843419_2004: | ||
| 116 | // CHECK-NEXT: 4fec: 02 0c 40 f9 ldr x2, [x0, #24] | ||
| 117 | // CHECK-NEXT: 4ff0: 06 f4 ff 17 b #-12264 | ||
| 118 | // CHECK: __CortexA53843419_4000: | ||
| 119 | // CHECK-NEXT: 4ff4: 00 0c 40 f9 ldr x0, [x0, #24] | ||
| 120 | // CHECK-NEXT: 4ff8: 03 fc ff 17 b #-4084 | ||
| 121 | |||
| 122 | .section .text.02, "ax", %progbits | ||
| 123 | .space 4096 - 36 | ||
| 124 | |||
| 125 | // Start a new InputSectionDescription (see Linker Script) so the | ||
| 126 | // start address will be affected by any patches added to previous | ||
| 127 | // InputSectionDescription. | ||
| 128 | |||
| 129 | // CHECK-PRINT-NEXT: detected cortex-a53-843419 erratum sequence starting at 4FFC in unpatched output | ||
| 130 | // CHECK: t3_ffc_str: | ||
| 131 | // CHECK-NEXT: 4ffc: 00 00 00 d0 adrp x0, #8192 | ||
| 132 | // CHECK-NEXT: 5000: 21 00 00 f9 str x1, [x1] | ||
| 133 | // CHECK-NEXT: 5004: fb 03 00 14 b #4076 | ||
| 134 | // CHECK-NEXT: 5008: c0 03 5f d6 ret | ||
| 135 | |||
| 136 | .section .newisd, "ax", %progbits | ||
| 137 | .globl t3_ffc_str | ||
| 138 | .type t3_ffc_str, %function | ||
| 139 | t3_ffc_str: | ||
| 140 | adrp x0, dat | ||
| 141 | str x1, [x1, #0] | ||
| 142 | ldr x0, [x0, :got_lo12:dat] | ||
| 143 | ret | ||
| 144 | .space 4096 - 28 | ||
| 145 | |||
| 146 | // CHECK: __CortexA53843419_5004: | ||
| 147 | // CHECK-NEXT: 5ff0: 00 0c 40 f9 ldr x0, [x0, #24] | ||
| 148 | // CHECK-NEXT: 5ff4: 05 fc ff 17 b #-4076 | ||
| 149 | |||
| 150 | // Start a new OutputSection (see Linker Script) so the | ||
| 151 | // start address will be affected by any patches added to previous | ||
| 152 | // InputSectionDescription. | ||
| 153 | |||
| 154 | //CHECK-PRINT-NEXT: detected cortex-a53-843419 erratum sequence starting at 5FF8 in unpatched output | ||
| 155 | // CHECK: t3_ff8_str: | ||
| 156 | // CHECK-NEXT: 5ff8: 00 00 00 b0 adrp x0, #4096 | ||
| 157 | // CHECK-NEXT: 5ffc: 21 00 00 f9 str x1, [x1] | ||
| 158 | // CHECK-NEXT: 6000: 03 00 00 14 b #12 | ||
| 159 | // CHECK-NEXT: 6004: c0 03 5f d6 ret | ||
| 160 | |||
| 161 | .section .newos, "ax", %progbits | ||
| 162 | .globl t3_ff8_str | ||
| 163 | .type t3_ff8_str, %function | ||
| 164 | t3_ff8_str: | ||
| 165 | adrp x0, dat | ||
| 166 | str x1, [x1, #0] | ||
| 167 | ldr x0, [x0, :got_lo12:dat] | ||
| 168 | ret | ||
| 169 | .globl _start | ||
| 170 | .type _start, %function | ||
| 171 | _start: | ||
| 172 | ret | ||
| 173 | |||
| 174 | // CHECK: __CortexA53843419_6000: | ||
| 175 | // CHECK-NEXT: 600c: 00 0c 40 f9 ldr x0, [x0, #24] | ||
| 176 | // CHECK-NEXT: 6010: fd ff ff 17 b #-12 | ||
| 177 | |||
| 178 | .data | ||
| 179 | .globl dat | ||
| 180 | dat: .word 0 | ||
deps/lld/test/ELF/aarch64-cortex-a53-843419-cli.s created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | // RUN: not ld.lld %t -fix-cortex-a53-843419 -o %t2 2>&1 | FileCheck %s | ||
| 4 | |||
| 5 | // CHECK: --fix-cortex-a53-843419 is only supported on AArch64 targets. | ||
| 6 | .globl entry | ||
| 7 | .text | ||
| 8 | .quad 0 | ||
| 9 | entry: | ||
| 10 | ret | ||
deps/lld/test/ELF/aarch64-cortex-a53-843419-large.s created+115| ... | @@ -0,0 +1,115 @@ | ||
| 1 | // REQUIRES: aarch64 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o | ||
| 3 | // RUN: ld.lld --fix-cortex-a53-843419 %t.o -o %t2 | ||
| 4 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=131072 -stop-address=131084 | FileCheck --check-prefix=CHECK1 %s | ||
| 5 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=135168 -stop-address=135172 | FileCheck --check-prefix=CHECK2 %s | ||
| 6 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=139256 -stop-address=139272 | FileCheck --check-prefix=CHECK3 %s | ||
| 7 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=67256312 -stop-address=67256328 | FileCheck --check-prefix=CHECK4 %s | ||
| 8 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=100810760 -stop-address=100810776 | FileCheck --check-prefix=CHECK5 %s | ||
| 9 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=134352908 -stop-address=134352912 | FileCheck --check-prefix=CHECK6 %s | ||
| 10 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=134356988 -stop-address=134357012 | FileCheck --check-prefix=CHECK7 %s | ||
| 11 | // Test case for Cortex-A53 Erratum 843419 in an OutputSection exceeding | ||
| 12 | // the maximum branch range. Both range extension thunks and patches are | ||
| 13 | // required. | ||
| 14 | |||
| 15 | // CHECK1: __AArch64AbsLongThunk_need_thunk_after_patch: | ||
| 16 | // CHECK1-NEXT: 20000: 50 00 00 58 ldr x16, #8 | ||
| 17 | // CHECK1-NEXT: 20004: 00 02 1f d6 br x16 | ||
| 18 | // CHECK1: $d: | ||
| 19 | // CHECK1-NEXT: 20008: 0c 10 02 08 .word 0x0802100c | ||
| 20 | |||
| 21 | .section .text.01, "ax", %progbits | ||
| 22 | .balign 4096 | ||
| 23 | .globl _start | ||
| 24 | .type _start, %function | ||
| 25 | _start: | ||
| 26 | // Expect thunk on pass 2 | ||
| 27 | bl need_thunk_after_patch | ||
| 28 | .section .text.02, "ax", %progbits | ||
| 29 | .space 4096 - 12 | ||
| 30 | |||
| 31 | // CHECK2: _start: | ||
| 32 | // CHECK2-NEXT: 21000: 00 fc ff 97 bl #-4096 | ||
| 33 | |||
| 34 | // Expect patch on pass 1 | ||
| 35 | .section .text.03, "ax", %progbits | ||
| 36 | .globl t3_ff8_ldr | ||
| 37 | .type t3_ff8_ldr, %function | ||
| 38 | t3_ff8_ldr: | ||
| 39 | adrp x0, dat | ||
| 40 | ldr x1, [x1, #0] | ||
| 41 | ldr x0, [x0, :got_lo12:dat] | ||
| 42 | ret | ||
| 43 | |||
| 44 | // CHECK3: t3_ff8_ldr: | ||
| 45 | // CHECK3-NEXT: 21ff8: 60 00 04 f0 adrp x0, #134279168 | ||
| 46 | // CHECK3-NEXT: 21ffc: 21 00 40 f9 ldr x1, [x1] | ||
| 47 | // CHECK3-NEXT: 22000: 02 08 80 15 b #100671496 | ||
| 48 | // CHECK3-NEXT: 22004: c0 03 5f d6 ret | ||
| 49 | |||
| 50 | .section .text.04, "ax", %progbits | ||
| 51 | .space 64 * 1024 * 1024 | ||
| 52 | |||
| 53 | // Expect patch on pass 1 | ||
| 54 | .section .text.05, "ax", %progbits | ||
| 55 | .balign 4096 | ||
| 56 | .space 4096 - 8 | ||
| 57 | .globl t3_ff8_str | ||
| 58 | .type t3_ff8_str, %function | ||
| 59 | t3_ff8_str: | ||
| 60 | adrp x0, dat | ||
| 61 | ldr x1, [x1, #0] | ||
| 62 | str x0, [x0, :got_lo12:dat] | ||
| 63 | ret | ||
| 64 | |||
| 65 | // CHECK4: t3_ff8_str: | ||
| 66 | // CHECK4-NEXT: 4023ff8: 60 00 02 b0 adrp x0, #67162112 | ||
| 67 | // CHECK4-NEXT: 4023ffc: 21 00 40 f9 ldr x1, [x1] | ||
| 68 | // CHECK4-NEXT: 4024000: 04 00 80 14 b #33554448 | ||
| 69 | // CHECK4-NEXT: 4024004: c0 03 5f d6 ret | ||
| 70 | |||
| 71 | .section .text.06, "ax", %progbits | ||
| 72 | .space 32 * 1024 * 1024 | ||
| 73 | |||
| 74 | // CHECK5: __CortexA53843419_21000: | ||
| 75 | // CHECK5-NEXT: 6024008: 00 00 40 f9 ldr x0, [x0] | ||
| 76 | // CHECK5-NEXT: 602400c: fe f7 7f 16 b #-100671496 | ||
| 77 | // CHECK5: __CortexA53843419_4023000: | ||
| 78 | // CHECK5-NEXT: 6024010: 00 00 00 f9 str x0, [x0] | ||
| 79 | // CHECK5-NEXT: 6024014: fc ff 7f 17 b #-33554448 | ||
| 80 | |||
| 81 | .section .text.07, "ax", %progbits | ||
| 82 | .space (32 * 1024 * 1024) - 12300 | ||
| 83 | |||
| 84 | .section .text.08, "ax", %progbits | ||
| 85 | .globl need_thunk_after_patch | ||
| 86 | .type need_thunk_after_patch, %function | ||
| 87 | need_thunk_after_patch: | ||
| 88 | ret | ||
| 89 | |||
| 90 | // CHECK6: need_thunk_after_patch: | ||
| 91 | // CHECK6-NEXT: 802100c: c0 03 5f d6 ret | ||
| 92 | |||
| 93 | // Will need a patch on pass 2 | ||
| 94 | .section .text.09, "ax", %progbits | ||
| 95 | .space 4096 - 20 | ||
| 96 | .globl t3_ffc_ldr | ||
| 97 | .type t3_ffc_ldr, %function | ||
| 98 | t3_ffc_ldr: | ||
| 99 | adrp x0, dat | ||
| 100 | ldr x1, [x1, #0] | ||
| 101 | ldr x0, [x0, :got_lo12:dat] | ||
| 102 | ret | ||
| 103 | |||
| 104 | // CHECK7: t3_ffc_ldr: | ||
| 105 | // CHECK7-NEXT: 8021ffc: 60 00 00 f0 adrp x0, #61440 | ||
| 106 | // CHECK7-NEXT: 8022000: 21 00 40 f9 ldr x1, [x1] | ||
| 107 | // CHECK7-NEXT: 8022004: 02 00 00 14 b #8 | ||
| 108 | // CHECK7-NEXT: 8022008: c0 03 5f d6 ret | ||
| 109 | // CHECK7: __CortexA53843419_8022004: | ||
| 110 | // CHECK7-NEXT: 802200c: 00 00 40 f9 ldr x0, [x0] | ||
| 111 | // CHECK7-NEXT: 8022010: fe ff ff 17 b #-8 | ||
| 112 | |||
| 113 | .section .data | ||
| 114 | .globl dat | ||
| 115 | dat: .quad 0 | ||
deps/lld/test/ELF/aarch64-cortex-a53-843419-nopatch.s created+338| ... | @@ -0,0 +1,338 @@ | ||
| 1 | // REQUIRES: aarch64 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o | ||
| 3 | // RUN: ld.lld -fix-cortex-a53-843419 -verbose -t %t.o -o %t2 | FileCheck %s | ||
| 4 | // Test cases for Cortex-A53 Erratum 843419 that we don't expect to recognize | ||
| 5 | // as needing a patch as one or more of the conditions isn't satisfied. | ||
| 6 | // See ARM-EPM-048406 Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf | ||
| 7 | // for full erratum details. | ||
| 8 | // In Summary | ||
| 9 | // 1.) | ||
| 10 | // ADRP (0xff8 or 0xffc) | ||
| 11 | // 2.) | ||
| 12 | // - load or store single register or either integer or vector registers | ||
| 13 | // - STP or STNP of either vector or vector registers | ||
| 14 | // - Advanced SIMD ST1 store instruction | ||
| 15 | // Must not write Rn | ||
| 16 | // 3.) optional instruction, can't be a branch, must not write Rn, may read Rn | ||
| 17 | // 4.) A load or store instruction from the Load/Store register unsigned | ||
| 18 | // immediate class using Rn as the base register | ||
| 19 | |||
| 20 | // Expect no patches detected. | ||
| 21 | // CHECK-NOT: detected cortex-a53-843419 erratum sequence | ||
| 22 | |||
| 23 | // erratum sequence but adrp (address & 0xfff) is not 0xff8 or 0xffc | ||
| 24 | .section .text.01, "ax", %progbits | ||
| 25 | .balign 4096 | ||
| 26 | .globl t3_0_ldr | ||
| 27 | .type t3_ff8_ldr, %function | ||
| 28 | t3_0_ldr: | ||
| 29 | adrp x0, dat | ||
| 30 | ldr x1, [x1, #0] | ||
| 31 | ldr x0, [x0, :got_lo12:dat] | ||
| 32 | ret | ||
| 33 | |||
| 34 | .section .text.02, "ax", %progbits | ||
| 35 | .balign 4096 | ||
| 36 | .globl t3_ff4_ldr | ||
| 37 | .space 4096 - 12 | ||
| 38 | .type t3_ff4_ldr, %function | ||
| 39 | t3_ff4_ldr: | ||
| 40 | adrp x0, dat | ||
| 41 | ldr x1, [x1, #0] | ||
| 42 | ldr x0, [x0, :got_lo12:dat] | ||
| 43 | ret | ||
| 44 | |||
| 45 | // Close matches for erratum sequence, with adrp at correct address but | ||
| 46 | // instruction 2 is a load or store but not one that matches the erratum | ||
| 47 | // conditions, but with a similar encoding to an instruction that does. | ||
| 48 | |||
| 49 | // ldp is not part of sequence, although stp is. | ||
| 50 | .section .text.03, "ax", %progbits | ||
| 51 | .balign 4096 | ||
| 52 | .globl t3_ff8_ldp | ||
| 53 | .type t3_ff8_ldp, %function | ||
| 54 | .space 4096 - 8 | ||
| 55 | t3_ff8_ldp: | ||
| 56 | adrp x16, dat | ||
| 57 | ldp x1,x2, [x3, #0] | ||
| 58 | ldr x13, [x16, :got_lo12:dat] | ||
| 59 | ret | ||
| 60 | |||
| 61 | // st2 is not part of sequence although st1 is. | ||
| 62 | .section .text.04, "ax", %progbits | ||
| 63 | .balign 4096 | ||
| 64 | .globl t3_ffc_st2 | ||
| 65 | .type t3_ffc_st2, %function | ||
| 66 | .space 4096 - 4 | ||
| 67 | t3_ffc_st2: | ||
| 68 | adrp x16, dat | ||
| 69 | st2 { v0.16b, v1.16b }, [x1] | ||
| 70 | ldr x13, [x16, :got_lo12:dat] | ||
| 71 | ret | ||
| 72 | |||
| 73 | // st3 is not part of sequence although st1 is. | ||
| 74 | .section .text.05, "ax", %progbits | ||
| 75 | .balign 4096 | ||
| 76 | .globl t3_ffc_st3 | ||
| 77 | .type t3_ffc_st3, %function | ||
| 78 | .space 4096 - 4 | ||
| 79 | t3_ffc_st3: | ||
| 80 | adrp x16, dat | ||
| 81 | st3 { v0.16b, v1.16b, v2.16b }, [x1], x2 | ||
| 82 | ldr x13, [x16, :got_lo12:dat] | ||
| 83 | ret | ||
| 84 | |||
| 85 | // ld1 is not part of sequence although st1 is. | ||
| 86 | .section .text.06, "ax", %progbits | ||
| 87 | .balign 4096 | ||
| 88 | .globl t3_ffc_ld2 | ||
| 89 | .type t3_ffc_st3, %function | ||
| 90 | .space 4096 - 4 | ||
| 91 | t3_ffc_ld1: | ||
| 92 | adrp x16, dat | ||
| 93 | ld1 { v0.16b }, [x2], x3 | ||
| 94 | ldr x13, [x16, :got_lo12:dat] | ||
| 95 | ret | ||
| 96 | |||
| 97 | // ldnp is not part of sequence although stnp is. | ||
| 98 | .section .text.07, "ax", %progbits | ||
| 99 | .balign 4096 | ||
| 100 | .globl t4_ff8_ldnp | ||
| 101 | .type t4_ff8_ldnp, %function | ||
| 102 | .space 4096 - 8 | ||
| 103 | t4_ff8_ldnp: | ||
| 104 | adrp x7, dat | ||
| 105 | ldnp x1,x2, [x3, #0] | ||
| 106 | nop | ||
| 107 | ldr x10, [x7, :got_lo12:dat] | ||
| 108 | ret | ||
| 109 | |||
| 110 | // Close match for erratum sequence, with adrp at correct address but | ||
| 111 | // instruction 2 writes to Rn, with Rn as either destination or as the | ||
| 112 | // transfer register but with writeback. | ||
| 113 | |||
| 114 | // ldr instruction writes to Rn | ||
| 115 | .section .text.08, "ax", %progbits | ||
| 116 | .balign 4096 | ||
| 117 | .globl t3_ff8_ldr | ||
| 118 | .type t3_ff8_ldr, %function | ||
| 119 | .space 4096 - 8 | ||
| 120 | t3_ff8_ldr: | ||
| 121 | adrp x0, dat | ||
| 122 | ldr x0, [x1, #0] | ||
| 123 | ldr x0, [x0, :got_lo12:dat] | ||
| 124 | ret | ||
| 125 | |||
| 126 | // str instruction writes to Rn via writeback (pre index) | ||
| 127 | .section .text.09, "ax", %progbits | ||
| 128 | .balign 4096 | ||
| 129 | .globl t3_ff8_str | ||
| 130 | .type t3_ff8_str, %function | ||
| 131 | .space 4096 - 8 | ||
| 132 | t3_ff8_str: | ||
| 133 | adrp x0, dat | ||
| 134 | str x1, [x0, #4]! | ||
| 135 | ldr x0, [x0, :got_lo12:dat] | ||
| 136 | ret | ||
| 137 | |||
| 138 | // ldr instruction writes to Rn via writeback (post index) | ||
| 139 | .section .text.09, "ax", %progbits | ||
| 140 | .balign 4096 | ||
| 141 | .globl t3_ffc_ldr | ||
| 142 | .type t3_ffc_ldr, %function | ||
| 143 | .space 4096 - 8 | ||
| 144 | t3_ffc_ldr: | ||
| 145 | adrp x0, dat | ||
| 146 | ldr x1, [x0], 0x8 | ||
| 147 | ldr x0, [x0, :got_lo12:dat] | ||
| 148 | ret | ||
| 149 | |||
| 150 | // stp writes to Rn via writeback (pre index) | ||
| 151 | .section .text.10, "ax", %progbits | ||
| 152 | .balign 4096 | ||
| 153 | .globl t4_ffc_stppre | ||
| 154 | .type t4_ffc_stppre, %function | ||
| 155 | .space 4096 - 4 | ||
| 156 | t4_ffc_stppre: | ||
| 157 | adrp x16, dat | ||
| 158 | stp x1,x2, [x16, #16]! | ||
| 159 | mul x3, x16, x16 | ||
| 160 | ldr x14, [x16, #8] | ||
| 161 | ret | ||
| 162 | |||
| 163 | // stp writes to Rn via writeback (post index) | ||
| 164 | .section .text.11, "ax", %progbits | ||
| 165 | .balign 4096 | ||
| 166 | .globl t4_ff8_stppost | ||
| 167 | .type t4_ff8_stppost, %function | ||
| 168 | .space 4096 - 8 | ||
| 169 | t4_ff8_stppost: | ||
| 170 | adrp x16, dat | ||
| 171 | stp x1,x2, [x16], #16 | ||
| 172 | mul x3, x16, x16 | ||
| 173 | ldr x14, [x16, #8] | ||
| 174 | ret | ||
| 175 | |||
| 176 | // st1 writes to Rn via writeback | ||
| 177 | .section .text.12, "ax", %progbits | ||
| 178 | .balign 4096 | ||
| 179 | .globl t3_ff8_st1 | ||
| 180 | .type t3_ff8_st1, %function | ||
| 181 | .space 4096 - 8 | ||
| 182 | t3_ff8_st1: | ||
| 183 | adrp x16, dat | ||
| 184 | st1 { v0.16b}, [x16], x2 | ||
| 185 | ldr x13, [x16, :got_lo12:dat] | ||
| 186 | ret | ||
| 187 | |||
| 188 | // Close match for erratum sequence, but with optional instruction 3 a branch | ||
| 189 | |||
| 190 | // function call via immediate | ||
| 191 | .section .text.13, "ax", %progbits | ||
| 192 | .balign 4096 | ||
| 193 | .globl t4_ffc_blimm | ||
| 194 | .type t4_ffc_blimm, %function | ||
| 195 | .space 4096 - 4 | ||
| 196 | t4_ffc_blimm: | ||
| 197 | adrp x7, dat | ||
| 198 | stnp x1,x2, [x3, #0] | ||
| 199 | bl t4_ffc_blimm | ||
| 200 | ldr x10, [x7, :got_lo12:dat] | ||
| 201 | ret | ||
| 202 | |||
| 203 | // function call via register | ||
| 204 | .section .text.14, "ax", %progbits | ||
| 205 | .balign 4096 | ||
| 206 | .globl t4_ffc_blreg | ||
| 207 | .type t4_ffc_blreg, %function | ||
| 208 | .space 4096 - 4 | ||
| 209 | t4_ffc_blreg: | ||
| 210 | adrp x7, dat | ||
| 211 | stnp x1,x2, [x3, #0] | ||
| 212 | blr x4 | ||
| 213 | ldr x10, [x7, :got_lo12:dat] | ||
| 214 | ret | ||
| 215 | |||
| 216 | // Unconditional branch immediate | ||
| 217 | .section .text.15, "ax", %progbits | ||
| 218 | .balign 4096 | ||
| 219 | .globl t4_ffc_branchimm | ||
| 220 | .type t4_ffc_branchimm, %function | ||
| 221 | .space 4096 - 4 | ||
| 222 | t4_ffc_branchimm: | ||
| 223 | adrp x7, dat | ||
| 224 | stnp x1,x2, [x3, #0] | ||
| 225 | b t4_ffc_branchimm | ||
| 226 | ldr x10, [x7, :got_lo12:dat] | ||
| 227 | ret | ||
| 228 | |||
| 229 | // Unconditional branch register | ||
| 230 | .section .text.16, "ax", %progbits | ||
| 231 | .balign 4096 | ||
| 232 | .globl t4_ffc_branchreg | ||
| 233 | .type t4_ffc_branchreg, %function | ||
| 234 | .space 4096 - 4 | ||
| 235 | t4_ffc_branchreg: | ||
| 236 | adrp x7, dat | ||
| 237 | stnp x1,x2, [x3, #0] | ||
| 238 | br x4 | ||
| 239 | ldr x10, [x7, :got_lo12:dat] | ||
| 240 | ret | ||
| 241 | |||
| 242 | // Conditional branch | ||
| 243 | .section .text.17, "ax", %progbits | ||
| 244 | .balign 4096 | ||
| 245 | .globl t4_ffc_branchcond | ||
| 246 | .type t4_ffc_branchcond, %function | ||
| 247 | .space 4096 - 4 | ||
| 248 | t4_ffc_branchcond: | ||
| 249 | adrp x7, dat | ||
| 250 | stnp x1,x2, [x3, #0] | ||
| 251 | cbz x5, t4_ffc_branchcond | ||
| 252 | ldr x10, [x7, :got_lo12:dat] | ||
| 253 | ret | ||
| 254 | |||
| 255 | // Conditional branch immediate | ||
| 256 | .section .text.18, "ax", %progbits | ||
| 257 | .balign 4096 | ||
| 258 | .globl t4_ffc_branchcondimm | ||
| 259 | .type t4_ffc_branchcondimm, %function | ||
| 260 | .space 4096 - 4 | ||
| 261 | t4_ffc_branchcondimm: | ||
| 262 | adrp x7, dat | ||
| 263 | stnp x1,x2, [x3, #0] | ||
| 264 | beq t4_ffc_branchcondimm | ||
| 265 | ldr x10, [x7, :got_lo12:dat] | ||
| 266 | ret | ||
| 267 | |||
| 268 | // Bitpattern matches erratum sequence but either all or part of the sequence | ||
| 269 | // is in inline literal data | ||
| 270 | .section .text.19, "ax", %progbits | ||
| 271 | .balign 4096 | ||
| 272 | .globl t3_ffc_ldrtraildata | ||
| 273 | .type t3_ff8_ldrtraildata, %function | ||
| 274 | .space 4096 - 8 | ||
| 275 | t3_ff8_ldrtraildata: | ||
| 276 | adrp x0, dat | ||
| 277 | ldr x1, [x1, #0] | ||
| 278 | // 0xf9400000 = ldr x0, [x0] | ||
| 279 | .byte 0x00 | ||
| 280 | .byte 0x00 | ||
| 281 | .byte 0x40 | ||
| 282 | .byte 0xf9 | ||
| 283 | ldr x0, [x0, :got_lo12:dat] | ||
| 284 | ret | ||
| 285 | |||
| 286 | .section .text.20, "ax", %progbits | ||
| 287 | .balign 4096 | ||
| 288 | .globl t3_ffc_ldrpredata | ||
| 289 | .type t3_ff8_ldrpredata, %function | ||
| 290 | .space 4096 - 8 | ||
| 291 | t3_ff8_ldrpredata: | ||
| 292 | // 0x90000000 = adrp x0, #0 | ||
| 293 | .byte 0x00 | ||
| 294 | .byte 0x00 | ||
| 295 | .byte 0x00 | ||
| 296 | .byte 0x90 | ||
| 297 | ldr x1, [x1, #0] | ||
| 298 | ldr x0, [x0, :got_lo12:dat] | ||
| 299 | ret | ||
| 300 | |||
| 301 | .section .text.21, "ax", %progbits | ||
| 302 | .balign 4096 | ||
| 303 | .globl t3_ffc_ldralldata | ||
| 304 | .type t3_ff8_ldralldata, %function | ||
| 305 | .space 4096 - 8 | ||
| 306 | t3_ff8_ldralldata: | ||
| 307 | // 0x90000000 = adrp x0, #0 | ||
| 308 | .byte 0x00 | ||
| 309 | .byte 0x00 | ||
| 310 | .byte 0x00 | ||
| 311 | .byte 0x90 | ||
| 312 | // 0xf9400021 = ldr x1, [x1] | ||
| 313 | .byte 0x21 | ||
| 314 | .byte 0x00 | ||
| 315 | .byte 0x40 | ||
| 316 | .byte 0xf9 | ||
| 317 | // 0xf9400000 = ldr x0, [x0] | ||
| 318 | .byte 0x00 | ||
| 319 | .byte 0x00 | ||
| 320 | .byte 0x40 | ||
| 321 | .byte 0xf9 | ||
| 322 | |||
| 323 | ret | ||
| 324 | |||
| 325 | .text | ||
| 326 | .globl _start | ||
| 327 | .type _start, %function | ||
| 328 | _start: | ||
| 329 | ret | ||
| 330 | |||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | |||
| 335 | // Bitpattern matches erratum sequence but section is not executable | ||
| 336 | .data | ||
| 337 | .globl dat | ||
| 338 | dat: .word 0 | ||
deps/lld/test/ELF/aarch64-cortex-a53-843419-recognize.s created+563| ... | @@ -0,0 +1,563 @@ | ||
| 1 | // REQUIRES: aarch64 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o | ||
| 3 | // RUN: ld.lld -fix-cortex-a53-843419 -verbose %t.o -o %t2 | FileCheck -check-prefix CHECK-PRINT %s | ||
| 4 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 | FileCheck %s -check-prefixes=CHECK,CHECK-FIX | ||
| 5 | // RUN: ld.lld -verbose %t.o -o %t3 | ||
| 6 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t3 | FileCheck %s -check-prefixes=CHECK,CHECK-NOFIX | ||
| 7 | // Test cases for Cortex-A53 Erratum 843419 | ||
| 8 | // See ARM-EPM-048406 Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf | ||
| 9 | // for full erratum details. | ||
| 10 | // In Summary | ||
| 11 | // 1.) | ||
| 12 | // ADRP (0xff8 or 0xffc). | ||
| 13 | // 2.) | ||
| 14 | // - load or store single register or either integer or vector registers. | ||
| 15 | // - STP or STNP of either vector or vector registers. | ||
| 16 | // - Advanced SIMD ST1 store instruction. | ||
| 17 | // - Must not write Rn. | ||
| 18 | // 3.) optional instruction, can't be a branch, must not write Rn, may read Rn. | ||
| 19 | // 4.) A load or store instruction from the Load/Store register unsigned | ||
| 20 | // immediate class using Rn as the base register. | ||
| 21 | |||
| 22 | // Each section contains a sequence of instructions that should be recognized | ||
| 23 | // as erratum 843419. The test cases cover the major variations such as: | ||
| 24 | // - adrp starts at 0xfff8 or 0xfffc. | ||
| 25 | // - Variations in instruction class for instruction 2. | ||
| 26 | // - Optional instruction 3 present or not. | ||
| 27 | // - Load or store for instruction 4. | ||
| 28 | |||
| 29 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21FF8 in unpatched output. | ||
| 30 | // CHECK: t3_ff8_ldr: | ||
| 31 | // CHECK-NEXT: 21ff8: e0 01 00 f0 adrp x0, #258048 | ||
| 32 | // CHECK-NEXT: 21ffc: 21 00 40 f9 ldr x1, [x1] | ||
| 33 | // CHECK-FIX: 22000: 03 b8 00 14 b #188428 | ||
| 34 | // CHECK-NOFIX: 22000: 00 00 40 f9 ldr x0, [x0] | ||
| 35 | // CHECK-NEXT: 22004: c0 03 5f d6 ret | ||
| 36 | .section .text.01, "ax", %progbits | ||
| 37 | .balign 4096 | ||
| 38 | .globl t3_ff8_ldr | ||
| 39 | .type t3_ff8_ldr, %function | ||
| 40 | .space 4096 - 8 | ||
| 41 | t3_ff8_ldr: | ||
| 42 | adrp x0, dat1 | ||
| 43 | ldr x1, [x1, #0] | ||
| 44 | ldr x0, [x0, :got_lo12:dat1] | ||
| 45 | ret | ||
| 46 | |||
| 47 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23FF8 in unpatched output. | ||
| 48 | // CHECK: t3_ff8_ldrsimd: | ||
| 49 | // CHECK-NEXT: 23ff8: e0 01 00 b0 adrp x0, #249856 | ||
| 50 | // CHECK-NEXT: 23ffc: 21 00 40 bd ldr s1, [x1] | ||
| 51 | // CHECK-FIX: 24000: 05 b0 00 14 b #180244 | ||
| 52 | // CHECK-NOFIX: 24000: 02 04 40 f9 ldr x2, [x0, #8] | ||
| 53 | // CHECK-NEXT: 24004: c0 03 5f d6 ret | ||
| 54 | .section .text.02, "ax", %progbits | ||
| 55 | .balign 4096 | ||
| 56 | .globl t3_ff8_ldrsimd | ||
| 57 | .type t3_ff8_ldrsimd, %function | ||
| 58 | .space 4096 - 8 | ||
| 59 | t3_ff8_ldrsimd: | ||
| 60 | adrp x0, dat2 | ||
| 61 | ldr s1, [x1, #0] | ||
| 62 | ldr x2, [x0, :got_lo12:dat2] | ||
| 63 | ret | ||
| 64 | |||
| 65 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 25FFC in unpatched output. | ||
| 66 | // CHECK: t3_ffc_ldrpost: | ||
| 67 | // CHECK-NEXT: 25ffc: c0 01 00 f0 adrp x0, #241664 | ||
| 68 | // CHECK-NEXT: 26000: 21 84 40 bc ldr s1, [x1], #8 | ||
| 69 | // CHECK-FIX: 26004: 06 a8 00 14 b #172056 | ||
| 70 | // CHECK-NOFIX: 26004: 03 08 40 f9 ldr x3, [x0, #16] | ||
| 71 | // CHECK-NEXT: 26008: c0 03 5f d6 ret | ||
| 72 | .section .text.03, "ax", %progbits | ||
| 73 | .balign 4096 | ||
| 74 | .globl t3_ffc_ldrpost | ||
| 75 | .type t3_ffc_ldrpost, %function | ||
| 76 | .space 4096 - 4 | ||
| 77 | t3_ffc_ldrpost: | ||
| 78 | adrp x0, dat3 | ||
| 79 | ldr s1, [x1], #8 | ||
| 80 | ldr x3, [x0, :got_lo12:dat3] | ||
| 81 | ret | ||
| 82 | |||
| 83 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 27FF8 in unpatched output. | ||
| 84 | // CHECK: t3_ff8_strpre: | ||
| 85 | // CHECK-NEXT: 27ff8: c0 01 00 b0 adrp x0, #233472 | ||
| 86 | // CHECK-NEXT: 27ffc: 21 8c 00 bc str s1, [x1, #8]! | ||
| 87 | // CHECK-FIX: 28000: 09 a0 00 14 b #163876 | ||
| 88 | // CHECK-NOFIX: 28000: 02 00 40 f9 ldr x2, [x0] | ||
| 89 | // CHECK-NEXT: 28004: c0 03 5f d6 ret | ||
| 90 | .section .text.04, "ax", %progbits | ||
| 91 | .balign 4096 | ||
| 92 | .globl t3_ff8_strpre | ||
| 93 | .type t3_ff8_strpre, %function | ||
| 94 | .space 4096 - 8 | ||
| 95 | t3_ff8_strpre: | ||
| 96 | adrp x0, dat1 | ||
| 97 | str s1, [x1, #8]! | ||
| 98 | ldr x2, [x0, :lo12:dat1] | ||
| 99 | ret | ||
| 100 | |||
| 101 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 29FFC in unpatched output. | ||
| 102 | // CHECK: t3_ffc_str: | ||
| 103 | // CHECK-NEXT: 29ffc: bc 01 00 f0 adrp x28, #225280 | ||
| 104 | // CHECK-NEXT: 2a000: 42 00 00 f9 str x2, [x2] | ||
| 105 | // CHECK-FIX: 2a004: 0a 98 00 14 b #155688 | ||
| 106 | // CHECK-NOFIX: 2a004: 9c 07 00 f9 str x28, [x28, #8] | ||
| 107 | // CHECK-NEXT: 2a008: c0 03 5f d6 ret | ||
| 108 | .section .text.05, "ax", %progbits | ||
| 109 | .balign 4096 | ||
| 110 | .globl t3_ffc_str | ||
| 111 | .type t3_ffc_str, %function | ||
| 112 | .space 4096 - 4 | ||
| 113 | t3_ffc_str: | ||
| 114 | adrp x28, dat2 | ||
| 115 | str x2, [x2, #0] | ||
| 116 | str x28, [x28, :lo12:dat2] | ||
| 117 | ret | ||
| 118 | |||
| 119 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 2BFFC in unpatched output. | ||
| 120 | // CHECK: t3_ffc_strsimd: | ||
| 121 | // CHECK-NEXT: 2bffc: bc 01 00 b0 adrp x28, #217088 | ||
| 122 | // CHECK-NEXT: 2c000: 44 00 00 b9 str w4, [x2] | ||
| 123 | // CHECK-FIX: 2c004: 0c 90 00 14 b #147504 | ||
| 124 | // CHECK-NOFIX: 2c004: 84 0b 00 f9 str x4, [x28, #16] | ||
| 125 | // CHECK-NEXT: 2c008: c0 03 5f d6 ret | ||
| 126 | .section .text.06, "ax", %progbits | ||
| 127 | .balign 4096 | ||
| 128 | .globl t3_ffc_strsimd | ||
| 129 | .type t3_ffc_strsimd, %function | ||
| 130 | .space 4096 - 4 | ||
| 131 | t3_ffc_strsimd: | ||
| 132 | adrp x28, dat3 | ||
| 133 | str w4, [x2, #0] | ||
| 134 | str x4, [x28, :lo12:dat3] | ||
| 135 | ret | ||
| 136 | |||
| 137 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 2DFF8 in unpatched output. | ||
| 138 | // CHECK: t3_ff8_ldrunpriv: | ||
| 139 | // CHECK-NEXT: 2dff8: 9d 01 00 f0 adrp x29, #208896 | ||
| 140 | // CHECK-NEXT: 2dffc: 41 08 40 38 ldtrb w1, [x2] | ||
| 141 | // CHECK-FIX: 2e000: 0f 88 00 14 b #139324 | ||
| 142 | // CHECK-NOFIX: 2e000: bd 03 40 f9 ldr x29, [x29] | ||
| 143 | // CHECK-NEXT: 2e004: c0 03 5f d6 ret | ||
| 144 | .section .text.07, "ax", %progbits | ||
| 145 | .balign 4096 | ||
| 146 | .globl t3_ff8_ldrunpriv | ||
| 147 | .type t3_ff8_ldrunpriv, %function | ||
| 148 | .space 4096 - 8 | ||
| 149 | t3_ff8_ldrunpriv: | ||
| 150 | adrp x29, dat1 | ||
| 151 | ldtrb w1, [x2, #0] | ||
| 152 | ldr x29, [x29, :got_lo12:dat1] | ||
| 153 | ret | ||
| 154 | |||
| 155 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 2FFFC in unpatched output. | ||
| 156 | // CHECK: t3_ffc_ldur: | ||
| 157 | // CHECK-NEXT: 2fffc: 9d 01 00 b0 adrp x29, #200704 | ||
| 158 | // CHECK-NEXT: 30000: 42 40 40 b8 ldur w2, [x2, #4] | ||
| 159 | // CHECK-FIX: 30004: 10 80 00 14 b #131136 | ||
| 160 | // CHECK-NOFIX: 30004: bd 07 40 f9 ldr x29, [x29, #8] | ||
| 161 | // CHECK-NEXT: 30008: c0 03 5f d6 ret | ||
| 162 | .balign 4096 | ||
| 163 | .globl t3_ffc_ldur | ||
| 164 | .type t3_ffc_ldur, %function | ||
| 165 | .space 4096 - 4 | ||
| 166 | t3_ffc_ldur: | ||
| 167 | adrp x29, dat2 | ||
| 168 | ldur w2, [x2, #4] | ||
| 169 | ldr x29, [x29, :got_lo12:dat2] | ||
| 170 | ret | ||
| 171 | |||
| 172 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 31FFC in unpatched output. | ||
| 173 | // CHECK: t3_ffc_sturh: | ||
| 174 | // CHECK-NEXT: 31ffc: 72 01 00 f0 adrp x18, #192512 | ||
| 175 | // CHECK-NEXT: 32000: 43 40 00 78 sturh w3, [x2, #4] | ||
| 176 | // CHECK-FIX: 32004: 12 78 00 14 b #122952 | ||
| 177 | // CHECK-NOFIX: 32004: 41 0a 40 f9 ldr x1, [x18, #16] | ||
| 178 | // CHECK-NEXT: 32008: c0 03 5f d6 ret | ||
| 179 | .section .text.09, "ax", %progbits | ||
| 180 | .balign 4096 | ||
| 181 | .globl t3_ffc_sturh | ||
| 182 | .type t3_ffc_sturh, %function | ||
| 183 | .space 4096 - 4 | ||
| 184 | t3_ffc_sturh: | ||
| 185 | adrp x18, dat3 | ||
| 186 | sturh w3, [x2, #4] | ||
| 187 | ldr x1, [x18, :got_lo12:dat3] | ||
| 188 | ret | ||
| 189 | |||
| 190 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 33FF8 in unpatched output. | ||
| 191 | // CHECK: t3_ff8_literal: | ||
| 192 | // CHECK-NEXT: 33ff8: 72 01 00 b0 adrp x18, #184320 | ||
| 193 | // CHECK-NEXT: 33ffc: e3 ff ff 58 ldr x3, #-4 | ||
| 194 | // CHECK-FIX: 34000: 15 70 00 14 b #114772 | ||
| 195 | // CHECK-NOFIX: 34000: 52 02 40 f9 ldr x18, [x18] | ||
| 196 | // CHECK-NEXT: 34004: c0 03 5f d6 ret | ||
| 197 | .section .text.10, "ax", %progbits | ||
| 198 | .balign 4096 | ||
| 199 | .globl t3_ff8_literal | ||
| 200 | .type t3_ff8_literal, %function | ||
| 201 | .space 4096 - 8 | ||
| 202 | t3_ff8_literal: | ||
| 203 | adrp x18, dat1 | ||
| 204 | ldr x3, t3_ff8_literal | ||
| 205 | ldr x18, [x18, :lo12:dat1] | ||
| 206 | ret | ||
| 207 | |||
| 208 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 35FFC in unpatched output. | ||
| 209 | // CHECK: t3_ffc_register: | ||
| 210 | // CHECK-NEXT: 35ffc: 4f 01 00 f0 adrp x15, #176128 | ||
| 211 | // CHECK-NEXT: 36000: 43 68 61 f8 ldr x3, [x2, x1] | ||
| 212 | // CHECK-FIX: 36004: 16 68 00 14 b #106584 | ||
| 213 | // CHECK-NOFIX: 36004: ea 05 40 f9 ldr x10, [x15, #8] | ||
| 214 | // CHECK-NEXT: 36008: c0 03 5f d6 ret | ||
| 215 | .section .text.11, "ax", %progbits | ||
| 216 | .balign 4096 | ||
| 217 | .globl t3_ffc_register | ||
| 218 | .type t3_ffc_register, %function | ||
| 219 | .space 4096 - 4 | ||
| 220 | t3_ffc_register: | ||
| 221 | adrp x15, dat2 | ||
| 222 | ldr x3, [x2, x1] | ||
| 223 | ldr x10, [x15, :lo12:dat2] | ||
| 224 | ret | ||
| 225 | |||
| 226 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 37FF8 in unpatched output. | ||
| 227 | // CHECK: t3_ff8_stp: | ||
| 228 | // CHECK-NEXT: 37ff8: 50 01 00 b0 adrp x16, #167936 | ||
| 229 | // CHECK-NEXT: 37ffc: 61 08 00 a9 stp x1, x2, [x3] | ||
| 230 | // CHECK-FIX: 38000: 19 60 00 14 b #98404 | ||
| 231 | // CHECK-NOFIX: 38000: 0d 0a 40 f9 ldr x13, [x16, #16] | ||
| 232 | // CHECK-NEXT: 38004: c0 03 5f d6 ret | ||
| 233 | .section .text.12, "ax", %progbits | ||
| 234 | .balign 4096 | ||
| 235 | .globl t3_ff8_stp | ||
| 236 | .type t3_ff8_stp, %function | ||
| 237 | .space 4096 - 8 | ||
| 238 | t3_ff8_stp: | ||
| 239 | adrp x16, dat3 | ||
| 240 | stp x1,x2, [x3, #0] | ||
| 241 | ldr x13, [x16, :lo12:dat3] | ||
| 242 | ret | ||
| 243 | |||
| 244 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 39FFC in unpatched output. | ||
| 245 | // CHECK: t3_ffc_stnp: | ||
| 246 | // CHECK-NEXT: 39ffc: 27 01 00 f0 adrp x7, #159744 | ||
| 247 | // CHECK-NEXT: 3a000: 61 08 00 a8 stnp x1, x2, [x3] | ||
| 248 | // CHECK-FIX: 3a004: 1a 58 00 14 b #90216 | ||
| 249 | // CHECK-NOFIX: 3a004: e9 00 40 f9 ldr x9, [x7] | ||
| 250 | // CHECK-NEXT: 3a008: c0 03 5f d6 ret | ||
| 251 | .section .text.13, "ax", %progbits | ||
| 252 | .balign 4096 | ||
| 253 | .globl t3_ffc_stnp | ||
| 254 | .type t3_ffc_stnp, %function | ||
| 255 | .space 4096 - 4 | ||
| 256 | t3_ffc_stnp: | ||
| 257 | adrp x7, dat1 | ||
| 258 | stnp x1,x2, [x3, #0] | ||
| 259 | ldr x9, [x7, :lo12:dat1] | ||
| 260 | ret | ||
| 261 | |||
| 262 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 3BFFC in unpatched output. | ||
| 263 | // CHECK: t3_ffc_st1singlepost: | ||
| 264 | // CHECK-NEXT: 3bffc: 37 01 00 b0 adrp x23, #151552 | ||
| 265 | // CHECK-NEXT: 3c000: 20 70 82 4c st1 { v0.16b }, [x1], x2 | ||
| 266 | // CHECK-FIX: 3c004: 1c 50 00 14 b #82032 | ||
| 267 | // CHECK-NOFIX: 3c004: f6 06 40 f9 ldr x22, [x23, #8] | ||
| 268 | // CHECK-NEXT: 3c008: c0 03 5f d6 ret | ||
| 269 | .section .text.14, "ax", %progbits | ||
| 270 | .balign 4096 | ||
| 271 | .globl t3_ffc_st1singlepost | ||
| 272 | .type t3_ffc_st1singlepost, %function | ||
| 273 | .space 4096 - 4 | ||
| 274 | t3_ffc_st1singlepost: | ||
| 275 | adrp x23, dat2 | ||
| 276 | st1 { v0.16b }, [x1], x2 | ||
| 277 | ldr x22, [x23, :lo12:dat2] | ||
| 278 | ret | ||
| 279 | |||
| 280 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 3DFF8 in unpatched output. | ||
| 281 | // CHECK: t3_ff8_st1multiple: | ||
| 282 | // CHECK-NEXT: 3dff8: 17 01 00 f0 adrp x23, #143360 | ||
| 283 | // CHECK-NEXT: 3dffc: 20 a0 00 4c st1 { v0.16b, v1.16b }, [x1] | ||
| 284 | // CHECK-FIX: 3e000: 1f 48 00 14 b #73852 | ||
| 285 | // CHECK-NOFIX: 3e000: f8 0a 40 f9 ldr x24, [x23, #16] | ||
| 286 | // CHECK-NEXT: 3e004: c0 03 5f d6 ret | ||
| 287 | .section .text.15, "ax", %progbits | ||
| 288 | .balign 4096 | ||
| 289 | .globl t3_ff8_st1multiple | ||
| 290 | .type t3_ff8_st1muliple, %function | ||
| 291 | .space 4096 - 8 | ||
| 292 | t3_ff8_st1multiple: | ||
| 293 | adrp x23, dat3 | ||
| 294 | st1 { v0.16b, v1.16b }, [x1] | ||
| 295 | ldr x24, [x23, :lo12:dat3] | ||
| 296 | ret | ||
| 297 | |||
| 298 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 3FFF8 in unpatched output. | ||
| 299 | // CHECK: t4_ff8_ldr: | ||
| 300 | // CHECK-NEXT: 3fff8: 00 01 00 b0 adrp x0, #135168 | ||
| 301 | // CHECK-NEXT: 3fffc: 21 00 40 f9 ldr x1, [x1] | ||
| 302 | // CHECK-NEXT: 40000: 42 00 00 8b add x2, x2, x0 | ||
| 303 | // CHECK-FIX: 40004: 20 40 00 14 b #65664 | ||
| 304 | // CHECK-NOFIX: 40004: 02 00 40 f9 ldr x2, [x0] | ||
| 305 | // CHECK-NEXT: 40008: c0 03 5f d6 ret | ||
| 306 | .section .text.16, "ax", %progbits | ||
| 307 | .balign 4096 | ||
| 308 | .globl t4_ff8_ldr | ||
| 309 | .type t4_ff8_ldr, %function | ||
| 310 | .space 4096 - 8 | ||
| 311 | t4_ff8_ldr: | ||
| 312 | adrp x0, dat1 | ||
| 313 | ldr x1, [x1, #0] | ||
| 314 | add x2, x2, x0 | ||
| 315 | ldr x2, [x0, :got_lo12:dat1] | ||
| 316 | ret | ||
| 317 | |||
| 318 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 41FFC in unpatched output. | ||
| 319 | // CHECK: t4_ffc_str: | ||
| 320 | // CHECK-NEXT: 41ffc: fc 00 00 f0 adrp x28, #126976 | ||
| 321 | // CHECK-NEXT: 42000: 42 00 00 f9 str x2, [x2] | ||
| 322 | // CHECK-NEXT: 42004: 20 00 02 cb sub x0, x1, x2 | ||
| 323 | // CHECK-FIX: 42008: 21 38 00 14 b #57476 | ||
| 324 | // CHECK-NOFIX: 42008: 9b 07 00 f9 str x27, [x28, #8] | ||
| 325 | // CHECK-NEXT: 4200c: c0 03 5f d6 ret | ||
| 326 | .section .text.17, "ax", %progbits | ||
| 327 | .balign 4096 | ||
| 328 | .globl t4_ffc_str | ||
| 329 | .type t4_ffc_str, %function | ||
| 330 | .space 4096 - 4 | ||
| 331 | t4_ffc_str: | ||
| 332 | adrp x28, dat2 | ||
| 333 | str x2, [x2, #0] | ||
| 334 | sub x0, x1, x2 | ||
| 335 | str x27, [x28, :got_lo12:dat2] | ||
| 336 | ret | ||
| 337 | |||
| 338 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 43FF8 in unpatched output. | ||
| 339 | // CHECK: t4_ff8_stp: | ||
| 340 | // CHECK-NEXT: 43ff8: f0 00 00 b0 adrp x16, #118784 | ||
| 341 | // CHECK-NEXT: 43ffc: 61 08 00 a9 stp x1, x2, [x3] | ||
| 342 | // CHECK-NEXT: 44000: 03 7e 10 9b mul x3, x16, x16 | ||
| 343 | // CHECK-FIX: 44004: 24 30 00 14 b #49296 | ||
| 344 | // CHECK-NOFIX: 44004: 0e 0a 40 f9 ldr x14, [x16, #16] | ||
| 345 | // CHECK-NEXT: 44008: c0 03 5f d6 ret | ||
| 346 | .section .text.18, "ax", %progbits | ||
| 347 | .balign 4096 | ||
| 348 | .globl t4_ff8_stp | ||
| 349 | .type t4_ff8_stp, %function | ||
| 350 | .space 4096 - 8 | ||
| 351 | t4_ff8_stp: | ||
| 352 | adrp x16, dat3 | ||
| 353 | stp x1,x2, [x3, #0] | ||
| 354 | mul x3, x16, x16 | ||
| 355 | ldr x14, [x16, :got_lo12:dat3] | ||
| 356 | ret | ||
| 357 | |||
| 358 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 45FF8 in unpatched output. | ||
| 359 | // CHECK: t4_ff8_stppre: | ||
| 360 | // CHECK-NEXT: 45ff8: d0 00 00 f0 adrp x16, #110592 | ||
| 361 | // CHECK-NEXT: 45ffc: 61 08 81 a9 stp x1, x2, [x3, #16]! | ||
| 362 | // CHECK-NEXT: 46000: 03 7e 10 9b mul x3, x16, x16 | ||
| 363 | // CHECK-FIX: 46004: 26 28 00 14 b #41112 | ||
| 364 | // CHECK-NOFIX: 46004: 0e 06 40 f9 ldr x14, [x16, #8] | ||
| 365 | // CHECK-NEXT: 46008: c0 03 5f d6 ret | ||
| 366 | .section .text.19, "ax", %progbits | ||
| 367 | .balign 4096 | ||
| 368 | .globl t4_ff8_stppre | ||
| 369 | .type t4_ff8_stppre, %function | ||
| 370 | .space 4096 - 8 | ||
| 371 | t4_ff8_stppre: | ||
| 372 | adrp x16, dat1 | ||
| 373 | stp x1,x2, [x3, #16]! | ||
| 374 | mul x3, x16, x16 | ||
| 375 | ldr x14, [x16, #8] | ||
| 376 | ret | ||
| 377 | |||
| 378 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 47FF8 in unpatched output. | ||
| 379 | // CHECK: t4_ff8_stppost: | ||
| 380 | // CHECK-NEXT: 47ff8: d0 00 00 b0 adrp x16, #102400 | ||
| 381 | // CHECK-NEXT: 47ffc: 61 08 81 a8 stp x1, x2, [x3], #16 | ||
| 382 | // CHECK-NEXT: 48000: 03 7e 10 9b mul x3, x16, x16 | ||
| 383 | // CHECK-FIX: 48004: 28 20 00 14 b #32928 | ||
| 384 | // CHECK-NOFIX: 48004: 0e 06 40 f9 ldr x14, [x16, #8] | ||
| 385 | // CHECK-NEXT: 48008: c0 03 5f d6 ret | ||
| 386 | .section .text.20, "ax", %progbits | ||
| 387 | .balign 4096 | ||
| 388 | .globl t4_ff8_stppost | ||
| 389 | .type t4_ff8_stppost, %function | ||
| 390 | .space 4096 - 8 | ||
| 391 | t4_ff8_stppost: | ||
| 392 | adrp x16, dat2 | ||
| 393 | stp x1,x2, [x3], #16 | ||
| 394 | mul x3, x16, x16 | ||
| 395 | ldr x14, [x16, #8] | ||
| 396 | ret | ||
| 397 | |||
| 398 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 49FFC in unpatched output. | ||
| 399 | // CHECK: t4_ffc_stpsimd: | ||
| 400 | // CHECK-NEXT: 49ffc: b0 00 00 f0 adrp x16, #94208 | ||
| 401 | // CHECK-NEXT: 4a000: 61 08 00 ad stp q1, q2, [x3] | ||
| 402 | // CHECK-NEXT: 4a004: 03 7e 10 9b mul x3, x16, x16 | ||
| 403 | // CHECK-FIX: 4a008: 29 18 00 14 b #24740 | ||
| 404 | // CHECK-NOFIX: 4a008: 0e 06 40 f9 ldr x14, [x16, #8] | ||
| 405 | // CHECK-NEXT: 4a00c: c0 03 5f d6 ret | ||
| 406 | .section .text.21, "ax", %progbits | ||
| 407 | .balign 4096 | ||
| 408 | .globl t4_ffc_stpsimd | ||
| 409 | .type t4_ffc_stpsimd, %function | ||
| 410 | .space 4096 - 4 | ||
| 411 | t4_ffc_stpsimd: | ||
| 412 | adrp x16, dat3 | ||
| 413 | stp q1,q2, [x3, #0] | ||
| 414 | mul x3, x16, x16 | ||
| 415 | ldr x14, [x16, #8] | ||
| 416 | ret | ||
| 417 | |||
| 418 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 4BFFC in unpatched output. | ||
| 419 | // CHECK: t4_ffc_stnp: | ||
| 420 | // CHECK-NEXT: 4bffc: a7 00 00 b0 adrp x7, #86016 | ||
| 421 | // CHECK-NEXT: 4c000: 61 08 00 a8 stnp x1, x2, [x3] | ||
| 422 | // CHECK-NEXT: 4c004: 1f 20 03 d5 nop | ||
| 423 | // CHECK-FIX: 4c008: 2b 10 00 14 b #16556 | ||
| 424 | // CHECK-NOFIX: 4c008: ea 00 40 f9 ldr x10, [x7] | ||
| 425 | // CHECK-NEXT: 4c00c: c0 03 5f d6 ret | ||
| 426 | .section .text.22, "ax", %progbits | ||
| 427 | .balign 4096 | ||
| 428 | .globl t4_ffc_stnp | ||
| 429 | .type t4_ffc_stnp, %function | ||
| 430 | .space 4096 - 4 | ||
| 431 | t4_ffc_stnp: | ||
| 432 | adrp x7, dat1 | ||
| 433 | stnp x1,x2, [x3, #0] | ||
| 434 | nop | ||
| 435 | ldr x10, [x7, :got_lo12:dat1] | ||
| 436 | ret | ||
| 437 | |||
| 438 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 4DFFC in unpatched output. | ||
| 439 | // CHECK: t4_ffc_st1: | ||
| 440 | // CHECK-NEXT: 4dffc: 98 00 00 f0 adrp x24, #77824 | ||
| 441 | // CHECK-NEXT: 4e000: 20 70 00 4c st1 { v0.16b }, [x1] | ||
| 442 | // CHECK-NEXT: 4e004: f6 06 40 f9 ldr x22, [x23, #8] | ||
| 443 | // CHECK-FIX: 4e008: 2d 08 00 14 b #8372 | ||
| 444 | // CHECK-NOFIX: 4e008: 18 ff 3f f9 str x24, [x24, #32760] | ||
| 445 | // CHECK-NEXT: 4e00c: c0 03 5f d6 ret | ||
| 446 | .section .text.23, "ax", %progbits | ||
| 447 | .balign 4096 | ||
| 448 | .globl t4_ffc_st1 | ||
| 449 | .type t4_ffc_st1, %function | ||
| 450 | .space 4096 - 4 | ||
| 451 | t4_ffc_st1: | ||
| 452 | adrp x24, dat2 | ||
| 453 | st1 { v0.16b }, [x1] | ||
| 454 | ldr x22, [x23, :got_lo12:dat2] | ||
| 455 | str x24, [x24, #32760] | ||
| 456 | ret | ||
| 457 | |||
| 458 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 4FFF8 in unpatched output. | ||
| 459 | // CHECK: t3_ff8_ldr_once: | ||
| 460 | // CHECK-NEXT: 4fff8: 80 00 00 b0 adrp x0, #69632 | ||
| 461 | // CHECK-NEXT: 4fffc: 20 70 82 4c st1 { v0.16b }, [x1], x2 | ||
| 462 | // CHECK-FIX: 50000: 31 00 00 14 b #196 | ||
| 463 | // CHECK-NOFIX: 50000: 01 08 40 f9 ldr x1, [x0, #16] | ||
| 464 | // CHECK-NEXT: 50004: 02 08 40 f9 ldr x2, [x0, #16] | ||
| 465 | // CHECK-NEXT: 50008: c0 03 5f d6 ret | ||
| 466 | .section .text.24, "ax", %progbits | ||
| 467 | .balign 4096 | ||
| 468 | .globl t3_ff8_ldr_once | ||
| 469 | .type t3_ff8_ldr_once, %function | ||
| 470 | .space 4096 - 8 | ||
| 471 | t3_ff8_ldr_once: | ||
| 472 | adrp x0, dat3 | ||
| 473 | st1 { v0.16b }, [x1], x2 | ||
| 474 | ldr x1, [x0, #16] | ||
| 475 | ldr x2, [x0, #16] | ||
| 476 | ret | ||
| 477 | |||
| 478 | .text | ||
| 479 | .globl _start | ||
| 480 | .type _start, %function | ||
| 481 | _start: | ||
| 482 | ret | ||
| 483 | |||
| 484 | // CHECK-FIX: __CortexA53843419_22000: | ||
| 485 | // CHECK-FIX-NEXT: 5000c: 00 00 40 f9 ldr x0, [x0] | ||
| 486 | // CHECK-FIX-NEXT: 50010: fd 47 ff 17 b #-188428 | ||
| 487 | // CHECK-FIX: __CortexA53843419_24000: | ||
| 488 | // CHECK-FIX-NEXT: 50014: 02 04 40 f9 ldr x2, [x0, #8] | ||
| 489 | // CHECK-FIX-NEXT: 50018: fb 4f ff 17 b #-180244 | ||
| 490 | // CHECK-FIX: __CortexA53843419_26004: | ||
| 491 | // CHECK-FIX-NEXT: 5001c: 03 08 40 f9 ldr x3, [x0, #16] | ||
| 492 | // CHECK-FIX-NEXT: 50020: fa 57 ff 17 b #-172056 | ||
| 493 | // CHECK-FIX: __CortexA53843419_28000: | ||
| 494 | // CHECK-FIX-NEXT: 50024: 02 00 40 f9 ldr x2, [x0] | ||
| 495 | // CHECK-FIX-NEXT: 50028: f7 5f ff 17 b #-163876 | ||
| 496 | // CHECK-FIX: __CortexA53843419_2A004: | ||
| 497 | // CHECK-FIX-NEXT: 5002c: 9c 07 00 f9 str x28, [x28, #8] | ||
| 498 | // CHECK-FIX-NEXT: 50030: f6 67 ff 17 b #-155688 | ||
| 499 | // CHECK-FIX: __CortexA53843419_2C004: | ||
| 500 | // CHECK-FIX-NEXT: 50034: 84 0b 00 f9 str x4, [x28, #16] | ||
| 501 | // CHECK-FIX-NEXT: 50038: f4 6f ff 17 b #-147504 | ||
| 502 | // CHECK-FIX: __CortexA53843419_2E000: | ||
| 503 | // CHECK-FIX-NEXT: 5003c: bd 03 40 f9 ldr x29, [x29] | ||
| 504 | // CHECK-FIX-NEXT: 50040: f1 77 ff 17 b #-139324 | ||
| 505 | // CHECK-FIX: __CortexA53843419_30004: | ||
| 506 | // CHECK-FIX-NEXT: 50044: bd 07 40 f9 ldr x29, [x29, #8] | ||
| 507 | // CHECK-FIX-NEXT: 50048: f0 7f ff 17 b #-131136 | ||
| 508 | // CHECK-FIX: __CortexA53843419_32004: | ||
| 509 | // CHECK-FIX-NEXT: 5004c: 41 0a 40 f9 ldr x1, [x18, #16] | ||
| 510 | // CHECK-FIX-NEXT: 50050: ee 87 ff 17 b #-122952 | ||
| 511 | // CHECK-FIX: __CortexA53843419_34000: | ||
| 512 | // CHECK-FIX-NEXT: 50054: 52 02 40 f9 ldr x18, [x18] | ||
| 513 | // CHECK-FIX-NEXT: 50058: eb 8f ff 17 b #-114772 | ||
| 514 | // CHECK-FIX: __CortexA53843419_36004: | ||
| 515 | // CHECK-FIX-NEXT: 5005c: ea 05 40 f9 ldr x10, [x15, #8] | ||
| 516 | // CHECK-FIX-NEXT: 50060: ea 97 ff 17 b #-106584 | ||
| 517 | // CHECK-FIX: __CortexA53843419_38000: | ||
| 518 | // CHECK-FIX-NEXT: 50064: 0d 0a 40 f9 ldr x13, [x16, #16] | ||
| 519 | // CHECK-FIX-NEXT: 50068: e7 9f ff 17 b #-98404 | ||
| 520 | // CHECK-FIX: __CortexA53843419_3A004: | ||
| 521 | // CHECK-FIX-NEXT: 5006c: e9 00 40 f9 ldr x9, [x7] | ||
| 522 | // CHECK-FIX-NEXT: 50070: e6 a7 ff 17 b #-90216 | ||
| 523 | // CHECK-FIX: __CortexA53843419_3C004: | ||
| 524 | // CHECK-FIX-NEXT: 50074: f6 06 40 f9 ldr x22, [x23, #8] | ||
| 525 | // CHECK-FIX-NEXT: 50078: e4 af ff 17 b #-82032 | ||
| 526 | // CHECK-FIX: __CortexA53843419_3E000: | ||
| 527 | // CHECK-FIX-NEXT: 5007c: f8 0a 40 f9 ldr x24, [x23, #16] | ||
| 528 | // CHECK-FIX-NEXT: 50080: e1 b7 ff 17 b #-73852 | ||
| 529 | // CHECK-FIX: __CortexA53843419_40004: | ||
| 530 | // CHECK-FIX-NEXT: 50084: 02 00 40 f9 ldr x2, [x0] | ||
| 531 | // CHECK-FIX-NEXT: 50088: e0 bf ff 17 b #-65664 | ||
| 532 | // CHECK-FIX: __CortexA53843419_42008: | ||
| 533 | // CHECK-FIX-NEXT: 5008c: 9b 07 00 f9 str x27, [x28, #8] | ||
| 534 | // CHECK-FIX-NEXT: 50090: df c7 ff 17 b #-57476 | ||
| 535 | // CHECK-FIX: __CortexA53843419_44004: | ||
| 536 | // CHECK-FIX-NEXT: 50094: 0e 0a 40 f9 ldr x14, [x16, #16] | ||
| 537 | // CHECK-FIX-NEXT: 50098: dc cf ff 17 b #-49296 | ||
| 538 | // CHECK-FIX: __CortexA53843419_46004: | ||
| 539 | // CHECK-FIX-NEXT: 5009c: 0e 06 40 f9 ldr x14, [x16, #8] | ||
| 540 | // CHECK-FIX-NEXT: 500a0: da d7 ff 17 b #-41112 | ||
| 541 | // CHECK-FIX: __CortexA53843419_48004: | ||
| 542 | // CHECK-FIX-NEXT: 500a4: 0e 06 40 f9 ldr x14, [x16, #8] | ||
| 543 | // CHECK-FIX-NEXT: 500a8: d8 df ff 17 b #-32928 | ||
| 544 | // CHECK-FIX: __CortexA53843419_4A008: | ||
| 545 | // CHECK-FIX-NEXT: 500ac: 0e 06 40 f9 ldr x14, [x16, #8] | ||
| 546 | // CHECK-FIX-NEXT: 500b0: d7 e7 ff 17 b #-24740 | ||
| 547 | // CHECK-FIX: __CortexA53843419_4C008: | ||
| 548 | // CHECK-FIX-NEXT: 500b4: ea 00 40 f9 ldr x10, [x7] | ||
| 549 | // CHECK-FIX-NEXT: 500b8: d5 ef ff 17 b #-16556 | ||
| 550 | // CHECK-FIX: __CortexA53843419_4E008: | ||
| 551 | // CHECK-FIX-NEXT: 500bc: 18 ff 3f f9 str x24, [x24, #32760] | ||
| 552 | // CHECK-FIX-NEXT: 500c0: d3 f7 ff 17 b #-8372 | ||
| 553 | // CHECK-FIX: __CortexA53843419_50000: | ||
| 554 | // CHECK-FIX-NEXT: 500c4: 01 08 40 f9 ldr x1, [x0, #16] | ||
| 555 | // CHECK-FIX-NEXT: 500c8: cf ff ff 17 b #-196 | ||
| 556 | |||
| 557 | .data | ||
| 558 | .globl dat | ||
| 559 | .globl dat2 | ||
| 560 | .globl dat3 | ||
| 561 | dat1: .quad 1 | ||
| 562 | dat2: .quad 2 | ||
| 563 | dat3: .quad 3 | ||
deps/lld/test/ELF/aarch64-cortex-a53-843419-thunk.s created+57| ... | @@ -0,0 +1,57 @@ | ||
| 1 | // REQUIRES: aarch64 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o | ||
| 3 | // RUN: echo "SECTIONS { \ | ||
| 4 | // RUN: .text1 0x10000 : { *(.text.01) *(.text.02) *(.text.03) } \ | ||
| 5 | // RUN: .text2 0x8010000 : { *(.text.04) } } " > %t.script | ||
| 6 | // RUN: ld.lld --script %t.script -fix-cortex-a53-843419 -verbose %t.o -o %t2 | FileCheck -check-prefix=CHECK-PRINT %s | ||
| 7 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 | FileCheck %s | ||
| 8 | |||
| 9 | // %t2 is 128 Megabytes, so delete it early. | ||
| 10 | // RUN: rm %t2 | ||
| 11 | |||
| 12 | // Test cases for Cortex-A53 Erratum 843419 that involve interactions with | ||
| 13 | // range extension thunks. Both erratum fixes and range extension thunks need | ||
| 14 | // precise address information and after creation alter address information. | ||
| 15 | |||
| 16 | |||
| 17 | .section .text.01, "ax", %progbits | ||
| 18 | .balign 4096 | ||
| 19 | .globl _start | ||
| 20 | .type _start, %function | ||
| 21 | _start: | ||
| 22 | bl far_away | ||
| 23 | // Thunk to far_away, size 16-bytes goes here. | ||
| 24 | |||
| 25 | .section .text.02, "ax", %progbits | ||
| 26 | .space 4096 - 28 | ||
| 27 | |||
| 28 | // Erratum sequence will only line up at address 0 modulo 0xffc when | ||
| 29 | // Thunk is inserted. | ||
| 30 | .section .text.03, "ax", %progbits | ||
| 31 | .globl t3_ff8_ldr | ||
| 32 | .type t3_ff8_ldr, %function | ||
| 33 | t3_ff8_ldr: | ||
| 34 | adrp x0, dat | ||
| 35 | ldr x1, [x1, #0] | ||
| 36 | ldr x0, [x0, :got_lo12:dat] | ||
| 37 | ret | ||
| 38 | |||
| 39 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 10FFC in unpatched output. | ||
| 40 | // CHECK: t3_ff8_ldr: | ||
| 41 | // CHECK-NEXT: 10ffc: 00 00 04 90 adrp x0, #134217728 | ||
| 42 | // CHECK-NEXT: 11000: 21 00 40 f9 ldr x1, [x1] | ||
| 43 | // CHECK-NEXT: 11004: 02 00 00 14 b #8 | ||
| 44 | // CHECK-NEXT: 11008: c0 03 5f d6 ret | ||
| 45 | // CHECK: __CortexA53843419_11004: | ||
| 46 | // CHECK-NEXT: 1100c: 00 08 40 f9 ldr x0, [x0, #16] | ||
| 47 | // CHECK-NEXT: 11010: fe ff ff 17 b #-8 | ||
| 48 | |||
| 49 | .section .text.04, "ax", %progbits | ||
| 50 | .globl far_away | ||
| 51 | .type far_away, function | ||
| 52 | far_away: | ||
| 53 | ret | ||
| 54 | |||
| 55 | .section .data | ||
| 56 | .globl dat | ||
| 57 | dat: .quad 0 | ||
deps/lld/test/ELF/aarch64-gnu-ifunc-plt.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %S/Inputs/shared2.s -o %t1.o | 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %S/Inputs/shared2.s -o %t1.o |
| 2 | // RUN: ld.lld %t1.o --shared -o %t.so | 2 | // RUN: ld.lld %t1.o --shared -o %t.so |
| 3 | // 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 %s -o %t.o |
| 4 | // RUN: ld.lld %t.so %t.o -o %tout | 4 | // RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout |
| 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM | 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM |
| 6 | // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT | 6 | // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT |
| 7 | // RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s | 7 | // RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s |
deps/lld/test/ELF/aarch64-gnu-ifunc.s+1-1| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | // CHECK-NEXT: Address: [[RELA:.*]] | 15 | // CHECK-NEXT: Address: [[RELA:.*]] |
| 16 | // CHECK-NEXT: Offset: 0x158 | 16 | // CHECK-NEXT: Offset: 0x158 |
| 17 | // CHECK-NEXT: Size: 48 | 17 | // CHECK-NEXT: Size: 48 |
| 18 | // CHECK-NEXT: Link: 6 | 18 | // CHECK-NEXT: Link: 0 |
| 19 | // CHECK-NEXT: Info: 0 | 19 | // CHECK-NEXT: Info: 0 |
| 20 | // CHECK-NEXT: AddressAlignment: 8 | 20 | // CHECK-NEXT: AddressAlignment: 8 |
| 21 | // CHECK-NEXT: EntrySize: 24 | 21 | // CHECK-NEXT: EntrySize: 24 |
deps/lld/test/ELF/aarch64-got-reloc.s+2-2| ... | @@ -9,8 +9,8 @@ | ... | @@ -9,8 +9,8 @@ |
| 9 | // CHECK-NEXT: SHF_ALLOC | 9 | // CHECK-NEXT: SHF_ALLOC |
| 10 | // CHECK-NEXT: SHF_WRITE | 10 | // CHECK-NEXT: SHF_WRITE |
| 11 | // CHECK-NEXT: ] | 11 | // CHECK-NEXT: ] |
| 12 | // CHECK-NEXT: Address: 0x30000 | 12 | // CHECK-NEXT: Address: |
| 13 | // CHECK-NEXT: Offset: 0x20000 | 13 | // CHECK-NEXT: Offset: |
| 14 | // CHECK-NEXT: Size: 8 | 14 | // CHECK-NEXT: Size: 8 |
| 15 | // CHECK-NEXT: Link: 0 | 15 | // CHECK-NEXT: Link: 0 |
| 16 | // CHECK-NEXT: Info: 0 | 16 | // CHECK-NEXT: Info: 0 |
deps/lld/test/ELF/aarch64-got-relocations.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | # REQUIRES: aarch64 | 1 | # REQUIRES: aarch64 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-cloudabi %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-cloudabi %s -o %t.o |
| 3 | # RUN: ld.lld -pie %t.o -o %t | 3 | # RUN: ld.lld --hash-style=sysv -pie %t.o -o %t |
| 4 | # RUN: llvm-readobj -r %t | FileCheck %s | 4 | # RUN: llvm-readobj -r %t | FileCheck %s |
| 5 | 5 | ||
| 6 | # If we're addressing a global relatively through the GOT, we still need to | 6 | # If we're addressing a global relatively through the GOT, we still need to |
deps/lld/test/ELF/aarch64-jump26-error.s deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %S/Inputs/abs.s -o %tabs | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t | ||
| 3 | // RUN: not ld.lld %t %tabs -o %t2 2>&1 | FileCheck %s | ||
| 4 | // REQUIRES: aarch64 | ||
| 5 | |||
| 6 | .text | ||
| 7 | .globl _start | ||
| 8 | _start: | ||
| 9 | b big | ||
| 10 | |||
| 11 | // CHECK: R_AARCH64_JUMP26 out of range | ||
deps/lld/test/ELF/aarch64-jump26-thunk.s created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %S/Inputs/abs.s -o %tabs | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t | ||
| 3 | // RUN: ld.lld %t %tabs -o %t2 2>&1 | ||
| 4 | // RUN: llvm-objdump -d -triple=aarch64-pc-freebsd %t2 | FileCheck %s | ||
| 5 | // REQUIRES: aarch64 | ||
| 6 | |||
| 7 | .text | ||
| 8 | .globl _start | ||
| 9 | _start: | ||
| 10 | b big | ||
| 11 | |||
| 12 | // CHECK: Disassembly of section .text: | ||
| 13 | // CHECK-NEXT: _start: | ||
| 14 | // CHECK-NEXT: 20000: 02 00 00 14 b #8 | ||
| 15 | // CHECK: __AArch64AbsLongThunk_big: | ||
| 16 | // CHECK-NEXT: 20008: 50 00 00 58 ldr x16, #8 | ||
| 17 | // CHECK-NEXT: 2000c: 00 02 1f d6 br x16 | ||
| 18 | // CHECK: $d: | ||
| 19 | // CHECK-NEXT: 20010: 00 00 00 00 .word 0x00000000 | ||
| 20 | // CHECK-NEXT: 20014: 10 00 00 00 .word 0x00000010 | ||
deps/lld/test/ELF/aarch64-ldprel-lo19-invalid.s created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | # REQUIRES: aarch64 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o | ||
| 4 | # RUN: not ld.lld -shared %t.o -o %t 2>&1 | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: relocation R_AARCH64_LD_PREL_LO19 out of range: 2065536 is not in [-1048576, 1048575] | ||
| 7 | |||
| 8 | ldr x8, patatino | ||
| 9 | .data | ||
| 10 | .zero 2000000 | ||
| 11 | patatino: | ||
deps/lld/test/ELF/aarch64-lo12-alignment.s created+45| ... | @@ -0,0 +1,45 @@ | ||
| 1 | // REQUIRES: aarch64 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t | ||
| 3 | // RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s | ||
| 4 | |||
| 5 | // Test derived from a typical ODR violation where a global is declared | ||
| 6 | // extern int but defined as a half or byte sized type. | ||
| 7 | .section .text | ||
| 8 | .globl _start | ||
| 9 | .type _start, %function | ||
| 10 | // Access foo2 as if it were an aligned 32-bit int, expect an error as | ||
| 11 | // foo is not aligned | ||
| 12 | |||
| 13 | _start: | ||
| 14 | ldrb w2, [x0, #:lo12:foo1] // Ok as no shift involved | ||
| 15 | ldrh w2, [x0, #:lo12:foo1] // Error foo1 is not 2-byte aligned | ||
| 16 | ldrh w2, [x0, #:lo12:foo2] // Ok as foo2 is 2-byte aligned | ||
| 17 | ldr w2, [x0, #:lo12:foo2] // Error foo2 is not 4-byte aligned | ||
| 18 | ldr w2, [x0, #:lo12:foo4] // Ok as foo4 is 4-byte aligned | ||
| 19 | ldr x3, [x0, #:lo12:foo4] // Error foo4 is not 8-byte aligned | ||
| 20 | ldr x3, [x0, #:lo12:foo8] // Ok as foo8 is 8-byte aligned | ||
| 21 | ldr q0, [x0, #:lo12:foo8] // Error foo8 is not 16-byte aligned | ||
| 22 | ldr q0, [x0, #:lo12:foo16] // Ok as foo16 is 16-byte aligned | ||
| 23 | |||
| 24 | .section .data.bool, "a", @nobits | ||
| 25 | .balign 16 | ||
| 26 | .globl foo16 | ||
| 27 | .globl foo1 | ||
| 28 | .globl foo2 | ||
| 29 | .globl foo4 | ||
| 30 | .globl foo8 | ||
| 31 | foo16: | ||
| 32 | .space 1 | ||
| 33 | foo1: | ||
| 34 | .space 1 | ||
| 35 | foo2: | ||
| 36 | .space 2 | ||
| 37 | foo4: | ||
| 38 | .space 4 | ||
| 39 | foo8: | ||
| 40 | .space 8 | ||
| 41 | |||
| 42 | // CHECK: improper alignment for relocation R_AARCH64_LDST16_ABS_LO12_NC: 0x30001 is not aligned to 2 bytes | ||
| 43 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST32_ABS_LO12_NC: 0x30002 is not aligned to 4 bytes | ||
| 44 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST64_ABS_LO12_NC: 0x30004 is not aligned to 8 bytes | ||
| 45 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST128_ABS_LO12_NC: 0x30008 is not aligned to 16 bytes | ||
deps/lld/test/ELF/aarch64-load-alignment.s created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | # REQUIRES: aarch64 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o | ||
| 4 | # RUN: not ld.lld -shared %t.o -o %t 2>&1 | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: improper alignment for relocation R_AARCH64_LD_PREL_LO19: 0x10005 is not aligned to 4 bytes | ||
| 7 | |||
| 8 | ldr x8, patatino | ||
| 9 | .data | ||
| 10 | .zero 5 | ||
| 11 | patatino: | ||
deps/lld/test/ELF/aarch64-prel16.s+1-1| ... | @@ -28,4 +28,4 @@ _start: | ... | @@ -28,4 +28,4 @@ _start: |
| 28 | // | FileCheck %s --check-prefix=OVERFLOW | 28 | // | FileCheck %s --check-prefix=OVERFLOW |
| 29 | // RUN: not ld.lld %t.o %t257.o -o %t2 | 29 | // RUN: not ld.lld %t.o %t257.o -o %t2 |
| 30 | // | FileCheck %s --check-prefix=OVERFLOW | 30 | // | FileCheck %s --check-prefix=OVERFLOW |
| 31 | // OVERFLOW: Relocation R_AARCH64_PREL16 out of range | 31 | // OVERFLOW: Relocation R_AARCH64_PREL16 out of range: -94209 is not in [-32768, 65535] |
deps/lld/test/ELF/aarch64-prel32.s+1-1| ... | @@ -28,4 +28,4 @@ _start: | ... | @@ -28,4 +28,4 @@ _start: |
| 28 | // | FileCheck %s --check-prefix=OVERFLOW | 28 | // | FileCheck %s --check-prefix=OVERFLOW |
| 29 | // RUN: not ld.lld %t.o %t257.o -o %t2 | 29 | // RUN: not ld.lld %t.o %t257.o -o %t2 |
| 30 | // | FileCheck %s --check-prefix=OVERFLOW | 30 | // | FileCheck %s --check-prefix=OVERFLOW |
| 31 | // OVERFLOW: Relocation R_AARCH64_PREL32 out of range | 31 | // OVERFLOW: Relocation R_AARCH64_PREL32 out of range: 18446744071562006527 is not in [-2147483648, 4294967295] |
deps/lld/test/ELF/aarch64-thunk-pi.s created+91| ... | @@ -0,0 +1,91 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t | ||
| 2 | // RUN: echo "SECTIONS { \ | ||
| 3 | // RUN: .text_low : { *(.text_low) } \ | ||
| 4 | // RUN: .text_high 0x10000000 : { *(.text_high) } \ | ||
| 5 | // RUN: } " > %t.script | ||
| 6 | // RUN: ld.lld --script %t.script --shared %t -o %t2 2>&1 | ||
| 7 | // RUN: llvm-objdump -d -triple=aarch64-linux-gnu %t2 | FileCheck %s | ||
| 8 | // REQUIRES: aarch64 | ||
| 9 | |||
| 10 | // Check that Position Independent thunks are generated for shared libraries. | ||
| 11 | .section .text_low, "ax", %progbits | ||
| 12 | .globl low_target | ||
| 13 | .type low_target, %function | ||
| 14 | low_target: | ||
| 15 | // Need thunk to high_target@plt | ||
| 16 | bl high_target | ||
| 17 | ret | ||
| 18 | // CHECK: low_target: | ||
| 19 | // CHECK-NEXT: 0: 04 00 00 94 bl #16 | ||
| 20 | // CHECK-NEXT: 4: c0 03 5f d6 ret | ||
| 21 | |||
| 22 | .hidden low_target2 | ||
| 23 | .globl low_target2 | ||
| 24 | .type low_target2, %function | ||
| 25 | low_target2: | ||
| 26 | // Need thunk to high_target | ||
| 27 | bl high_target2 | ||
| 28 | ret | ||
| 29 | // CHECK: low_target2: | ||
| 30 | // CHECK-NEXT: 8: 05 00 00 94 bl #20 | ||
| 31 | // CHECK-NEXT: c: c0 03 5f d6 ret | ||
| 32 | |||
| 33 | // Expect range extension thunks for .text_low | ||
| 34 | // adrp calculation is (PC + signed immediate) & (!0xfff) | ||
| 35 | // CHECK: __AArch64ADRPThunk_high_target: | ||
| 36 | // CHECK-NEXT: 10: 10 00 08 90 adrp x16, #268435456 | ||
| 37 | // CHECK-NEXT: 14: 10 82 04 91 add x16, x16, #288 | ||
| 38 | // CHECK-NEXT: 18: 00 02 1f d6 br x16 | ||
| 39 | // CHECK: __AArch64ADRPThunk_high_target2: | ||
| 40 | // CHECK-NEXT: 1c: 10 00 08 90 adrp x16, #268435456 | ||
| 41 | // CHECK-NEXT: 20: 10 22 00 91 add x16, x16, #8 | ||
| 42 | // CHECK-NEXT: 24: 00 02 1f d6 br x16 | ||
| 43 | |||
| 44 | |||
| 45 | .section .text_high, "ax", %progbits | ||
| 46 | .globl high_target | ||
| 47 | .type high_target, %function | ||
| 48 | high_target: | ||
| 49 | // No thunk needed as we can reach low_target@plt | ||
| 50 | bl low_target | ||
| 51 | ret | ||
| 52 | // CHECK: high_target: | ||
| 53 | // CHECK-NEXT: 10000000: 4c 00 00 94 bl #304 | ||
| 54 | // CHECK-NEXT: 10000004: c0 03 5f d6 ret | ||
| 55 | |||
| 56 | .hidden high_target2 | ||
| 57 | .globl high_target2 | ||
| 58 | .type high_target2, %function | ||
| 59 | high_target2: | ||
| 60 | // Need thunk to low_target | ||
| 61 | bl low_target2 | ||
| 62 | ret | ||
| 63 | // CHECK: high_target2: | ||
| 64 | // CHECK-NEXT: 10000008: 02 00 00 94 bl #8 | ||
| 65 | // CHECK-NEXT: 1000000c: c0 03 5f d6 ret | ||
| 66 | |||
| 67 | // Expect Thunk for .text.high | ||
| 68 | |||
| 69 | // CHECK: __AArch64ADRPThunk_low_target2: | ||
| 70 | // CHECK-NEXT: 10000010:	10 00 f8 90 	adrp	x16, #-268435456 | ||
| 71 | // CHECK-NEXT: 10000014:	10 22 00 91 	add	x16, x16, #8 | ||
| 72 | // CHECK-NEXT: 10000018:	00 02 1f d6 	br	x16 | ||
| 73 | |||
| 74 | // CHECK: Disassembly of section .plt: | ||
| 75 | // CHECK-NEXT: .plt: | ||
| 76 | // CHECK-NEXT: 10000100: f0 7b bf a9 stp x16, x30, [sp, #-16]! | ||
| 77 | // CHECK-NEXT: 10000104: 10 00 00 90 adrp x16, #0 | ||
| 78 | // CHECK-NEXT: 10000108: 11 aa 40 f9 ldr x17, [x16, #336] | ||
| 79 | // CHECK-NEXT: 1000010c: 10 42 05 91 add x16, x16, #336 | ||
| 80 | // CHECK-NEXT: 10000110: 20 02 1f d6 br x17 | ||
| 81 | // CHECK-NEXT: 10000114: 1f 20 03 d5 nop | ||
| 82 | // CHECK-NEXT: 10000118: 1f 20 03 d5 nop | ||
| 83 | // CHECK-NEXT: 1000011c: 1f 20 03 d5 nop | ||
| 84 | // CHECK-NEXT: 10000120: 10 00 00 90 adrp x16, #0 | ||
| 85 | // CHECK-NEXT: 10000124: 11 ae 40 f9 ldr x17, [x16, #344] | ||
| 86 | // CHECK-NEXT: 10000128: 10 62 05 91 add x16, x16, #344 | ||
| 87 | // CHECK-NEXT: 1000012c: 20 02 1f d6 br x17 | ||
| 88 | // CHECK-NEXT: 10000130: 10 00 00 90 adrp x16, #0 | ||
| 89 | // CHECK-NEXT: 10000134: 11 b2 40 f9 ldr x17, [x16, #352] | ||
| 90 | // CHECK-NEXT: 10000138: 10 82 05 91 add x16, x16, #352 | ||
| 91 | // CHECK-NEXT: 1000013c: 20 02 1f d6 br x17 | ||
deps/lld/test/ELF/aarch64-thunk-script.s created+41| ... | @@ -0,0 +1,41 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t | ||
| 2 | // RUN: echo "SECTIONS { \ | ||
| 3 | // RUN: .text_low 0x2000: { *(.text_low) } \ | ||
| 4 | // RUN: .text_high 0x8002000 : { *(.text_high) } \ | ||
| 5 | // RUN: } " > %t.script | ||
| 6 | // RUN: ld.lld --script %t.script %t -o %t2 2>&1 | ||
| 7 | // RUN: llvm-objdump -d -triple=aarch64-linux-gnu %t2 | FileCheck %s | ||
| 8 | // REQUIRES: aarch64 | ||
| 9 | |||
| 10 | // Check that we have the out of branch range calculation right. The immediate | ||
| 11 | // field is signed so we have a slightly higher negative displacement. | ||
| 12 | .section .text_low, "ax", %progbits | ||
| 13 | .globl _start | ||
| 14 | .type _start, %function | ||
| 15 | _start: | ||
| 16 | // Need thunk to high_target@plt | ||
| 17 | bl high_target | ||
| 18 | ret | ||
| 19 | |||
| 20 | .section .text_high, "ax", %progbits | ||
| 21 | .globl high_target | ||
| 22 | .type high_target, %function | ||
| 23 | high_target: | ||
| 24 | // No Thunk needed as we are within signed immediate range | ||
| 25 | bl _start | ||
| 26 | ret | ||
| 27 | |||
| 28 | // CHECK: Disassembly of section .text_low: | ||
| 29 | // CHECK-NEXT: _start: | ||
| 30 | // CHECK-NEXT: 2000: 02 00 00 94 bl #8 | ||
| 31 | // CHECK-NEXT: 2004: c0 03 5f d6 ret | ||
| 32 | // CHECK: __AArch64AbsLongThunk_high_target: | ||
| 33 | // CHECK-NEXT: 2008: 50 00 00 58 ldr x16, #8 | ||
| 34 | // CHECK-NEXT: 200c: 00 02 1f d6 br x16 | ||
| 35 | // CHECK: $d: | ||
| 36 | // CHECK-NEXT: 2010: 00 20 00 08 .word 0x08002000 | ||
| 37 | // CHECK-NEXT: 2014: 00 00 00 00 .word 0x00000000 | ||
| 38 | // CHECK: Disassembly of section .text_high: | ||
| 39 | // CHECK-NEXT: high_target: | ||
| 40 | // CHECK-NEXT: 8002000: 00 00 00 96 bl #-134217728 | ||
| 41 | // CHECK-NEXT: 8002004: c0 03 5f d6 ret | ||
deps/lld/test/ELF/aarch64-thunk-section-location.s created+41| ... | @@ -0,0 +1,41 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t | ||
| 2 | // RUN: ld.lld %t -o %t2 2>&1 | ||
| 3 | // RUN: llvm-objdump -d -start-address=134086664 -stop-address=134086676 -triple=aarch64-linux-gnu %t2 | FileCheck %s | ||
| 4 | // REQUIRES: aarch64 | ||
| 5 | // Check that the range extension thunks are dumped close to the aarch64 branch | ||
| 6 | // range of 128 MiB | ||
| 7 | .section .text.1, "ax", %progbits | ||
| 8 | .balign 0x1000 | ||
| 9 | .globl _start | ||
| 10 | _start: | ||
| 11 | bl high_target | ||
| 12 | ret | ||
| 13 | |||
| 14 | .section .text.2, "ax", %progbits | ||
| 15 | .space 0x2000000 | ||
| 16 | |||
| 17 | .section .text.2, "ax", %progbits | ||
| 18 | .space 0x2000000 | ||
| 19 | |||
| 20 | .section .text.3, "ax", %progbits | ||
| 21 | .space 0x2000000 | ||
| 22 | |||
| 23 | .section .text.4, "ax", %progbits | ||
| 24 | .space 0x2000000 - 0x40000 | ||
| 25 | |||
| 26 | .section .text.5, "ax", %progbits | ||
| 27 | .space 0x40000 | ||
| 28 | |||
| 29 | .section .text.6, "ax", %progbits | ||
| 30 | .balign 0x1000 | ||
| 31 | |||
| 32 | .globl high_target | ||
| 33 | .type high_target, %function | ||
| 34 | high_target: | ||
| 35 | ret | ||
| 36 | |||
| 37 | // CHECK: __AArch64AbsLongThunk_high_target: | ||
| 38 | // CHECK-NEXT: 7fe0008: 50 00 00 58 ldr x16, #8 | ||
| 39 | // CHECK-NEXT: 7fe000c: 00 02 1f d6 br x16 | ||
| 40 | // CHECK: $d: | ||
| 41 | // CHECK-NEXT: 7fe0010: 00 10 02 08 .word 0x08021000 | ||
deps/lld/test/ELF/aarch64-tls-gdie.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux | 2 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux |
| 3 | // RUN: llvm-mc %p/Inputs/aarch64-tls-gdie.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux | 3 | // 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 -shared | 4 | // RUN: ld.lld %t2.o -o %t2.so -shared |
| 5 | // RUN: ld.lld %t.o %t2.so -o %t | 5 | // RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t |
| 6 | // RUN: llvm-readobj -s %t | FileCheck --check-prefix=SEC %s | 6 | // RUN: llvm-readobj -s %t | FileCheck --check-prefix=SEC %s |
| 7 | // RUN: llvm-objdump -d %t | FileCheck %s | 7 | // RUN: llvm-objdump -d %t | FileCheck %s |
| 8 | 8 |
deps/lld/test/ELF/aarch64-tls-ie.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tls-ie.s -o %tdso.o | 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tls-ie.s -o %tdso.o |
| 3 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o | 3 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o |
| 4 | # RUN: ld.lld -shared %tdso.o -o %tdso.so | 4 | # RUN: ld.lld -shared %tdso.o -o %tdso.so |
| 5 | # RUN: ld.lld %tmain.o %tdso.so -o %tout | 5 | # RUN: ld.lld --hash-style=sysv %tmain.o %tdso.so -o %tout |
| 6 | # RUN: llvm-objdump -d %tout | FileCheck %s | 6 | # RUN: llvm-objdump -d %tout | FileCheck %s |
| 7 | # RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s | 7 | # RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s |
| 8 | # REQUIRES: aarch64 | 8 | # REQUIRES: aarch64 |
deps/lld/test/ELF/aarch64-tls-static.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: aarch64 | 1 | // REQUIRES: aarch64 |
| 2 | // RUN: llvm-mc %s -o %t.o -triple aarch64-pc-linux -filetype=obj | 2 | // RUN: llvm-mc %s -o %t.o -triple aarch64-pc-linux -filetype=obj |
| 3 | // RUN: ld.lld %t.o -o %t.so -shared | 3 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 4 | // RUN: llvm-readobj -s %t.so | FileCheck --check-prefix=SEC %s | 4 | // RUN: llvm-readobj -s %t.so | FileCheck --check-prefix=SEC %s |
| 5 | // RUN: llvm-objdump -d %t.so | FileCheck %s | 5 | // RUN: llvm-objdump -d %t.so | FileCheck %s |
| 6 | 6 |
deps/lld/test/ELF/aarch64-tlsdesc.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: aarch64 | 1 | // REQUIRES: aarch64 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld -shared %t.o -o %t.so | 3 | // RUN: ld.lld --hash-style=sysv -shared %t.o -o %t.so |
| 4 | // RUN: llvm-objdump -d %t.so | FileCheck %s | 4 | // RUN: llvm-objdump -d %t.so | FileCheck %s |
| 5 | // RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=REL %s | 5 | // RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=REL %s |
| 6 | 6 |
deps/lld/test/ELF/aarch64-undefined-weak.s+5-1| ... | @@ -30,9 +30,11 @@ _start: | ... | @@ -30,9 +30,11 @@ _start: |
| 30 | .xword target - . | 30 | .xword target - . |
| 31 | // R_AARCH64_PREL16 | 31 | // R_AARCH64_PREL16 |
| 32 | .hword target - . | 32 | .hword target - . |
| 33 | // R_AARCH64_LD_PREL_LO19 | ||
| 34 | ldr x8, target | ||
| 33 | 35 | ||
| 34 | // CHECK: Disassembly of section .text: | 36 | // CHECK: Disassembly of section .text: |
| 35 | // 131076 = 0x20004 | 37 | // 131072 = 0x20000 |
| 36 | // CHECK: 20000: {{.*}} b #4 | 38 | // CHECK: 20000: {{.*}} b #4 |
| 37 | // CHECK-NEXT: 20004: {{.*}} bl #4 | 39 | // CHECK-NEXT: 20004: {{.*}} bl #4 |
| 38 | // CHECK-NEXT: 20008: {{.*}} b.eq #4 | 40 | // CHECK-NEXT: 20008: {{.*}} b.eq #4 |
| ... | @@ -43,3 +45,5 @@ _start: | ... | @@ -43,3 +45,5 @@ _start: |
| 43 | // CHECK-NEXT: 2001c: {{.*}} .word 0x00000000 | 45 | // CHECK-NEXT: 2001c: {{.*}} .word 0x00000000 |
| 44 | // CHECK-NEXT: 20020: {{.*}} .word 0x00000000 | 46 | // CHECK-NEXT: 20020: {{.*}} .word 0x00000000 |
| 45 | // CHECK-NEXT: 20024: {{.*}} .short 0x0000 | 47 | // CHECK-NEXT: 20024: {{.*}} .short 0x0000 |
| 48 | // CHECK: $x.2: | ||
| 49 | // CHECK-NEXT: 20026: {{.*}} ldr x8, #0 |
deps/lld/test/ELF/abs-hidden.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 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/abs-hidden.s -o %t2.o | 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/abs-hidden.s -o %t2.o |
| 4 | // RUN: ld.lld %t.o %t2.o -o %t.so -shared | 4 | // 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 %s | 5 | // RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s |
| 6 | 6 | ||
| 7 | .quad foo | 7 | .quad foo |
deps/lld/test/ELF/allow-multiple-definition.s+5| ... | @@ -8,6 +8,11 @@ | ... | @@ -8,6 +8,11 @@ |
| 8 | # RUN: llvm-objdump -d %t3 | FileCheck %s | 8 | # RUN: llvm-objdump -d %t3 | FileCheck %s |
| 9 | # RUN: llvm-objdump -d %t4 | FileCheck -check-prefix=REVERT %s | 9 | # RUN: llvm-objdump -d %t4 | FileCheck -check-prefix=REVERT %s |
| 10 | 10 | ||
| 11 | # RUN: ld.lld -z muldefs %t1 %t2 -o %t3 | ||
| 12 | # RUN: ld.lld -z muldefs %t2 %t1 -o %t4 | ||
| 13 | # RUN: llvm-objdump -d %t3 | FileCheck %s | ||
| 14 | # RUN: llvm-objdump -d %t4 | FileCheck -check-prefix=REVERT %s | ||
| 15 | |||
| 11 | # inputs contain different constants for instuction movl. | 16 | # inputs contain different constants for instuction movl. |
| 12 | # Tests below checks that order of files in command line | 17 | # Tests below checks that order of files in command line |
| 13 | # affects on what symbol will be used. | 18 | # affects on what symbol will be used. |
deps/lld/test/ELF/amdgpu-elf-flags-err.s created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -filetype=obj %S/Inputs/amdgpu-kernel-0.s -o %t-0.o | ||
| 2 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -filetype=obj %S/Inputs/amdgpu-kernel-1.s -o %t-1.o | ||
| 3 | # RUN: not ld.lld -shared %t-0.o %t-1.o %S/Inputs/amdgpu-kernel-2.o -o %t.so 2>&1 | FileCheck %s | ||
| 4 | |||
| 5 | # REQUIRES: amdgpu | ||
| 6 | |||
| 7 | # CHECK: error: incompatible e_flags: {{.*}}amdgpu-kernel-2.o | ||
deps/lld/test/ELF/amdgpu-elf-flags.s created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -filetype=obj %S/Inputs/amdgpu-kernel-0.s -o %t-0.o | ||
| 2 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -filetype=obj %S/Inputs/amdgpu-kernel-1.s -o %t-1.o | ||
| 3 | # RUN: ld.lld -shared %t-0.o %t-1.o -o %t.so | ||
| 4 | # RUN: llvm-readobj -file-headers %t.so | FileCheck %s | ||
| 5 | |||
| 6 | # REQUIRES: amdgpu | ||
| 7 | |||
| 8 | # CHECK: Flags [ (0x2) | ||
| 9 | # CHECK: EF_AMDGPU_ARCH_GCN (0x2) | ||
| 10 | # CHECK: ] | ||
deps/lld/test/ELF/amdgpu-relocs.s+14-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | # RUN: llvm-mc -filetype=obj -triple=amdgcn--amdhsa -mcpu=fiji %s -o %t.o | 1 | # RUN: llvm-mc -filetype=obj -triple=amdgcn--amdhsa -mcpu=fiji %s -o %t.o |
| 2 | # RUN: ld.lld -shared %t.o -o %t.so | 2 | # RUN: ld.lld --hash-style=sysv -shared %t.o -o %t.so |
| 3 | # RUN: llvm-readobj -r %t.so | FileCheck %s | 3 | # RUN: llvm-readobj -r %t.so | FileCheck %s |
| 4 | # RUN: llvm-objdump -s %t.so | FileCheck %s --check-prefix=OBJDUMP | 4 | # RUN: llvm-objdump -s %t.so | FileCheck %s --check-prefix=OBJDUMP |
| 5 | 5 | ||
| ... | @@ -65,10 +65,23 @@ ptr: | ... | @@ -65,10 +65,23 @@ ptr: |
| 65 | .quad temp | 65 | .quad temp |
| 66 | .size ptr, 8 | 66 | .size ptr, 8 |
| 67 | 67 | ||
| 68 | # R_AMDGPU_RELATIVE64: | ||
| 69 | .type temp2, @object | ||
| 70 | .local temp2 | ||
| 71 | .size temp2, 4 | ||
| 72 | |||
| 73 | .type ptr2, @object | ||
| 74 | .globl ptr2 | ||
| 75 | .size ptr2, 8 | ||
| 76 | .p2align 3 | ||
| 77 | ptr2: | ||
| 78 | .quad temp2 | ||
| 79 | |||
| 68 | # The relocation for local_var{0, 1, 2} and var should be resolved by the | 80 | # The relocation for local_var{0, 1, 2} and var should be resolved by the |
| 69 | # linker. | 81 | # linker. |
| 70 | # CHECK: Relocations [ | 82 | # CHECK: Relocations [ |
| 71 | # CHECK: .rela.dyn { | 83 | # CHECK: .rela.dyn { |
| 84 | # CHECK-NEXT: R_AMDGPU_RELATIVE64 - 0x0 | ||
| 72 | # CHECK-NEXT: R_AMDGPU_ABS64 common_var0 0x0 | 85 | # CHECK-NEXT: R_AMDGPU_ABS64 common_var0 0x0 |
| 73 | # CHECK-NEXT: R_AMDGPU_ABS64 common_var1 0x0 | 86 | # CHECK-NEXT: R_AMDGPU_ABS64 common_var1 0x0 |
| 74 | # CHECK-NEXT: R_AMDGPU_ABS64 common_var2 0x0 | 87 | # CHECK-NEXT: R_AMDGPU_ABS64 common_var2 0x0 |
deps/lld/test/ELF/arm-bl-v6.s created+51| ... | @@ -0,0 +1,51 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: ld.lld %t -o %t2 2>&1 | FileCheck %s | ||
| 3 | // REQUIRES: arm | ||
| 4 | |||
| 5 | // On Arm v6 the range of a Thumb BL instruction is only 4 megabytes as the | ||
| 6 | // extended range encoding is not supported. The following example has a Thumb | ||
| 7 | // BL that is out of range on ARM v6 and requires a range extension thunk. | ||
| 8 | // As v6 does not support MOVT or MOVW instructions the Thunk must not | ||
| 9 | // use these instructions either. At present we don't support v6 so we give a | ||
| 10 | // warning for unsupported features. | ||
| 11 | |||
| 12 | // CHECK: warning: lld uses extended branch encoding, no object with architecture supporting feature detected. | ||
| 13 | // CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected. | ||
| 14 | // ARM v6 supports blx so we shouldn't see the blx not supported warning. | ||
| 15 | // CHECK-NOT: warning: lld uses blx instruction, no object with architecture supporting feature detected. | ||
| 16 | .text | ||
| 17 | .syntax unified | ||
| 18 | .cpu arm1176jzf-s | ||
| 19 | .eabi_attribute 6, 6 @ Tag_CPU_arch | ||
| 20 | .globl _start | ||
| 21 | .type _start,%function | ||
| 22 | .balign 0x1000 | ||
| 23 | _start: | ||
| 24 | bl thumbfunc | ||
| 25 | bx lr | ||
| 26 | |||
| 27 | .thumb | ||
| 28 | .section .text.2, "ax", %progbits | ||
| 29 | .globl thumbfunc | ||
| 30 | .type thumbfunc,%function | ||
| 31 | thumbfunc: | ||
| 32 | bl farthumbfunc | ||
| 33 | |||
| 34 | // 6 Megabytes, enough to make farthumbfunc out of range of caller on a v6 | ||
| 35 | // Arm, but not on a v7 Arm. | ||
| 36 | .section .text.3, "ax", %progbits | ||
| 37 | .space 0x200000 | ||
| 38 | |||
| 39 | .section .text.4, "ax", %progbits | ||
| 40 | .space 0x200000 | ||
| 41 | |||
| 42 | .section .text.5, "ax", %progbits | ||
| 43 | .space 0x200000 | ||
| 44 | |||
| 45 | .thumb | ||
| 46 | .section .text.6, "ax", %progbits | ||
| 47 | .balign 0x1000 | ||
| 48 | .globl farthumbfunc | ||
| 49 | .type farthumbfunc,%function | ||
| 50 | farthumbfunc: | ||
| 51 | bx lr | ||
deps/lld/test/ELF/arm-blx-v4t.s created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: ld.lld %t -o %t2 2>&1 | FileCheck %s | ||
| 3 | // REQUIRES: arm | ||
| 4 | |||
| 5 | // On Arm v4t there is no blx instruction so all interworking must go via | ||
| 6 | // a thunk. At present we don't support v4t so we give a warning for unsupported | ||
| 7 | // features. | ||
| 8 | |||
| 9 | // CHECK: warning: lld uses blx instruction, no object with architecture supporting feature detected. | ||
| 10 | // CHECK-NEXT: warning: lld uses extended branch encoding, no object with architecture supporting feature detected. | ||
| 11 | // CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected. | ||
| 12 | |||
| 13 | .text | ||
| 14 | .syntax unified | ||
| 15 | .cpu arm7tdmi | ||
| 16 | .eabi_attribute 6, 2 @ Tag_CPU_arch | ||
| 17 | .arm | ||
| 18 | .globl _start | ||
| 19 | .type _start,%function | ||
| 20 | .p2align 2 | ||
| 21 | _start: | ||
| 22 | bl thumbfunc | ||
| 23 | bx lr | ||
| 24 | |||
| 25 | .thumb | ||
| 26 | .section .text.2, "ax", %progbits | ||
| 27 | .globl thumbfunc | ||
| 28 | .type thumbfunc,%function | ||
| 29 | thumbfunc: | ||
| 30 | bx lr | ||
deps/lld/test/ELF/arm-branch-error.s deleted-19| ... | @@ -1,19 +0,0 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar | ||
| 3 | // RUN: not ld.lld %t %tfar -o %t2 2>&1 | FileCheck %s | ||
| 4 | // REQUIRES: arm | ||
| 5 | .syntax unified | ||
| 6 | .section .text, "ax",%progbits | ||
| 7 | .globl _start | ||
| 8 | .balign 0x10000 | ||
| 9 | .type _start,%function | ||
| 10 | _start: | ||
| 11 | // address of too_far symbols are just out of range of ARM branch with | ||
| 12 | // 26-bit immediate field and an addend of -8 | ||
| 13 | bl too_far1 | ||
| 14 | b too_far2 | ||
| 15 | beq too_far3 | ||
| 16 | |||
| 17 | // CHECK: R_ARM_CALL out of range | ||
| 18 | // CHECK-NEXT: R_ARM_JUMP24 out of range | ||
| 19 | // CHECK-NEXT: R_ARM_JUMP24 out of range | ||
deps/lld/test/ELF/arm-branch-rangethunk.s created+34| ... | @@ -0,0 +1,34 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar | ||
| 3 | // RUN: ld.lld %t %tfar -o %t2 2>&1 | ||
| 4 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s | ||
| 5 | // REQUIRES: arm | ||
| 6 | .syntax unified | ||
| 7 | .section .text, "ax",%progbits | ||
| 8 | .globl _start | ||
| 9 | .balign 0x10000 | ||
| 10 | .type _start,%function | ||
| 11 | _start: | ||
| 12 | // address of too_far symbols are just out of range of ARM branch with | ||
| 13 | // 26-bit immediate field and an addend of -8 | ||
| 14 | bl too_far1 | ||
| 15 | b too_far2 | ||
| 16 | beq too_far3 | ||
| 17 | |||
| 18 | // CHECK: Disassembly of section .text: | ||
| 19 | // CHECK-NEXT: _start: | ||
| 20 | // CHECK-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1> | ||
| 21 | // CHECK-NEXT: 20004: 03 00 00 ea b #12 <__ARMv7ABSLongThunk_too_far2> | ||
| 22 | // CHECK-NEXT: 20008: 05 00 00 0a beq #20 <__ARMv7ABSLongThunk_too_far3> | ||
| 23 | // CHECK: __ARMv7ABSLongThunk_too_far1: | ||
| 24 | // CHECK-NEXT: 2000c: 08 c0 00 e3 movw r12, #8 | ||
| 25 | // CHECK-NEXT: 20010: 02 c2 40 e3 movt r12, #514 | ||
| 26 | // CHECK-NEXT: 20014: 1c ff 2f e1 bx r12 | ||
| 27 | // CHECK: __ARMv7ABSLongThunk_too_far2: | ||
| 28 | // CHECK-NEXT: 20018: 0c c0 00 e3 movw r12, #12 | ||
| 29 | // CHECK-NEXT: 2001c: 02 c2 40 e3 movt r12, #514 | ||
| 30 | // CHECK-NEXT: 20020: 1c ff 2f e1 bx r12 | ||
| 31 | // CHECK: __ARMv7ABSLongThunk_too_far3: | ||
| 32 | // CHECK-NEXT: 20024: 10 c0 00 e3 movw r12, #16 | ||
| 33 | // CHECK-NEXT: 20028: 02 c2 40 e3 movt r12, #514 | ||
| 34 | // CHECK-NEXT: 2002c: 1c ff 2f e1 bx r12 | ||
deps/lld/test/ELF/arm-branch-undef-weak-plt-thunk.s created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-shared.s -o %t | ||
| 2 | // RUN: ld.lld %t --shared -o %t.so | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2 | ||
| 4 | // RUN: ld.lld %t2 %t.so -o %t3 | ||
| 5 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi -start-address=69632 -stop-address=69664 %t3 | FileCheck %s | ||
| 6 | // REQUIRES: arm | ||
| 7 | |||
| 8 | // When we are dynamic linking, undefined weak references have a PLT entry so | ||
| 9 | // we must create a thunk for the branch to the PLT entry. | ||
| 10 | |||
| 11 | .text | ||
| 12 | .globl bar2 | ||
| 13 | .weak undefined_weak_we_expect_a_plt_entry_for | ||
| 14 | _start: | ||
| 15 | .globl _start | ||
| 16 | .type _start, %function | ||
| 17 | b undefined_weak_we_expect_a_plt_entry_for | ||
| 18 | bl bar2 | ||
| 19 | // Create 32 Mb gap between the call to the weak reference and the PLT so that | ||
| 20 | // the b and bl need a range-extension thunk. | ||
| 21 | .section .text.1, "ax", %progbits | ||
| 22 | .space 32 * 1024 * 1024 | ||
| 23 | |||
| 24 | // CHECK: Disassembly of section .text: | ||
| 25 | // 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: 11004: 02 00 00 eb bl #8 <__ARMv7ABSLongThunk_bar2> | ||
| 28 | // CHECK: __ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for: | ||
| 29 | // CHECK-NEXT: 11008: 40 c0 01 e3 movw r12, #4160 | ||
| 30 | // CHECK-NEXT: 1100c: 01 c2 40 e3 movt r12, #513 | ||
| 31 | // CHECK-NEXT: 11010: 1c ff 2f e1 bx r12 | ||
| 32 | // CHECK: __ARMv7ABSLongThunk_bar2: | ||
| 33 | // CHECK-NEXT: 11014: 50 c0 01 e3 movw r12, #4176 | ||
| 34 | // CHECK-NEXT: 11018: 01 c2 40 e3 movt r12, #513 | ||
| 35 | // CHECK-NEXT: 1101c: 1c ff 2f e1 bx r12 | ||
deps/lld/test/ELF/arm-copy.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o |
| 3 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/relocation-copy-arm.s -o %t2.o | 3 | // 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 -o %t2.so | 4 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 5 | // RUN: ld.lld %t.o %t2.so -o %t3 | 5 | // RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t3 |
| 6 | // RUN: llvm-readobj -s -r --expand-relocs -symbols %t3 | FileCheck %s | 6 | // 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 %s | 7 | // 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 %s | 8 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi -section=.rodata %t3 | FileCheck -check-prefix=RODATA %s |
deps/lld/test/ELF/arm-exidx-dedup-and-sentinel.s created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | ||
| 3 | // RUN: ld.lld %t.o -shared -o %t.so --section-start .text=0x2000 --section-start .ARM.exidx=0x1000 | ||
| 4 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s | ||
| 5 | |||
| 6 | .syntax unified | ||
| 7 | |||
| 8 | .section .text.foo, "ax", %progbits | ||
| 9 | .globl foo | ||
| 10 | foo: | ||
| 11 | .fnstart | ||
| 12 | bx lr | ||
| 13 | .cantunwind | ||
| 14 | .fnend | ||
| 15 | |||
| 16 | .section .text.bar, "ax", %progbits | ||
| 17 | .globl bar | ||
| 18 | bar: | ||
| 19 | .fnstart | ||
| 20 | bx lr | ||
| 21 | .cantunwind | ||
| 22 | .fnend | ||
| 23 | |||
| 24 | // CHECK: Contents of section .ARM.exidx: | ||
| 25 | // 1000 + 1000 = 0x2000 = foo | ||
| 26 | // The entry for bar is the same as previous and is eliminated. | ||
| 27 | // The sentinel entry should be preserved. | ||
| 28 | // 1008 + 1000 = 0x2008 = bar + sizeof(bar) | ||
| 29 | // CHECK-NEXT: 1000 00100000 01000000 00100000 01000000 | ||
deps/lld/test/ELF/arm-exidx-dedup.s created+126| ... | @@ -0,0 +1,126 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: ld.lld %t --no-merge-exidx-entries -o %t2 | ||
| 3 | // RUN: llvm-objdump -s %t2 | FileCheck --check-prefix CHECK-DUPS %s | ||
| 4 | // RUN: ld.lld %t -o %t3 | ||
| 5 | // RUN: llvm-objdump -s %t3 | FileCheck %s | ||
| 6 | // REQUIRES: arm | ||
| 7 | // Test that lld can at least remove duplicate .ARM.exidx sections. A more | ||
| 8 | // fine grained implementation will be able to remove duplicate entries within | ||
| 9 | // a .ARM.exidx section. | ||
| 10 | |||
| 11 | // With duplicate entries | ||
| 12 | // CHECK-DUPS: Contents of section .ARM.exidx: | ||
| 13 | // CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000 | ||
| 14 | // CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000 | ||
| 15 | // CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780 | ||
| 16 | // CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 14000000 | ||
| 17 | // CHECK-DUPS-NEXT: 10114 0c0f0000 18000000 080f0000 01000000 | ||
| 18 | // CHECK-DUPS-NEXT: Contents of section .ARM.extab: | ||
| 19 | |||
| 20 | // After duplicate entry removal | ||
| 21 | // CHECK: Contents of section .ARM.exidx: | ||
| 22 | // CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780 | ||
| 23 | // CHECK-NEXT: 100e4 380f0000 14000000 340f0000 18000000 | ||
| 24 | // CHECK-NEXT: 100f4 300f0000 01000000 | ||
| 25 | // CHECK-NEXT: Contents of section .ARM.extab: | ||
| 26 | .syntax unified | ||
| 27 | |||
| 28 | // Expect 1 EXIDX_CANTUNWIND entry. | ||
| 29 | .section .text.00, "ax", %progbits | ||
| 30 | .globl _start | ||
| 31 | _start: | ||
| 32 | .fnstart | ||
| 33 | bx lr | ||
| 34 | .cantunwind | ||
| 35 | .fnend | ||
| 36 | |||
| 37 | // Expect .ARM.exidx.text.01 to be identical to .ARM.exidx.text.00 | ||
| 38 | .section .text.01, "ax", %progbits | ||
| 39 | .globl f1 | ||
| 40 | f1: | ||
| 41 | .fnstart | ||
| 42 | bx lr | ||
| 43 | .cantunwind | ||
| 44 | .fnend | ||
| 45 | |||
| 46 | // Expect 2 EXIDX_CANTUNWIND entries, these can be duplicated into | ||
| 47 | // .ARM.exid.text.00 | ||
| 48 | .section .text.02, "ax", %progbits | ||
| 49 | .globl f2 | ||
| 50 | f2: | ||
| 51 | .fnstart | ||
| 52 | bx lr | ||
| 53 | .cantunwind | ||
| 54 | .fnend | ||
| 55 | |||
| 56 | .globl f3 | ||
| 57 | f3: | ||
| 58 | .fnstart | ||
| 59 | bx lr | ||
| 60 | .cantunwind | ||
| 61 | .fnend | ||
| 62 | |||
| 63 | // Expect inline unwind instructions, not a duplicate of previous entry. | ||
| 64 | .section .text.03, "ax", %progbits | ||
| 65 | .global f4 | ||
| 66 | f4: | ||
| 67 | .fnstart | ||
| 68 | bx lr | ||
| 69 | .save {r7, lr} | ||
| 70 | .setfp r7, sp, #0 | ||
| 71 | .fnend | ||
| 72 | |||
| 73 | // Expect 2 inline unwind entries that are a duplicate of | ||
| 74 | // .ARM.exidx.text.03 | ||
| 75 | .section .text.04, "ax", %progbits | ||
| 76 | .global f5 | ||
| 77 | f5: | ||
| 78 | .fnstart | ||
| 79 | bx lr | ||
| 80 | .save {r7, lr} | ||
| 81 | .setfp r7, sp, #0 | ||
| 82 | .fnend | ||
| 83 | |||
| 84 | .global f6 | ||
| 85 | f6: | ||
| 86 | .fnstart | ||
| 87 | bx lr | ||
| 88 | .save {r7, lr} | ||
| 89 | .setfp r7, sp, #0 | ||
| 90 | .fnend | ||
| 91 | |||
| 92 | // Expect a section with a reference to an .ARM.extab. Not a duplicate | ||
| 93 | // of previous inline table entry. | ||
| 94 | .section .text.05, "ax",%progbits | ||
| 95 | .global f7 | ||
| 96 | f7: | ||
| 97 | .fnstart | ||
| 98 | bx lr | ||
| 99 | .personality __gxx_personality_v0 | ||
| 100 | .handlerdata | ||
| 101 | .long 0 | ||
| 102 | .fnend | ||
| 103 | |||
| 104 | // Expect a reference to an identical .ARM.extab. We do not try to | ||
| 105 | // deduplicate references to .ARM.extab sections. | ||
| 106 | .section .text.06, "ax",%progbits | ||
| 107 | .global f8 | ||
| 108 | f8: | ||
| 109 | .fnstart | ||
| 110 | bx lr | ||
| 111 | .personality __gxx_personality_v0 | ||
| 112 | .handlerdata | ||
| 113 | .long 0 | ||
| 114 | .fnend | ||
| 115 | |||
| 116 | // Dummy implementation of personality routines to satisfy reference from | ||
| 117 | // exception tables | ||
| 118 | .section .text.__gcc_personality_v0, "ax", %progbits | ||
| 119 | .global __gxx_personality_v0 | ||
| 120 | __gxx_personality_v0: | ||
| 121 | bx lr | ||
| 122 | |||
| 123 | .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits | ||
| 124 | .global __aeabi_unwind_cpp_pr0 | ||
| 125 | __aeabi_unwind_cpp_pr0: | ||
| 126 | bx lr | ||
deps/lld/test/ELF/arm-exidx-gc.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t |
| 2 | // RUN: ld.lld %t -o %t2 --gc-sections 2>&1 | 2 | // RUN: ld.lld %t --no-merge-exidx-entries -o %t2 --gc-sections 2>&1 |
| 3 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s | 3 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s |
| 4 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s | 4 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s |
| 5 | // REQUIRES: arm | 5 | // REQUIRES: arm |
deps/lld/test/ELF/arm-exidx-order.s+2-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-exidx-cantunwind.s -o %tcantunwind | 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-exidx-cantunwind.s -o %tcantunwind |
| 3 | // RUN: ld.lld %t %tcantunwind -o %t2 2>&1 | 3 | // RUN: ld.lld --no-merge-exidx-entries %t %tcantunwind -o %t2 2>&1 |
| 4 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s | 4 | // 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 %s | 5 | // 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 %s | 6 | // RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s |
| ... | @@ -8,7 +8,7 @@ | ... | @@ -8,7 +8,7 @@ |
| 8 | // RUN: echo "SECTIONS { \ | 8 | // RUN: echo "SECTIONS { \ |
| 9 | // RUN: .text 0x11000 : { *(.text*) } \ | 9 | // RUN: .text 0x11000 : { *(.text*) } \ |
| 10 | // RUN: .ARM.exidx : { *(.ARM.exidx) } } " > %t.script | 10 | // RUN: .ARM.exidx : { *(.ARM.exidx) } } " > %t.script |
| 11 | // RUN: ld.lld --script %t.script %tcantunwind %t -o %t3 2>&1 | 11 | // RUN: ld.lld --no-merge-exidx-entries --script %t.script %tcantunwind %t -o %t3 2>&1 |
| 12 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-SCRIPT %s | 12 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-SCRIPT %s |
| 13 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-SCRIPT-EXIDX %s | 13 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-SCRIPT-EXIDX %s |
| 14 | // REQUIRES: arm | 14 | // REQUIRES: arm |
deps/lld/test/ELF/arm-exidx-sentinel-orphan.s+1-1| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | // RUN: echo "SECTIONS { \ | 4 | // RUN: echo "SECTIONS { \ |
| 5 | // RUN: .text 0x11000 : { *(.text*) } \ | 5 | // RUN: .text 0x11000 : { *(.text*) } \ |
| 6 | // RUN: } " > %t.script | 6 | // RUN: } " > %t.script |
| 7 | // RUN: ld.lld --script %t.script %t -o %t2 | 7 | // RUN: ld.lld --no-merge-exidx-entries --script %t.script %t -o %t2 |
| 8 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s | 8 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s |
| 9 | // REQUIRES: arm | 9 | // REQUIRES: arm |
| 10 | 10 |
deps/lld/test/ELF/arm-exidx-shared.s+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t |
| 2 | // RUN: ld.lld %t --shared -o %t2 2>&1 | 2 | // RUN: ld.lld --hash-style=sysv %t --shared -o %t2 2>&1 |
| 3 | // RUN: llvm-readobj --relocations %t2 | FileCheck %s | 3 | // RUN: llvm-readobj --relocations %t2 | FileCheck %s |
| 4 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXTAB %s | 4 | // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXTAB %s |
| 5 | // REQUIRES: arm | 5 | // REQUIRES: arm |
| ... | @@ -41,5 +41,5 @@ __aeabi_unwind_cpp_pr0: | ... | @@ -41,5 +41,5 @@ __aeabi_unwind_cpp_pr0: |
| 41 | // CHECK-NEXT: 0x200C R_ARM_JUMP_SLOT __gxx_personality_v0 | 41 | // CHECK-NEXT: 0x200C R_ARM_JUMP_SLOT __gxx_personality_v0 |
| 42 | 42 | ||
| 43 | // CHECK-EXTAB: Contents of section .ARM.extab: | 43 | // CHECK-EXTAB: Contents of section .ARM.extab: |
| 44 | // 014c + 0ed8 = 0x1024 = __gxx_personality_v0(PLT) | 44 | // 014c + 0ee4 = 0x1030 = __gxx_personality_v0(PLT) |
| 45 | // CHECK-EXTAB-NEXT: 014c d80e0000 b0b0b000 00000000 | 45 | // CHECK-EXTAB-NEXT: 014c e40e0000 b0b0b000 00000000 |
deps/lld/test/ELF/arm-gnu-ifunc-plt.s+28-28| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %S/Inputs/arm-shared.s -o %t1.o | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %S/Inputs/arm-shared.s -o %t1.o |
| 2 | // RUN: ld.lld %t1.o --shared -o %t.so | 2 | // RUN: ld.lld %t1.o --shared -o %t.so |
| 3 | // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t.o | 3 | // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t.o |
| 4 | // RUN: ld.lld %t.so %t.o -o %tout | 4 | // RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout |
| 5 | // RUN: llvm-objdump -triple=armv7a-linux-gnueabihf -d %tout | FileCheck %s --check-prefix=DISASM | 5 | // RUN: llvm-objdump -triple=armv7a-linux-gnueabihf -d %tout | FileCheck %s --check-prefix=DISASM |
| 6 | // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT | 6 | // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT |
| 7 | // RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s | 7 | // RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s |
| ... | @@ -33,49 +33,49 @@ | ... | @@ -33,49 +33,49 @@ |
| 33 | // DISASM-NEXT: 11000: 1e ff 2f e1 bx lr | 33 | // DISASM-NEXT: 11000: 1e ff 2f e1 bx lr |
| 34 | // DISASM: bar: | 34 | // DISASM: bar: |
| 35 | // DISASM-NEXT: 11004: 1e ff 2f e1 bx lr | 35 | // DISASM-NEXT: 11004: 1e ff 2f e1 bx lr |
| 36 | // DISASM: _start: | 36 | // DISASM: _start: |
| 37 | // DISASM-NEXT: 11008: 14 00 00 eb bl #80 | 37 | // DISASM-NEXT: 11008: 14 00 00 eb bl #80 |
| 38 | // DISASM-NEXT: 1100c: 17 00 00 eb bl #92 | 38 | // DISASM-NEXT: 1100c: 17 00 00 eb bl #92 |
| 39 | // DISASM: 11010: 00 00 00 00 .word 0x00000000 | 39 | // DISASM: $d.1: |
| 40 | // DISASM-NEXT: 11010: 00 00 00 00 .word 0x00000000 | ||
| 40 | // DISASM-NEXT: 11014: 04 00 00 00 .word 0x00000004 | 41 | // DISASM-NEXT: 11014: 04 00 00 00 .word 0x00000004 |
| 41 | // DISASM: 11018: 05 00 00 eb bl #20 | 42 | // DISASM: 11018: 08 00 00 eb bl #32 |
| 42 | // DISASM-NEXT: 1101c: 08 00 00 eb bl #32 | 43 | // DISASM-NEXT: 1101c: 0b 00 00 eb bl #44 |
| 43 | // DISASM-NEXT: Disassembly of section .plt: | 44 | // DISASM-NEXT: Disassembly of section .plt: |
| 44 | // DISASM-NEXT: $a: | 45 | // DISASM-NEXT: $a: |
| 45 | // DISASM-NEXT: 11020: 04 e0 2d e5 str lr, [sp, #-4]! | 46 | // DISASM-NEXT: 11020: 04 e0 2d e5 str lr, [sp, #-4]! |
| 46 | // DISASM-NEXT: 11024: 04 e0 9f e5 ldr lr, [pc, #4] | 47 | // DISASM-NEXT: 11024: 00 e6 8f e2 add lr, pc, #0, #12 |
| 47 | // DISASM-NEXT: 11028: 0e e0 8f e0 add lr, pc, lr | 48 | // DISASM-NEXT: 11028: 00 ea 8e e2 add lr, lr, #0, #20 |
| 48 | // DISASM-NEXT: 1102c: 08 f0 be e5 ldr pc, [lr, #8]! | 49 | // DISASM-NEXT: 1102c: dc ff be e5 ldr pc, [lr, #4060]! |
| 49 | // DISASM: $d: | 50 | // DISASM: $d: |
| 50 | // DISASM-NEXT: 11030: d0 0f 00 00 .word 0x00000fd0 | 51 | // DISASM-NEXT: 11030: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 52 | // DISASM-NEXT: 11034: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 53 | // DISASM-NEXT: 11038: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 54 | // DISASM-NEXT: 1103c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 51 | // DISASM: $a: | 55 | // DISASM: $a: |
| 52 | // DISASM-NEXT: 11034: 04 c0 9f e5 ldr r12, [pc, #4] | 56 | // DISASM-NEXT: 11040: 00 c6 8f e2 add r12, pc, #0, #12 |
| 53 | // DISASM-NEXT: 11038: 0f c0 8c e0 add r12, r12, pc | 57 | // DISASM-NEXT: 11044: 00 ca 8c e2 add r12, r12, #0, #20 |
| 54 | // DISASM-NEXT: 1103c: 00 f0 9c e5 ldr pc, [r12] | 58 | // DISASM-NEXT: 11048: c4 ff bc e5 ldr pc, [r12, #4036]! |
| 55 | // DISASM: $d: | 59 | // DISASM: $d: |
| 56 | // DISASM-NEXT: 11040: cc 0f 00 00 .word 0x00000fcc | 60 | // DISASM-NEXT: 1104c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 57 | // DISASM: $a: | 61 | // DISASM: $a: |
| 58 | // DISASM-NEXT: 11044: 04 c0 9f e5 ldr r12, [pc, #4] | 62 | // DISASM-NEXT: 11050: 00 c6 8f e2 add r12, pc, #0, #12 |
| 59 | // DISASM-NEXT: 11048: 0f c0 8c e0 add r12, r12, pc | 63 | // DISASM-NEXT: 11054: 00 ca 8c e2 add r12, r12, #0, #20 |
| 60 | // DISASM-NEXT: 1104c: 00 f0 9c e5 ldr pc, [r12] | 64 | // DISASM-NEXT: 11058: b8 ff bc e5 ldr pc, [r12, #4024]! |
| 61 | // DISASM: $d: | 65 | // DISASM: $d: |
| 62 | // DISASM-NEXT: 11050: c0 0f 00 00 .word 0x00000fc0 | ||
| 63 | // Alignment to 16 byte boundary not strictly necessary on ARM, but harmless | ||
| 64 | // DISASM-NEXT: 11054: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 65 | // DISASM-NEXT: 11058: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 66 | // DISASM-NEXT: 1105c: d4 d4 d4 d4 .word 0xd4d4d4d4 | 66 | // DISASM-NEXT: 1105c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 67 | // DISASM: $a: | 67 | // DISASM: $a: |
| 68 | // DISASM-NEXT: 11060: 04 c0 9f e5 ldr r12, [pc, #4] | 68 | // DISASM-NEXT: 11060: 00 c6 8f e2 add r12, pc, #0, #12 |
| 69 | // DISASM-NEXT: 11064: 0f c0 8c e0 add r12, r12, pc | 69 | // DISASM-NEXT: 11064: 02 ca 8c e2 add r12, r12, #8192 |
| 70 | // DISASM-NEXT: 11068: 00 f0 9c e5 ldr pc, [r12] | 70 | // DISASM-NEXT: 11068: 18 f0 bc e5 ldr pc, [r12, #24]! |
| 71 | // DISASM: $d: | 71 | // DISASM: $d: |
| 72 | // DISASM-NEXT: 1106c: 14 20 00 00 .word 0x00002014 | 72 | // DISASM-NEXT: 1106c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 73 | // DISASM: $a: | 73 | // DISASM: $a: |
| 74 | // DISASM-NEXT: 11070: 04 c0 9f e5 ldr r12, [pc, #4] | 74 | // DISASM-NEXT: 11070: 00 c6 8f e2 add r12, pc, #0, #12 |
| 75 | // DISASM-NEXT: 11074: 0f c0 8c e0 add r12, r12, pc | 75 | // DISASM-NEXT: 11074: 02 ca 8c e2 add r12, r12, #8192 |
| 76 | // DISASM-NEXT: 11078: 00 f0 9c e5 ldr pc, [r12] | 76 | // DISASM-NEXT: 11078: 0c f0 bc e5 ldr pc, [r12, #12]! |
| 77 | // DISASM: $d: | 77 | // DISASM: $d: |
| 78 | // DISASM-NEXT: 1107c: 08 20 00 00 .word 0x00002008 | 78 | // DISASM-NEXT: 1107c:	d4 d4 d4 d4 	.word	0xd4d4d4d4 |
| 79 | 79 | ||
| 80 | .syntax unified | 80 | .syntax unified |
| 81 | .text | 81 | .text |
deps/lld/test/ELF/arm-gnu-ifunc.s+20-21| ... | @@ -111,30 +111,29 @@ _start: | ... | @@ -111,30 +111,29 @@ _start: |
| 111 | 111 | ||
| 112 | // DISASM: Disassembly of section .text: | 112 | // DISASM: Disassembly of section .text: |
| 113 | // DISASM-NEXT: foo: | 113 | // DISASM-NEXT: foo: |
| 114 | // DISASM-NEXT: 11000:	1e ff 2f e1 	bx	lr | 114 | // DISASM-NEXT: 11000: 1e ff 2f e1 bx lr |
| 115 | // DISASM: bar: | 115 | // DISASM: bar: |
| 116 | // DISASM-NEXT: 11004:	1e ff 2f e1 	bx	lr | 116 | // DISASM-NEXT: 11004: 1e ff 2f e1 bx lr |
| 117 | // DISASM: _start: | 117 | // DISASM: _start: |
| 118 | // DISASM-NEXT: 11008:	04 00 00 eb 	bl	#16 | 118 | // DISASM-NEXT: 11008: 04 00 00 eb bl #16 |
| 119 | // DISASM-NEXT: 1100c:	07 00 00 eb 	bl	#28 | 119 | // DISASM-NEXT: 1100c: 07 00 00 eb bl #28 |
| 120 | // 1 * 65536 + 244 = 0x100f4 __rel_iplt_start | 120 | // 1 * 65536 + 244 = 0x100f4 __rel_iplt_start |
| 121 | // DISASM-NEXT: 11010:	f4 00 00 e3 	movw	r0, #244 | 121 | // DISASM-NEXT: 11010: f4 00 00 e3 movw r0, #244 |
| 122 | // DISASM-NEXT: 11014:	01 00 40 e3 	movt	r0, #1 | 122 | // DISASM-NEXT: 11014: 01 00 40 e3 movt r0, #1 |
| 123 | // 1 * 65536 + 260 = 0x10104 __rel_iplt_end | 123 | // 1 * 65536 + 260 = 0x10104 __rel_iplt_end |
| 124 | // DISASM-NEXT: 11018:	04 01 00 e3 	movw	r0, #260 | 124 | // DISASM-NEXT: 11018: 04 01 00 e3 movw r0, #260 |
| 125 | // DISASM-NEXT: 1101c:	01 00 40 e3 	movt	r0, #1 | 125 | // DISASM-NEXT: 1101c: 01 00 40 e3 movt r0, #1 |
| 126 | // DISASM-NEXT: Disassembly of section .plt: | 126 | // DISASM-NEXT: Disassembly of section .plt: |
| 127 | // DISASM: $a: | 127 | // DISASM-NEXT: $a: |
| 128 | // DISASM-NEXT: 11020: 04 c0 9f e5 ldr r12, [pc, #4] | 128 | // DISASM-NEXT: 11020: 00 c6 8f e2 add r12, pc, #0, #12 |
| 129 | // DISASM-NEXT: 11024: 0f c0 8c e0 add r12, r12, pc | 129 | // DISASM-NEXT: 11024: 00 ca 8c e2 add r12, r12, #0, #20 |
| 130 | // 11024 + 8 + fd4 = 0x12000 | 130 | // DISASM-NEXT: 11028: d8 ff bc e5 ldr pc, [r12, #4056]! |
| 131 | // DISASM-NEXT: 11028: 00 f0 9c e5 ldr pc, [r12] | ||
| 132 | // DISASM: $d: | 131 | // DISASM: $d: |
| 133 | // DISASM-NEXT: 1102c: d4 0f 00 00 .word 0x00000fd4 | 132 | // DISASM-NEXT: 1102c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 134 | // DISASM: $a: | 133 | // DISASM: $a: |
| 135 | // DISASM-NEXT: 11030: 04 c0 9f e5 ldr r12, [pc, #4] | 134 | // DISASM-NEXT: 11030: 00 c6 8f e2 add r12, pc, #0, #12 |
| 136 | // DISASM-NEXT: 11034: 0f c0 8c e0 add r12, r12, pc | 135 | // DISASM-NEXT: 11034: 00 ca 8c e2 add r12, r12, #0, #20 |
| 137 | // 11034 + 8 + fc8 = 0x12004 | 136 | // DISASM-NEXT: 11038: cc ff bc e5 ldr pc, [r12, #4044]! |
| 138 | // DISASM-NEXT: 11038: 00 f0 9c e5 ldr pc, [r12] | ||
| 139 | // DISASM: $d: | 137 | // DISASM: $d: |
| 140 | // DISASM-NEXT: 1103c: c8 0f 00 00 .word 0x00000fc8 | 138 | // DISASM-NEXT: 1103c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 139 |
deps/lld/test/ELF/arm-got-relative.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: arm | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -position-independent -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | 2 | // RUN: llvm-mc -position-independent -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o |
| 3 | // RUN: ld.lld %t.o -shared -o %t | 3 | // RUN: ld.lld --hash-style=sysv %t.o -shared -o %t |
| 4 | // RUN: llvm-readobj -s -symbols -dyn-relocations %t | FileCheck %s | 4 | // 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 %s | 5 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s |
| 6 | .syntax unified | 6 | .syntax unified |
deps/lld/test/ELF/arm-icf-exidx.s+1-1| ... | @@ -23,7 +23,7 @@ __aeabi_unwind_cpp_pr0: | ... | @@ -23,7 +23,7 @@ __aeabi_unwind_cpp_pr0: |
| 23 | bx lr | 23 | bx lr |
| 24 | 24 | ||
| 25 | // CHECK: Disassembly of section .text: | 25 | // CHECK: Disassembly of section .text: |
| 26 | // CHECK-NEXT: f: | 26 | // CHECK-NEXT: g: |
| 27 | // CHECK-NEXT: 11000: 1e ff 2f e1 bx lr | 27 | // CHECK-NEXT: 11000: 1e ff 2f e1 bx lr |
| 28 | // CHECK: __aeabi_unwind_cpp_pr0: | 28 | // CHECK: __aeabi_unwind_cpp_pr0: |
| 29 | // CHECK-NEXT: 11004: 00 f0 20 e3 nop | 29 | // CHECK-NEXT: 11004: 00 f0 20 e3 nop |
deps/lld/test/ELF/arm-pie-relative.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t |
| 2 | // RUN: ld.lld %t --pie -o %t2 | 2 | // RUN: ld.lld --hash-style=sysv %t --pie -o %t2 |
| 3 | // RUN: llvm-readobj -r %t2 | FileCheck %s | 3 | // RUN: llvm-readobj -r %t2 | FileCheck %s |
| 4 | // RUN: llvm-objdump -s %t2 | FileCheck %s --check-prefix=GOT | 4 | // RUN: llvm-objdump -s %t2 | FileCheck %s --check-prefix=GOT |
| 5 | // REQUIRES: arm | 5 | // REQUIRES: arm |
deps/lld/test/ELF/arm-plt-reloc.s+232-32| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2 | 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2 |
| 3 | // RUN: ld.lld %t1 %t2 -o %t | 3 | // RUN: ld.lld %t1 %t2 -o %t |
| 4 | // RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t | FileCheck %s | 4 | // RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t | FileCheck %s |
| 5 | // RUN: ld.lld -shared %t1 %t2 -o %t3 | 5 | // RUN: ld.lld --hash-style=sysv -shared %t1 %t2 -o %t3 |
| 6 | // RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSO %s | 6 | // RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSO %s |
| 7 | // RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s | 7 | // RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s |
| 8 | // REQUIRES: arm | 8 | // REQUIRES: arm |
| ... | @@ -32,51 +32,55 @@ _start: | ... | @@ -32,51 +32,55 @@ _start: |
| 32 | // CHECK-NEXT: 11014: fb ff ff 0a beq #-20 <func3> | 32 | // CHECK-NEXT: 11014: fb ff ff 0a beq #-20 <func3> |
| 33 | 33 | ||
| 34 | // Expect PLT entries as symbols can be preempted | 34 | // Expect PLT entries as symbols can be preempted |
| 35 | // The .got.plt and .plt displacement is small so we can use small PLT entries. | ||
| 35 | // DSO: Disassembly of section .text: | 36 | // DSO: Disassembly of section .text: |
| 36 | // DSO-NEXT: func1: | 37 | // DSO-NEXT: func1: |
| 37 | // DSO-NEXT: 1000: 1e ff 2f e1 bx lr | 38 | // DSO-NEXT: 1000: 1e ff 2f e1 bx lr |
| 38 | // DSO: func2: | 39 | // DSO: func2: |
| 39 | // DSO-NEXT: 1004: 1e ff 2f e1 bx lr | 40 | // DSO-NEXT: 1004: 1e ff 2f e1 bx lr |
| 40 | // DSO: func3: | 41 | // DSO: func3: |
| 41 | // DSO-NEXT: 1008: 1e ff 2f e1 bx lr | 42 | // DSO-NEXT: 1008: 1e ff 2f e1 bx lr |
| 42 | // DSO: _start: | 43 | // DSO: _start: |
| 43 | // S(0x1034) - P(0x100c) + A(-8) = 0x20 = 32 | 44 | // S(0x1040) - P(0x100c) + A(-8) = 0x2c = 32 |
| 44 | // DSO-NEXT: 100c: 08 00 00 ea b #32 | 45 | // DSO-NEXT: 100c: 0b 00 00 ea b #44 |
| 45 | // S(0x1044) - P(0x1010) + A(-8) = 0x2c = 44 | 46 | // S(0x1050) - P(0x1010) + A(-8) = 0x38 = 56 |
| 46 | // DSO-NEXT: 1010: 0b 00 00 eb bl #44 | 47 | // DSO-NEXT: 1010: 0e 00 00 eb bl #56 |
| 47 | // S(0x1054) - P(0x1014) + A(-8) = 0x38 = 56 | 48 | // S(0x10160) - P(0x1014) + A(-8) = 0x44 = 68 |
| 48 | // DSO-NEXT: 1014: 0e 00 00 0a beq #56 | 49 | // DSO-NEXT: 1014: 11 00 00 0a beq #68 |
| 49 | 50 | // DSO-NEXT: Disassembly of section .plt: | |
| 50 | // DSO: Disassembly of section .plt: | ||
| 51 | // DSO-NEXT: $a: | 51 | // DSO-NEXT: $a: |
| 52 | // DSO-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]! | 52 | // DSO-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]! |
| 53 | // DSO-NEXT: 1024: 04 e0 9f e5 ldr lr, [pc, #4] | 53 | // (0x1024 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfdc) = 0x2008 = .got.plt[3] |
| 54 | // DSO-NEXT: 1028: 0e e0 8f e0 add lr, pc, lr | 54 | // DSO-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #12 |
| 55 | // DSO-NEXT: 102c: 08 f0 be e5 ldr pc, [lr, #8]! | 55 | // DSO-NEXT: 1028: 00 ea 8e e2 add lr, lr, #0, #20 |
| 56 | // 0x1028 + 8 + 0fd0 = 0x2000 | 56 | // DSO-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]! |
| 57 | // DSO: $d: | 57 | // DSO: $d: |
| 58 | // DSO-NEXT: 1030: d0 0f 00 00 .word 0x00000fd0 | 58 | // DSO-NEXT: 1030: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 59 | // DSO-NEXT: 1034: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 60 | // DSO-NEXT: 1038: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 61 | // DSO-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 59 | // DSO: $a: | 62 | // DSO: $a: |
| 60 | // DSO-NEXT: 1034: 04 c0 9f e5 ldr r12, [pc, #4] | 63 | // (0x1040 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfc4) = 0x200c |
| 61 | // DSO-NEXT: 1038: 0f c0 8c e0 add r12, r12, pc | 64 | // DSO-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #12 |
| 62 | // DSO-NEXT: 103c: 00 f0 9c e5 ldr pc, [r12] | 65 | // DSO-NEXT: 1044: 00 ca 8c e2 add r12, r12, #0, #20 |
| 63 | // 0x1038 + 8 + 0fcc = 0x200c | 66 | // DSO-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]! |
| 64 | // DSO: $d: | 67 | // DSO: $d: |
| 65 | // DSO-NEXT: 1040: cc 0f 00 00 .word 0x00000fcc | 68 | // DSO-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 66 | // DSO: $a: | 69 | // DSO: $a: |
| 67 | // DSO-NEXT: 1044: 04 c0 9f e5 ldr r12, [pc, #4] | 70 | // (0x1050 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfb8) = 0x2010 |
| 68 | // DSO-NEXT: 1048: 0f c0 8c e0 add r12, r12, pc | 71 | // DSO-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #12 |
| 69 | // DSO-NEXT: 104c: 00 f0 9c e5 ldr pc, [r12] | 72 | // DSO-NEXT: 1054: 00 ca 8c e2 add r12, r12, #0, #20 |
| 70 | // 0x1048 + 8 + 0fc0 = 0x2010 | 73 | // DSO-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]! |
| 71 | // DSO: $d: | 74 | // DSO: $d: |
| 72 | // DSO-NEXT: 1050: c0 0f 00 00 .word 0x00000fc0 | 75 | // DSO-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 73 | // DSO: $a: | 76 | // DSO: $a: |
| 74 | // DSO-NEXT: 1054: 04 c0 9f e5 ldr r12, [pc, #4] | 77 | // (0x1060 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfac) = 0x2014 |
| 75 | // DSO-NEXT: 1058: 0f c0 8c e0 add r12, r12, pc | 78 | // DSO-NEXT: 1060: 00 c6 8f e2 add r12, pc, #0, #12 |
| 76 | // DSO-NEXT: 105c: 00 f0 9c e5 ldr pc, [r12] | 79 | // DSO-NEXT: 1064: 00 ca 8c e2 add r12, r12, #0, #20 |
| 77 | // 0x1058 + 8 + 0fb4 = 0x2014 | 80 | // DSO-NEXT: 1068: ac ff bc e5 ldr pc, [r12, #4012]! |
| 78 | // DSO: $d: | 81 | // DSO: $d: |
| 79 | // DSO-NEXT: 1060: b4 0f 00 00 .word 0x00000fb4 | 82 | // DSO-NEXT: 106c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 83 | |||
| 80 | 84 | ||
| 81 | // DSOREL: Name: .got.plt | 85 | // DSOREL: Name: .got.plt |
| 82 | // DSOREL-NEXT: Type: SHT_PROGBITS | 86 | // DSOREL-NEXT: Type: SHT_PROGBITS |
| ... | @@ -96,3 +100,199 @@ _start: | ... | @@ -96,3 +100,199 @@ _start: |
| 96 | // DSOREL-NEXT: 0x200C R_ARM_JUMP_SLOT func1 0x0 | 100 | // DSOREL-NEXT: 0x200C R_ARM_JUMP_SLOT func1 0x0 |
| 97 | // DSOREL-NEXT: 0x2010 R_ARM_JUMP_SLOT func2 0x0 | 101 | // DSOREL-NEXT: 0x2010 R_ARM_JUMP_SLOT func2 0x0 |
| 98 | // DSOREL-NEXT: 0x2014 R_ARM_JUMP_SLOT func3 0x0 | 102 | // DSOREL-NEXT: 0x2014 R_ARM_JUMP_SLOT func3 0x0 |
| 103 | |||
| 104 | // Test a large separation between the .plt and .got.plt | ||
| 105 | // The .got.plt and .plt displacement is large but still within the range | ||
| 106 | // of the short plt sequence. | ||
| 107 | // RUN: echo "SECTIONS { \ | ||
| 108 | // RUN: .text 0x1000 : { *(.text) } \ | ||
| 109 | // RUN: .plt 0x2000 : { *(.plt) *(.plt.*) } \ | ||
| 110 | // RUN: .got.plt 0x1100000 : { *(.got.plt) } \ | ||
| 111 | // RUN: }" > %t.script | ||
| 112 | // 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 %s | ||
| 114 | // RUN: llvm-readobj -s -r %t4 | FileCheck --check-prefix=DSORELHIGH %s | ||
| 115 | |||
| 116 | // CHECKHIGH: Disassembly of section .text: | ||
| 117 | // CHECKHIGH-NEXT: func1: | ||
| 118 | // CHECKHIGH-NEXT: 1000: 1e ff 2f e1 bx lr | ||
| 119 | // CHECKHIGH: func2: | ||
| 120 | // CHECKHIGH-NEXT: 1004: 1e ff 2f e1 bx lr | ||
| 121 | // CHECKHIGH: func3: | ||
| 122 | // CHECKHIGH-NEXT: 1008: 1e ff 2f e1 bx lr | ||
| 123 | // CHECKHIGH: _start: | ||
| 124 | // CHECKHIGH-NEXT: 100c: 03 04 00 ea b #4108 <$a> | ||
| 125 | // CHECKHIGH-NEXT: 1010: 06 04 00 eb bl #4120 <$a> | ||
| 126 | // CHECKHIGH-NEXT: 1014: 09 04 00 0a beq #4132 <$a> | ||
| 127 | // CHECKHIGH-NEXT: Disassembly of section .plt: | ||
| 128 | // CHECKHIGH-NEXT: $a: | ||
| 129 | // CHECKHIGH-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]! | ||
| 130 | // CHECKHIGH-NEXT: 2004: 10 e6 8f e2 add lr, pc, #16, #12 | ||
| 131 | // CHECKHIGH-NEXT: 2008: fd ea 8e e2 add lr, lr, #1036288 | ||
| 132 | // CHECKHIGH-NEXT: 200c: fc ff be e5 ldr pc, [lr, #4092]! | ||
| 133 | // CHECKHIGH: $d: | ||
| 134 | // CHECKHIGH-NEXT: 2010: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 135 | // CHECKHIGH-NEXT: 2014: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 136 | // CHECKHIGH-NEXT: 2018: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 137 | // CHECKHIGH-NEXT: 201c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 138 | // CHECKHIGH: $a: | ||
| 139 | // CHECKHIGH-NEXT: 2020: 10 c6 8f e2 add r12, pc, #16, #12 | ||
| 140 | // CHECKHIGH-NEXT: 2024: fd ca 8c e2 add r12, r12, #1036288 | ||
| 141 | // CHECKHIGH-NEXT: 2028: e4 ff bc e5 ldr pc, [r12, #4068]! | ||
| 142 | // CHECKHIGH: $d: | ||
| 143 | // CHECKHIGH-NEXT: 202c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 144 | // CHECKHIGH: $a: | ||
| 145 | // CHECKHIGH-NEXT: 2030: 10 c6 8f e2 add r12, pc, #16, #12 | ||
| 146 | // CHECKHIGH-NEXT: 2034: fd ca 8c e2 add r12, r12, #1036288 | ||
| 147 | // CHECKHIGH-NEXT: 2038: d8 ff bc e5 ldr pc, [r12, #4056]! | ||
| 148 | // CHECKHIGH: $d: | ||
| 149 | // CHECKHIGH-NEXT: 203c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 150 | // CHECKHIGH: $a: | ||
| 151 | // CHECKHIGH-NEXT: 2040: 10 c6 8f e2 add r12, pc, #16, #12 | ||
| 152 | // CHECKHIGH-NEXT: 2044: fd ca 8c e2 add r12, r12, #1036288 | ||
| 153 | // CHECKHIGH-NEXT: 2048: cc ff bc e5 ldr pc, [r12, #4044]! | ||
| 154 | // CHECKHIGH: $d: | ||
| 155 | // CHECKHIGH-NEXT: 204c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 156 | |||
| 157 | // DSORELHIGH: Name: .got.plt | ||
| 158 | // DSORELHIGH-NEXT: Type: SHT_PROGBITS | ||
| 159 | // DSORELHIGH-NEXT: Flags [ | ||
| 160 | // DSORELHIGH-NEXT: SHF_ALLOC | ||
| 161 | // DSORELHIGH-NEXT: SHF_WRITE | ||
| 162 | // DSORELHIGH-NEXT: ] | ||
| 163 | // DSORELHIGH-NEXT: Address: 0x1100000 | ||
| 164 | // DSORELHIGH: Relocations [ | ||
| 165 | // DSORELHIGH-NEXT: Section (6) .rel.plt { | ||
| 166 | // DSORELHIGH-NEXT: 0x110000C R_ARM_JUMP_SLOT func1 0x0 | ||
| 167 | // DSORELHIGH-NEXT: 0x1100010 R_ARM_JUMP_SLOT func2 0x0 | ||
| 168 | // DSORELHIGH-NEXT: 0x1100014 R_ARM_JUMP_SLOT func3 0x0 | ||
| 169 | |||
| 170 | // Test a very large separation between the .plt and .got.plt so we must use | ||
| 171 | // large plt entries that do not have any range restriction. | ||
| 172 | // RUN: echo "SECTIONS { \ | ||
| 173 | // RUN: .text 0x1000 : { *(.text) } \ | ||
| 174 | // RUN: .plt 0x2000 : { *(.plt) *(.plt.*) } \ | ||
| 175 | // RUN: .got.plt 0x11111100 : { *(.got.plt) } \ | ||
| 176 | // RUN: }" > %t2.script | ||
| 177 | // 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 %s | ||
| 179 | // RUN: llvm-readobj -s -r %t5 | FileCheck --check-prefix=DSORELLONG %s | ||
| 180 | |||
| 181 | // CHECKLONG: Disassembly of section .text: | ||
| 182 | // CHECKLONG-NEXT: func1: | ||
| 183 | // CHECKLONG-NEXT: 1000: 1e ff 2f e1 bx lr | ||
| 184 | // CHECKLONG: func2: | ||
| 185 | // CHECKLONG-NEXT: 1004: 1e ff 2f e1 bx lr | ||
| 186 | // CHECKLONG: func3: | ||
| 187 | // CHECKLONG-NEXT: 1008: 1e ff 2f e1 bx lr | ||
| 188 | // CHECKLONG: _start: | ||
| 189 | // CHECKLONG-NEXT: 100c: 03 04 00 ea b #4108 <$a> | ||
| 190 | // CHECKLONG-NEXT: 1010: 06 04 00 eb bl #4120 <$a> | ||
| 191 | // CHECKLONG-NEXT: 1014: 09 04 00 0a beq #4132 <$a> | ||
| 192 | // CHECKLONG-NEXT: Disassembly of section .plt: | ||
| 193 | // CHECKLONG-NEXT: $a: | ||
| 194 | // CHECKLONG-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]! | ||
| 195 | // CHECKLONG-NEXT: 2004: 04 e0 9f e5 ldr lr, [pc, #4] | ||
| 196 | // CHECKLONG-NEXT: 2008: 0e e0 8f e0 add lr, pc, lr | ||
| 197 | // CHECKLONG-NEXT: 200c: 08 f0 be e5 ldr pc, [lr, #8]! | ||
| 198 | // CHECKLONG: $d: | ||
| 199 | // CHECKLONG-NEXT: 2010: f0 f0 10 11 .word 0x1110f0f0 | ||
| 200 | // CHECKLONG-NEXT: 2014: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 201 | // CHECKLONG-NEXT: 2018: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 202 | // CHECKLONG-NEXT: 201c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 203 | // CHECKLONG: $a: | ||
| 204 | // CHECKLONG-NEXT: 2020: 04 c0 9f e5 ldr r12, [pc, #4] | ||
| 205 | // CHECKLONG-NEXT: 2024: 0f c0 8c e0 add r12, r12, pc | ||
| 206 | // CHECKLONG-NEXT: 2028: 00 f0 9c e5 ldr pc, [r12] | ||
| 207 | // CHECKLONG: $d: | ||
| 208 | // CHECKLONG-NEXT: 202c: e0 f0 10 11 .word 0x1110f0e0 | ||
| 209 | // CHECKLONG: $a: | ||
| 210 | // CHECKLONG-NEXT: 2030: 04 c0 9f e5 ldr r12, [pc, #4] | ||
| 211 | // CHECKLONG-NEXT: 2034: 0f c0 8c e0 add r12, r12, pc | ||
| 212 | // CHECKLONG-NEXT: 2038: 00 f0 9c e5 ldr pc, [r12] | ||
| 213 | // CHECKLONG: $d: | ||
| 214 | // CHECKLONG-NEXT: 203c: d4 f0 10 11 .word 0x1110f0d4 | ||
| 215 | // CHECKLONG: $a: | ||
| 216 | // CHECKLONG-NEXT: 2040: 04 c0 9f e5 ldr r12, [pc, #4] | ||
| 217 | // CHECKLONG-NEXT: 2044: 0f c0 8c e0 add r12, r12, pc | ||
| 218 | // CHECKLONG-NEXT: 2048: 00 f0 9c e5 ldr pc, [r12] | ||
| 219 | // CHECKLONG: $d: | ||
| 220 | // CHECKLONG-NEXT: 204c: c8 f0 10 11 .word 0x1110f0c8 | ||
| 221 | |||
| 222 | // DSORELLONG: Name: .got.plt | ||
| 223 | // DSORELLONG-NEXT: Type: SHT_PROGBITS | ||
| 224 | // DSORELLONG-NEXT: Flags [ | ||
| 225 | // DSORELLONG-NEXT: SHF_ALLOC | ||
| 226 | // DSORELLONG-NEXT: SHF_WRITE | ||
| 227 | // DSORELLONG-NEXT: ] | ||
| 228 | // DSORELLONG-NEXT: Address: 0x11111100 | ||
| 229 | // DSORELLONG: Relocations [ | ||
| 230 | // DSORELLONG-NEXT: Section (6) .rel.plt { | ||
| 231 | // DSORELLONG-NEXT: 0x1111110C R_ARM_JUMP_SLOT func1 0x0 | ||
| 232 | // DSORELLONG-NEXT: 0x11111110 R_ARM_JUMP_SLOT func2 0x0 | ||
| 233 | // DSORELLONG-NEXT: 0x11111114 R_ARM_JUMP_SLOT func3 0x0 | ||
| 234 | |||
| 235 | // Test a separation between the .plt and .got.plt that is part in range of | ||
| 236 | // short table entries and part needing long entries. We use the long entries | ||
| 237 | // only when we need to. | ||
| 238 | // RUN: echo "SECTIONS { \ | ||
| 239 | // RUN: .text 0x1000 : { *(.text) } \ | ||
| 240 | // RUN: .plt 0x2000 : { *(.plt) *(.plt.*) } \ | ||
| 241 | // RUN: .got.plt 0x8002020 : { *(.got.plt) } \ | ||
| 242 | // RUN: }" > %t3.script | ||
| 243 | // 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 %s | ||
| 245 | // RUN: llvm-readobj -s -r %t6 | FileCheck --check-prefix=DSORELMIX %s | ||
| 246 | |||
| 247 | // CHECKMIX: Disassembly of section .text: | ||
| 248 | // CHECKMIX-NEXT: func1: | ||
| 249 | // CHECKMIX-NEXT: 1000: 1e ff 2f e1 bx lr | ||
| 250 | // CHECKMIX: func2: | ||
| 251 | // CHECKMIX-NEXT: 1004: 1e ff 2f e1 bx lr | ||
| 252 | // CHECKMIX: func3: | ||
| 253 | // CHECKMIX-NEXT: 1008: 1e ff 2f e1 bx lr | ||
| 254 | // CHECKMIX: _start: | ||
| 255 | // CHECKMIX-NEXT: 100c: 03 04 00 ea b #4108 <$a> | ||
| 256 | // CHECKMIX-NEXT: 1010: 06 04 00 eb bl #4120 <$a> | ||
| 257 | // CHECKMIX-NEXT: 1014: 09 04 00 0a beq #4132 <$a> | ||
| 258 | // CHECKMIX-NEXT: Disassembly of section .plt: | ||
| 259 | // CHECKMIX-NEXT: $a: | ||
| 260 | // CHECKMIX-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]! | ||
| 261 | // CHECKMIX-NEXT: 2004: 04 e0 9f e5 ldr lr, [pc, #4] | ||
| 262 | // CHECKMIX-NEXT: 2008: 0e e0 8f e0 add lr, pc, lr | ||
| 263 | // CHECKMIX-NEXT: 200c: 08 f0 be e5 ldr pc, [lr, #8]! | ||
| 264 | // CHECKMIX: $d: | ||
| 265 | // CHECKMIX-NEXT: 2010: 10 00 00 08 .word 0x08000010 | ||
| 266 | // CHECKMIX-NEXT: 2014: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 267 | // CHECKMIX-NEXT: 2018: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 268 | // CHECKMIX-NEXT: 201c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 269 | // CHECKMIX: $a: | ||
| 270 | // CHECKMIX-NEXT: 2020: 04 c0 9f e5 ldr r12, [pc, #4] | ||
| 271 | // CHECKMIX-NEXT: 2024: 0f c0 8c e0 add r12, r12, pc | ||
| 272 | // CHECKMIX-NEXT: 2028: 00 f0 9c e5 ldr pc, [r12] | ||
| 273 | // CHECKMIX: $d: | ||
| 274 | // CHECKMIX-NEXT: 202c: 00 00 00 08 .word 0x08000000 | ||
| 275 | // CHECKMIX: $a: | ||
| 276 | // CHECKMIX-NEXT: 2030: 7f c6 8f e2 add r12, pc, #133169152 | ||
| 277 | // CHECKMIX-NEXT: 2034: ff ca 8c e2 add r12, r12, #1044480 | ||
| 278 | // CHECKMIX-NEXT: 2038: f8 ff bc e5 ldr pc, [r12, #4088]! | ||
| 279 | // CHECKMIX: $d: | ||
| 280 | // CHECKMIX-NEXT: 203c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 281 | // CHECKMIX: $a: | ||
| 282 | // CHECKMIX-NEXT: 2040: 7f c6 8f e2 add r12, pc, #133169152 | ||
| 283 | // CHECKMIX-NEXT: 2044: ff ca 8c e2 add r12, r12, #1044480 | ||
| 284 | // CHECKMIX-NEXT: 2048: ec ff bc e5 ldr pc, [r12, #4076]! | ||
| 285 | // CHECKMIX: $d: | ||
| 286 | // CHECKMIX-NEXT: 204c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 287 | |||
| 288 | // DSORELMIX: Name: .got.plt | ||
| 289 | // DSORELMIX-NEXT: Type: SHT_PROGBITS | ||
| 290 | // DSORELMIX-NEXT: Flags [ | ||
| 291 | // DSORELMIX-NEXT: SHF_ALLOC | ||
| 292 | // DSORELMIX-NEXT: SHF_WRITE | ||
| 293 | // DSORELMIX-NEXT: ] | ||
| 294 | // DSORELMIX-NEXT: Address: 0x8002020 | ||
| 295 | // DSORELMIX: Section (6) .rel.plt { | ||
| 296 | // DSORELMIX-NEXT: 0x800202C R_ARM_JUMP_SLOT func1 0x0 | ||
| 297 | // DSORELMIX-NEXT: 0x8002030 R_ARM_JUMP_SLOT func2 0x0 | ||
| 298 | // DSORELMIX-NEXT: 0x8002034 R_ARM_JUMP_SLOT func3 0x0 |
deps/lld/test/ELF/arm-static-defines.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t |
| 2 | // RUN: ld.lld %t --static -o %t2 2>&1 | 2 | // RUN: ld.lld --no-merge-exidx-entries %t --static -o %t2 2>&1 |
| 3 | // RUN: llvm-readobj --symbols %t2 | FileCheck %s | 3 | // RUN: llvm-readobj --symbols %t2 | FileCheck %s |
| 4 | // REQUIRES: arm | 4 | // REQUIRES: arm |
| 5 | 5 |
deps/lld/test/ELF/arm-thumb-branch-error.s deleted-19| ... | @@ -1,19 +0,0 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar | ||
| 3 | // RUN: not ld.lld %t %tfar -o %t2 2>&1 | FileCheck %s | ||
| 4 | // REQUIRES: arm | ||
| 5 | .syntax unified | ||
| 6 | .section .text, "ax",%progbits | ||
| 7 | .globl _start | ||
| 8 | .balign 0x10000 | ||
| 9 | .type _start,%function | ||
| 10 | _start: | ||
| 11 | // address of too_far symbols are just out of range of ARM branch with | ||
| 12 | // 26-bit immediate field and an addend of -8 | ||
| 13 | bl too_far1 | ||
| 14 | b too_far2 | ||
| 15 | beq.w too_far3 | ||
| 16 | |||
| 17 | // CHECK: R_ARM_THM_CALL out of range | ||
| 18 | // CHECK-NEXT: R_ARM_THM_JUMP24 out of range | ||
| 19 | // CHECK-NEXT: R_ARM_THM_JUMP19 out of range | ||
deps/lld/test/ELF/arm-thumb-branch-rangethunk.s created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar | ||
| 3 | // RUN: ld.lld %t %tfar -o %t2 2>&1 | ||
| 4 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | ||
| 5 | // REQUIRES: arm | ||
| 6 | .syntax unified | ||
| 7 | .thumb | ||
| 8 | .section .text, "ax",%progbits | ||
| 9 | .globl _start | ||
| 10 | .balign 0x10000 | ||
| 11 | .type _start,%function | ||
| 12 | _start: | ||
| 13 | // address of too_far symbols are just out of range of ARM branch with | ||
| 14 | // 26-bit immediate field and an addend of -8 | ||
| 15 | bl too_far1 | ||
| 16 | b too_far2 | ||
| 17 | beq.w too_far3 | ||
| 18 | |||
| 19 | // CHECK: Disassembly of section .text: | ||
| 20 | // CHECK-NEXT: _start: | ||
| 21 | // 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: 20008: 00 f0 0a 80 beq.w #20 <__Thumbv7ABSLongThunk_too_far3> | ||
| 24 | // CHECK: __Thumbv7ABSLongThunk_too_far1: | ||
| 25 | // CHECK-NEXT: 2000c: 40 f2 05 0c movw r12, #5 | ||
| 26 | // CHECK-NEXT: 20010: c0 f2 02 1c movt r12, #258 | ||
| 27 | // CHECK-NEXT: 20014: 60 47 bx r12 | ||
| 28 | // CHECK: __Thumbv7ABSLongThunk_too_far2: | ||
| 29 | // CHECK-NEXT: 20016: 40 f2 09 0c movw r12, #9 | ||
| 30 | // CHECK-NEXT: 2001a: c0 f2 02 1c movt r12, #258 | ||
| 31 | // CHECK-NEXT: 2001e: 60 47 bx r12 | ||
| 32 | // CHECK: __Thumbv7ABSLongThunk_too_far3: | ||
| 33 | // CHECK-NEXT: 20020: 40 f2 0d 0c movw r12, #13 | ||
| 34 | // CHECK-NEXT: 20024: c0 f2 12 0c movt r12, #18 | ||
| 35 | // CHECK-NEXT: 20028: 60 47 bx r12 | ||
| 36 | // CHECK-NEXT: 2002a: 00 00 movs r0, r0 | ||
deps/lld/test/ELF/arm-thumb-condbranch-thunk.s created+117| ... | @@ -0,0 +1,117 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: ld.lld %t -o %t2 2>&1 | ||
| 4 | // The output file is large, most of it zeroes. We dissassemble only the | ||
| 5 | // parts we need to speed up the test and avoid a large output file | ||
| 6 | // RUN: llvm-objdump -d %t2 -start-address=524288 -stop-address=524316 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 7 | // RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048584 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 8 | // RUN: llvm-objdump -d %t2 -start-address=1572864 -stop-address=1572872 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s | ||
| 9 | // RUN: llvm-objdump -d %t2 -start-address=5242884 -stop-address=5242894 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s | ||
| 10 | // RUN: llvm-objdump -d %t2 -start-address=5767168 -stop-address=5767174 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK5 %s | ||
| 11 | // RUN: llvm-objdump -d %t2 -start-address=16777220 -stop-address=16777240 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s | ||
| 12 | // RUN: llvm-objdump -d %t2 -start-address=17825792 -stop-address=17825798 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s | ||
| 13 | // Test Range extension Thunks for the Thumb conditional branch instruction. | ||
| 14 | // This instruction only has a range of 1Mb whereas all the other Thumb wide | ||
| 15 | // Branch instructions have 16Mb range. We still place our pre-created Thunk | ||
| 16 | // Sections at 16Mb intervals as conditional branches to a target defined | ||
| 17 | // in a different section are rare. | ||
| 18 | .syntax unified | ||
| 19 | // Define a function aligned on a half megabyte boundary | ||
| 20 | .macro FUNCTION suff | ||
| 21 | .section .text.\suff\(), "ax", %progbits | ||
| 22 | .thumb | ||
| 23 | .balign 0x80000 | ||
| 24 | .globl tfunc\suff\() | ||
| 25 | .type tfunc\suff\(), %function | ||
| 26 | tfunc\suff\(): | ||
| 27 | bx lr | ||
| 28 | .endm | ||
| 29 | |||
| 30 | .globl _start | ||
| 31 | _start: | ||
| 32 | FUNCTION 00 | ||
| 33 | // Long Range Thunk needed for 16Mb range branch, can reach pre-created Thunk | ||
| 34 | // Section | ||
| 35 | bl tfunc33 | ||
| 36 | // CHECK1: Disassembly of section .text: | ||
| 37 | // CHECK1-NEXT: tfunc00: | ||
| 38 | // CHECK1-NEXT: 80000: 70 47 bx lr | ||
| 39 | // CHECK1-NEXT: 80002: 7f f3 ff d7 bl #16252926 | ||
| 40 | // CHECK1: __Thumbv7ABSLongThunk_tfunc05: | ||
| 41 | // CHECK1-NEXT: 80008: 40 f2 01 0c movw r12, #1 | ||
| 42 | // CHECK1-NEXT: 8000c: c0 f2 30 0c movt r12, #48 | ||
| 43 | // CHECK1-NEXT: 80010: 60 47 bx r12 | ||
| 44 | // CHECK1: __Thumbv7ABSLongThunk_tfunc00: | ||
| 45 | // CHECK1-NEXT: 80012: 40 f2 01 0c movw r12, #1 | ||
| 46 | // CHECK1-NEXT: 80016: c0 f2 08 0c movt r12, #8 | ||
| 47 | // CHECK1-NEXT: 8001a: 60 47 bx r12 | ||
| 48 | FUNCTION 01 | ||
| 49 | // tfunc02 is within range of tfunc02 | ||
| 50 | beq.w tfunc02 | ||
| 51 | // tfunc05 is out of range, and we can't reach the pre-created Thunk Section | ||
| 52 | // create a new one. | ||
| 53 | bne.w tfunc05 | ||
| 54 | // CHECK2: tfunc01: | ||
| 55 | // CHECK2-NEXT: 100000: 70 47 bx lr | ||
| 56 | // CHECK2-NEXT: 100002: 3f f0 fd a7 beq.w #524282 <tfunc02> | ||
| 57 | // CHECK2-NEXT: 100006: 7f f4 ff a7 bne.w #-524290 <__Thumbv7ABSLongThunk_tfunc05> | ||
| 58 | FUNCTION 02 | ||
| 59 | // We can reach the Thunk Section created for bne.w tfunc05 | ||
| 60 | bne.w tfunc05 | ||
| 61 | beq.w tfunc00 | ||
| 62 | // CHECK3: 180000: 70 47 bx lr | ||
| 63 | // CHECK3-NEXT: 180002: 40 f4 01 80 bne.w #-1048574 <__Thumbv7ABSLongThunk_tfunc05> | ||
| 64 | // CHECK3-NEXT: 180006: 00 f4 04 80 beq.w #-1048568 <__Thumbv7ABSLongThunk_tfunc00> | ||
| 65 | FUNCTION 03 | ||
| 66 | FUNCTION 04 | ||
| 67 | FUNCTION 05 | ||
| 68 | FUNCTION 06 | ||
| 69 | FUNCTION 07 | ||
| 70 | FUNCTION 08 | ||
| 71 | FUNCTION 09 | ||
| 72 | // CHECK4: __Thumbv7ABSLongThunk_tfunc03: | ||
| 73 | // CHECK4-NEXT: 500004: 40 f2 01 0c movw r12, #1 | ||
| 74 | // CHECK4-NEXT: 500008: c0 f2 20 0c movt r12, #32 | ||
| 75 | // CHECK4-NEXT: 50000c: 60 47 bx r12 | ||
| 76 | FUNCTION 10 | ||
| 77 | // We can't reach any Thunk Section, create a new one | ||
| 78 | beq.w tfunc03 | ||
| 79 | // CHECK5: tfunc10: | ||
| 80 | // CHECK5-NEXT: 580000: 70 47 bx lr | ||
| 81 | // CHECK5-NEXT: 580002: 3f f4 ff a7 beq.w #-524290 <__Thumbv7ABSLongThunk_tfunc03> | ||
| 82 | FUNCTION 11 | ||
| 83 | FUNCTION 12 | ||
| 84 | FUNCTION 13 | ||
| 85 | FUNCTION 14 | ||
| 86 | FUNCTION 15 | ||
| 87 | FUNCTION 16 | ||
| 88 | FUNCTION 17 | ||
| 89 | FUNCTION 18 | ||
| 90 | FUNCTION 19 | ||
| 91 | FUNCTION 20 | ||
| 92 | FUNCTION 21 | ||
| 93 | FUNCTION 22 | ||
| 94 | FUNCTION 23 | ||
| 95 | FUNCTION 24 | ||
| 96 | FUNCTION 25 | ||
| 97 | FUNCTION 26 | ||
| 98 | FUNCTION 27 | ||
| 99 | FUNCTION 28 | ||
| 100 | FUNCTION 29 | ||
| 101 | FUNCTION 30 | ||
| 102 | FUNCTION 31 | ||
| 103 | // CHECK6: __Thumbv7ABSLongThunk_tfunc33: | ||
| 104 | // CHECK6-NEXT: 1000004: 40 f2 01 0c movw r12, #1 | ||
| 105 | // CHECK6-NEXT: 1000008: c0 f2 10 1c movt r12, #272 | ||
| 106 | // CHECK6-NEXT: 100000c: 60 47 bx r12 | ||
| 107 | // CHECK6: __Thumbv7ABSLongThunk_tfunc00: | ||
| 108 | // CHECK6-NEXT: 100000e: 40 f2 01 0c movw r12, #1 | ||
| 109 | // CHECK6-NEXT: 1000012: c0 f2 08 0c movt r12, #8 | ||
| 110 | // CHECK6-NEXT: 1000016: 60 47 bx r12 | ||
| 111 | FUNCTION 32 | ||
| 112 | FUNCTION 33 | ||
| 113 | // We should be able to reach an existing ThunkSection. | ||
| 114 | b.w tfunc00 | ||
| 115 | // CHECK7: tfunc33: | ||
| 116 | // CHECK7-NEXT: 1100000: 70 47 bx lr | ||
| 117 | // CHECK7-NEXT: 1100002: 00 f7 04 b8 b.w #-1048568 <__Thumbv7ABSLongThunk_tfunc00> | ||
deps/lld/test/ELF/arm-thumb-interwork-shared.s+20-17| ... | @@ -19,34 +19,37 @@ sym1: | ... | @@ -19,34 +19,37 @@ sym1: |
| 19 | // CHECK-NEXT: 1000: 00 f0 02 b8 b.w #4 <__ThumbV7PILongThunk_elsewhere> | 19 | // 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> | 20 | // CHECK-NEXT: 1004: 00 f0 06 b8 b.w #12 <__ThumbV7PILongThunk_weakref> |
| 21 | // CHECK: __ThumbV7PILongThunk_elsewhere: | 21 | // CHECK: __ThumbV7PILongThunk_elsewhere: |
| 22 | // CHECK-NEXT: 1008: 40 f2 20 0c movw r12, #32 | 22 | // CHECK-NEXT: 1008: 40 f2 2c 0c movw r12, #44 |
| 23 | // CHECK-NEXT: 100c: c0 f2 00 0c movt r12, #0 | 23 | // CHECK-NEXT: 100c: c0 f2 00 0c movt r12, #0 |
| 24 | // CHECK-NEXT: 1010: fc 44 add r12, pc | 24 | // CHECK-NEXT: 1010: fc 44 add r12, pc |
| 25 | // CHECK-NEXT: 1012: 60 47 bx r12 | 25 | // CHECK-NEXT: 1012: 60 47 bx r12 |
| 26 | |||
| 27 | // CHECK: __ThumbV7PILongThunk_weakref: | 26 | // CHECK: __ThumbV7PILongThunk_weakref: |
| 28 | // CHECK-NEXT: 1014: 40 f2 24 0c movw r12, #36 | 27 | // CHECK-NEXT: 1014: 40 f2 30 0c movw r12, #48 |
| 29 | // CHECK-NEXT: 1018: c0 f2 00 0c movt r12, #0 | 28 | // CHECK-NEXT: 1018: c0 f2 00 0c movt r12, #0 |
| 30 | // CHECK-NEXT: 101c: fc 44 add r12, pc | 29 | // CHECK-NEXT: 101c: fc 44 add r12, pc |
| 31 | // CHECK-NEXT: 101e: 60 47 bx r12 | 30 | // CHECK-NEXT: 101e: 60 47 bx r12 |
| 32 | 31 | ||
| 33 | // PLT: Disassembly of section .plt: | 32 | // PLT: Disassembly of section .plt: |
| 34 | // PLT: $a: | 33 | // PLT-NEXT: $a: |
| 35 | // PLT-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]! | 34 | // PLT-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]! |
| 36 | // PLT-NEXT: 1024: 04 e0 9f e5 ldr lr, [pc, #4] | 35 | // PLT-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #12 |
| 37 | // PLT-NEXT: 1028: 0e e0 8f e0 add lr, pc, lr | 36 | // PLT-NEXT: 1028: 00 ea 8e e2 add lr, lr, #0, #20 |
| 38 | // PLT-NEXT: 102c: 08 f0 be e5 ldr pc, [lr, #8]! | 37 | // PLT-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]! |
| 39 | // PLT: $d: | 38 | // PLT: $d: |
| 40 | // PLT-NEXT: 1030: d0 0f 00 00 .word 0x00000fd0 | 39 | // PLT-NEXT: 1030: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 40 | // PLT-NEXT: 1034: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 41 | // PLT-NEXT: 1038: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 42 | // PLT-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 41 | // PLT: $a: | 43 | // PLT: $a: |
| 42 | // PLT-NEXT: 1034: 04 c0 9f e5 ldr r12, [pc, #4] | 44 | // PLT-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #12 |
| 43 | // PLT-NEXT: 1038: 0f c0 8c e0 add r12, r12, pc | 45 | // PLT-NEXT: 1044: 00 ca 8c e2 add r12, r12, #0, #20 |
| 44 | // PLT-NEXT: 103c: 00 f0 9c e5 ldr pc, [r12] | 46 | // PLT-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]! |
| 45 | // PLT: $d: | 47 | // PLT: $d: |
| 46 | // PLT-NEXT: 1040: cc 0f 00 00 .word 0x00000fcc | 48 | // PLT-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 47 | // PLT: $a: | 49 | // PLT: $a: |
| 48 | // PLT-NEXT: 1044: 04 c0 9f e5 ldr r12, [pc, #4] | 50 | // PLT-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #12 |
| 49 | // PLT-NEXT: 1048: 0f c0 8c e0 add r12, r12, pc | 51 | // PLT-NEXT: 1054: 00 ca 8c e2 add r12, r12, #0, #20 |
| 50 | // PLT-NEXT: 104c: 00 f0 9c e5 ldr pc, [r12] | 52 | // PLT-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]! |
| 51 | // PLT: $d: | 53 | // PLT: $d: |
| 52 | // PLT-NEXT: 1050: c0 0f 00 00 .word 0x00000fc0 | 54 | // PLT-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 55 |
deps/lld/test/ELF/arm-thumb-mix-range-thunk-os.s created+195| ... | @@ -0,0 +1,195 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: ld.lld %t -o %t2 2>&1 | ||
| 4 | // The output file is large, most of it zeroes. We dissassemble only the | ||
| 5 | // parts we need to speed up the test and avoid a large output file | ||
| 6 | // RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048604 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 7 | // RUN: llvm-objdump -d %t2 -start-address=2097152 -stop-address=2097162 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 8 | // RUN: llvm-objdump -d %t2 -start-address=16777220 -stop-address=16777232 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s | ||
| 9 | // RUN: llvm-objdump -d %t2 -start-address=16777232 -stop-address=16777242 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s | ||
| 10 | // RUN: llvm-objdump -d %t2 -start-address=32505860 -stop-address=32505870 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK5 %s | ||
| 11 | // RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651590 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s | ||
| 12 | // RUN: llvm-objdump -d %t2 -start-address=36700160 -stop-address=36700168 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s | ||
| 13 | // RUN: llvm-objdump -d %t2 -start-address=48234500 -stop-address=48234512 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s | ||
| 14 | // RUN: llvm-objdump -d %t2 -start-address=63963140 -stop-address=63963160 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s | ||
| 15 | // RUN: llvm-objdump -d %t2 -start-address=68157440 -stop-address=68157452 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK10 %s | ||
| 16 | // RUN: llvm-objdump -d %t2 -start-address=69206016 -stop-address=69206024 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK11 %s | ||
| 17 | |||
| 18 | // Test the Range extension Thunks for ARM and Thumb when all the code is in a | ||
| 19 | // single OutputSection. The ARM branches and branch and link instructions | ||
| 20 | // have a range of 32Mb, the Thumb unconditional branch and | ||
| 21 | // branch and link instructions have . We create a series of Functions a | ||
| 22 | // megabyte apart. We expect range extension thunks to be created when a | ||
| 23 | // branch is out of range. Thunks will be reused whenever they are in range | ||
| 24 | .syntax unified | ||
| 25 | |||
| 26 | // Define a function aligned on a megabyte boundary | ||
| 27 | .macro ARMFUNCTION suff | ||
| 28 | .section .text.\suff\(), "ax", %progbits | ||
| 29 | .arm | ||
| 30 | .balign 0x100000 | ||
| 31 | .globl afunc\suff\() | ||
| 32 | .type afunc\suff\(), %function | ||
| 33 | afunc\suff\(): | ||
| 34 | bx lr | ||
| 35 | .endm | ||
| 36 | |||
| 37 | // Define a function aligned on a megabyte boundary | ||
| 38 | .macro THUMBFUNCTION suff | ||
| 39 | .section .text.\suff\(), "ax", %progbits | ||
| 40 | .thumb | ||
| 41 | .balign 0x100000 | ||
| 42 | .globl tfunc\suff\() | ||
| 43 | .type tfunc\suff\(), %function | ||
| 44 | tfunc\suff\(): | ||
| 45 | bx lr | ||
| 46 | .endm | ||
| 47 | |||
| 48 | .section .text, "ax", %progbits | ||
| 49 | .thumb | ||
| 50 | .globl _start | ||
| 51 | _start: | ||
| 52 | |||
| 53 | ARMFUNCTION 00 | ||
| 54 | // Expect ARM bl to be in range (can use blx to change state) | ||
| 55 | bl tfunc31 | ||
| 56 | // ARM b and beq are in range but need Thunk to change state to Thumb | ||
| 57 | b tfunc31 | ||
| 58 | beq tfunc31 | ||
| 59 | // afunc32 is out of range of ARM branch and branch and link | ||
| 60 | bl afunc32 | ||
| 61 | b afunc32 | ||
| 62 | bne afunc32 | ||
| 63 | // CHECK1: afunc00: | ||
| 64 | // CHECK1-NEXT: 100000: 1e ff 2f e1 bx lr | ||
| 65 | // CHECK1-NEXT: 100004: fd ff 7b fa blx #32505844 | ||
| 66 | // CHECK1-NEXT: 100008: fd ff 3b ea b #15728628 | ||
| 67 | // CHECK1-NEXT: 10000c: fc ff 3b 0a beq #15728624 | ||
| 68 | // CHECK1-NEXT: 100010: fa ff 7f eb bl #33554408 | ||
| 69 | // CHECK1-NEXT: 100014: f9 ff 7f ea b #33554404 | ||
| 70 | // CHECK1-NEXT: 100018: f8 ff 7f 1a bne #33554400 | ||
| 71 | THUMBFUNCTION 01 | ||
| 72 | // Expect Thumb bl to be in range (can use blx to change state) | ||
| 73 | bl afunc14 | ||
| 74 | // In range but need thunk to change state to Thumb | ||
| 75 | b.w afunc14 | ||
| 76 | // CHECK2: tfunc01: | ||
| 77 | // CHECK2-NEXT: 200000: 70 47 bx lr | ||
| 78 | // CHECK2-NEXT: 200002: ff f0 fe c7 blx #13631484 | ||
| 79 | // CHECK2-NEXT: 200006: 00 f2 03 90 b.w #14680070 <__Thumbv7ABSLongThunk_afunc14> | ||
| 80 | |||
| 81 | ARMFUNCTION 02 | ||
| 82 | THUMBFUNCTION 03 | ||
| 83 | ARMFUNCTION 04 | ||
| 84 | THUMBFUNCTION 05 | ||
| 85 | ARMFUNCTION 06 | ||
| 86 | THUMBFUNCTION 07 | ||
| 87 | ARMFUNCTION 08 | ||
| 88 | THUMBFUNCTION 09 | ||
| 89 | ARMFUNCTION 10 | ||
| 90 | THUMBFUNCTION 11 | ||
| 91 | ARMFUNCTION 12 | ||
| 92 | THUMBFUNCTION 13 | ||
| 93 | ARMFUNCTION 14 | ||
| 94 | // CHECK3: __ARMv7ABSLongThunk_tfunc31: | ||
| 95 | // CHECK3-NEXT: 1000004: 01 c0 00 e3 movw r12, #1 | ||
| 96 | // CHECK3-NEXT: 1000008: 00 c2 40 e3 movt r12, #512 | ||
| 97 | // CHECK3-NEXT: 100000c: 1c ff 2f e1 bx r12 | ||
| 98 | // CHECK4: __Thumbv7ABSLongThunk_afunc14: | ||
| 99 | // CHECK4-NEXT: 1000010: 40 f2 00 0c movw r12, #0 | ||
| 100 | // CHECK4-NEXT: 1000014: c0 f2 f0 0c movt r12, #240 | ||
| 101 | // CHECK4-NEXT: 1000018: 60 47 bx r12 | ||
| 102 | THUMBFUNCTION 15 | ||
| 103 | ARMFUNCTION 16 | ||
| 104 | THUMBFUNCTION 17 | ||
| 105 | ARMFUNCTION 18 | ||
| 106 | THUMBFUNCTION 19 | ||
| 107 | ARMFUNCTION 20 | ||
| 108 | THUMBFUNCTION 21 | ||
| 109 | ARMFUNCTION 22 | ||
| 110 | THUMBFUNCTION 23 | ||
| 111 | ARMFUNCTION 24 | ||
| 112 | THUMBFUNCTION 25 | ||
| 113 | ARMFUNCTION 26 | ||
| 114 | THUMBFUNCTION 27 | ||
| 115 | ARMFUNCTION 28 | ||
| 116 | THUMBFUNCTION 29 | ||
| 117 | ARMFUNCTION 30 | ||
| 118 | // Expect precreated Thunk Section here | ||
| 119 | // CHECK5: __Thumbv7ABSLongThunk_afunc00: | ||
| 120 | // CHECK5-NEXT: 1f00004: 40 f2 00 0c movw r12, #0 | ||
| 121 | // CHECK5-NEXT: 1f00008: c0 f2 10 0c movt r12, #16 | ||
| 122 | // CHECK5-NEXT: 1f0000c: 60 47 bx r12 | ||
| 123 | THUMBFUNCTION 31 | ||
| 124 | ARMFUNCTION 32 | ||
| 125 | THUMBFUNCTION 33 | ||
| 126 | // Out of range, can only reach closest Thunk Section | ||
| 127 | bl afunc00 | ||
| 128 | // CHECK6: tfunc33: | ||
| 129 | // CHECK6-NEXT: 2200000: 70 47 bx lr | ||
| 130 | // CHECK6-NEXT: 2200002: ff f4 ff ff bl #-3145730 | ||
| 131 | ARMFUNCTION 34 | ||
| 132 | // Out of range, can reach earlier Thunk Section | ||
| 133 | // CHECK7: afunc34: | ||
| 134 | // CHECK7-NEXT: 2300000: 1e ff 2f e1 bx lr | ||
| 135 | // CHECK7-NEXT: 2300004: fe ff ef fa blx #-4194312 <__Thumbv7ABSLongThunk_afunc00 | ||
| 136 | bl afunc00 | ||
| 137 | THUMBFUNCTION 35 | ||
| 138 | ARMFUNCTION 36 | ||
| 139 | THUMBFUNCTION 37 | ||
| 140 | ARMFUNCTION 38 | ||
| 141 | THUMBFUNCTION 39 | ||
| 142 | ARMFUNCTION 40 | ||
| 143 | THUMBFUNCTION 41 | ||
| 144 | ARMFUNCTION 42 | ||
| 145 | THUMBFUNCTION 43 | ||
| 146 | ARMFUNCTION 44 | ||
| 147 | THUMBFUNCTION 45 | ||
| 148 | // Expect precreated Thunk Section here | ||
| 149 | // CHECK8: __ARMv7ABSLongThunk_tfunc35: | ||
| 150 | // CHECK8-NEXT: 2e00004: 01 c0 00 e3 movw r12, #1 | ||
| 151 | // CHECK8-NEXT: 2e00008: 40 c2 40 e3 movt r12, #576 | ||
| 152 | // CHECK8-NEXT: 2e0000c: 1c ff 2f e1 bx r12 | ||
| 153 | ARMFUNCTION 46 | ||
| 154 | THUMBFUNCTION 47 | ||
| 155 | ARMFUNCTION 48 | ||
| 156 | THUMBFUNCTION 49 | ||
| 157 | ARMFUNCTION 50 | ||
| 158 | THUMBFUNCTION 51 | ||
| 159 | ARMFUNCTION 52 | ||
| 160 | THUMBFUNCTION 53 | ||
| 161 | ARMFUNCTION 54 | ||
| 162 | THUMBFUNCTION 55 | ||
| 163 | ARMFUNCTION 56 | ||
| 164 | THUMBFUNCTION 57 | ||
| 165 | ARMFUNCTION 58 | ||
| 166 | THUMBFUNCTION 59 | ||
| 167 | ARMFUNCTION 60 | ||
| 168 | // Expect precreated Thunk Section here | ||
| 169 | // CHECK9: __Thumbv7ABSLongThunk_afunc34: | ||
| 170 | // CHECK9-NEXT: 3d00004: 40 f2 00 0c movw r12, #0 | ||
| 171 | // CHECK9-NEXT: 3d00008: c0 f2 30 2c movt r12, #560 | ||
| 172 | // CHECK9-NEXT: 3d0000c: 60 47 bx r12 | ||
| 173 | // CHECK9: __Thumbv7ABSLongThunk_tfunc35: | ||
| 174 | // CHECK9-NEXT: 3d0000e: 40 f2 01 0c movw r12, #1 | ||
| 175 | // CHECK9-NEXT: 3d00012: c0 f2 40 2c movt r12, #576 | ||
| 176 | // CHECK9-NEXT: 3d00016: 60 47 bx r12 | ||
| 177 | THUMBFUNCTION 61 | ||
| 178 | ARMFUNCTION 62 | ||
| 179 | THUMBFUNCTION 63 | ||
| 180 | ARMFUNCTION 64 | ||
| 181 | // afunc34 is in range, as is tfunc35 but a branch needs a state change Thunk | ||
| 182 | bl afunc34 | ||
| 183 | b tfunc35 | ||
| 184 | // CHECK10: afunc64: | ||
| 185 | // CHECK10-NEXT: 4100000: 1e ff 2f e1 bx lr | ||
| 186 | // CHECK10-NEXT: 4100004: fd ff 87 eb bl #-31457292 <afunc34> | ||
| 187 | // CHECK10-NEXT: 4100008: fd ff b3 ea b #-19922956 <__ARMv7ABSLongThunk_tfunc35> | ||
| 188 | THUMBFUNCTION 65 | ||
| 189 | // afunc34 and tfunc35 are both out of range | ||
| 190 | bl afunc34 | ||
| 191 | bl tfunc35 | ||
| 192 | // CHECK11: tfunc65: | ||
| 193 | // CHECK11: 4200000: 70 47 bx lr | ||
| 194 | // CHECK11-NEXT: 4200002: ff f6 ff f7 bl #-5242882 | ||
| 195 | // CHECK11-NEXT: 4200006: 00 f7 02 f0 bl #-5242876 | ||
deps/lld/test/ELF/arm-thumb-no-undefined-thunk.s+1-1| ... | @@ -21,4 +21,4 @@ _start: | ... | @@ -21,4 +21,4 @@ _start: |
| 21 | // 69636 = 0x11004 = next instruction | 21 | // 69636 = 0x11004 = next instruction |
| 22 | // CHECK: 11000: {{.*}} bl #0 | 22 | // CHECK: 11000: {{.*}} bl #0 |
| 23 | // CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8> | 23 | // CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8> |
| 24 | // CHECK-NEXT: 11008: {{.*}} b.w #0 <_start+0xC> | 24 | // CHECK-NEXT: 11008: {{.*}} b.w #0 <_start+0xc> |
deps/lld/test/ELF/arm-thumb-plt-range-thunk-os.s created+92| ... | @@ -0,0 +1,92 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: ld.lld %t --shared -o %t.so | ||
| 4 | // The output file is large, most of it zeroes. We dissassemble only the | ||
| 5 | // parts we need to speed up the test and avoid a large output file | ||
| 6 | // RUN: llvm-objdump -d %t.so -start-address=8388608 -stop-address=8388624 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 7 | // RUN: llvm-objdump -d %t.so -start-address=16777216 -stop-address=16777256 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 8 | // RUN: llvm-objdump -d %t.so -start-address=25165824 -stop-address=25165828 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s | ||
| 9 | // RUN: llvm-objdump -d %t.so -start-address=25165828 -stop-address=25165924 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s | ||
| 10 | .syntax unified | ||
| 11 | .thumb | ||
| 12 | |||
| 13 | // Make sure that we generate a range extension thunk to a PLT entry | ||
| 14 | .section ".text.1", "ax", %progbits | ||
| 15 | .global sym1 | ||
| 16 | .global elsewhere | ||
| 17 | .type elsewhere, %function | ||
| 18 | .global preemptible | ||
| 19 | .type preemptible, %function | ||
| 20 | .global far_preemptible | ||
| 21 | .type far_preemptible, %function | ||
| 22 | sym1: | ||
| 23 | bl elsewhere | ||
| 24 | bl preemptible | ||
| 25 | bx lr | ||
| 26 | preemptible: | ||
| 27 | bl far_preemptible | ||
| 28 | bx lr | ||
| 29 | // CHECK1: Disassembly of section .text: | ||
| 30 | // CHECK1-NEXT: sym1: | ||
| 31 | // CHECK1-NEXT: 800000: 00 f0 00 d8 bl #8388608 | ||
| 32 | // CHECK1-NEXT: 800004: 00 f0 04 d8 bl #8388616 | ||
| 33 | // CHECK1-NEXT: 800008: 70 47 bx lr | ||
| 34 | // CHECK1: preemptible: | ||
| 35 | // CHECK1-NEXT: 80000a: 00 f0 07 d8 bl #8388622 | ||
| 36 | // CHECK1-NEXT: 80000e: 70 47 bx lr | ||
| 37 | |||
| 38 | .section .text.2, "ax", %progbits | ||
| 39 | .balign 0x0800000 | ||
| 40 | bx lr | ||
| 41 | // CHECK2: __ThumbV7PILongThunk_elsewhere: | ||
| 42 | // CHECK2-NEXT: 1000004: 40 f2 20 0c movw r12, #32 | ||
| 43 | // CHECK2-NEXT: 1000008: c0 f2 80 0c movt r12, #128 | ||
| 44 | // CHECK2-NEXT: 100000c: fc 44 add r12, pc | ||
| 45 | // CHECK2-NEXT: 100000e: 60 47 bx r12 | ||
| 46 | // CHECK2: __ThumbV7PILongThunk_preemptible: | ||
| 47 | // CHECK2-NEXT: 1000010: 40 f2 24 0c movw r12, #36 | ||
| 48 | // CHECK2-NEXT: 1000014: c0 f2 80 0c movt r12, #128 | ||
| 49 | // CHECK2-NEXT: 1000018: fc 44 add r12, pc | ||
| 50 | // CHECK2-NEXT: 100001a: 60 47 bx r12 | ||
| 51 | // CHECK2: __ThumbV7PILongThunk_far_preemptible: | ||
| 52 | // CHECK2-NEXT: 100001c: 40 f2 28 0c movw r12, #40 | ||
| 53 | // CHECK2-NEXT: 1000020: c0 f2 80 0c movt r12, #128 | ||
| 54 | // CHECK2-NEXT: 1000024: fc 44 add r12, pc | ||
| 55 | // CHECK2-NEXT: 1000026: 60 47 bx r12 | ||
| 56 | |||
| 57 | .section .text.3, "ax", %progbits | ||
| 58 | .balign 0x0800000 | ||
| 59 | far_preemptible: | ||
| 60 | bl elsewhere | ||
| 61 | // CHECK3: far_preemptible: | ||
| 62 | // CHECK3: 1800000: 00 f0 16 e8 blx #44 | ||
| 63 | |||
| 64 | // CHECK4: Disassembly of section .plt: | ||
| 65 | // CHECK4-NEXT: $a: | ||
| 66 | // CHECK4-NEXT: 1800010:	04 e0 2d e5 	str	lr, [sp, #-4]! | ||
| 67 | // CHECK4-NEXT: 1800014:	00 e6 8f e2 	add	lr, pc, #0, #12 | ||
| 68 | // CHECK4-NEXT: 1800018:	00 ea 8e e2 	add	lr, lr, #0, #20 | ||
| 69 | // CHECK4-NEXT: 180001c:	ec ff be e5 	ldr	pc, [lr, #4076]! | ||
| 70 | // CHECK4: $d: | ||
| 71 | // CHECK4-NEXT: 1800020:	d4 d4 d4 d4 	.word	0xd4d4d4d4 | ||
| 72 | // CHECK4-NEXT: 1800024:	d4 d4 d4 d4 	.word	0xd4d4d4d4 | ||
| 73 | // CHECK4-NEXT: 1800028:	d4 d4 d4 d4 	.word	0xd4d4d4d4 | ||
| 74 | // CHECK4-NEXT: 180002c:	d4 d4 d4 d4 	.word	0xd4d4d4d4 | ||
| 75 | // CHECK4: $a: | ||
| 76 | // CHECK4-NEXT: 1800030:	00 c6 8f e2 	add	r12, pc, #0, #12 | ||
| 77 | // CHECK4-NEXT: 1800034:	00 ca 8c e2 	add	r12, r12, #0, #20 | ||
| 78 | // CHECK4-NEXT: 1800038:	d4 ff bc e5 	ldr	pc, [r12, #4052]! | ||
| 79 | // CHECK4: $d: | ||
| 80 | // CHECK4-NEXT: 180003c:	d4 d4 d4 d4 	.word	0xd4d4d4d4 | ||
| 81 | // CHECK4: $a: | ||
| 82 | // CHECK4-NEXT: 1800040:	00 c6 8f e2 	add	r12, pc, #0, #12 | ||
| 83 | // CHECK4-NEXT: 1800044:	00 ca 8c e2 	add	r12, r12, #0, #20 | ||
| 84 | // CHECK4-NEXT: 1800048:	c8 ff bc e5 	ldr	pc, [r12, #4040]! | ||
| 85 | // CHECK4: $d: | ||
| 86 | // CHECK4-NEXT: 180004c:	d4 d4 d4 d4 	.word	0xd4d4d4d4 | ||
| 87 | // CHECK4: $a: | ||
| 88 | // CHECK4-NEXT: 1800050:	00 c6 8f e2 	add	r12, pc, #0, #12 | ||
| 89 | // CHECK4-NEXT: 1800054:	00 ca 8c e2 	add	r12, r12, #0, #20 | ||
| 90 | // CHECK4-NEXT: 1800058:	bc ff bc e5 	ldr	pc, [r12, #4028]! | ||
| 91 | // CHECK4: $d: | ||
| 92 | // CHECK4-NEXT: 180005c:	d4 d4 d4 d4 	.word	0xd4d4d4d4 | ||
deps/lld/test/ELF/arm-thumb-plt-reloc.s+37-33| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t2 | 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t2 |
| 3 | // RUN: ld.lld %t1 %t2 -o %t | 3 | // RUN: ld.lld %t1 %t2 -o %t |
| 4 | // RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t | FileCheck %s | 4 | // RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t | FileCheck %s |
| 5 | // RUN: ld.lld -shared %t1 %t2 -o %t3 | 5 | // RUN: ld.lld --hash-style=sysv -shared %t1 %t2 -o %t3 |
| 6 | // RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOTHUMB %s | 6 | // RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOTHUMB %s |
| 7 | // RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOARM %s | 7 | // RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOARM %s |
| 8 | // RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s | 8 | // RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s |
| ... | @@ -43,50 +43,54 @@ _start: | ... | @@ -43,50 +43,54 @@ _start: |
| 43 | // .text is Thumb and .plt is ARM, llvm-objdump can currently only disassemble | 43 | // .text is Thumb and .plt is ARM, llvm-objdump can currently only disassemble |
| 44 | // as ARM or Thumb. Work around by disassembling twice. | 44 | // as ARM or Thumb. Work around by disassembling twice. |
| 45 | // DSOTHUMB: Disassembly of section .text: | 45 | // DSOTHUMB: Disassembly of section .text: |
| 46 | // DSOTHUMB: func1: | 46 | // DSOTHUMB-NEXT: func1: |
| 47 | // DSOTHUMB-NEXT: 1000: 70 47 bx lr | 47 | // DSOTHUMB-NEXT: 1000: 70 47 bx lr |
| 48 | // DSOTHUMB: func2: | 48 | // DSOTHUMB: func2: |
| 49 | // DSOTHUMB-NEXT: 1002: 70 47 bx lr | 49 | // DSOTHUMB-NEXT: 1002: 70 47 bx lr |
| 50 | // DSOTHUMB: func3: | 50 | // DSOTHUMB: func3: |
| 51 | // DSOTHUMB-NEXT: 1004: 70 47 bx lr | 51 | // DSOTHUMB-NEXT: 1004: 70 47 bx lr |
| 52 | // DSOTHUMB-NEXT: 1006: d4 d4 | 52 | // DSOTHUMB-NEXT: 1006: d4 d4 bmi #-88 |
| 53 | // DSOTHUMB: _start: | 53 | // DSOTHUMB: _start: |
| 54 | // 0x1008 + 0x28 + 4 = 0x1034 = PLT func1 | 54 | // 0x1008 + 0x34 + 4 = 0x1040 = PLT func1 |
| 55 | // DSOTHUMB-NEXT: 1008: 00 f0 14 e8 blx #40 | 55 | // DSOTHUMB-NEXT: 1008: 00 f0 1a e8 blx #52 |
| 56 | // 0x100c + 0x34 + 4 = 0x1044 = PLT func2 | 56 | // 0x100c + 0x40 + 4 = 0x1050 = PLT func2 |
| 57 | // DSOTHUMB-NEXT: 100c: 00 f0 1a e8 blx #52 | 57 | // DSOTHUMB-NEXT: 100c: 00 f0 20 e8 blx #64 |
| 58 | // 0x1010 + 0x40 + 4 = 0x1054 = PLT func3 | 58 | // 0x1010 + 0x4C + 4 = 0x1060 = PLT func3 |
| 59 | // DSOTHUMB-NEXT: 1010: 00 f0 20 e8 blx #64 | 59 | // DSOTHUMB-NEXT: 1010: 00 f0 26 e8 blx #76 |
| 60 | // DSOARM: Disassembly of section .plt: | 60 | // DSOARM: Disassembly of section .plt: |
| 61 | // DSOARM-NEXT: $a: | 61 | // DSOARM-NEXT: $a: |
| 62 | // DSOARM-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]! | 62 | // DSOARM-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]! |
| 63 | // DSOARM-NEXT: 1024: 04 e0 9f e5 ldr lr, [pc, #4] | 63 | // (0x1024 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfdc) = 0x2008 = .got.plt[3] |
| 64 | // DSOARM-NEXT: 1028: 0e e0 8f e0 add lr, pc, lr | 64 | // DSOARM-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #12 |
| 65 | // DSOARM-NEXT: 102c: 08 f0 be e5 ldr pc, [lr, #8]! | 65 | // DSOARM-NEXT: 1028: 00 ea 8e e2 add lr, lr, #0, #20 |
| 66 | // DSOARM-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]! | ||
| 66 | // DSOARM: $d: | 67 | // DSOARM: $d: |
| 67 | // DSOARM-NEXT: 1030: d0 0f 00 00 .word 0x00000fd0 | 68 | |
| 68 | // 0x1028 + 8 + 0fd0 = 0x2000 | 69 | // DSOARM-NEXT: 1030: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 70 | // DSOARM-NEXT: 1034: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 71 | // DSOARM-NEXT: 1038: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 72 | // DSOARM-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 69 | // DSOARM: $a: | 73 | // DSOARM: $a: |
| 70 | // DSOARM-NEXT: 1034: 04 c0 9f e5 ldr r12, [pc, #4] | 74 | // (0x1040 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfc4) = 0x200c |
| 71 | // DSOARM-NEXT: 1038: 0f c0 8c e0 add r12, r12, pc | 75 | // DSOARM-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #12 |
| 72 | // DSOARM-NEXT: 103c: 00 f0 9c e5 ldr pc, [r12] | 76 | // DSOARM-NEXT: 1044: 00 ca 8c e2 add r12, r12, #0, #20 |
| 77 | // DSOARM-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]! | ||
| 73 | // DSOARM: $d: | 78 | // DSOARM: $d: |
| 74 | // DSOARM-NEXT: 1040: cc 0f 00 00 .word 0x00000fcc | 79 | // DSOARM-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 75 | // 0x1038 + 8 + 0fcc = 0x200c | ||
| 76 | // DSOARM: $a: | 80 | // DSOARM: $a: |
| 77 | // DSOARM-NEXT: 1044: 04 c0 9f e5 ldr r12, [pc, #4] | 81 | // (0x1050 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfb8) = 0x2010 |
| 78 | // DSOARM-NEXT: 1048: 0f c0 8c e0 add r12, r12, pc | 82 | // DSOARM-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #12 |
| 79 | // DSOARM-NEXT: 104c: 00 f0 9c e5 ldr pc, [r12] | 83 | // DSOARM-NEXT: 1054: 00 ca 8c e2 add r12, r12, #0, #20 |
| 84 | // DSOARM-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]! | ||
| 80 | // DSOARM: $d: | 85 | // DSOARM: $d: |
| 81 | // DSOARM-NEXT: 1050: c0 0f 00 00 .word 0x00000fc0 | 86 | // DSOARM-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 82 | // 0x1048 + 8 + 0fc0 = 0x2010 | ||
| 83 | // DSOARM: $a: | 87 | // DSOARM: $a: |
| 84 | // DSOARM-NEXT: 1054: 04 c0 9f e5 ldr r12, [pc, #4] | 88 | // (0x1060 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfac) = 0x2014 |
| 85 | // DSOARM-NEXT: 1058: 0f c0 8c e0 add r12, r12, pc | 89 | // DSOARM-NEXT: 1060: 00 c6 8f e2 add r12, pc, #0, #12 |
| 86 | // DSOARM-NEXT: 105c: 00 f0 9c e5 ldr pc, [r12] | 90 | // DSOARM-NEXT: 1064: 00 ca 8c e2 add r12, r12, #0, #20 |
| 91 | // DSOARM-NEXT: 1068: ac ff bc e5 ldr pc, [r12, #4012]! | ||
| 87 | // DSOARM: $d: | 92 | // DSOARM: $d: |
| 88 | // DSOARM-NEXT: 1060: b4 0f 00 00 .word 0x00000fb4 | 93 | // DSOARM-NEXT: 106c: d4 d4 d4 d4 .word 0xd4d4d4d4 |
| 89 | // 0x1058 + 8 + 0fb4 = 0x2014 | ||
| 90 | 94 | ||
| 91 | // DSOREL: Name: .got.plt | 95 | // DSOREL: Name: .got.plt |
| 92 | // DSOREL-NEXT: Type: SHT_PROGBITS | 96 | // DSOREL-NEXT: Type: SHT_PROGBITS |
deps/lld/test/ELF/arm-thumb-range-thunk-os.s created+159| ... | @@ -0,0 +1,159 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: ld.lld %t -o %t2 2>&1 | ||
| 4 | // The output file is large, most of it zeroes. We dissassemble only the | ||
| 5 | // parts we need to speed up the test and avoid a large output file | ||
| 6 | // RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048588 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 7 | // RUN: llvm-objdump -d %t2 -start-address=2097152 -stop-address=2097154 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 8 | // RUN: llvm-objdump -d %t2 -start-address=3145728 -stop-address=3145730 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s | ||
| 9 | // RUN: llvm-objdump -d %t2 -start-address=4194304 -stop-address=4194310 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s | ||
| 10 | // RUN: llvm-objdump -d %t2 -start-address=16777216 -stop-address=16777270 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK5 %s | ||
| 11 | // RUN: llvm-objdump -d %t2 -start-address=17825792 -stop-address=17825808 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s | ||
| 12 | // RUN: llvm-objdump -d %t2 -start-address=31457280 -stop-address=31457286 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s | ||
| 13 | // RUN: llvm-objdump -d %t2 -start-address=32505860 -stop-address=32505880 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s | ||
| 14 | // RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651594 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s | ||
| 15 | // RUN: llvm-objdump -d %t2 -start-address=36700160 -stop-address=36700170 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK10 %s | ||
| 16 | |||
| 17 | // Test the Range extension Thunks for Thumb when all the code is in a single | ||
| 18 | // OutputSection. The Thumb unconditional branch b.w and branch and link bl | ||
| 19 | // instructions have a range of 16Mb. We create a series of Functions a | ||
| 20 | // megabyte apart. We expect range extension thunks to be created when a | ||
| 21 | // branch is out of range. Thunks will be reused whenever they are in range | ||
| 22 | .syntax unified | ||
| 23 | |||
| 24 | // Define a function aligned on a megabyte boundary | ||
| 25 | .macro FUNCTION suff | ||
| 26 | .section .text.\suff\(), "ax", %progbits | ||
| 27 | .thumb | ||
| 28 | .balign 0x100000 | ||
| 29 | .globl tfunc\suff\() | ||
| 30 | .type tfunc\suff\(), %function | ||
| 31 | tfunc\suff\(): | ||
| 32 | bx lr | ||
| 33 | .endm | ||
| 34 | |||
| 35 | .section .text, "ax", %progbits | ||
| 36 | .thumb | ||
| 37 | .globl _start | ||
| 38 | _start: | ||
| 39 | // tfunc00 and tfunc15 are within 16Mb no Range Thunks expected | ||
| 40 | bl tfunc00 | ||
| 41 | bl tfunc15 | ||
| 42 | // tfunc16 is > 16Mb away, expect a Range Thunk to be generated, to go into | ||
| 43 | // the first of the pre-created ThunkSections. | ||
| 44 | bl tfunc16 | ||
| 45 | // CHECK1: Disassembly of section .text: | ||
| 46 | // CHECK1-NEXT: _start: | ||
| 47 | // CHECK1-NEXT: 100000: ff f0 fe ff bl #1048572 | ||
| 48 | // CHECK1-NEXT: 100004: ff f3 fc d7 bl #16777208 | ||
| 49 | // CHECK1-NEXT: 100008: ff f2 fc d7 bl #15728632 | ||
| 50 | |||
| 51 | FUNCTION 00 | ||
| 52 | // CHECK2: tfunc00: | ||
| 53 | // CHECK2-NEXT: 200000: 70 47 bx lr | ||
| 54 | FUNCTION 01 | ||
| 55 | // CHECK3: tfunc01: | ||
| 56 | // CHECK3-NEXT: 300000: 70 47 bx lr | ||
| 57 | FUNCTION 02 | ||
| 58 | // tfunc28 is > 16Mb away, expect a Range Thunk to be generated, to go into | ||
| 59 | // the first of the pre-created ThunkSections. | ||
| 60 | b.w tfunc28 | ||
| 61 | // CHECK4: tfunc02: | ||
| 62 | // CHECK4-NEXT: 400000: 70 47 bx lr | ||
| 63 | // CHECK4-NEXT: 400002: 00 f0 04 90 b.w #12582920 <__Thumbv7ABSLongThunk_tfunc28> | ||
| 64 | FUNCTION 03 | ||
| 65 | FUNCTION 04 | ||
| 66 | FUNCTION 05 | ||
| 67 | FUNCTION 06 | ||
| 68 | FUNCTION 07 | ||
| 69 | FUNCTION 08 | ||
| 70 | FUNCTION 09 | ||
| 71 | FUNCTION 10 | ||
| 72 | FUNCTION 11 | ||
| 73 | FUNCTION 12 | ||
| 74 | FUNCTION 13 | ||
| 75 | FUNCTION 14 | ||
| 76 | // Expect precreated ThunkSection here | ||
| 77 | // CHECK5: __Thumbv7ABSLongThunk_tfunc16: | ||
| 78 | // CHECK5-NEXT: 1000004: 40 f2 01 0c movw r12, #1 | ||
| 79 | // CHECK5-NEXT: 1000008: c0 f2 20 1c movt r12, #288 | ||
| 80 | // CHECK5-NEXT: 100000c: 60 47 bx r12 | ||
| 81 | // CHECK5: __Thumbv7ABSLongThunk_tfunc28: | ||
| 82 | // CHECK5-NEXT: 100000e: 40 f2 01 0c movw r12, #1 | ||
| 83 | // CHECK5-NEXT: 1000012: c0 f2 e0 1c movt r12, #480 | ||
| 84 | // CHECK5-NEXT: 1000016: 60 47 bx r12 | ||
| 85 | // CHECK5: __Thumbv7ABSLongThunk_tfunc32: | ||
| 86 | // CHECK5-NEXT: 1000018: 40 f2 01 0c movw r12, #1 | ||
| 87 | // CHECK5-NEXT: 100001c: c0 f2 20 2c movt r12, #544 | ||
| 88 | // CHECK5-NEXT: 1000020: 60 47 bx r12 | ||
| 89 | // CHECK5: __Thumbv7ABSLongThunk_tfunc33: | ||
| 90 | // CHECK5-NEXT: 1000022: 40 f2 01 0c movw r12, #1 | ||
| 91 | // CHECK5-NEXT: 1000026: c0 f2 30 2c movt r12, #560 | ||
| 92 | // CHECK5-NEXT: 100002a: 60 47 bx r12 | ||
| 93 | // CHECK5: __Thumbv7ABSLongThunk_tfunc02: | ||
| 94 | // CHECK5-NEXT: 100002c: 40 f2 01 0c movw r12, #1 | ||
| 95 | // CHECK5-NEXT: 1000030: c0 f2 40 0c movt r12, #64 | ||
| 96 | // CHECK5-NEXT: 1000034: 60 47 bx r12 | ||
| 97 | FUNCTION 15 | ||
| 98 | // tfunc00 and tfunc01 are < 16Mb away, expect no range extension thunks | ||
| 99 | bl tfunc00 | ||
| 100 | bl tfunc01 | ||
| 101 | // tfunc32 and tfunc33 are > 16Mb away, expect range extension thunks in the | ||
| 102 | // precreated thunk section | ||
| 103 | bl tfunc32 | ||
| 104 | bl tfunc33 | ||
| 105 | // CHECK6: tfunc15: | ||
| 106 | // CHECK6-NEXT: 1100000: 70 47 bx lr | ||
| 107 | // CHECK6-NEXT: 1100002: ff f4 fd d7 bl #-15728646 | ||
| 108 | // CHECK6-NEXT: 1100006: ff f5 fb d7 bl #-14680074 | ||
| 109 | // CHECK6-NEXT: 110000a: 00 f7 05 f8 bl #-1048566 | ||
| 110 | // CHECK6-NEXT: 110000e: 00 f7 08 f8 bl #-1048560 | ||
| 111 | FUNCTION 16 | ||
| 112 | FUNCTION 17 | ||
| 113 | FUNCTION 18 | ||
| 114 | FUNCTION 19 | ||
| 115 | FUNCTION 20 | ||
| 116 | FUNCTION 21 | ||
| 117 | FUNCTION 22 | ||
| 118 | FUNCTION 23 | ||
| 119 | FUNCTION 24 | ||
| 120 | FUNCTION 25 | ||
| 121 | FUNCTION 26 | ||
| 122 | FUNCTION 27 | ||
| 123 | FUNCTION 28 | ||
| 124 | // tfunc02 is > 16Mb away, expect range extension thunks in precreated thunk | ||
| 125 | // section | ||
| 126 | // CHECK7: tfunc28: | ||
| 127 | // CHECK7-NEXT: 1e00000: 70 47 bx lr | ||
| 128 | // CHECK7-NEXT: 1e00002: 00 f6 13 90 b.w #-14680026 <__Thumbv7ABSLongThunk_tfunc02> | ||
| 129 | |||
| 130 | b.w tfunc02 | ||
| 131 | FUNCTION 29 | ||
| 132 | // Expect another precreated thunk section here | ||
| 133 | // CHECK8: __Thumbv7ABSLongThunk_tfunc15: | ||
| 134 | // CHECK8-NEXT: 1f00004: 40 f2 01 0c movw r12, #1 | ||
| 135 | // CHECK8-NEXT: 1f00008: c0 f2 10 1c movt r12, #272 | ||
| 136 | // CHECK8-NEXT: 1f0000c: 60 47 bx r12 | ||
| 137 | // CHECK8: __Thumbv7ABSLongThunk_tfunc16: | ||
| 138 | // CHECK8-NEXT: 1f0000e: 40 f2 01 0c movw r12, #1 | ||
| 139 | // CHECK8-NEXT: 1f00012: c0 f2 20 1c movt r12, #288 | ||
| 140 | // CHECK8-NEXT: 1f00016: 60 47 bx r12 | ||
| 141 | FUNCTION 30 | ||
| 142 | FUNCTION 31 | ||
| 143 | FUNCTION 32 | ||
| 144 | // tfunc15 and tfunc16 are > 16 Mb away expect Thunks in the nearest | ||
| 145 | // precreated thunk section. | ||
| 146 | bl tfunc15 | ||
| 147 | bl tfunc16 | ||
| 148 | // CHECK9: tfunc32: | ||
| 149 | // CHECK9: 2200000: 70 47 bx lr | ||
| 150 | // CHECK9-NEXT: 2200002: ff f4 ff ff bl #-3145730 | ||
| 151 | // CHECK9-NEXT: 2200006: 00 f5 02 f8 bl #-3145724 | ||
| 152 | |||
| 153 | FUNCTION 33 | ||
| 154 | bl tfunc15 | ||
| 155 | bl tfunc16 | ||
| 156 | // CHECK10: tfunc33: | ||
| 157 | // CHECK10: 2300000: 70 47 bx lr | ||
| 158 | // CHECK10-NEXT: 2300002: ff f7 ff f7 bl #-4194306 | ||
| 159 | // CHECK10-NEXT: 2300006: 00 f4 02 f8 bl #-4194300 | ||
deps/lld/test/ELF/arm-thumb-thunk-empty-pass.s created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: ld.lld %t -o %t2 2>&1 | ||
| 4 | // RUN: llvm-objdump -d %t2 -start-address=69632 -stop-address=69646 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 5 | // RUN: llvm-objdump -d %t2 -start-address=16846860 -stop-address=16846874 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 6 | .syntax unified | ||
| 7 | .global _start, foo | ||
| 8 | .type _start, %function | ||
| 9 | .section .text.start,"ax",%progbits | ||
| 10 | _start: | ||
| 11 | bl _start | ||
| 12 | .section .text.dummy1,"ax",%progbits | ||
| 13 | .space 0xfffffe | ||
| 14 | .section .text.foo,"ax",%progbits | ||
| 15 | .type foo, %function | ||
| 16 | foo: | ||
| 17 | bl _start | ||
| 18 | |||
| 19 | // CHECK1: Disassembly of section .text: | ||
| 20 | // CHECK1-NEXT: _start: | ||
| 21 | // CHECK1-NEXT: 11000: ff f7 fe ff bl #-4 | ||
| 22 | // CHECK1: __Thumbv7ABSLongThunk__start: | ||
| 23 | // CHECK1-NEXT: 11004: 41 f2 01 0c movw r12, #4097 | ||
| 24 | // CHECK1-NEXT: 11008: c0 f2 01 0c movt r12, #1 | ||
| 25 | // CHECK1-NEXT: 1100c: 60 47 bx r12 | ||
| 26 | |||
| 27 | // CHECK2: __Thumbv7ABSLongThunk__start: | ||
| 28 | // CHECK2: 101100c: 41 f2 01 0c movw r12, #4097 | ||
| 29 | // CHECK2-NEXT: 1011010: c0 f2 01 0c movt r12, #1 | ||
| 30 | // CHECK2-NEXT: 1011014: 60 47 bx r12 | ||
| 31 | // CHECK2: foo: | ||
| 32 | // CHECK2-NEXT: 1011016: ff f7 f9 ff bl #-14 | ||
deps/lld/test/ELF/arm-thumb-thunk-symbols.s+3-3| ... | @@ -25,18 +25,18 @@ arm_fn: | ... | @@ -25,18 +25,18 @@ arm_fn: |
| 25 | b thumb_fn | 25 | b thumb_fn |
| 26 | 26 | ||
| 27 | // CHECK: Name: __Thumbv7ABSLongThunk_arm_fn | 27 | // CHECK: Name: __Thumbv7ABSLongThunk_arm_fn |
| 28 | // CHECK-NEXT: Value: 0x11005 | 28 | // CHECK-NEXT: Value: 0x12005 |
| 29 | // CHECK-NEXT: Size: 10 | 29 | // CHECK-NEXT: Size: 10 |
| 30 | // CHECK-NEXT: Binding: Local (0x0) | 30 | // CHECK-NEXT: Binding: Local (0x0) |
| 31 | // CHECK-NEXT: Type: Function (0x2) | 31 | // CHECK-NEXT: Type: Function (0x2) |
| 32 | // CHECK: Name: __ARMv7ABSLongThunk_thumb_fn | 32 | // CHECK: Name: __ARMv7ABSLongThunk_thumb_fn |
| 33 | // CHECK-NEXT: Value: 0x11010 | 33 | // CHECK-NEXT: Value: 0x12010 |
| 34 | // CHECK-NEXT: Size: 12 | 34 | // CHECK-NEXT: Size: 12 |
| 35 | // CHECK-NEXT: Binding: Local (0x0) | 35 | // CHECK-NEXT: Binding: Local (0x0) |
| 36 | // CHECK-NEXT: Type: Function (0x2) | 36 | // CHECK-NEXT: Type: Function (0x2) |
| 37 | 37 | ||
| 38 | // CHECK-PI: Name: __ThumbV7PILongThunk_arm_fn | 38 | // CHECK-PI: Name: __ThumbV7PILongThunk_arm_fn |
| 39 | // CHECK-PI-NEXT: Value: 0x1005 | 39 | // CHECK-PI-NEXT: Value: 0x2005 |
| 40 | // CHECK-PI-NEXT: Size: 12 | 40 | // CHECK-PI-NEXT: Size: 12 |
| 41 | // CHECK-PI-NEXT: Binding: Local (0x0) | 41 | // CHECK-PI-NEXT: Binding: Local (0x0) |
| 42 | // CHECK-PI-NEXT: Type: Function (0x2) | 42 | // CHECK-PI-NEXT: Type: Function (0x2) |
deps/lld/test/ELF/arm-thunk-edgecase.s created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | ||
| 3 | // RUN: echo "SECTIONS { \ | ||
| 4 | // RUN: .text_armfunc 0x1000 : { *(.text_armfunc) } \ | ||
| 5 | // RUN: .text_thumbfunc 0x11010 : { *(.text_thumbfunc) } \ | ||
| 6 | // RUN: }" > %tarm_to_thumb.script | ||
| 7 | // RUN: echo "SECTIONS { \ | ||
| 8 | // RUN: .text_thumbfunc 0x1000 : { *(.text_thumbfunc) } \ | ||
| 9 | // RUN: .text_armfunc 0x1100c : { *(.text_armfunc) } \ | ||
| 10 | // RUN: }" > %tthumb_to_arm.script | ||
| 11 | // RUN: ld.lld -shared -Bsymbolic -script %tarm_to_thumb.script %t.o -o %tarm_to_thumb.so | ||
| 12 | // RUN: ld.lld -shared -Bsymbolic -script %tthumb_to_arm.script %t.o -o %tthumb_to_arm.so | ||
| 13 | // RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %tarm_to_thumb.so | FileCheck -check-prefix=ARM-TO-THUMB %s | ||
| 14 | // RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %tthumb_to_arm.so | FileCheck -check-prefix=THUMB-TO-ARM %s | ||
| 15 | |||
| 16 | .syntax unified | ||
| 17 | |||
| 18 | .arm | ||
| 19 | .section .text_armfunc, "ax", %progbits | ||
| 20 | .globl armfunc | ||
| 21 | armfunc: | ||
| 22 | 	b	thumbfunc | ||
| 23 | |||
| 24 | .thumb | ||
| 25 | .section .text_thumbfunc, "ax", %progbits | ||
| 26 | .globl thumbfunc | ||
| 27 | .thumb_func | ||
| 28 | thumbfunc: | ||
| 29 | 	b.w	armfunc | ||
| 30 | |||
| 31 | // ARM-TO-THUMB: __ARMV7PILongThunk_thumbfunc: | ||
| 32 | // ARM-TO-THUMB-NEXT: 1004: fd cf 0f e3 movw r12, #65533 | ||
| 33 | // ARM-TO-THUMB-NEXT: 1008: 00 c0 40 e3 movt r12, #0 | ||
| 34 | |||
| 35 | // THUMB-TO-ARM: __ThumbV7PILongThunk_armfunc: | ||
| 36 | // THUMB-TO-ARM-NEXT: 1004: 4f f6 fc 7c movw r12, #65532 | ||
| 37 | // THUMB-TO-ARM-NEXT: 1008: c0 f2 00 0c movt r12, #0 | ||
deps/lld/test/ELF/arm-thunk-largesection.s created+42| ... | @@ -0,0 +1,42 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: ld.lld %t -o %t2 2>&1 | ||
| 3 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=69632 -stop-address=69636 %t2 | FileCheck -check-prefix=CHECK1 %s | ||
| 4 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=73732 -stop-address=73742 %t2 | FileCheck -check-prefix=CHECK2 %s | ||
| 5 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=16850944 -stop-address=16850948 %t2 | FileCheck -check-prefix=CHECK3 %s | ||
| 6 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=33628160 -stop-address=33628164 %t2 | FileCheck -check-prefix=CHECK4 %s | ||
| 7 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=50405364 -stop-address=50405376 %t2 | FileCheck -check-prefix=CHECK5 %s | ||
| 8 | // REQUIRES: arm | ||
| 9 | .syntax unified | ||
| 10 | .balign 0x1000 | ||
| 11 | .thumb | ||
| 12 | .text | ||
| 13 | .globl _start | ||
| 14 | .type _start, %function | ||
| 15 | _start: | ||
| 16 | bx lr | ||
| 17 | .space 0x1000 | ||
| 18 | // CHECK1: Disassembly of section .text: | ||
| 19 | // CHECK1-NEXT: _start: | ||
| 20 | // CHECK1-NEXT: 11000: 70 47 bx lr | ||
| 21 | // CHECK1-NEXT: 11002: 00 00 movs r0, r0 | ||
| 22 | |||
| 23 | // CHECK2: __Thumbv7ABSLongThunk__start: | ||
| 24 | // CHECK2-NEXT: 12004: 41 f2 01 0c movw r12, #4097 | ||
| 25 | // CHECK2-NEXT: 12008: c0 f2 01 0c movt r12, #1 | ||
| 26 | // CHECK2-NEXT: 1200c: 60 47 bx r12 | ||
| 27 | |||
| 28 | // Gigantic section where we need a ThunkSection either side of it | ||
| 29 | .section .text.large1, "ax", %progbits | ||
| 30 | .balign 4 | ||
| 31 | .space (16 * 1024 * 1024) - 16 | ||
| 32 | bl _start | ||
| 33 | .space (16 * 1024 * 1024) - 4 | ||
| 34 | bl _start | ||
| 35 | .space (16 * 1024 * 1024) - 16 | ||
| 36 | // CHECK3: 1012000: 00 f4 00 d0 bl #-16777216 | ||
| 37 | // CHECK4: 2012000: ff f3 f8 d7 bl #16777200 | ||
| 38 | |||
| 39 | // CHECK5: __Thumbv7ABSLongThunk__start: | ||
| 40 | // CHECK5-NEXT: 3011ff4: 41 f2 01 0c movw r12, #4097 | ||
| 41 | // CHECK5-NEXT: 3011ff8: c0 f2 01 0c movt r12, #1 | ||
| 42 | // CHECK5-NEXT: 3011ffc: 60 47 bx r12 | ||
deps/lld/test/ELF/arm-thunk-linkerscript-dotexpr.s created+77| ... | @@ -0,0 +1,77 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: echo "SECTIONS { \ | ||
| 3 | // RUN: . = SIZEOF_HEADERS; \ | ||
| 4 | // RUN: .text_low : { *(.text_low) *(.text_low2) . = . + 0x2000000 ; *(.text_high) *(.text_high2) } \ | ||
| 5 | // RUN: } " > %t.script | ||
| 6 | // RUN: ld.lld --script %t.script %t -o %t2 2>&1 | ||
| 7 | // RUN: llvm-objdump -d %t2 -start-address=148 -stop-address=188 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 8 | // RUN: llvm-objdump -d %t2 -start-address=33554620 -stop-address=33554654 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 9 | // REQUIRES: arm | ||
| 10 | // Test that range extension thunks can handle location expressions within | ||
| 11 | // a Section Description | ||
| 12 | .syntax unified | ||
| 13 | .section .text_low, "ax", %progbits | ||
| 14 | .thumb | ||
| 15 | .globl _start | ||
| 16 | _start: bx lr | ||
| 17 | .globl low_target | ||
| 18 | .type low_target, %function | ||
| 19 | low_target: | ||
| 20 | bl high_target | ||
| 21 | bl high_target2 | ||
| 22 | |||
| 23 | .section .text_low2, "ax", %progbits | ||
| 24 | .thumb | ||
| 25 | .globl low_target2 | ||
| 26 | .type low_target2, %function | ||
| 27 | low_target2: | ||
| 28 | bl high_target | ||
| 29 | bl high_target2 | ||
| 30 | // CHECK1: Disassembly of section .text_low: | ||
| 31 | // CHECK1-NEXT: _start: | ||
| 32 | // CHECK1-NEXT: 94: 70 47 bx lr | ||
| 33 | // CHECK1: low_target: | ||
| 34 | // CHECK1-NEXT: 96: 00 f0 03 f8 bl #6 | ||
| 35 | // CHECK1-NEXT: 9a: 00 f0 06 f8 bl #12 | ||
| 36 | // CHECK1: __Thumbv7ABSLongThunk_high_target: | ||
| 37 | // CHECK1-NEXT: a0: 40 f2 bd 0c movw r12, #189 | ||
| 38 | // CHECK1-NEXT: a4: c0 f2 00 2c movt r12, #512 | ||
| 39 | // CHECK1-NEXT: a8: 60 47 bx r12 | ||
| 40 | // CHECK1: __Thumbv7ABSLongThunk_high_target2: | ||
| 41 | // CHECK1-NEXT: aa: 40 f2 d9 0c movw r12, #217 | ||
| 42 | // CHECK1-NEXT: ae: c0 f2 00 2c movt r12, #512 | ||
| 43 | // CHECK1-NEXT: b2: 60 47 bx r12 | ||
| 44 | // CHECK1: low_target2: | ||
| 45 | // CHECK1-NEXT: b4: ff f7 f4 ff bl #-24 | ||
| 46 | // CHECK1-NEXT: b8: ff f7 f7 ff bl #-18 | ||
| 47 | |||
| 48 | .section .text_high, "ax", %progbits | ||
| 49 | .thumb | ||
| 50 | .globl high_target | ||
| 51 | .type high_target, %function | ||
| 52 | high_target: | ||
| 53 | bl low_target | ||
| 54 | bl low_target2 | ||
| 55 | |||
| 56 | .section .text_high2, "ax", %progbits | ||
| 57 | .thumb | ||
| 58 | .globl high_target2 | ||
| 59 | .type high_target2, %function | ||
| 60 | high_target2: | ||
| 61 | bl low_target | ||
| 62 | bl low_target2 | ||
| 63 | |||
| 64 | // CHECK2: high_target: | ||
| 65 | // CHECK2-NEXT: 20000bc: 00 f0 02 f8 bl #4 | ||
| 66 | // CHECK2-NEXT: 20000c0: 00 f0 05 f8 bl #10 | ||
| 67 | // CHECK2: __Thumbv7ABSLongThunk_low_target: | ||
| 68 | // CHECK2-NEXT: 20000c4: 40 f2 97 0c movw r12, #151 | ||
| 69 | // CHECK2-NEXT: 20000c8: c0 f2 00 0c movt r12, #0 | ||
| 70 | // CHECK2-NEXT: 20000cc: 60 47 bx r12 | ||
| 71 | // CHECK2: __Thumbv7ABSLongThunk_low_target2: | ||
| 72 | // CHECK2-NEXT: 20000ce: 40 f2 b5 0c movw r12, #181 | ||
| 73 | // CHECK2-NEXT: 20000d2: c0 f2 00 0c movt r12, #0 | ||
| 74 | // CHECK2-NEXT: 20000d6: 60 47 bx r12 | ||
| 75 | // CHECK2: high_target2: | ||
| 76 | // CHECK2-NEXT: 20000d8: ff f7 f4 ff bl #-24 | ||
| 77 | // CHECK2-NEXT: 20000dc: ff f7 f7 ff bl #-18 | ||
deps/lld/test/ELF/arm-thunk-linkerscript-large.s created+176| ... | @@ -0,0 +1,176 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: echo "SECTIONS { \ | ||
| 4 | // RUN: .text 0x100000 : { *(.text) } \ | ||
| 5 | // RUN: .textl : { *(.text_l0*) *(.text_l1*) *(.text_l2*) *(.text_l3*) } \ | ||
| 6 | // RUN: .texth : { *(.text_h0*) *(.text_h1*) *(.text_h2*) *(.text_h3*) } \ | ||
| 7 | // RUN: }" > %t.script | ||
| 8 | // RUN: ld.lld --script %t.script %t -o %t2 2>&1 | ||
| 9 | // The output file is large, most of it zeroes. We dissassemble only the | ||
| 10 | // parts we need to speed up the test and avoid a large output file | ||
| 11 | // RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048594 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK1 %s | ||
| 12 | // RUN: llvm-objdump -d %t2 -start-address=2097152 -stop-address=2097160 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK2 %s | ||
| 13 | // RUN: llvm-objdump -d %t2 -start-address=11534340 -stop-address=11534350 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK3 %s | ||
| 14 | // RUN: llvm-objdump -d %t2 -start-address=34603008 -stop-address=34603034 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK4 %s | ||
| 15 | // RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651598 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK5 %s | ||
| 16 | // RUN: llvm-objdump -d %t2 -start-address=68157440 -stop-address=68157472 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK6 %s | ||
| 17 | |||
| 18 | // Test the range extensions in a linker script where there are several | ||
| 19 | // OutputSections requiring range extension Thunks. We should be able to reuse | ||
| 20 | // Thunks between OutputSections but our placement of new Thunks is done on a | ||
| 21 | // per OutputSection basis | ||
| 22 | .syntax unified | ||
| 23 | |||
| 24 | // Define a function that we can match with .text_l* aligned on a megabyte // boundary | ||
| 25 | .macro FUNCTIONL suff | ||
| 26 | .section .text_l\suff\(), "ax", %progbits | ||
| 27 | .thumb | ||
| 28 | .balign 0x100000 | ||
| 29 | .globl tfuncl\suff\() | ||
| 30 | .type tfuncl\suff\(), %function | ||
| 31 | tfuncl\suff\(): | ||
| 32 | bx lr | ||
| 33 | .endm | ||
| 34 | |||
| 35 | // Define a function that we can match with .text_h* aligned on a megabyte | ||
| 36 | // boundary | ||
| 37 | .macro FUNCTIONH suff | ||
| 38 | .section .text_h\suff\(), "ax", %progbits | ||
| 39 | .thumb | ||
| 40 | .balign 0x100000 | ||
| 41 | .globl tfunch\suff\() | ||
| 42 | .type tfunch\suff\(), %function | ||
| 43 | tfunch\suff\(): | ||
| 44 | bx lr | ||
| 45 | .endm | ||
| 46 | |||
| 47 | .section .text, "ax", %progbits | ||
| 48 | .thumb | ||
| 49 | .globl _start | ||
| 50 | _start: | ||
| 51 | bl tfuncl00 | ||
| 52 | // Expect a range extension thunk in .text OutputSection | ||
| 53 | bl tfunch31 | ||
| 54 | // CHECK1: Disassembly of section .text: | ||
| 55 | // CHECK1-NEXT: _start: | ||
| 56 | // CHECK1-NEXT: 100000: ff f0 fe ff bl #1048572 | ||
| 57 | // CHECK1-NEXT: 100004: 00 f0 00 f8 bl #0 | ||
| 58 | // CHECK1: __Thumbv7ABSLongThunk_tfunch31: | ||
| 59 | // CHECK1-NEXT: 100008: 40 f2 01 0c movw r12, #1 | ||
| 60 | // CHECK1-NEXT: 10000c: c0 f2 10 4c movt r12, #1040 | ||
| 61 | // CHECK1-NEXT: 100010: 60 47 bx r12 | ||
| 62 | FUNCTIONL 00 | ||
| 63 | // Create a range extension thunk in .textl | ||
| 64 | bl tfuncl24 | ||
| 65 | // We can reuse existing thunk in .text | ||
| 66 | bl tfunch31 | ||
| 67 | // CHECK2: Disassembly of section .textl: | ||
| 68 | // CHECK2-NEXT: tfuncl00: | ||
| 69 | // CHECK2-NEXT: 200000:	70 47 	bx	lr | ||
| 70 | // CHECK2-NEXT: 200002:	ff f0 ff df 	bl	#9437182 | ||
| 71 | // CHECK2-NEXT: 200006:	ff f6 ff ff 	bl	#-1048578 | ||
| 72 | FUNCTIONL 01 | ||
| 73 | FUNCTIONL 02 | ||
| 74 | FUNCTIONL 03 | ||
| 75 | FUNCTIONL 04 | ||
| 76 | FUNCTIONL 05 | ||
| 77 | FUNCTIONL 06 | ||
| 78 | FUNCTIONL 07 | ||
| 79 | FUNCTIONL 08 | ||
| 80 | FUNCTIONL 09 | ||
| 81 | // CHECK3: __Thumbv7ABSLongThunk_tfuncl24: | ||
| 82 | // CHECK3-NEXT: b00004:	40 f2 01 0c 	movw	r12, #1 | ||
| 83 | // CHECK3-NEXT: b00008:	c0 f2 a0 1c 	movt	r12, #416 | ||
| 84 | // CHECK3-NEXT: b0000c:	60 47 	bx	r12 | ||
| 85 | FUNCTIONL 10 | ||
| 86 | FUNCTIONL 11 | ||
| 87 | FUNCTIONL 12 | ||
| 88 | FUNCTIONL 13 | ||
| 89 | FUNCTIONL 14 | ||
| 90 | FUNCTIONL 15 | ||
| 91 | FUNCTIONL 16 | ||
| 92 | FUNCTIONL 17 | ||
| 93 | FUNCTIONL 18 | ||
| 94 | FUNCTIONL 19 | ||
| 95 | FUNCTIONL 20 | ||
| 96 | FUNCTIONL 21 | ||
| 97 | FUNCTIONL 22 | ||
| 98 | FUNCTIONL 23 | ||
| 99 | FUNCTIONL 24 | ||
| 100 | FUNCTIONL 25 | ||
| 101 | FUNCTIONL 26 | ||
| 102 | FUNCTIONL 27 | ||
| 103 | FUNCTIONL 28 | ||
| 104 | FUNCTIONL 29 | ||
| 105 | FUNCTIONL 30 | ||
| 106 | FUNCTIONL 31 | ||
| 107 | // Create range extension thunks in .textl | ||
| 108 | bl tfuncl00 | ||
| 109 | bl tfuncl24 | ||
| 110 | // Shouldn't need a thunk | ||
| 111 | bl tfunch00 | ||
| 112 | // CHECK4: 2100002: 00 f0 05 f8 bl #10 | ||
| 113 | // CHECK4-NEXT: 2100006: ff f4 fb f7 bl #-7340042 | ||
| 114 | // CHECK4-NEXT: 210000a: ff f0 f9 ff bl #1048562 | ||
| 115 | // CHECK4: __Thumbv7ABSLongThunk_tfuncl00: | ||
| 116 | // CHECK4-NEXT: 2100010: 40 f2 01 0c movw r12, #1 | ||
| 117 | // CHECK4-NEXT: 2100014: c0 f2 20 0c movt r12, #32 | ||
| 118 | // CHECK4-NEXT: 2100018: 60 47 bx r12 | ||
| 119 | FUNCTIONH 00 | ||
| 120 | // Can reuse existing thunks in .textl | ||
| 121 | bl tfuncl00 | ||
| 122 | bl tfuncl24 | ||
| 123 | // Shouldn't need a thunk | ||
| 124 | bl tfuncl31 | ||
| 125 | // CHECK5: Disassembly of section .texth: | ||
| 126 | // CHECK5-NEXT: tfunch00: | ||
| 127 | // CHECK5-NEXT: 2200000: 70 47 bx lr | ||
| 128 | // CHECK5-NEXT: 2200002: 00 f7 05 f8 bl #-1048566 | ||
| 129 | // CHECK5-NEXT: 2200006: ff f7 fb df bl #-8388618 | ||
| 130 | // CHECK5-NEXT: 220000a: ff f6 f9 ff bl #-1048590 | ||
| 131 | FUNCTIONH 01 | ||
| 132 | FUNCTIONH 02 | ||
| 133 | FUNCTIONH 03 | ||
| 134 | FUNCTIONH 04 | ||
| 135 | FUNCTIONH 05 | ||
| 136 | FUNCTIONH 06 | ||
| 137 | FUNCTIONH 07 | ||
| 138 | FUNCTIONH 08 | ||
| 139 | FUNCTIONH 09 | ||
| 140 | FUNCTIONH 10 | ||
| 141 | FUNCTIONH 11 | ||
| 142 | FUNCTIONH 12 | ||
| 143 | FUNCTIONH 13 | ||
| 144 | FUNCTIONH 14 | ||
| 145 | FUNCTIONH 15 | ||
| 146 | FUNCTIONH 16 | ||
| 147 | FUNCTIONH 17 | ||
| 148 | FUNCTIONH 18 | ||
| 149 | FUNCTIONH 19 | ||
| 150 | FUNCTIONH 20 | ||
| 151 | FUNCTIONH 21 | ||
| 152 | FUNCTIONH 22 | ||
| 153 | FUNCTIONH 23 | ||
| 154 | FUNCTIONH 24 | ||
| 155 | FUNCTIONH 25 | ||
| 156 | FUNCTIONH 26 | ||
| 157 | FUNCTIONH 27 | ||
| 158 | FUNCTIONH 28 | ||
| 159 | FUNCTIONH 29 | ||
| 160 | FUNCTIONH 30 | ||
| 161 | FUNCTIONH 31 | ||
| 162 | // expect Thunks in .texth | ||
| 163 | bl tfuncl00 | ||
| 164 | bl tfunch00 | ||
| 165 | // CHECK6: tfunch31: | ||
| 166 | // CHECK6-NEXT: 4100000: 70 47 bx lr | ||
| 167 | // CHECK6-NEXT: 4100002: 00 f0 03 f8 bl #6 | ||
| 168 | // CHECK6-NEXT: 4100006: 00 f0 06 f8 bl #12 | ||
| 169 | // CHECK6: __Thumbv7ABSLongThunk_tfuncl00: | ||
| 170 | // CHECK6-NEXT: 410000c: 40 f2 01 0c movw r12, #1 | ||
| 171 | // CHECK6-NEXT: 4100010: c0 f2 20 0c movt r12, #32 | ||
| 172 | // CHECK6-NEXT: 4100014: 60 47 bx r12 | ||
| 173 | // CHECK6: __Thumbv7ABSLongThunk_tfunch00: | ||
| 174 | // CHECK6-NEXT: 4100016: 40 f2 01 0c movw r12, #1 | ||
| 175 | // CHECK6-NEXT: 410001a: c0 f2 20 2c movt r12, #544 | ||
| 176 | // CHECK6-NEXT: 410001e: 60 47 bx r12 | ||
deps/lld/test/ELF/arm-thunk-linkerscript-orphan.s created+63| ... | @@ -0,0 +1,63 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: echo "SECTIONS { \ | ||
| 4 | // RUN: .text_low 0x100000 : { *(.text_low) } \ | ||
| 5 | // RUN: .text_high 0x2000000 : { *(.text_high) } \ | ||
| 6 | // RUN: .data : { *(.data) } \ | ||
| 7 | // RUN: }" > %t.script | ||
| 8 | // RUN: ld.lld --script %t.script %t -o %t2 2>&1 | ||
| 9 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s | ||
| 10 | .syntax unified | ||
| 11 | .section .text_low, "ax", %progbits | ||
| 12 | .thumb | ||
| 13 | .globl _start | ||
| 14 | _start: bx lr | ||
| 15 | .globl low_target | ||
| 16 | .type low_target, %function | ||
| 17 | low_target: | ||
| 18 | bl high_target | ||
| 19 | bl orphan_target | ||
| 20 | // CHECK: Disassembly of section .text_low: | ||
| 21 | // CHECK-NEXT: _start: | ||
| 22 | // CHECK-NEXT: 100000: 70 47 bx lr | ||
| 23 | // CHECK: low_target: | ||
| 24 | // CHECK-NEXT: 100002: 00 f0 03 f8 bl #6 | ||
| 25 | // CHECK-NEXT: 100006: 00 f0 06 f8 bl #12 | ||
| 26 | // CHECK: __Thumbv7ABSLongThunk_high_target: | ||
| 27 | // CHECK-NEXT: 10000c: 40 f2 01 0c movw r12, #1 | ||
| 28 | // CHECK-NEXT: 100010: c0 f2 00 2c movt r12, #512 | ||
| 29 | // CHECK-NEXT: 100014: 60 47 bx r12 | ||
| 30 | // CHECK: __Thumbv7ABSLongThunk_orphan_target: | ||
| 31 | // CHECK-NEXT: 100016: 40 f2 15 0c movw r12, #21 | ||
| 32 | // CHECK-NEXT: 10001a: c0 f2 00 2c movt r12, #512 | ||
| 33 | // CHECK-NEXT: 10001e: 60 47 bx r12 | ||
| 34 | .section .text_high, "ax", %progbits | ||
| 35 | .thumb | ||
| 36 | .globl high_target | ||
| 37 | .type high_target, %function | ||
| 38 | high_target: | ||
| 39 | bl low_target | ||
| 40 | bl orphan_target | ||
| 41 | // CHECK: Disassembly of section .text_high: | ||
| 42 | // CHECK-NEXT: high_target: | ||
| 43 | // CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4 | ||
| 44 | // CHECK-NEXT: 2000004: 00 f0 06 f8 bl #12 | ||
| 45 | // CHECK: __Thumbv7ABSLongThunk_low_target: | ||
| 46 | // CHECK-NEXT: 2000008: 40 f2 03 0c movw r12, #3 | ||
| 47 | // CHECK-NEXT: 200000c: c0 f2 10 0c movt r12, #16 | ||
| 48 | // CHECK-NEXT: 2000010: 60 47 bx r12 | ||
| 49 | |||
| 50 | .section orphan, "ax", %progbits | ||
| 51 | .thumb | ||
| 52 | .globl orphan_target | ||
| 53 | .type orphan_target, %function | ||
| 54 | orphan_target: | ||
| 55 | bl low_target | ||
| 56 | bl high_target | ||
| 57 | // CHECK: Disassembly of section orphan: | ||
| 58 | // CHECK-NEXT: orphan_target: | ||
| 59 | // CHECK-NEXT: 2000014: ff f7 f8 ff bl #-16 | ||
| 60 | // CHECK-NEXT: 2000018: ff f7 f2 ff bl #-28 | ||
| 61 | |||
| 62 | .data | ||
| 63 | .word 10 | ||
deps/lld/test/ELF/arm-thunk-linkerscript-sort.s created+71| ... | @@ -0,0 +1,71 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: echo "SECTIONS { \ | ||
| 4 | // RUN: .text 0x100000 : { *(SORT_BY_NAME(.text.*)) } \ | ||
| 5 | // RUN: }" > %t.script | ||
| 6 | // RUN: ld.lld --script %t.script %t -o %t2 2>&1 | ||
| 7 | // RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048584 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 8 | // RUN: llvm-objdump -d %t2 -start-address=16777220 -stop-address=16777230 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 9 | |||
| 10 | .syntax unified | ||
| 11 | |||
| 12 | // Test that linkerscript sorting does not apply to Thunks, we expect that the | ||
| 13 | // sort will reverse the order of sections presented here. | ||
| 14 | |||
| 15 | // Define a function aligned on a megabyte boundary | ||
| 16 | .macro FUNCTION suff | ||
| 17 | .section .text.\suff\(), "ax", %progbits | ||
| 18 | .thumb | ||
| 19 | .balign 0x100000 | ||
| 20 | .globl tfunc\suff\() | ||
| 21 | .type tfunc\suff\(), %function | ||
| 22 | tfunc\suff\(): | ||
| 23 | bx lr | ||
| 24 | .endm | ||
| 25 | |||
| 26 | FUNCTION 31 | ||
| 27 | FUNCTION 30 | ||
| 28 | FUNCTION 29 | ||
| 29 | FUNCTION 28 | ||
| 30 | FUNCTION 27 | ||
| 31 | FUNCTION 26 | ||
| 32 | FUNCTION 25 | ||
| 33 | FUNCTION 24 | ||
| 34 | FUNCTION 23 | ||
| 35 | FUNCTION 22 | ||
| 36 | FUNCTION 21 | ||
| 37 | FUNCTION 20 | ||
| 38 | FUNCTION 19 | ||
| 39 | FUNCTION 18 | ||
| 40 | FUNCTION 17 | ||
| 41 | FUNCTION 16 | ||
| 42 | FUNCTION 15 | ||
| 43 | // CHECK2: __Thumbv7ABSLongThunk_tfunc31: | ||
| 44 | // CHECK2-NEXT: 1000004: 40 f2 01 0c movw r12, #1 | ||
| 45 | // CHECK2-NEXT: 1000008: c0 f2 00 2c movt r12, #512 | ||
| 46 | // CHECK2-NEXT: 100000c: 60 47 bx r12 | ||
| 47 | FUNCTION 14 | ||
| 48 | FUNCTION 13 | ||
| 49 | FUNCTION 12 | ||
| 50 | FUNCTION 11 | ||
| 51 | FUNCTION 10 | ||
| 52 | FUNCTION 09 | ||
| 53 | FUNCTION 08 | ||
| 54 | FUNCTION 07 | ||
| 55 | FUNCTION 06 | ||
| 56 | FUNCTION 05 | ||
| 57 | FUNCTION 04 | ||
| 58 | FUNCTION 03 | ||
| 59 | FUNCTION 02 | ||
| 60 | FUNCTION 01 | ||
| 61 | .section .text.00, "ax", %progbits | ||
| 62 | .thumb | ||
| 63 | .globl _start | ||
| 64 | _start: | ||
| 65 | // Expect no range extension needed for tfunc01 and an extension needed for | ||
| 66 | // tfunc31 | ||
| 67 | bl tfunc01 | ||
| 68 | bl tfunc31 | ||
| 69 | // CHECK1: _start: | ||
| 70 | // CHECK1-NEXT: 100000: ff f0 fe ff bl #1048572 | ||
| 71 | // CHECK1-NEXT: 100004: ff f2 fe d7 bl #15728636 | ||
deps/lld/test/ELF/arm-thunk-linkerscript.s created+78| ... | @@ -0,0 +1,78 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: echo "SECTIONS { \ | ||
| 3 | // RUN: . = SIZEOF_HEADERS; \ | ||
| 4 | // RUN: .text_low : { *(.text_low) *(.text_low2) } \ | ||
| 5 | // RUN: .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \ | ||
| 6 | // RUN: } " > %t.script | ||
| 7 | // RUN: ld.lld --script %t.script %t -o %t2 2>&1 | ||
| 8 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s | ||
| 9 | // REQUIRES: arm | ||
| 10 | // Simple test that we can support range extension thunks with linker scripts | ||
| 11 | .syntax unified | ||
| 12 | .section .text_low, "ax", %progbits | ||
| 13 | .thumb | ||
| 14 | .globl _start | ||
| 15 | _start: bx lr | ||
| 16 | .globl low_target | ||
| 17 | .type low_target, %function | ||
| 18 | low_target: | ||
| 19 | bl high_target | ||
| 20 | bl high_target2 | ||
| 21 | |||
| 22 | .section .text_low2, "ax", %progbits | ||
| 23 | .thumb | ||
| 24 | .globl low_target2 | ||
| 25 | .type low_target2, %function | ||
| 26 | low_target2: | ||
| 27 | bl high_target | ||
| 28 | bl high_target2 | ||
| 29 | |||
| 30 | // CHECK: Disassembly of section .text_low: | ||
| 31 | // CHECK-NEXT: _start: | ||
| 32 | // CHECK-NEXT: 94: 70 47 bx lr | ||
| 33 | // CHECK: low_target: | ||
| 34 | // CHECK-NEXT: 96: 00 f0 03 f8 bl #6 | ||
| 35 | // CHECK-NEXT: 9a: 00 f0 06 f8 bl #12 | ||
| 36 | // CHECK: __Thumbv7ABSLongThunk_high_target: | ||
| 37 | // CHECK-NEXT: a0: 40 f2 01 0c movw r12, #1 | ||
| 38 | // CHECK-NEXT: a4: c0 f2 00 2c movt r12, #512 | ||
| 39 | // CHECK-NEXT: a8: 60 47 bx r12 | ||
| 40 | // CHECK: __Thumbv7ABSLongThunk_high_target2: | ||
| 41 | // CHECK-NEXT: aa: 40 f2 1d 0c movw r12, #29 | ||
| 42 | // CHECK-NEXT: ae: c0 f2 00 2c movt r12, #512 | ||
| 43 | // CHECK-NEXT: b2: 60 47 bx r12 | ||
| 44 | // CHECK: low_target2: | ||
| 45 | // CHECK-NEXT: b4: ff f7 f4 ff bl #-24 | ||
| 46 | // CHECK-NEXT: b8: ff f7 f7 ff bl #-18 | ||
| 47 | |||
| 48 | .section .text_high, "ax", %progbits | ||
| 49 | .thumb | ||
| 50 | .globl high_target | ||
| 51 | .type high_target, %function | ||
| 52 | high_target: | ||
| 53 | bl low_target | ||
| 54 | bl low_target2 | ||
| 55 | |||
| 56 | .section .text_high2, "ax", %progbits | ||
| 57 | .thumb | ||
| 58 | .globl high_target2 | ||
| 59 | .type high_target2, %function | ||
| 60 | high_target2: | ||
| 61 | bl low_target | ||
| 62 | bl low_target2 | ||
| 63 | |||
| 64 | // CHECK: Disassembly of section .text_high: | ||
| 65 | // CHECK-NEXT: high_target: | ||
| 66 | // CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4 | ||
| 67 | // CHECK-NEXT: 2000004: 00 f0 05 f8 bl #10 | ||
| 68 | // CHECK: __Thumbv7ABSLongThunk_low_target: | ||
| 69 | // CHECK-NEXT: 2000008: 40 f2 97 0c movw r12, #151 | ||
| 70 | // CHECK-NEXT: 200000c: c0 f2 00 0c movt r12, #0 | ||
| 71 | // CHECK-NEXT: 2000010: 60 47 bx r12 | ||
| 72 | // CHECK: __Thumbv7ABSLongThunk_low_target2: | ||
| 73 | // CHECK-NEXT: 2000012: 40 f2 b5 0c movw r12, #181 | ||
| 74 | // CHECK-NEXT: 2000016: c0 f2 00 0c movt r12, #0 | ||
| 75 | // CHECK-NEXT: 200001a: 60 47 bx r12 | ||
| 76 | // CHECK: high_target2: | ||
| 77 | // CHECK-NEXT: 200001c: ff f7 f4 ff bl #-24 | ||
| 78 | // CHECK-NEXT: 2000020: ff f7 f7 ff bl #-18 | ||
deps/lld/test/ELF/arm-thunk-multipass.s created+96| ... | @@ -0,0 +1,96 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: ld.lld %t -o %t2 2>&1 | ||
| 4 | // The output file is large, most of it zeroes. We dissassemble only the | ||
| 5 | // parts we need to speed up the test and avoid a large output file | ||
| 6 | // RUN: llvm-objdump -d %t2 -start-address=1048578 -stop-address=1048586 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 7 | // RUN: llvm-objdump -d %t2 -start-address=16777224 -stop-address=16777254 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 8 | // RUN: llvm-objdump -d %t2 -start-address=17825818 -stop-address=17825828 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s | ||
| 9 | // In this test case a branch that is in range and does not need its range | ||
| 10 | // extended can be pushed out of range by another Thunk, necessitating another | ||
| 11 | // pass | ||
| 12 | |||
| 13 | .macro FUNCTION suff | ||
| 14 | .section .text.\suff\(), "ax", %progbits | ||
| 15 | .thumb | ||
| 16 | .balign 0x100000 | ||
| 17 | .globl tfunc\suff\() | ||
| 18 | .type tfunc\suff\(), %function | ||
| 19 | tfunc\suff\(): | ||
| 20 | bx lr | ||
| 21 | .endm | ||
| 22 | |||
| 23 | FUNCTION 00 | ||
| 24 | .globl _start | ||
| 25 | _start: | ||
| 26 | bl target | ||
| 27 | b.w arm_target | ||
| 28 | // arm_target is in range but needs an interworking thunk | ||
| 29 | // CHECK1: _start: | ||
| 30 | // CHECK1-NEXT: 100002: 00 f3 06 d0 bl #15728652 | ||
| 31 | // CHECK1-NEXT: 100006: ff f2 ff 97 b.w #15728638 <__Thumbv7ABSLongThunk_arm_target> | ||
| 32 | nop | ||
| 33 | nop | ||
| 34 | nop | ||
| 35 | .globl target2 | ||
| 36 | .type target2, %function | ||
| 37 | nop | ||
| 38 | |||
| 39 | target2: | ||
| 40 | FUNCTION 01 | ||
| 41 | FUNCTION 02 | ||
| 42 | FUNCTION 03 | ||
| 43 | FUNCTION 04 | ||
| 44 | FUNCTION 05 | ||
| 45 | FUNCTION 06 | ||
| 46 | FUNCTION 07 | ||
| 47 | FUNCTION 08 | ||
| 48 | FUNCTION 09 | ||
| 49 | FUNCTION 10 | ||
| 50 | FUNCTION 11 | ||
| 51 | FUNCTION 12 | ||
| 52 | FUNCTION 13 | ||
| 53 | FUNCTION 14 | ||
| 54 | FUNCTION 15 | ||
| 55 | |||
| 56 | .section .text.16, "ax", %progbits | ||
| 57 | .arm | ||
| 58 | .globl arm_target | ||
| 59 | .type arm_target, %function | ||
| 60 | arm_target: | ||
| 61 | bx lr | ||
| 62 | // CHECK2: __Thumbv7ABSLongThunk_arm_target: | ||
| 63 | // CHECK2-NEXT: 1000008: 40 f2 02 0c movw r12, #2 | ||
| 64 | // CHECK2-NEXT: 100000c: c0 f2 00 1c movt r12, #256 | ||
| 65 | // CHECK2-NEXT: 1000010: 60 47 bx r12 | ||
| 66 | // CHECK2: __Thumbv7ABSLongThunk_target: | ||
| 67 | // CHECK2-NEXT: 1000012: 40 f2 1b 0c movw r12, #27 | ||
| 68 | // CHECK2-NEXT: 1000016: c0 f2 10 1c movt r12, #272 | ||
| 69 | // CHECK2-NEXT: 100001a: 60 47 bx r12 | ||
| 70 | // CHECK2: __Thumbv7ABSLongThunk_target2: | ||
| 71 | // CHECK2-NEXT: 100001c: 40 f2 13 0c movw r12, #19 | ||
| 72 | // CHECK2-NEXT: 1000020: c0 f2 10 0c movt r12, #16 | ||
| 73 | // CHECK2-NEXT: 1000024: 60 47 bx r12 | ||
| 74 | |||
| 75 | .section .text.17, "ax", %progbits | ||
| 76 | // Just enough space so that bl target is in range if no extension thunks are | ||
| 77 | // generated. | ||
| 78 | |||
| 79 | .space 0x100000 - 12 | ||
| 80 | |||
| 81 | .section .text.18, "ax", %progbits | ||
| 82 | .thumb | ||
| 83 | .globl target | ||
| 84 | .type target, %function | ||
| 85 | // target is at maximum ARM branch range away from caller. | ||
| 86 | target: | ||
| 87 | // Similar case in the backwards direction | ||
| 88 | bl target2 | ||
| 89 | nop | ||
| 90 | nop | ||
| 91 | bx lr | ||
| 92 | // CHECK3: target: | ||
| 93 | // CHECK3-NEXT: 110001a: ff f6 ff ff bl #-1048578 | ||
| 94 | // CHECK3-NEXT: 110001e: 00 bf nop | ||
| 95 | // CHECK3-NEXT: 1100020: 00 bf nop | ||
| 96 | // CHECK3-NEXT: 1100022: 70 47 bx lr | ||
deps/lld/test/ELF/arm-thunk-re-add.s created+123| ... | @@ -0,0 +1,123 @@ | ||
| 1 | // REQUIRES: arm | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 3 | // RUN: ld.lld %t --shared -o %t.so | ||
| 4 | // The output file is large, most of it zeroes. We dissassemble only the | ||
| 5 | // parts we need to speed up the test and avoid a large output file | ||
| 6 | // RUN: llvm-objdump -d %t.so -start-address=16777220 -stop-address=16777244 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s | ||
| 7 | // RUN: llvm-objdump -d %t.so -start-address=17825800 -stop-address=17825826 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s | ||
| 8 | // RUN: llvm-objdump -d %t.so -start-address=17825824 -stop-address=17825892 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s | ||
| 9 | |||
| 10 | // A branch to a Thunk that we create on pass N, can drift out of range if | ||
| 11 | // other Thunks are added in between. In this case we must create a new Thunk | ||
| 12 | // for the branch that is in range. We also need to make sure that if the | ||
| 13 | // destination of the Thunk is in the PLT the new Thunk also targets the PLT | ||
| 14 | .syntax unified | ||
| 15 | .thumb | ||
| 16 | |||
| 17 | .macro FUNCTION suff | ||
| 18 | .section .text.\suff\(), "ax", %progbits | ||
| 19 | .thumb | ||
| 20 | .balign 0x80000 | ||
| 21 | .globl tfunc\suff\() | ||
| 22 | .type tfunc\suff\(), %function | ||
| 23 | tfunc\suff\(): | ||
| 24 | bx lr | ||
| 25 | .endm | ||
| 26 | |||
| 27 | .globl imported | ||
| 28 | .type imported, %function | ||
| 29 | .globl imported2 | ||
| 30 | .type imported2, %function | ||
| 31 | .globl imported3 | ||
| 32 | .type imported3, %function | ||
| 33 | .globl imported4 | ||
| 34 | .type imported4, %function | ||
| 35 | FUNCTION 00 | ||
| 36 | FUNCTION 01 | ||
| 37 | FUNCTION 02 | ||
| 38 | FUNCTION 03 | ||
| 39 | FUNCTION 04 | ||
| 40 | FUNCTION 05 | ||
| 41 | FUNCTION 06 | ||
| 42 | FUNCTION 07 | ||
| 43 | FUNCTION 08 | ||
| 44 | FUNCTION 09 | ||
| 45 | FUNCTION 10 | ||
| 46 | FUNCTION 11 | ||
| 47 | FUNCTION 12 | ||
| 48 | FUNCTION 13 | ||
| 49 | FUNCTION 14 | ||
| 50 | FUNCTION 15 | ||
| 51 | FUNCTION 16 | ||
| 52 | FUNCTION 17 | ||
| 53 | FUNCTION 18 | ||
| 54 | FUNCTION 19 | ||
| 55 | FUNCTION 20 | ||
| 56 | FUNCTION 21 | ||
| 57 | FUNCTION 22 | ||
| 58 | FUNCTION 23 | ||
| 59 | FUNCTION 24 | ||
| 60 | FUNCTION 25 | ||
| 61 | FUNCTION 26 | ||
| 62 | FUNCTION 27 | ||
| 63 | FUNCTION 28 | ||
| 64 | FUNCTION 29 | ||
| 65 | FUNCTION 30 | ||
| 66 | FUNCTION 31 | ||
| 67 | // Precreated Thunk Pool goes here | ||
| 68 | // CHECK1: __ThumbV7PILongThunk_imported: | ||
| 69 | // CHECK1-NEXT: 1000004: 40 f2 30 0c movw r12, #48 | ||
| 70 | // CHECK1-NEXT: 1000008: c0 f2 10 0c movt r12, #16 | ||
| 71 | // CHECK1-NEXT: 100000c: fc 44 add r12, pc | ||
| 72 | // CHECK1-NEXT: 100000e: 60 47 bx r12 | ||
| 73 | // CHECK1: __ThumbV7PILongThunk_imported2: | ||
| 74 | // CHECK1-NEXT: 1000010: 40 f2 34 0c movw r12, #52 | ||
| 75 | // CHECK1-NEXT: 1000014: c0 f2 10 0c movt r12, #16 | ||
| 76 | // CHECK1-NEXT: 1000018: fc 44 add r12, pc | ||
| 77 | // CHECK1-NEXT: 100001a: 60 47 bx r12 | ||
| 78 | |||
| 79 | .section .text.32, "ax", %progbits | ||
| 80 | .space 0x80000 | ||
| 81 | .section .text.33, "ax", %progbits | ||
| 82 | .space 0x80000 - 0x14 | ||
| 83 | .section .text.34, "ax", %progbits | ||
| 84 | // Need a Thunk to the PLT entry, can use precreated ThunkSection | ||
| 85 | .globl callers | ||
| 86 | .type callers, %function | ||
| 87 | callers: | ||
| 88 | b.w imported | ||
| 89 | beq.w imported | ||
| 90 | b.w imported2 | ||
| 91 | // CHECK2: __ThumbV7PILongThunk_imported: | ||
| 92 | // CHECK2-NEXT: 1100008: 40 f2 2c 0c movw r12, #44 | ||
| 93 | // CHECK2-NEXT: 110000c: c0 f2 00 0c movt r12, #0 | ||
| 94 | // CHECK2-NEXT: 1100010: fc 44 add r12, pc | ||
| 95 | // CHECK2-NEXT: 1100012: 60 47 bx r12 | ||
| 96 | // CHECK2: callers: | ||
| 97 | // CHECK2-NEXT: 1100014: ff f6 f6 bf b.w #-1048596 <__ThumbV7PILongThunk_imported> | ||
| 98 | // CHECK2-NEXT: 1100018: 3f f4 f6 af beq.w #-20 <__ThumbV7PILongThunk_imported> | ||
| 99 | // CHECK2-NEXT: 110001c: ff f6 f8 bf b.w #-1048592 <__ThumbV7PILongThunk_imported2> | ||
| 100 | |||
| 101 | // CHECK3: Disassembly of section .plt: | ||
| 102 | // CHECK3-NEXT: $a: | ||
| 103 | // CHECK3-NEXT: 1100020: 04 e0 2d e5 str lr, [sp, #-4]! | ||
| 104 | // CHECK3-NEXT: 1100024: 00 e6 8f e2 add lr, pc, #0, #12 | ||
| 105 | // CHECK3-NEXT: 1100028: 00 ea 8e e2 add lr, lr, #0, #20 | ||
| 106 | // CHECK3-NEXT: 110002c: dc ff be e5 ldr pc, [lr, #4060]! | ||
| 107 | // CHECK3: $d: | ||
| 108 | // CHECK3-NEXT: 1100030: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 109 | // CHECK3-NEXT: 1100034: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 110 | // CHECK3-NEXT: 1100038: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 111 | // CHECK3-NEXT: 110003c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 112 | // CHECK3: $a: | ||
| 113 | // CHECK3-NEXT: 1100040: 00 c6 8f e2 add r12, pc, #0, #12 | ||
| 114 | // CHECK3-NEXT: 1100044: 00 ca 8c e2 add r12, r12, #0, #20 | ||
| 115 | // CHECK3-NEXT: 1100048: c4 ff bc e5 ldr pc, [r12, #4036]! | ||
| 116 | // CHECK3: $d: | ||
| 117 | // CHECK3-NEXT: 110004c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
| 118 | // CHECK3: $a: | ||
| 119 | // CHECK3-NEXT: 1100050: 00 c6 8f e2 add r12, pc, #0, #12 | ||
| 120 | // CHECK3-NEXT: 1100054: 00 ca 8c e2 add r12, r12, #0, #20 | ||
| 121 | // CHECK3-NEXT: 1100058: b8 ff bc e5 ldr pc, [r12, #4024]! | ||
| 122 | // CHECK3: $d: | ||
| 123 | // CHECK3-NEXT: 110005c: d4 d4 d4 d4 .word 0xd4d4d4d4 | ||
deps/lld/test/ELF/arm-thunk-toolargesection.s created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | ||
| 2 | // RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s | ||
| 3 | // REQUIRES: arm | ||
| 4 | .syntax unified | ||
| 5 | .balign 0x1000 | ||
| 6 | .thumb | ||
| 7 | .text | ||
| 8 | .globl _start | ||
| 9 | .type _start, %function | ||
| 10 | _start: | ||
| 11 | bx lr | ||
| 12 | |||
| 13 | .section .text.large1, "ax", %progbits | ||
| 14 | .balign 4 | ||
| 15 | .space (17 * 1024 * 1024) | ||
| 16 | bl _start | ||
| 17 | .space (17 * 1024 * 1024) | ||
| 18 | |||
| 19 | // CHECK: error: InputSection too large for range extension thunk {{.*}}.text.large1 | ||
deps/lld/test/ELF/arm-tls-gd-nonpreemptible.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | // RUN: ld.lld %t -o %t2 | 2 | // RUN: ld.lld %t -o %t2 |
| 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi | 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi |
| 4 | // RUN: llvm-objdump -s %t2 | FileCheck %s | 4 | // RUN: llvm-objdump -s %t2 | FileCheck %s |
| 5 | // RUN: ld.lld %t --shared -o %t3.so | 5 | // RUN: ld.lld --hash-style=sysv %t --shared -o %t3.so |
| 6 | // RUN: llvm-objdump -s %t3.so | FileCheck -check-prefix=CHECK-SHARED %s | 6 | // RUN: llvm-objdump -s %t3.so | FileCheck -check-prefix=CHECK-SHARED %s |
| 7 | // REQUIRES: arm | 7 | // REQUIRES: arm |
| 8 | 8 |
deps/lld/test/ELF/arm-tls-gd32.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi | 1 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi |
| 2 | // RUN: ld.lld %t.o -o %t.so -shared | 2 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 3 | // RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s | 3 | // RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s |
| 4 | // RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s | 4 | // RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s |
| 5 | // REQUIRES: arm | 5 | // REQUIRES: arm |
deps/lld/test/ELF/arm-tls-ie32.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi | 1 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi |
| 2 | // RUN: ld.lld %t.o -o %t.so -shared | 2 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 3 | // RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s | 3 | // RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s |
| 4 | // RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s | 4 | // RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s |
| 5 | // REQUIRES: arm | 5 | // REQUIRES: arm |
deps/lld/test/ELF/arm-tls-ldm32.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi | 1 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi |
| 2 | // RUN: ld.lld %t.o -o %t.so -shared | 2 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 3 | // RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s | 3 | // RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s |
| 4 | // RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s | 4 | // RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s |
| 5 | // REQUIRES: arm | 5 | // REQUIRES: arm |
deps/lld/test/ELF/arm-tls-norelax-gd-ie.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-tls-get-addr.s -o %t1 | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-tls-get-addr.s -o %t1 |
| 2 | // RUN: ld.lld %t1 --shared -o %t1.so | 2 | // RUN: ld.lld %t1 --shared -o %t1.so |
| 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi | 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi |
| 4 | // RUN: ld.lld %t1.so %t.o -o %t | 4 | // RUN: ld.lld --hash-style=sysv %t1.so %t.o -o %t |
| 5 | // RUN: llvm-readobj -s -dyn-relocations %t | FileCheck %s | 5 | // RUN: llvm-readobj -s -dyn-relocations %t | FileCheck %s |
| 6 | // REQUIRES: arm | 6 | // REQUIRES: arm |
| 7 | 7 |
deps/lld/test/ELF/arm-tls-norelax-gd-le.s+5-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-tls-get-addr.s -o %t1 | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-tls-get-addr.s -o %t1 |
| 2 | // RUN: ld.lld %t1 --shared -o %t1.so | 2 | // RUN: ld.lld %t1 --shared -o %t1.so |
| 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi | 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi |
| 4 | // RUN: ld.lld %t1.so %t.o -o %t | 4 | // RUN: ld.lld --hash-style=sysv %t1.so %t.o -o %t |
| 5 | // RUN: llvm-objdump -s %t | FileCheck %s | 5 | // RUN: llvm-objdump -s %t | FileCheck %s |
| 6 | // REQUIRES: arm | 6 | // REQUIRES: arm |
| 7 | 7 | ||
| ... | @@ -35,3 +35,7 @@ x: | ... | @@ -35,3 +35,7 @@ x: |
| 35 | // Module index is always 1 for executable | 35 | // Module index is always 1 for executable |
| 36 | // CHECK-NEXT: 13060 01000000 00000000 | 36 | // CHECK-NEXT: 13060 01000000 00000000 |
| 37 | 37 | ||
| 38 | |||
| 39 | // Without any definition of __tls_get_addr we get an error | ||
| 40 | // RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck --check-prefix=ERR %s | ||
| 41 | // ERR: error: undefined symbol: __tls_get_addr |
deps/lld/test/ELF/arm-tls-norelax-ie-le.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-tls-get-addr.s -o %t1 | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-tls-get-addr.s -o %t1 |
| 2 | // RUN: ld.lld %t1 --shared -o %t1.so | 2 | // RUN: ld.lld %t1 --shared -o %t1.so |
| 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi | 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi |
| 4 | // RUN: ld.lld %t1.so %t.o -o %t | 4 | // RUN: ld.lld --hash-style=sysv %t1.so %t.o -o %t |
| 5 | // RUN: llvm-objdump -s -triple=armv7a-linux-gnueabi %t | FileCheck %s | 5 | // RUN: llvm-objdump -s -triple=armv7a-linux-gnueabi %t | FileCheck %s |
| 6 | // REQUIRES: arm | 6 | // REQUIRES: arm |
| 7 | 7 |
deps/lld/test/ELF/arm-tls-norelax-ld-le.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-tls-get-addr.s -o %t1 | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-tls-get-addr.s -o %t1 |
| 2 | // RUN: ld.lld %t1 --shared -o %t1.so | 2 | // RUN: ld.lld %t1 --shared -o %t1.so |
| 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi | 3 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi |
| 4 | // RUN: ld.lld %t1.so %t.o -o %t | 4 | // RUN: ld.lld --hash-style=sysv %t1.so %t.o -o %t |
| 5 | // RUN: llvm-objdump -s %t | FileCheck %s | 5 | // RUN: llvm-objdump -s %t | FileCheck %s |
| 6 | // REQUIRES: arm | 6 | // REQUIRES: arm |
| 7 | 7 |
deps/lld/test/ELF/arm-undefined-weak.s+1-1| ... | @@ -32,7 +32,7 @@ _start: | ... | @@ -32,7 +32,7 @@ _start: |
| 32 | // CHECK: 11000: {{.*}} b #-4 <_start+0x4> | 32 | // CHECK: 11000: {{.*}} b #-4 <_start+0x4> |
| 33 | // CHECK-NEXT: 11004: {{.*}} bl #-4 <_start+0x8> | 33 | // CHECK-NEXT: 11004: {{.*}} bl #-4 <_start+0x8> |
| 34 | // blx is transformed into bl so we don't change state | 34 | // blx is transformed into bl so we don't change state |
| 35 | // CHECK-NEXT: 11008: {{.*}} bl #-4 <_start+0xC> | 35 | // CHECK-NEXT: 11008: {{.*}} bl #-4 <_start+0xc> |
| 36 | // CHECK-NEXT: 1100c: {{.*}} movt r0, #0 | 36 | // CHECK-NEXT: 1100c: {{.*}} movt r0, #0 |
| 37 | // CHECK-NEXT: 11010: {{.*}} movw r0, #0 | 37 | // CHECK-NEXT: 11010: {{.*}} movw r0, #0 |
| 38 | // CHECK: 11014: {{.*}} .word 0x00000000 | 38 | // CHECK: 11014: {{.*}} .word 0x00000000 |
deps/lld/test/ELF/as-needed.s+4| ... | @@ -15,6 +15,10 @@ | ... | @@ -15,6 +15,10 @@ |
| 15 | // RUN: ld.lld --as-needed %t.o %t2.so %t3.so %t4.so -o %t2 | 15 | // 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 %s | 16 | // RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s |
| 17 | 17 | ||
| 18 | // Test with the .o last | ||
| 19 | // 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 %s | ||
| 21 | |||
| 18 | // RUN: ld.lld --as-needed %t.o %t2.so --no-as-needed %t3.so %t4.so -o %t2 | 22 | // RUN: ld.lld --as-needed %t.o %t2.so --no-as-needed %t3.so %t4.so -o %t2 |
| 19 | // RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s | 23 | // RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s |
| 20 | 24 |
deps/lld/test/ELF/assignment-archive.s created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %ta.o | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t.o < /dev/null | ||
| 4 | # RUN: rm -f %tar.a | ||
| 5 | # RUN: llvm-ar rcs %tar.a %ta.o | ||
| 6 | |||
| 7 | # RUN: echo "SECTIONS { foo = 1; }" > %t1.script | ||
| 8 | # RUN: ld.lld -o %t1.exe --script %t1.script %tar.a %t.o | ||
| 9 | # RUN: llvm-readobj -symbols %t1.exe | FileCheck %s | ||
| 10 | # CHECK-NOT: bar | ||
| 11 | # CHECK: foo | ||
| 12 | # CHECK-NOT: bar | ||
| 13 | |||
| 14 | # RUN: echo "SECTIONS { zed = foo; }" > %t2.script | ||
| 15 | # RUN: ld.lld -o %t2.exe --script %t2.script %tar.a %t.o | ||
| 16 | # RUN: llvm-readobj -symbols %t2.exe | FileCheck %s --check-prefix=SYMS | ||
| 17 | # SYMS: bar | ||
| 18 | # SYMS: foo | ||
| 19 | |||
| 20 | .text | ||
| 21 | .globl foo | ||
| 22 | foo: | ||
| 23 | nop | ||
| 24 | |||
| 25 | .globl bar | ||
| 26 | bar: | ||
| 27 | nop | ||
deps/lld/test/ELF/avoid-empty-program-headers.s+3-3| ... | @@ -42,8 +42,8 @@ _start: | ... | @@ -42,8 +42,8 @@ _start: |
| 42 | // CHECK-NEXT: Offset: 0x1000 | 42 | // CHECK-NEXT: Offset: 0x1000 |
| 43 | // CHECK-NEXT: VirtualAddress: 0x201000 | 43 | // CHECK-NEXT: VirtualAddress: 0x201000 |
| 44 | // CHECK-NEXT: PhysicalAddress: 0x201000 | 44 | // CHECK-NEXT: PhysicalAddress: 0x201000 |
| 45 | // CHECK-NEXT: FileSize: 1 | 45 | // CHECK-NEXT: FileSize: 4096 |
| 46 | // CHECK-NEXT: MemSize: 1 | 46 | // CHECK-NEXT: MemSize: 4096 |
| 47 | // CHECK-NEXT: Flags [ (0x5) | 47 | // CHECK-NEXT: Flags [ (0x5) |
| 48 | // CHECK-NEXT: PF_R (0x4) | 48 | // CHECK-NEXT: PF_R (0x4) |
| 49 | // CHECK-NEXT: PF_X (0x1) | 49 | // CHECK-NEXT: PF_X (0x1) |
| ... | @@ -52,7 +52,7 @@ _start: | ... | @@ -52,7 +52,7 @@ _start: |
| 52 | // CHECK-NEXT: } | 52 | // CHECK-NEXT: } |
| 53 | // CHECK-NEXT: ProgramHeader { | 53 | // CHECK-NEXT: ProgramHeader { |
| 54 | // CHECK-NEXT: Type: PT_TLS (0x7) | 54 | // CHECK-NEXT: Type: PT_TLS (0x7) |
| 55 | // CHECK-NEXT: Offset: 0x1001 | 55 | // CHECK-NEXT: Offset: 0x2000 |
| 56 | // CHECK-NEXT: VirtualAddress: 0x201001 | 56 | // CHECK-NEXT: VirtualAddress: 0x201001 |
| 57 | // CHECK-NEXT: PhysicalAddress: 0x201001 | 57 | // CHECK-NEXT: PhysicalAddress: 0x201001 |
| 58 | // CHECK-NEXT: FileSize: 0 | 58 | // CHECK-NEXT: FileSize: 0 |
deps/lld/test/ELF/basic-aarch64.s+8-8| ... | @@ -26,7 +26,7 @@ _start: | ... | @@ -26,7 +26,7 @@ _start: |
| 26 | # CHECK-NEXT: Version: 1 | 26 | # CHECK-NEXT: Version: 1 |
| 27 | # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] | 27 | # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] |
| 28 | # CHECK-NEXT: ProgramHeaderOffset: 0x40 | 28 | # CHECK-NEXT: ProgramHeaderOffset: 0x40 |
| 29 | # CHECK-NEXT: SectionHeaderOffset: 0x10098 | 29 | # CHECK-NEXT: SectionHeaderOffset: 0x11088 |
| 30 | # CHECK-NEXT: Flags [ (0x0) | 30 | # CHECK-NEXT: Flags [ (0x0) |
| 31 | # CHECK-NEXT: ] | 31 | # CHECK-NEXT: ] |
| 32 | # CHECK-NEXT: HeaderSize: 64 | 32 | # CHECK-NEXT: HeaderSize: 64 |
| ... | @@ -76,12 +76,12 @@ _start: | ... | @@ -76,12 +76,12 @@ _start: |
| 76 | # CHECK-NEXT: SHF_STRINGS (0x20) | 76 | # CHECK-NEXT: SHF_STRINGS (0x20) |
| 77 | # CHECK-NEXT: ] | 77 | # CHECK-NEXT: ] |
| 78 | # CHECK-NEXT: Address: 0x0 | 78 | # CHECK-NEXT: Address: 0x0 |
| 79 | # CHECK-NEXT: Offset: 0x1000C | 79 | # CHECK-NEXT: Offset: 0x11000 |
| 80 | # CHECK-NEXT: Size: 8 | 80 | # CHECK-NEXT: Size: 8 |
| 81 | # CHECK-NEXT: Link: 0 | 81 | # CHECK-NEXT: Link: 0 |
| 82 | # CHECK-NEXT: Info: 0 | 82 | # CHECK-NEXT: Info: 0 |
| 83 | # CHECK-NEXT: AddressAlignment: 1 | 83 | # CHECK-NEXT: AddressAlignment: 1 |
| 84 | # CHECK-NEXT: EntrySize: 0 | 84 | # CHECK-NEXT: EntrySize: 1 |
| 85 | # CHECK-NEXT: } | 85 | # CHECK-NEXT: } |
| 86 | # CHECK-NEXT: Section { | 86 | # CHECK-NEXT: Section { |
| 87 | # CHECK-NEXT: Index: 3 | 87 | # CHECK-NEXT: Index: 3 |
| ... | @@ -90,7 +90,7 @@ _start: | ... | @@ -90,7 +90,7 @@ _start: |
| 90 | # CHECK-NEXT: Flags [ (0x0) | 90 | # CHECK-NEXT: Flags [ (0x0) |
| 91 | # CHECK-NEXT: ] | 91 | # CHECK-NEXT: ] |
| 92 | # CHECK-NEXT: Address: 0x0 | 92 | # CHECK-NEXT: Address: 0x0 |
| 93 | # CHECK-NEXT: Offset: 0x10018 | 93 | # CHECK-NEXT: Offset: 0x11008 |
| 94 | # CHECK-NEXT: Size: 72 | 94 | # CHECK-NEXT: Size: 72 |
| 95 | # CHECK-NEXT: Link: 5 | 95 | # CHECK-NEXT: Link: 5 |
| 96 | # CHECK-NEXT: Info: 2 | 96 | # CHECK-NEXT: Info: 2 |
| ... | @@ -104,7 +104,7 @@ _start: | ... | @@ -104,7 +104,7 @@ _start: |
| 104 | # CHECK-NEXT: Flags [ (0x0) | 104 | # CHECK-NEXT: Flags [ (0x0) |
| 105 | # CHECK-NEXT: ] | 105 | # CHECK-NEXT: ] |
| 106 | # CHECK-NEXT: Address: 0x0 | 106 | # CHECK-NEXT: Address: 0x0 |
| 107 | # CHECK-NEXT: Offset: 0x10060 | 107 | # CHECK-NEXT: Offset: 0x11050 |
| 108 | # CHECK-NEXT: Size: 42 | 108 | # CHECK-NEXT: Size: 42 |
| 109 | # CHECK-NEXT: Link: 0 | 109 | # CHECK-NEXT: Link: 0 |
| 110 | # CHECK-NEXT: Info: 0 | 110 | # CHECK-NEXT: Info: 0 |
| ... | @@ -118,7 +118,7 @@ _start: | ... | @@ -118,7 +118,7 @@ _start: |
| 118 | # CHECK-NEXT: Flags [ (0x0) | 118 | # CHECK-NEXT: Flags [ (0x0) |
| 119 | # CHECK-NEXT: ] | 119 | # CHECK-NEXT: ] |
| 120 | # CHECK-NEXT: Address: 0x0 | 120 | # CHECK-NEXT: Address: 0x0 |
| 121 | # CHECK-NEXT: Offset: 0x1008A | 121 | # CHECK-NEXT: Offset: 0x1107A |
| 122 | # CHECK-NEXT: Size: 13 | 122 | # CHECK-NEXT: Size: 13 |
| 123 | # CHECK-NEXT: Link: 0 | 123 | # CHECK-NEXT: Link: 0 |
| 124 | # CHECK-NEXT: Info: 0 | 124 | # CHECK-NEXT: Info: 0 |
| ... | @@ -185,8 +185,8 @@ _start: | ... | @@ -185,8 +185,8 @@ _start: |
| 185 | # CHECK-NEXT: Offset: 0x1000 | 185 | # CHECK-NEXT: Offset: 0x1000 |
| 186 | # CHECK-NEXT: VirtualAddress: 0x20000 | 186 | # CHECK-NEXT: VirtualAddress: 0x20000 |
| 187 | # CHECK-NEXT: PhysicalAddress: 0x20000 | 187 | # CHECK-NEXT: PhysicalAddress: 0x20000 |
| 188 | # CHECK-NEXT: FileSize: 12 | 188 | # CHECK-NEXT: FileSize: 4096 |
| 189 | # CHECK-NEXT: MemSize: 12 | 189 | # CHECK-NEXT: MemSize: 4096 |
| 190 | # CHECK-NEXT: Flags [ (0x5) | 190 | # CHECK-NEXT: Flags [ (0x5) |
| 191 | # CHECK-NEXT: PF_R (0x4) | 191 | # CHECK-NEXT: PF_R (0x4) |
| 192 | # CHECK-NEXT: PF_X (0x1) | 192 | # CHECK-NEXT: PF_X (0x1) |
deps/lld/test/ELF/basic-mips.s+2-2| ... | @@ -164,7 +164,7 @@ __start: | ... | @@ -164,7 +164,7 @@ __start: |
| 164 | # CHECK-NEXT: Link: 0 | 164 | # CHECK-NEXT: Link: 0 |
| 165 | # CHECK-NEXT: Info: 0 | 165 | # CHECK-NEXT: Info: 0 |
| 166 | # CHECK-NEXT: AddressAlignment: 1 | 166 | # CHECK-NEXT: AddressAlignment: 1 |
| 167 | # CHECK-NEXT: EntrySize: 0 | 167 | # CHECK-NEXT: EntrySize: 1 |
| 168 | # CHECK-NEXT: } | 168 | # CHECK-NEXT: } |
| 169 | # CHECK-NEXT: Section { | 169 | # CHECK-NEXT: Section { |
| 170 | # CHECK-NEXT: Index: 8 | 170 | # CHECK-NEXT: Index: 8 |
| ... | @@ -228,7 +228,7 @@ __start: | ... | @@ -228,7 +228,7 @@ __start: |
| 228 | # CHECK-NEXT: Other [ (0x2) | 228 | # CHECK-NEXT: Other [ (0x2) |
| 229 | # CHECK-NEXT: STV_HIDDEN (0x2) | 229 | # CHECK-NEXT: STV_HIDDEN (0x2) |
| 230 | # CHECK-NEXT: ] | 230 | # CHECK-NEXT: ] |
| 231 | # CHECK-NEXT: Section: Absolute | 231 | # CHECK-NEXT: Section: .got |
| 232 | # CHECK-NEXT: } | 232 | # CHECK-NEXT: } |
| 233 | # CHECK-NEXT: Symbol { | 233 | # CHECK-NEXT: Symbol { |
| 234 | # CHECK-NEXT: Name: __start | 234 | # CHECK-NEXT: Name: __start |
deps/lld/test/ELF/basic-ppc.s+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | # RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t | 1 | # RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t |
| 2 | # RUN: ld.lld -discard-all -shared %t -o %t2 | 2 | # RUN: ld.lld --hash-style=sysv -discard-all -shared %t -o %t2 |
| 3 | # RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s | 3 | # RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s |
| 4 | # REQUIRES: ppc | 4 | # REQUIRES: ppc |
| 5 | 5 | ||
| ... | @@ -163,7 +163,7 @@ | ... | @@ -163,7 +163,7 @@ |
| 163 | // CHECK-NEXT: Link: 0 | 163 | // CHECK-NEXT: Link: 0 |
| 164 | // CHECK-NEXT: Info: 0 | 164 | // CHECK-NEXT: Info: 0 |
| 165 | // CHECK-NEXT: AddressAlignment: 1 | 165 | // CHECK-NEXT: AddressAlignment: 1 |
| 166 | // CHECK-NEXT: EntrySize: 0 | 166 | // CHECK-NEXT: EntrySize: 1 |
| 167 | // CHECK-NEXT: SectionData ( | 167 | // CHECK-NEXT: SectionData ( |
| 168 | // CHECK-NEXT: 0000: 4C4C4420 312E3000 |LLD 1.0.| | 168 | // CHECK-NEXT: 0000: 4C4C4420 312E3000 |LLD 1.0.| |
| 169 | // CHECK-NEXT: ) | 169 | // CHECK-NEXT: ) |
deps/lld/test/ELF/basic-sparcv9.s+8-8| ... | @@ -26,7 +26,7 @@ _start: | ... | @@ -26,7 +26,7 @@ _start: |
| 26 | # CHECK-NEXT: Version: 1 | 26 | # CHECK-NEXT: Version: 1 |
| 27 | # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] | 27 | # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] |
| 28 | # CHECK-NEXT: ProgramHeaderOffset: 0x40 | 28 | # CHECK-NEXT: ProgramHeaderOffset: 0x40 |
| 29 | # CHECK-NEXT: SectionHeaderOffset: 0x100080 | 29 | # CHECK-NEXT: SectionHeaderOffset: 0x102070 |
| 30 | # CHECK-NEXT: Flags [ (0x0) | 30 | # CHECK-NEXT: Flags [ (0x0) |
| 31 | # CHECK-NEXT: ] | 31 | # CHECK-NEXT: ] |
| 32 | # CHECK-NEXT: HeaderSize: 64 | 32 | # CHECK-NEXT: HeaderSize: 64 |
| ... | @@ -76,12 +76,12 @@ _start: | ... | @@ -76,12 +76,12 @@ _start: |
| 76 | # CHECK-NEXT: SHF_STRINGS (0x20) | 76 | # CHECK-NEXT: SHF_STRINGS (0x20) |
| 77 | # CHECK-NEXT: ] | 77 | # CHECK-NEXT: ] |
| 78 | # CHECK-NEXT: Address: 0x0 | 78 | # CHECK-NEXT: Address: 0x0 |
| 79 | # CHECK-NEXT: Offset: 0x10000C | 79 | # CHECK-NEXT: Offset: 0x102000 |
| 80 | # CHECK-NEXT: Size: 8 | 80 | # CHECK-NEXT: Size: 8 |
| 81 | # CHECK-NEXT: Link: 0 | 81 | # CHECK-NEXT: Link: 0 |
| 82 | # CHECK-NEXT: Info: 0 | 82 | # CHECK-NEXT: Info: 0 |
| 83 | # CHECK-NEXT: AddressAlignment: 1 | 83 | # CHECK-NEXT: AddressAlignment: 1 |
| 84 | # CHECK-NEXT: EntrySize: 0 | 84 | # CHECK-NEXT: EntrySize: 1 |
| 85 | # CHECK-NEXT: } | 85 | # CHECK-NEXT: } |
| 86 | # CHECK-NEXT: Section { | 86 | # CHECK-NEXT: Section { |
| 87 | # CHECK-NEXT: Index: 3 | 87 | # CHECK-NEXT: Index: 3 |
| ... | @@ -90,7 +90,7 @@ _start: | ... | @@ -90,7 +90,7 @@ _start: |
| 90 | # CHECK-NEXT: Flags [ (0x0) | 90 | # CHECK-NEXT: Flags [ (0x0) |
| 91 | # CHECK-NEXT: ] | 91 | # CHECK-NEXT: ] |
| 92 | # CHECK-NEXT: Address: 0x0 | 92 | # CHECK-NEXT: Address: 0x0 |
| 93 | # CHECK-NEXT: Offset: 0x100018 | 93 | # CHECK-NEXT: Offset: 0x102008 |
| 94 | # CHECK-NEXT: Size: 48 | 94 | # CHECK-NEXT: Size: 48 |
| 95 | # CHECK-NEXT: Link: 5 | 95 | # CHECK-NEXT: Link: 5 |
| 96 | # CHECK-NEXT: Info: 1 | 96 | # CHECK-NEXT: Info: 1 |
| ... | @@ -104,7 +104,7 @@ _start: | ... | @@ -104,7 +104,7 @@ _start: |
| 104 | # CHECK-NEXT: Flags [ (0x0) | 104 | # CHECK-NEXT: Flags [ (0x0) |
| 105 | # CHECK-NEXT: ] | 105 | # CHECK-NEXT: ] |
| 106 | # CHECK-NEXT: Address: 0x0 | 106 | # CHECK-NEXT: Address: 0x0 |
| 107 | # CHECK-NEXT: Offset: 0x100048 | 107 | # CHECK-NEXT: Offset: 0x102038 |
| 108 | # CHECK-NEXT: Size: 42 | 108 | # CHECK-NEXT: Size: 42 |
| 109 | # CHECK-NEXT: Link: 0 | 109 | # CHECK-NEXT: Link: 0 |
| 110 | # CHECK-NEXT: Info: 0 | 110 | # CHECK-NEXT: Info: 0 |
| ... | @@ -118,7 +118,7 @@ _start: | ... | @@ -118,7 +118,7 @@ _start: |
| 118 | # CHECK-NEXT: Flags [ (0x0) | 118 | # CHECK-NEXT: Flags [ (0x0) |
| 119 | # CHECK-NEXT: ] | 119 | # CHECK-NEXT: ] |
| 120 | # CHECK-NEXT: Address: 0x0 | 120 | # CHECK-NEXT: Address: 0x0 |
| 121 | # CHECK-NEXT: Offset: 0x100072 | 121 | # CHECK-NEXT: Offset: 0x102062 |
| 122 | # CHECK-NEXT: Size: 8 | 122 | # CHECK-NEXT: Size: 8 |
| 123 | # CHECK-NEXT: Link: 0 | 123 | # CHECK-NEXT: Link: 0 |
| 124 | # CHECK-NEXT: Info: 0 | 124 | # CHECK-NEXT: Info: 0 |
| ... | @@ -176,8 +176,8 @@ _start: | ... | @@ -176,8 +176,8 @@ _start: |
| 176 | # CHECK-NEXT: Offset: 0x100000 | 176 | # CHECK-NEXT: Offset: 0x100000 |
| 177 | # CHECK-NEXT: VirtualAddress: 0x200000 | 177 | # CHECK-NEXT: VirtualAddress: 0x200000 |
| 178 | # CHECK-NEXT: PhysicalAddress: 0x200000 | 178 | # CHECK-NEXT: PhysicalAddress: 0x200000 |
| 179 | # CHECK-NEXT: FileSize: 12 | 179 | # CHECK-NEXT: FileSize: 8192 |
| 180 | # CHECK-NEXT: MemSize: 12 | 180 | # CHECK-NEXT: MemSize: 8192 |
| 181 | # CHECK-NEXT: Flags [ (0x5) | 181 | # CHECK-NEXT: Flags [ (0x5) |
| 182 | # CHECK-NEXT: PF_R (0x4) | 182 | # CHECK-NEXT: PF_R (0x4) |
| 183 | # CHECK-NEXT: PF_X (0x1) | 183 | # CHECK-NEXT: PF_X (0x1) |
deps/lld/test/ELF/basic.s+10-8| ... | @@ -28,7 +28,7 @@ _start: | ... | @@ -28,7 +28,7 @@ _start: |
| 28 | # CHECK-NEXT: Version: 1 | 28 | # CHECK-NEXT: Version: 1 |
| 29 | # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] | 29 | # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] |
| 30 | # CHECK-NEXT: ProgramHeaderOffset: 0x40 | 30 | # CHECK-NEXT: ProgramHeaderOffset: 0x40 |
| 31 | # CHECK-NEXT: SectionHeaderOffset: 0x1080 | 31 | # CHECK-NEXT: SectionHeaderOffset: 0x2070 |
| 32 | # CHECK-NEXT: Flags [ (0x0) | 32 | # CHECK-NEXT: Flags [ (0x0) |
| 33 | # CHECK-NEXT: ] | 33 | # CHECK-NEXT: ] |
| 34 | # CHECK-NEXT: HeaderSize: 64 | 34 | # CHECK-NEXT: HeaderSize: 64 |
| ... | @@ -78,12 +78,12 @@ _start: | ... | @@ -78,12 +78,12 @@ _start: |
| 78 | # CHECK-NEXT: SHF_STRINGS (0x20) | 78 | # CHECK-NEXT: SHF_STRINGS (0x20) |
| 79 | # CHECK-NEXT: ] | 79 | # CHECK-NEXT: ] |
| 80 | # CHECK-NEXT: Address: 0x0 | 80 | # CHECK-NEXT: Address: 0x0 |
| 81 | # CHECK-NEXT: Offset: 0x1010 | 81 | # CHECK-NEXT: Offset: 0x2000 |
| 82 | # CHECK-NEXT: Size: 8 | 82 | # CHECK-NEXT: Size: 8 |
| 83 | # CHECK-NEXT: Link: 0 | 83 | # CHECK-NEXT: Link: 0 |
| 84 | # CHECK-NEXT: Info: 0 | 84 | # CHECK-NEXT: Info: 0 |
| 85 | # CHECK-NEXT: AddressAlignment: 1 | 85 | # CHECK-NEXT: AddressAlignment: 1 |
| 86 | # CHECK-NEXT: EntrySize: 0 | 86 | # CHECK-NEXT: EntrySize: 1 |
| 87 | # CHECK-NEXT: } | 87 | # CHECK-NEXT: } |
| 88 | # CHECK-NEXT: Section { | 88 | # CHECK-NEXT: Section { |
| 89 | # CHECK-NEXT: Index: 3 | 89 | # CHECK-NEXT: Index: 3 |
| ... | @@ -92,7 +92,7 @@ _start: | ... | @@ -92,7 +92,7 @@ _start: |
| 92 | # CHECK-NEXT: Flags [ (0x0) | 92 | # CHECK-NEXT: Flags [ (0x0) |
| 93 | # CHECK-NEXT: ] | 93 | # CHECK-NEXT: ] |
| 94 | # CHECK-NEXT: Address: 0x0 | 94 | # CHECK-NEXT: Address: 0x0 |
| 95 | # CHECK-NEXT: Offset: 0x1018 | 95 | # CHECK-NEXT: Offset: 0x2008 |
| 96 | # CHECK-NEXT: Size: 48 | 96 | # CHECK-NEXT: Size: 48 |
| 97 | # CHECK-NEXT: Link: 5 | 97 | # CHECK-NEXT: Link: 5 |
| 98 | # CHECK-NEXT: Info: 1 | 98 | # CHECK-NEXT: Info: 1 |
| ... | @@ -106,7 +106,7 @@ _start: | ... | @@ -106,7 +106,7 @@ _start: |
| 106 | # CHECK-NEXT: Flags [ (0x0) | 106 | # CHECK-NEXT: Flags [ (0x0) |
| 107 | # CHECK-NEXT: ] | 107 | # CHECK-NEXT: ] |
| 108 | # CHECK-NEXT: Address: 0x0 | 108 | # CHECK-NEXT: Address: 0x0 |
| 109 | # CHECK-NEXT: Offset: 0x1048 | 109 | # CHECK-NEXT: Offset: 0x2038 |
| 110 | # CHECK-NEXT: Size: 42 | 110 | # CHECK-NEXT: Size: 42 |
| 111 | # CHECK-NEXT: Link: 0 | 111 | # CHECK-NEXT: Link: 0 |
| 112 | # CHECK-NEXT: Info: 0 | 112 | # CHECK-NEXT: Info: 0 |
| ... | @@ -120,7 +120,7 @@ _start: | ... | @@ -120,7 +120,7 @@ _start: |
| 120 | # CHECK-NEXT: Flags [ (0x0) | 120 | # CHECK-NEXT: Flags [ (0x0) |
| 121 | # CHECK-NEXT: ] | 121 | # CHECK-NEXT: ] |
| 122 | # CHECK-NEXT: Address: 0x0 | 122 | # CHECK-NEXT: Address: 0x0 |
| 123 | # CHECK-NEXT: Offset: 0x1072 | 123 | # CHECK-NEXT: Offset: 0x2062 |
| 124 | # CHECK-NEXT: Size: 8 | 124 | # CHECK-NEXT: Size: 8 |
| 125 | # CHECK-NEXT: Link: 0 | 125 | # CHECK-NEXT: Link: 0 |
| 126 | # CHECK-NEXT: Info: 0 | 126 | # CHECK-NEXT: Info: 0 |
| ... | @@ -178,8 +178,8 @@ _start: | ... | @@ -178,8 +178,8 @@ _start: |
| 178 | # CHECK-NEXT: Offset: 0x1000 | 178 | # CHECK-NEXT: Offset: 0x1000 |
| 179 | # CHECK-NEXT: VirtualAddress: 0x201000 | 179 | # CHECK-NEXT: VirtualAddress: 0x201000 |
| 180 | # CHECK-NEXT: PhysicalAddress: 0x201000 | 180 | # CHECK-NEXT: PhysicalAddress: 0x201000 |
| 181 | # CHECK-NEXT: FileSize: 16 | 181 | # CHECK-NEXT: FileSize: 4096 |
| 182 | # CHECK-NEXT: MemSize: 16 | 182 | # CHECK-NEXT: MemSize: 4096 |
| 183 | # CHECK-NEXT: Flags [ (0x5) | 183 | # CHECK-NEXT: Flags [ (0x5) |
| 184 | # CHECK-NEXT: PF_R (0x4) | 184 | # CHECK-NEXT: PF_R (0x4) |
| 185 | # CHECK-NEXT: PF_X (0x1) | 185 | # CHECK-NEXT: PF_X (0x1) |
| ... | @@ -246,7 +246,9 @@ _start: | ... | @@ -246,7 +246,9 @@ _start: |
| 246 | # UNKNOWN_EMUL: unknown emulation: wrong_emul_fbsd | 246 | # UNKNOWN_EMUL: unknown emulation: wrong_emul_fbsd |
| 247 | 247 | ||
| 248 | # RUN: not ld.lld %t --lto-partitions=0 2>&1 | FileCheck --check-prefix=NOTHREADS %s | 248 | # RUN: not ld.lld %t --lto-partitions=0 2>&1 | FileCheck --check-prefix=NOTHREADS %s |
| 249 | # RUN: not ld.lld %t --plugin-opt=lto-partitions=0 2>&1 | FileCheck --check-prefix=NOTHREADS %s | ||
| 249 | # NOTHREADS: --lto-partitions: number of threads must be > 0 | 250 | # NOTHREADS: --lto-partitions: number of threads must be > 0 |
| 250 | 251 | ||
| 251 | # RUN: not ld.lld %t --thinlto-jobs=0 2>&1 | FileCheck --check-prefix=NOTHREADSTHIN %s | 252 | # 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 %s | ||
| 252 | # NOTHREADSTHIN: --thinlto-jobs: number of threads must be > 0 | 254 | # NOTHREADSTHIN: --thinlto-jobs: number of threads must be > 0 |
deps/lld/test/ELF/basic32.s+8-8| ... | @@ -25,7 +25,7 @@ _start: | ... | @@ -25,7 +25,7 @@ _start: |
| 25 | # CHECK-NEXT: Version: 1 | 25 | # CHECK-NEXT: Version: 1 |
| 26 | # CHECK-NEXT: Entry: 0x11000 | 26 | # CHECK-NEXT: Entry: 0x11000 |
| 27 | # CHECK-NEXT: ProgramHeaderOffset: 0x34 | 27 | # CHECK-NEXT: ProgramHeaderOffset: 0x34 |
| 28 | # CHECK-NEXT: SectionHeaderOffset: 0x1068 | 28 | # CHECK-NEXT: SectionHeaderOffset: 0x205C |
| 29 | # CHECK-NEXT: Flags [ (0x0) | 29 | # CHECK-NEXT: Flags [ (0x0) |
| 30 | # CHECK-NEXT: ] | 30 | # CHECK-NEXT: ] |
| 31 | # CHECK-NEXT: HeaderSize: 52 | 31 | # CHECK-NEXT: HeaderSize: 52 |
| ... | @@ -75,12 +75,12 @@ _start: | ... | @@ -75,12 +75,12 @@ _start: |
| 75 | # CHECK-NEXT: SHF_STRINGS (0x20) | 75 | # CHECK-NEXT: SHF_STRINGS (0x20) |
| 76 | # CHECK-NEXT: ] | 76 | # CHECK-NEXT: ] |
| 77 | # CHECK-NEXT: Address: 0x0 | 77 | # CHECK-NEXT: Address: 0x0 |
| 78 | # CHECK-NEXT: Offset: 0x100C | 78 | # CHECK-NEXT: Offset: 0x2000 |
| 79 | # CHECK-NEXT: Size: 8 | 79 | # CHECK-NEXT: Size: 8 |
| 80 | # CHECK-NEXT: Link: 0 | 80 | # CHECK-NEXT: Link: 0 |
| 81 | # CHECK-NEXT: Info: 0 | 81 | # CHECK-NEXT: Info: 0 |
| 82 | # CHECK-NEXT: AddressAlignment: 1 | 82 | # CHECK-NEXT: AddressAlignment: 1 |
| 83 | # CHECK-NEXT: EntrySize: 0 | 83 | # CHECK-NEXT: EntrySize: 1 |
| 84 | # CHECK-NEXT: } | 84 | # CHECK-NEXT: } |
| 85 | # CHECK-NEXT: Section { | 85 | # CHECK-NEXT: Section { |
| 86 | # CHECK-NEXT: Index: 3 | 86 | # CHECK-NEXT: Index: 3 |
| ... | @@ -89,7 +89,7 @@ _start: | ... | @@ -89,7 +89,7 @@ _start: |
| 89 | # CHECK-NEXT: Flags [ | 89 | # CHECK-NEXT: Flags [ |
| 90 | # CHECK-NEXT: ] | 90 | # CHECK-NEXT: ] |
| 91 | # CHECK-NEXT: Address: 0x0 | 91 | # CHECK-NEXT: Address: 0x0 |
| 92 | # CHECK-NEXT: Offset: 0x1014 | 92 | # CHECK-NEXT: Offset: 0x2008 |
| 93 | # CHECK-NEXT: Size: 32 | 93 | # CHECK-NEXT: Size: 32 |
| 94 | # CHECK-NEXT: Link: 5 | 94 | # CHECK-NEXT: Link: 5 |
| 95 | # CHECK-NEXT: Info: 1 | 95 | # CHECK-NEXT: Info: 1 |
| ... | @@ -103,7 +103,7 @@ _start: | ... | @@ -103,7 +103,7 @@ _start: |
| 103 | # CHECK-NEXT: Flags [ (0x0) | 103 | # CHECK-NEXT: Flags [ (0x0) |
| 104 | # CHECK-NEXT: ] | 104 | # CHECK-NEXT: ] |
| 105 | # CHECK-NEXT: Address: 0x0 | 105 | # CHECK-NEXT: Address: 0x0 |
| 106 | # CHECK-NEXT: Offset: 0x1034 | 106 | # CHECK-NEXT: Offset: 0x2028 |
| 107 | # CHECK-NEXT: Size: 42 | 107 | # CHECK-NEXT: Size: 42 |
| 108 | # CHECK-NEXT: Link: 0 | 108 | # CHECK-NEXT: Link: 0 |
| 109 | # CHECK-NEXT: Info: 0 | 109 | # CHECK-NEXT: Info: 0 |
| ... | @@ -117,7 +117,7 @@ _start: | ... | @@ -117,7 +117,7 @@ _start: |
| 117 | # CHECK-NEXT: Flags [ (0x0) | 117 | # CHECK-NEXT: Flags [ (0x0) |
| 118 | # CHECK-NEXT: ] | 118 | # CHECK-NEXT: ] |
| 119 | # CHECK-NEXT: Address: 0x0 | 119 | # CHECK-NEXT: Address: 0x0 |
| 120 | # CHECK-NEXT: Offset: 0x105E | 120 | # CHECK-NEXT: Offset: 0x2052 |
| 121 | # CHECK-NEXT: Size: 8 | 121 | # CHECK-NEXT: Size: 8 |
| 122 | # CHECK-NEXT: Link: 0 | 122 | # CHECK-NEXT: Link: 0 |
| 123 | # CHECK-NEXT: Info: 0 | 123 | # CHECK-NEXT: Info: 0 |
| ... | @@ -155,8 +155,8 @@ _start: | ... | @@ -155,8 +155,8 @@ _start: |
| 155 | # CHECK-NEXT: Offset: 0x1000 | 155 | # CHECK-NEXT: Offset: 0x1000 |
| 156 | # CHECK-NEXT: VirtualAddress: 0x11000 | 156 | # CHECK-NEXT: VirtualAddress: 0x11000 |
| 157 | # CHECK-NEXT: PhysicalAddress: 0x11000 | 157 | # CHECK-NEXT: PhysicalAddress: 0x11000 |
| 158 | # CHECK-NEXT: FileSize: 12 | 158 | # CHECK-NEXT: FileSize: 4096 |
| 159 | # CHECK-NEXT: MemSize: 12 | 159 | # CHECK-NEXT: MemSize: 4096 |
| 160 | # CHECK-NEXT: Flags [ (0x5) | 160 | # CHECK-NEXT: Flags [ (0x5) |
| 161 | # CHECK-NEXT: PF_R (0x4) | 161 | # CHECK-NEXT: PF_R (0x4) |
| 162 | # CHECK-NEXT: PF_X (0x1) | 162 | # CHECK-NEXT: PF_X (0x1) |
deps/lld/test/ELF/basic64be.s+1-1| ... | @@ -175,7 +175,7 @@ _start: | ... | @@ -175,7 +175,7 @@ _start: |
| 175 | # CHECK-NEXT: Link: 0 | 175 | # CHECK-NEXT: Link: 0 |
| 176 | # CHECK-NEXT: Info: 0 | 176 | # CHECK-NEXT: Info: 0 |
| 177 | # CHECK-NEXT: AddressAlignment: 1 | 177 | # CHECK-NEXT: AddressAlignment: 1 |
| 178 | # CHECK-NEXT: EntrySize: 0 | 178 | # CHECK-NEXT: EntrySize: 1 |
| 179 | # CHECK-NEXT: SectionData ( | 179 | # CHECK-NEXT: SectionData ( |
| 180 | # CHECK-NEXT: 0000: 4C4C4420 312E3000 |LLD 1.0.| | 180 | # CHECK-NEXT: 0000: 4C4C4420 312E3000 |LLD 1.0.| |
| 181 | # CHECK-NEXT: ) | 181 | # CHECK-NEXT: ) |
deps/lld/test/ELF/build-id.s+18-3| ... | @@ -2,6 +2,9 @@ | ... | @@ -2,6 +2,9 @@ |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | 4 | ||
| 5 | # RUN: ld.lld --build-id %t -o %t2 | ||
| 6 | # RUN: llvm-readobj -s %t2 | FileCheck -check-prefix=ALIGN %s | ||
| 7 | |||
| 5 | # RUN: ld.lld --build-id %t -o %t2 -threads | 8 | # RUN: ld.lld --build-id %t -o %t2 -threads |
| 6 | # RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=DEFAULT %s | 9 | # RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=DEFAULT %s |
| 7 | # RUN: ld.lld --build-id %t -o %t2 -no-threads | 10 | # RUN: ld.lld --build-id %t -o %t2 -no-threads |
| ... | @@ -45,18 +48,30 @@ _start: | ... | @@ -45,18 +48,30 @@ _start: |
| 45 | .section .note.test, "a", @note | 48 | .section .note.test, "a", @note |
| 46 | .quad 42 | 49 | .quad 42 |
| 47 | 50 | ||
| 51 | # ALIGN: Name: .note.gnu.build-id | ||
| 52 | # ALIGN-NEXT: Type: SHT_NOTE | ||
| 53 | # ALIGN-NEXT: Flags [ | ||
| 54 | # ALIGN-NEXT: SHF_ALLOC | ||
| 55 | # ALIGN-NEXT: ] | ||
| 56 | # ALIGN-NEXT: Address: | ||
| 57 | # ALIGN-NEXT: Offset: [[_:0x[0-9A-Z]*(0|4|8|C)$]] | ||
| 58 | # ALIGN-NEXT: Size: | ||
| 59 | # ALIGN-NEXT: Link: | ||
| 60 | # ALIGN-NEXT: Info: | ||
| 61 | # ALIGN-NEXT: AddressAlignment: 4 | ||
| 62 | |||
| 48 | # DEFAULT: Contents of section .note.test: | 63 | # DEFAULT: Contents of section .note.test: |
| 49 | # DEFAULT: Contents of section .note.gnu.build-id: | 64 | # DEFAULT: Contents of section .note.gnu.build-id: |
| 50 | # DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU. | 65 | # DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU. |
| 51 | # DEFAULT-NEXT: fd36edb1 f6ff02af | 66 | # DEFAULT-NEXT: 894c04e8 fbf5556b |
| 52 | 67 | ||
| 53 | # MD5: Contents of section .note.gnu.build-id: | 68 | # MD5: Contents of section .note.gnu.build-id: |
| 54 | # MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. | 69 | # MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. |
| 55 | # MD5-NEXT: fc | 70 | # MD5-NEXT: 6a51bbd7 9e8ee3f9 2e02d213 711cfec9 |
| 56 | 71 | ||
| 57 | # SHA1: Contents of section .note.gnu.build-id: | 72 | # SHA1: Contents of section .note.gnu.build-id: |
| 58 | # SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU. | 73 | # SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU. |
| 59 | # SHA1-NEXT: 55b1eedb 03b588e1 09987d1d e9a79be7 | 74 | # SHA1-NEXT: 9a8618b1 d6fd0e5c eda73dd8 76de5596 |
| 60 | 75 | ||
| 61 | # UUID: Contents of section .note.gnu.build-id: | 76 | # UUID: Contents of section .note.gnu.build-id: |
| 62 | # UUID-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. | 77 | # UUID-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. |
deps/lld/test/ELF/chroot.s created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: rm -rf %t.dir | ||
| 3 | # RUN: mkdir %t.dir | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/chroot.o | ||
| 5 | # RUN: ld.lld --chroot %t.dir -o %t.exe /chroot.o | ||
| 6 | |||
| 7 | # RUN: echo 'INPUT(/chroot.o)' > %t.dir/scr | ||
| 8 | # RUN: ld.lld --chroot %t.dir -o %t.exe /scr | ||
| 9 | |||
| 10 | .globl _start | ||
| 11 | _start: | ||
| 12 | ret | ||
deps/lld/test/ELF/comment-gc.s+1-2| ... | @@ -5,8 +5,7 @@ | ... | @@ -5,8 +5,7 @@ |
| 5 | # RUN: llvm-objdump -s %t1 | FileCheck %s | 5 | # RUN: llvm-objdump -s %t1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK: Contents of section .comment: | 7 | # CHECK: Contents of section .comment: |
| 8 | # CHECK-NEXT: 0000 00666f6f 00626172 004c4c44 20312e30 .foo.bar.LLD 1.0 | 8 | # CHECK-NEXT: foo..LLD 1.0.bar |
| 9 | # CHECK-NEXT: 0010 00 . | ||
| 10 | 9 | ||
| 11 | .ident "foo" | 10 | .ident "foo" |
| 12 | 11 |
deps/lld/test/ELF/common-gc.s created+41| ... | @@ -0,0 +1,41 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | ||
| 3 | |||
| 4 | # RUN: ld.lld %t -o %t2 | ||
| 5 | # RUN: llvm-readobj -sections -symbols %t2 | FileCheck %s --check-prefix=NOGC | ||
| 6 | |||
| 7 | # NOGC: Name: .bss | ||
| 8 | # NOGC-NEXT: Type: | ||
| 9 | # NOGC-NEXT: Flags [ | ||
| 10 | # NOGC-NEXT: SHF_ALLOC | ||
| 11 | # NOGC-NEXT: SHF_WRITE | ||
| 12 | # NOGC-NEXT: ] | ||
| 13 | # NOGC-NEXT: Address: | ||
| 14 | # NOGC-NEXT: Offset: | ||
| 15 | # NOGC-NEXT: Size: 8 | ||
| 16 | |||
| 17 | # NOGC: Name: bar | ||
| 18 | # NOGC: Name: foo | ||
| 19 | |||
| 20 | # RUN: ld.lld -gc-sections %t -o %t1 | ||
| 21 | # RUN: llvm-readobj -sections -symbols %t1 | FileCheck %s --check-prefix=GC | ||
| 22 | |||
| 23 | # GC: Name: .bss | ||
| 24 | # GC-NEXT: Type: | ||
| 25 | # GC-NEXT: Flags [ | ||
| 26 | # GC-NEXT: SHF_ALLOC | ||
| 27 | # GC-NEXT: SHF_WRITE | ||
| 28 | # GC-NEXT: ] | ||
| 29 | # GC-NEXT: Address: | ||
| 30 | # GC-NEXT: Offset: | ||
| 31 | # GC-NEXT: Size: 4 | ||
| 32 | |||
| 33 | # GC-NOT: Name: bar | ||
| 34 | |||
| 35 | .comm foo,4,4 | ||
| 36 | .comm bar,4,4 | ||
| 37 | |||
| 38 | .text | ||
| 39 | .globl _start | ||
| 40 | _start: | ||
| 41 | .quad foo | ||
deps/lld/test/ELF/common-gc2.s created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | ||
| 3 | # RUN: ld.lld -gc-sections -export-dynamic %t -o %t1 | ||
| 4 | # RUN: llvm-readobj --dyn-symbols %t1 | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: Name: bar@ | ||
| 7 | # CHECK: Name: foo@ | ||
| 8 | |||
| 9 | .comm foo,4,4 | ||
| 10 | .comm bar,4,4 | ||
| 11 | |||
| 12 | .text | ||
| 13 | .globl _start | ||
| 14 | _start: | ||
| 15 | .quad foo | ||
deps/lld/test/ELF/common-gc3.s created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld %t.o -o %t1 --gc-sections | ||
| 4 | # RUN: llvm-objdump -s %t1 | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: Contents of section .noalloc: | ||
| 7 | # 0000 00000000 00000000 ........ | ||
| 8 | |||
| 9 | 	.section	.text._start,"ax",@progbits | ||
| 10 | 	.globl	_start | ||
| 11 | _start: | ||
| 12 | 	retq | ||
| 13 | |||
| 14 | 	.type	unused,@object | ||
| 15 | 	.comm	unused,4,4 | ||
| 16 | |||
| 17 | 	.section	.noalloc,"",@progbits | ||
| 18 | 	.quad	unused | ||
deps/lld/test/ELF/common.s+5-5| ... | @@ -12,13 +12,13 @@ | ... | @@ -12,13 +12,13 @@ |
| 12 | // CHECK-NEXT: ] | 12 | // CHECK-NEXT: ] |
| 13 | // CHECK-NEXT: Address: 0x201000 | 13 | // CHECK-NEXT: Address: 0x201000 |
| 14 | // CHECK-NEXT: Offset: | 14 | // CHECK-NEXT: Offset: |
| 15 | // CHECK-NEXT: Size: 22 | 15 | // CHECK-NEXT: Size: 36 |
| 16 | // CHECK-NEXT: Link: 0 | 16 | // CHECK-NEXT: Link: 0 |
| 17 | // CHECK-NEXT: Info: 0 | 17 | // CHECK-NEXT: Info: 0 |
| 18 | // CHECK-NEXT: AddressAlignment: 16 | 18 | // CHECK-NEXT: AddressAlignment: 16 |
| 19 | 19 | ||
| 20 | // CHECK: Name: sym1 | 20 | // CHECK: Name: sym1 |
| 21 | // CHECK-NEXT: Value: 0x201004 | 21 | // CHECK-NEXT: Value: 0x201000 |
| 22 | // CHECK-NEXT: Size: 8 | 22 | // CHECK-NEXT: Size: 8 |
| 23 | // CHECK-NEXT: Binding: Global | 23 | // CHECK-NEXT: Binding: Global |
| 24 | // CHECK-NEXT: Type: Object | 24 | // CHECK-NEXT: Type: Object |
| ... | @@ -26,7 +26,7 @@ | ... | @@ -26,7 +26,7 @@ |
| 26 | // CHECK-NEXT: Section: .bss | 26 | // CHECK-NEXT: Section: .bss |
| 27 | 27 | ||
| 28 | // CHECK: Name: sym2 | 28 | // CHECK: Name: sym2 |
| 29 | // CHECK-NEXT: Value: 0x20100C | 29 | // CHECK-NEXT: Value: 0x201008 |
| 30 | // CHECK-NEXT: Size: 8 | 30 | // CHECK-NEXT: Size: 8 |
| 31 | // CHECK-NEXT: Binding: Global | 31 | // CHECK-NEXT: Binding: Global |
| 32 | // CHECK-NEXT: Type: Object | 32 | // CHECK-NEXT: Type: Object |
| ... | @@ -34,7 +34,7 @@ | ... | @@ -34,7 +34,7 @@ |
| 34 | // CHECK-NEXT: Section: .bss | 34 | // CHECK-NEXT: Section: .bss |
| 35 | 35 | ||
| 36 | // CHECK: Name: sym3 | 36 | // CHECK: Name: sym3 |
| 37 | // CHECK-NEXT: Value: 0x201014 | 37 | // CHECK-NEXT: Value: 0x201010 |
| 38 | // CHECK-NEXT: Size: 2 | 38 | // CHECK-NEXT: Size: 2 |
| 39 | // CHECK-NEXT: Binding: Global | 39 | // CHECK-NEXT: Binding: Global |
| 40 | // CHECK-NEXT: Type: Object | 40 | // CHECK-NEXT: Type: Object |
| ... | @@ -42,7 +42,7 @@ | ... | @@ -42,7 +42,7 @@ |
| 42 | // CHECK-NEXT: Section: .bss | 42 | // CHECK-NEXT: Section: .bss |
| 43 | 43 | ||
| 44 | // CHECK: Name: sym4 | 44 | // CHECK: Name: sym4 |
| 45 | // CHECK-NEXT: Value: 0x201000 | 45 | // CHECK-NEXT: Value: 0x201020 |
| 46 | // CHECK-NEXT: Size: 4 | 46 | // CHECK-NEXT: Size: 4 |
| 47 | // CHECK-NEXT: Binding: Global | 47 | // CHECK-NEXT: Binding: Global |
| 48 | // CHECK-NEXT: Type: Object | 48 | // CHECK-NEXT: Type: Object |
deps/lld/test/ELF/compress-debug-sections-reloc.s created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | # REQUIRES: x86, zlib | ||
| 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 %S/Inputs/compress-debug.s -o %t2.o | ||
| 5 | # RUN: ld.lld %t2.o %t.o -o %t1 --compress-debug-sections=zlib -Ttext=0 | ||
| 6 | # RUN: llvm-dwarfdump %t1 -debug-str | FileCheck %s | ||
| 7 | # These two checks correspond to the patched values of a_sym and a_debug_sym. | ||
| 8 | # D = 0x44 - address of .text input section for this file (the start address of | ||
| 9 | # .text is 0 as requested on the command line, and the size of the | ||
| 10 | #	 preceding .text in the other input file is 0x44). | ||
| 11 | # C = 0x43 - offset of .debug_info section for this file (the size of | ||
| 12 | # the preceding .debug_info from the other input file is 0x43). | ||
| 13 | # CHECK: 0x00000000: "D" | ||
| 14 | # CHECK: 0x00000004: "C" | ||
| 15 | |||
| 16 | .text | ||
| 17 | a_sym: | ||
| 18 | nop | ||
| 19 | |||
| 20 | .section .debug_str,"",@progbits | ||
| 21 | .long a_sym | ||
| 22 | .long a_debug_sym | ||
| 23 | |||
| 24 | .section .debug_info,"",@progbits | ||
| 25 | a_debug_sym: | ||
| 26 | .long 0x88776655 | ||
deps/lld/test/ELF/compress-debug-sections.s+6-1| ... | @@ -15,12 +15,17 @@ | ... | @@ -15,12 +15,17 @@ |
| 15 | # ZLIBFLAGS-NEXT: Flags [ | 15 | # ZLIBFLAGS-NEXT: Flags [ |
| 16 | # ZLIBFLAGS-NEXT: SHF_COMPRESSED | 16 | # ZLIBFLAGS-NEXT: SHF_COMPRESSED |
| 17 | 17 | ||
| 18 | # RUN: llvm-dwarfdump %t1 -debug-dump=str | \ | 18 | # RUN: llvm-dwarfdump %t1 -debug-str | \ |
| 19 | # RUN: FileCheck %s --check-prefix=DEBUGSTR | 19 | # RUN: FileCheck %s --check-prefix=DEBUGSTR |
| 20 | # DEBUGSTR: .debug_str contents: | 20 | # DEBUGSTR: .debug_str contents: |
| 21 | # DEBUGSTR-NEXT: AAAAAAAAAAAAAAAAAAAAAAAAAAA | 21 | # DEBUGSTR-NEXT: AAAAAAAAAAAAAAAAAAAAAAAAAAA |
| 22 | # DEBUGSTR-NEXT: BBBBBBBBBBBBBBBBBBBBBBBBBBB | 22 | # DEBUGSTR-NEXT: BBBBBBBBBBBBBBBBBBBBBBBBBBB |
| 23 | 23 | ||
| 24 | ## Test alias. | ||
| 25 | # RUN: ld.lld %t.o -o %t2 --compress-debug-sections zlib | ||
| 26 | # RUN: llvm-objdump -s %t2 | FileCheck %s --check-prefix=ZLIBCONTENT | ||
| 27 | # RUN: llvm-readobj -s %t2 | FileCheck %s --check-prefix=ZLIBFLAGS | ||
| 28 | |||
| 24 | # 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 | \ |
| 25 | # RUN: FileCheck -check-prefix=ERR %s | 30 | # RUN: FileCheck -check-prefix=ERR %s |
| 26 | # ERR: unknown --compress-debug-sections value: zlib-gabi | 31 | # ERR: unknown --compress-debug-sections value: zlib-gabi |
deps/lld/test/ELF/compressed-debug-conflict.s created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | # REQUIRES: x86, zlib | ||
| 2 | # 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 %s | ||
| 4 | # RUN: not ld.lld %t.o %t.o -o %tout 2>&1 | FileCheck -check-prefix=ERROR %s | ||
| 5 | |||
| 6 | # OBJ: Sections [ | ||
| 7 | # OBJ: Section { | ||
| 8 | # OBJ: Index: 3 | ||
| 9 | # OBJ-NEXT: Name: .debug_line (16) | ||
| 10 | # OBJ-NEXT: Type: SHT_PROGBITS (0x1) | ||
| 11 | # OBJ-NEXT: Flags [ (0x800) | ||
| 12 | # OBJ-NEXT: SHF_COMPRESSED (0x800) | ||
| 13 | # OBJ-NEXT: ] | ||
| 14 | |||
| 15 | # ERROR: error: duplicate symbol: main | ||
| 16 | # ERROR-NEXT: >>> defined at reduced.c:2 (/tmp/reduced.c:2) | ||
| 17 | # ERROR-NEXT: >>> | ||
| 18 | # ERROR-NEXT: >>> defined at reduced.c:2 (/tmp/reduced.c:2) | ||
| 19 | # ERROR-NEXT: >>> | ||
| 20 | |||
| 21 | 	.text | ||
| 22 | 	.file	"reduced.c" | ||
| 23 | 	.globl	main | ||
| 24 | main: | ||
| 25 | 	.file	1 "/tmp" "reduced.c" | ||
| 26 | 	.loc	1 2 0 | ||
| 27 | 	xorl	%eax, %eax | ||
| 28 | 	retl | ||
| 29 | 	.file	2 "/tmp/repeat/repeat/repeat/repeat" "repeat.h" | ||
deps/lld/test/ELF/compressed-debug-input.s+8-8| ... | @@ -39,10 +39,10 @@ | ... | @@ -39,10 +39,10 @@ |
| 39 | # GNU-NEXT: EntrySize: 1 | 39 | # GNU-NEXT: EntrySize: 1 |
| 40 | # GNU-NEXT: } | 40 | # GNU-NEXT: } |
| 41 | 41 | ||
| 42 | # RUN: ld.lld %t -o %t.so -shared | 42 | # RUN: ld.lld --hash-style=sysv %t -o %t.so -shared |
| 43 | # RUN: llvm-readobj -sections -section-data %t.so | FileCheck -check-prefix=DATA %s | 43 | # RUN: llvm-readobj -sections -section-data %t.so | FileCheck -check-prefix=DATA %s |
| 44 | 44 | ||
| 45 | # RUN: ld.lld %t2 -o %t2.so -shared | 45 | # RUN: ld.lld --hash-style=sysv %t2 -o %t2.so -shared |
| 46 | # RUN: llvm-readobj -sections -section-data %t2.so | FileCheck -check-prefix=DATA %s | 46 | # RUN: llvm-readobj -sections -section-data %t2.so | FileCheck -check-prefix=DATA %s |
| 47 | 47 | ||
| 48 | # DATA: Section { | 48 | # DATA: Section { |
| ... | @@ -59,13 +59,13 @@ | ... | @@ -59,13 +59,13 @@ |
| 59 | # DATA-NEXT: Link: 0 | 59 | # DATA-NEXT: Link: 0 |
| 60 | # DATA-NEXT: Info: 0 | 60 | # DATA-NEXT: Info: 0 |
| 61 | # DATA-NEXT: AddressAlignment: 1 | 61 | # DATA-NEXT: AddressAlignment: 1 |
| 62 | # DATA-NEXT: EntrySize: 0 | 62 | # DATA-NEXT: EntrySize: 1 |
| 63 | # DATA-NEXT: SectionData ( | 63 | # DATA-NEXT: SectionData ( |
| 64 | # DATA-NEXT: 0000: 73686F72 7420756E 7369676E 65642069 |short unsigned i| | 64 | # DATA-NEXT: 0000: 6C6F6E67 20756E73 69676E65 6420696E |long unsigned in| |
| 65 | # DATA-NEXT: 0010: 6E740075 6E736967 6E656420 696E7400 |nt.unsigned int.| | 65 | # DATA-NEXT: 0010: 7400756E 7369676E 65642063 68617200 |t.unsigned char.| |
| 66 | # DATA-NEXT: 0020: 6C6F6E67 20756E73 69676E65 6420696E |long unsigned in| | 66 | # DATA-NEXT: 0020: 756E7369 676E6564 20696E74 00636861 |unsigned int.cha| |
| 67 | # DATA-NEXT: 0030: 74006368 61720075 6E736967 6E656420 |t.char.unsigned | | 67 | # DATA-NEXT: 0030: 72007368 6F727420 756E7369 676E6564 |r.short unsigned| |
| 68 | # DATA-NEXT: 0040: 63686172 00 |char.| | 68 | # DATA-NEXT: 0040: 20696E74 00 | int.| |
| 69 | # DATA-NEXT: ) | 69 | # DATA-NEXT: ) |
| 70 | # DATA-NEXT: } | 70 | # DATA-NEXT: } |
| 71 | 71 |
deps/lld/test/ELF/conflict-debug-variable.s created+144| ... | @@ -0,0 +1,144 @@ | ||
| 1 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 2 | # RUN: llvm-dwarfdump %t.o | FileCheck -check-prefix=INPUT %s | ||
| 3 | # RUN: not ld.lld %t.o %t.o -o %t 2>&1 | FileCheck %s | ||
| 4 | |||
| 5 | # INPUT: .debug_info contents: | ||
| 6 | # INPUT: DW_TAG_variable | ||
| 7 | # INPUT-NEXT: DW_AT_name ("foo") | ||
| 8 | # INPUT-NEXT: DW_AT_decl_file ("1.c") | ||
| 9 | # INPUT-NEXT: DW_AT_decl_line (1) | ||
| 10 | # INPUT-NEXT: DW_AT_type (cu + 0x0032 "int") | ||
| 11 | # INPUT-NEXT: DW_AT_external (true) | ||
| 12 | # INPUT-NEXT: DW_AT_location (DW_OP_addr 0x0) | ||
| 13 | # INPUT: DW_TAG_variable | ||
| 14 | # INPUT-NEXT: DW_AT_name ("bar") | ||
| 15 | # INPUT-NEXT: DW_AT_decl_file ("1.c") | ||
| 16 | # INPUT-NEXT: DW_AT_decl_line (2) | ||
| 17 | # INPUT-NEXT: DW_AT_type (cu + 0x0032 "int") | ||
| 18 | # INPUT-NEXT: DW_AT_external (true) | ||
| 19 | # INPUT-NEXT: DW_AT_location (DW_OP_addr 0x0) | ||
| 20 | |||
| 21 | ## Check we use information from .debug_info in messages. | ||
| 22 | # CHECK: duplicate symbol: bar | ||
| 23 | # CHECK-NEXT: >>> defined at 1.c:2 | ||
| 24 | # CHECK-NEXT: >>> {{.*}}:(bar) | ||
| 25 | # CHECK-NEXT: >>> defined at 1.c:2 | ||
| 26 | # CHECK-NEXT: >>> {{.*}}:(.data+0x0) | ||
| 27 | # CHECK: duplicate symbol: foo | ||
| 28 | # CHECK-NEXT: >>> defined at 1.c:1 | ||
| 29 | # CHECK-NEXT: >>> {{.*}}:(foo) | ||
| 30 | # CHECK-NEXT: >>> defined at 1.c:1 | ||
| 31 | # CHECK-NEXT: >>> {{.*}}:(.bss+0x0) | ||
| 32 | |||
| 33 | ## Check that stripping debug sections does not break error reporting. | ||
| 34 | # RUN: not ld.lld --strip-debug %t.o %t.o -o %t 2>&1 | FileCheck %s | ||
| 35 | |||
| 36 | # Used reduced output from following code and gcc 7.1.0 | ||
| 37 | # to produce this input file: | ||
| 38 | # Source (1.c): | ||
| 39 | # int foo = 0; | ||
| 40 | # int bar = 1; | ||
| 41 | # Invocation: g++ -g -S 1.c | ||
| 42 | |||
| 43 | .bss | ||
| 44 | .globl foo | ||
| 45 | .type foo, @object | ||
| 46 | .size foo, 4 | ||
| 47 | foo: | ||
| 48 | |||
| 49 | .data | ||
| 50 | .globl bar | ||
| 51 | .type bar, @object | ||
| 52 | .size bar, 4 | ||
| 53 | bar: | ||
| 54 | |||
| 55 | .text | ||
| 56 | .file 1 "1.c" | ||
| 57 | |||
| 58 | .section .debug_info,"",@progbits | ||
| 59 | .long 0x4b # Compile Unit: length = 0x0000004b) | ||
| 60 | .value 0x4 # version = 0x0004 | ||
| 61 | .long 0 # abbr_offset = 0x0 | ||
| 62 | .byte 0x8 # addr_size = 0x08 | ||
| 63 | |||
| 64 | .uleb128 0x1 # DW_TAG_compile_unit [1] * | ||
| 65 | .long 0 # DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000000] = ) | ||
| 66 | .byte 0x4 # DW_AT_language [DW_FORM_data1] (DW_LANG_C_plus_plus) | ||
| 67 | .string "1.c" # DW_AT_name [DW_FORM_string] ("1.c") | ||
| 68 | .long 0 # DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000000] = ) | ||
| 69 | .long 0 # DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000) | ||
| 70 | |||
| 71 | .uleb128 0x2 # DW_TAG_variable [2] | ||
| 72 | .string "foo" # DW_AT_name [DW_FORM_string] ("foo") | ||
| 73 | .byte 0x1 # DW_AT_decl_file [DW_FORM_data1] ("1.c") | ||
| 74 | .byte 0x1 # DW_AT_decl_line [DW_FORM_data1] (1) | ||
| 75 | .long 0x32 # DW_AT_type [DW_FORM_ref4] (cu + 0x0032 => {0x00000032}) | ||
| 76 | .uleb128 0x9 # DW_AT_external [DW_FORM_flag_present] (true) | ||
| 77 | .byte 0x3 | ||
| 78 | .quad foo # DW_AT_location [DW_FORM_exprloc] (DW_OP_addr 0x0) | ||
| 79 | |||
| 80 | .uleb128 0x3 # DW_TAG_base_type [3] | ||
| 81 | .byte 0x4 # DW_AT_byte_size [DW_FORM_data1] (0x04) | ||
| 82 | .byte 0x5 # DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed) | ||
| 83 | .string "int" # DW_AT_name [DW_FORM_string] ("int") | ||
| 84 | |||
| 85 | .uleb128 0x2 # DW_TAG_variable [2] | ||
| 86 | .string "bar" # DW_AT_name [DW_FORM_string] ("bar") | ||
| 87 | .byte 0x1 # DW_AT_decl_file [DW_FORM_data1] ("1.c") | ||
| 88 | .byte 0x2 # DW_AT_decl_line [DW_FORM_data1] (2) | ||
| 89 | .long 0x32 # DW_AT_type [DW_FORM_ref4] (cu + 0x0032 => {0x00000032}) | ||
| 90 | .uleb128 0x9 # DW_AT_external [DW_FORM_flag_present] (true) | ||
| 91 | .byte 0x3 | ||
| 92 | .quad bar # DW_AT_location [DW_FORM_exprloc] (DW_OP_addr 0x0) | ||
| 93 | .byte 0 # END | ||
| 94 | |||
| 95 | |||
| 96 | .section .debug_abbrev,"",@progbits | ||
| 97 | .uleb128 0x1 # Abbreviation code. | ||
| 98 | .uleb128 0x11 # DW_TAG_compile_unit | ||
| 99 | |||
| 100 | .byte 0x1 # ID | ||
| 101 | .uleb128 0x25 # DW_AT_producer, DW_FORM_strp | ||
| 102 | .uleb128 0xe | ||
| 103 | .uleb128 0x13 # DW_AT_language, DW_FORM_data1 | ||
| 104 | .uleb128 0xb | ||
| 105 | .uleb128 0x3 # DW_AT_name, DW_FORM_string | ||
| 106 | .uleb128 0x8 | ||
| 107 | .uleb128 0x1b # DW_AT_comp_dir, DW_FORM_strp | ||
| 108 | .uleb128 0xe | ||
| 109 | .uleb128 0x10 # DW_AT_stmt_list, DW_FORM_sec_offset | ||
| 110 | .uleb128 0x17 | ||
| 111 | .byte 0 | ||
| 112 | .byte 0 | ||
| 113 | |||
| 114 | .uleb128 0x2 # ID | ||
| 115 | .uleb128 0x34 # DW_TAG_variable, DW_CHILDREN_no | ||
| 116 | .byte 0 | ||
| 117 | .uleb128 0x3 # DW_AT_name, DW_FORM_string | ||
| 118 | .uleb128 0x8 | ||
| 119 | .uleb128 0x3a # DW_AT_decl_file, DW_FORM_data1 | ||
| 120 | .uleb128 0xb | ||
| 121 | .uleb128 0x3b # DW_AT_decl_line, DW_FORM_data1 | ||
| 122 | .uleb128 0xb | ||
| 123 | .uleb128 0x49 # DW_AT_type, DW_FORM_ref4 | ||
| 124 | .uleb128 0x13 | ||
| 125 | .uleb128 0x3f # DW_AT_external, DW_FORM_flag_present | ||
| 126 | .uleb128 0x19 | ||
| 127 | .uleb128 0x2 # DW_AT_location, DW_FORM_exprloc | ||
| 128 | .uleb128 0x18 | ||
| 129 | .byte 0 | ||
| 130 | .byte 0 | ||
| 131 | |||
| 132 | .uleb128 0x3 # ID | ||
| 133 | .uleb128 0x24 # DW_TAG_base_type, DW_CHILDREN_no | ||
| 134 | .byte 0 | ||
| 135 | .uleb128 0xb # DW_AT_byte_size, DW_FORM_data1 | ||
| 136 | .uleb128 0xb | ||
| 137 | .uleb128 0x3e # DW_AT_encoding, DW_FORM_data1 | ||
| 138 | .uleb128 0xb | ||
| 139 | .uleb128 0x3 # DW_AT_name, DW_FORM_string | ||
| 140 | .uleb128 0x8 | ||
| 141 | .byte 0 | ||
| 142 | .byte 0 | ||
| 143 | .byte 0 | ||
| 144 | |||
deps/lld/test/ELF/conflict-debug-variable2.s created+160| ... | @@ -0,0 +1,160 @@ | ||
| 1 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 2 | |||
| 3 | # RUN: llvm-dwarfdump -v %t.o | FileCheck -check-prefix=INPUT %s | ||
| 4 | # INPUT: .debug_info contents: | ||
| 5 | # INPUT: DW_TAG_variable | ||
| 6 | # INPUT-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000027] = "foo") | ||
| 7 | # INPUT-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0033 => {0x00000033} "int") | ||
| 8 | # INPUT-NEXT: DW_AT_external [DW_FORM_flag_present] (true) | ||
| 9 | # INPUT-NEXT: DW_AT_decl_file [DW_FORM_data1] ("/home/path/test.c") | ||
| 10 | # INPUT-NEXT: DW_AT_decl_line [DW_FORM_data1] (1) | ||
| 11 | # INPUT-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addr 0x0) | ||
| 12 | # INPUT: DW_TAG_variable | ||
| 13 | # INPUT-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000002f] = "bar") | ||
| 14 | # INPUT-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0033 => {0x00000033} "int") | ||
| 15 | # INPUT-NEXT: DW_AT_external [DW_FORM_flag_present] (true) | ||
| 16 | # INPUT-NEXT: DW_AT_decl_file [DW_FORM_data1] ("/home/path/test.c") | ||
| 17 | # INPUT-NEXT: DW_AT_decl_line [DW_FORM_data1] (2) | ||
| 18 | # INPUT-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_addr 0x0) | ||
| 19 | |||
| 20 | ## Check we use information from .debug_info in messages. | ||
| 21 | # RUN: not ld.lld %t.o %t.o -o %t 2>&1 | FileCheck %s | ||
| 22 | # CHECK: duplicate symbol: bar | ||
| 23 | # CHECK-NEXT: >>> defined at test.c:2 | ||
| 24 | # CHECK-NEXT: >>> {{.*}}:(bar) | ||
| 25 | # CHECK-NEXT: >>> defined at test.c:2 | ||
| 26 | # CHECK-NEXT: >>> {{.*}}:(.data+0x0) | ||
| 27 | # CHECK: duplicate symbol: foo | ||
| 28 | # CHECK-NEXT: >>> defined at test.c:1 | ||
| 29 | # CHECK-NEXT: >>> {{.*}}:(foo) | ||
| 30 | # CHECK-NEXT: >>> defined at test.c:1 | ||
| 31 | # CHECK-NEXT: >>> {{.*}}:(.bss+0x0) | ||
| 32 | |||
| 33 | # Used reduced output from following code and clang | ||
| 34 | # version 6.0.0 (trunk 316661) to produce this input file: | ||
| 35 | # Source (test.c): | ||
| 36 | # int foo = 0; | ||
| 37 | # int bar = 1; | ||
| 38 | # Invocation: clang -g -S test.c | ||
| 39 | |||
| 40 | .text | ||
| 41 | .file "test.c" | ||
| 42 | .file 1 "test.c" | ||
| 43 | |||
| 44 | .type foo,@object | ||
| 45 | .bss | ||
| 46 | .globl foo | ||
| 47 | .p2align 2 | ||
| 48 | foo: | ||
| 49 | .long 0 | ||
| 50 | .size foo, 4 | ||
| 51 | |||
| 52 | .type bar,@object | ||
| 53 | .data | ||
| 54 | .globl bar | ||
| 55 | .p2align 2 | ||
| 56 | bar: | ||
| 57 | .long 1 | ||
| 58 | .size bar, 4 | ||
| 59 | |||
| 60 | .section .debug_str,"MS",@progbits,1 | ||
| 61 | .Linfo_string0: | ||
| 62 | .asciz "clang version 6.0.0" | ||
| 63 | .Linfo_string1: | ||
| 64 | .asciz "test.c" | ||
| 65 | .Linfo_string2: | ||
| 66 | .asciz "/home/path/" | ||
| 67 | .Linfo_string3: | ||
| 68 | .asciz "foo" | ||
| 69 | .Linfo_string4: | ||
| 70 | .asciz "int" | ||
| 71 | .Linfo_string5: | ||
| 72 | .asciz "bar" | ||
| 73 | |||
| 74 | .section .debug_abbrev,"",@progbits | ||
| 75 | .byte 1 # Abbreviation Code | ||
| 76 | .byte 17 # DW_TAG_compile_unit | ||
| 77 | .byte 1 # DW_CHILDREN_yes | ||
| 78 | .byte 37 # DW_AT_producer | ||
| 79 | .byte 14 # DW_FORM_strp | ||
| 80 | .byte 19 # DW_AT_language | ||
| 81 | .byte 5 # DW_FORM_data2 | ||
| 82 | .byte 3 # DW_AT_name | ||
| 83 | .byte 14 # DW_FORM_strp | ||
| 84 | .byte 16 # DW_AT_stmt_list | ||
| 85 | .byte 23 # DW_FORM_sec_offset | ||
| 86 | .byte 27 # DW_AT_comp_dir | ||
| 87 | .byte 14 # DW_FORM_strp | ||
| 88 | .ascii "\264B" # DW_AT_GNU_pubnames | ||
| 89 | .byte 25 # DW_FORM_flag_present | ||
| 90 | .byte 0 # EOM(1) | ||
| 91 | .byte 0 # EOM(2) | ||
| 92 | |||
| 93 | .byte 2 # Abbreviation Code | ||
| 94 | .byte 52 # DW_TAG_variable | ||
| 95 | .byte 0 # DW_CHILDREN_no | ||
| 96 | .byte 3 # DW_AT_name | ||
| 97 | .byte 14 # DW_FORM_strp | ||
| 98 | .byte 73 # DW_AT_type | ||
| 99 | .byte 19 # DW_FORM_ref4 | ||
| 100 | .byte 63 # DW_AT_external | ||
| 101 | .byte 25 # DW_FORM_flag_present | ||
| 102 | .byte 58 # DW_AT_decl_file | ||
| 103 | .byte 11 # DW_FORM_data1 | ||
| 104 | .byte 59 # DW_AT_decl_line | ||
| 105 | .byte 11 # DW_FORM_data1 | ||
| 106 | .byte 2 # DW_AT_location | ||
| 107 | .byte 24 # DW_FORM_exprloc | ||
| 108 | .byte 0 # EOM(1) | ||
| 109 | .byte 0 # EOM(2) | ||
| 110 | |||
| 111 | .byte 3 # Abbreviation Code | ||
| 112 | .byte 36 # DW_TAG_base_type | ||
| 113 | .byte 0 # DW_CHILDREN_no | ||
| 114 | .byte 3 # DW_AT_name | ||
| 115 | .byte 14 # DW_FORM_strp | ||
| 116 | .byte 62 # DW_AT_encoding | ||
| 117 | .byte 11 # DW_FORM_data1 | ||
| 118 | .byte 11 # DW_AT_byte_size | ||
| 119 | .byte 11 # DW_FORM_data1 | ||
| 120 | .byte 0 # EOM(1) | ||
| 121 | .byte 0 # EOM(2) | ||
| 122 | .byte 0 # EOM(3) | ||
| 123 | |||
| 124 | .section .debug_info,"",@progbits | ||
| 125 | .Lcu_begin0: | ||
| 126 | .long 76 # Length of Unit | ||
| 127 | .short 4 # DWARF version number | ||
| 128 | .long .debug_abbrev # Offset Into Abbrev. Section | ||
| 129 | .byte 8 # Address Size (in bytes) | ||
| 130 | |||
| 131 | .byte 1 # Abbrev [1] 0xb:0x45 DW_TAG_compile_unit | ||
| 132 | .long .Linfo_string0 # DW_AT_producer | ||
| 133 | .short 12 # DW_AT_language | ||
| 134 | .long .Linfo_string1 # DW_AT_name | ||
| 135 | .long 0 # DW_AT_stmt_list | ||
| 136 | .long .Linfo_string2 # DW_AT_comp_dir | ||
| 137 | |||
| 138 | .byte 2 # Abbrev [2] 0x1e:0x15 DW_TAG_variable | ||
| 139 | .long .Linfo_string3 # DW_AT_name | ||
| 140 | .long 51 # DW_AT_type | ||
| 141 | .byte 1 # DW_AT_decl_file | ||
| 142 | .byte 1 # DW_AT_decl_line | ||
| 143 | .byte 9 # DW_AT_location | ||
| 144 | .byte 3 | ||
| 145 | .quad foo | ||
| 146 | |||
| 147 | .byte 3 # Abbrev [3] 0x33:0x7 DW_TAG_base_type | ||
| 148 | .long .Linfo_string4 # DW_AT_name | ||
| 149 | .byte 5 # DW_AT_encoding | ||
| 150 | .byte 4 # DW_AT_byte_size | ||
| 151 | |||
| 152 | .byte 2 # Abbrev [2] 0x3a:0x15 DW_TAG_variable | ||
| 153 | .long .Linfo_string5 # DW_AT_name | ||
| 154 | .long 51 # DW_AT_type | ||
| 155 | .byte 1 # DW_AT_decl_file | ||
| 156 | .byte 2 # DW_AT_decl_line | ||
| 157 | .byte 9 # DW_AT_location | ||
| 158 | .byte 3 | ||
| 159 | .quad bar | ||
| 160 | .byte 0 # End Of Children Mark | ||
deps/lld/test/ELF/copy-errors.s+3| ... | @@ -9,6 +9,9 @@ | ... | @@ -9,6 +9,9 @@ |
| 9 | // CHECK: >>> referenced by {{.*}}.o:(.text+0x1) | 9 | // CHECK: >>> referenced by {{.*}}.o:(.text+0x1) |
| 10 | // CHECK: symbol 'zed' defined in {{.*}}.so has no type | 10 | // CHECK: symbol 'zed' defined in {{.*}}.so has no type |
| 11 | 11 | ||
| 12 | // RUN: not ld.lld --noinhibit-exec %t.o %t2.so -o %t 2>&1 | FileCheck %s --check-prefix=NOINHIBIT | ||
| 13 | // NOINHIBIT: warning: symbol 'zed' defined in {{.*}}.so has no type | ||
| 14 | |||
| 12 | .global _start | 15 | .global _start |
| 13 | _start: | 16 | _start: |
| 14 | call bar | 17 | call bar |
deps/lld/test/ELF/copy-rel-abs.s created+47| ... | @@ -0,0 +1,47 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/copy-rel-abs.s -o %t1.o | ||
| 3 | // RUN: ld.lld --hash-style=gnu -shared %t1.o -o %t1.so | ||
| 4 | // RUN: llvm-readelf --dyn-symbols %t1.so | FileCheck --check-prefix=SYMS %s | ||
| 5 | |||
| 6 | // The symbols have the same st_value, but one is ABS. | ||
| 7 | // SYMS: 0000000000001000 {{.*}} 4 bar | ||
| 8 | // SYMS: 0000000000001000 {{.*}} 4 foo | ||
| 9 | // SYMS: 0000000000001000 {{.*}} ABS zed | ||
| 10 | |||
| 11 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o | ||
| 12 | // RUN: ld.lld %t2.o %t1.so -o %t2 | ||
| 13 | // RUN: llvm-readobj --dyn-symbols %t2 | FileCheck %s | ||
| 14 | |||
| 15 | // CHECK: DynamicSymbols [ | ||
| 16 | // CHECK-NEXT: Symbol { | ||
| 17 | // CHECK-NEXT: Name: | ||
| 18 | // CHECK-NEXT: Value: | ||
| 19 | // CHECK-NEXT: Size: | ||
| 20 | // CHECK-NEXT: Binding: | ||
| 21 | // CHECK-NEXT: Type: | ||
| 22 | // CHECK-NEXT: Other: | ||
| 23 | // CHECK-NEXT: Section: | ||
| 24 | // CHECK-NEXT: } | ||
| 25 | // CHECK-NEXT: Symbol { | ||
| 26 | // CHECK-NEXT: Name: foo | ||
| 27 | // CHECK-NEXT: Value: | ||
| 28 | // CHECK-NEXT: Size: | ||
| 29 | // CHECK-NEXT: Binding: | ||
| 30 | // CHECK-NEXT: Type: | ||
| 31 | // CHECK-NEXT: Other: | ||
| 32 | // CHECK-NEXT: Section: .bss.rel.ro | ||
| 33 | // CHECK-NEXT: } | ||
| 34 | // CHECK-NEXT: Symbol { | ||
| 35 | // CHECK-NEXT: Name: bar | ||
| 36 | // CHECK-NEXT: Value: | ||
| 37 | // CHECK-NEXT: Size: | ||
| 38 | // CHECK-NEXT: Binding: | ||
| 39 | // CHECK-NEXT: Type: | ||
| 40 | // CHECK-NEXT: Other: | ||
| 41 | // CHECK-NEXT: Section: .bss.rel.ro | ||
| 42 | // CHECK-NEXT: } | ||
| 43 | // CHECK-NEXT: ] | ||
| 44 | |||
| 45 | .global _start | ||
| 46 | _start: | ||
| 47 | .quad foo | ||
deps/lld/test/ELF/copy-rel-large.s created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/copy-rel-large.s -o %t1.o | ||
| 3 | // RUN: ld.lld -shared %t1.o -o %t1.so | ||
| 4 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o | ||
| 5 | // RUN: ld.lld %t2.o %t1.so -o %t2 | ||
| 6 | // RUN: llvm-readobj --dyn-symbols %t2 | FileCheck %s | ||
| 7 | |||
| 8 | .global _start | ||
| 9 | _start: | ||
| 10 | .quad foo | ||
| 11 | |||
| 12 | // CHECK: Symbol { | ||
| 13 | // CHECK: Name: foo | ||
| 14 | // CHECK-NEXT: Value: | ||
| 15 | // CHECK-NEXT: Size: 4294967297 | ||
| 16 | // CHECK-NEXT: Binding: | ||
| 17 | // CHECK-NEXT: Type: | ||
| 18 | // CHECK-NEXT: Other: | ||
| 19 | // CHECK-NEXT: Section: .bss.rel.ro | ||
| 20 | // CHECK-NEXT: } | ||
deps/lld/test/ELF/copy-rel-pie.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux | 1 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux |
| 2 | // RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux | 2 | // RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux |
| 3 | // RUN: ld.lld %t2.o -o %t2.so -shared | 3 | // RUN: ld.lld %t2.o -o %t2.so -shared |
| 4 | // RUN: ld.lld %t.o %t2.so -o %t.exe -pie | 4 | // RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t.exe -pie |
| 5 | // RUN: llvm-readobj -s -r %t.exe | FileCheck %s | 5 | // RUN: llvm-readobj -s -r %t.exe | FileCheck %s |
| 6 | // RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s | 6 | // RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s |
| 7 | 7 |
deps/lld/test/ELF/corrupted-version-reference.s created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | # RUN: llvm-mc -triple=mips64-unknown-freebsd %s -filetype=obj -o %t.o | ||
| 2 | # RUN: not ld.lld %t.o %S/Inputs/corrupt-version-reference.so -o %t.exe 2>&1 | FileCheck %s | ||
| 3 | # REQUIRES: mips | ||
| 4 | |||
| 5 | # CHECK: error: corrupt input file: version definition index 9 for symbol __cxa_finalize is out of bounds | ||
| 6 | # CHECK: >>> defined in {{.+}}/corrupt-version-reference.so | ||
| 7 | |||
| 8 | # CHECK: error: corrupt input file: version definition index 0 for symbol _Jv_RegisterClasses is out of bounds | ||
| 9 | # CHECK-NEXT: >>> defined in {{.*}}/corrupt-version-reference.so | ||
| 10 | |||
| 11 | .globl __start | ||
| 12 | __start: | ||
| 13 | dla $a0, __cxa_finalize | ||
| 14 | nop | ||
deps/lld/test/ELF/debug-gc.s+2-2| ... | @@ -4,11 +4,11 @@ | ... | @@ -4,11 +4,11 @@ |
| 4 | # RUN: llvm-objdump -s %t1 | FileCheck %s | 4 | # RUN: llvm-objdump -s %t1 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: Contents of section .debug_str: | 6 | # CHECK: Contents of section .debug_str: |
| 7 | # CHECK-NEXT: 0000 41414100 42424200 43434300 AAA.BBB.CCC. | 7 | # CHECK-NEXT: 0000 41414100 43434300 42424200 AAA.CCC.BBB. |
| 8 | # CHECK: Contents of section .foo: | 8 | # CHECK: Contents of section .foo: |
| 9 | # CHECK-NEXT: 0000 2a000000 | 9 | # CHECK-NEXT: 0000 2a000000 |
| 10 | # CHECK: Contents of section .debug_info: | 10 | # CHECK: Contents of section .debug_info: |
| 11 | # CHECK-NEXT: 0000 00000000 04000000 | 11 | # CHECK-NEXT: 0000 00000000 08000000 |
| 12 | 12 | ||
| 13 | .globl _start | 13 | .globl _start |
| 14 | _start: | 14 | _start: |
deps/lld/test/ELF/defsym-dynamic.s created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld -o %t.so -shared %t.o --defsym=foo2=foo1 | ||
| 4 | # RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: Name: foo1 | ||
| 7 | # CHECK: Name: foo2 | ||
| 8 | |||
| 9 | .globl foo1 | ||
| 10 | foo1 = 0x123 | ||
deps/lld/test/ELF/defsym.s+37-5| ... | @@ -19,7 +19,7 @@ | ... | @@ -19,7 +19,7 @@ |
| 19 | # CHECK-NEXT: Section: Absolute | 19 | # CHECK-NEXT: Section: Absolute |
| 20 | # CHECK-NEXT: } | 20 | # CHECK-NEXT: } |
| 21 | # CHECK-NEXT: Symbol { | 21 | # CHECK-NEXT: Symbol { |
| 22 | # CHECK-NEXT: Name: foo1 | 22 | # CHECK-NEXT: Name: foo2 |
| 23 | # CHECK-NEXT: Value: 0x123 | 23 | # CHECK-NEXT: Value: 0x123 |
| 24 | # CHECK-NEXT: Size: | 24 | # CHECK-NEXT: Size: |
| 25 | # CHECK-NEXT: Binding: Global | 25 | # CHECK-NEXT: Binding: Global |
| ... | @@ -33,11 +33,43 @@ | ... | @@ -33,11 +33,43 @@ |
| 33 | # USE-NEXT: _start: | 33 | # USE-NEXT: _start: |
| 34 | # USE-NEXT: movl $0x123, %edx | 34 | # USE-NEXT: movl $0x123, %edx |
| 35 | 35 | ||
| 36 | # RUN: not ld.lld -o %t %t.o --defsym=foo2=1 2>&1 | FileCheck %s -check-prefix=ERR1 | 36 | # RUN: ld.lld -o %t %t.o --defsym=foo2=1 |
| 37 | # ERR1: error: --defsym: symbol name expected, but got 1 | 37 | # RUN: llvm-readobj -t -s %t | FileCheck %s --check-prefix=ABS |
| 38 | 38 | ||
| 39 | # RUN: not ld.lld -o %t %t.o --defsym=foo2=und 2>&1 | FileCheck %s -check-prefix=ERR2 | 39 | # ABS: Symbol { |
| 40 | # ERR2: error: -defsym: undefined symbol: und | 40 | # ABS: Name: foo2 |
| 41 | # ABS-NEXT: Value: 0x1 | ||
| 42 | # ABS-NEXT: Size: | ||
| 43 | # ABS-NEXT: Binding: Global | ||
| 44 | # ABS-NEXT: Type: | ||
| 45 | # ABS-NEXT: Other: | ||
| 46 | # ABS-NEXT: Section: Absolute | ||
| 47 | # ABS-NEXT: } | ||
| 48 | |||
| 49 | # RUN: ld.lld -o %t %t.o --defsym=foo2=foo1+5 | ||
| 50 | # RUN: llvm-readobj -t -s %t | FileCheck %s --check-prefix=EXPR | ||
| 51 | |||
| 52 | # EXPR: Symbol { | ||
| 53 | # EXPR: Name: foo1 | ||
| 54 | # EXPR-NEXT: Value: 0x123 | ||
| 55 | # EXPR-NEXT: Size: | ||
| 56 | # EXPR-NEXT: Binding: Global | ||
| 57 | # EXPR-NEXT: Type: | ||
| 58 | # EXPR-NEXT: Other: | ||
| 59 | # EXPR-NEXT: Section: Absolute | ||
| 60 | # EXPR-NEXT: } | ||
| 61 | # EXPR-NEXT: Symbol { | ||
| 62 | # EXPR-NEXT: Name: foo2 | ||
| 63 | # EXPR-NEXT: Value: 0x128 | ||
| 64 | # EXPR-NEXT: Size: | ||
| 65 | # EXPR-NEXT: Binding: Global | ||
| 66 | # EXPR-NEXT: Type: | ||
| 67 | # EXPR-NEXT: Other: | ||
| 68 | # EXPR-NEXT: Section: Absolute | ||
| 69 | # EXPR-NEXT: } | ||
| 70 | |||
| 71 | # RUN: not ld.lld -o %t %t.o --defsym=foo2=und 2>&1 | FileCheck %s -check-prefix=ERR | ||
| 72 | # ERR: error: -defsym:1: symbol not found: und | ||
| 41 | 73 | ||
| 42 | .globl foo1 | 74 | .globl foo1 |
| 43 | foo1 = 0x123 | 75 | foo1 = 0x123 |
deps/lld/test/ELF/driver-access.test+1-1| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | # RUN: mkdir -p %t.dir | 7 | # RUN: mkdir -p %t.dir |
| 8 | # RUN: chmod 100 %t.dir | 8 | # RUN: chmod 100 %t.dir |
| 9 | # RUN: cd %t.dir | 9 | # RUN: cd %t.dir |
| 10 | # RUN: ld.lld %t.o -o %t.exe | 10 | # RUN: ld.lld %t.o -o %t.exe -M |
| 11 | # RUN: chmod 755 %t.dir | 11 | # RUN: chmod 755 %t.dir |
| 12 | 12 | ||
| 13 | .globl _start | 13 | .globl _start |
deps/lld/test/ELF/driver.test+2-2| ... | @@ -18,10 +18,10 @@ | ... | @@ -18,10 +18,10 @@ |
| 18 | # HELP: : supported targets:{{.*}} elf | 18 | # HELP: : supported targets:{{.*}} elf |
| 19 | 19 | ||
| 20 | # RUN: ld.lld --version 2>&1 | FileCheck -check-prefix=VERSION %s | 20 | # RUN: ld.lld --version 2>&1 | FileCheck -check-prefix=VERSION %s |
| 21 | # RUN: ld.lld -v 2>&1 | FileCheck -check-prefix=VERSION %s | ||
| 22 | # RUN: not ld.lld -v xyz 2>&1 | FileCheck -check-prefix=VERSION %s | ||
| 21 | # VERSION: LLD {{.*}} (compatible with GNU linkers) | 23 | # VERSION: LLD {{.*}} (compatible with GNU linkers) |
| 22 | 24 | ||
| 23 | # RUN: not ld.lld -v 2>&1 | FileCheck -check-prefix=VERSION %s | ||
| 24 | |||
| 25 | ## Attempt to link DSO with -r | 25 | ## Attempt to link DSO with -r |
| 26 | # RUN: ld.lld -shared %t -o %t.so | 26 | # 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 %s | 27 | # RUN: not ld.lld -r %t.so %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR %s |
deps/lld/test/ELF/duplicated-synthetic-sym.s+2-1| ... | @@ -1,9 +1,10 @@ | ... | @@ -1,9 +1,10 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 2 | // RUN: cd %S | 2 | // RUN: cd %S |
| 3 | // RUN: not ld.lld %t.o --format=binary duplicated-synthetic-sym.s -o %t.elf 2>&1 | FileCheck %s | 3 | // RUN: not ld.lld %t.o --format=binary duplicated-synthetic-sym.s -o %t.elf 2>&1 | FileCheck %s |
| 4 | // RUN: not ld.lld %t.o --format binary duplicated-synthetic-sym.s -o %t.elf 2>&1 | FileCheck %s | ||
| 4 | 5 | ||
| 5 | // CHECK: duplicate symbol: _binary_duplicated_synthetic_sym_s_start | 6 | // CHECK: duplicate symbol: _binary_duplicated_synthetic_sym_s_start |
| 6 | // CHECK: defined at (internal):(.data+0x0) | 7 | // CHECK: defined at <internal>:(.data+0x0) |
| 7 | 8 | ||
| 8 | .globl _binary_duplicated_synthetic_sym_s_start | 9 | .globl _binary_duplicated_synthetic_sym_s_start |
| 9 | _binary_duplicated_synthetic_sym_s_start: | 10 | _binary_duplicated_synthetic_sym_s_start: |
deps/lld/test/ELF/dynamic-got.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld %t.o -o %t.so -shared | 3 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 4 | // RUN: llvm-readobj -s -l -section-data -r %t.so | FileCheck %s | 4 | // RUN: llvm-readobj -s -l -section-data -r %t.so | FileCheck %s |
| 5 | 5 | ||
| 6 | // CHECK: Name: .got | 6 | // CHECK: Name: .got |
deps/lld/test/ELF/dynamic-list-empty.s created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # BFD reports a parse error on empty lists, but it is clear how to | ||
| 4 | # handle it. | ||
| 5 | |||
| 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 7 | # RUN: echo "{ };" > %t.list | ||
| 8 | # RUN: ld.lld -dynamic-list %t.list -shared %t.o -o %t.so | ||
| 9 | # RUN: llvm-readobj -r %t.so | FileCheck %s | ||
| 10 | |||
| 11 | # CHECK: Relocations [ | ||
| 12 | # CHECK-NEXT: ] | ||
| 13 | |||
| 14 | .globl foo | ||
| 15 | foo: | ||
| 16 | ret | ||
| 17 | |||
| 18 | call foo@PLT | ||
deps/lld/test/ELF/dynamic-list-preempt.s created+76| ... | @@ -0,0 +1,76 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 4 | # RUN: echo "{ foo; zed; };" > %t.list | ||
| 5 | # 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.so | ||
| 7 | # RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOCS %s | ||
| 8 | # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=DYNSYMS %s | ||
| 9 | |||
| 10 | # RELOCS: Relocations [ | ||
| 11 | # RELOCS-NEXT: Section ({{.*}}) .rela.plt { | ||
| 12 | # RELOCS-NEXT: R_X86_64_JUMP_SLOT foo 0x0 | ||
| 13 | # RELOCS-NEXT: R_X86_64_JUMP_SLOT ext 0x0 | ||
| 14 | # RELOCS-NEXT: } | ||
| 15 | # RELOCS-NEXT: ] | ||
| 16 | |||
| 17 | # DYNSYMS: DynamicSymbols [ | ||
| 18 | # DYNSYMS-NEXT: Symbol { | ||
| 19 | # DYNSYMS-NEXT: Name: @ (0) | ||
| 20 | # DYNSYMS-NEXT: Value: 0x0 | ||
| 21 | # DYNSYMS-NEXT: Size: 0 | ||
| 22 | # DYNSYMS-NEXT: Binding: Local | ||
| 23 | # DYNSYMS-NEXT: Type: None | ||
| 24 | # DYNSYMS-NEXT: Other: 0 | ||
| 25 | # DYNSYMS-NEXT: Section: Undefined | ||
| 26 | # DYNSYMS-NEXT: } | ||
| 27 | # DYNSYMS-NEXT: Symbol { | ||
| 28 | # DYNSYMS-NEXT: Name: bar@ | ||
| 29 | # DYNSYMS-NEXT: Value: | ||
| 30 | # DYNSYMS-NEXT: Size: | ||
| 31 | # DYNSYMS-NEXT: Binding: Global | ||
| 32 | # DYNSYMS-NEXT: Type: | ||
| 33 | # DYNSYMS-NEXT: Other: | ||
| 34 | # DYNSYMS-NEXT: Section: | ||
| 35 | # DYNSYMS-NEXT: } | ||
| 36 | # DYNSYMS-NEXT: Symbol { | ||
| 37 | # DYNSYMS-NEXT: Name: ext@ | ||
| 38 | # DYNSYMS-NEXT: Value: | ||
| 39 | # DYNSYMS-NEXT: Size: | ||
| 40 | # DYNSYMS-NEXT: Binding: Global | ||
| 41 | # DYNSYMS-NEXT: Type: | ||
| 42 | # DYNSYMS-NEXT: Other: | ||
| 43 | # DYNSYMS-NEXT: Section: | ||
| 44 | # DYNSYMS-NEXT: } | ||
| 45 | # DYNSYMS-NEXT: Symbol { | ||
| 46 | # DYNSYMS-NEXT: Name: foo@ | ||
| 47 | # DYNSYMS-NEXT: Value: | ||
| 48 | # DYNSYMS-NEXT: Size: | ||
| 49 | # DYNSYMS-NEXT: Binding: Global | ||
| 50 | # DYNSYMS-NEXT: Type: | ||
| 51 | # DYNSYMS-NEXT: Other: | ||
| 52 | # DYNSYMS-NEXT: Section: | ||
| 53 | # DYNSYMS-NEXT: } | ||
| 54 | # DYNSYMS-NEXT: ] | ||
| 55 | |||
| 56 | .globl foo | ||
| 57 | foo: | ||
| 58 | ret | ||
| 59 | |||
| 60 | .globl bar | ||
| 61 | bar: | ||
| 62 | ret | ||
| 63 | |||
| 64 | .globl baz | ||
| 65 | baz: | ||
| 66 | ret | ||
| 67 | |||
| 68 | .globl zed | ||
| 69 | zed: | ||
| 70 | ret | ||
| 71 | |||
| 72 | call foo@PLT | ||
| 73 | call bar@PLT | ||
| 74 | call baz@PLT | ||
| 75 | call zed@PLT | ||
| 76 | call ext@PLT | ||
deps/lld/test/ELF/dynamic-list-weak-archive.s created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/dynamic-list-weak-archive.s -o %t2.o | ||
| 5 | # RUN: rm -f %t.a | ||
| 6 | # RUN: llvm-ar rcs %t.a %t2.o | ||
| 7 | # RUN: echo "{ zed; };" > %t.list | ||
| 8 | # RUN: ld.lld -shared --dynamic-list %t.list %t1.o %t.a -o %t.so | ||
| 9 | # RUN: llvm-readobj -r %t.so | FileCheck %s | ||
| 10 | |||
| 11 | # CHECK: Relocations [ | ||
| 12 | # CHECK-NEXT: Section ({{.*}}) .rela.plt { | ||
| 13 | # CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT foo | ||
| 14 | # CHECK-NEXT: } | ||
| 15 | # CHECK-NEXT: ] | ||
| 16 | |||
| 17 | callq foo@PLT | ||
| 18 | .weak foo | ||
deps/lld/test/ELF/dynamic-list-wildcard.s created+53| ... | @@ -0,0 +1,53 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 4 | |||
| 5 | # RUN: echo "{ foo1*; };" > %t.list | ||
| 6 | # RUN: ld.lld --hash-style=sysv -pie --dynamic-list %t.list %t -o %t.exe | ||
| 7 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s | ||
| 8 | |||
| 9 | # CHECK: DynamicSymbols [ | ||
| 10 | # CHECK-NEXT: Symbol { | ||
| 11 | # CHECK-NEXT: Name:	 @ (0) | ||
| 12 | # CHECK-NEXT: Value:	 0x0 | ||
| 13 | # CHECK-NEXT: Size:	 0 | ||
| 14 | # CHECK-NEXT: Binding:	 Local (0x0) | ||
| 15 | # CHECK-NEXT: Type:	 None (0x0) | ||
| 16 | # CHECK-NEXT: Other:	 0 | ||
| 17 | # CHECK-NEXT: Section:	 Undefined (0x0) | ||
| 18 | # CHECK-NEXT: } | ||
| 19 | # CHECK-NEXT: Symbol { | ||
| 20 | # CHECK-NEXT: Name:	 foo1@ (1) | ||
| 21 | # CHECK-NEXT: Value:	 0x1000 | ||
| 22 | # CHECK-NEXT: Size:	 0 | ||
| 23 | # CHECK-NEXT: Binding:	 Global (0x1) | ||
| 24 | # CHECK-NEXT: Type:	 None (0x0) | ||
| 25 | # CHECK-NEXT: Other:	 0 | ||
| 26 | # CHECK-NEXT: Section:	 .text (0x4) | ||
| 27 | # CHECK-NEXT: } | ||
| 28 | # CHECK-NEXT: Symbol { | ||
| 29 | # CHECK-NEXT: Name:	 foo11@ (6) | ||
| 30 | # CHECK-NEXT: Value:	 0x1001 | ||
| 31 | # CHECK-NEXT: Size:	 0 | ||
| 32 | # CHECK-NEXT: Binding:	 Global (0x1) | ||
| 33 | # CHECK-NEXT: Type:	 None (0x0) | ||
| 34 | # CHECK-NEXT: Other:	 0 | ||
| 35 | # CHECK-NEXT: Section:	 .text (0x4) | ||
| 36 | # CHECK-NEXT: } | ||
| 37 | # CHECK-NEXT: ] | ||
| 38 | |||
| 39 | .globl foo1 | ||
| 40 | foo1: | ||
| 41 | ret | ||
| 42 | |||
| 43 | .globl foo11 | ||
| 44 | foo11: | ||
| 45 | ret | ||
| 46 | |||
| 47 | .globl foo2 | ||
| 48 | foo2: | ||
| 49 | ret | ||
| 50 | |||
| 51 | .globl _start | ||
| 52 | _start: | ||
| 53 | retq | ||
deps/lld/test/ELF/dynamic-list.s+9-13| ... | @@ -1,28 +1,24 @@ | ... | @@ -1,28 +1,24 @@ |
| 1 | ## There is some bad quoting interaction between lit's internal shell, which is | ||
| 2 | ## implemented in Python, and the Cygwin implementations of the Unix utilities. | ||
| 3 | ## Avoid running these tests on Windows for now by requiring a real shell. | ||
| 4 | |||
| 5 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 6 | 2 | ||
| 7 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o |
| 8 | # RUN: ld.lld -shared %t2.o -soname shared -o %t2.so | 4 | # RUN: ld.lld --hash-style=sysv -shared %t2.o -soname shared -o %t2.so |
| 9 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 10 | 6 | ||
| 11 | ## Check exporting only one symbol. | 7 | ## Check exporting only one symbol. |
| 12 | # RUN: echo "{ foo1; };" > %t.list | 8 | # RUN: echo "{ foo1; };" > %t.list |
| 13 | # RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe | 9 | # RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe |
| 14 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s | 10 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s |
| 15 | 11 | ||
| 16 | ## And now using quoted strings (the output is the same since it does | 12 | ## And now using quoted strings (the output is the same since it does |
| 17 | ## use any wildcard character). | 13 | ## use any wildcard character). |
| 18 | # RUN: echo "{ \"foo1\"; };" > %t.list | 14 | # RUN: echo "{ \"foo1\"; };" > %t.list |
| 19 | # RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe | 15 | # RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe |
| 20 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s | 16 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s |
| 21 | 17 | ||
| 22 | ## And now using --export-dynamic-symbol. | 18 | ## And now using --export-dynamic-symbol. |
| 23 | # RUN: ld.lld --export-dynamic-symbol foo1 %t %t2.so -o %t.exe | 19 | # RUN: ld.lld --hash-style=sysv --export-dynamic-symbol foo1 %t %t2.so -o %t.exe |
| 24 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s | 20 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s |
| 25 | # RUN: ld.lld --export-dynamic-symbol=foo1 %t %t2.so -o %t.exe | 21 | # RUN: ld.lld --hash-style=sysv --export-dynamic-symbol=foo1 %t %t2.so -o %t.exe |
| 26 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s | 22 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s |
| 27 | 23 | ||
| 28 | # CHECK: DynamicSymbols [ | 24 | # CHECK: DynamicSymbols [ |
| ... | @@ -49,11 +45,11 @@ | ... | @@ -49,11 +45,11 @@ |
| 49 | 45 | ||
| 50 | ## Now export all the foo1, foo2, and foo31 symbols | 46 | ## Now export all the foo1, foo2, and foo31 symbols |
| 51 | # RUN: echo "{ foo1; foo2; foo31; };" > %t.list | 47 | # RUN: echo "{ foo1; foo2; foo31; };" > %t.list |
| 52 | # RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe | 48 | # RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe |
| 53 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK2 %s | 49 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK2 %s |
| 54 | # RUN: echo "{ foo1; foo2; };" > %t1.list | 50 | # RUN: echo "{ foo1; foo2; };" > %t1.list |
| 55 | # RUN: echo "{ foo31; };" > %t2.list | 51 | # RUN: echo "{ foo31; };" > %t2.list |
| 56 | # RUN: ld.lld --dynamic-list %t1.list --dynamic-list %t2.list %t %t2.so -o %t.exe | 52 | # RUN: ld.lld --hash-style=sysv --dynamic-list %t1.list --dynamic-list %t2.list %t %t2.so -o %t.exe |
| 57 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK2 %s | 53 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK2 %s |
| 58 | 54 | ||
| 59 | # CHECK2: DynamicSymbols [ | 55 | # CHECK2: DynamicSymbols [ |
| ... | @@ -99,11 +95,11 @@ | ... | @@ -99,11 +95,11 @@ |
| 99 | ## --export-dynamic overrides --dynamic-list, i.e. --export-dynamic with an | 95 | ## --export-dynamic overrides --dynamic-list, i.e. --export-dynamic with an |
| 100 | ## incomplete dynamic-list still exports everything. | 96 | ## incomplete dynamic-list still exports everything. |
| 101 | # RUN: echo "{ foo2; };" > %t.list | 97 | # RUN: echo "{ foo2; };" > %t.list |
| 102 | # RUN: ld.lld --dynamic-list %t.list --export-dynamic %t %t2.so -o %t.exe | 98 | # RUN: ld.lld --hash-style=sysv --dynamic-list %t.list --export-dynamic %t %t2.so -o %t.exe |
| 103 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK3 %s | 99 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK3 %s |
| 104 | 100 | ||
| 105 | ## The same with --export-dynamic-symbol. | 101 | ## The same with --export-dynamic-symbol. |
| 106 | # RUN: ld.lld --export-dynamic-symbol=foo2 --export-dynamic %t %t2.so -o %t.exe | 102 | # RUN: ld.lld --hash-style=sysv --export-dynamic-symbol=foo2 --export-dynamic %t %t2.so -o %t.exe |
| 107 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK3 %s | 103 | # RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK3 %s |
| 108 | 104 | ||
| 109 | # CHECK3: DynamicSymbols [ | 105 | # CHECK3: DynamicSymbols [ |
deps/lld/test/ELF/dynamic-no-rosegment.s created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld -shared --no-rosegment -z rodynamic -o %t %t.o | ||
| 4 | # RUN: llvm-readobj -dynamic-table -s %t | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: DynamicSection [ (7 entries) | ||
| 7 | # CHECK-NEXT: Tag Type Name/Value | ||
| 8 | # CHECK-NEXT: 0x0000000000000006 SYMTAB 0x120 | ||
| 9 | # CHECK-NEXT: 0x000000000000000B SYMENT 24 (bytes) | ||
| 10 | # CHECK-NEXT: 0x0000000000000005 STRTAB 0x1D0 | ||
| 11 | # CHECK-NEXT: 0x000000000000000A STRSZ 1 (bytes) | ||
| 12 | # CHECK-NEXT: 0x000000006FFFFEF5 GNU_HASH 0x138 | ||
| 13 | # CHECK-NEXT: 0x0000000000000004 HASH 0x150 | ||
| 14 | # CHECK-NEXT: 0x0000000000000000 NULL 0x0 | ||
| 15 | # CHECK-NEXT: ] | ||
deps/lld/test/ELF/dynamic-reloc-in-ro.s+3-3| ... | @@ -2,9 +2,9 @@ | ... | @@ -2,9 +2,9 @@ |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s | 3 | // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s |
| 4 | 4 | ||
| 5 | // CHECK: can't create dynamic relocation R_X86_64_64 against local symbol in readonly segment | 5 | // CHECK: can't create dynamic relocation R_X86_64_64 against local symbol in readonly segment; recompile object files with -fPIC |
| 6 | // CHECK: >>> defined in {{.*}}.o | 6 | // CHECK-NEXT: >>> defined in {{.*}}.o |
| 7 | // CHECK: >>> referenced by {{.*}}.o:(.text+0x0) | 7 | // CHECK-NEXT: >>> referenced by {{.*}}.o:(.text+0x0) |
| 8 | 8 | ||
| 9 | foo: | 9 | foo: |
| 10 | .quad foo | 10 | .quad foo |
deps/lld/test/ELF/dynamic-reloc.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o |
| 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dynamic-reloc.s -o %t3.o | 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dynamic-reloc.s -o %t3.o |
| 4 | // RUN: ld.lld -shared %t2.o -o %t2.so | 4 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 5 | // RUN: ld.lld %t.o %t3.o %t2.so -o %t | 5 | // RUN: ld.lld --hash-style=sysv %t.o %t3.o %t2.so -o %t |
| 6 | // RUN: llvm-readobj -dynamic-table -r --expand-relocs -s %t | FileCheck %s | 6 | // RUN: llvm-readobj -dynamic-table -r --expand-relocs -s %t | FileCheck %s |
| 7 | // REQUIRES: x86 | 7 | // REQUIRES: x86 |
| 8 | 8 |
deps/lld/test/ELF/dynstr-no-rosegment.s created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | # Verify that a .dynstr in the .text segment has null byte terminators | ||
| 2 | |||
| 3 | # REQUIRES: x86 | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 5 | # RUN: ld.lld %t.o -no-rosegment -o %t.so -shared | ||
| 6 | # RUN: llvm-objdump %t.so -s -j .dynstr | FileCheck %s | ||
| 7 | |||
| 8 | # CHECK: 00666f6f 00 .foo. | ||
| 9 | |||
| 10 | .globl foo | ||
| 11 | foo: | ||
| 12 | ret | ||
deps/lld/test/ELF/dynsym-no-rosegment.s created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld -shared --no-rosegment -o %t %t.o | ||
| 4 | # RUN: llvm-readobj -dyn-symbols -s %t | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: DynamicSymbols [ | ||
| 7 | # CHECK-NEXT: Symbol { | ||
| 8 | # CHECK-NEXT: Name: @ (0) | ||
| 9 | # CHECK-NEXT: Value: 0x0 | ||
| 10 | # CHECK-NEXT: Size: 0 | ||
| 11 | # CHECK-NEXT: Binding: Local | ||
| 12 | # CHECK-NEXT: Type: None | ||
| 13 | # CHECK-NEXT: Other: 0 | ||
| 14 | # CHECK-NEXT: Section: Undefined | ||
| 15 | # CHECK-NEXT: } | ||
| 16 | # CHECK-NEXT: Symbol { | ||
| 17 | # CHECK-NEXT: Name: undef@ | ||
| 18 | # CHECK-NEXT: Value: 0x0 | ||
| 19 | # CHECK-NEXT: Size: 0 | ||
| 20 | # CHECK-NEXT: Binding: Global | ||
| 21 | # CHECK-NEXT: Type: None | ||
| 22 | # CHECK-NEXT: Other: 0 | ||
| 23 | # CHECK-NEXT: Section: Undefined | ||
| 24 | # CHECK-NEXT: } | ||
| 25 | # CHECK-NEXT: ] | ||
| 26 | |||
| 27 | callq undef@PLT | ||
deps/lld/test/ELF/dynsym-pie.s+48-4| ... | @@ -3,6 +3,51 @@ | ... | @@ -3,6 +3,51 @@ |
| 3 | # RUN: ld.lld -pie %t -o %t.out | 3 | # RUN: ld.lld -pie %t -o %t.out |
| 4 | # RUN: llvm-readobj -t -dyn-symbols %t.out | FileCheck %s | 4 | # RUN: llvm-readobj -t -dyn-symbols %t.out | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: Symbols [ | ||
| 7 | # CHECK: Symbol { | ||
| 8 | # CHECK: Name: hidden | ||
| 9 | # CHECK-NEXT: Value: 0x1000 | ||
| 10 | # CHECK-NEXT: Size: 0 | ||
| 11 | # CHECK-NEXT: Binding: Local | ||
| 12 | # CHECK-NEXT: Type: None | ||
| 13 | # CHECK-NEXT: Other [ | ||
| 14 | # CHECK-NEXT: STV_HIDDEN | ||
| 15 | # CHECK-NEXT: ] | ||
| 16 | # CHECK-NEXT: Section: .text | ||
| 17 | # CHECK-NEXT: } | ||
| 18 | # CHECK: Symbol { | ||
| 19 | # CHECK: Name: internal | ||
| 20 | # CHECK-NEXT: Value: 0x1000 | ||
| 21 | # CHECK-NEXT: Size: 0 | ||
| 22 | # CHECK-NEXT: Binding: Local | ||
| 23 | # CHECK-NEXT: Type: None | ||
| 24 | # CHECK-NEXT: Other [ | ||
| 25 | # CHECK-NEXT: STV_INTERNAL | ||
| 26 | # CHECK-NEXT: ] | ||
| 27 | # CHECK-NEXT: Section: .text | ||
| 28 | # CHECK-NEXT: } | ||
| 29 | # CHECK: Symbol { | ||
| 30 | # CHECK: Name: default | ||
| 31 | # CHECK-NEXT: Value: 0x1000 | ||
| 32 | # CHECK-NEXT: Size: 0 | ||
| 33 | # CHECK-NEXT: Binding: Global | ||
| 34 | # CHECK-NEXT: Type: None | ||
| 35 | # CHECK-NEXT: Other: 0 | ||
| 36 | # CHECK-NEXT: Section: .text | ||
| 37 | # CHECK-NEXT: } | ||
| 38 | # CHECK: Symbol { | ||
| 39 | # CHECK: Name: protected | ||
| 40 | # CHECK-NEXT: Value: 0x1000 | ||
| 41 | # CHECK-NEXT: Size: 0 | ||
| 42 | # CHECK-NEXT: Binding: Global | ||
| 43 | # CHECK-NEXT: Type: None | ||
| 44 | # CHECK-NEXT: Other [ | ||
| 45 | # CHECK-NEXT: STV_PROTECTED | ||
| 46 | # CHECK-NEXT: ] | ||
| 47 | # CHECK-NEXT: Section: .text | ||
| 48 | # CHECK-NEXT: } | ||
| 49 | # CHECK-NEXT: ] | ||
| 50 | |||
| 6 | # CHECK: DynamicSymbols [ | 51 | # CHECK: DynamicSymbols [ |
| 7 | # CHECK-NEXT: Symbol { | 52 | # CHECK-NEXT: Symbol { |
| 8 | # CHECK-NEXT: Name: @ | 53 | # CHECK-NEXT: Name: @ |
| ... | @@ -23,14 +68,13 @@ _start: | ... | @@ -23,14 +68,13 @@ _start: |
| 23 | default: | 68 | default: |
| 24 | 69 | ||
| 25 | .global protected | 70 | .global protected |
| 71 | .protected protected | ||
| 26 | protected: | 72 | protected: |
| 27 | 73 | ||
| 28 | .global hidden | 74 | .global hidden |
| 75 | .hidden hidden | ||
| 29 | hidden: | 76 | hidden: |
| 30 | 77 | ||
| 31 | .global internal | 78 | .global internal |
| 79 | .internal internal | ||
| 32 | internal: | 80 | internal: |
| 33 | |||
| 34 | .global protected_with_hidden | ||
| 35 | .protected | ||
| 36 | protected_with_hidden: |
deps/lld/test/ELF/edata-etext.s+1-1| ... | @@ -19,7 +19,7 @@ | ... | @@ -19,7 +19,7 @@ |
| 19 | # CHECK: SYMBOL TABLE: | 19 | # CHECK: SYMBOL TABLE: |
| 20 | # CHECK-NEXT: 0000000000000000 *UND* 00000000 | 20 | # CHECK-NEXT: 0000000000000000 *UND* 00000000 |
| 21 | # CHECK-NEXT: 0000000000202002 .data 00000000 _edata | 21 | # CHECK-NEXT: 0000000000202002 .data 00000000 _edata |
| 22 | # CHECK-NEXT: 000000000020200a .data 00000000 _end | 22 | # CHECK-NEXT: 000000000020200a .bss 00000000 _end |
| 23 | # CHECK-NEXT: 0000000000201001 .text 00000000 _etext | 23 | # CHECK-NEXT: 0000000000201001 .text 00000000 _etext |
| 24 | # CHECK-NEXT: 0000000000201000 .text 00000000 _start | 24 | # CHECK-NEXT: 0000000000201000 .text 00000000 _start |
| 25 | 25 |
deps/lld/test/ELF/edata-no-bss.s created+18| ... | @@ -0,0 +1,18 @@ | ||
| 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 --gc-sections | ||
| 4 | # RUN: llvm-objdump -t -section-headers %t | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: .data 00000008 0000000000202000 DATA | ||
| 7 | |||
| 8 | # CHECK: 0000000000202008 .data 00000000 _edata | ||
| 9 | |||
| 10 | .text | ||
| 11 | .globl _start | ||
| 12 | _start: | ||
| 13 | .long .data - . | ||
| 14 | |||
| 15 | .data | ||
| 16 | .quad 0 | ||
| 17 | |||
| 18 | .globl _edata | ||
deps/lld/test/ELF/eh-align-cie.s+1-1| ... | @@ -31,7 +31,7 @@ bar: | ... | @@ -31,7 +31,7 @@ bar: |
| 31 | // OBJ-NEXT: ) | 31 | // OBJ-NEXT: ) |
| 32 | 32 | ||
| 33 | 33 | ||
| 34 | // RUN: ld.lld %t.o -o %t -shared | 34 | // RUN: ld.lld --hash-style=sysv %t.o -o %t -shared |
| 35 | // RUN: llvm-readobj -s -section-data %t | FileCheck %s | 35 | // RUN: llvm-readobj -s -section-data %t | FileCheck %s |
| 36 | 36 | ||
| 37 | // Check that the size of the CIE was changed to (0x1C + 4) and the FDE one was | 37 | // Check that the size of the CIE was changed to (0x1C + 4) and the FDE one was |
deps/lld/test/ELF/eh-frame-hdr-augmentation.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld --eh-frame-hdr %t.o -o %t -shared | 3 | // RUN: ld.lld --hash-style=sysv --eh-frame-hdr %t.o -o %t -shared |
| 4 | // RUN: llvm-objdump --dwarf=frames %t | FileCheck %s | 4 | // RUN: llvm-objdump --dwarf=frames %t | FileCheck %s |
| 5 | 5 | ||
| 6 | // CHECK: .eh_frame contents: | 6 | // CHECK: .eh_frame contents: |
deps/lld/test/ELF/eh-frame-hdr-icf-fde.s created+95| ... | @@ -0,0 +1,95 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | ## Testcase checks that we correctly deduplicate FDEs when ICF | ||
| 4 | ## merges two sections. | ||
| 5 | |||
| 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 7 | # RUN: ld.lld %t -o %t2 --icf=all --eh-frame-hdr | ||
| 8 | # RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=OBJ | ||
| 9 | # RUN: llvm-readobj -s -section-data %t2 | FileCheck %s | ||
| 10 | |||
| 11 | # OBJ: Relocations [ | ||
| 12 | # OBJ-NEXT: Section {{.*}} .rela.eh_frame { | ||
| 13 | # OBJ-NEXT: 0x20 R_X86_64_PC32 .text.f1 0x0 | ||
| 14 | # OBJ-NEXT: 0x34 R_X86_64_PC32 .text.f1 0x2 | ||
| 15 | # OBJ-NEXT: 0x48 R_X86_64_PC32 .text.f2 0x0 | ||
| 16 | # OBJ-NEXT: 0x5C R_X86_64_PC32 .text.f2 0x2 | ||
| 17 | # OBJ-NEXT: } | ||
| 18 | # OBJ-NEXT: ] | ||
| 19 | |||
| 20 | # CHECK: Section { | ||
| 21 | # CHECK: Index: 1 | ||
| 22 | # CHECK: Name: .eh_frame_hdr | ||
| 23 | # CHECK-NEXT: Type: SHT_PROGBITS | ||
| 24 | # CHECK-NEXT: Flags [ | ||
| 25 | # CHECK-NEXT: SHF_ALLOC | ||
| 26 | # CHECK-NEXT: ] | ||
| 27 | # CHECK-NEXT: Address: 0x200158 | ||
| 28 | # CHECK-NEXT: Offset: 0x158 | ||
| 29 | # CHECK-NEXT: Size: 28 | ||
| 30 | # CHECK-NEXT: Link: 0 | ||
| 31 | # CHECK-NEXT: Info: 0 | ||
| 32 | # CHECK-NEXT: AddressAlignment: | ||
| 33 | # CHECK-NEXT: EntrySize: 0 | ||
| 34 | # CHECK-NEXT: SectionData ( | ||
| 35 | # CHECK-NEXT: 0000: 011B033B 1C000000 02000000 A80E0000 | ||
| 36 | ## ^ ^-- FDE(1) PC | ||
| 37 | ## ^-- Number of FDEs | ||
| 38 | # CHECK-NEXT: 0010: 38000000 AA0E0000 50000000 | ||
| 39 | ## ^-- FDE(2) PC | ||
| 40 | # CHECK-NEXT: ) | ||
| 41 | # CHECK-NEXT: } | ||
| 42 | ## FDE(1) == 0x201000 - .eh_frame_hdr(0x200158) = 0xEA8 | ||
| 43 | ## FDE(2) == 0x201000 - .eh_frame_hdr(0x200158) + 2(relocation addend) = 0xEAA | ||
| 44 | |||
| 45 | ## Check .eh_frame contains CIE and two FDEs remaining after ICF. | ||
| 46 | # CHECK-NEXT: Section { | ||
| 47 | # CHECK-NEXT: Index: 2 | ||
| 48 | # CHECK-NEXT: Name: .eh_frame | ||
| 49 | # CHECK-NEXT: Type: SHT_PROGBITS | ||
| 50 | # CHECK-NEXT: Flags [ | ||
| 51 | # CHECK-NEXT: SHF_ALLOC | ||
| 52 | # CHECK-NEXT: ] | ||
| 53 | # CHECK-NEXT: Address: 0x200178 | ||
| 54 | # CHECK-NEXT: Offset: 0x178 | ||
| 55 | # CHECK-NEXT: Size: 72 | ||
| 56 | # CHECK-NEXT: Link: 0 | ||
| 57 | # CHECK-NEXT: Info: 0 | ||
| 58 | # CHECK-NEXT: AddressAlignment: 8 | ||
| 59 | # CHECK-NEXT: EntrySize: 0 | ||
| 60 | # CHECK-NEXT: SectionData ( | ||
| 61 | # CHECK-NEXT: 0000: 14000000 00000000 017A5200 01781001 | ||
| 62 | # CHECK-NEXT: 0010: 1B0C0708 90010000 14000000 1C000000 | ||
| 63 | # CHECK-NEXT: 0020: 680E0000 01000000 00000000 00000000 | ||
| 64 | # CHECK-NEXT: 0030: 14000000 34000000 520E0000 01000000 | ||
| 65 | # CHECK-NEXT: 0040: 00000000 00000000 | ||
| 66 | # CHECK-NEXT: ) | ||
| 67 | # CHECK-NEXT: } | ||
| 68 | |||
| 69 | # CHECK: Section { | ||
| 70 | # CHECK: Index: | ||
| 71 | # CHECK: Name: .text | ||
| 72 | # CHECK-NEXT: Type: SHT_PROGBITS | ||
| 73 | # CHECK-NEXT: Flags [ | ||
| 74 | # CHECK-NEXT: SHF_ALLOC | ||
| 75 | # CHECK-NEXT: SHF_EXECINSTR | ||
| 76 | # CHECK-NEXT: ] | ||
| 77 | # CHECK-NEXT: Address: 0x201000 | ||
| 78 | |||
| 79 | .section .text.f1, "ax" | ||
| 80 | .cfi_startproc | ||
| 81 | nop | ||
| 82 | .cfi_endproc | ||
| 83 | nop | ||
| 84 | .cfi_startproc | ||
| 85 | ret | ||
| 86 | .cfi_endproc | ||
| 87 | |||
| 88 | .section .text.f2, "ax" | ||
| 89 | .cfi_startproc | ||
| 90 | nop | ||
| 91 | .cfi_endproc | ||
| 92 | nop | ||
| 93 | .cfi_startproc | ||
| 94 | ret | ||
| 95 | .cfi_endproc | ||
deps/lld/test/ELF/eh-frame-hdr-icf.s+8-7| ... | @@ -2,17 +2,18 @@ | ... | @@ -2,17 +2,18 @@ |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: ld.lld %t -o %t2 --icf=all --eh-frame-hdr | 4 | # RUN: ld.lld %t -o %t2 --icf=all --eh-frame-hdr |
| 5 | # RUN: llvm-objdump -s %t2 | FileCheck %s | 5 | # RUN: llvm-objdump -s -section-headers %t2 | FileCheck %s |
| 6 | |||
| 7 | ## Check .eh_frame_hdr contains single FDE and no garbage data at tail. | ||
| 8 | # CHECK: Sections: | ||
| 9 | # CHECK: Idx Name Size | ||
| 10 | # CHECK: .eh_frame_hdr 00000014 | ||
| 6 | 11 | ||
| 7 | # CHECK: Contents of section .eh_frame_hdr: | 12 | # CHECK: Contents of section .eh_frame_hdr: |
| 8 | # CHECK-NEXT: 200158 011b033b 1c000000 01000000 a80e0000 | 13 | # CHECK-NEXT: 200158 011b033b 14000000 01000000 |
| 9 | # ^ FDE count | 14 | # ^ FDE count |
| 10 | # CHECK-NEXT: 200168 38000000 00000000 00000000 | ||
| 11 | # ^ FDE for f2 | ||
| 12 | 15 | ||
| 13 | .globl _start, f1, f2 | 16 | .globl f1, f2 |
| 14 | _start: | ||
| 15 | ret | ||
| 16 | 17 | ||
| 17 | .section .text.f1, "ax" | 18 | .section .text.f1, "ax" |
| 18 | f1: | 19 | f1: |
deps/lld/test/ELF/eh-frame-hdr.s+10-2| ... | @@ -1,9 +1,17 @@ | ... | @@ -1,9 +1,17 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | |||
| 3 | // RUN: ld.lld %t.o -o %t | 4 | // RUN: ld.lld %t.o -o %t |
| 4 | // RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t | FileCheck %s --check-prefix=NOHDR | 5 | // RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t \ |
| 6 | // RUN: | FileCheck %s --check-prefix=NOHDR | ||
| 7 | |||
| 8 | // 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 \ | ||
| 10 | // RUN: | FileCheck %s --check-prefix=NOHDR | ||
| 11 | |||
| 5 | // RUN: ld.lld --eh-frame-hdr %t.o -o %t | 12 | // RUN: ld.lld --eh-frame-hdr %t.o -o %t |
| 6 | // RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t | FileCheck %s --check-prefix=HDR | 13 | // RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t \ |
| 14 | // RUN: | FileCheck %s --check-prefix=HDR | ||
| 7 | // RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=HDRDISASM | 15 | // RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=HDRDISASM |
| 8 | 16 | ||
| 9 | .section foo,"ax",@progbits | 17 | .section foo,"ax",@progbits |
deps/lld/test/ELF/eh-frame-merge.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld %t.o %t.o -o %t -shared | 3 | // RUN: ld.lld --hash-style=sysv %t.o %t.o -o %t -shared |
| 4 | // RUN: llvm-readobj -s -section-data %t | FileCheck %s | 4 | // RUN: llvm-readobj -s -section-data %t | FileCheck %s |
| 5 | 5 | ||
| 6 | .section	foo,"ax",@progbits | 6 | .section	foo,"ax",@progbits |
deps/lld/test/ELF/eh-frame-padding-no-rosegment.s+1-1| ... | @@ -31,7 +31,7 @@ bar: | ... | @@ -31,7 +31,7 @@ bar: |
| 31 | // OBJ-NEXT: 0020: 20000000 00000000 00000000 00000000 | 31 | // OBJ-NEXT: 0020: 20000000 00000000 00000000 00000000 |
| 32 | // OBJ-NEXT: ) | 32 | // OBJ-NEXT: ) |
| 33 | 33 | ||
| 34 | // RUN: ld.lld %t.o -no-rosegment -o %t -shared | 34 | // RUN: ld.lld --hash-style=sysv %t.o -no-rosegment -o %t -shared |
| 35 | 35 | ||
| 36 | // Check that .eh_frame is in the same segment as .text | 36 | // Check that .eh_frame is in the same segment as .text |
| 37 | // RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=PHDR %s | 37 | // RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=PHDR %s |
deps/lld/test/ELF/eh-frame.s created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/eh-frame.s -o %t2.o | ||
| 4 | // RUN: ld.lld %t1.o %t2.o -o %t | ||
| 5 | // RUN: llvm-dwarfdump -eh-frame %t | FileCheck %s | ||
| 6 | |||
| 7 | // CHECK: DW_CFA_def_cfa_offset: +64 | ||
| 8 | // CHECK: DW_CFA_def_cfa_offset: +32 | ||
| 9 | |||
| 10 | .cfi_startproc | ||
| 11 | .cfi_def_cfa_offset 64 | ||
| 12 | .cfi_endproc | ||
deps/lld/test/ELF/emit-relocs-gc.s created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 3 | |||
| 4 | ## Show that we emit .rela.bar and .rela.text when GC is disabled. | ||
| 5 | # RUN: ld.lld --emit-relocs %t.o -o %t | ||
| 6 | # RUN: llvm-objdump %t -section-headers | FileCheck %s --check-prefix=NOGC | ||
| 7 | # NOGC: .rela.text | ||
| 8 | # NOGC: .rela.bar | ||
| 9 | |||
| 10 | ## GC collects .bar section and we exclude .rela.bar from output. We keep | ||
| 11 | ## .rela.text because we keep .text. | ||
| 12 | # RUN: ld.lld --gc-sections --emit-relocs --print-gc-sections %t.o -o %t \ | ||
| 13 | # RUN: | FileCheck --check-prefix=MSG %s | ||
| 14 | # MSG: removing unused section from '.bar' in file | ||
| 15 | # MSG: removing unused section from '.rela.bar' in file | ||
| 16 | # RUN: llvm-objdump %t -section-headers | FileCheck %s --check-prefix=GC | ||
| 17 | # GC-NOT: rela.bar | ||
| 18 | # GC: rela.text | ||
| 19 | # GC-NOT: rela.bar | ||
| 20 | |||
| 21 | .section .bar,"a" | ||
| 22 | .quad .bar | ||
| 23 | |||
| 24 | .text | ||
| 25 | relocs: | ||
| 26 | .quad _start | ||
| 27 | |||
| 28 | .global _start | ||
| 29 | _start: | ||
| 30 | nop | ||
deps/lld/test/ELF/emit-relocs-merge.s+1-1| ... | @@ -8,7 +8,7 @@ | ... | @@ -8,7 +8,7 @@ |
| 8 | # CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0 | 8 | # CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0 |
| 9 | # CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0 | 9 | # CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0 |
| 10 | # CHECK-NEXT: } | 10 | # CHECK-NEXT: } |
| 11 | # CHECK-NEXT: Section ({{.*}}) .rela.data.foo { | 11 | # CHECK-NEXT: Section ({{.*}}) .rela.data { |
| 12 | # CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0 | 12 | # CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0 |
| 13 | # CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0 | 13 | # CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0 |
| 14 | # CHECK-NEXT: } | 14 | # CHECK-NEXT: } |
deps/lld/test/ELF/emit-relocs-mergeable-i386.s created+66| ... | @@ -0,0 +1,66 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t1 | ||
| 3 | # RUN: ld.lld --emit-relocs %t1 -o %t2 | ||
| 4 | # RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s | ||
| 5 | |||
| 6 | ## Check lf we produce proper relocations when doing merging of SHF_MERGE sections. | ||
| 7 | |||
| 8 | ## Check addends of relocations are: 0x0, 0x8, 0x8, 0x4 | ||
| 9 | # CHECK: Section { | ||
| 10 | # CHECK: Index: | ||
| 11 | # CHECK: Name: .foo | ||
| 12 | # CHECK-NEXT: Type: SHT_PROGBITS | ||
| 13 | # CHECK-NEXT: Flags [ | ||
| 14 | # CHECK-NEXT: SHF_ALLOC | ||
| 15 | # CHECK-NEXT: SHF_EXECINSTR | ||
| 16 | # CHECK-NEXT: ] | ||
| 17 | # CHECK-NEXT: Address: | ||
| 18 | # CHECK-NEXT: Offset: | ||
| 19 | # CHECK-NEXT: Size: | ||
| 20 | # CHECK-NEXT: Link: | ||
| 21 | # CHECK-NEXT: Info: | ||
| 22 | # CHECK-NEXT: AddressAlignment: | ||
| 23 | # CHECK-NEXT: EntrySize: | ||
| 24 | # CHECK-NEXT: SectionData ( | ||
| 25 | # CHECK-NEXT: 0000: 00000000 08000000 08000000 04000000 | ||
| 26 | # CHECK-NEXT: ) | ||
| 27 | # CHECK-NEXT: } | ||
| 28 | |||
| 29 | ## Check that offsets for AAA is 0x0, for BBB is 0x8 and CCC has offset 0x4. | ||
| 30 | # CHECK: Section { | ||
| 31 | # CHECK: Index: | ||
| 32 | # CHECK: Name: .strings | ||
| 33 | # CHECK-NEXT: Type: SHT_PROGBITS | ||
| 34 | # CHECK-NEXT: Flags [ | ||
| 35 | # CHECK-NEXT: SHF_MERGE | ||
| 36 | # CHECK-NEXT: SHF_STRINGS | ||
| 37 | # CHECK-NEXT: ] | ||
| 38 | # CHECK-NEXT: Address: | ||
| 39 | # CHECK-NEXT: Offset: | ||
| 40 | # CHECK-NEXT: Size: | ||
| 41 | # CHECK-NEXT: Link: | ||
| 42 | # CHECK-NEXT: Info: | ||
| 43 | # CHECK-NEXT: AddressAlignment: | ||
| 44 | # CHECK-NEXT: EntrySize: | ||
| 45 | # CHECK-NEXT: SectionData ( | ||
| 46 | # CHECK-NEXT: |AAA.CCC.BBB.| | ||
| 47 | # CHECK-NEXT: ) | ||
| 48 | # CHECK-NEXT: } | ||
| 49 | |||
| 50 | .section .strings,"MS",@progbits,1,unique,10 | ||
| 51 | .Linfo_string0: | ||
| 52 | .asciz "AAA" | ||
| 53 | .Linfo_string1: | ||
| 54 | .asciz "BBB" | ||
| 55 | |||
| 56 | .section .strings,"MS",@progbits,1,unique,20 | ||
| 57 | .Linfo_string2: | ||
| 58 | .asciz "BBB" | ||
| 59 | .Linfo_string3: | ||
| 60 | .asciz "CCC" | ||
| 61 | |||
| 62 | .section .foo,"ax",@progbits | ||
| 63 | .long .Linfo_string0 | ||
| 64 | .long .Linfo_string1 | ||
| 65 | .long .Linfo_string2 | ||
| 66 | .long .Linfo_string3 | ||
deps/lld/test/ELF/emit-relocs-mergeable.s created+53| ... | @@ -0,0 +1,53 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 | ||
| 3 | # RUN: ld.lld --emit-relocs %t1 -o %t2 | ||
| 4 | # RUN: llvm-readobj -sections -section-data -r %t2 | FileCheck %s | ||
| 5 | |||
| 6 | ## Check if we produce proper relocations when doing merging of SHF_MERGE sections. | ||
| 7 | |||
| 8 | # CHECK: Section { | ||
| 9 | # CHECK: Index: | ||
| 10 | # CHECK: Name: .strings | ||
| 11 | # CHECK-NEXT: Type: SHT_PROGBITS | ||
| 12 | # CHECK-NEXT: Flags [ | ||
| 13 | # CHECK-NEXT: SHF_MERGE | ||
| 14 | # CHECK-NEXT: SHF_STRINGS | ||
| 15 | # CHECK-NEXT: ] | ||
| 16 | # CHECK-NEXT: Address: | ||
| 17 | # CHECK-NEXT: Offset: | ||
| 18 | # CHECK-NEXT: Size: 12 | ||
| 19 | # CHECK-NEXT: Link: | ||
| 20 | # CHECK-NEXT: Info: | ||
| 21 | # CHECK-NEXT: AddressAlignment: | ||
| 22 | # CHECK-NEXT: EntrySize: | ||
| 23 | # CHECK-NEXT: SectionData ( | ||
| 24 | # CHECK-NEXT: 0000: 41414100 43434300 42424200 |AAA.CCC.BBB.| | ||
| 25 | # CHECK-NEXT: ) | ||
| 26 | # CHECK-NEXT: } | ||
| 27 | |||
| 28 | # CHECK: Relocations [ | ||
| 29 | # CHECK-NEXT: Section {{.*}} .rela.foo { | ||
| 30 | # CHECK-NEXT: 0x201000 R_X86_64_64 .strings 0x0 | ||
| 31 | # CHECK-NEXT: 0x201008 R_X86_64_64 .strings 0x8 | ||
| 32 | # CHECK-NEXT: 0x201010 R_X86_64_64 .strings 0x8 | ||
| 33 | # CHECK-NEXT: 0x201018 R_X86_64_64 .strings 0x4 | ||
| 34 | # CHECK-NEXT: } | ||
| 35 | # CHECK-NEXT: ] | ||
| 36 | |||
| 37 | .section .strings,"MS",@progbits,1,unique,10 | ||
| 38 | .Linfo_string0: | ||
| 39 | .asciz "AAA" | ||
| 40 | .Linfo_string1: | ||
| 41 | .asciz "BBB" | ||
| 42 | |||
| 43 | .section .strings,"MS",@progbits,1,unique,20 | ||
| 44 | .Linfo_string2: | ||
| 45 | .asciz "BBB" | ||
| 46 | .Linfo_string3: | ||
| 47 | .asciz "CCC" | ||
| 48 | |||
| 49 | .section .foo,"ax",@progbits | ||
| 50 | .quad .Linfo_string0 | ||
| 51 | .quad .Linfo_string1 | ||
| 52 | .quad .Linfo_string2 | ||
| 53 | .quad .Linfo_string3 | ||
deps/lld/test/ELF/emit-relocs-shared.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | # RUN: ld.lld --emit-relocs %t.o -o %t.so -shared | 3 | # RUN: ld.lld --hash-style=sysv --emit-relocs %t.o -o %t.so -shared |
| 4 | # RUN: llvm-readobj -r %t.so | FileCheck %s | 4 | # RUN: llvm-readobj -r %t.so | FileCheck %s |
| 5 | 5 | ||
| 6 | .data | 6 | .data |
deps/lld/test/ELF/emit-relocs.s+11-2| ... | @@ -64,6 +64,15 @@ | ... | @@ -64,6 +64,15 @@ |
| 64 | # CHECK-NEXT: Section: .text | 64 | # CHECK-NEXT: Section: .text |
| 65 | # CHECK-NEXT: } | 65 | # CHECK-NEXT: } |
| 66 | # CHECK-NEXT: Symbol { | 66 | # CHECK-NEXT: Symbol { |
| 67 | # CHECK-NEXT: Name: | ||
| 68 | # CHECK-NEXT: Value: 0x0 | ||
| 69 | # CHECK-NEXT: Size: 0 | ||
| 70 | # CHECK-NEXT: Binding: Local | ||
| 71 | # CHECK-NEXT: Type: Section | ||
| 72 | # CHECK-NEXT: Other: 0 | ||
| 73 | # CHECK-NEXT: Section: .comment | ||
| 74 | # CHECK-NEXT: } | ||
| 75 | # CHECK-NEXT: Symbol { | ||
| 67 | # CHECK-NEXT: Name: fn | 76 | # CHECK-NEXT: Name: fn |
| 68 | # CHECK-NEXT: Value: 0x201000 | 77 | # CHECK-NEXT: Value: 0x201000 |
| 69 | # CHECK-NEXT: Size: 0 | 78 | # CHECK-NEXT: Size: 0 |
| ... | @@ -83,7 +92,7 @@ | ... | @@ -83,7 +92,7 @@ |
| 83 | # CHECK-NEXT: } | 92 | # CHECK-NEXT: } |
| 84 | # CHECK-NEXT: ] | 93 | # CHECK-NEXT: ] |
| 85 | 94 | ||
| 86 | .section .text,"ax",@progbits,unique,0 | 95 | .section .text.fn,"ax",@progbits,unique,0 |
| 87 | .globl fn | 96 | .globl fn |
| 88 | .type fn,@function | 97 | .type fn,@function |
| 89 | fn: | 98 | fn: |
| ... | @@ -94,7 +103,7 @@ bar: | ... | @@ -94,7 +103,7 @@ bar: |
| 94 | callq fn@PLT | 103 | callq fn@PLT |
| 95 | nop | 104 | nop |
| 96 | 105 | ||
| 97 | .section .text,"ax",@progbits,unique,1 | 106 | .section .text.fn2,"ax",@progbits,unique,1 |
| 98 | .globl fn2 | 107 | .globl fn2 |
| 99 | .type fn2,@function | 108 | .type fn2,@function |
| 100 | fn2: | 109 | fn2: |
deps/lld/test/ELF/exclude-libs.s+6| ... | @@ -22,6 +22,12 @@ | ... | @@ -22,6 +22,12 @@ |
| 22 | // RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL | 22 | // RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL |
| 23 | // RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s | 23 | // RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s |
| 24 | 24 | ||
| 25 | // RUN: ld.lld -shared --whole-archive %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo,bar,exc.a | ||
| 26 | // RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s | ||
| 27 | |||
| 28 | // RUN: ld.lld -shared --whole-archive %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL | ||
| 29 | // RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s | ||
| 30 | |||
| 25 | // DEFAULT: Name: fn | 31 | // DEFAULT: Name: fn |
| 26 | // EXCLUDE-NOT: Name: fn | 32 | // EXCLUDE-NOT: Name: fn |
| 27 | 33 |
deps/lld/test/ELF/executable-undefined-ignoreall.s created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: ld.lld %t -o %tout --unresolved-symbols=ignore-all -pie | ||
| 4 | # RUN: llvm-readobj -r %tout | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: Relocations [ | ||
| 7 | # CHECK-NEXT: Section ({{.*}}) .rela.plt { | ||
| 8 | # CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT foo 0x0 | ||
| 9 | # CHECK-NEXT: } | ||
| 10 | # CHECK-NEXT: ] | ||
| 11 | |||
| 12 | _start: | ||
| 13 | callq foo@PLT | ||
deps/lld/test/ELF/executable-undefined-protected-ignoreall.s created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: not ld.lld %t -o %tout --unresolved-symbols=ignore-all -pie 2>&1 | FileCheck %s | ||
| 4 | # CHECK: error: undefined symbol: foo | ||
| 5 | |||
| 6 | .protected foo | ||
| 7 | _start: | ||
| 8 | callq foo@PLT | ||
deps/lld/test/ELF/file-access.s created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | # REQUIRES: x86, shell | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 4 | # RUN: ld.lld -r %t.o -o %t1.o | ||
| 5 | # RUN: [ ! -x %t1.o ] | ||
| 6 | # RUN: ld.lld -shared %t.o -o %t2.so | ||
| 7 | # RUN: [ -x %t2.so ] | ||
| 8 | # RUN: ld.lld %t.o -o %t3 | ||
| 9 | # RUN: [ -x %t3 ] | ||
| 10 | |||
| 11 | .global _start | ||
| 12 | _start: | ||
| 13 | nop | ||
deps/lld/test/ELF/fill-trap.s created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 4 | # RUN: ld.lld %t -o %t2 | ||
| 5 | # RUN: llvm-readobj -program-headers %t2 | FileCheck %s | ||
| 6 | # RUN: od -Ax -x -N16 -j0x1ff0 %t2 | FileCheck %s -check-prefix=FILL | ||
| 7 | |||
| 8 | # CHECK: ProgramHeader { | ||
| 9 | # CHECK: Type: PT_LOAD | ||
| 10 | # CHECK: Offset: 0x1000 | ||
| 11 | # CHECK-NEXT: VirtualAddress: | ||
| 12 | # CHECK-NEXT: PhysicalAddress: | ||
| 13 | # CHECK-NEXT: FileSize: 4096 | ||
| 14 | # CHECK-NEXT: MemSize: | ||
| 15 | # CHECK-NEXT: Flags [ | ||
| 16 | # CHECK-NEXT: PF_R | ||
| 17 | # CHECK-NEXT: PF_X | ||
| 18 | # CHECK-NEXT: ] | ||
| 19 | |||
| 20 | ## Check that executable page is filled with traps at its end. | ||
| 21 | # FILL: 001ff0 cccc cccc cccc cccc cccc cccc cccc cccc | ||
| 22 | |||
| 23 | .globl _start | ||
| 24 | _start: | ||
| 25 | nop | ||
deps/lld/test/ELF/filter.s+5-1| ... | @@ -2,10 +2,14 @@ | ... | @@ -2,10 +2,14 @@ |
| 2 | # RUN: ld.lld %t.o -shared -F foo.so -F boo.so -o %t1 | 2 | # RUN: ld.lld %t.o -shared -F foo.so -F boo.so -o %t1 |
| 3 | # RUN: llvm-readobj --dynamic-table %t1 | FileCheck %s | 3 | # RUN: llvm-readobj --dynamic-table %t1 | FileCheck %s |
| 4 | 4 | ||
| 5 | # Test alias. | 5 | # Test alias #1. |
| 6 | # RUN: ld.lld %t.o -shared --filter=foo.so --filter=boo.so -o %t2 | 6 | # RUN: ld.lld %t.o -shared --filter=foo.so --filter=boo.so -o %t2 |
| 7 | # RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s | 7 | # RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s |
| 8 | 8 | ||
| 9 | # Test alias #2. | ||
| 10 | # RUN: ld.lld %t.o -shared --filter foo.so --filter boo.so -o %t3 | ||
| 11 | # RUN: llvm-readobj --dynamic-table %t3 | FileCheck %s | ||
| 12 | |||
| 9 | # CHECK: DynamicSection [ | 13 | # CHECK: DynamicSection [ |
| 10 | # CHECK-NEXT: Tag Type Name/Value | 14 | # CHECK-NEXT: Tag Type Name/Value |
| 11 | # CHECK-NEXT: 0x000000007FFFFFFF FILTER Filter library: [foo.so] | 15 | # CHECK-NEXT: 0x000000007FFFFFFF FILTER Filter library: [foo.so] |
deps/lld/test/ELF/format-binary-non-ascii.s created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t£.o | ||
| 3 | |||
| 4 | # RUN: ld.lld -o %t.elf %t£.o --format=binary %t£.o | ||
| 5 | # RUN: llvm-readobj -symbols %t.elf | FileCheck %s | ||
| 6 | |||
| 7 | # 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_end | ||
| 9 | # CHECK: Name: _binary_{{[a-zA-Z0-9_]+}}test_ELF_Output_format_binary_non_ascii_s_tmp___o_size | ||
| 10 | |||
| 11 | .text | ||
| 12 | .align 4 | ||
| 13 | .globl _start | ||
| 14 | _start: | ||
| 15 | nop | ||
deps/lld/test/ELF/gc-collect-undefined.s created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: ld.lld %t -o %tout --gc-sections -shared | ||
| 4 | # RUN: llvm-nm -D %tout | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK-NOT: qux | ||
| 7 | # CHECK: bar | ||
| 8 | # CHECK-NOT: qux | ||
| 9 | |||
| 10 | 	.global foo,bar,qux | ||
| 11 | 	.local baz | ||
| 12 | |||
| 13 | 	.section .data.foo,"aw",%progbits | ||
| 14 | foo: | ||
| 15 | 	.dc.a	bar | ||
| 16 | |||
| 17 | 	.section .bata.baz,"aw",%progbits | ||
| 18 | baz: | ||
| 19 | 	.dc.a	qux | ||
deps/lld/test/ELF/gc-merge-local-sym.s+1-1| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | // CHECK-NEXT: Link: 0 | 15 | // CHECK-NEXT: Link: 0 |
| 16 | // CHECK-NEXT: Info: 0 | 16 | // CHECK-NEXT: Info: 0 |
| 17 | // CHECK-NEXT: AddressAlignment: 1 | 17 | // CHECK-NEXT: AddressAlignment: 1 |
| 18 | // CHECK-NEXT: EntrySize: 0 | 18 | // CHECK-NEXT: EntrySize: 1 |
| 19 | // CHECK-NEXT: SectionData ( | 19 | // CHECK-NEXT: SectionData ( |
| 20 | // CHECK-NEXT: 0000: 61626300 |abc.| | 20 | // CHECK-NEXT: 0000: 61626300 |abc.| |
| 21 | // CHECK-NEXT: ) | 21 | // CHECK-NEXT: ) |
deps/lld/test/ELF/gc-sections-linker-defined-symbol.s created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 4 | # RUN: ld.lld %t.o -o %t.so --gc-sections -shared | ||
| 5 | # RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: Name: _end@ | ||
| 8 | # CHECK-NEXT: Value: | ||
| 9 | # CHECK-NEXT: Size: | ||
| 10 | # CHECK-NEXT: Binding: Global | ||
| 11 | # CHECK-NEXT: Type: None | ||
| 12 | # CHECK-NEXT: Other: | ||
| 13 | # CHECK-NEXT: Section: .dynamic | ||
| 14 | |||
| 15 | .data | ||
| 16 | .globl g | ||
| 17 | g: | ||
| 18 | .quad _end | ||
deps/lld/test/ELF/gc-sections-merge-addend.s+1-1| ... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
| 16 | // CHECK-NEXT: Link: 0 | 16 | // CHECK-NEXT: Link: 0 |
| 17 | // CHECK-NEXT: Info: 0 | 17 | // CHECK-NEXT: Info: 0 |
| 18 | // CHECK-NEXT: AddressAlignment: 1 | 18 | // CHECK-NEXT: AddressAlignment: 1 |
| 19 | // CHECK-NEXT: EntrySize: 0 | 19 | // CHECK-NEXT: EntrySize: 1 |
| 20 | // CHECK-NEXT: SectionData ( | 20 | // CHECK-NEXT: SectionData ( |
| 21 | // CHECK-NEXT: 0000: 62617200 |bar.| | 21 | // CHECK-NEXT: 0000: 62617200 |bar.| |
| 22 | // CHECK-NEXT: ) | 22 | // CHECK-NEXT: ) |
deps/lld/test/ELF/gc-sections-merge-implicit-addend.s+1-1| ... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
| 16 | // CHECK-NEXT: Link: 0 | 16 | // CHECK-NEXT: Link: 0 |
| 17 | // CHECK-NEXT: Info: 0 | 17 | // CHECK-NEXT: Info: 0 |
| 18 | // CHECK-NEXT: AddressAlignment: 1 | 18 | // CHECK-NEXT: AddressAlignment: 1 |
| 19 | // CHECK-NEXT: EntrySize: 0 | 19 | // CHECK-NEXT: EntrySize: 1 |
| 20 | // CHECK-NEXT: SectionData ( | 20 | // CHECK-NEXT: SectionData ( |
| 21 | // CHECK-NEXT: 0000: 62617200 |bar.| | 21 | // CHECK-NEXT: 0000: 62617200 |bar.| |
| 22 | // CHECK-NEXT: ) | 22 | // CHECK-NEXT: ) |
deps/lld/test/ELF/gc-sections-merge.s+2-2| ... | @@ -18,7 +18,7 @@ | ... | @@ -18,7 +18,7 @@ |
| 18 | // CHECK-NEXT: Link: 0 | 18 | // CHECK-NEXT: Link: 0 |
| 19 | // CHECK-NEXT: Info: 0 | 19 | // CHECK-NEXT: Info: 0 |
| 20 | // CHECK-NEXT: AddressAlignment: 1 | 20 | // CHECK-NEXT: AddressAlignment: 1 |
| 21 | // CHECK-NEXT: EntrySize: 0 | 21 | // CHECK-NEXT: EntrySize: 1 |
| 22 | // CHECK-NEXT: SectionData ( | 22 | // CHECK-NEXT: SectionData ( |
| 23 | // CHECK-NEXT: 0000: 666F6F00 62617200 |foo.bar.| | 23 | // CHECK-NEXT: 0000: 666F6F00 62617200 |foo.bar.| |
| 24 | // CHECK-NEXT: ) | 24 | // CHECK-NEXT: ) |
| ... | @@ -36,7 +36,7 @@ | ... | @@ -36,7 +36,7 @@ |
| 36 | // GC-NEXT: Link: 0 | 36 | // GC-NEXT: Link: 0 |
| 37 | // GC-NEXT: Info: 0 | 37 | // GC-NEXT: Info: 0 |
| 38 | // GC-NEXT: AddressAlignment: 1 | 38 | // GC-NEXT: AddressAlignment: 1 |
| 39 | // GC-NEXT: EntrySize: 0 | 39 | // GC-NEXT: EntrySize: 1 |
| 40 | // GC-NEXT: SectionData ( | 40 | // GC-NEXT: SectionData ( |
| 41 | // GC-NEXT: 0000: 666F6F00 |foo.| | 41 | // GC-NEXT: 0000: 666F6F00 |foo.| |
| 42 | // GC-NEXT: ) | 42 | // GC-NEXT: ) |
deps/lld/test/ELF/gc-sections-print.s+6| ... | @@ -5,6 +5,12 @@ | ... | @@ -5,6 +5,12 @@ |
| 5 | # PRINT: removing unused section from '.text.x' in file | 5 | # PRINT: removing unused section from '.text.x' in file |
| 6 | # PRINT-NEXT: removing unused section from '.text.y' in file | 6 | # PRINT-NEXT: removing unused section from '.text.y' in file |
| 7 | 7 | ||
| 8 | # RUN: ld.lld %t --gc-sections --print-gc-sections --no-print-gc-sections -o %t2 >& %t.log | ||
| 9 | # RUN: echo >> %t.log | ||
| 10 | # RUN: FileCheck -check-prefix=NOPRINT %s < %t.log | ||
| 11 | |||
| 12 | # NOPRINT-NOT: removing | ||
| 13 | |||
| 8 | .globl _start | 14 | .globl _start |
| 9 | .protected a, x, y | 15 | .protected a, x, y |
| 10 | _start: | 16 | _start: |
deps/lld/test/ELF/gc-sections-shared.s+89-4| ... | @@ -1,12 +1,18 @@ | ... | @@ -1,12 +1,18 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/gc-sections-shared.s -o %t3.o | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/gc-sections-shared2.s -o %t4.o | ||
| 3 | # RUN: ld.lld -shared %t2.o -o %t2.so | 5 | # RUN: ld.lld -shared %t2.o -o %t2.so |
| 6 | # RUN: ld.lld -shared %t3.o -o %t3.so | ||
| 7 | # RUN: ld.lld -shared %t4.o -o %t4.so | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 8 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 5 | # RUN: ld.lld --gc-sections --export-dynamic-symbol foo -o %t %t.o --as-needed %t2.so | 9 | # RUN: ld.lld --gc-sections --export-dynamic-symbol foo -o %t %t.o --as-needed %t2.so %t3.so %t4.so |
| 6 | # RUN: llvm-readobj --dynamic-table --dyn-symbols %t | FileCheck %s | 10 | # RUN: llvm-readobj --dynamic-table --dyn-symbols %t | FileCheck %s |
| 7 | 11 | ||
| 8 | # This test the property that we have a needed line for every undefined. | 12 | # This test the property that we have a needed line for every undefined. |
| 9 | # It would also be OK to drop bar2 and the need for the .so | 13 | # It would also be OK to keep bar2 and the need for %t2.so |
| 14 | # At the same time, weak symbols should not cause adding DT_NEEDED; | ||
| 15 | # this case is checked with symbol qux and %t4.so. | ||
| 10 | 16 | ||
| 11 | # CHECK: DynamicSymbols [ | 17 | # CHECK: DynamicSymbols [ |
| 12 | # CHECK-NEXT: Symbol { | 18 | # CHECK-NEXT: Symbol { |
| ... | @@ -19,7 +25,16 @@ | ... | @@ -19,7 +25,16 @@ |
| 19 | # CHECK-NEXT: Section: Undefined (0x0) | 25 | # CHECK-NEXT: Section: Undefined (0x0) |
| 20 | # CHECK-NEXT: } | 26 | # CHECK-NEXT: } |
| 21 | # CHECK-NEXT: Symbol { | 27 | # CHECK-NEXT: Symbol { |
| 22 | # CHECK-NEXT: Name: bar2 | 28 | # CHECK-NEXT: Name: bar |
| 29 | # CHECK-NEXT: Value: | ||
| 30 | # CHECK-NEXT: Size: | ||
| 31 | # CHECK-NEXT: Binding: Global | ||
| 32 | # CHECK-NEXT: Type: | ||
| 33 | # CHECK-NEXT: Other: | ||
| 34 | # CHECK-NEXT: Section: .text | ||
| 35 | # CHECK-NEXT: } | ||
| 36 | # CHECK-NEXT: Symbol { | ||
| 37 | # CHECK-NEXT: Name: baz | ||
| 23 | # CHECK-NEXT: Value: | 38 | # CHECK-NEXT: Value: |
| 24 | # CHECK-NEXT: Size: | 39 | # CHECK-NEXT: Size: |
| 25 | # CHECK-NEXT: Binding: Global | 40 | # CHECK-NEXT: Binding: Global |
| ... | @@ -36,9 +51,76 @@ | ... | @@ -36,9 +51,76 @@ |
| 36 | # CHECK-NEXT: Other: | 51 | # CHECK-NEXT: Other: |
| 37 | # CHECK-NEXT: Section: .text | 52 | # CHECK-NEXT: Section: .text |
| 38 | # CHECK-NEXT: } | 53 | # CHECK-NEXT: } |
| 54 | # CHECK-NEXT: Symbol { | ||
| 55 | # CHECK-NEXT: Name: qux | ||
| 56 | # CHECK-NEXT: Value: | ||
| 57 | # CHECK-NEXT: Size: | ||
| 58 | # CHECK-NEXT: Binding: Weak | ||
| 59 | # CHECK-NEXT: Type: | ||
| 60 | # CHECK-NEXT: Other: | ||
| 61 | # CHECK-NEXT: Section: Undefined | ||
| 62 | # CHECK-NEXT: } | ||
| 39 | # CHECK-NEXT: ] | 63 | # CHECK-NEXT: ] |
| 40 | 64 | ||
| 41 | # CHECK: NEEDED Shared library: [{{.*}}.so] | 65 | # CHECK-NOT: NEEDED |
| 66 | # CHECK: NEEDED Shared library: [{{.*}}3.so] | ||
| 67 | # CHECK-NOT: NEEDED | ||
| 68 | |||
| 69 | # Test with %t.o at the end too. | ||
| 70 | # RUN: ld.lld --gc-sections --export-dynamic-symbol foo -o %t --as-needed %t2.so %t3.so %t4.so %t.o | ||
| 71 | # RUN: llvm-readobj --dynamic-table --dyn-symbols %t | FileCheck --check-prefix=CHECK2 %s | ||
| 72 | |||
| 73 | # CHECK2: DynamicSymbols [ | ||
| 74 | # CHECK2-NEXT: Symbol { | ||
| 75 | # CHECK2-NEXT: Name: | ||
| 76 | # CHECK2-NEXT: Value: | ||
| 77 | # CHECK2-NEXT: Size: | ||
| 78 | # CHECK2-NEXT: Binding: Local | ||
| 79 | # CHECK2-NEXT: Type: | ||
| 80 | # CHECK2-NEXT: Other: | ||
| 81 | # CHECK2-NEXT: Section: Undefined (0x0) | ||
| 82 | # CHECK2-NEXT: } | ||
| 83 | # CHECK2-NEXT: Symbol { | ||
| 84 | # CHECK2-NEXT: Name: bar | ||
| 85 | # CHECK2-NEXT: Value: | ||
| 86 | # CHECK2-NEXT: Size: | ||
| 87 | # CHECK2-NEXT: Binding: Global | ||
| 88 | # CHECK2-NEXT: Type: | ||
| 89 | # CHECK2-NEXT: Other: | ||
| 90 | # CHECK2-NEXT: Section: .text | ||
| 91 | # CHECK2-NEXT: } | ||
| 92 | # CHECK2-NEXT: Symbol { | ||
| 93 | # CHECK2-NEXT: Name: baz | ||
| 94 | # CHECK2-NEXT: Value: | ||
| 95 | # CHECK2-NEXT: Size: | ||
| 96 | # CHECK2-NEXT: Binding: Global | ||
| 97 | # CHECK2-NEXT: Type: | ||
| 98 | # CHECK2-NEXT: Other: | ||
| 99 | # CHECK2-NEXT: Section: Undefined | ||
| 100 | # CHECK2-NEXT: } | ||
| 101 | # CHECK2-NEXT: Symbol { | ||
| 102 | # CHECK2-NEXT: Name: qux | ||
| 103 | # CHECK2-NEXT: Value: | ||
| 104 | # CHECK2-NEXT: Size: | ||
| 105 | # CHECK2-NEXT: Binding: Weak | ||
| 106 | # CHECK2-NEXT: Type: | ||
| 107 | # CHECK2-NEXT: Other: | ||
| 108 | # CHECK2-NEXT: Section: Undefined | ||
| 109 | # CHECK2-NEXT: } | ||
| 110 | # CHECK2-NEXT: Symbol { | ||
| 111 | # CHECK2-NEXT: Name: foo | ||
| 112 | # CHECK2-NEXT: Value: | ||
| 113 | # CHECK2-NEXT: Size: | ||
| 114 | # CHECK2-NEXT: Binding: Global | ||
| 115 | # CHECK2-NEXT: Type: | ||
| 116 | # CHECK2-NEXT: Other: | ||
| 117 | # CHECK2-NEXT: Section: .text | ||
| 118 | # CHECK2-NEXT: } | ||
| 119 | # CHECK2-NEXT: ] | ||
| 120 | |||
| 121 | # CHECK2-NOT: NEEDED | ||
| 122 | # CHECK2: NEEDED Shared library: [{{.*}}3.so] | ||
| 123 | # CHECK2-NOT: NEEDED | ||
| 42 | 124 | ||
| 43 | .section .text.foo, "ax" | 125 | .section .text.foo, "ax" |
| 44 | .globl foo | 126 | .globl foo |
| ... | @@ -52,7 +134,10 @@ ret | ... | @@ -52,7 +134,10 @@ ret |
| 52 | 134 | ||
| 53 | .section .text._start, "ax" | 135 | .section .text._start, "ax" |
| 54 | .globl _start | 136 | .globl _start |
| 137 | .weak qux | ||
| 55 | _start: | 138 | _start: |
| 139 | call baz | ||
| 140 | call qux | ||
| 56 | ret | 141 | ret |
| 57 | 142 | ||
| 58 | .section .text.unused, "ax" | 143 | .section .text.unused, "ax" |
deps/lld/test/ELF/gc-sections-undefined.s created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: ld.lld %t -o %t1 --gc-sections --undefined=foo | ||
| 4 | # RUN: llvm-readobj -t %t1 | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: foo | ||
| 7 | |||
| 8 | .section .foo,"ax" | ||
| 9 | .global foo | ||
| 10 | foo: | ||
deps/lld/test/ELF/gdb-index-base-addr.s created+70| ... | @@ -0,0 +1,70 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | ||
| 3 | # RUN: ld.lld --gdb-index %t1.o -o %t | ||
| 4 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: .gnu_index contents: | ||
| 7 | # CHECK: Address area offset = 0x28, has 2 entries: | ||
| 8 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 | ||
| 9 | # CHECK-NEXT: Low/High address = [0x201003, 0x201006) (Size: 0x3), CU id = 0 | ||
| 10 | |||
| 11 | .text | ||
| 12 | .globl foo | ||
| 13 | .type foo,@function | ||
| 14 | foo: | ||
| 15 | .Lfunc_begin0: | ||
| 16 | nop | ||
| 17 | .Ltmp0: | ||
| 18 | nop | ||
| 19 | nop | ||
| 20 | .Ltmp1: | ||
| 21 | nop | ||
| 22 | nop | ||
| 23 | nop | ||
| 24 | .Ltmp2: | ||
| 25 | |||
| 26 | .section .debug_abbrev,"",@progbits | ||
| 27 | .byte 1 # Abbreviation Code | ||
| 28 | .byte 17 # DW_TAG_compile_unit | ||
| 29 | .byte 0 # DW_CHILDREN_no | ||
| 30 | .byte 37 # DW_AT_producer | ||
| 31 | .byte 14 # DW_FORM_strp | ||
| 32 | .byte 19 # DW_AT_language | ||
| 33 | .byte 5 # DW_FORM_data2 | ||
| 34 | .byte 3 # DW_AT_name | ||
| 35 | .byte 14 # DW_FORM_strp | ||
| 36 | .byte 16 # DW_AT_stmt_list | ||
| 37 | .byte 23 # DW_FORM_sec_offset | ||
| 38 | .byte 27 # DW_AT_comp_dir | ||
| 39 | .byte 14 # DW_FORM_strp | ||
| 40 | .byte 17 # DW_AT_low_pc | ||
| 41 | .byte 1 # DW_FORM_addr | ||
| 42 | .byte 85 # DW_AT_ranges | ||
| 43 | .byte 23 # DW_FORM_sec_offset | ||
| 44 | .byte 0 # EOM(1) | ||
| 45 | .byte 0 # EOM(2) | ||
| 46 | .byte 0 # EOM(3) | ||
| 47 | |||
| 48 | .section .debug_info,"",@progbits | ||
| 49 | .Lcu_begin0: | ||
| 50 | .long 38 # Length of Unit | ||
| 51 | .short 4 # DWARF version number | ||
| 52 | .long .debug_abbrev # Offset Into Abbrev. Section | ||
| 53 | .byte 8 # Address Size (in bytes) | ||
| 54 | .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit | ||
| 55 | .long 0 # DW_AT_producer | ||
| 56 | .short 4 # DW_AT_language | ||
| 57 | .long 0 # DW_AT_name | ||
| 58 | .long 0 # DW_AT_stmt_list | ||
| 59 | .long 0 # DW_AT_comp_dir | ||
| 60 | .quad .Lfunc_begin0 # DW_AT_low_pc | ||
| 61 | .long .Ldebug_ranges0 # DW_AT_ranges | ||
| 62 | |||
| 63 | .section .debug_ranges,"",@progbits | ||
| 64 | .Ldebug_ranges0: | ||
| 65 | .quad .Lfunc_begin0-.Lfunc_begin0 | ||
| 66 | .quad .Ltmp0-.Lfunc_begin0 | ||
| 67 | .quad .Ltmp1-.Lfunc_begin0 | ||
| 68 | .quad .Ltmp2-.Lfunc_begin0 | ||
| 69 | .quad 0 | ||
| 70 | .quad 0 | ||
deps/lld/test/ELF/gdb-index-dup-types.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | # RUN: ld.lld --gdb-index %t.o -o %t | 3 | # RUN: ld.lld --gdb-index %t.o -o %t |
| 4 | # RUN: llvm-dwarfdump -debug-dump=gdb_index %t | FileCheck %s | 4 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s |
| 5 | 5 | ||
| 6 | ## Testcase is based on output produced by gcc version 5.4.1 20160904 | 6 | ## Testcase is based on output produced by gcc version 5.4.1 20160904 |
| 7 | ## it has duplicate entries in .debug_gnu_pubtypes which seems to be | 7 | ## it has duplicate entries in .debug_gnu_pubtypes which seems to be |
deps/lld/test/ELF/gdb-index-empty.s+2-2| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t %s | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t %s |
| 3 | # RUN: ld.lld --gdb-index --gc-sections -o %t2 %t | 3 | # RUN: ld.lld --gdb-index --gc-sections -o %t2 %t |
| 4 | # RUN: llvm-dwarfdump -debug-dump=gdb_index %t2 | FileCheck %s | 4 | # RUN: llvm-dwarfdump -gdb-index %t2 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: Address area offset = 0x28, has 0 entries: | 6 | # CHECK: Address area offset = 0x28, has 0 entries: |
| 7 | 7 | ||
| ... | @@ -74,7 +74,7 @@ _start: | ... | @@ -74,7 +74,7 @@ _start: |
| 74 | .quad .Lfunc_begin0 # DW_AT_low_pc | 74 | .quad .Lfunc_begin0 # DW_AT_low_pc |
| 75 | .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc | 75 | .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc |
| 76 | .byte 1 # DW_AT_frame_base | 76 | .byte 1 # DW_AT_frame_base |
| 77 | .byte 87 | 77 | .byte 87 |
| 78 | .long 0 # DW_AT_name | 78 | .long 0 # DW_AT_name |
| 79 | .byte 1 # DW_AT_decl_file | 79 | .byte 1 # DW_AT_decl_file |
| 80 | .byte 1 # DW_AT_decl_line | 80 | .byte 1 # DW_AT_decl_line |
deps/lld/test/ELF/gdb-index-gc-sections.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t %s | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t %s |
| 3 | # RUN: ld.lld --gdb-index --gc-sections -o %t2 %t | 3 | # RUN: ld.lld --gdb-index --gc-sections -o %t2 %t |
| 4 | # RUN: llvm-dwarfdump -debug-dump=gdb_index %t2 | FileCheck %s | 4 | # RUN: llvm-dwarfdump -gdb-index %t2 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: Address area offset = 0x28, has 1 entries: | 6 | # CHECK: Address area offset = 0x28, has 1 entries: |
| 7 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 | 7 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 |
deps/lld/test/ELF/gdb-index-noranges.s created+49| ... | @@ -0,0 +1,49 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | ||
| 3 | |||
| 4 | ## Input is reduced from following code and invocation: | ||
| 5 | ## clang++ -gsplit-dwarf -c test.ii -o test.s -S | ||
| 6 | ## clang version: 6.0.0 (trunk 318293) | ||
| 7 | ## | ||
| 8 | ## test.ii: | ||
| 9 | ## int a; | ||
| 10 | ## | ||
| 11 | ## Debug information does not contain any address ranges. | ||
| 12 | ## We crashed in that case. Check we don't. | ||
| 13 | # RUN: ld.lld --gdb-index %t1.o -o %t | ||
| 14 | |||
| 15 | .section .debug_str,"MS",@progbits,1 | ||
| 16 | .Lskel_string0: | ||
| 17 | .asciz "t.dwo" | ||
| 18 | .Lskel_string1: | ||
| 19 | .asciz "path" | ||
| 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 | .ascii "\260B" # DW_AT_GNU_dwo_name | ||
| 28 | .byte 14 # DW_FORM_strp | ||
| 29 | .byte 27 # DW_AT_comp_dir | ||
| 30 | .byte 14 # DW_FORM_strp | ||
| 31 | .ascii "\261B" # DW_AT_GNU_dwo_id | ||
| 32 | .byte 7 # DW_FORM_data8 | ||
| 33 | .ascii "\263B" # DW_AT_GNU_addr_base | ||
| 34 | .byte 23 # DW_FORM_sec_offset | ||
| 35 | .byte 0 # EOM(1) | ||
| 36 | .byte 0 # EOM(2) | ||
| 37 | .byte 0 # EOM(3) | ||
| 38 | |||
| 39 | .section .debug_info,"",@progbits | ||
| 40 | .long 32 # Length of Unit | ||
| 41 | .short 4 # DWARF version number | ||
| 42 | .long .debug_abbrev # Offset Into Abbrev. Section | ||
| 43 | .byte 8 # Address Size (in bytes) | ||
| 44 | .byte 1 # Abbrev [1] 0xb:0x19 DW_TAG_compile_unit | ||
| 45 | .long 0 # DW_AT_stmt_list | ||
| 46 | .long .Lskel_string0 # DW_AT_GNU_dwo_name | ||
| 47 | .long .Lskel_string1 # DW_AT_comp_dir | ||
| 48 | .quad -3824446529333676116 # DW_AT_GNU_dwo_id | ||
| 49 | .long 0 # DW_AT_GNU_addr_base | ||
deps/lld/test/ELF/gdb-index-ranges.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | # RUN: ld.lld --gdb-index -e main %t.o -o %t | 3 | # RUN: ld.lld --gdb-index -e main %t.o -o %t |
| 4 | # RUN: llvm-dwarfdump -debug-dump=gdb_index %t | FileCheck %s | 4 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: .gnu_index contents: | 6 | # CHECK: .gnu_index contents: |
| 7 | # CHECK: Address area offset = 0x28, has 2 entries: | 7 | # CHECK: Address area offset = 0x28, has 2 entries: |
deps/lld/test/ELF/gdb-index-tls.s created+91| ... | @@ -0,0 +1,91 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld --gdb-index -shared %t.o -o %t | ||
| 4 | |||
| 5 | # This used to fail trying to compute R_X86_64_DTPOFF64 | ||
| 6 | |||
| 7 | 	.section	.tdata,"awT",@progbits | ||
| 8 | PrettyStackTraceHead: | ||
| 9 | 	.long	42 # 0x2a | ||
| 10 | |||
| 11 | 	.section	.debug_str,"MS",@progbits,1 | ||
| 12 | 	.asciz	"" | ||
| 13 | |||
| 14 | 	.section	.debug_abbrev,"",@progbits | ||
| 15 | 	.byte	1 # Abbreviation Code | ||
| 16 | 	.byte	17 # DW_TAG_compile_unit | ||
| 17 | 	.byte	1 # DW_CHILDREN_yes | ||
| 18 | 	.byte	37 # DW_AT_producer | ||
| 19 | 	.byte	14 # DW_FORM_strp | ||
| 20 | 	.byte	19 # DW_AT_language | ||
| 21 | 	.byte	5 # DW_FORM_data2 | ||
| 22 | 	.byte	3 # DW_AT_name | ||
| 23 | 	.byte	14 # DW_FORM_strp | ||
| 24 | 	.byte	16 # DW_AT_stmt_list | ||
| 25 | 	.byte	23 # DW_FORM_sec_offset | ||
| 26 | 	.byte	27 # DW_AT_comp_dir | ||
| 27 | 	.byte	14 # DW_FORM_strp | ||
| 28 | 	.ascii	"\264B" # DW_AT_GNU_pubnames | ||
| 29 | 	.byte	25 # DW_FORM_flag_present | ||
| 30 | 	.byte	0 # EOM(1) | ||
| 31 | 	.byte	0 # EOM(2) | ||
| 32 | 	.byte	2 # Abbreviation Code | ||
| 33 | 	.byte	52 # DW_TAG_variable | ||
| 34 | 	.byte	0 # DW_CHILDREN_no | ||
| 35 | 	.byte	3 # DW_AT_name | ||
| 36 | 	.byte	14 # DW_FORM_strp | ||
| 37 | 	.byte	73 # DW_AT_type | ||
| 38 | 	.byte	19 # DW_FORM_ref4 | ||
| 39 | 	.byte	63 # DW_AT_external | ||
| 40 | 	.byte	25 # DW_FORM_flag_present | ||
| 41 | 	.byte	58 # DW_AT_decl_file | ||
| 42 | 	.byte	11 # DW_FORM_data1 | ||
| 43 | 	.byte	59 # DW_AT_decl_line | ||
| 44 | 	.byte	11 # DW_FORM_data1 | ||
| 45 | 	.byte	2 # DW_AT_location | ||
| 46 | 	.byte	24 # DW_FORM_exprloc | ||
| 47 | 	.byte	0 # EOM(1) | ||
| 48 | 	.byte	0 # EOM(2) | ||
| 49 | 	.byte	3 # Abbreviation Code | ||
| 50 | 	.byte	36 # DW_TAG_base_type | ||
| 51 | 	.byte	0 # DW_CHILDREN_no | ||
| 52 | 	.byte	3 # DW_AT_name | ||
| 53 | 	.byte	14 # DW_FORM_strp | ||
| 54 | 	.byte	62 # DW_AT_encoding | ||
| 55 | 	.byte	11 # DW_FORM_data1 | ||
| 56 | 	.byte	11 # DW_AT_byte_size | ||
| 57 | 	.byte	11 # DW_FORM_data1 | ||
| 58 | 	.byte	0 # EOM(1) | ||
| 59 | 	.byte	0 # EOM(2) | ||
| 60 | 	.byte	0 # EOM(3) | ||
| 61 | |||
| 62 | 	.section	.debug_info,"",@progbits | ||
| 63 | .Lcu_begin0: | ||
| 64 | 	.long	56 # Length of Unit | ||
| 65 | 	.short	4 # DWARF version number | ||
| 66 | 	.long	.debug_abbrev # Offset Into Abbrev. Section | ||
| 67 | 	.byte	8 # Address Size (in bytes) | ||
| 68 | 	.byte	1 # Abbrev [1] 0xb:0x31 DW_TAG_compile_unit | ||
| 69 | 	.long	.debug_str # DW_AT_producer | ||
| 70 | 	.short	4 # DW_AT_language | ||
| 71 | 	.long	.debug_str # DW_AT_name | ||
| 72 | 	.long	.debug_line # DW_AT_stmt_list | ||
| 73 | 	.long	.debug_str # DW_AT_comp_dir | ||
| 74 | # DW_AT_GNU_pubnames | ||
| 75 | 	.byte	2 # Abbrev [2] 0x1e:0x16 DW_TAG_variable | ||
| 76 | 	.long	.debug_str # DW_AT_name | ||
| 77 | 	.long	52 # DW_AT_type | ||
| 78 | # DW_AT_external | ||
| 79 | 	.byte	1 # DW_AT_decl_file | ||
| 80 | 	.byte	1 # DW_AT_decl_line | ||
| 81 | 	.byte	10 # DW_AT_location | ||
| 82 | 	.byte	14 | ||
| 83 | 	.quad	PrettyStackTraceHead@DTPOFF | ||
| 84 | 	.byte	224 | ||
| 85 | 	.byte	3 # Abbrev [3] 0x34:0x7 DW_TAG_base_type | ||
| 86 | 	.long	.debug_str # DW_AT_name | ||
| 87 | 	.byte	5 # DW_AT_encoding | ||
| 88 | 	.byte	4 # DW_AT_byte_size | ||
| 89 | 	.byte	0 # End Of Children Mark | ||
| 90 | |||
| 91 | 	.section	.debug_line,"",@progbits | ||
deps/lld/test/ELF/gdb-index.s+17-13| ... | @@ -1,12 +1,12 @@ | ... | @@ -1,12 +1,12 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/gdb-index.s -o %t2.o | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/gdb-index.s -o %t2.o |
| 4 | # RUN: ld.lld --gdb-index -e main %t1.o %t2.o -o %t | 4 | # RUN: ld.lld --gdb-index %t1.o %t2.o -o %t |
| 5 | # RUN: llvm-dwarfdump -debug-dump=gdb_index %t | FileCheck %s | 5 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s |
| 6 | # RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM | 6 | # RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM |
| 7 | 7 | ||
| 8 | # DISASM: Disassembly of section .text: | 8 | # DISASM: Disassembly of section .text: |
| 9 | # DISASM: main: | 9 | # DISASM: entrypoint: |
| 10 | # DISASM-CHECK: 201000: 90 nop | 10 | # DISASM-CHECK: 201000: 90 nop |
| 11 | # DISASM-CHECK: 201001: cc int3 | 11 | # DISASM-CHECK: 201001: cc int3 |
| 12 | # DISASM-CHECK: 201002: cc int3 | 12 | # DISASM-CHECK: 201002: cc int3 |
| ... | @@ -24,25 +24,29 @@ | ... | @@ -24,25 +24,29 @@ |
| 24 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 | 24 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 |
| 25 | # CHECK-NEXT: Low/High address = [0x201004, 0x201006) (Size: 0x2), CU id = 1 | 25 | # CHECK-NEXT: Low/High address = [0x201004, 0x201006) (Size: 0x2), CU id = 1 |
| 26 | # CHECK: Symbol table offset = 0x60, size = 1024, filled slots: | 26 | # CHECK: Symbol table offset = 0x60, size = 1024, filled slots: |
| 27 | # CHECK-NEXT: 489: Name offset = 0x1d, CU vector offset = 0x0 | 27 | # CHECK-NEXT: 754: Name offset = 0x27, CU vector offset = 0x8 |
| 28 | # CHECK-NEXT: String name: main, CU vector index: 0 | 28 | # CHECK-NEXT:	 String name: int, CU vector index: 1 |
| 29 | # CHECK-NEXT: 754: Name offset = 0x22, CU vector offset = 0x8 | 29 | # CHECK-NEXT: 822: Name offset = 0x1c, CU vector offset = 0x0 |
| 30 | # CHECK-NEXT: String name: int, CU vector index: 1 | 30 | # CHECK-NEXT:	 String name: entrypoint, CU vector index: 0 |
| 31 | # CHECK-NEXT: 956: Name offset = 0x26, CU vector offset = 0x14 | 31 | # CHECK-NEXT: 956: Name offset = 0x2b, CU vector offset = 0x14 |
| 32 | # CHECK-NEXT: String name: main2, CU vector index: 2 | 32 | # CHECK-NEXT: String name: main2, CU vector index: 2 |
| 33 | # CHECK: Constant pool offset = 0x2060, has 3 CU vectors: | 33 | # CHECK: Constant pool offset = 0x2060, has 3 CU vectors: |
| 34 | # CHECK-NEXT: 0(0x0): 0x30000000 | 34 | # CHECK-NEXT: 0(0x0): 0x30000000 |
| 35 | # CHECK-NEXT: 1(0x8): 0x90000000 0x90000001 | 35 | # CHECK-NEXT: 1(0x8): 0x90000000 0x90000001 |
| 36 | # CHECK-NEXT: 2(0x14): 0x30000001 | 36 | # CHECK-NEXT: 2(0x14): 0x30000001 |
| 37 | 37 | ||
| 38 | # RUN: ld.lld --gdb-index --no-gdb-index %t1.o %t2.o -o %t2 | ||
| 39 | # RUN: llvm-readobj -sections %t2 | FileCheck -check-prefix=NOGDB %s | ||
| 40 | # NOGDB-NOT: Name: .gdb_index | ||
| 41 | |||
| 38 | ## The following section contents are created by this using gcc 7.1.0: | 42 | ## The following section contents are created by this using gcc 7.1.0: |
| 39 | ## echo 'int main() { return 0; }' | gcc -gsplit-dwarf -xc++ -S -o- - | 43 | ## echo 'int entrypoint() { return 0; }' | gcc -gsplit-dwarf -xc++ -S -o- - |
| 40 | 44 | ||
| 41 | .text | 45 | .text |
| 42 | .Ltext0: | 46 | .Ltext0: |
| 43 | .globl main | 47 | .globl entrypoint |
| 44 | .type main, @function | 48 | .type entrypoint, @function |
| 45 | main: | 49 | entrypoint: |
| 46 | nop | 50 | nop |
| 47 | .Letext0: | 51 | .Letext0: |
| 48 | 52 | ||
| ... | @@ -98,7 +102,7 @@ main: | ... | @@ -98,7 +102,7 @@ main: |
| 98 | .long 0x33 | 102 | .long 0x33 |
| 99 | .long 0x18 | 103 | .long 0x18 |
| 100 | .byte 0x30 | 104 | .byte 0x30 |
| 101 | .string "main" | 105 | .string "entrypoint" |
| 102 | .long 0 | 106 | .long 0 |
| 103 | 107 | ||
| 104 | .section .debug_gnu_pubtypes,"",@progbits | 108 | .section .debug_gnu_pubtypes,"",@progbits |
deps/lld/test/ELF/global-offset-table-position-aarch64.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t |
| 2 | // RUN: ld.lld -shared %t -o %t2 | 2 | // RUN: ld.lld --hash-style=sysv -shared %t -o %t2 |
| 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s | 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s |
| 4 | // REQUIRES: aarch64 | 4 | // REQUIRES: aarch64 |
| 5 | .globl a | 5 | .globl a |
deps/lld/test/ELF/global-offset-table-position-arm.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t |
| 2 | // RUN: ld.lld -shared %t -o %t2 | 2 | // RUN: ld.lld --hash-style=sysv -shared %t -o %t2 |
| 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s | 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s |
| 4 | // REQUIRES: arm | 4 | // REQUIRES: arm |
| 5 | 5 |
deps/lld/test/ELF/global-offset-table-position-i386.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t |
| 2 | // RUN: ld.lld -shared %t -o %t2 | 2 | // RUN: ld.lld --hash-style=sysv -shared %t -o %t2 |
| 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s | 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s |
| 4 | // REQUIRES: x86 | 4 | // REQUIRES: x86 |
| 5 | 5 |
deps/lld/test/ELF/global-offset-table-position.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t |
| 2 | // RUN: ld.lld -shared %t -o %t2 | 2 | // RUN: ld.lld --hash-style=sysv -shared %t -o %t2 |
| 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s | 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s |
| 4 | // REQUIRES: x86 | 4 | // REQUIRES: x86 |
| 5 | 5 |
deps/lld/test/ELF/global_offset_table_shared.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t |
| 2 | // RUN: ld.lld -shared %t -o %t2 | 2 | // RUN: ld.lld --hash-style=sysv -shared %t -o %t2 |
| 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s | 3 | // RUN: llvm-readobj -t %t2 | FileCheck %s |
| 4 | .long _GLOBAL_OFFSET_TABLE_ - . | 4 | .long _GLOBAL_OFFSET_TABLE_ - . |
| 5 | 5 |
deps/lld/test/ELF/gnu-hash-table-copy.s created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: echo ".global foo; .type foo, @object; .size foo, 4; foo:; .long 0" > %t.s | ||
| 4 | # RUN: echo ".global bar; .type bar, @object; .size bar, 4; bar:; .long 0" >> %t.s | ||
| 5 | # RUN: echo ".global zed; .type zed, @function; zed:" >> %t.s | ||
| 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t.s -o %t1.o | ||
| 7 | # RUN: ld.lld %t1.o -o %t1.so -shared | ||
| 8 | |||
| 9 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o | ||
| 10 | # RUN: ld.lld --hash-style=gnu %t2.o %t1.so -o %t2 | ||
| 11 | |||
| 12 | # RUN: llvm-readelf --symbols --gnu-hash-table %t2 | FileCheck %s | ||
| 13 | |||
| 14 | # CHECK: Symbol table '.dynsym' contains 4 entries: | ||
| 15 | # CHECK-NEXT: Num: Value Size Type Bind Vis Ndx Name | ||
| 16 | # CHECK-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND @ | ||
| 17 | # CHECK-NEXT: 1: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND foo@ | ||
| 18 | # CHECK-DAG: : {{.*}} 4 OBJECT GLOBAL DEFAULT {{.*}} bar@ | ||
| 19 | # CHECK-DAG: : {{.*}} 0 FUNC GLOBAL DEFAULT UND zed@ | ||
| 20 | |||
| 21 | # CHECK: First Hashed Symbol Index: 2 | ||
| 22 | |||
| 23 | .global _start | ||
| 24 | _start: | ||
| 25 | |||
| 26 | .quad bar | ||
| 27 | .quad zed | ||
| 28 | |||
| 29 | .data | ||
| 30 | .quad foo | ||
deps/lld/test/ELF/gnu-hash-table-many.s created+55| ... | @@ -0,0 +1,55 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 4 | # RUN: ld.lld -hash-style=gnu %t.o -o %t.so -shared | ||
| 5 | # RUN: llvm-readelf --gnu-hash-table %t.so | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: Num Buckets: 4 | ||
| 8 | |||
| 9 | .global sym1 | ||
| 10 | sym1: | ||
| 11 | |||
| 12 | .global sym2 | ||
| 13 | sym2: | ||
| 14 | |||
| 15 | .global sym3 | ||
| 16 | sym3: | ||
| 17 | |||
| 18 | .global sym4 | ||
| 19 | sym4: | ||
| 20 | |||
| 21 | .global sym5 | ||
| 22 | sym5: | ||
| 23 | |||
| 24 | .global sym6 | ||
| 25 | sym6: | ||
| 26 | |||
| 27 | .global sym7 | ||
| 28 | sym7: | ||
| 29 | |||
| 30 | .global sym8 | ||
| 31 | sym8: | ||
| 32 | |||
| 33 | .global sym9 | ||
| 34 | sym9: | ||
| 35 | |||
| 36 | .global sym10 | ||
| 37 | sym10: | ||
| 38 | |||
| 39 | .global sym11 | ||
| 40 | sym11: | ||
| 41 | |||
| 42 | .global sym12 | ||
| 43 | sym12: | ||
| 44 | |||
| 45 | .global sym13 | ||
| 46 | sym13: | ||
| 47 | |||
| 48 | .global sym14 | ||
| 49 | sym14: | ||
| 50 | |||
| 51 | .global sym15 | ||
| 52 | sym15: | ||
| 53 | |||
| 54 | .global sym16 | ||
| 55 | sym16: | ||
deps/lld/test/ELF/gnu-hash-table-rwsegment.s created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # 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.o | ||
| 5 | # RUN: llvm-readobj -gnu-hash-table %t.so | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: GnuHashTable { | ||
| 8 | # CHECK-NEXT: Num Buckets: 1 | ||
| 9 | # CHECK-NEXT: First Hashed Symbol Index: 1 | ||
| 10 | # CHECK-NEXT: Num Mask Words: 1 | ||
| 11 | # CHECK-NEXT: Shift Count: 6 | ||
| 12 | # CHECK-NEXT: Bloom Filter: [0x400000000004204] | ||
| 13 | # CHECK-NEXT: Buckets: [1] | ||
| 14 | # CHECK-NEXT: Values: [0xB8860BA, 0xB887389] | ||
| 15 | # CHECK-NEXT: } | ||
| 16 | |||
| 17 | .globl foo, bar | ||
| 18 | foo: | ||
| 19 | bar: | ||
| 20 | ret | ||
deps/lld/test/ELF/gnu-hash-table.s+66-13| ... | @@ -1,15 +1,34 @@ | ... | @@ -1,15 +1,34 @@ |
| 1 | # REQUIRES: x86,ppc | 1 | # REQUIRES: x86,ppc |
| 2 | 2 | ||
| 3 | # RUN: echo ".globl foo" > %te.s | 3 | # RUN: echo ".globl foo; .data; .dc.a foo" > %te.s |
| 4 | # RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %te.s -o %te-i386.o | 4 | # RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %te.s -o %te-i386.o |
| 5 | # RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t-i386.o | 5 | # RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t-i386.o |
| 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t-x86_64.o | 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t-x86_64.o |
| 7 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-pc-linux %s -o %t-ppc64.o | 7 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-pc-linux %s -o %t-ppc64.o |
| 8 | 8 | ||
| 9 | # RUN: echo ".global zed; zed:" > %t2.s | ||
| 10 | # RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %t2.s -o %t2-i386.o | ||
| 11 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2-x86_64.o | ||
| 12 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-pc-linux %t2.s -o %t2-ppc64.o | ||
| 13 | |||
| 14 | # RUN: rm -f %t2-i386.a %t2-x86_64.a %t2-ppc64.a | ||
| 15 | # RUN: llvm-ar rc %t2-i386.a %t2-i386.o | ||
| 16 | # RUN: llvm-ar rc %t2-x86_64.a %t2-x86_64.o | ||
| 17 | # RUN: llvm-ar rc %t2-ppc64.a %t2-ppc64.o | ||
| 18 | |||
| 19 | # RUN: echo ".global xyz; xyz:" > %t3.s | ||
| 20 | # RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %t3.s -o %t3-i386.o | ||
| 21 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t3.s -o %t3-x86_64.o | ||
| 22 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-pc-linux %t3.s -o %t3-ppc64.o | ||
| 23 | |||
| 24 | # RUN: ld.lld -shared %t3-i386.o -o %t3-i386.so | ||
| 25 | # RUN: ld.lld -shared %t3-x86_64.o -o %t3-x86_64.so | ||
| 26 | # RUN: ld.lld -shared %t3-ppc64.o -o %t3-ppc64.so | ||
| 27 | |||
| 9 | # RUN: ld.lld -shared --hash-style=gnu -o %te-i386.so %te-i386.o | 28 | # RUN: ld.lld -shared --hash-style=gnu -o %te-i386.so %te-i386.o |
| 10 | # RUN: ld.lld -shared -hash-style=gnu -o %t-i386.so %t-i386.o | 29 | # RUN: ld.lld -shared -hash-style=gnu -o %t-i386.so %t-i386.o %t2-i386.a %t3-i386.so |
| 11 | # RUN: ld.lld -shared -hash-style=gnu -o %t-x86_64.so %t-x86_64.o | 30 | # RUN: ld.lld -shared -hash-style=gnu -o %t-x86_64.so %t-x86_64.o %t2-x86_64.a %t3-x86_64.so |
| 12 | # RUN: ld.lld -shared --hash-style both -o %t-ppc64.so %t-ppc64.o | 31 | # RUN: ld.lld -shared --hash-style both -o %t-ppc64.so %t-ppc64.o %t2-ppc64.a %t3-ppc64.so |
| 13 | 32 | ||
| 14 | # RUN: llvm-readobj -dyn-symbols -gnu-hash-table %te-i386.so \ | 33 | # RUN: llvm-readobj -dyn-symbols -gnu-hash-table %te-i386.so \ |
| 15 | # RUN: | FileCheck %s -check-prefix=EMPTY | 34 | # RUN: | FileCheck %s -check-prefix=EMPTY |
| ... | @@ -70,6 +89,16 @@ | ... | @@ -70,6 +89,16 @@ |
| 70 | # I386: Section: Undefined | 89 | # I386: Section: Undefined |
| 71 | # I386: } | 90 | # I386: } |
| 72 | # I386: Symbol { | 91 | # I386: Symbol { |
| 92 | # I386: Name: xyz@ | ||
| 93 | # I386: Binding: Global | ||
| 94 | # I386: Section: Undefined | ||
| 95 | # I386: } | ||
| 96 | # I386: Symbol { | ||
| 97 | # I386: Name: zed@ | ||
| 98 | # I386: Binding: Weak | ||
| 99 | # I386: Section: Undefined | ||
| 100 | # I386: } | ||
| 101 | # I386: Symbol { | ||
| 73 | # I386: Name: bar@ | 102 | # I386: Name: bar@ |
| 74 | # I386: Binding: Global | 103 | # I386: Binding: Global |
| 75 | # I386: Section: .text | 104 | # I386: Section: .text |
| ... | @@ -82,11 +111,11 @@ | ... | @@ -82,11 +111,11 @@ |
| 82 | # I386: ] | 111 | # I386: ] |
| 83 | # I386: GnuHashTable { | 112 | # I386: GnuHashTable { |
| 84 | # I386-NEXT: Num Buckets: 1 | 113 | # I386-NEXT: Num Buckets: 1 |
| 85 | # I386-NEXT: First Hashed Symbol Index: 2 | 114 | # I386-NEXT: First Hashed Symbol Index: 4 |
| 86 | # I386-NEXT: Num Mask Words: 1 | 115 | # I386-NEXT: Num Mask Words: 1 |
| 87 | # I386-NEXT: Shift Count: 5 | 116 | # I386-NEXT: Shift Count: 5 |
| 88 | # I386-NEXT: Bloom Filter: [0x14000220] | 117 | # I386-NEXT: Bloom Filter: [0x14000220] |
| 89 | # I386-NEXT: Buckets: [2] | 118 | # I386-NEXT: Buckets: [4] |
| 90 | # I386-NEXT: Values: [0xB8860BA, 0xB887389] | 119 | # I386-NEXT: Values: [0xB8860BA, 0xB887389] |
| 91 | # I386-NEXT: } | 120 | # I386-NEXT: } |
| 92 | 121 | ||
| ... | @@ -120,6 +149,16 @@ | ... | @@ -120,6 +149,16 @@ |
| 120 | # X86_64: Section: Undefined | 149 | # X86_64: Section: Undefined |
| 121 | # X86_64: } | 150 | # X86_64: } |
| 122 | # X86_64: Symbol { | 151 | # X86_64: Symbol { |
| 152 | # X86_64: Name: xyz@ | ||
| 153 | # X86_64: Binding: Global | ||
| 154 | # X86_64: Section: Undefined | ||
| 155 | # X86_64: } | ||
| 156 | # X86_64: Symbol { | ||
| 157 | # X86_64: Name: zed@ | ||
| 158 | # X86_64: Binding: Weak | ||
| 159 | # X86_64: Section: Undefined | ||
| 160 | # X86_64: } | ||
| 161 | # X86_64: Symbol { | ||
| 123 | # X86_64: Name: bar@ | 162 | # X86_64: Name: bar@ |
| 124 | # X86_64: Binding: Global | 163 | # X86_64: Binding: Global |
| 125 | # X86_64: Section: .text | 164 | # X86_64: Section: .text |
| ... | @@ -132,11 +171,11 @@ | ... | @@ -132,11 +171,11 @@ |
| 132 | # X86_64: ] | 171 | # X86_64: ] |
| 133 | # X86_64: GnuHashTable { | 172 | # X86_64: GnuHashTable { |
| 134 | # X86_64-NEXT: Num Buckets: 1 | 173 | # X86_64-NEXT: Num Buckets: 1 |
| 135 | # X86_64-NEXT: First Hashed Symbol Index: 2 | 174 | # X86_64-NEXT: First Hashed Symbol Index: 4 |
| 136 | # X86_64-NEXT: Num Mask Words: 1 | 175 | # X86_64-NEXT: Num Mask Words: 1 |
| 137 | # X86_64-NEXT: Shift Count: 6 | 176 | # X86_64-NEXT: Shift Count: 6 |
| 138 | # X86_64-NEXT: Bloom Filter: [0x400000000004204] | 177 | # X86_64-NEXT: Bloom Filter: [0x400000000004204] |
| 139 | # X86_64-NEXT: Buckets: [2] | 178 | # X86_64-NEXT: Buckets: [4] |
| 140 | # X86_64-NEXT: Values: [0xB8860BA, 0xB887389] | 179 | # X86_64-NEXT: Values: [0xB8860BA, 0xB887389] |
| 141 | # X86_64-NEXT: } | 180 | # X86_64-NEXT: } |
| 142 | 181 | ||
| ... | @@ -149,10 +188,10 @@ | ... | @@ -149,10 +188,10 @@ |
| 149 | # PPC64-NEXT: Flags [ | 188 | # PPC64-NEXT: Flags [ |
| 150 | # PPC64-NEXT: SHF_ALLOC | 189 | # PPC64-NEXT: SHF_ALLOC |
| 151 | # PPC64-NEXT: ] | 190 | # PPC64-NEXT: ] |
| 152 | # PPC64-NEXT: Address: 0x228 | 191 | # PPC64-NEXT: Address: |
| 153 | # PPC64-NEXT: Offset: 0x228 | 192 | # PPC64-NEXT: Offset: |
| 154 | # PPC64-NEXT: Size: 36 | 193 | # PPC64-NEXT: Size: 36 |
| 155 | # PPC64-NEXT: Link: 1 | 194 | # PPC64-NEXT: Link: |
| 156 | # PPC64-NEXT: Info: 0 | 195 | # PPC64-NEXT: Info: 0 |
| 157 | # PPC64-NEXT: AddressAlignment: 8 | 196 | # PPC64-NEXT: AddressAlignment: 8 |
| 158 | # PPC64-NEXT: EntrySize: 0 | 197 | # PPC64-NEXT: EntrySize: 0 |
| ... | @@ -170,6 +209,16 @@ | ... | @@ -170,6 +209,16 @@ |
| 170 | # PPC64: Section: Undefined | 209 | # PPC64: Section: Undefined |
| 171 | # PPC64: } | 210 | # PPC64: } |
| 172 | # PPC64: Symbol { | 211 | # PPC64: Symbol { |
| 212 | # PPC64: Name: xyz@ | ||
| 213 | # PPC64: Binding: Global | ||
| 214 | # PPC64: Section: Undefined | ||
| 215 | # PPC64: } | ||
| 216 | # PPC64: Symbol { | ||
| 217 | # PPC64: Name: zed@ | ||
| 218 | # PPC64: Binding: Weak | ||
| 219 | # PPC64: Section: Undefined | ||
| 220 | # PPC64: } | ||
| 221 | # PPC64: Symbol { | ||
| 173 | # PPC64: Name: bar@ | 222 | # PPC64: Name: bar@ |
| 174 | # PPC64: Binding: Global | 223 | # PPC64: Binding: Global |
| 175 | # PPC64: Section: .text | 224 | # PPC64: Section: .text |
| ... | @@ -182,14 +231,18 @@ | ... | @@ -182,14 +231,18 @@ |
| 182 | # PPC64: ] | 231 | # PPC64: ] |
| 183 | # PPC64: GnuHashTable { | 232 | # PPC64: GnuHashTable { |
| 184 | # PPC64-NEXT: Num Buckets: 1 | 233 | # PPC64-NEXT: Num Buckets: 1 |
| 185 | # PPC64-NEXT: First Hashed Symbol Index: 2 | 234 | # PPC64-NEXT: First Hashed Symbol Index: 4 |
| 186 | # PPC64-NEXT: Num Mask Words: 1 | 235 | # PPC64-NEXT: Num Mask Words: 1 |
| 187 | # PPC64-NEXT: Shift Count: 6 | 236 | # PPC64-NEXT: Shift Count: 6 |
| 188 | # PPC64-NEXT: Bloom Filter: [0x400000000004204] | 237 | # PPC64-NEXT: Bloom Filter: [0x400000000004204] |
| 189 | # PPC64-NEXT: Buckets: [2] | 238 | # PPC64-NEXT: Buckets: [4] |
| 190 | # PPC64-NEXT: Values: [0xB8860BA, 0xB887389] | 239 | # PPC64-NEXT: Values: [0xB8860BA, 0xB887389] |
| 191 | # PPC64-NEXT: } | 240 | # PPC64-NEXT: } |
| 192 | 241 | ||
| 193 | .globl foo,bar,baz | 242 | .globl foo,bar,baz |
| 194 | foo: | 243 | foo: |
| 195 | bar: | 244 | bar: |
| 245 | .weak zed | ||
| 246 | .global xyz | ||
| 247 | .data | ||
| 248 | .dc.a baz |
deps/lld/test/ELF/gnu-ifunc-dynsym.s created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 2 | // RUN: ld.lld -static -export-dynamic %t.o -o %tout | ||
| 3 | // RUN: llvm-nm -U %tout | FileCheck %s | ||
| 4 | // REQUIRES: x86 | ||
| 5 | |||
| 6 | // CHECK: __rela_iplt_end | ||
| 7 | // CHECK: __rela_iplt_start | ||
| 8 | |||
| 9 | .text | ||
| 10 | .type foo STT_GNU_IFUNC | ||
| 11 | .globl foo | ||
| 12 | foo: | ||
| 13 | ret | ||
| 14 | |||
| 15 | .globl _start | ||
| 16 | _start: | ||
| 17 | call foo | ||
| 18 | movl $__rela_iplt_start,%edx | ||
| 19 | movl $__rela_iplt_end,%edx | ||
deps/lld/test/ELF/gnu-ifunc-dyntags.s created+41| ... | @@ -0,0 +1,41 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld -pie %t.o -o %tout | ||
| 4 | # RUN: llvm-objdump -section-headers %tout | FileCheck %s | ||
| 5 | # RUN: llvm-readobj -dynamic-table -r %tout | FileCheck %s --check-prefix=TAGS | ||
| 6 | |||
| 7 | ## Check we produce DT_PLTREL/DT_JMPREL/DT_PLTGOT and DT_PLTRELSZ tags | ||
| 8 | ## when there are no other relocations except R_*_IRELATIVE. | ||
| 9 | |||
| 10 | # CHECK: Name Size Address | ||
| 11 | # CHECK: .rela.plt 00000030 0000000000000210 | ||
| 12 | # CHECK: .got.plt 00000010 0000000000002000 | ||
| 13 | |||
| 14 | # TAGS: Relocations [ | ||
| 15 | # TAGS-NEXT: Section {{.*}} .rela.plt { | ||
| 16 | # TAGS-NEXT: R_X86_64_IRELATIVE | ||
| 17 | # TAGS-NEXT: R_X86_64_IRELATIVE | ||
| 18 | # TAGS-NEXT: } | ||
| 19 | # TAGS-NEXT: ] | ||
| 20 | |||
| 21 | # TAGS: Tag Type Name/Value | ||
| 22 | # TAGS: 0x0000000000000017 JMPREL 0x210 | ||
| 23 | # TAGS: 0x0000000000000002 PLTRELSZ 48 | ||
| 24 | # TAGS: 0x0000000000000003 PLTGOT 0x2000 | ||
| 25 | # TAGS: 0x0000000000000014 PLTREL RELA | ||
| 26 | |||
| 27 | .text | ||
| 28 | .type foo STT_GNU_IFUNC | ||
| 29 | .globl foo | ||
| 30 | foo: | ||
| 31 | ret | ||
| 32 | |||
| 33 | .type bar STT_GNU_IFUNC | ||
| 34 | .globl bar | ||
| 35 | bar: | ||
| 36 | ret | ||
| 37 | |||
| 38 | .globl _start | ||
| 39 | _start: | ||
| 40 | call foo | ||
| 41 | call bar | ||
deps/lld/test/ELF/gnu-ifunc-gotpcrel.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/gnu-ifunc-gotpcrel.s -o %t2.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/gnu-ifunc-gotpcrel.s -o %t2.o |
| 3 | # RUN: ld.lld -shared %t2.o -o %t2.so | 3 | # RUN: ld.lld -shared %t2.o -o %t2.so |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 5 | # RUN: ld.lld %t.o %t2.so -o %t | 5 | # RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t |
| 6 | # RUN: llvm-readobj -dyn-relocations %t | FileCheck %s | 6 | # RUN: llvm-readobj -dyn-relocations %t | FileCheck %s |
| 7 | 7 | ||
| 8 | # CHECK: Dynamic Relocations { | 8 | # CHECK: Dynamic Relocations { |
deps/lld/test/ELF/gnu-ifunc-i386.s+3-3| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | // CHECK-NEXT: Address: [[RELA:.*]] | 15 | // CHECK-NEXT: Address: [[RELA:.*]] |
| 16 | // CHECK-NEXT: Offset: 0xD4 | 16 | // CHECK-NEXT: Offset: 0xD4 |
| 17 | // CHECK-NEXT: Size: 16 | 17 | // CHECK-NEXT: Size: 16 |
| 18 | // CHECK-NEXT: Link: 6 | 18 | // CHECK-NEXT: Link: 0 |
| 19 | // CHECK-NEXT: Info: 0 | 19 | // CHECK-NEXT: Info: 0 |
| 20 | // CHECK-NEXT: AddressAlignment: 4 | 20 | // CHECK-NEXT: AddressAlignment: 4 |
| 21 | // CHECK-NEXT: EntrySize: 8 | 21 | // CHECK-NEXT: EntrySize: 8 |
| ... | @@ -102,10 +102,10 @@ | ... | @@ -102,10 +102,10 @@ |
| 102 | // DISASM-NEXT: .plt: | 102 | // DISASM-NEXT: .plt: |
| 103 | // DISASM-NEXT: 11020: ff 25 00 20 01 00 jmpl *73728 | 103 | // DISASM-NEXT: 11020: ff 25 00 20 01 00 jmpl *73728 |
| 104 | // DISASM-NEXT: 11026: 68 10 00 00 00 pushl $16 | 104 | // DISASM-NEXT: 11026: 68 10 00 00 00 pushl $16 |
| 105 | // DISASM-NEXT: 1102b: e9 e0 ff ff ff jmp -32 <_start+0xE> | 105 | // DISASM-NEXT: 1102b: e9 e0 ff ff ff jmp -32 <_start+0xe> |
| 106 | // DISASM-NEXT: 11030: ff 25 04 20 01 00 jmpl *73732 | 106 | // DISASM-NEXT: 11030: ff 25 04 20 01 00 jmpl *73732 |
| 107 | // DISASM-NEXT: 11036: 68 18 00 00 00 pushl $24 | 107 | // DISASM-NEXT: 11036: 68 18 00 00 00 pushl $24 |
| 108 | // DISASM-NEXT: 1103b: e9 d0 ff ff ff jmp -48 <_start+0xE> | 108 | // DISASM-NEXT: 1103b: e9 d0 ff ff ff jmp -48 <_start+0xe> |
| 109 | 109 | ||
| 110 | .text | 110 | .text |
| 111 | .type foo STT_GNU_IFUNC | 111 | .type foo STT_GNU_IFUNC |
deps/lld/test/ELF/gnu-ifunc-plt-i386.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/shared2-x86-64.s -o %t1.o | 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/shared2-x86-64.s -o %t1.o |
| 2 | // RUN: ld.lld %t1.o --shared -o %t.so | 2 | // RUN: ld.lld %t1.o --shared -o %t.so |
| 3 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o | 3 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o |
| 4 | // RUN: ld.lld %t.so %t.o -o %tout | 4 | // RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout |
| 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM | 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM |
| 6 | // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT | 6 | // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT |
| 7 | // RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s | 7 | // RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s |
deps/lld/test/ELF/gnu-ifunc-plt.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/shared2-x86-64.s -o %t1.o | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/shared2-x86-64.s -o %t1.o |
| 2 | // RUN: ld.lld %t1.o --shared -o %t.so | 2 | // RUN: ld.lld %t1.o --shared -o %t.so |
| 3 | // 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 %s -o %t.o |
| 4 | // RUN: ld.lld %t.so %t.o -o %tout | 4 | // RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout |
| 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM | 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM |
| 6 | // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT | 6 | // RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT |
| 7 | // RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s | 7 | // RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s |
deps/lld/test/ELF/gnu-ifunc-shared.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | // RUN: ld.lld --shared -o %t.so %t.o | 3 | // RUN: ld.lld --hash-style=sysv --shared -o %t.so %t.o |
| 4 | // RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=DISASM | 4 | // RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=DISASM |
| 5 | // RUN: llvm-readobj -r %t.so | FileCheck %s | 5 | // RUN: llvm-readobj -r %t.so | FileCheck %s |
| 6 | 6 |
deps/lld/test/ELF/gnu-ifunc.s+3-3| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | // CHECK-NEXT: Address: [[RELA:.*]] | 15 | // CHECK-NEXT: Address: [[RELA:.*]] |
| 16 | // CHECK-NEXT: Offset: 0x158 | 16 | // CHECK-NEXT: Offset: 0x158 |
| 17 | // CHECK-NEXT: Size: 48 | 17 | // CHECK-NEXT: Size: 48 |
| 18 | // CHECK-NEXT: Link: 6 | 18 | // CHECK-NEXT: Link: 0 |
| 19 | // CHECK-NEXT: Info: 0 | 19 | // CHECK-NEXT: Info: 0 |
| 20 | // CHECK-NEXT: AddressAlignment: 8 | 20 | // CHECK-NEXT: AddressAlignment: 8 |
| 21 | // CHECK-NEXT: EntrySize: 24 | 21 | // CHECK-NEXT: EntrySize: 24 |
| ... | @@ -102,10 +102,10 @@ | ... | @@ -102,10 +102,10 @@ |
| 102 | // DISASM-NEXT: .plt: | 102 | // DISASM-NEXT: .plt: |
| 103 | // DISASM-NEXT: 201020: {{.*}} jmpq *4058(%rip) | 103 | // DISASM-NEXT: 201020: {{.*}} jmpq *4058(%rip) |
| 104 | // DISASM-NEXT: 201026: {{.*}} pushq $0 | 104 | // DISASM-NEXT: 201026: {{.*}} pushq $0 |
| 105 | // DISASM-NEXT: 20102b: {{.*}} jmp -32 <_start+0xE> | 105 | // DISASM-NEXT: 20102b: {{.*}} jmp -32 <_start+0xe> |
| 106 | // DISASM-NEXT: 201030: {{.*}} jmpq *4050(%rip) | 106 | // DISASM-NEXT: 201030: {{.*}} jmpq *4050(%rip) |
| 107 | // DISASM-NEXT: 201036: {{.*}} pushq $1 | 107 | // DISASM-NEXT: 201036: {{.*}} pushq $1 |
| 108 | // DISASM-NEXT: 20103b: {{.*}} jmp -48 <_start+0xE> | 108 | // DISASM-NEXT: 20103b: {{.*}} jmp -48 <_start+0xe> |
| 109 | 109 | ||
| 110 | .text | 110 | .text |
| 111 | .type foo STT_GNU_IFUNC | 111 | .type foo STT_GNU_IFUNC |
deps/lld/test/ELF/got-aarch64.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.o |
| 2 | // RUN: ld.lld -shared %t.o -o %t.so | 2 | // RUN: ld.lld --hash-style=sysv -shared %t.o -o %t.so |
| 3 | // RUN: llvm-readobj -s -r %t.so | FileCheck %s | 3 | // RUN: llvm-readobj -s -r %t.so | FileCheck %s |
| 4 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s | 4 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s |
| 5 | // REQUIRES: aarch64 | 5 | // REQUIRES: aarch64 |
deps/lld/test/ELF/got.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o |
| 3 | // RUN: ld.lld -shared %t2.o -o %t2.so | 3 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 4 | // RUN: ld.lld %t.o %t2.so -o %t | 4 | // RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t |
| 5 | // RUN: llvm-readobj -s -r %t | FileCheck %s | 5 | // RUN: llvm-readobj -s -r %t | FileCheck %s |
| 6 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s | 6 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s |
| 7 | // REQUIRES: x86 | 7 | // REQUIRES: x86 |
deps/lld/test/ELF/got32-i386-pie-rw.s created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld %t.o -o %t -pie | ||
| 4 | # RUN: llvm-readelf -r -s %t | FileCheck %s | ||
| 5 | |||
| 6 | # Unlike bfd and gold we accept this. | ||
| 7 | |||
| 8 | # CHECK: .foobar PROGBITS 00001000 | ||
| 9 | # CHECK: .got PROGBITS [[GOT:[0-9a-z]*]] | ||
| 10 | # CHECK: [[GOT]] 00000008 R_386_RELATIVE | ||
| 11 | # CHECK: 00001002 00000008 R_386_RELATIVE | ||
| 12 | foo: | ||
| 13 | |||
| 14 | .section .foobar, "awx" | ||
| 15 | .global _start | ||
| 16 | _start: | ||
| 17 | movl foo@GOT, %ebx | ||
deps/lld/test/ELF/got32-i386.s+1-1| ... | @@ -20,4 +20,4 @@ _start: | ... | @@ -20,4 +20,4 @@ _start: |
| 20 | # CHECK: .got 00000004 0000000000012000 | 20 | # CHECK: .got 00000004 0000000000012000 |
| 21 | 21 | ||
| 22 | # RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s --check-prefix=ERR | 22 | # RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s --check-prefix=ERR |
| 23 | # ERR: relocation R_386_GOT32 against 'foo' without base register can not be used when PIC enabled | 23 | # ERR: error: can't create dynamic relocation R_386_GOT32 against symbol: foo in readonly segment; recompile object files with -fPIC |
deps/lld/test/ELF/got32x-i386.s+2-2| ... | @@ -43,5 +43,5 @@ | ... | @@ -43,5 +43,5 @@ |
| 43 | 43 | ||
| 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=ERR | 45 | # RUN: FileCheck %s --check-prefix=ERR |
| 46 | # ERR: relocation R_386_GOT32X against 'foo' without base register can not be used when PIC enabled | 46 | # ERR: error: can't create dynamic relocation R_386_GOT32X against symbol: foo in readonly segment; recompile object files with -fPIC |
| 47 | # ERR: relocation R_386_GOT32X against 'foo' without base register can not be used when PIC enabled | 47 | # ERR: error: can't create dynamic relocation R_386_GOT32X against symbol: foo in readonly segment; recompile object files with -fPIC |
deps/lld/test/ELF/gotpc-relax-nopic.s+3-3| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | # RUN: ld.lld %t.o -o %t1 | 3 | # RUN: ld.lld --hash-style=sysv %t.o -o %t1 |
| 4 | # RUN: llvm-readobj -symbols -r %t1 | FileCheck --check-prefix=SYMRELOC %s | 4 | # RUN: llvm-readobj -symbols -r %t1 | FileCheck --check-prefix=SYMRELOC %s |
| 5 | # RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s | 5 | # RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s |
| 6 | 6 | ||
| ... | @@ -25,7 +25,7 @@ | ... | @@ -25,7 +25,7 @@ |
| 25 | # DISASM-NEXT: 201031: {{.*}} xorq $2105344, %r8 | 25 | # DISASM-NEXT: 201031: {{.*}} xorq $2105344, %r8 |
| 26 | # DISASM-NEXT: 201038: {{.*}} testq $2105344, %r15 | 26 | # DISASM-NEXT: 201038: {{.*}} testq $2105344, %r15 |
| 27 | 27 | ||
| 28 | # RUN: ld.lld -shared %t.o -o %t2 | 28 | # RUN: ld.lld --hash-style=sysv -shared %t.o -o %t2 |
| 29 | # RUN: llvm-readobj -s -r -d %t2 | FileCheck --check-prefix=SEC-PIC %s | 29 | # RUN: llvm-readobj -s -r -d %t2 | FileCheck --check-prefix=SEC-PIC %s |
| 30 | # RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM-PIC %s | 30 | # RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM-PIC %s |
| 31 | # SEC-PIC: Section { | 31 | # SEC-PIC: Section { |
| ... | @@ -64,7 +64,7 @@ | ... | @@ -64,7 +64,7 @@ |
| 64 | # DISASM-PIC-NEXT: 1023: {{.*}} sbbq 8310(%rip), %rsi | 64 | # DISASM-PIC-NEXT: 1023: {{.*}} sbbq 8310(%rip), %rsi |
| 65 | # DISASM-PIC-NEXT: 102a: {{.*}} subq 8303(%rip), %rbp | 65 | # DISASM-PIC-NEXT: 102a: {{.*}} subq 8303(%rip), %rbp |
| 66 | # DISASM-PIC-NEXT: 1031: {{.*}} xorq 8296(%rip), %r8 | 66 | # DISASM-PIC-NEXT: 1031: {{.*}} xorq 8296(%rip), %r8 |
| 67 | # DISASM-PIC-NEXT: 1038: {{.*}} testq 8289(%rip), %r15 | 67 | # DISASM-PIC-NEXT: 1038: {{.*}} testq %r15, 8289(%rip) |
| 68 | 68 | ||
| 69 | .data | 69 | .data |
| 70 | .type bar, @object | 70 | .type bar, @object |
deps/lld/test/ELF/gotpc-relax-und-dso.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | # RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | # RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %S/Inputs/gotpc-relax-und-dso.s -o %tdso.o | 3 | # 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.so | 4 | # RUN: ld.lld -shared %tdso.o -o %t.so |
| 5 | # RUN: ld.lld -shared %t.o %t.so -o %tout | 5 | # RUN: ld.lld --hash-style=sysv -shared %t.o %t.so -o %tout |
| 6 | # RUN: llvm-readobj -r -s %tout | FileCheck --check-prefix=RELOC %s | 6 | # RUN: llvm-readobj -r -s %tout | FileCheck --check-prefix=RELOC %s |
| 7 | # RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s | 7 | # RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s |
| 8 | 8 |
deps/lld/test/ELF/gotpcrelx.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -relax-relocations -triple x86_64-pc-linux-gnu \ | 1 | // RUN: llvm-mc -filetype=obj -relax-relocations -triple x86_64-pc-linux-gnu \ |
| 2 | // RUN: %s -o %t.o | 2 | // RUN: %s -o %t.o |
| 3 | // RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELS %s | 3 | // RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELS %s |
| 4 | // RUN: ld.lld %t.o -o %t.so -shared | 4 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 5 | // RUN: llvm-readobj -s -r %t.so | FileCheck %s | 5 | // RUN: llvm-readobj -s -r %t.so | FileCheck %s |
| 6 | 6 | ||
| 7 | movq foo@GOTPCREL(%rip), %rax | 7 | movq foo@GOTPCREL(%rip), %rax |
deps/lld/test/ELF/help.s created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | # RUN: ld.lld --help 2>&1 | FileCheck %s | ||
| 2 | # CHECK: OPTIONS: | ||
| 3 | # CHECK: --output=<value> Path to file to write output | ||
| 4 | # CHECK: --output <value> Path to file to write output | ||
| 5 | # CHECK: -o <path> Path to file to write output | ||
deps/lld/test/ELF/i386-debug-noabs.test created+33| ... | @@ -0,0 +1,33 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: yaml2obj %s -o %t.o | ||
| 4 | # RUN: ld.lld %t.o -o %t.exe | ||
| 5 | |||
| 6 | ## This is for https://bugs.llvm.org//show_bug.cgi?id=34852. GCC 8.0 or | ||
| 7 | ## earlier have a bug which creates non-absolute R_386_GOTPC relocations | ||
| 8 | ## in non-allocated sections. It is illegal, but we want to make sure that | ||
| 9 | ## lld skips them instead of reporting errors. | ||
| 10 | |||
| 11 | --- !ELF | ||
| 12 | FileHeader: | ||
| 13 | Class: ELFCLASS32 | ||
| 14 | Data: ELFDATA2LSB | ||
| 15 | Type: ET_REL | ||
| 16 | Machine: EM_386 | ||
| 17 | Sections: | ||
| 18 | - Name: .debug_info | ||
| 19 | Type: SHT_PROGBITS | ||
| 20 | AddressAlign: 0x0000000000000001 | ||
| 21 | Content: 0000000000000000 | ||
| 22 | - Name: .rel.debug_info | ||
| 23 | Type: SHT_REL | ||
| 24 | Link: .symtab | ||
| 25 | AddressAlign: 0x0000000000000004 | ||
| 26 | Info: .debug_info | ||
| 27 | Relocations: | ||
| 28 | - Offset: 0x000000000000041F | ||
| 29 | Symbol: _GLOBAL_OFFSET_TABLE_ | ||
| 30 | Type: R_386_GOTPC | ||
| 31 | Symbols: | ||
| 32 | Global: | ||
| 33 | - Name: _GLOBAL_OFFSET_TABLE_ | ||
deps/lld/test/ELF/i386-got-and-copy.s+1-1| ... | @@ -9,7 +9,7 @@ | ... | @@ -9,7 +9,7 @@ |
| 9 | # RUN: %S/Inputs/copy-in-shared.s -o %t.so.o | 9 | # RUN: %S/Inputs/copy-in-shared.s -o %t.so.o |
| 10 | # RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o | 10 | # RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o |
| 11 | # RUN: ld.lld %t.so.o -shared -o %t.so | 11 | # RUN: ld.lld %t.so.o -shared -o %t.so |
| 12 | # RUN: ld.lld %t.o %t.so -o %t.exe | 12 | # RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t.exe |
| 13 | # RUN: llvm-readobj -r %t.exe | FileCheck %s | 13 | # RUN: llvm-readobj -r %t.exe | FileCheck %s |
| 14 | 14 | ||
| 15 | # CHECK: Relocations [ | 15 | # CHECK: Relocations [ |
deps/lld/test/ELF/i386-got-value.s created+33| ... | @@ -0,0 +1,33 @@ | ||
| 1 | # RUN: llvm-mc %s -o %t.o -filetype=obj -triple=i386-pc-linux | ||
| 2 | # RUN: ld.lld %t.o -o %t.so -shared | ||
| 3 | # RUN: llvm-readobj --relocations --sections --section-data %t.so | FileCheck %s | ||
| 4 | |||
| 5 | # Check that the value of a preemptible symbol is not written to the | ||
| 6 | # got entry when using Elf_Rel. It is not needed since the dynamic | ||
| 7 | # linker will write the final value. | ||
| 8 | |||
| 9 | # CHECK: 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: | ||
| 16 | # CHECK-NEXT: Offset: | ||
| 17 | # CHECK-NEXT: Size: 4 | ||
| 18 | # CHECK-NEXT: Link: | ||
| 19 | # CHECK-NEXT: Info: | ||
| 20 | # CHECK-NEXT: AddressAlignment: | ||
| 21 | # CHECK-NEXT: EntrySize: | ||
| 22 | # CHECK-NEXT: SectionData ( | ||
| 23 | # CHECK-NEXT: 0000: 00000000 | ||
| 24 | # CHECK-NEXT: ) | ||
| 25 | |||
| 26 | # CHECK: R_386_GLOB_DAT bar 0x0 | ||
| 27 | |||
| 28 | movl bar@GOT(%eax), %eax | ||
| 29 | |||
| 30 | .data | ||
| 31 | .globl bar | ||
| 32 | bar: | ||
| 33 | .long 42 | ||
deps/lld/test/ELF/i386-gotoff-shared.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld %t.o -o %t.so -shared | 3 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 4 | // RUN: llvm-readobj -s %t.so | FileCheck %s | 4 | // RUN: llvm-readobj -s %t.so | FileCheck %s |
| 5 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s | 5 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s |
| 6 | 6 |
deps/lld/test/ELF/i386-gotpc-dynamic.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o |
| 3 | # RUN: ld.lld %t.o -o %t.so -shared | 3 | # RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 4 | # RUN: llvm-readobj -s %t.so | FileCheck %s | 4 | # RUN: llvm-readobj -s %t.so | FileCheck %s |
| 5 | # RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s | 5 | # RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s |
| 6 | 6 |
deps/lld/test/ELF/i386-gotpc.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld %t.o -o %t.so -shared | 3 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 4 | // RUN: llvm-readobj -s %t.so | FileCheck %s | 4 | // RUN: llvm-readobj -s %t.so | FileCheck %s |
| 5 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s | 5 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s |
| 6 | 6 |
deps/lld/test/ELF/i386-pc8-pc16-addend.s+1-1| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | # RUN: ld.lld %t1.o -o %t.out | 4 | # RUN: ld.lld %t1.o -o %t.out |
| 5 | # RUN: llvm-objdump -s -t %t.out | FileCheck %s | 5 | # RUN: llvm-objdump -s -t %t.out | FileCheck %s |
| 6 | # CHECK: Contents of section .text: | 6 | # CHECK: Contents of section .text: |
| 7 | # CHECK-NEXT: 11000 020000 | 7 | # CHECK-NEXT: 11000 020000 |
| 8 | ## 0x11003 - 0x11000 + addend(-1) = 0x02 | 8 | ## 0x11003 - 0x11000 + addend(-1) = 0x02 |
| 9 | ## 0x11003 - 0x11001 + addend(-2) = 0x0000 | 9 | ## 0x11003 - 0x11001 + addend(-2) = 0x0000 |
| 10 | # CHECK: SYMBOL TABLE: | 10 | # CHECK: SYMBOL TABLE: |
deps/lld/test/ELF/i386-reloc-16.s+1-1| ... | @@ -9,6 +9,6 @@ | ... | @@ -9,6 +9,6 @@ |
| 9 | // CHECK-NEXT: 200000 42 | 9 | // CHECK-NEXT: 200000 42 |
| 10 | 10 | ||
| 11 | // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s | 11 | // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s |
| 12 | // ERROR: relocation R_386_16 out of range | 12 | // ERROR: relocation R_386_16 out of range: 65536 is not in [0, 65535] |
| 13 | 13 | ||
| 14 | .short foo | 14 | .short foo |
deps/lld/test/ELF/i386-reloc-8.s+1-1| ... | @@ -9,6 +9,6 @@ | ... | @@ -9,6 +9,6 @@ |
| 9 | // CHECK-NEXT: 200000 42 | 9 | // CHECK-NEXT: 200000 42 |
| 10 | 10 | ||
| 11 | // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s | 11 | // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s |
| 12 | // ERROR: relocation R_386_8 out of range | 12 | // ERROR: relocation R_386_8 out of range: 256 is not in [0, 255] |
| 13 | 13 | ||
| 14 | .byte foo | 14 | .byte foo |
deps/lld/test/ELF/i386-reloc-range.s+1-1| ... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | ||
| 17 | // RUN: not ld.lld -Ttext 0x200 %t.o %t2.o -o %t2 2>&1 | FileCheck --check-prefix=ERR %s | 17 | // RUN: not ld.lld -Ttext 0x200 %t.o %t2.o -o %t2 2>&1 | FileCheck --check-prefix=ERR %s |
| 18 | 18 | ||
| 19 | // ERR: {{.*}}:(.text+0x1): relocation R_386_PC16 out of range | 19 | // ERR: {{.*}}:(.text+0x1): relocation R_386_PC16 out of range: 65536 is not in [-65536, 65535] |
| 20 | 20 | ||
| 21 | .global _start | 21 | .global _start |
| 22 | _start: | 22 | _start: |
deps/lld/test/ELF/i386-reloc8-reloc16-addend.s+1-1| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | # RUN: ld.lld -Ttext=0x0 %t1.o -o %t.out | 4 | # RUN: ld.lld -Ttext=0x0 %t1.o -o %t.out |
| 5 | # RUN: llvm-objdump -s -t %t.out | FileCheck %s | 5 | # RUN: llvm-objdump -s -t %t.out | FileCheck %s |
| 6 | # CHECK: Contents of section .text: | 6 | # CHECK: Contents of section .text: |
| 7 | # CHECK-NEXT: 0000 020100 | 7 | # CHECK-NEXT: 0000 020100 |
| 8 | ## 0x3 + addend(-1) = 0x02 | 8 | ## 0x3 + addend(-1) = 0x02 |
| 9 | ## 0x3 + addend(-2) = 0x0100 | 9 | ## 0x3 + addend(-2) = 0x0100 |
| 10 | # CHECK: SYMBOL TABLE: | 10 | # CHECK: SYMBOL TABLE: |
deps/lld/test/ELF/i386-tls-ie-shared.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o |
| 3 | // RUN: ld.lld -shared %tso.o -o %tso | 3 | // RUN: ld.lld -shared %tso.o -o %tso |
| 4 | // RUN: ld.lld -shared %t.o %tso -o %t1 | 4 | // RUN: ld.lld --hash-style=sysv -shared %t.o %tso -o %t1 |
| 5 | // RUN: llvm-readobj -s -r -d %t1 | FileCheck --check-prefix=GOTRELSHARED %s | 5 | // RUN: llvm-readobj -s -r -d %t1 | FileCheck --check-prefix=GOTRELSHARED %s |
| 6 | // RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s | 6 | // RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s |
| 7 | 7 |
deps/lld/test/ELF/i386-tls-initial-exec-local.s created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc %s -o %t.o -filetype=obj -triple=i386-pc-linux | ||
| 3 | # RUN: ld.lld %t.o -o %t.so -shared | ||
| 4 | # RUN: llvm-readobj --relocations --sections --section-data %t.so | FileCheck %s | ||
| 5 | |||
| 6 | # Check initial exec access to a local symbol. | ||
| 7 | |||
| 8 | # CHECK: Name: .got ( | ||
| 9 | # CHECK-NEXT: Type: | ||
| 10 | # CHECK-NEXT: Flags [ | ||
| 11 | # CHECK-NEXT: SHF_ALLOC | ||
| 12 | # CHECK-NEXT: SHF_WRITE | ||
| 13 | # CHECK-NEXT: ] | ||
| 14 | # CHECK-NEXT: Address: | ||
| 15 | # CHECK-NEXT: Offset: | ||
| 16 | # CHECK-NEXT: Size: 8 | ||
| 17 | # CHECK-NEXT: Link: | ||
| 18 | # CHECK-NEXT: Info: | ||
| 19 | # CHECK-NEXT: AddressAlignment: | ||
| 20 | # CHECK-NEXT: EntrySize: | ||
| 21 | # CHECK-NEXT: SectionData ( | ||
| 22 | # CHECK-NEXT: 0000: 00000000 04000000 | ||
| 23 | # CHECK-NEXT: ) | ||
| 24 | |||
| 25 | # CHECK: R_386_TLS_TPOFF - 0x0 | ||
| 26 | # CHECK-NEXT: R_386_TLS_TPOFF - 0x0 | ||
| 27 | |||
| 28 | 	movl	bar1@GOTNTPOFF(%eax), %ecx | ||
| 29 | 	movl	bar2@GOTNTPOFF(%eax), %eax | ||
| 30 | |||
| 31 | 	.section	.tdata,"awT",@progbits | ||
| 32 | bar1: | ||
| 33 | 	.long	42 | ||
| 34 | |||
| 35 | bar2: | ||
| 36 | 	.long	42 | ||
deps/lld/test/ELF/icf-absolute.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-absolute.s -o %t2 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-absolute.s -o %t2 |
| 5 | # RUN: ld.lld %t %t2 -o %t3 --icf=all --verbose | FileCheck %s | 5 | # RUN: ld.lld %t %t2 -o %t3 --icf=all --verbose 2>&1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK: selected .text.f1 | 7 | # CHECK: selected .text.f1 |
| 8 | # CHECK: removed .text.f2 | 8 | # CHECK: removed .text.f2 |
deps/lld/test/ELF/icf-comdat.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s | 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: selected .text.f1 | 6 | # CHECK: selected .text.f1 |
| 7 | # CHECK: removed .text.f2 | 7 | # CHECK: removed .text.f2 |
deps/lld/test/ELF/icf-i386.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | # This test is to make sure that we can handle implicit addends properly. | 2 | # This test is to make sure that we can handle implicit addends properly. |
| 3 | 3 | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %s -o %t | 4 | # RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %s -o %t |
| 5 | # RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s | 5 | # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK: selected .text.f1 | 7 | # CHECK: selected .text.f1 |
| 8 | # CHECK: removed .text.f2 | 8 | # CHECK: removed .text.f2 |
deps/lld/test/ELF/icf-merge-sec.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge-sec.s -o %t2 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge-sec.s -o %t2 |
| 5 | # RUN: ld.lld %t %t2 -o %t3 --icf=all --verbose | FileCheck %s | 5 | # RUN: ld.lld %t %t2 -o %t3 --icf=all --verbose 2>&1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK: selected .text.f1 | 7 | # CHECK: selected .text.f1 |
| 8 | # CHECK: removed .text.f2 | 8 | # CHECK: removed .text.f2 |
deps/lld/test/ELF/icf-merge.s+3-3| ... | @@ -2,13 +2,13 @@ | ... | @@ -2,13 +2,13 @@ |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge.s -o %t1 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge.s -o %t1 |
| 5 | # RUN: ld.lld %t %t1 -o %t1.out --icf=all --verbose | FileCheck %s | 5 | # RUN: ld.lld %t %t1 -o %t1.out --icf=all --verbose 2>&1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge2.s -o %t2 | 7 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge2.s -o %t2 |
| 8 | # RUN: ld.lld %t %t2 -o %t3.out --icf=all --verbose | FileCheck --check-prefix=NOMERGE %s | 8 | # RUN: ld.lld %t %t2 -o %t3.out --icf=all --verbose 2>&1 | FileCheck --check-prefix=NOMERGE %s |
| 9 | 9 | ||
| 10 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge3.s -o %t3 | 10 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-merge3.s -o %t3 |
| 11 | # RUN: ld.lld %t %t3 -o %t3.out --icf=all --verbose | FileCheck --check-prefix=NOMERGE %s | 11 | # RUN: ld.lld %t %t3 -o %t3.out --icf=all --verbose 2>&1 | FileCheck --check-prefix=NOMERGE %s |
| 12 | 12 | ||
| 13 | # CHECK: selected .text.f1 | 13 | # CHECK: selected .text.f1 |
| 14 | # CHECK: removed .text.f2 | 14 | # CHECK: removed .text.f2 |
deps/lld/test/ELF/icf-non-mergeable.s+2-2| ... | @@ -1,14 +1,14 @@ | ... | @@ -1,14 +1,14 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | 2 | ||
| 3 | // This file contains two functions. They are themselves identical, | 3 | // This file contains two functions. They are themselves identical, |
| 4 | // but because they have reloactions against different data section, | 4 | // but because they have relocations against different data sections, |
| 5 | // they are not mergeable. | 5 | // they are not mergeable. |
| 6 | 6 | ||
| 7 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 | 7 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 |
| 8 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ | 8 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ |
| 9 | // RUN: %p/Inputs/icf-non-mergeable.s -o %t2 | 9 | // RUN: %p/Inputs/icf-non-mergeable.s -o %t2 |
| 10 | 10 | ||
| 11 | // RUN: ld.lld %t1 %t2 -o %t3 --icf=all --verbose | FileCheck %s | 11 | // RUN: ld.lld %t1 %t2 -o %t3 --icf=all --verbose 2>&1 | FileCheck %s |
| 12 | 12 | ||
| 13 | // CHECK-NOT: selected .text.f1 | 13 | // CHECK-NOT: selected .text.f1 |
| 14 | // CHECK-NOT: removed .text.f2 | 14 | // CHECK-NOT: removed .text.f2 |
deps/lld/test/ELF/icf-none.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: ld.lld %t -o %t2 --icf=all --icf=none --verbose | FileCheck %s | 4 | # RUN: ld.lld %t -o %t2 --icf=all --icf=none --verbose 2>&1 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK-NOT: selected .text.f1 | 6 | # CHECK-NOT: selected .text.f1 |
| 7 | 7 |
deps/lld/test/ELF/icf-symbol-type.s created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 4 | # RUN: ld.lld --hash-style=sysv %t.o -o %t --icf=all -shared | ||
| 5 | # RUN: llvm-readelf --dyn-symbols --sections %t | FileCheck %s | ||
| 6 | |||
| 7 | # We used to mark bar as absolute. | ||
| 8 | |||
| 9 | # CHECK: .text PROGBITS 0000000000001000 | ||
| 10 | # CHECK: 0000000000001001 0 NOTYPE GLOBAL DEFAULT 4 foo | ||
| 11 | # CHECK: 0000000000001001 0 NOTYPE GLOBAL DEFAULT 4 bar | ||
| 12 | |||
| 13 | # The nop makes the test more interesting by making the offset of | ||
| 14 | # text.f non zero. | ||
| 15 | |||
| 16 | nop | ||
| 17 | |||
| 18 | .section .text.f,"ax",@progbits | ||
| 19 | .globl foo | ||
| 20 | foo: | ||
| 21 | retq | ||
| 22 | |||
| 23 | .section .text.g,"ax",@progbits | ||
| 24 | .globl bar | ||
| 25 | bar: | ||
| 26 | retq | ||
deps/lld/test/ELF/icf1.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s | 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: selected .text.f1 | 6 | # CHECK: selected .text.f1 |
| 7 | # CHECK: removed .text.f2 | 7 | # CHECK: removed .text.f2 |
deps/lld/test/ELF/icf2.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/icf2.s -o %t2 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/icf2.s -o %t2 |
| 5 | # RUN: ld.lld %t1 %t2 -o %t --icf=all --verbose | FileCheck %s | 5 | # RUN: ld.lld %t1 %t2 -o %t --icf=all --verbose 2>&1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK: selected .text.f1 | 7 | # CHECK: selected .text.f1 |
| 8 | # CHECK: removed .text.f2 | 8 | # CHECK: removed .text.f2 |
deps/lld/test/ELF/icf3.s+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/icf2.s -o %t2 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/icf2.s -o %t2 |
| 5 | # RUN: ld.lld %t1 %t2 -o %t --icf=all --verbose | FileCheck %s | 5 | # RUN: ld.lld %t1 %t2 -o %t --icf=all --verbose 2>&1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK-NOT: Selected .text.f1 | 7 | # CHECK-NOT: Selected .text.f1 |
| 8 | # CHECK-NOT: Selected .text.f2 | 8 | # CHECK-NOT: Selected .text.f2 |
deps/lld/test/ELF/icf4.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s | 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK-NOT: Selected .text.f1 | 6 | # CHECK-NOT: Selected .text.f1 |
| 7 | # CHECK-NOT: Selected .text.f2 | 7 | # CHECK-NOT: Selected .text.f2 |
deps/lld/test/ELF/icf5.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s | 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK-NOT: Selected .text.f1 | 6 | # CHECK-NOT: Selected .text.f1 |
| 7 | # CHECK-NOT: Selected .text.f2 | 7 | # CHECK-NOT: Selected .text.f2 |
deps/lld/test/ELF/icf6.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s | 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK-NOT: Selected .text.f1 | 6 | # CHECK-NOT: Selected .text.f1 |
| 7 | # CHECK-NOT: Selected .text.f2 | 7 | # CHECK-NOT: Selected .text.f2 |
deps/lld/test/ELF/icf7.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s | 4 | # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s |
| 5 | # RUN: llvm-objdump -t %t2 | FileCheck -check-prefix=ALIGN %s | 5 | # RUN: llvm-objdump -t %t2 | FileCheck -check-prefix=ALIGN %s |
| 6 | 6 | ||
| 7 | # CHECK: selected .text.f1 | 7 | # CHECK: selected .text.f1 |
deps/lld/test/ELF/icf9.s+17-5| ... | @@ -2,19 +2,31 @@ | ... | @@ -2,19 +2,31 @@ |
| 2 | 2 | ||
| 3 | ### Make sure that we do not merge data. | 3 | ### Make sure that we do not merge data. |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 5 | # RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s | 5 | # RUN: ld.lld %t -o %t2 --icf=all --verbose 2>&1 | FileCheck %s |
| 6 | # RUN: llvm-readelf -S -W %t2 | FileCheck --check-prefix=SEC %s | ||
| 6 | 7 | ||
| 7 | # CHECK-NOT: selected .data.d1 | 8 | # SEC: .rodata PROGBITS 0000000000200120 000120 000002 00 A 0 0 1 |
| 8 | # CHECK-NOT: selected .data.d2 | 9 | |
| 10 | # CHECK-NOT: selected .rodata.d1 | ||
| 11 | # CHECK-NOT: selected .rodata.d2 | ||
| 12 | |||
| 13 | # We do merge rodata if passed --icf-data | ||
| 14 | # RUN: ld.lld %t -o %t2 --icf=all --verbose --icf-data 2>&1 | FileCheck --check-prefix=DATA %s | ||
| 15 | # RUN: llvm-readelf -S -W %t2 | FileCheck --check-prefix=DATA-SEC %s | ||
| 16 | |||
| 17 | # DATA: selected .rodata.d1 | ||
| 18 | # DATA: removed .rodata.d2 | ||
| 19 | |||
| 20 | # DATA-SEC: .rodata PROGBITS 0000000000200120 000120 000001 00 A 0 0 1 | ||
| 9 | 21 | ||
| 10 | .globl _start, d1, d2 | 22 | .globl _start, d1, d2 |
| 11 | _start: | 23 | _start: |
| 12 | ret | 24 | ret |
| 13 | 25 | ||
| 14 | .section .data.f1, "a" | 26 | .section .rodata.d1, "a" |
| 15 | d1: | 27 | d1: |
| 16 | .byte 1 | 28 | .byte 1 |
| 17 | 29 | ||
| 18 | .section .data.f2, "a" | 30 | .section .rodata.d2, "a" |
| 19 | d2: | 31 | d2: |
| 20 | .byte 1 | 32 | .byte 1 |
deps/lld/test/ELF/image-base.s+5-2| ... | @@ -6,6 +6,9 @@ | ... | @@ -6,6 +6,9 @@ |
| 6 | # RUN: ld.lld -image-base=0x1000 -z max-page-size=0x2000 %t -o %t1 2>&1 | FileCheck --check-prefix=WARN %s | 6 | # RUN: ld.lld -image-base=0x1000 -z max-page-size=0x2000 %t -o %t1 2>&1 | FileCheck --check-prefix=WARN %s |
| 7 | # WARN: warning: -image-base: address isn't multiple of page size: 0x1000 | 7 | # WARN: warning: -image-base: address isn't multiple of page size: 0x1000 |
| 8 | 8 | ||
| 9 | # Check alias. | ||
| 10 | # RUN: ld.lld -image-base 0x1000000 %t -o %t1 | ||
| 11 | # RUN: llvm-readobj -program-headers %t1 | FileCheck %s | ||
| 9 | 12 | ||
| 10 | .global _start | 13 | .global _start |
| 11 | _start: | 14 | _start: |
| ... | @@ -41,8 +44,8 @@ _start: | ... | @@ -41,8 +44,8 @@ _start: |
| 41 | # CHECK-NEXT: Offset: 0x1000 | 44 | # CHECK-NEXT: Offset: 0x1000 |
| 42 | # CHECK-NEXT: VirtualAddress: 0x1001000 | 45 | # CHECK-NEXT: VirtualAddress: 0x1001000 |
| 43 | # CHECK-NEXT: PhysicalAddress: 0x1001000 | 46 | # CHECK-NEXT: PhysicalAddress: 0x1001000 |
| 44 | # CHECK-NEXT: FileSize: 1 | 47 | # CHECK-NEXT: FileSize: 4096 |
| 45 | # CHECK-NEXT: MemSize: 1 | 48 | # CHECK-NEXT: MemSize: 4096 |
| 46 | # CHECK-NEXT: Flags [ (0x5) | 49 | # CHECK-NEXT: Flags [ (0x5) |
| 47 | # CHECK-NEXT: PF_R (0x4) | 50 | # CHECK-NEXT: PF_R (0x4) |
| 48 | # CHECK-NEXT: PF_X (0x1) | 51 | # CHECK-NEXT: PF_X (0x1) |
deps/lld/test/ELF/init_fini_priority.s+18-6| ... | @@ -1,34 +1,46 @@ | ... | @@ -1,34 +1,46 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 2 | // RUN: llvm-objdump -section-headers %t | FileCheck %s --check-prefix=OBJ | ||
| 2 | // RUN: ld.lld %t -o %t.exe | 3 | // RUN: ld.lld %t -o %t.exe |
| 3 | // RUN: llvm-objdump -s %t.exe | FileCheck %s | 4 | // RUN: llvm-objdump -s %t.exe | FileCheck %s |
| 4 | // REQUIRES: x86 | 5 | // REQUIRES: x86 |
| 5 | 6 | ||
| 7 | // OBJ: 3 .init_array | ||
| 8 | // OBJ-NEXT: 4 .init_array.100 | ||
| 9 | // OBJ-NEXT: 5 .init_array.5 | ||
| 10 | // OBJ-NEXT: 6 .init_array | ||
| 11 | // OBJ-NEXT: 7 .init_array | ||
| 12 | // OBJ-NEXT: 8 .fini_array | ||
| 13 | // OBJ-NEXT: 9 .fini_array.100 | ||
| 14 | // OBJ-NEXT: 10 .fini_array.5 | ||
| 15 | // OBJ-NEXT: 11 .fini_array | ||
| 16 | // OBJ-NEXT: 12 .fini_array | ||
| 17 | |||
| 6 | .globl _start | 18 | .globl _start |
| 7 | _start: | 19 | _start: |
| 8 | nop | 20 | nop |
| 9 | 21 | ||
| 10 | .section .init_array, "aw", @init_array | 22 | .section .init_array, "aw", @init_array, unique, 0 |
| 11 | .align 8 | 23 | .align 8 |
| 12 | .byte 1 | 24 | .byte 1 |
| 13 | .section .init_array.100, "aw", @init_array | 25 | .section .init_array.100, "aw", @init_array |
| 14 | .long 2 | 26 | .long 2 |
| 15 | .section .init_array.5, "aw", @init_array | 27 | .section .init_array.5, "aw", @init_array |
| 16 | .byte 3 | 28 | .byte 3 |
| 17 | .section .init_array, "aw", @init_array | 29 | .section .init_array, "aw", @init_array, unique, 1 |
| 18 | .byte 4 | 30 | .byte 4 |
| 19 | .section .init_array, "aw", @init_array | 31 | .section .init_array, "aw", @init_array, unique, 2 |
| 20 | .byte 5 | 32 | .byte 5 |
| 21 | 33 | ||
| 22 | .section .fini_array, "aw", @fini_array | 34 | .section .fini_array, "aw", @fini_array, unique, 0 |
| 23 | .align 8 | 35 | .align 8 |
| 24 | .byte 0x11 | 36 | .byte 0x11 |
| 25 | .section .fini_array.100, "aw", @fini_array | 37 | .section .fini_array.100, "aw", @fini_array |
| 26 | .long 0x12 | 38 | .long 0x12 |
| 27 | .section .fini_array.5, "aw", @fini_array | 39 | .section .fini_array.5, "aw", @fini_array |
| 28 | .byte 0x13 | 40 | .byte 0x13 |
| 29 | .section .fini_array, "aw", @fini_array | 41 | .section .fini_array, "aw", @fini_array, unique, 1 |
| 30 | .byte 0x14 | 42 | .byte 0x14 |
| 31 | .section .fini_array, "aw", @fini_array | 43 | .section .fini_array, "aw", @fini_array, unique, 2 |
| 32 | .byte 0x15 | 44 | .byte 0x15 |
| 33 | 45 | ||
| 34 | // CHECK: Contents of section .init_array: | 46 | // CHECK: Contents of section .init_array: |
deps/lld/test/ELF/invalid-linkerscript.test+1-1| ... | @@ -45,7 +45,7 @@ | ... | @@ -45,7 +45,7 @@ |
| 45 | 45 | ||
| 46 | # RUN: echo "INCLUDE /no/such/file" > %t7 | 46 | # RUN: echo "INCLUDE /no/such/file" > %t7 |
| 47 | # RUN: not ld.lld %t7 no-such-file 2>&1 | FileCheck -check-prefix=ERR7 %s | 47 | # RUN: not ld.lld %t7 no-such-file 2>&1 | FileCheck -check-prefix=ERR7 %s |
| 48 | # ERR7: cannot open /no/such/file | 48 | # ERR7: cannot find linker script /no/such/file |
| 49 | # ERR7: cannot open no-such-file: | 49 | # ERR7: cannot open no-such-file: |
| 50 | 50 | ||
| 51 | # RUN: echo "OUTPUT_FORMAT(x y z)" > %t8 | 51 | # RUN: echo "OUTPUT_FORMAT(x y z)" > %t8 |
deps/lld/test/ELF/invalid-local-symbol-in-dso.s created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # We used to crash on this | ||
| 4 | # RUN: ld.lld %p/Inputs/local-symbol-in-dso.so -o %t 2>&1 | \ | ||
| 5 | # RUN: FileCheck -check-prefix=WARN %s | ||
| 6 | # WARN: found local symbol 'foo' in global part of symbol table in file {{.*}}local-symbol-in-dso.so | ||
| 7 | |||
| 8 | # RUN: llvm-mc %s -o %t.o -filetype=obj -triple x86_64-pc-linux | ||
| 9 | # RUN: not ld.lld %t.o %p/Inputs/local-symbol-in-dso.so -o %t | ||
| 10 | |||
| 11 | .globl main | ||
| 12 | main: | ||
| 13 | movq foo@GOTTPOFF(%rip), %rax | ||
deps/lld/test/ELF/invalid-undef-section-symbol.test created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | # RUN: yaml2obj %s -o %t.o | ||
| 2 | # RUN: not ld.lld -r %t.o -o %2.o 2>&1 | FileCheck %s | ||
| 3 | |||
| 4 | # We used to crash at this. | ||
| 5 | # CHECK: STT_SECTION symbol should be defined | ||
| 6 | |||
| 7 | --- !ELF | ||
| 8 | FileHeader: | ||
| 9 | Class: ELFCLASS64 | ||
| 10 | Data: ELFDATA2LSB | ||
| 11 | Type: ET_REL | ||
| 12 | Machine: EM_X86_64 | ||
| 13 | Sections: | ||
| 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 | ||
| 24 | Symbols: | ||
| 25 | Local: | ||
| 26 | - Name: .text | ||
| 27 | Type: STT_SECTION | ||
deps/lld/test/ELF/invalid/Inputs/section-index2.elf deleted| Binary files a/deps/lld/test/ELF/invalid/Inputs/section-index2.elf and /dev/null differ | |||
deps/lld/test/ELF/invalid/invalid-debug-relocations.test+1-2| ... | @@ -2,8 +2,7 @@ | ... | @@ -2,8 +2,7 @@ |
| 2 | # RUN: yaml2obj %s -o %t.o | 2 | # RUN: yaml2obj %s -o %t.o |
| 3 | # RUN: not ld.lld -gdb-index %t.o -o %t.exe 2>&1 | FileCheck %s | 3 | # RUN: not ld.lld -gdb-index %t.o -o %t.exe 2>&1 | FileCheck %s |
| 4 | 4 | ||
| 5 | # CHECK: error: {{.*}}.o: error parsing DWARF data: | 5 | # CHECK: error: {{.*}}invalid-debug-relocations.test.tmp.o:(.debug_info+0x0): has non-ABS relocation Unknown (255) against symbol '_start' |
| 6 | # CHECK-NEXT: >>> failed to compute relocation: Unknown, Invalid data was encountered while parsing the file | ||
| 7 | 6 | ||
| 8 | !ELF | 7 | !ELF |
| 9 | FileHeader: | 8 | FileHeader: |
deps/lld/test/ELF/invalid/invalid-elf.test-4| ... | @@ -20,10 +20,6 @@ | ... | @@ -20,10 +20,6 @@ |
| 20 | # RUN: FileCheck --check-prefix=INVALID-SECTION-INDEX-LLD %s | 20 | # RUN: FileCheck --check-prefix=INVALID-SECTION-INDEX-LLD %s |
| 21 | # INVALID-SECTION-INDEX-LLD: invalid section index | 21 | # INVALID-SECTION-INDEX-LLD: invalid section index |
| 22 | 22 | ||
| 23 | ## section-index2.elf has local symbol with incorrect section index. | ||
| 24 | # RUN: not ld.lld %p/Inputs/section-index2.elf -o %t2 2>&1 | \ | ||
| 25 | # RUN: FileCheck --check-prefix=INVALID-SECTION-INDEX-LLD %s | ||
| 26 | |||
| 27 | # RUN: not ld.lld %p/Inputs/multiple-eh-relocs.elf -o %t2 2>&1 | \ | 23 | # RUN: not ld.lld %p/Inputs/multiple-eh-relocs.elf -o %t2 2>&1 | \ |
| 28 | # RUN: FileCheck --check-prefix=INVALID-EH-RELOCS %s | 24 | # RUN: FileCheck --check-prefix=INVALID-EH-RELOCS %s |
| 29 | # INVALID-EH-RELOCS: multiple relocation sections to one section are not supported | 25 | # INVALID-EH-RELOCS: multiple relocation sections to one section are not supported |
deps/lld/test/ELF/invalid/invalid-relocation-x64.test+12-6| ... | @@ -1,7 +1,10 @@ | ... | @@ -1,7 +1,10 @@ |
| 1 | # RUN: yaml2obj %s -o %t.o | 1 | # REQUIRES: x86 |
| 2 | # RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s | 2 | # RUN: yaml2obj %s -o %t1.o |
| 3 | # CHECK: {{.*}}.o: unknown relocation type: Unknown (152) | 3 | # RUN: echo ".global foo; foo:" > %t2.s |
| 4 | # CHECK: {{.*}}.o: unknown relocation type: Unknown (153) | 4 | # 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 %s | ||
| 6 | # CHECK: error: unrecognized reloc 152 | ||
| 7 | # CHECK: error: unrecognized reloc 153 | ||
| 5 | 8 | ||
| 6 | !ELF | 9 | !ELF |
| 7 | FileHeader: | 10 | FileHeader: |
| ... | @@ -20,8 +23,11 @@ Sections: | ... | @@ -20,8 +23,11 @@ Sections: |
| 20 | Info: .text | 23 | Info: .text |
| 21 | Relocations: | 24 | Relocations: |
| 22 | - Offset: 0x0000000000000000 | 25 | - Offset: 0x0000000000000000 |
| 23 | Symbol: '' | 26 | Symbol: foo |
| 24 | Type: 0x98 | 27 | Type: 0x98 |
| 25 | - Offset: 0x0000000000000000 | 28 | - Offset: 0x0000000000000000 |
| 26 | Symbol: '' | 29 | Symbol: foo |
| 27 | Type: 0x99 | 30 | Type: 0x99 |
| 31 | Symbols: | ||
| 32 | Global: | ||
| 33 | - Name: foo |
deps/lld/test/ELF/libsearch.s+1| ... | @@ -60,6 +60,7 @@ | ... | @@ -60,6 +60,7 @@ |
| 60 | 60 | ||
| 61 | // Check long forms as well | 61 | // Check long forms as well |
| 62 | // RUN: ld.lld -o %t3 %t.o --library-path=%t.dir --library=ls | 62 | // RUN: ld.lld -o %t3 %t.o --library-path=%t.dir --library=ls |
| 63 | // RUN: ld.lld -o %t3 %t.o --library-path %t.dir --library ls | ||
| 63 | 64 | ||
| 64 | // Should not search for dynamic libraries if -Bstatic is specified | 65 | // Should not search for dynamic libraries if -Bstatic is specified |
| 65 | // RUN: ld.lld -o %t3 %t.o -L%t.dir -Bstatic -lls | 66 | // RUN: ld.lld -o %t3 %t.o -L%t.dir -Bstatic -lls |
deps/lld/test/ELF/linkerscript/Inputs/common-filespec1.s created+2| ... | @@ -0,0 +1,2 @@ | ||
| 1 | .comm common_uniq_1,8,8 | ||
| 2 | .comm common_multiple,16,8 | ||
deps/lld/test/ELF/linkerscript/Inputs/common-filespec2.s created+2| ... | @@ -0,0 +1,2 @@ | ||
| 1 | .comm common_uniq_2,16,16 | ||
| 2 | .comm common_multiple,32,8 | ||
deps/lld/test/ELF/linkerscript/Inputs/copy-rel-symbol-value.s created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | .global bar | ||
| 2 | .type bar, @object | ||
| 3 | .size bar, 8 | ||
| 4 | bar: | ||
| 5 | .quad 0 | ||
deps/lld/test/ELF/linkerscript/Inputs/provide-shared.s created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | .global foo | ||
| 2 | .size foo, 8 | ||
| 3 | .type foo, @object | ||
| 4 | foo: | ||
| 5 | .quad 42 | ||
deps/lld/test/ELF/linkerscript/Inputs/symbol-reserved.script created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | SECTIONS | ||
| 2 | { | ||
| 3 | .text : { *(.text) } | ||
| 4 | PROVIDE_HIDDEN(_end = .); | ||
| 5 | } | ||
deps/lld/test/ELF/linkerscript/absolute2.s created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 3 | |||
| 4 | # RUN: echo "SECTIONS { .text : { *(.text) } foo = ABSOLUTE(_start) + _start; };" > %t.script | ||
| 5 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 6 | # RUN: llvm-objdump -t %t | FileCheck %s | ||
| 7 | |||
| 8 | # RUN: echo "SECTIONS { .text : { *(.text) } foo = _start + ABSOLUTE(_start); };" > %t.script | ||
| 9 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 10 | # RUN: llvm-objdump -t %t | FileCheck %s | ||
| 11 | |||
| 12 | # CHECK: 0000000000000001 .text 00000000 _start | ||
| 13 | # CHECK: 0000000000000002 .text 00000000 foo | ||
| 14 | |||
| 15 | .global _start | ||
| 16 | nop | ||
| 17 | _start: | ||
deps/lld/test/ELF/linkerscript/align-section-offset.s created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { .foo : ALIGN(2M) { *(.foo) } }" > %t.script | ||
| 4 | # RUN: ld.lld -o %t --script %t.script %t.o -shared | ||
| 5 | # RUN: llvm-readelf -S -l %t | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: .foo PROGBITS 0000000000200000 200000 000008 00 WA 0 0 2097152 | ||
| 8 | # CHECK: LOAD 0x200000 0x0000000000200000 0x0000000000200000 {{.*}} RW 0x200000 | ||
| 9 | |||
| 10 | .section .foo, "aw" | ||
| 11 | .quad 42 | ||
deps/lld/test/ELF/linkerscript/align-section.s created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { .foo : ALIGN(2M) { } }" > %t.script | ||
| 4 | # RUN: ld.lld -o %t --script %t.script %t.o -shared | ||
| 5 | |||
| 6 | # We would crash if an empty section had an ALIGN. | ||
deps/lld/test/ELF/linkerscript/align.s+45| ... | @@ -66,6 +66,51 @@ | ... | @@ -66,6 +66,51 @@ |
| 66 | # SYMBOLS-NEXT: 0000000000011000 .bbb 00000000 __start_bbb | 66 | # SYMBOLS-NEXT: 0000000000011000 .bbb 00000000 __start_bbb |
| 67 | # SYMBOLS-NEXT: 0000000000012000 .bbb 00000000 __end_bbb | 67 | # SYMBOLS-NEXT: 0000000000012000 .bbb 00000000 __end_bbb |
| 68 | 68 | ||
| 69 | ## Check that ALIGN zero do nothing and does not crash #1. | ||
| 70 | # RUN: echo "SECTIONS { . = ALIGN(0x123, 0); .aaa : { *(.aaa) } }" > %t.script | ||
| 71 | # RUN: ld.lld -o %t4 --script %t.script %t | ||
| 72 | # RUN: llvm-objdump -section-headers %t4 | FileCheck %s -check-prefix=ZERO | ||
| 73 | |||
| 74 | # ZERO: Sections: | ||
| 75 | # ZERO-NEXT: Idx Name Size Address Type | ||
| 76 | # ZERO-NEXT: 0 00000000 0000000000000000 | ||
| 77 | # ZERO-NEXT: 1 .aaa 00000008 0000000000000123 DATA | ||
| 78 | |||
| 79 | ## Check that ALIGN zero do nothing and does not crash #2. | ||
| 80 | # RUN: echo "SECTIONS { . = 0x123; . = ALIGN(0); .aaa : { *(.aaa) } }" > %t.script | ||
| 81 | # RUN: ld.lld -o %t5 --script %t.script %t | ||
| 82 | # RUN: llvm-objdump -section-headers %t5 | FileCheck %s -check-prefix=ZERO | ||
| 83 | |||
| 84 | ## Test we fail gracefuly when alignment value is not a power of 2 (#1). | ||
| 85 | # RUN: echo "SECTIONS { . = 0x123; . = ALIGN(0x123, 3); .aaa : { *(.aaa) } }" > %t.script | ||
| 86 | # RUN: not ld.lld -o %t6 --script %t.script %t 2>&1 | FileCheck -check-prefix=ERR %s | ||
| 87 | # ERR: {{.*}}.script:1: alignment must be power of 2 | ||
| 88 | |||
| 89 | ## Test we fail gracefuly when alignment value is not a power of 2 (#2). | ||
| 90 | # RUN: echo "SECTIONS { . = 0x123; . = ALIGN(3); .aaa : { *(.aaa) } }" > %t.script | ||
| 91 | # RUN: not ld.lld -o %t7 --script %t.script %t 2>&1 | FileCheck -check-prefix=ERR %s | ||
| 92 | |||
| 93 | # RUN: echo "SECTIONS { \ | ||
| 94 | # RUN: . = 0xff8; \ | ||
| 95 | # RUN: .aaa : { \ | ||
| 96 | # RUN: *(.aaa) \ | ||
| 97 | # RUN: foo = ALIGN(., 0x100); \ | ||
| 98 | # RUN: bar = .; \ | ||
| 99 | # RUN: zed1 = ALIGN(., 0x100) + 1; \ | ||
| 100 | # RUN: zed2 = ALIGN(., 0x100) - 1; \ | ||
| 101 | # RUN: } \ | ||
| 102 | # RUN: .bbb : { *(.bbb); } \ | ||
| 103 | # RUN: .ccc : { *(.ccc); } \ | ||
| 104 | # RUN: .text : { *(.text); } \ | ||
| 105 | # RUN: }" > %t.script | ||
| 106 | # RUN: ld.lld -o %t1 --script %t.script %t | ||
| 107 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=OFFSET %s | ||
| 108 | |||
| 109 | # OFFSET: 0000000000001000 .aaa 00000000 foo | ||
| 110 | # OFFSET: 0000000000001000 .aaa 00000000 bar | ||
| 111 | # OFFSET: 0000000000001001 .aaa 00000000 zed1 | ||
| 112 | # OFFSET: 0000000000000fff .aaa 00000000 zed2 | ||
| 113 | |||
| 69 | .global _start | 114 | .global _start |
| 70 | _start: | 115 | _start: |
| 71 | nop | 116 | nop |
deps/lld/test/ELF/linkerscript/arm-exidx-order.s created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | # REQUIRES: arm | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { . = SIZEOF_HEADERS; \ | ||
| 4 | # RUN: .ARM.exidx : { *(.ARM.exidx*) } \ | ||
| 5 | # RUN: .foo : { _foo = 0; } }" > %t.script | ||
| 6 | # RUN: ld.lld -T %t.script %t.o -shared -o %t.so | ||
| 7 | # RUN: llvm-readobj -s %t.so | FileCheck %s | ||
| 8 | |||
| 9 | # CHECK: Section { | ||
| 10 | # CHECK: Index: | ||
| 11 | # CHECK: Name: .foo | ||
| 12 | # CHECK-NEXT: Type: SHT_NOBITS | ||
| 13 | # CHECK-NEXT: Flags [ | ||
| 14 | # CHECK-NEXT: SHF_ALLOC | ||
| 15 | # CHECK-NEXT: ] | ||
| 16 | |||
| 17 | .fnstart | ||
| 18 | .cantunwind | ||
| 19 | .fnend | ||
deps/lld/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s created+41| ... | @@ -0,0 +1,41 @@ | ||
| 1 | # REQUIRES: arm | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { \ | ||
| 4 | # RUN: .ARM.exidx 0x1000 : { *(.ARM.exidx*) foo = .; } \ | ||
| 5 | # RUN: .text 0x2000 : { *(.text*) } \ | ||
| 6 | # RUN: }" > %t.script | ||
| 7 | ## We used to crash if the last output section command for .ARM.exidx | ||
| 8 | ## was anything but an input section description. | ||
| 9 | # 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 %s | ||
| 11 | # RUN: llvm-readobj -s -t %t.so | FileCheck %s --check-prefix=SYMBOL | ||
| 12 | |||
| 13 | .syntax unified | ||
| 14 | .text | ||
| 15 | .global _start | ||
| 16 | _start: | ||
| 17 | .fnstart | ||
| 18 | .cantunwind | ||
| 19 | bx lr | ||
| 20 | .fnend | ||
| 21 | |||
| 22 | # CHECK: Contents of section .ARM.exidx: | ||
| 23 | # 1000 + 1000 = 0x2000 = _start | ||
| 24 | # 1008 + 0ffc = 0x2004 = _start + sizeof(_start) | ||
| 25 | # CHECK-NEXT: 1000 00100000 01000000 fc0f0000 01000000 | ||
| 26 | |||
| 27 | # SYMBOL: Section { | ||
| 28 | # SYMBOL: Name: .ARM.exidx | ||
| 29 | # SYMBOL-NEXT: Type: SHT_ARM_EXIDX | ||
| 30 | # SYMBOL-NEXT: Flags [ | ||
| 31 | # SYMBOL-NEXT: SHF_ALLOC | ||
| 32 | # SYMBOL-NEXT: SHF_LINK_ORDER | ||
| 33 | # SYMBOL-NEXT: ] | ||
| 34 | # SYMBOL-NEXT: Address: 0x1000 | ||
| 35 | # SYMBOL-NEXT: Offset: | ||
| 36 | # SYMBOL-NEXT: Size: 16 | ||
| 37 | |||
| 38 | # Symbol 'foo' is expected to point at the end of the section. | ||
| 39 | # SYMBOL: Symbol { | ||
| 40 | # SYMBOL: Name: foo | ||
| 41 | # SYMBOL-NEXT: Value: 0x1010 | ||
deps/lld/test/ELF/linkerscript/at-addr.s-4| ... | @@ -8,10 +8,6 @@ | ... | @@ -8,10 +8,6 @@ |
| 8 | # RUN: ld.lld %t --script %t.script -o %t2 | 8 | # RUN: ld.lld %t --script %t.script -o %t2 |
| 9 | # RUN: llvm-readobj -program-headers %t2 | FileCheck %s | 9 | # RUN: llvm-readobj -program-headers %t2 | FileCheck %s |
| 10 | 10 | ||
| 11 | # CHECK: Type: PT_LOAD | ||
| 12 | # CHECK-NEXT: Offset: 0x0 | ||
| 13 | # CHECK-NEXT: VirtualAddress: 0x0 | ||
| 14 | # CHECK-NEXT: PhysicalAddress: 0x0 | ||
| 15 | # CHECK: Type: PT_LOAD | 11 | # CHECK: Type: PT_LOAD |
| 16 | # CHECK-NEXT: Offset: 0x1000 | 12 | # CHECK-NEXT: Offset: 0x1000 |
| 17 | # CHECK-NEXT: VirtualAddress: 0x1000 | 13 | # CHECK-NEXT: VirtualAddress: 0x1000 |
deps/lld/test/ELF/linkerscript/at.s-25| ... | @@ -13,31 +13,6 @@ | ... | @@ -13,31 +13,6 @@ |
| 13 | 13 | ||
| 14 | # CHECK: ProgramHeaders [ | 14 | # CHECK: ProgramHeaders [ |
| 15 | # CHECK-NEXT: ProgramHeader { | 15 | # CHECK-NEXT: ProgramHeader { |
| 16 | # CHECK-NEXT: Type: PT_PHDR | ||
| 17 | # CHECK-NEXT: Offset: 0x40 | ||
| 18 | # CHECK-NEXT: VirtualAddress: 0x40 | ||
| 19 | # CHECK-NEXT: PhysicalAddress: 0x40 | ||
| 20 | # CHECK-NEXT: FileSize: | ||
| 21 | # CHECK-NEXT: MemSize: | ||
| 22 | # CHECK-NEXT: Flags [ | ||
| 23 | # CHECK-NEXT: PF_R | ||
| 24 | # CHECK-NEXT: ] | ||
| 25 | # CHECK-NEXT: Alignment: 8 | ||
| 26 | # CHECK-NEXT: } | ||
| 27 | # CHECK-NEXT: ProgramHeader { | ||
| 28 | # CHECK-NEXT: Type: PT_LOAD | ||
| 29 | # CHECK-NEXT: Offset: 0x0 | ||
| 30 | # CHECK-NEXT: VirtualAddress: 0x0 | ||
| 31 | # CHECK-NEXT: PhysicalAddress: 0x0 | ||
| 32 | # CHECK-NEXT: FileSize: | ||
| 33 | # CHECK-NEXT: MemSize: | ||
| 34 | # CHECK-NEXT: Flags [ | ||
| 35 | # CHECK-NEXT: PF_R | ||
| 36 | # CHECK-NEXT: PF_X | ||
| 37 | # CHECK-NEXT: ] | ||
| 38 | # CHECK-NEXT: Alignment: | ||
| 39 | # CHECK-NEXT: } | ||
| 40 | # CHECK-NEXT: ProgramHeader { | ||
| 41 | # CHECK-NEXT: Type: PT_LOAD | 16 | # CHECK-NEXT: Type: PT_LOAD |
| 42 | # CHECK-NEXT: Offset: 0x1000 | 17 | # CHECK-NEXT: Offset: 0x1000 |
| 43 | # CHECK-NEXT: VirtualAddress: 0x1000 | 18 | # CHECK-NEXT: VirtualAddress: 0x1000 |
deps/lld/test/ELF/linkerscript/common-exclude.s created+86| ... | @@ -0,0 +1,86 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfile0.o | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec1.s -o %tfile1.o | ||
| 4 | # 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.script | ||
| 6 | # RUN: ld.lld -o %t1 --script %t.script %tfile0.o %tfile1.o %tfile2.o | ||
| 7 | # RUN: llvm-readobj -s -t %t1 | FileCheck %s | ||
| 8 | |||
| 9 | # 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 by | ||
| 11 | # the second in .common.excl | ||
| 12 | # CHECK: Section { | ||
| 13 | # CHECK: Index: | ||
| 14 | # CHECK: Name: .common.incl | ||
| 15 | # CHECK-NEXT: Type: SHT_NOBITS | ||
| 16 | # CHECK-NEXT: Flags [ | ||
| 17 | # CHECK-NEXT: SHF_ALLOC | ||
| 18 | # CHECK-NEXT: SHF_WRITE | ||
| 19 | # CHECK-NEXT: ] | ||
| 20 | # CHECK-NEXT: Address: 0x8 | ||
| 21 | # CHECK-NEXT: Offset: 0x | ||
| 22 | # CHECK-NEXT: Size: 16 | ||
| 23 | # CHECK-NEXT: Link: 0 | ||
| 24 | # CHECK-NEXT: Info: 0 | ||
| 25 | # CHECK-NEXT: AddressAlignment: 8 | ||
| 26 | # CHECK-NEXT: EntrySize: 0 | ||
| 27 | # CHECK-NEXT: } | ||
| 28 | # CHECK: Section { | ||
| 29 | # CHECK: Index: | ||
| 30 | # CHECK: Name: .common.excl | ||
| 31 | # CHECK-NEXT: Type: SHT_NOBITS | ||
| 32 | # CHECK-NEXT: Flags [ | ||
| 33 | # CHECK-NEXT: SHF_ALLOC | ||
| 34 | # CHECK-NEXT: SHF_WRITE | ||
| 35 | # CHECK-NEXT: ] | ||
| 36 | # CHECK-NEXT: Address: 0x20 | ||
| 37 | # CHECK-NEXT: Offset: 0x | ||
| 38 | # CHECK-NEXT: Size: 48 | ||
| 39 | # CHECK-NEXT: Link: 0 | ||
| 40 | # CHECK-NEXT: Info: 0 | ||
| 41 | # CHECK-NEXT: AddressAlignment: 16 | ||
| 42 | # CHECK-NEXT: EntrySize: 0 | ||
| 43 | # CHECK-NEXT: } | ||
| 44 | # CHECK: Symbol { | ||
| 45 | # CHECK: Name: common_multiple | ||
| 46 | # CHECK-NEXT: Value: 0x20 | ||
| 47 | # CHECK-NEXT: Size: 32 | ||
| 48 | # CHECK-NEXT: Binding: Global | ||
| 49 | # CHECK-NEXT: Type: Object | ||
| 50 | # CHECK-NEXT: Other: 0 | ||
| 51 | # CHECK-NEXT: Section: .common.excl | ||
| 52 | # CHECK-NEXT: } | ||
| 53 | # CHECK: Symbol { | ||
| 54 | # CHECK: Name: common_uniq_0 | ||
| 55 | # CHECK-NEXT: Value: 0x8 | ||
| 56 | # CHECK-NEXT: Size: 4 | ||
| 57 | # CHECK-NEXT: Binding: Global | ||
| 58 | # CHECK-NEXT: Type: Object | ||
| 59 | # CHECK-NEXT: Other: 0 | ||
| 60 | # CHECK-NEXT: Section: .common.incl | ||
| 61 | # CHECK-NEXT: } | ||
| 62 | # CHECK: Symbol { | ||
| 63 | # CHECK: Name: common_uniq_1 | ||
| 64 | # CHECK-NEXT: Value: 0x10 | ||
| 65 | # CHECK-NEXT: Size: 8 | ||
| 66 | # CHECK-NEXT: Binding: Global | ||
| 67 | # CHECK-NEXT: Type: Object | ||
| 68 | # CHECK-NEXT: Other: 0 | ||
| 69 | # CHECK-NEXT: Section: .common.incl | ||
| 70 | # CHECK-NEXT: } | ||
| 71 | # CHECK: Symbol { | ||
| 72 | # CHECK: Name: common_uniq_2 | ||
| 73 | # CHECK-NEXT: Value: 0x40 | ||
| 74 | # CHECK-NEXT: Size: 16 | ||
| 75 | # CHECK-NEXT: Binding: Global | ||
| 76 | # CHECK-NEXT: Type: Object | ||
| 77 | # CHECK-NEXT: Other: 0 | ||
| 78 | # CHECK-NEXT: Section: .common.excl | ||
| 79 | # CHECK-NEXT: } | ||
| 80 | |||
| 81 | .globl _start | ||
| 82 | _start: | ||
| 83 | jmp _start | ||
| 84 | |||
| 85 | .comm common_uniq_0,4,4 | ||
| 86 | .comm common_multiple,8,8 | ||
deps/lld/test/ELF/linkerscript/common-filespec.s created+105| ... | @@ -0,0 +1,105 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfile0.o | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec1.s -o %tfile1.o | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec2.s -o %tfile2.o | ||
| 5 | # RUN: echo "SECTIONS { .common_0 : { *file0.o(COMMON) } .common_1 : { *file1.o(COMMON) } .common_2 : { *file2.o(COMMON) } }" > %t.script | ||
| 6 | # RUN: ld.lld -o %t1 --script %t.script %tfile0.o %tfile1.o %tfile2.o | ||
| 7 | # RUN: llvm-readobj -s -t %t1 | FileCheck %s | ||
| 8 | |||
| 9 | # Make sure all 3 sections are allocated and they have sizes and alignments | ||
| 10 | # corresponding to the commons assigned to them | ||
| 11 | # CHECK: Section { | ||
| 12 | # CHECK: Index: | ||
| 13 | # CHECK: Name: .common_0 | ||
| 14 | # CHECK-NEXT: Type: SHT_NOBITS | ||
| 15 | # CHECK-NEXT: Flags [ | ||
| 16 | # CHECK-NEXT: SHF_ALLOC | ||
| 17 | # CHECK-NEXT: SHF_WRITE | ||
| 18 | # CHECK-NEXT: ] | ||
| 19 | # CHECK-NEXT: Address: 0x4 | ||
| 20 | # CHECK-NEXT: Offset: 0x | ||
| 21 | # CHECK-NEXT: Size: 4 | ||
| 22 | # CHECK-NEXT: Link: 0 | ||
| 23 | # CHECK-NEXT: Info: 0 | ||
| 24 | # CHECK-NEXT: AddressAlignment: 4 | ||
| 25 | # CHECK-NEXT: EntrySize: 0 | ||
| 26 | # CHECK-NEXT: } | ||
| 27 | # CHECK: Section { | ||
| 28 | # CHECK: Index: | ||
| 29 | # CHECK: Name: .common_1 | ||
| 30 | # CHECK-NEXT: Type: SHT_NOBITS | ||
| 31 | # CHECK-NEXT: Flags [ | ||
| 32 | # CHECK-NEXT: SHF_ALLOC | ||
| 33 | # CHECK-NEXT: SHF_WRITE | ||
| 34 | # CHECK-NEXT: ] | ||
| 35 | # CHECK-NEXT: Address: 0x8 | ||
| 36 | # CHECK-NEXT: Offset: 0x | ||
| 37 | # CHECK-NEXT: Size: 8 | ||
| 38 | # CHECK-NEXT: Link: 0 | ||
| 39 | # CHECK-NEXT: Info: 0 | ||
| 40 | # CHECK-NEXT: AddressAlignment: 8 | ||
| 41 | # CHECK-NEXT: EntrySize: 0 | ||
| 42 | # CHECK-NEXT: } | ||
| 43 | # CHECK: Section { | ||
| 44 | # CHECK: Index: | ||
| 45 | # CHECK: Name: .common_2 | ||
| 46 | # CHECK-NEXT: Type: SHT_NOBITS | ||
| 47 | # CHECK-NEXT: Flags [ | ||
| 48 | # CHECK-NEXT: SHF_ALLOC | ||
| 49 | # CHECK-NEXT: SHF_WRITE | ||
| 50 | # CHECK-NEXT: ] | ||
| 51 | # CHECK-NEXT: Address: 0x10 | ||
| 52 | # CHECK-NEXT: Offset: 0x | ||
| 53 | # CHECK-NEXT: Size: 48 | ||
| 54 | # CHECK-NEXT: Link: 0 | ||
| 55 | # CHECK-NEXT: Info: 0 | ||
| 56 | # CHECK-NEXT: AddressAlignment: 16 | ||
| 57 | # CHECK-NEXT: EntrySize: 0 | ||
| 58 | # CHECK-NEXT: } | ||
| 59 | |||
| 60 | # Commons with unique name in each file must be assigned to that file's section. | ||
| 61 | # For a common with multiple definitions, the largest one wins and it must be | ||
| 62 | # assigned to the section from the file which provided the winning def | ||
| 63 | # CHECK: Symbol { | ||
| 64 | # CHECK: Name: common_multiple | ||
| 65 | # CHECK-NEXT: Value: 0x10 | ||
| 66 | # CHECK-NEXT: Size: 32 | ||
| 67 | # CHECK-NEXT: Binding: Global | ||
| 68 | # CHECK-NEXT: Type: Object | ||
| 69 | # CHECK-NEXT: Other: 0 | ||
| 70 | # CHECK-NEXT: Section: .common_2 | ||
| 71 | # CHECK-NEXT: } | ||
| 72 | # CHECK: Symbol { | ||
| 73 | # CHECK: Name: common_uniq_0 | ||
| 74 | # CHECK-NEXT: Value: 0x4 | ||
| 75 | # CHECK-NEXT: Size: 4 | ||
| 76 | # CHECK-NEXT: Binding: Global | ||
| 77 | # CHECK-NEXT: Type: Object | ||
| 78 | # CHECK-NEXT: Other: 0 | ||
| 79 | # CHECK-NEXT: Section: .common_0 | ||
| 80 | # CHECK-NEXT: } | ||
| 81 | # CHECK: Symbol { | ||
| 82 | # CHECK: Name: common_uniq_1 | ||
| 83 | # CHECK-NEXT: Value: 0x8 | ||
| 84 | # CHECK-NEXT: Size: 8 | ||
| 85 | # CHECK-NEXT: Binding: Global | ||
| 86 | # CHECK-NEXT: Type: Object | ||
| 87 | # CHECK-NEXT: Other: 0 | ||
| 88 | # CHECK-NEXT: Section: .common_1 | ||
| 89 | # CHECK-NEXT: } | ||
| 90 | # CHECK: Symbol { | ||
| 91 | # CHECK: Name: common_uniq_2 | ||
| 92 | # CHECK-NEXT: Value: 0x30 | ||
| 93 | # CHECK-NEXT: Size: 16 | ||
| 94 | # CHECK-NEXT: Binding: Global | ||
| 95 | # CHECK-NEXT: Type: Object | ||
| 96 | # CHECK-NEXT: Other: 0 | ||
| 97 | # CHECK-NEXT: Section: .common_2 | ||
| 98 | # CHECK-NEXT: } | ||
| 99 | |||
| 100 | .globl _start | ||
| 101 | _start: | ||
| 102 | jmp _start | ||
| 103 | |||
| 104 | .comm common_uniq_0,4,4 | ||
| 105 | .comm common_multiple,8,8 | ||
deps/lld/test/ELF/linkerscript/common.s+3-5| ... | @@ -4,8 +4,6 @@ | ... | @@ -4,8 +4,6 @@ |
| 4 | # RUN: ld.lld -o %t1 --script %t.script %t | 4 | # RUN: ld.lld -o %t1 --script %t.script %t |
| 5 | # RUN: llvm-readobj -s -t %t1 | FileCheck %s | 5 | # RUN: llvm-readobj -s -t %t1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # q2 alignment is greater than q1, so it should have smaller offset | ||
| 8 | # because of sorting | ||
| 9 | # CHECK: Section { | 7 | # CHECK: Section { |
| 10 | # CHECK: Index: | 8 | # CHECK: Index: |
| 11 | # CHECK: Name: .common | 9 | # CHECK: Name: .common |
| ... | @@ -16,7 +14,7 @@ | ... | @@ -16,7 +14,7 @@ |
| 16 | # CHECK-NEXT: ] | 14 | # CHECK-NEXT: ] |
| 17 | # CHECK-NEXT: Address: 0x200 | 15 | # CHECK-NEXT: Address: 0x200 |
| 18 | # CHECK-NEXT: Offset: 0x | 16 | # CHECK-NEXT: Offset: 0x |
| 19 | # CHECK-NEXT: Size: 256 | 17 | # CHECK-NEXT: Size: 384 |
| 20 | # CHECK-NEXT: Link: 0 | 18 | # CHECK-NEXT: Link: 0 |
| 21 | # CHECK-NEXT: Info: 0 | 19 | # CHECK-NEXT: Info: 0 |
| 22 | # CHECK-NEXT: AddressAlignment: 256 | 20 | # CHECK-NEXT: AddressAlignment: 256 |
| ... | @@ -24,7 +22,7 @@ | ... | @@ -24,7 +22,7 @@ |
| 24 | # CHECK-NEXT: } | 22 | # CHECK-NEXT: } |
| 25 | # CHECK: Symbol { | 23 | # CHECK: Symbol { |
| 26 | # CHECK: Name: q1 | 24 | # CHECK: Name: q1 |
| 27 | # CHECK-NEXT: Value: 0x280 | 25 | # CHECK-NEXT: Value: 0x200 |
| 28 | # CHECK-NEXT: Size: 128 | 26 | # CHECK-NEXT: Size: 128 |
| 29 | # CHECK-NEXT: Binding: Global | 27 | # CHECK-NEXT: Binding: Global |
| 30 | # CHECK-NEXT: Type: Object | 28 | # CHECK-NEXT: Type: Object |
| ... | @@ -33,7 +31,7 @@ | ... | @@ -33,7 +31,7 @@ |
| 33 | # CHECK-NEXT: } | 31 | # CHECK-NEXT: } |
| 34 | # CHECK-NEXT: Symbol { | 32 | # CHECK-NEXT: Symbol { |
| 35 | # CHECK-NEXT: Name: q2 | 33 | # CHECK-NEXT: Name: q2 |
| 36 | # CHECK-NEXT: Value: 0x200 | 34 | # CHECK-NEXT: Value: 0x300 |
| 37 | # CHECK-NEXT: Size: 128 | 35 | # CHECK-NEXT: Size: 128 |
| 38 | # CHECK-NEXT: Binding: Global | 36 | # CHECK-NEXT: Binding: Global |
| 39 | # CHECK-NEXT: Type: Object | 37 | # CHECK-NEXT: Type: Object |
deps/lld/test/ELF/linkerscript/compress-debug-sections-custom.s created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | # REQUIRES: x86, zlib | ||
| 2 | |||
| 3 | # RUN: echo "SECTIONS { \ | ||
| 4 | # RUN: .text : { . += 0x10; *(.text) } \ | ||
| 5 | # RUN: .debug_str : { . += 0x10; *(.debug_str) } \ | ||
| 6 | # RUN: .debug_info : { . += 0x10; *(.debug_info) } \ | ||
| 7 | # RUN: }" > %t.script | ||
| 8 | |||
| 9 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 10 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/../Inputs/compress-debug.s -o %t2.o | ||
| 11 | # RUN: ld.lld %t2.o %t.o -o %t1 --compress-debug-sections=zlib -T %t.script | ||
| 12 | # RUN: llvm-dwarfdump %t1 -debug-str | FileCheck %s | ||
| 13 | # These two checks correspond to the patched values of a_sym and a_debug_sym. | ||
| 14 | # T = 0x54 - address of .text input section for this file (the start address of | ||
| 15 | # .text is 0 by default, the size of the preceding .text in the other input | ||
| 16 | #	 file is 0x44, and the linker script adds an additional 0x10). | ||
| 17 | # S = 0x53 - offset of .debug_info section for this file (the size of | ||
| 18 | # the preceding .debug_info from the other input file is 0x43, and the | ||
| 19 | #	 linker script adds an additional 0x10). | ||
| 20 | # Also note that the .debug_str offsets are also offset by 0x10, as directed by | ||
| 21 | # the linker script. | ||
| 22 | # CHECK: 0x00000010: "T" | ||
| 23 | # CHECK: 0x00000014: "S" | ||
| 24 | |||
| 25 | .text | ||
| 26 | a_sym: | ||
| 27 | nop | ||
| 28 | |||
| 29 | .section .debug_str,"",@progbits | ||
| 30 | .long a_sym | ||
| 31 | .long a_debug_sym | ||
| 32 | |||
| 33 | .section .debug_info,"",@progbits | ||
| 34 | a_debug_sym: | ||
| 35 | .long 0x88776655 | ||
deps/lld/test/ELF/linkerscript/compress-debug-sections.s+2-2| ... | @@ -10,12 +10,12 @@ | ... | @@ -10,12 +10,12 @@ |
| 10 | 10 | ||
| 11 | # RUN: echo "SECTIONS { }" > %t.script | 11 | # RUN: echo "SECTIONS { }" > %t.script |
| 12 | # RUN: ld.lld -O0 %t1.o %t2.o %t.script -o %t1 --compress-debug-sections=zlib | 12 | # RUN: ld.lld -O0 %t1.o %t2.o %t.script -o %t1 --compress-debug-sections=zlib |
| 13 | # RUN: llvm-dwarfdump %t1 | FileCheck %s | 13 | # RUN: llvm-dwarfdump -a %t1 | FileCheck %s |
| 14 | # RUN: llvm-readobj -s %t1 | FileCheck %s --check-prefix=ZLIBFLAGS | 14 | # RUN: llvm-readobj -s %t1 | FileCheck %s --check-prefix=ZLIBFLAGS |
| 15 | 15 | ||
| 16 | # RUN: echo "SECTIONS { .debug_str 0 : { *(.debug_str) } }" > %t2.script | 16 | # 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=zlib | 17 | # RUN: ld.lld -O0 %t1.o %t2.o %t2.script -o %t2 --compress-debug-sections=zlib |
| 18 | # RUN: llvm-dwarfdump %t2 | FileCheck %s | 18 | # RUN: llvm-dwarfdump -a %t2 | FileCheck %s |
| 19 | # RUN: llvm-readobj -s %t2 | FileCheck %s --check-prefix=ZLIBFLAGS | 19 | # RUN: llvm-readobj -s %t2 | FileCheck %s --check-prefix=ZLIBFLAGS |
| 20 | 20 | ||
| 21 | # CHECK: .debug_str contents: | 21 | # CHECK: .debug_str contents: |
deps/lld/test/ELF/linkerscript/copy-rel-symbol-value-err.s created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/copy-rel-symbol-value.s -o %t2.o | ||
| 4 | # RUN: ld.lld %t2.o -o %t2.so -shared | ||
| 5 | # RUN: echo "SECTIONS { . = . + SIZEOF_HEADERS; foo = bar; }" > %t.script | ||
| 6 | # RUN: not ld.lld %t.o %t2.so --script %t.script -o %t 2>&1 | FileCheck %s | ||
| 7 | |||
| 8 | # CHECK: symbol not found: bar | ||
| 9 | |||
| 10 | .global _start | ||
| 11 | _start: | ||
| 12 | .quad bar@got | ||
deps/lld/test/ELF/linkerscript/copy-rel-symbol-value.s created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/copy-rel-symbol-value.s -o %t2.o | ||
| 4 | # RUN: ld.lld %t2.o -o %t2.so -shared | ||
| 5 | # RUN: echo "SECTIONS { . = . + SIZEOF_HEADERS; foo = bar; }" > %t.script | ||
| 6 | # RUN: ld.lld %t.o %t2.so --script %t.script -o %t | ||
| 7 | # RUN: llvm-readobj -t %t | FileCheck %s | ||
| 8 | |||
| 9 | # CHECK: Name: bar | ||
| 10 | # CHECK-NEXT: Value: 0x[[VAL:.*]] | ||
| 11 | # CHECK-NEXT: Size: 8 | ||
| 12 | # CHECK-NEXT: Binding: Global | ||
| 13 | # CHECK-NEXT: Type: Object | ||
| 14 | # CHECK-NEXT: Other: 0 | ||
| 15 | # CHECK-NEXT: Section: .bss.rel.ro | ||
| 16 | |||
| 17 | # CHECK: Name: foo | ||
| 18 | # CHECK-NEXT: Value: 0x[[VAL]] | ||
| 19 | # CHECK-NEXT: Size: | ||
| 20 | # CHECK-NEXT: Binding: Global | ||
| 21 | # CHECK-NEXT: Type: | ||
| 22 | # CHECK-NEXT: Other: 0 | ||
| 23 | # CHECK-NEXT: Section: .bss.rel.ro | ||
| 24 | |||
| 25 | .global _start | ||
| 26 | _start: | ||
| 27 | .quad bar | ||
deps/lld/test/ELF/linkerscript/data-commands.s+36| ... | @@ -44,6 +44,42 @@ | ... | @@ -44,6 +44,42 @@ |
| 44 | # BE-NEXT: ff12ff11 22ff1122 3346ff11 22334455 | 44 | # BE-NEXT: ff12ff11 22ff1122 3346ff11 22334455 |
| 45 | # BE-NEXT: 667788 | 45 | # BE-NEXT: 667788 |
| 46 | 46 | ||
| 47 | # RUN: echo "MEMORY { \ | ||
| 48 | # RUN: rom (rwx) : ORIGIN = 0x00, LENGTH = 2K \ | ||
| 49 | # RUN: } \ | ||
| 50 | # RUN: SECTIONS { \ | ||
| 51 | # RUN: .foo : { \ | ||
| 52 | # RUN: *(.foo.1) \ | ||
| 53 | # RUN: BYTE(0x11) \ | ||
| 54 | # RUN: *(.foo.2) \ | ||
| 55 | # RUN: SHORT(0x1122) \ | ||
| 56 | # RUN: *(.foo.3) \ | ||
| 57 | # RUN: LONG(0x11223344) \ | ||
| 58 | # RUN: *(.foo.4) \ | ||
| 59 | # RUN: QUAD(0x1122334455667788) \ | ||
| 60 | # RUN: } > rom \ | ||
| 61 | # RUN: .bar : { \ | ||
| 62 | # RUN: *(.bar.1) \ | ||
| 63 | # RUN: BYTE(a + 1) \ | ||
| 64 | # RUN: *(.bar.2) \ | ||
| 65 | # RUN: SHORT(b) \ | ||
| 66 | # RUN: *(.bar.3) \ | ||
| 67 | # RUN: LONG(c + 2) \ | ||
| 68 | # RUN: *(.bar.4) \ | ||
| 69 | # RUN: QUAD(d) \ | ||
| 70 | # RUN: } > rom \ | ||
| 71 | # RUN: }" > %t-memory.script | ||
| 72 | # RUN: ld.lld -o %t-memory %t.o --script %t-memory.script | ||
| 73 | # RUN: llvm-objdump -s %t-memory | FileCheck %s --check-prefix=MEM | ||
| 74 | |||
| 75 | # MEM: Contents of section .foo: | ||
| 76 | # MEM-NEXT: 0000 ff11ff22 11ff4433 2211ff88 77665544 | ||
| 77 | # MEM-NEXT: 0010 332211 | ||
| 78 | |||
| 79 | # MEM: Contents of section .bar: | ||
| 80 | # MEM-NEXT: 0013 ff12ff22 11ff4633 2211ff88 77665544 | ||
| 81 | # MEM-NEXT: 0023 332211 | ||
| 82 | |||
| 47 | .global a | 83 | .global a |
| 48 | a = 0x11 | 84 | a = 0x11 |
| 49 | 85 |
deps/lld/test/ELF/linkerscript/data-segment-relro.s+2-2| ... | @@ -19,9 +19,9 @@ | ... | @@ -19,9 +19,9 @@ |
| 19 | 19 | ||
| 20 | ## With relro or without DATA_SEGMENT_RELRO_END just aligns to | 20 | ## With relro or without DATA_SEGMENT_RELRO_END just aligns to |
| 21 | ## page boundary. | 21 | ## page boundary. |
| 22 | # RUN: ld.lld -z norelro %t1.o %t2.so --script %t.script -o %t | 22 | # RUN: ld.lld --hash-style=sysv -z norelro %t1.o %t2.so --script %t.script -o %t |
| 23 | # RUN: llvm-readobj -s %t | FileCheck %s | 23 | # RUN: llvm-readobj -s %t | FileCheck %s |
| 24 | # RUN: ld.lld -z relro %t1.o %t2.so --script %t.script -o %t2 | 24 | # RUN: ld.lld --hash-style=sysv -z relro %t1.o %t2.so --script %t.script -o %t2 |
| 25 | # RUN: llvm-readobj -s %t2 | FileCheck %s | 25 | # RUN: llvm-readobj -s %t2 | FileCheck %s |
| 26 | 26 | ||
| 27 | # CHECK: Section { | 27 | # CHECK: Section { |
deps/lld/test/ELF/linkerscript/diagnostic.s+7-7| ... | @@ -50,9 +50,9 @@ | ... | @@ -50,9 +50,9 @@ |
| 50 | # RUN: echo ".temp : { *(.temp) } }" >> %t.script | 50 | # RUN: echo ".temp : { *(.temp) } }" >> %t.script |
| 51 | # RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ | 51 | # RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ |
| 52 | # RUN: FileCheck -check-prefix=ERR6 -strict-whitespace %s | 52 | # RUN: FileCheck -check-prefix=ERR6 -strict-whitespace %s |
| 53 | # ERR6: error: {{.*}}.script:1: | 53 | # ERR6: error: {{.*}}.script:1: unknown directive: UNKNOWN_TAG |
| 54 | # ERR6-NEXT: error: {{.*}}.script:1: UNKNOWN_TAG { | 54 | # ERR6-NEXT: >>> UNKNOWN_TAG { |
| 55 | # ERR6-NEXT: error: {{.*}}.script:1: ^ | 55 | # ERR6-NEXT: >>> ^ |
| 56 | 56 | ||
| 57 | ## One more check that text of lines and pointer to 'bad' token are working ok. | 57 | ## One more check that text of lines and pointer to 'bad' token are working ok. |
| 58 | # RUN: echo "SECTIONS {" > %t.script | 58 | # RUN: echo "SECTIONS {" > %t.script |
| ... | @@ -62,8 +62,8 @@ | ... | @@ -62,8 +62,8 @@ |
| 62 | # RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ | 62 | # RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ |
| 63 | # RUN: FileCheck -check-prefix=ERR7 -strict-whitespace %s | 63 | # RUN: FileCheck -check-prefix=ERR7 -strict-whitespace %s |
| 64 | # ERR7: error: {{.*}}.script:4: malformed number: .temp | 64 | # ERR7: error: {{.*}}.script:4: malformed number: .temp |
| 65 | # ERR7-NEXT: error: {{.*}}.script:4: boom .temp : { *(.temp) } } | 65 | # ERR7-NEXT: >>> boom .temp : { *(.temp) } } |
| 66 | # ERR7-NEXT: error: {{.*}}.script:4: ^ | 66 | # ERR7-NEXT: >>> ^ |
| 67 | 67 | ||
| 68 | ## Check tokenize() error | 68 | ## Check tokenize() error |
| 69 | # RUN: echo "SECTIONS {}" > %t.script | 69 | # RUN: echo "SECTIONS {}" > %t.script |
| ... | @@ -89,8 +89,8 @@ | ... | @@ -89,8 +89,8 @@ |
| 89 | # RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ | 89 | # RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | \ |
| 90 | # RUN: FileCheck -check-prefix=ERR10 -strict-whitespace %s | 90 | # RUN: FileCheck -check-prefix=ERR10 -strict-whitespace %s |
| 91 | # ERR10: error: {{.*}}.script.inc:4: malformed number: .temp | 91 | # ERR10: error: {{.*}}.script.inc:4: malformed number: .temp |
| 92 | # ERR10-NEXT: error: {{.*}}.script.inc:4: boom .temp : { *(.temp) } } | 92 | # ERR10-NEXT: >>> boom .temp : { *(.temp) } } |
| 93 | # ERR10-NEXT: error: {{.*}}.script.inc:4: ^ | 93 | # ERR10-NEXT: >>> ^ |
| 94 | 94 | ||
| 95 | ## Check error reporting in script with INCLUDE directive. | 95 | ## Check error reporting in script with INCLUDE directive. |
| 96 | # RUN: echo "SECTIONS {" > %t.script.inc | 96 | # RUN: echo "SECTIONS {" > %t.script.inc |
deps/lld/test/ELF/linkerscript/discard-section-err.s+2| ... | @@ -21,3 +21,5 @@ | ... | @@ -21,3 +21,5 @@ |
| 21 | # RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ | 21 | # RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ |
| 22 | # RUN: FileCheck -check-prefix=DYNSTR %s | 22 | # RUN: FileCheck -check-prefix=DYNSTR %s |
| 23 | # DYNSTR: discarding .dynstr section is not allowed | 23 | # DYNSTR: discarding .dynstr section is not allowed |
| 24 | |||
| 25 | .comm foo,4,4 |
deps/lld/test/ELF/linkerscript/early-assign-symbol.s+19-5| ... | @@ -1,14 +1,28 @@ | ... | @@ -1,14 +1,28 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | 3 | ||
| 4 | # RUN: echo "SECTIONS { aaa = 1 + ABSOLUTE(foo - 1); .text : { *(.text*) } }" > %t1.script | 4 | # RUN: echo "SECTIONS { aaa = foo | 1; .text : { *(.text*) } }" > %t3.script |
| 5 | # RUN: not ld.lld -o %t --script %t1.script %t.o 2>&1 | FileCheck %s | 5 | # RUN: not ld.lld -o %t --script %t3.script %t.o 2>&1 | FileCheck %s |
| 6 | |||
| 7 | # RUN: echo "SECTIONS { aaa = ABSOLUTE(foo - 1) + 1; .text : { *(.text*) } }" > %t2.script | ||
| 8 | # RUN: not ld.lld -o %t --script %t2.script %t.o 2>&1 | FileCheck %s | ||
| 9 | 6 | ||
| 10 | # CHECK: error: {{.*}}.script:1: unable to evaluate expression: input section .text has no output section assigned | 7 | # CHECK: error: {{.*}}.script:1: unable to evaluate expression: input section .text has no output section assigned |
| 11 | 8 | ||
| 9 | # Simple cases that we can handle. | ||
| 10 | |||
| 11 | # RUN: echo "SECTIONS { aaa = ABSOLUTE(foo - 1) + 1; .text : { *(.text*) } }" > %t.script | ||
| 12 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 13 | # RUN: llvm-objdump -t %t | FileCheck --check-prefix=VAL %s | ||
| 14 | |||
| 15 | # RUN: echo "SECTIONS { aaa = 1 + ABSOLUTE(foo - 1); .text : { *(.text*) } }" > %t.script | ||
| 16 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 17 | # RUN: llvm-objdump -t %t | FileCheck --check-prefix=VAL %s | ||
| 18 | |||
| 19 | # RUN: echo "SECTIONS { aaa = ABSOLUTE(foo); .text : { *(.text*) } }" > %t4.script | ||
| 20 | # RUN: ld.lld -o %t --script %t4.script %t.o | ||
| 21 | # RUN: llvm-objdump -t %t | FileCheck --check-prefix=VAL %s | ||
| 22 | |||
| 23 | # VAL: 0000000000000000 .text 00000000 foo | ||
| 24 | # VAL: 0000000000000000 *ABS* 00000000 aaa | ||
| 25 | |||
| 12 | .section .text | 26 | .section .text |
| 13 | .globl foo | 27 | .globl foo |
| 14 | foo: | 28 | foo: |
deps/lld/test/ELF/linkerscript/eh-frame-reloc-out-of-range.s+1-1| ... | @@ -12,7 +12,7 @@ | ... | @@ -12,7 +12,7 @@ |
| 12 | # RUN: }" > %t.script | 12 | # RUN: }" > %t.script |
| 13 | # RUN: not ld.lld %t.o -T %t.script -o %t 2>&1 | FileCheck %s | 13 | # RUN: not ld.lld %t.o -T %t.script -o %t 2>&1 | FileCheck %s |
| 14 | 14 | ||
| 15 | # CHECK: error: {{.*}}:(.eh_frame+0x20): relocation R_X86_64_PC32 out of range | 15 | # CHECK: error: {{.*}}:(.eh_frame+0x20): relocation R_X86_64_PC32 out of range: 64424443872 is not in [-2147483648, 2147483647] |
| 16 | 16 | ||
| 17 | 	.text | 17 | 	.text |
| 18 | .globl _start | 18 | .globl _start |
deps/lld/test/ELF/linkerscript/emit-reloc-section-names.s created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { .text.zed : { *(.text.foo) } \ | ||
| 4 | # RUN: .text.qux : { *(.text.bar) } }" > %t.script | ||
| 5 | # RUN: ld.lld -T %t.script --emit-relocs %t.o -o %t | ||
| 6 | # RUN: llvm-objdump -section-headers %t | FileCheck %s | ||
| 7 | |||
| 8 | ## Check we name relocation sections in according to | ||
| 9 | ## their target sections names. | ||
| 10 | |||
| 11 | # CHECK: .text.zed | ||
| 12 | # CHECK: .text.qux | ||
| 13 | # CHECK: .rela.text.zed | ||
| 14 | # CHECK: .rela.text.qux | ||
| 15 | |||
| 16 | .section .text.foo,"ax" | ||
| 17 | foo: | ||
| 18 | mov $bar, %rax | ||
| 19 | |||
| 20 | .section .text.bar,"ax" | ||
| 21 | bar: | ||
| 22 | mov $foo, %rax | ||
deps/lld/test/ELF/linkerscript/emit-reloc.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | # RUN: echo "SECTIONS { .rela.dyn : { *(.rela.data) } }" > %t.script | 3 | # RUN: echo "SECTIONS { .rela.dyn : { *(.rela.data) } }" > %t.script |
| 4 | # RUN: ld.lld -T %t.script --emit-relocs %t.o -o %t.so -shared | 4 | # RUN: ld.lld --hash-style=sysv -T %t.script --emit-relocs %t.o -o %t.so -shared |
| 5 | # RUN: llvm-readobj -r %t.so | FileCheck %s | 5 | # RUN: llvm-readobj -r %t.so | FileCheck %s |
| 6 | 6 | ||
| 7 | .data | 7 | .data |
deps/lld/test/ELF/linkerscript/emit-relocs-multiple.s+1-1| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | # RUN: llvm-readobj -r %t1 | FileCheck %s | 5 | # RUN: llvm-readobj -r %t1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK: Relocations [ | 7 | # CHECK: Relocations [ |
| 8 | # CHECK-NEXT: Section {{.*}} .rela.foo { | 8 | # CHECK-NEXT: Section {{.*}} .rela.zed { |
| 9 | # CHECK-NEXT: 0x1 R_X86_64_32 .zed 0x0 | 9 | # CHECK-NEXT: 0x1 R_X86_64_32 .zed 0x0 |
| 10 | # CHECK-NEXT: 0x6 R_X86_64_32 .zed 0x5 | 10 | # CHECK-NEXT: 0x6 R_X86_64_32 .zed 0x5 |
| 11 | # CHECK-NEXT: } | 11 | # CHECK-NEXT: } |
deps/lld/test/ELF/linkerscript/extend-pt-load.s+6-7| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | # RUN: . = ALIGN(0x1000); \ | 15 | # RUN: . = ALIGN(0x1000); \ |
| 16 | # RUN: .data.rel.ro : { *(.data.rel.ro) } \ | 16 | # RUN: .data.rel.ro : { *(.data.rel.ro) } \ |
| 17 | # RUN: }" > %t.script | 17 | # RUN: }" > %t.script |
| 18 | # RUN: ld.lld -o %t1 --script %t.script %t.o -shared | 18 | # RUN: ld.lld --hash-style=sysv -o %t1 --script %t.script %t.o -shared |
| 19 | # RUN: llvm-readobj --elf-output-style=GNU -l -s %t1 | FileCheck --check-prefix=CHECK1 %s | 19 | # RUN: llvm-readobj --elf-output-style=GNU -l -s %t1 | FileCheck --check-prefix=CHECK1 %s |
| 20 | 20 | ||
| 21 | # CHECK1: .text PROGBITS 00000000000001bc 0001bc 000001 00 AX | 21 | # CHECK1: .text PROGBITS 00000000000001bc 0001bc 000001 00 AX |
| ... | @@ -33,18 +33,17 @@ | ... | @@ -33,18 +33,17 @@ |
| 33 | # RUN:	.hash : { } \ | 33 | # RUN:	.hash : { } \ |
| 34 | # RUN:	.dynstr : { } \ | 34 | # RUN:	.dynstr : { } \ |
| 35 | # RUN: .text : { *(.text) } \ | 35 | # RUN: .text : { *(.text) } \ |
| 36 | # RUN: . = ALIGN(0x1000); \ | 36 | # RUN: bar : { . = ALIGN(0x1000); } \ |
| 37 | # RUN: bar : { HIDDEN(bar_sym = .); } \ | ||
| 38 | # RUN: .data.rel.ro : { *(.data.rel.ro) } \ | 37 | # RUN: .data.rel.ro : { *(.data.rel.ro) } \ |
| 39 | # RUN: }" > %t.script | 38 | # RUN: }" > %t.script |
| 40 | # RUN: ld.lld -o %t2 --script %t.script %t.o -shared | 39 | # RUN: ld.lld --hash-style=sysv -o %t2 --script %t.script %t.o -shared |
| 41 | # RUN: llvm-readobj --elf-output-style=GNU -l -s %t2 | FileCheck --check-prefix=CHECK2 %s | 40 | # RUN: llvm-readobj --elf-output-style=GNU -l -s %t2 | FileCheck --check-prefix=CHECK2 %s |
| 42 | 41 | ||
| 43 | # CHECK2: .text PROGBITS 00000000000001bc 0001bc 000001 00 AX | 42 | # CHECK2: .text PROGBITS 00000000000001bc 0001bc 000001 00 AX |
| 44 | # CHECK2-NEXT: bar PROGBITS 0000000000001000 001000 000000 00 AX | 43 | # CHECK2-NEXT: bar NOBITS 00000000000001bd 0001bd 000e43 00 AX |
| 45 | # CHECK2-NEXT: .data.rel.ro PROGBITS 0000000000001000 001000 000001 00 WA | 44 | # CHECK2-NEXT: .data.rel.ro PROGBITS 0000000000001000 001000 000001 00 WA |
| 46 | 45 | ||
| 47 | # CHECK2: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x001000 0x001000 R E | 46 | # CHECK2: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0001bd 0x001000 R E |
| 48 | # CHECK2-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000068 0x000068 RW | 47 | # CHECK2-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000068 0x000068 RW |
| 49 | 48 | ||
| 50 | # If the current behavior becomes a problem we should consider just moving the commands out | 49 | # If the current behavior becomes a problem we should consider just moving the commands out |
| ... | @@ -60,7 +59,7 @@ | ... | @@ -60,7 +59,7 @@ |
| 60 | # RUN: HIDDEN(bar_sym = .); \ | 59 | # RUN: HIDDEN(bar_sym = .); \ |
| 61 | # RUN: .data.rel.ro : { *(.data.rel.ro) } \ | 60 | # RUN: .data.rel.ro : { *(.data.rel.ro) } \ |
| 62 | # RUN: }" > %t.script | 61 | # RUN: }" > %t.script |
| 63 | # RUN: ld.lld -o %t3 --script %t.script %t.o -shared | 62 | # RUN: ld.lld --hash-style=sysv -o %t3 --script %t.script %t.o -shared |
| 64 | # RUN: llvm-readobj --elf-output-style=GNU -l -s %t3 | FileCheck --check-prefix=CHECK1 %s | 63 | # RUN: llvm-readobj --elf-output-style=GNU -l -s %t3 | FileCheck --check-prefix=CHECK1 %s |
| 65 | 64 | ||
| 66 | nop | 65 | nop |
deps/lld/test/ELF/linkerscript/filename-spec.s+43-4| ... | @@ -33,24 +33,63 @@ | ... | @@ -33,24 +33,63 @@ |
| 33 | # RUN: ld.lld -o %t4 --script %t4.script %tfirst.o %tsecond.o | 33 | # RUN: ld.lld -o %t4 --script %t4.script %tfirst.o %tsecond.o |
| 34 | # RUN: llvm-objdump -s %t4 | FileCheck --check-prefix=SECONDFIRST %s | 34 | # RUN: llvm-objdump -s %t4 | FileCheck --check-prefix=SECONDFIRST %s |
| 35 | 35 | ||
| 36 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %T/filename-spec1.o | 36 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o filename-spec1.o |
| 37 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ | 37 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ |
| 38 | # RUN: %p/Inputs/filename-spec.s -o %T/filename-spec2.o | 38 | # RUN: %p/Inputs/filename-spec.s -o filename-spec2.o |
| 39 | 39 | ||
| 40 | # RUN: echo "SECTIONS { .foo : { \ | 40 | # RUN: echo "SECTIONS { .foo : { \ |
| 41 | # RUN: filename-spec2.o(.foo) \ | 41 | # RUN: filename-spec2.o(.foo) \ |
| 42 | # RUN: filename-spec1.o(.foo) } }" > %t5.script | 42 | # RUN: filename-spec1.o(.foo) } }" > %t5.script |
| 43 | # RUN: ld.lld -o %t5 --script %t5.script \ | 43 | # RUN: ld.lld -o %t5 --script %t5.script \ |
| 44 | # RUN: %T/filename-spec1.o %T/filename-spec2.o | 44 | # RUN: filename-spec1.o filename-spec2.o |
| 45 | # RUN: llvm-objdump -s %t5 | FileCheck --check-prefix=SECONDFIRST %s | 45 | # RUN: llvm-objdump -s %t5 | FileCheck --check-prefix=SECONDFIRST %s |
| 46 | 46 | ||
| 47 | # RUN: echo "SECTIONS { .foo : { \ | 47 | # RUN: echo "SECTIONS { .foo : { \ |
| 48 | # RUN: filename-spec1.o(.foo) \ | 48 | # RUN: filename-spec1.o(.foo) \ |
| 49 | # RUN: filename-spec2.o(.foo) } }" > %t6.script | 49 | # RUN: filename-spec2.o(.foo) } }" > %t6.script |
| 50 | # RUN: ld.lld -o %t6 --script %t6.script \ | 50 | # RUN: ld.lld -o %t6 --script %t6.script \ |
| 51 | # RUN: %T/filename-spec1.o %T/filename-spec2.o | 51 | # RUN: filename-spec1.o filename-spec2.o |
| 52 | # RUN: llvm-objdump -s %t6 | FileCheck --check-prefix=FIRSTSECOND %s | 52 | # RUN: llvm-objdump -s %t6 | FileCheck --check-prefix=FIRSTSECOND %s |
| 53 | 53 | ||
| 54 | # RUN: mkdir -p %t.testdir1 %t.testdir2 | ||
| 55 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.testdir1/filename-spec1.o | ||
| 56 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ | ||
| 57 | # RUN: %p/Inputs/filename-spec.s -o %t.testdir2/filename-spec2.o | ||
| 58 | # RUN: llvm-ar rsc %t.testdir1/lib1.a %t.testdir1/filename-spec1.o | ||
| 59 | # RUN: llvm-ar rsc %t.testdir2/lib2.a %t.testdir2/filename-spec2.o | ||
| 60 | |||
| 61 | # Verify matching of archive library names. | ||
| 62 | # RUN: echo "SECTIONS { .foo : { \ | ||
| 63 | # RUN: *lib2*(.foo) \ | ||
| 64 | # RUN: *lib1*(.foo) } }" > %t7.script | ||
| 65 | # RUN: ld.lld -o %t7 --script %t7.script --whole-archive \ | ||
| 66 | # RUN: %t.testdir1/lib1.a %t.testdir2/lib2.a | ||
| 67 | # RUN: llvm-objdump -s %t7 | FileCheck --check-prefix=SECONDFIRST %s | ||
| 68 | |||
| 69 | # Verify matching directories. | ||
| 70 | # RUN: echo "SECTIONS { .foo : { \ | ||
| 71 | # RUN: *testdir2*(.foo) \ | ||
| 72 | # RUN: *testdir1*(.foo) } }" > %t8.script | ||
| 73 | # RUN: ld.lld -o %t8 --script %t8.script --whole-archive \ | ||
| 74 | # RUN: %t.testdir1/lib1.a %t.testdir2/lib2.a | ||
| 75 | # RUN: llvm-objdump -s %t8 | FileCheck --check-prefix=SECONDFIRST %s | ||
| 76 | |||
| 77 | # Verify matching of archive library names in KEEP. | ||
| 78 | # RUN: echo "SECTIONS { .foo : { \ | ||
| 79 | # RUN: KEEP(*lib2*(.foo)) \ | ||
| 80 | # RUN: KEEP(*lib1*(.foo)) } }" > %t9.script | ||
| 81 | # RUN: ld.lld -o %t9 --script %t9.script --whole-archive \ | ||
| 82 | # RUN: %t.testdir1/lib1.a %t.testdir2/lib2.a | ||
| 83 | # RUN: llvm-objdump -s %t9 | FileCheck --check-prefix=SECONDFIRST %s | ||
| 84 | |||
| 85 | # Verify matching directories in KEEP. | ||
| 86 | # RUN: echo "SECTIONS { .foo : { \ | ||
| 87 | # RUN: KEEP(*testdir2*(.foo)) \ | ||
| 88 | # RUN: KEEP(*testdir1*(.foo)) } }" > %t10.script | ||
| 89 | # RUN: ld.lld -o %t10 --script %t10.script --whole-archive \ | ||
| 90 | # RUN: %t.testdir1/lib1.a %t.testdir2/lib2.a | ||
| 91 | # RUN: llvm-objdump -s %t10 | FileCheck --check-prefix=SECONDFIRST %s | ||
| 92 | |||
| 54 | .global _start | 93 | .global _start |
| 55 | _start: | 94 | _start: |
| 56 | nop | 95 | nop |
deps/lld/test/ELF/linkerscript/header-addr.s+11-11| ... | @@ -2,20 +2,20 @@ | ... | @@ -2,20 +2,20 @@ |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | # RUN: echo "PHDRS {all PT_LOAD PHDRS;} \ | 3 | # RUN: echo "PHDRS {all PT_LOAD PHDRS;} \ |
| 4 | # RUN: SECTIONS { \ | 4 | # RUN: SECTIONS { \ |
| 5 | # RUN: . = 0x2000; \ | 5 | # RUN: . = 0x2000 + SIZEOF_HEADERS; \ |
| 6 | # RUN: .text : {*(.text)} :all \ | 6 | # RUN: .text : {*(.text)} :all \ |
| 7 | # RUN: }" > %t.script | 7 | # RUN: }" > %t.script |
| 8 | # RUN: ld.lld -o %t.so --script %t.script %t.o -shared | 8 | # RUN: ld.lld --hash-style=sysv -o %t.so --script %t.script %t.o -shared |
| 9 | # RUN: llvm-readobj -program-headers %t.so | FileCheck %s | 9 | # RUN: llvm-readobj -program-headers %t.so | FileCheck %s |
| 10 | 10 | ||
| 11 | # CHECK: ProgramHeaders [ | 11 | # CHECK: ProgramHeaders [ |
| 12 | # CHECK-NEXT: ProgramHeader { | 12 | # CHECK-NEXT: ProgramHeader { |
| 13 | # CHECK-NEXT: Type: PT_LOAD | 13 | # CHECK-NEXT: Type: PT_LOAD |
| 14 | # CHECK-NEXT: Offset: 0x40 | 14 | # CHECK-NEXT: Offset: 0x40 |
| 15 | # CHECK-NEXT: VirtualAddress: 0x1040 | 15 | # CHECK-NEXT: VirtualAddress: 0x2040 |
| 16 | # CHECK-NEXT: PhysicalAddress: 0x1040 | 16 | # CHECK-NEXT: PhysicalAddress: 0x2040 |
| 17 | # CHECK-NEXT: FileSize: 4176 | 17 | # CHECK-NEXT: FileSize: 200 |
| 18 | # CHECK-NEXT: MemSize: 4176 | 18 | # CHECK-NEXT: MemSize: 200 |
| 19 | # CHECK-NEXT: Flags [ | 19 | # CHECK-NEXT: Flags [ |
| 20 | # CHECK-NEXT: PF_R (0x4) | 20 | # CHECK-NEXT: PF_R (0x4) |
| 21 | # CHECK-NEXT: PF_W (0x2) | 21 | # CHECK-NEXT: PF_W (0x2) |
| ... | @@ -25,7 +25,7 @@ | ... | @@ -25,7 +25,7 @@ |
| 25 | # CHECK-NEXT: } | 25 | # CHECK-NEXT: } |
| 26 | # CHECK-NEXT: ] | 26 | # CHECK-NEXT: ] |
| 27 | 27 | ||
| 28 | # RUN: ld.lld -o %t2.so --script %t.script %t.o -shared -z max-page-size=0x2000 | 28 | # RUN: ld.lld --hash-style=sysv -o %t2.so --script %t.script %t.o -shared -z max-page-size=0x2000 |
| 29 | # RUN: llvm-readobj -program-headers %t2.so \ | 29 | # RUN: llvm-readobj -program-headers %t2.so \ |
| 30 | # RUN: | FileCheck --check-prefix=MAXPAGE %s | 30 | # RUN: | FileCheck --check-prefix=MAXPAGE %s |
| 31 | 31 | ||
| ... | @@ -33,10 +33,10 @@ | ... | @@ -33,10 +33,10 @@ |
| 33 | # MAXPAGE-NEXT: ProgramHeader { | 33 | # MAXPAGE-NEXT: ProgramHeader { |
| 34 | # MAXPAGE-NEXT: Type: PT_LOAD | 34 | # MAXPAGE-NEXT: Type: PT_LOAD |
| 35 | # MAXPAGE-NEXT: Offset: 0x40 | 35 | # MAXPAGE-NEXT: Offset: 0x40 |
| 36 | # MAXPAGE-NEXT: VirtualAddress: 0x40 | 36 | # MAXPAGE-NEXT: VirtualAddress: 0x2040 |
| 37 | # MAXPAGE-NEXT: PhysicalAddress: 0x40 | 37 | # MAXPAGE-NEXT: PhysicalAddress: 0x2040 |
| 38 | # MAXPAGE-NEXT: FileSize: 8272 | 38 | # MAXPAGE-NEXT: FileSize: 200 |
| 39 | # MAXPAGE-NEXT: MemSize: 8272 | 39 | # MAXPAGE-NEXT: MemSize: 200 |
| 40 | # MAXPAGE-NEXT: Flags [ | 40 | # MAXPAGE-NEXT: Flags [ |
| 41 | # MAXPAGE-NEXT: PF_R | 41 | # MAXPAGE-NEXT: PF_R |
| 42 | # MAXPAGE-NEXT: PF_W | 42 | # MAXPAGE-NEXT: PF_W |
deps/lld/test/ELF/linkerscript/header-phdr.s created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: echo "PHDRS { foobar PT_LOAD FILEHDR PHDRS; } \ | ||
| 4 | # RUN: SECTIONS { . = 0x1000; .abc : { *(.zed) } : foobar }" > %t.script | ||
| 5 | # RUN: ld.lld --script %t.script %t.o -o %t | ||
| 6 | # RUN: llvm-readelf -l -S -W %t | FileCheck %s | ||
| 7 | |||
| 8 | .section .zed, "a" | ||
| 9 | .zero 4 | ||
| 10 | |||
| 11 | |||
| 12 | # CHECK: [ 1] .abc PROGBITS 0000000000001000 001000 000004 00 A 0 0 1 | ||
| 13 | # CHECK: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x001004 0x001004 R E 0x1000 | ||
deps/lld/test/ELF/linkerscript/image-base.s created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 4 | # RUN: echo "SECTIONS { mysym = .; }" > %t.script | ||
| 5 | |||
| 6 | # RUN: ld.lld %t.o -o %t-default.elf -T %t.script | ||
| 7 | # RUN: llvm-readobj --symbols %t-default.elf | FileCheck %s --check-prefix=DEFAULT | ||
| 8 | # DEFAULT: Name: mysym | ||
| 9 | # DEFAULT-NEXT: Value: 0x0 | ||
| 10 | |||
| 11 | # RUN: ld.lld %t.o -o %t-switch.elf -T %t.script --image-base=0x100000 | ||
| 12 | # RUN: llvm-readobj --symbols %t-switch.elf | FileCheck %s --check-prefix=SWITCH | ||
| 13 | # SWITCH: Name: mysym | ||
| 14 | # SWITCH-NEXT: Value: 0x100000 | ||
| 15 | |||
| 16 | .global _start | ||
| 17 | _start: | ||
| 18 | nop | ||
deps/lld/test/ELF/linkerscript/implicit-program-header.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | # RUN: ld.lld -o %t1 --script %S/Inputs/implicit-program-header.script \ | 3 | # RUN: ld.lld --hash-style=sysv -o %t1 --script %S/Inputs/implicit-program-header.script \ |
| 4 | # RUN: %t.o -shared | 4 | # RUN: %t.o -shared |
| 5 | # RUN: llvm-readobj -elf-output-style=GNU -l %t1 | FileCheck %s | 5 | # RUN: llvm-readobj -elf-output-style=GNU -l %t1 | FileCheck %s |
| 6 | 6 |
deps/lld/test/ELF/linkerscript/include-cycle.s created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 3 | |||
| 4 | # RUN: echo "INCLUDE \"%t1.script\"" > %t1.script | ||
| 5 | # RUN: not ld.lld %t.o %t1.script 2>&1 | FileCheck %s | ||
| 6 | |||
| 7 | # RUN: echo "INCLUDE \"%t2.script\"" > %t1.script | ||
| 8 | # RUN: echo "INCLUDE \"%t1.script\"" > %t2.script | ||
| 9 | # RUN: not ld.lld %t.o %t1.script 2>&1 | FileCheck %s | ||
| 10 | |||
| 11 | # CHECK: there is a cycle in linker script INCLUDEs | ||
| 12 | |||
| 13 | .globl _start | ||
| 14 | _start: | ||
| 15 | ret | ||
deps/lld/test/ELF/linkerscript/linker-script-in-search-path.s created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # Check that we fall back to search paths if a linker script was not found | ||
| 3 | # This behaviour matches ld.bfd and various projects appear to rely on this | ||
| 4 | |||
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 6 | # RUN: mkdir -p %T/searchpath | ||
| 7 | # RUN: echo "OUTPUT(\"%t.out\")" > %T/searchpath/foo.script | ||
| 8 | # RUN: ld.lld -T%T/searchpath/foo.script %t.o | ||
| 9 | # RUN: llvm-readobj %t.out | FileCheck %s | ||
| 10 | # CHECK: Format: ELF64-x86-64 | ||
| 11 | |||
| 12 | # If the linker script specified with -T is missing we should emit an error | ||
| 13 | # RUN: not ld.lld -Tfoo.script %t.o 2>&1 | FileCheck %s -check-prefix ERROR | ||
| 14 | # ERROR: error: cannot find linker script foo.script | ||
| 15 | |||
| 16 | # But if it exists in the search path we should fall back to that instead: | ||
| 17 | # RUN: rm %t.out | ||
| 18 | # RUN: ld.lld -L %T/searchpath -Tfoo.script %t.o | ||
| 19 | # RUN: llvm-readobj %t.out | FileCheck %s | ||
deps/lld/test/ELF/linkerscript/linkerscript.s+2-2| ... | @@ -37,8 +37,8 @@ | ... | @@ -37,8 +37,8 @@ |
| 37 | # RUN: echo "OUTPUT(\"%t.out\")" > %T/foo.script | 37 | # RUN: echo "OUTPUT(\"%t.out\")" > %T/foo.script |
| 38 | # RUN: not ld.lld %t.script > %t.log 2>&1 | 38 | # RUN: not ld.lld %t.script > %t.log 2>&1 |
| 39 | # RUN: FileCheck -check-prefix=INCLUDE_ERR %s < %t.log | 39 | # RUN: FileCheck -check-prefix=INCLUDE_ERR %s < %t.log |
| 40 | # INCLUDE_ERR: error: {{.+}}.script:1: cannot open foo.script | 40 | # INCLUDE_ERR: error: {{.+}}.script:1: cannot find linker script foo.script |
| 41 | # INCLUDE_ERR-NEXT: error: {{.+}}.script:1: INCLUDE "foo.script" | 41 | # INCLUDE_ERR-NEXT: INCLUDE "foo.script" |
| 42 | # RUN: ld.lld -L %T %t.script %t | 42 | # RUN: ld.lld -L %T %t.script %t |
| 43 | 43 | ||
| 44 | # RUN: echo "FOO(BAR)" > %t.script | 44 | # RUN: echo "FOO(BAR)" > %t.script |
deps/lld/test/ELF/linkerscript/memory-at.s created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: echo "MEMORY { \ | ||
| 4 | # RUN: FLASH (rx) : ORIGIN = 0x1000, LENGTH = 0x100 \ | ||
| 5 | # RUN: RAM (rwx) : ORIGIN = 0x2000, LENGTH = 0x100 } \ | ||
| 6 | # RUN: SECTIONS { \ | ||
| 7 | # RUN: .text : { *(.text*) } > FLASH \ | ||
| 8 | # RUN: __etext = .; \ | ||
| 9 | # RUN: .data : AT (__etext) { *(.data*) } > RAM \ | ||
| 10 | # RUN: }" > %t.script | ||
| 11 | # RUN: ld.lld %t --script %t.script -o %t2 | ||
| 12 | # RUN: llvm-readobj -program-headers %t2 | FileCheck %s | ||
| 13 | |||
| 14 | # CHECK: ProgramHeaders [ | ||
| 15 | # CHECK-NEXT: ProgramHeader { | ||
| 16 | # CHECK-NEXT: Type: PT_LOAD | ||
| 17 | # CHECK-NEXT: Offset: 0x1000 | ||
| 18 | # CHECK-NEXT: VirtualAddress: 0x1000 | ||
| 19 | # CHECK-NEXT: PhysicalAddress: 0x1000 | ||
| 20 | # CHECK-NEXT: FileSize: 8 | ||
| 21 | # CHECK-NEXT: MemSize: 8 | ||
| 22 | # CHECK-NEXT: Flags [ | ||
| 23 | # CHECK-NEXT: PF_R | ||
| 24 | # CHECK-NEXT: PF_X | ||
| 25 | # CHECK-NEXT: ] | ||
| 26 | # CHECK-NEXT: Alignment: | ||
| 27 | # CHECK-NEXT: } | ||
| 28 | # CHECK-NEXT: ProgramHeader { | ||
| 29 | # CHECK-NEXT: Type: PT_LOAD | ||
| 30 | # CHECK-NEXT: Offset: 0x2000 | ||
| 31 | # CHECK-NEXT: VirtualAddress: 0x2000 | ||
| 32 | # CHECK-NEXT: PhysicalAddress: 0x1008 | ||
| 33 | # CHECK-NEXT: FileSize: 8 | ||
| 34 | # CHECK-NEXT: MemSize: 8 | ||
| 35 | # CHECK-NEXT: Flags [ | ||
| 36 | # CHECK-NEXT: PF_R | ||
| 37 | # CHECK-NEXT: PF_W | ||
| 38 | # CHECK-NEXT: ] | ||
| 39 | # CHECK-NEXT: Alignment: | ||
| 40 | # CHECK-NEXT: } | ||
| 41 | |||
| 42 | .section .text, "ax" | ||
| 43 | .quad 0 | ||
| 44 | |||
| 45 | .section .data, "aw" | ||
| 46 | .quad 0 | ||
deps/lld/test/ELF/linkerscript/memory-err.s created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: echo "MEMORY { name : ORIGIN = DATA_SEGMENT_RELRO_END; }" > %t.script | ||
| 4 | # RUN: not ld.lld -shared -o %t2 --script %t.script %t 2>&1 | FileCheck %s | ||
| 5 | # CHECK: error: {{.*}}.script:1: unable to calculate page size | ||
| 6 | |||
| 7 | # RUN: echo "MEMORY { name : ORIGIN = CONSTANT(COMMONPAGESIZE); }" > %t.script | ||
| 8 | # RUN: not ld.lld -shared -o %t2 --script %t.script %t 2>&1 |\ | ||
| 9 | # RUN: FileCheck %s --check-prefix=ERR2 | ||
| 10 | # ERR2: error: {{.*}}.script:1: unable to calculate page size | ||
| 11 | |||
| 12 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 13 | # RUN: echo "MEMORY { name : ORIGIN = .; }" > %t.script | ||
| 14 | # RUN: not ld.lld -shared -o %t2 --script %t.script %t 2>&1 |\ | ||
| 15 | # RUN: FileCheck %s --check-prefix=ERR3 | ||
| 16 | # ERR3: error: {{.*}}.script:1: unable to get location counter value | ||
deps/lld/test/ELF/linkerscript/memory.s+2-2| ... | @@ -21,8 +21,8 @@ | ... | @@ -21,8 +21,8 @@ |
| 21 | # RUN: rom (rx) : org = (0x80 * 0x1000 * 0x1000), len = 64M \ | 21 | # RUN: rom (rx) : org = (0x80 * 0x1000 * 0x1000), len = 64M \ |
| 22 | # RUN: } \ | 22 | # RUN: } \ |
| 23 | # RUN: SECTIONS { \ | 23 | # RUN: SECTIONS { \ |
| 24 | # RUN: .text : { *(.text) } > rom \ | 24 | # RUN: .text : { *(.text) } >rom \ |
| 25 | # RUN: .data : { *(.data) } > ram \ | 25 | # RUN: .data : { *(.data) } >ram \ |
| 26 | # RUN: }" > %t.script | 26 | # RUN: }" > %t.script |
| 27 | # RUN: ld.lld -o %t1 --script %t.script %t | 27 | # RUN: ld.lld -o %t1 --script %t.script %t |
| 28 | # RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=RAMROM %s | 28 | # RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=RAMROM %s |
deps/lld/test/ELF/linkerscript/memory2.s created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: echo "MEMORY { ram (rwx) : ORIGIN = 0, LENGTH = 2K } \ | ||
| 4 | # RUN: SECTIONS { .text : { *(.text*) } > ram }" > %t.script | ||
| 5 | # RUN: ld.lld -o %t2 --script %t.script %t | ||
| 6 | |||
| 7 | .text | ||
| 8 | .global _start | ||
| 9 | _start: | ||
| 10 | .zero 1024 | ||
| 11 | |||
| 12 | .section .text.foo,"ax",%progbits | ||
| 13 | foo: | ||
| 14 | nop | ||
deps/lld/test/ELF/linkerscript/memory3.s created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: echo "MEMORY { ram2 (ax) : ORIGIN = 0x1000, LENGTH = 1K \ | ||
| 4 | # RUN: ram1 (ax) : ORIGIN = 0x4000, LENGTH = 1K } \ | ||
| 5 | # RUN: SECTIONS {}" > %t1.script | ||
| 6 | # RUN: ld.lld -o %t1 --script %t1.script %t | ||
| 7 | # RUN: llvm-objdump -section-headers %t1 | FileCheck %s | ||
| 8 | |||
| 9 | # RUN: echo "MEMORY { ram1 (ax) : ORIGIN = 0x1000, LENGTH = 1K \ | ||
| 10 | # RUN: ram2 (ax) : ORIGIN = 0x4000, LENGTH = 1K } \ | ||
| 11 | # RUN: SECTIONS {}" > %t2.script | ||
| 12 | # RUN: ld.lld -o %t2 --script %t2.script %t | ||
| 13 | # RUN: llvm-objdump -section-headers %t2 | FileCheck %s | ||
| 14 | |||
| 15 | ## Check we place .text into first defined memory region with appropriate flags. | ||
| 16 | # CHECK: Sections: | ||
| 17 | # CHECK: Idx Name Size Address | ||
| 18 | # CHECK: 0 00000000 0000000000000000 | ||
| 19 | # CHECK: 1 .text 00000001 0000000000001000 | ||
| 20 | |||
| 21 | .section .text.foo,"ax",%progbits | ||
| 22 | foo: | ||
| 23 | nop | ||
deps/lld/test/ELF/linkerscript/merge-sections.s+1-1| ... | @@ -36,7 +36,7 @@ | ... | @@ -36,7 +36,7 @@ |
| 36 | # RUN: llvm-readobj -s -t %t2 | FileCheck %s --check-prefix=GC | 36 | # RUN: llvm-readobj -s -t %t2 | FileCheck %s --check-prefix=GC |
| 37 | 37 | ||
| 38 | # GC: Name: .foo | 38 | # GC: Name: .foo |
| 39 | # GC-NEXT: Type: SHT_PROGBITS | 39 | # GC-NEXT: Type: SHT_NOBITS |
| 40 | # GC-NEXT: Flags [ | 40 | # GC-NEXT: Flags [ |
| 41 | # GC-NEXT: SHF_ALLOC | 41 | # GC-NEXT: SHF_ALLOC |
| 42 | # GC-NEXT: ] | 42 | # GC-NEXT: ] |
deps/lld/test/ELF/linkerscript/no-space.s+2-2| ... | @@ -2,11 +2,11 @@ | ... | @@ -2,11 +2,11 @@ |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | 3 | ||
| 4 | # RUN: echo "SECTIONS {foo 0 : {*(foo*)} }" > %t.script | 4 | # RUN: echo "SECTIONS {foo 0 : {*(foo*)} }" > %t.script |
| 5 | # RUN: ld.lld -o %t --script %t.script %t.o -shared | 5 | # RUN: ld.lld --hash-style=sysv -o %t --script %t.script %t.o -shared |
| 6 | # RUN: llvm-readobj -elf-output-style=GNU -l %t | FileCheck %s | 6 | # RUN: llvm-readobj -elf-output-style=GNU -l %t | FileCheck %s |
| 7 | 7 | ||
| 8 | # RUN: echo "SECTIONS {foo : {*(foo*)} }" > %t.script | 8 | # RUN: echo "SECTIONS {foo : {*(foo*)} }" > %t.script |
| 9 | # RUN: ld.lld -o %t --script %t.script %t.o -shared | 9 | # RUN: ld.lld --hash-style=sysv -o %t --script %t.script %t.o -shared |
| 10 | # RUN: llvm-readobj -elf-output-style=GNU -l %t | FileCheck %s | 10 | # RUN: llvm-readobj -elf-output-style=GNU -l %t | FileCheck %s |
| 11 | 11 | ||
| 12 | # There is not enough address space available for the header, so just start the PT_LOAD | 12 | # There is not enough address space available for the header, so just start the PT_LOAD |
deps/lld/test/ELF/linkerscript/nobits-offset.s created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { \ | ||
| 4 | # RUN: .sec1 (NOLOAD) : { . += 1; } \ | ||
| 5 | # RUN: .text : { *(.text) } \ | ||
| 6 | # RUN: };" > %t.script | ||
| 7 | # RUN: ld.lld %t.o -T %t.script -o %t | ||
| 8 | # RUN: llvm-readelf --sections %t | FileCheck %s | ||
| 9 | |||
| 10 | # We used to misalign section offsets if the first section in a | ||
| 11 | # PT_LOAD was SHT_NOBITS. | ||
| 12 | |||
| 13 | # CHECK: [ 2] .text PROGBITS 0000000000000010 001010 000010 00 AX 0 0 16 | ||
| 14 | |||
| 15 | .global _start | ||
| 16 | _start: | ||
| 17 | nop | ||
| 18 | .p2align 4 | ||
deps/lld/test/ELF/linkerscript/noload.s+2-2| ... | @@ -4,10 +4,10 @@ | ... | @@ -4,10 +4,10 @@ |
| 4 | # RUN: .data_noload_a (NOLOAD) : { *(.data_noload_a) } \ | 4 | # RUN: .data_noload_a (NOLOAD) : { *(.data_noload_a) } \ |
| 5 | # RUN: .data_noload_b (0x10000) (NOLOAD) : { *(.data_noload_b) } };" > %t.script | 5 | # RUN: .data_noload_b (0x10000) (NOLOAD) : { *(.data_noload_b) } };" > %t.script |
| 6 | # RUN: ld.lld -o %t --script %t.script %t.o | 6 | # RUN: ld.lld -o %t --script %t.script %t.o |
| 7 | # RUN: llvm-readobj --symbols -sections %t | 7 | # RUN: llvm-readobj --symbols -sections %t | FileCheck %s |
| 8 | 8 | ||
| 9 | # CHECK: Section { | 9 | # CHECK: Section { |
| 10 | # CHECK-NEXT: Index: 2 | 10 | # CHECK: Index: 2 |
| 11 | # CHECK-NEXT: Name: .data_noload_a | 11 | # CHECK-NEXT: Name: .data_noload_a |
| 12 | # CHECK-NEXT: Type: SHT_NOBITS | 12 | # CHECK-NEXT: Type: SHT_NOBITS |
| 13 | # CHECK-NEXT: Flags [ | 13 | # CHECK-NEXT: Flags [ |
deps/lld/test/ELF/linkerscript/non-alloc.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 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t |
| 3 | 3 | ||
| 4 | # RUN: echo "SECTIONS { .foo 0 : {*(foo)} }" > %t.script | 4 | # RUN: echo "SECTIONS { .foo 0 : {*(foo)} }" > %t.script |
| 5 | # RUN: ld.lld -o %t1 --script %t.script %t -shared | 5 | # RUN: ld.lld --hash-style=sysv -o %t1 --script %t.script %t -shared |
| 6 | # RUN: llvm-readobj -elf-output-style=GNU -s -l %t1 | FileCheck %s | 6 | # RUN: llvm-readobj -elf-output-style=GNU -s -l %t1 | FileCheck %s |
| 7 | 7 | ||
| 8 | # Test that we create all necessary PT_LOAD. We use to stop at the first | 8 | # Test that we create all necessary PT_LOAD. We use to stop at the first |
deps/lld/test/ELF/linkerscript/operators.s+8| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 3 | # RUN: echo "SECTIONS { \ | 3 | # RUN: echo "SECTIONS { \ |
| 4 | # RUN: _start = .; \ | ||
| 4 | # RUN: plus = 1 + 2 + 3; \ | 5 | # RUN: plus = 1 + 2 + 3; \ |
| 5 | # RUN: minus = 5 - 1; \ | 6 | # RUN: minus = 5 - 1; \ |
| 6 | # RUN: div = 6 / 2; \ | 7 | # RUN: div = 6 / 2; \ |
| ... | @@ -25,6 +26,10 @@ | ... | @@ -25,6 +26,10 @@ |
| 25 | # RUN: commonpagesize = CONSTANT (COMMONPAGESIZE); \ | 26 | # RUN: commonpagesize = CONSTANT (COMMONPAGESIZE); \ |
| 26 | # RUN: . = 0xfff0; \ | 27 | # RUN: . = 0xfff0; \ |
| 27 | # RUN: datasegmentalign = DATA_SEGMENT_ALIGN (0xffff, 0); \ | 28 | # RUN: datasegmentalign = DATA_SEGMENT_ALIGN (0xffff, 0); \ |
| 29 | # RUN: datasegmentalign2 = DATA_SEGMENT_ALIGN (0, 0); \ | ||
| 30 | # RUN: _end = .; \ | ||
| 31 | # RUN: minus_rel = _end - 0x10; \ | ||
| 32 | # RUN: minus_abs = _end - _start; \ | ||
| 28 | # RUN: }" > %t.script | 33 | # RUN: }" > %t.script |
| 29 | # RUN: ld.lld %t --script %t.script -o %t2 | 34 | # RUN: ld.lld %t --script %t.script -o %t2 |
| 30 | # RUN: llvm-objdump -t %t2 | FileCheck %s | 35 | # RUN: llvm-objdump -t %t2 | FileCheck %s |
| ... | @@ -51,6 +56,9 @@ | ... | @@ -51,6 +56,9 @@ |
| 51 | # CHECK: 00000000001000 *ABS* 00000000 maxpagesize | 56 | # CHECK: 00000000001000 *ABS* 00000000 maxpagesize |
| 52 | # CHECK: 00000000001000 *ABS* 00000000 commonpagesize | 57 | # CHECK: 00000000001000 *ABS* 00000000 commonpagesize |
| 53 | # CHECK: 0000000000ffff *ABS* 00000000 datasegmentalign | 58 | # CHECK: 0000000000ffff *ABS* 00000000 datasegmentalign |
| 59 | # CHECK: 0000000000fff0 *ABS* 00000000 datasegmentalign2 | ||
| 60 | # CHECK: 0000000000ffe0 .text 00000000 minus_rel | ||
| 61 | # CHECK: 0000000000fff0 *ABS* 00000000 minus_abs | ||
| 54 | 62 | ||
| 55 | ## Mailformed number error. | 63 | ## Mailformed number error. |
| 56 | # RUN: echo "SECTIONS { . = 0x12Q41; }" > %t.script | 64 | # RUN: echo "SECTIONS { . = 0x12Q41; }" > %t.script |
deps/lld/test/ELF/linkerscript/orphan-discard.s created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -position-independent -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { \ | ||
| 4 | # RUN: . = 0xffffffff80000000; \ | ||
| 5 | # RUN: .text : ALIGN(4096) { *(.text) } \ | ||
| 6 | # RUN: .data : ALIGN(4096) { *(.data) } \ | ||
| 7 | # RUN: .bss : ALIGN(4096) { *(.bss); } \ | ||
| 8 | # RUN: . = ALIGN(4096); \ | ||
| 9 | # RUN: _end = .; \ | ||
| 10 | # RUN: /DISCARD/ : { *(.comment) } \ | ||
| 11 | # RUN: }" > %t.script | ||
| 12 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 13 | # RUN: llvm-readelf -s -symbols %t | FileCheck %s | ||
| 14 | |||
| 15 | # CHECK: .bss NOBITS ffffffff80002000 002008 000002 00 WA 0 0 4096 | ||
| 16 | # CHECK: ffffffff80003000 0 NOTYPE GLOBAL DEFAULT 3 _end | ||
| 17 | |||
| 18 | .section .text, "ax" | ||
| 19 | ret | ||
| 20 | |||
| 21 | .section .data, "aw" | ||
| 22 | .quad 0 | ||
| 23 | |||
| 24 | .section .bss, "", @nobits | ||
| 25 | .short 0 | ||
deps/lld/test/ELF/linkerscript/orphan-end.s created+57| ... | @@ -0,0 +1,57 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | |||
| 4 | # Test that .orphan_rx is placed after __stack_end. This matches bfd's | ||
| 5 | # behavior when the orphan section is the last one. | ||
| 6 | |||
| 7 | # RUN: echo "SECTIONS { \ | ||
| 8 | # RUN: __start_text = .; \ | ||
| 9 | # RUN: .text : { *(.text*) } \ | ||
| 10 | # RUN: __end_text = .; \ | ||
| 11 | # RUN: __stack_start = .; \ | ||
| 12 | # RUN: . = . + 0x1000; \ | ||
| 13 | # RUN: __stack_end = .; \ | ||
| 14 | # RUN: }" > %t.script | ||
| 15 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 16 | # RUN: llvm-readelf -S --symbols %t | FileCheck %s | ||
| 17 | |||
| 18 | # CHECK-DAG: .text PROGBITS 0000000000000000 | ||
| 19 | # CHECK-DAG: .orphan_rx PROGBITS 0000000000001004 | ||
| 20 | |||
| 21 | # CHECK-DAG: 0000000000000000 {{.*}} __start_text | ||
| 22 | # CHECK-DAG: 0000000000000004 {{.*}} __end_text | ||
| 23 | # CHECK-DAG: 0000000000000004 {{.*}} __stack_start | ||
| 24 | # CHECK-DAG: 0000000000001004 {{.*}} __stack_end | ||
| 25 | |||
| 26 | # Test that .orphan_rx is now placed before __stack_end. This matches bfd's | ||
| 27 | # behavior when the orphan section is not the last one. | ||
| 28 | |||
| 29 | # RUN: echo "SECTIONS { \ | ||
| 30 | # RUN: __start_text = .; \ | ||
| 31 | # RUN: .text : { *(.text*) } \ | ||
| 32 | # RUN: __end_text = .; \ | ||
| 33 | # RUN: __stack_start = .; \ | ||
| 34 | # RUN: . = . + 0x1000; \ | ||
| 35 | # RUN: __stack_end = .; \ | ||
| 36 | # RUN: .orphan_rw : { *(.orphan_rw*) } \ | ||
| 37 | # RUN: }" > %t.script | ||
| 38 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 39 | # RUN: llvm-readelf -S --symbols %t | FileCheck --check-prefix=MIDDLE %s | ||
| 40 | |||
| 41 | # MIDDLE-DAG: .text PROGBITS 0000000000000000 | ||
| 42 | # MIDDLE-DAG: .orphan_rx PROGBITS 0000000000000004 | ||
| 43 | |||
| 44 | # MIDDLE-DAG: 0000000000000000 {{.*}} __start_text | ||
| 45 | # MIDDLE-DAG: 0000000000000004 {{.*}} __end_text | ||
| 46 | # MIDDLE-DAG: 0000000000000004 {{.*}} __stack_start | ||
| 47 | # MIDDLE-DAG: 0000000000001008 {{.*}} __stack_end | ||
| 48 | |||
| 49 | .global _start | ||
| 50 | _start: | ||
| 51 | .zero 4 | ||
| 52 | |||
| 53 | .section .orphan_rx,"ax" | ||
| 54 | .zero 4 | ||
| 55 | |||
| 56 | .section .orphan_rw,"aw" | ||
| 57 | .zero 4 | ||
deps/lld/test/ELF/linkerscript/orphan-phdrs.s created+34| ... | @@ -0,0 +1,34 @@ | ||
| 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: rw PT_LOAD FLAGS(0x4 | 0x2); \ | ||
| 6 | # RUN: } \ | ||
| 7 | # RUN: SECTIONS { \ | ||
| 8 | # RUN: .text : { *(.text) } :exec \ | ||
| 9 | # RUN: .empty : { *(.empty) } :rw \ | ||
| 10 | # RUN: .rw : { *(.rw) } \ | ||
| 11 | # RUN: }" > %t.script | ||
| 12 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 13 | # RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck %s | ||
| 14 | |||
| 15 | ## Check that the orphan section is placed correctly and belongs to | ||
| 16 | ## the correct segment. | ||
| 17 | |||
| 18 | # CHECK: Section Headers | ||
| 19 | # CHECK: .text | ||
| 20 | # CHECK-NEXT: .orphan | ||
| 21 | # CHECK-NEXT: .rw | ||
| 22 | |||
| 23 | # CHECK: Segment Sections | ||
| 24 | # CHECK-NEXT: .text .orphan | ||
| 25 | # CHECK-NEXT: .rw | ||
| 26 | |||
| 27 | .section .text, "ax" | ||
| 28 | ret | ||
| 29 | |||
| 30 | .section .rw, "aw" | ||
| 31 | .quad 0 | ||
| 32 | |||
| 33 | .section .orphan, "ax" | ||
| 34 | ret | ||
deps/lld/test/ELF/linkerscript/orphan-report.s created+54| ... | @@ -0,0 +1,54 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { .text : { *(.text.1) } }" > %t.script | ||
| 4 | |||
| 5 | ## Check we do not report orphans by default even with -verbose. | ||
| 6 | # RUN: ld.lld -shared -o %t.out --script %t.script %t.o 2>&1 -verbose \ | ||
| 7 | # RUN: | FileCheck %s --check-prefix=DEFAULT | ||
| 8 | # DEFAULT-NOT: placed | ||
| 9 | |||
| 10 | ## Check --orphan-handling=place has the same behavior as default. | ||
| 11 | # RUN: ld.lld -shared --orphan-handling=place -o %t.out --script %t.script \ | ||
| 12 | # RUN: %t.o 2>&1 -verbose -error-limit=0 | FileCheck %s --check-prefix=DEFAULT | ||
| 13 | |||
| 14 | ## Check --orphan-handling=error reports errors about orphans. | ||
| 15 | # RUN: not ld.lld -shared --orphan-handling=error -o %t.out --script %t.script \ | ||
| 16 | # RUN: %t.o 2>&1 -verbose -error-limit=0 | FileCheck %s --check-prefix=REPORT | ||
| 17 | # REPORT: {{.*}}.o:(.text) is being placed in '.text' | ||
| 18 | # REPORT-NEXT: {{.*}}.o:(.text.2) is being placed in '.text' | ||
| 19 | # REPORT-NEXT: <internal>:(.comment) is being placed in '.comment' | ||
| 20 | # REPORT-NEXT: <internal>:(.bss) is being placed in '.bss' | ||
| 21 | # REPORT-NEXT: <internal>:(.bss.rel.ro) is being placed in '.bss.rel.ro' | ||
| 22 | # REPORT-NEXT: <internal>:(.dynsym) is being placed in '.dynsym' | ||
| 23 | # REPORT-NEXT: <internal>:(.gnu.version) is being placed in '.gnu.version' | ||
| 24 | # REPORT-NEXT: <internal>:(.gnu.version_r) is being placed in '.gnu.version_r' | ||
| 25 | # REPORT-NEXT: <internal>:(.gnu.hash) is being placed in '.gnu.hash' | ||
| 26 | # REPORT-NEXT: <internal>:(.hash) is being placed in '.hash' | ||
| 27 | # REPORT-NEXT: <internal>:(.dynamic) is being placed in '.dynamic' | ||
| 28 | # REPORT-NEXT: <internal>:(.dynstr) is being placed in '.dynstr' | ||
| 29 | # REPORT-NEXT: <internal>:(.rela.dyn) is being placed in '.rela.dyn' | ||
| 30 | # 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' | ||
| 33 | # REPORT-NEXT: <internal>:(.rela.plt) is being placed in '.rela.plt' | ||
| 34 | # 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' | ||
| 37 | # REPORT-NEXT: <internal>:(.eh_frame) is being placed in '.eh_frame' | ||
| 38 | # REPORT-NEXT: <internal>:(.symtab) is being placed in '.symtab' | ||
| 39 | # REPORT-NEXT: <internal>:(.shstrtab) is being placed in '.shstrtab' | ||
| 40 | # REPORT-NEXT: <internal>:(.strtab) is being placed in '.strtab' | ||
| 41 | |||
| 42 | ## Check --orphan-handling=warn reports warnings about orphans. | ||
| 43 | # RUN: ld.lld -shared --orphan-handling=warn -o %t.out --script %t.script \ | ||
| 44 | # RUN: %t.o 2>&1 -verbose | FileCheck %s --check-prefix=REPORT | ||
| 45 | |||
| 46 | # RUN: not ld.lld --orphan-handling=foo -o %t.out --script %t.script %t.o 2>&1 \ | ||
| 47 | # RUN: | FileCheck %s --check-prefix=UNKNOWN | ||
| 48 | # UNKNOWN: unknown --orphan-handling mode: foo | ||
| 49 | |||
| 50 | .section .text.1,"a" | ||
| 51 | nop | ||
| 52 | |||
| 53 | .section .text.2,"a" | ||
| 54 | nop | ||
deps/lld/test/ELF/linkerscript/out-of-order.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-linux %s -o %t.o |
| 3 | # RUN: echo "SECTIONS { .data 0x4000 : { *(.data) } .text 0x2000 : { *(.text) } }" > %t.script | 3 | # RUN: echo "SECTIONS { .data 0x4000 : { *(.data) } .text 0x2000 : { *(.text) } }" > %t.script |
| 4 | # RUN: ld.lld -o %t.so --script %t.script %t.o -shared | 4 | # RUN: ld.lld --hash-style=sysv -o %t.so --script %t.script %t.o -shared |
| 5 | # RUN: llvm-objdump -section-headers %t.so | FileCheck %s | 5 | # RUN: llvm-objdump -section-headers %t.so | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK: Sections: | 7 | # CHECK: Sections: |
deps/lld/test/ELF/linkerscript/phdr-check.s+2-2| ... | @@ -1,14 +1,14 @@ | ... | @@ -1,14 +1,14 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 3 | 3 | ||
| 4 | # RUN: echo "SECTIONS { . = 0x10000000; .text : {*(.text.*)} }" > %t.script | 4 | # RUN: echo "SECTIONS { . = 0x10000000 + SIZEOF_HEADERS; .text : {*(.text.*)} }" > %t.script |
| 5 | # RUN: ld.lld -o %t1 --script %t.script %t | 5 | # RUN: ld.lld -o %t1 --script %t.script %t |
| 6 | # RUN: llvm-readobj -program-headers %t1 | FileCheck %s | 6 | # RUN: llvm-readobj -program-headers %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) |
| 10 | # CHECK-NEXT: Offset: 0x40 | 10 | # CHECK-NEXT: Offset: 0x40 |
| 11 | # CHECK-NEXT: VirtualAddress: 0xFFFF040 | 11 | # CHECK-NEXT: VirtualAddress: 0x10000040 |
| 12 | 12 | ||
| 13 | .global _start | 13 | .global _start |
| 14 | _start: | 14 | _start: |
deps/lld/test/ELF/linkerscript/phdrs.s+2-2| ... | @@ -39,9 +39,9 @@ | ... | @@ -39,9 +39,9 @@ |
| 39 | # RUN: ld.lld -o %t1 --script %t.script %t | 39 | # RUN: ld.lld -o %t1 --script %t.script %t |
| 40 | # RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s | 40 | # RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s |
| 41 | 41 | ||
| 42 | ## Check that error is reported when trying to use phdr which is not listed | 42 | ## Check that error is reported when trying to use phdr which is not listed |
| 43 | ## inside PHDRS {} block | 43 | ## inside PHDRS {} block |
| 44 | ## TODO: If script doesn't contain PHDRS {} block then default phdr is always | 44 | ## TODO: If script doesn't contain PHDRS {} block then default phdr is always |
| 45 | ## created and error is not reported. | 45 | ## created and error is not reported. |
| 46 | # RUN: echo "PHDRS { all PT_LOAD; } \ | 46 | # RUN: echo "PHDRS { all PT_LOAD; } \ |
| 47 | # RUN: SECTIONS { .baz : {*(.foo.*)} :bar }" > %t.script | 47 | # RUN: SECTIONS { .baz : {*(.foo.*)} :bar }" > %t.script |
deps/lld/test/ELF/linkerscript/provide-shared.s created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/provide-shared.s -o %t2.o | ||
| 4 | # RUN: ld.lld %t2.o -o %t2.so -shared | ||
| 5 | # RUN: echo "SECTIONS { . = . + SIZEOF_HEADERS; PROVIDE(foo = 42);}" > %t.script | ||
| 6 | # RUN: ld.lld -o %t --script %t.script %t.o %t2.so | ||
| 7 | # RUN: llvm-objdump -t %t | FileCheck %s | ||
| 8 | |||
| 9 | # CHECK: 000000000000002a *ABS* 00000000 foo | ||
| 10 | |||
| 11 | .global _start | ||
| 12 | _start: | ||
| 13 | .quad foo | ||
deps/lld/test/ELF/linkerscript/region-alias.s created+54| ... | @@ -0,0 +1,54 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 3 | # RUN: echo "MEMORY { \ | ||
| 4 | # RUN: ROM (rwx): ORIGIN = 0x1000, LENGTH = 0x100 \ | ||
| 5 | # RUN: RAM (rwx): ORIGIN = 0x2000, LENGTH = 0x100 \ | ||
| 6 | # RUN: } \ | ||
| 7 | # RUN: INCLUDE \"%t.script.inc\" \ | ||
| 8 | # RUN: SECTIONS { \ | ||
| 9 | # RUN: .text : { *(.text*) } > ALIAS_TEXT \ | ||
| 10 | # RUN: .data : { *(.data*) } > ALIAS_DATA \ | ||
| 11 | # RUN: }" > %t.script | ||
| 12 | |||
| 13 | ## .text to ROM, .data to RAM. | ||
| 14 | # RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", ROM);" > %t.script.inc | ||
| 15 | # RUN: echo "REGION_ALIAS (\"ALIAS_DATA\", RAM);" >> %t.script.inc | ||
| 16 | # RUN: ld.lld %t --script %t.script -o %t2 | ||
| 17 | # RUN: llvm-objdump -section-headers %t2 | FileCheck %s | ||
| 18 | # CHECK: .text 00000001 0000000000001000 TEXT DATA | ||
| 19 | # CHECK: .data 00000008 0000000000002000 DATA | ||
| 20 | |||
| 21 | ## All to ROM. | ||
| 22 | # RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", ROM);" > %t.script.inc | ||
| 23 | # RUN: echo "REGION_ALIAS (\"ALIAS_DATA\", ROM);" >> %t.script.inc | ||
| 24 | # RUN: ld.lld %t --script %t.script -o %t2 | ||
| 25 | # RUN: llvm-objdump -section-headers %t2 | FileCheck %s --check-prefix=RAM | ||
| 26 | # RAM: .text 00000001 0000000000001000 TEXT DATA | ||
| 27 | # RAM: .data 00000008 0000000000001001 DATA | ||
| 28 | |||
| 29 | ## Redefinition of region. | ||
| 30 | # RUN: echo "REGION_ALIAS (\"ROM\", ROM);" > %t.script.inc | ||
| 31 | # RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ | ||
| 32 | # RUN: FileCheck %s --check-prefix=ERR1 | ||
| 33 | # ERR1: {{.*}}script.inc:1: redefinition of memory region 'ROM' | ||
| 34 | |||
| 35 | ## Redefinition of alias. | ||
| 36 | # RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", ROM);" > %t.script.inc | ||
| 37 | # RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", ROM);" >> %t.script.inc | ||
| 38 | # RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ | ||
| 39 | # RUN: FileCheck %s --check-prefix=ERR2 | ||
| 40 | # ERR2: {{.*}}script.inc:2: redefinition of memory region 'ALIAS_TEXT' | ||
| 41 | |||
| 42 | ## Attemp to create an alias for undefined region. | ||
| 43 | # RUN: echo "REGION_ALIAS (\"ALIAS_TEXT\", FOO);" > %t.script.inc | ||
| 44 | # RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \ | ||
| 45 | # RUN: FileCheck %s --check-prefix=ERR3 | ||
| 46 | # ERR3: {{.*}}script.inc:1: memory region 'FOO' is not defined | ||
| 47 | |||
| 48 | .text | ||
| 49 | .global _start | ||
| 50 | _start: | ||
| 51 | nop | ||
| 52 | |||
| 53 | .section .data,"aw" | ||
| 54 | .quad 0 | ||
deps/lld/test/ELF/linkerscript/repsection-symbol.s+1-1| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | # RUN: .text : { *(.text) } \ | 6 | # RUN: .text : { *(.text) } \ |
| 7 | # RUN: .foo : {foo1 = .; *(.foo.*) foo2 = .; *(.bar) foo3 = .;} \ | 7 | # RUN: .foo : {foo1 = .; *(.foo.*) foo2 = .; *(.bar) foo3 = .;} \ |
| 8 | # RUN: }" > %t.script | 8 | # RUN: }" > %t.script |
| 9 | # RUN: ld.lld -o %t1 --script %t.script %t -shared | 9 | # RUN: ld.lld --hash-style=sysv -o %t1 --script %t.script %t -shared |
| 10 | # RUN: llvm-readobj -t %t1 | FileCheck %s | 10 | # RUN: llvm-readobj -t %t1 | FileCheck %s |
| 11 | 11 | ||
| 12 | # CHECK: Name: foo1 | 12 | # CHECK: Name: foo1 |
deps/lld/test/ELF/linkerscript/sections-sort.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.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | 3 | ||
| 4 | # RUN: echo "SECTIONS { .text : {*(.text)} foo : {*(foo)}}" > %t.script | 4 | # RUN: echo "SECTIONS { .text : {*(.text)} foo : {*(foo)}}" > %t.script |
| 5 | # RUN: ld.lld -o %t --script %t.script %t.o -shared | 5 | # RUN: ld.lld --hash-style=sysv -o %t --script %t.script %t.o -shared |
| 6 | # RUN: llvm-objdump --section-headers %t | FileCheck %s | 6 | # RUN: llvm-objdump --section-headers %t | FileCheck %s |
| 7 | 7 | ||
| 8 | # Test the section order. This is a case where at least with libstdc++'s | 8 | # Test the section order. This is a case where at least with libstdc++'s |
deps/lld/test/ELF/linkerscript/segment-headers.s created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { . = 0x2000; .text : AT(0x100000) { *(.text) } }" > %t.script | ||
| 4 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 5 | # RUN: llvm-readobj -l %t | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: ProgramHeaders [ | ||
| 8 | # CHECK-NEXT: ProgramHeader { | ||
| 9 | # CHECK-NEXT: Type: PT_LOAD (0x1) | ||
| 10 | # CHECK-NEXT: Offset: 0x1000 | ||
| 11 | # CHECK-NEXT: VirtualAddress: 0x2000 | ||
| 12 | # CHECK-NEXT: PhysicalAddress: 0x100000 | ||
| 13 | # CHECK-NEXT: FileSize: 1 | ||
| 14 | # CHECK-NEXT: MemSize: 1 | ||
| 15 | # CHECK-NEXT: Flags [ (0x5) | ||
| 16 | # CHECK-NEXT: PF_R (0x4) | ||
| 17 | # CHECK-NEXT: PF_X (0x1) | ||
| 18 | # CHECK-NEXT: ] | ||
| 19 | # CHECK-NEXT: Alignment: 4096 | ||
| 20 | # CHECK-NEXT: } | ||
| 21 | |||
| 22 | .section .text | ||
| 23 | .global _start | ||
| 24 | |||
| 25 | _start: | ||
| 26 | ret | ||
deps/lld/test/ELF/linkerscript/segment-start.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld %t.o %S/Inputs/segment-start.script -shared -o %t.so | 3 | // RUN: ld.lld --hash-style=sysv %t.o %S/Inputs/segment-start.script -shared -o %t.so |
| 4 | // RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s | 4 | // RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s |
| 5 | 5 | ||
| 6 | // CHECK: Name: foobar1 | 6 | // CHECK: Name: foobar1 |
deps/lld/test/ELF/linkerscript/sort-non-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 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t |
| 3 | 3 | ||
| 4 | # RUN: echo "SECTIONS { foo : {*(foo)} }" > %t.script | 4 | # RUN: echo "SECTIONS { foo : {*(foo)} }" > %t.script |
| 5 | # RUN: ld.lld -o %t1 --script %t.script %t -shared | 5 | # RUN: ld.lld --hash-style=sysv -o %t1 --script %t.script %t -shared |
| 6 | # RUN: llvm-readobj -elf-output-style=GNU -s %t1 | FileCheck %s | 6 | # RUN: llvm-readobj -elf-output-style=GNU -s %t1 | FileCheck %s |
| 7 | 7 | ||
| 8 | # CHECK: .text {{.*}} AX | 8 | # CHECK: .text {{.*}} AX |
deps/lld/test/ELF/linkerscript/subalign.s+17| ... | @@ -22,6 +22,23 @@ | ... | @@ -22,6 +22,23 @@ |
| 22 | # SUBALIGN: 01000000 00000000 02000000 00000000 | 22 | # SUBALIGN: 01000000 00000000 02000000 00000000 |
| 23 | # SUBALIGN: 03000000 00000000 04000000 00000000 | 23 | # SUBALIGN: 03000000 00000000 04000000 00000000 |
| 24 | 24 | ||
| 25 | ## Test we do not assert or crash when dot(.) is used inside SUBALIGN. | ||
| 26 | ## ld.bfd does not allow to use dot in such expressions, our behavior is | ||
| 27 | ## different for simplicity of implementation. Value of dot is undefined. | ||
| 28 | # RUN: echo "SECTIONS { . = 0x32; .aaa : SUBALIGN(.) { *(.aaa*) } }" > %t3.script | ||
| 29 | # RUN: ld.lld %t1.o --script %t3.script -o %t3 | ||
| 30 | # RUN: llvm-objdump -s %t3 > /dev/null | ||
| 31 | |||
| 32 | ## Test we are able to link with zero alignment, this is consistent with bfd 2.26.1. | ||
| 33 | # RUN: echo "SECTIONS { .aaa : SUBALIGN(0) { *(.aaa*) } }" > %t4.script | ||
| 34 | # RUN: ld.lld %t1.o --script %t4.script -o %t4 | ||
| 35 | # RUN: llvm-objdump -s %t4 | FileCheck -check-prefix=SUBALIGN %s | ||
| 36 | |||
| 37 | ## Test we fail gracefuly when alignment value is not a power of 2. | ||
| 38 | # RUN: echo "SECTIONS { .aaa : SUBALIGN(3) { *(.aaa*) } }" > %t5.script | ||
| 39 | # RUN: not ld.lld %t1.o --script %t5.script -o %t5 2>&1 | FileCheck -check-prefix=ERR %s | ||
| 40 | # ERR: {{.*}}.script:1: alignment must be power of 2 | ||
| 41 | |||
| 25 | .global _start | 42 | .global _start |
| 26 | _start: | 43 | _start: |
| 27 | nop | 44 | nop |
deps/lld/test/ELF/linkerscript/symbol-assignexpr.s+7-1| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | # RUN: symbol2 = symbol + 0x1234; \ | 6 | # RUN: symbol2 = symbol + 0x1234; \ |
| 7 | # RUN: symbol3 = symbol2; \ | 7 | # RUN: symbol3 = symbol2; \ |
| 8 | # RUN: symbol4 = symbol + -4; \ | 8 | # RUN: symbol4 = symbol + -4; \ |
| 9 | # RUN: symbol5 = symbol - ~ 0xfffb; \ | 9 | # RUN: symbol5 = symbol - ~0xfffb; \ |
| 10 | # RUN: symbol6 = symbol - ~(0xfff0 + 0xb); \ | 10 | # RUN: symbol6 = symbol - ~(0xfff0 + 0xb); \ |
| 11 | # RUN: symbol7 = symbol - ~ 0xfffb + 4; \ | 11 | # RUN: symbol7 = symbol - ~ 0xfffb + 4; \ |
| 12 | # RUN: symbol8 = ~ 0xffff + 4; \ | 12 | # RUN: symbol8 = ~ 0xffff + 4; \ |
| ... | @@ -15,6 +15,9 @@ | ... | @@ -15,6 +15,9 @@ |
| 15 | # RUN: symbol11 = ((0x28000 + 0x1fff) & ~(0x1000 + -1)); \ | 15 | # RUN: symbol11 = ((0x28000 + 0x1fff) & ~(0x1000 + -1)); \ |
| 16 | # RUN: symbol12 = 0x1234; \ | 16 | # RUN: symbol12 = 0x1234; \ |
| 17 | # RUN: symbol12 += 1; \ | 17 | # RUN: symbol12 += 1; \ |
| 18 | # RUN: symbol13 = !1; \ | ||
| 19 | # RUN: symbol14 = !0; \ | ||
| 20 | # RUN: symbol15 = 0!=1; \ | ||
| 18 | # RUN: bar = 0x5678; \ | 21 | # RUN: bar = 0x5678; \ |
| 19 | # RUN: baz = 0x9abc; \ | 22 | # RUN: baz = 0x9abc; \ |
| 20 | # RUN: }" > %t.script | 23 | # RUN: }" > %t.script |
| ... | @@ -39,6 +42,9 @@ | ... | @@ -39,6 +42,9 @@ |
| 39 | # CHECK-NEXT: fedcba9876543210 *ABS* 00000000 symbol10 | 42 | # CHECK-NEXT: fedcba9876543210 *ABS* 00000000 symbol10 |
| 40 | # CHECK-NEXT: 0000000000029000 *ABS* 00000000 symbol11 | 43 | # CHECK-NEXT: 0000000000029000 *ABS* 00000000 symbol11 |
| 41 | # CHECK-NEXT: 0000000000001235 *ABS* 00000000 symbol12 | 44 | # CHECK-NEXT: 0000000000001235 *ABS* 00000000 symbol12 |
| 45 | # CHECK-NEXT: 0000000000000000 *ABS* 00000000 symbol13 | ||
| 46 | # CHECK-NEXT: 0000000000000001 *ABS* 00000000 symbol14 | ||
| 47 | # CHECK-NEXT: 0000000000000001 *ABS* 00000000 symbol15 | ||
| 42 | 48 | ||
| 43 | # RUN: echo "SECTIONS { symbol2 = symbol; }" > %t2.script | 49 | # RUN: echo "SECTIONS { symbol2 = symbol; }" > %t2.script |
| 44 | # RUN: not ld.lld -o %t2 --script %t2.script %t 2>&1 \ | 50 | # RUN: not ld.lld -o %t2 --script %t2.script %t 2>&1 \ |
deps/lld/test/ELF/linkerscript/symbol-only-flags.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 { . = SIZEOF_HEADERS; \ | ||
| 4 | # RUN: .tbss : { *(.tbss) } \ | ||
| 5 | # RUN: .foo : { bar = .; } }" > %t.script | ||
| 6 | # RUN: ld.lld -o %t --script %t.script %t.o | ||
| 7 | # RUN: llvm-readobj -s %t | FileCheck %s | ||
| 8 | |||
| 9 | ## Check .foo does not get SHF_TLS flag. | ||
| 10 | # CHECK: Section { | ||
| 11 | # CHECK: Index: | ||
| 12 | # CHECK: Name: .foo | ||
| 13 | # CHECK-NEXT: Type: SHT_NOBITS | ||
| 14 | # CHECK-NEXT: Flags [ | ||
| 15 | # CHECK-NEXT: SHF_ALLOC | ||
| 16 | # CHECK-NEXT: SHF_WRITE | ||
| 17 | # CHECK-NEXT: ] | ||
| 18 | |||
| 19 | .section .tbss,"awT",@nobits | ||
| 20 | .quad 0 | ||
deps/lld/test/ELF/linkerscript/symbol-only.s+1-1| ... | @@ -12,7 +12,7 @@ | ... | @@ -12,7 +12,7 @@ |
| 12 | # CHECK: Sections: | 12 | # CHECK: Sections: |
| 13 | # CHECK-NEXT: Idx Name Size Address | 13 | # CHECK-NEXT: Idx Name Size Address |
| 14 | # CHECK-NEXT: 0 00000000 0000000000000000 | 14 | # CHECK-NEXT: 0 00000000 0000000000000000 |
| 15 | # CHECK: abc 00000000 [[ADDR:[0-9a-f]*]] DATA | 15 | # CHECK: abc 00000000 [[ADDR:[0-9a-f]*]] BSS |
| 16 | # CHECK-NEXT: bar 00000000 0000000000001000 DATA | 16 | # CHECK-NEXT: bar 00000000 0000000000001000 DATA |
| 17 | 17 | ||
| 18 | # CHECK: SYMBOL TABLE: | 18 | # CHECK: SYMBOL TABLE: |
deps/lld/test/ELF/linkerscript/symbol-ordering-file.s created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: echo "SECTIONS { .foo : { *(.foo) } }" > %t.script | ||
| 4 | |||
| 5 | # RUN: ld.lld %t.o --script %t.script -o %t.out | ||
| 6 | # RUN: llvm-objdump -s %t.out| FileCheck %s --check-prefix=BEFORE | ||
| 7 | # BEFORE: Contents of section .foo: | ||
| 8 | # BEFORE-NEXT: 1122 | ||
| 9 | |||
| 10 | # RUN: echo "_foo2" > %t.ord | ||
| 11 | # RUN: echo "_foo1" >> %t.ord | ||
| 12 | # RUN: ld.lld --symbol-ordering-file %t.ord %t.o --script %t.script -o %t2.out | ||
| 13 | # RUN: llvm-objdump -s %t2.out| FileCheck %s --check-prefix=AFTER | ||
| 14 | # AFTER: Contents of section .foo: | ||
| 15 | # AFTER-NEXT: 2211 | ||
| 16 | |||
| 17 | .section .foo,"ax",@progbits,unique,1 | ||
| 18 | _foo1: | ||
| 19 | .byte 0x11 | ||
| 20 | |||
| 21 | .section .foo,"ax",@progbits,unique,2 | ||
| 22 | _foo2: | ||
| 23 | .byte 0x22 | ||
deps/lld/test/ELF/linkerscript/symbol-reserved.s+28| ... | @@ -17,6 +17,34 @@ | ... | @@ -17,6 +17,34 @@ |
| 17 | 17 | ||
| 18 | # ALIGNED: 0000000000200005 .text 00000000 .hidden newsym | 18 | # ALIGNED: 0000000000200005 .text 00000000 .hidden newsym |
| 19 | 19 | ||
| 20 | # RUN: echo "PROVIDE_HIDDEN(newsym = ALIGN(3, 8) + 10);" > %t.script | ||
| 21 | # RUN: ld.lld -o %t1 %t.script %t | ||
| 22 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=ALIGN-ADD %s | ||
| 23 | # ALIGN-ADD: 0000000000000012 *ABS* 00000000 .hidden newsym | ||
| 24 | |||
| 25 | # RUN: echo "PROVIDE_HIDDEN(newsym = ALIGN(11, 8) - 10);" > %t.script | ||
| 26 | # RUN: ld.lld -o %t1 %t.script %t | ||
| 27 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=ALIGN-SUB %s | ||
| 28 | # ALIGN-SUB: 0000000000000006 *ABS* 00000000 .hidden newsym | ||
| 29 | |||
| 30 | # RUN: echo "PROVIDE_HIDDEN(newsym = ALIGN(_end, CONSTANT(MAXPAGESIZE)) + 5);" > %t.script | ||
| 31 | # RUN: ld.lld -o %t1 %t %t.script | ||
| 32 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=RELATIVE %s | ||
| 33 | # RELATIVE: 0000000000202005 .text 00000000 .hidden newsym | ||
| 34 | # RELATIVE: 0000000000201007 .text 00000000 _end | ||
| 35 | |||
| 36 | # RUN: echo "PROVIDE_HIDDEN(newsym = ALIGN(_end, CONSTANT(MAXPAGESIZE)) + 5);" > %t.script | ||
| 37 | # RUN: ld.lld -o %t1 --script %p/Inputs/symbol-reserved.script %t %t.script | ||
| 38 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=RELATIVE-ADD %s | ||
| 39 | # RELATIVE-ADD: 0000000000001005 .text 00000000 .hidden newsym | ||
| 40 | # RELATIVE-ADD: 0000000000000007 .text 00000000 .hidden _end | ||
| 41 | |||
| 42 | # RUN: echo "PROVIDE_HIDDEN(newsym = ALIGN(_end, CONSTANT(MAXPAGESIZE)) - 5);" > %t.script | ||
| 43 | # RUN: ld.lld -o %t1 --script %p/Inputs/symbol-reserved.script %t %t.script | ||
| 44 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=RELATIVE-SUB %s | ||
| 45 | # RELATIVE-SUB: 0000000000000ffb .text 00000000 .hidden newsym | ||
| 46 | # RELATIVE-SUB: 0000000000000007 .text 00000000 .hidden _end | ||
| 47 | |||
| 20 | .global _start | 48 | .global _start |
| 21 | _start: | 49 | _start: |
| 22 | lea newsym(%rip),%rax | 50 | lea newsym(%rip),%rax |
deps/lld/test/ELF/linkerscript/symbols.s+5-8| ... | @@ -12,14 +12,13 @@ | ... | @@ -12,14 +12,13 @@ |
| 12 | # The symbol is not referenced. Don't provide it. | 12 | # The symbol is not referenced. Don't provide it. |
| 13 | # RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script | 13 | # RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script |
| 14 | # RUN: ld.lld -o %t1 --script %t.script %t | 14 | # RUN: ld.lld -o %t1 --script %t.script %t |
| 15 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE1 %s | 15 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=DONTPROVIDE %s |
| 16 | # PROVIDE1-NOT: 0000000000000001 *ABS* 00000000 newsym | 16 | # DONTPROVIDE-NOT: newsym |
| 17 | 17 | ||
| 18 | # The symbol is not referenced. Don't provide it. | 18 | # The symbol is not referenced. Don't provide it. |
| 19 | # RUN: echo "SECTIONS { PROVIDE_HIDDEN(newsym = 1);}" > %t.script | 19 | # RUN: echo "SECTIONS { PROVIDE_HIDDEN(newsym = 1);}" > %t.script |
| 20 | # RUN: ld.lld -o %t1 --script %t.script %t | 20 | # RUN: ld.lld -o %t1 --script %t.script %t |
| 21 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN1 %s | 21 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=DONTPROVIDE %s |
| 22 | # HIDDEN1-NOT: 0000000000000001 *ABS* 00000000 .hidden newsym | ||
| 23 | 22 | ||
| 24 | # Provide existing symbol. The value should be 0, even though we | 23 | # Provide existing symbol. The value should be 0, even though we |
| 25 | # have value of 1 in PROVIDE() | 24 | # have value of 1 in PROVIDE() |
| ... | @@ -44,14 +43,12 @@ | ... | @@ -44,14 +43,12 @@ |
| 44 | # The symbol is not referenced. Don't provide it. | 43 | # The symbol is not referenced. Don't provide it. |
| 45 | # RUN: echo "PROVIDE(newsym = 1);" > %t.script | 44 | # RUN: echo "PROVIDE(newsym = 1);" > %t.script |
| 46 | # RUN: ld.lld -o %t1 --script %t.script %t | 45 | # RUN: ld.lld -o %t1 --script %t.script %t |
| 47 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE4 %s | 46 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=DONTPROVIDE %s |
| 48 | # PROVIDE4-NOT: 0000000000000001 *ABS* 00000000 newsym | ||
| 49 | 47 | ||
| 50 | # The symbol is not referenced. Don't provide it. | 48 | # The symbol is not referenced. Don't provide it. |
| 51 | # RUN: echo "PROVIDE_HIDDEN(newsym = 1);" > %t.script | 49 | # RUN: echo "PROVIDE_HIDDEN(newsym = 1);" > %t.script |
| 52 | # RUN: ld.lld -o %t1 --script %t.script %t | 50 | # RUN: ld.lld -o %t1 --script %t.script %t |
| 53 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN4 %s | 51 | # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=DONTPROVIDE %s |
| 54 | # HIDDEN4-NOT: 0000000000000001 *ABS* 00000000 .hidden newsym | ||
| 55 | 52 | ||
| 56 | # Provide existing symbol. The value should be 0, even though we | 53 | # Provide existing symbol. The value should be 0, even though we |
| 57 | # have value of 1 in PROVIDE() | 54 | # have value of 1 in PROVIDE() |
deps/lld/test/ELF/linkerscript/thunk-gen-mips.s created+40| ... | @@ -0,0 +1,40 @@ | ||
| 1 | # REQUIRES: mips | ||
| 2 | # RUN:	llvm-mc -filetype=obj -defsym=MAIN=1 -triple=mips-unknown-freebsd %s -o %t | ||
| 3 | # RUN:	llvm-mc -filetype=obj -defsym=TARGET=1 -triple=mips-unknown-freebsd %s -o %t1 | ||
| 4 | |||
| 5 | # SECTIONS command with the first pattern that does not match. | ||
| 6 | # Linking a PIC and non-PIC object files triggers the LA25 thunk generation. | ||
| 7 | # RUN:		echo "SECTIONS { \ | ||
| 8 | # RUN:		.text : { \ | ||
| 9 | # RUN:			*(.nomatch) \ | ||
| 10 | # RUN:			%t(.text) \ | ||
| 11 | # RUN:			. = . + 0x100000 ; \ | ||
| 12 | # RUN:			%t1(.text) \ | ||
| 13 | # RUN:		} \ | ||
| 14 | # RUN:	}" > %t.script | ||
| 15 | # RUN: ld.lld -o %t.exe --script %t.script %t %t1 | ||
| 16 | # RUN: llvm-objdump -t %t.exe | FileCheck %s | ||
| 17 | # CHECK: SYMBOL TABLE: | ||
| 18 | # CHECK-ANY: 00000000 .text 00000000 _start | ||
| 19 | # CHECK-ANY: 0010000c l F .text 00000010 __LA25Thunk_too_far | ||
| 20 | # CHECK-ANY: 00100020 g F .text 00000024 too_far | ||
| 21 | |||
| 22 | .ifdef MAIN | ||
| 23 | .global _start | ||
| 24 | _start: | ||
| 25 | 	j too_far | ||
| 26 | 	nop | ||
| 27 | .endif | ||
| 28 | |||
| 29 | .ifdef TARGET | ||
| 30 | 	.text | ||
| 31 | 	.abicalls | ||
| 32 | 	.set noreorder | ||
| 33 | 	.globl too_far | ||
| 34 | 	.ent too_far | ||
| 35 | too_far: | ||
| 36 | 	nop | ||
| 37 | 	jr $ra | ||
| 38 | 	nop | ||
| 39 | 	.end too_far | ||
| 40 | .endif | ||
deps/lld/test/ELF/linkerscript/unused-synthetic.s+10| ... | @@ -13,6 +13,16 @@ | ... | @@ -13,6 +13,16 @@ |
| 13 | # CHECK: .text | 13 | # CHECK: .text |
| 14 | # CHECK-NEXT: .dynsym | 14 | # CHECK-NEXT: .dynsym |
| 15 | 15 | ||
| 16 | # Test that the size of a removed unused synthetic input section is not added | ||
| 17 | # to the output section size. Adding a symbol assignment prevents removal of | ||
| 18 | # the output section, but does not cause the section size to be recomputed. | ||
| 19 | # RUN: echo "SECTIONS { \ | ||
| 20 | # RUN: .got.plt : { a_sym = .; *(.got.plt) } \ | ||
| 21 | # RUN: }" > %t2.script | ||
| 22 | # RUN: ld.lld -shared -o %t2.so --script %t2.script %t.o | ||
| 23 | # RUN: llvm-objdump -section-headers %t2.so | FileCheck %s --check-prefix=CHECK2 | ||
| 24 | # CHECK2: .got.plt 00000000 | ||
| 25 | |||
| 16 | .global _start | 26 | .global _start |
| 17 | _start: | 27 | _start: |
| 18 | nop | 28 | nop |
deps/lld/test/ELF/linkerscript/version-linker-symbol.s created+28| ... | @@ -0,0 +1,28 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: echo "VER1 { global: _end; foo ; local: * ; } ;" > %t.script | ||
| 4 | # 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.so | ||
| 6 | # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s | ||
| 7 | |||
| 8 | # CHECK: Name: _end@@VER1 | ||
| 9 | # CHECK-NEXT: Value: 0 | ||
| 10 | # CHECK-NEXT: Size: 0 | ||
| 11 | # CHECK-NEXT: Binding: Global | ||
| 12 | # CHECK-NEXT: Type: None | ||
| 13 | # CHECK-NEXT: Other: 0 | ||
| 14 | # CHECK-NEXT: Section: .dynamic | ||
| 15 | |||
| 16 | # CHECK: Name: foo@@VER1 | ||
| 17 | # CHECK-NEXT: Value: 0 | ||
| 18 | # CHECK-NEXT: Size: 0 | ||
| 19 | # CHECK-NEXT: Binding: Global | ||
| 20 | # CHECK-NEXT: Type: None | ||
| 21 | # CHECK-NEXT: Other: 0 | ||
| 22 | # CHECK-NEXT: Section: .text | ||
| 23 | |||
| 24 | .global foo | ||
| 25 | foo: | ||
| 26 | .data | ||
| 27 | .quad _end | ||
| 28 | .quad foo | ||
deps/lld/test/ELF/lit.local.cfg-1| ... | @@ -1,2 +1 @@ | ... | @@ -1,2 +1 @@ |
| 1 | config.suffixes = ['.test', '.s', '.ll'] | 1 | config.suffixes = ['.test', '.s', '.ll'] |
| 2 |
deps/lld/test/ELF/local-got-pie.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 2 | // RUN: ld.lld %t.o -o %t -pie | 2 | // RUN: ld.lld --hash-style=sysv %t.o -o %t -pie |
| 3 | // RUN: llvm-readobj -s -r -d %t | FileCheck %s | 3 | // RUN: llvm-readobj -s -r -d %t | FileCheck %s |
| 4 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s | 4 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s |
| 5 | 5 |
deps/lld/test/ELF/local-got-shared.s+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 2 | // RUN: ld.lld %t.o -o %t -shared | 2 | // RUN: ld.lld --hash-style=sysv %t.o -o %t -shared |
| 3 | // RUN: llvm-readobj -s -r -d %t | FileCheck %s | 3 | // RUN: llvm-readobj -s -r -d %t | FileCheck %s |
| 4 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s | 4 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s |
| 5 | 5 |
deps/lld/test/ELF/local-got.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o |
| 3 | // RUN: ld.lld -shared %t2.o -o %t2.so | 3 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 4 | // RUN: ld.lld %t.o %t2.so -o %t | 4 | // RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t |
| 5 | // RUN: llvm-readobj -s -r -section-data %t | FileCheck %s | 5 | // RUN: llvm-readobj -s -r -section-data %t | FileCheck %s |
| 6 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s | 6 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s |
| 7 | 7 |
deps/lld/test/ELF/lto-plugin-ignore.s created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | ||
| 4 | # RUN: ld.lld %t -plugin-opt=/foo/bar -plugin-opt=-fresolution=zed \ | ||
| 5 | # RUN: -plugin-opt=-pass-through=-lgcc -plugin-opt=-function-sections \ | ||
| 6 | # RUN: -plugin-opt=-data-sections -o /dev/null | ||
| 7 | |||
| 8 | # RUN: not ld.lld %t -plugin-opt=-data-sectionssss \ | ||
| 9 | # RUN: -plugin-opt=-function-sectionsss 2>&1 | FileCheck %s | ||
| 10 | # CHECK: unknown option: -data-sectionsss | ||
| 11 | # CHECK: unknown option: -function-sectionsss | ||
deps/lld/test/ELF/lto/Inputs/data-ordering-lto.ll created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 2 | target triple = "x86_64-scei-ps4" | ||
| 3 | |||
| 4 | @pat = global i32 33, align 4 | ||
| 5 | @tin = global i32 33, align 4 | ||
| 6 | @dipsy = global i32 33, align 4 | ||
deps/lld/test/ELF/lto/Inputs/linker-script-symbols-ipo.ll created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 2 | target triple = "x86_64-unknown-linux-gnu" | ||
| 3 | |||
| 4 | declare i32 @bar() | ||
| 5 | |||
| 6 | define i32 @_start() { | ||
| 7 | %1 = tail call i32 @bar() | ||
| 8 | ret i32 %1 | ||
| 9 | } | ||
deps/lld/test/ELF/lto/Inputs/symbol-ordering-lto.ll created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 2 | target triple = "x86_64-scei-ps4" | ||
| 3 | |||
| 4 | define i32 @tin() { | ||
| 5 | ret i32 22 | ||
| 6 | } | ||
| 7 | |||
| 8 | define i32 @pat() { | ||
| 9 | ret i32 42 | ||
| 10 | } | ||
deps/lld/test/ELF/lto/cache.ll+11-3| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | ; Create two files that would be removed by cache pruning due to age. | 7 | ; Create two files that would be removed by cache pruning due to age. |
| 8 | ; We should only remove files matching the pattern "llvmcache-*". | 8 | ; We should only remove files matching the pattern "llvmcache-*". |
| 9 | ; RUN: touch -t 197001011200 %t.cache/llvmcache-foo %t.cache/foo | 9 | ; RUN: touch -t 197001011200 %t.cache/llvmcache-foo %t.cache/foo |
| 10 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy prune_after=1h -o %t3 %t2.o %t.o | 10 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy prune_after=1h:prune_interval=0s -o %t3 %t2.o %t.o |
| 11 | 11 | ||
| 12 | ; Two cached objects, plus a timestamp file and "foo", minus the file we removed. | 12 | ; Two cached objects, plus a timestamp file and "foo", minus the file we removed. |
| 13 | ; RUN: ls %t.cache | count 4 | 13 | ; RUN: ls %t.cache | count 4 |
| ... | @@ -16,13 +16,21 @@ | ... | @@ -16,13 +16,21 @@ |
| 16 | ; RUN: %python -c "print(' ' * 65536)" > %t.cache/llvmcache-foo | 16 | ; RUN: %python -c "print(' ' * 65536)" > %t.cache/llvmcache-foo |
| 17 | 17 | ||
| 18 | ; This should leave the file in place. | 18 | ; This should leave the file in place. |
| 19 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k -o %t3 %t2.o %t.o | 19 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k:prune_interval=0s -o %t3 %t2.o %t.o |
| 20 | ; RUN: ls %t.cache | count 5 | 20 | ; RUN: ls %t.cache | count 5 |
| 21 | 21 | ||
| 22 | ; This should remove it. | 22 | ; This should remove it. |
| 23 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=32k -o %t3 %t2.o %t.o | 23 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=32k:prune_interval=0s -o %t3 %t2.o %t.o |
| 24 | ; RUN: ls %t.cache | count 4 | 24 | ; RUN: ls %t.cache | count 4 |
| 25 | 25 | ||
| 26 | ; Setting max number of files to 0 should disable the limit, not delete everything. | ||
| 27 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy prune_after=0s:cache_size=0%:cache_size_files=0:prune_interval=0s -o %t3 %t2.o %t.o | ||
| 28 | ; RUN: ls %t.cache | count 4 | ||
| 29 | |||
| 30 | ; Delete everything except for the timestamp, "foo" and one cache file. | ||
| 31 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy prune_after=0s:cache_size=0%:cache_size_files=1:prune_interval=0s -o %t3 %t2.o %t.o | ||
| 32 | ; RUN: ls %t.cache | count 3 | ||
| 33 | |||
| 26 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | 34 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| 27 | target triple = "x86_64-unknown-linux-gnu" | 35 | target triple = "x86_64-unknown-linux-gnu" |
| 28 | 36 |
deps/lld/test/ELF/lto/data-ordering-lto.s created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-scei-ps4 %s -o %t.o | ||
| 3 | # RUN: llvm-as %p/Inputs/data-ordering-lto.ll -o %t.bc | ||
| 4 | |||
| 5 | # Set up the symbol file | ||
| 6 | # RUN: echo "tin " > %t_order_lto.txt | ||
| 7 | # RUN: echo "dipsy " >> %t_order_lto.txt | ||
| 8 | # RUN: echo "pat " >> %t_order_lto.txt | ||
| 9 | |||
| 10 | # RUN: ld.lld --symbol-ordering-file %t_order_lto.txt %t.o %t.bc -o %t2.out | ||
| 11 | # RUN: llvm-readobj -elf-output-style=GNU -t %t2.out| FileCheck %s | ||
| 12 | |||
| 13 | # Check that the order is tin -> dipsy -> pat. | ||
| 14 | |||
| 15 | # CHECK: Symbol table '.symtab' contains 5 entries: | ||
| 16 | # CHECK-NEXT: Num: Value Size Type Bind Vis Ndx Name | ||
| 17 | # CHECK-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND | ||
| 18 | # CHECK-NEXT: 1: 0000000000201000 0 NOTYPE GLOBAL DEFAULT 1 _start | ||
| 19 | # CHECK-NEXT: 2: 0000000000202004 4 OBJECT GLOBAL DEFAULT 2 dipsy | ||
| 20 | # CHECK-NEXT: 3: 0000000000202008 4 OBJECT GLOBAL DEFAULT 2 pat | ||
| 21 | # CHECK-NEXT: 4: 0000000000202000 4 OBJECT GLOBAL DEFAULT 2 tin | ||
| 22 | |||
| 23 | .globl _start | ||
| 24 | _start: | ||
| 25 | movl $pat, %ecx | ||
| 26 | movl $dipsy, %ebx | ||
| 27 | movl $tin, %eax | ||
deps/lld/test/ELF/lto/keep-undefined.ll created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | ; REQUIRES: x86 | ||
| 2 | ; This test checks that symbols which are specified in "-u" switches | ||
| 3 | ; are kept over LTO if we link an executable. | ||
| 4 | ; RUN: llvm-as %s -o %t.o | ||
| 5 | ; RUN: ld.lld -m elf_x86_64 %t.o -o %tout -u foo | ||
| 6 | ; RUN: llvm-nm %tout | FileCheck %s | ||
| 7 | |||
| 8 | ; CHECK: T foo | ||
| 9 | |||
| 10 | target triple = "x86_64-unknown-linux-gnu" | ||
| 11 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 12 | |||
| 13 | define void @foo() { | ||
| 14 | ret void | ||
| 15 | } | ||
| 16 | |||
| 17 | define void @_start() { | ||
| 18 | call void @foo() | ||
| 19 | ret void | ||
| 20 | } | ||
deps/lld/test/ELF/lto/linker-script-symbols-assign.ll created+48| ... | @@ -0,0 +1,48 @@ | ||
| 1 | ; REQUIRES: x86 | ||
| 2 | ; RUN: llvm-as %s -o %t.o | ||
| 3 | |||
| 4 | ; RUN: echo "foo = 1;" > %t.script | ||
| 5 | ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 --script %t.script -save-temps | ||
| 6 | ; RUN: llvm-readobj -symbols %t2.lto.o | FileCheck %s | ||
| 7 | |||
| 8 | ; CHECK-NOT: bar | ||
| 9 | ; CHECK: Symbol { | ||
| 10 | ; CHECK: Name: foo | ||
| 11 | ; CHECK-NEXT: Value: 0x0 | ||
| 12 | ; CHECK-NEXT: Size: 4 | ||
| 13 | ; CHECK-NEXT: Binding: Weak | ||
| 14 | ; CHECK-NEXT: Type: Object | ||
| 15 | ; CHECK-NEXT: Other: 0 | ||
| 16 | ; CHECK-NEXT: Section: .bss.foo | ||
| 17 | ; CHECK-NEXT: } | ||
| 18 | ; CHECK-NEXT:] | ||
| 19 | |||
| 20 | ; RUN: llvm-readobj -symbols %t2 | FileCheck %s --check-prefix=VAL | ||
| 21 | ; VAL: Symbol { | ||
| 22 | ; VAL: Name: foo | ||
| 23 | ; VAL-NEXT: Value: 0x1 | ||
| 24 | ; VAL-NEXT: Size: | ||
| 25 | ; VAL-NEXT: Binding: Global | ||
| 26 | ; VAL-NEXT: Type: None | ||
| 27 | ; VAL-NEXT: Other: | ||
| 28 | ; VAL-NEXT: Section: Absolute | ||
| 29 | ; VAL-NEXT: } | ||
| 30 | |||
| 31 | ; RUN: echo "zed = 1;" > %t2.script | ||
| 32 | ; RUN: ld.lld -m elf_x86_64 %t.o -o %t3 --script %t2.script | ||
| 33 | ; RUN: llvm-readobj -symbols %t3 | FileCheck %s --check-prefix=ABS | ||
| 34 | ; ABS: Symbol { | ||
| 35 | ; ABS: Name: zed | ||
| 36 | ; ABS-NEXT: Value: 0x1 | ||
| 37 | ; ABS-NEXT: Size: 0 | ||
| 38 | ; ABS-NEXT: Binding: Global | ||
| 39 | ; ABS-NEXT: Type: None | ||
| 40 | ; ABS-NEXT: Other: 0 | ||
| 41 | ; ABS-NEXT: Section: Absolute | ||
| 42 | ; ABS-NEXT: } | ||
| 43 | |||
| 44 | target triple = "x86_64-unknown-linux-gnu" | ||
| 45 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 46 | |||
| 47 | @foo = global i32 0 | ||
| 48 | @bar = global i32 0 | ||
deps/lld/test/ELF/lto/linker-script-symbols-ipo.ll created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | ; REQUIRES: x86 | ||
| 2 | ; RUN: llvm-as %s -o %t1.o | ||
| 3 | ; RUN: llvm-as %S/Inputs/linker-script-symbols-ipo.ll -o %t2.o | ||
| 4 | ; RUN: echo "bar = foo;" > %t.script | ||
| 5 | |||
| 6 | ;; Check that without linkerscript bar is inlined. | ||
| 7 | ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t3 -save-temps | ||
| 8 | ; RUN: llvm-objdump -d %t3 | FileCheck %s --check-prefix=IPO | ||
| 9 | ; IPO: Disassembly of section .text: | ||
| 10 | ; IPO: _start: | ||
| 11 | ; IPO-NEXT: 201000: {{.*}} movl $1, %eax | ||
| 12 | ; IPO-NEXT: 201005: {{.*}} retq | ||
| 13 | |||
| 14 | ;; Check that LTO does not do IPO for symbols assigned by script. | ||
| 15 | ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t4 --script %t.script -save-temps | ||
| 16 | ; RUN: llvm-objdump -d %t4 | FileCheck %s --check-prefix=NOIPO | ||
| 17 | ; NOIPO: Disassembly of section .text: | ||
| 18 | ; NOIPO: foo: | ||
| 19 | ; NOIPO-NEXT: 201010: {{.*}} movl $2, %eax | ||
| 20 | ; NOIPO: _start: | ||
| 21 | ; NOIPO-NEXT: 201020: {{.*}} jmp -21 <foo> | ||
| 22 | |||
| 23 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 24 | target triple = "x86_64-unknown-linux-gnu" | ||
| 25 | |||
| 26 | define i32 @bar() { | ||
| 27 | ret i32 1 | ||
| 28 | } | ||
| 29 | |||
| 30 | define i32 @foo() { | ||
| 31 | ret i32 2 | ||
| 32 | } | ||
deps/lld/test/ELF/lto/linker-script-symbols.ll created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | ; REQUIRES: x86 | ||
| 2 | ; RUN: llvm-as %s -o %t.o | ||
| 3 | ; RUN: echo "foo = bar;" > %t.script | ||
| 4 | |||
| 5 | ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 --script %t.script -save-temps | ||
| 6 | ; RUN: llvm-readobj -symbols %t2.lto.o | FileCheck %s | ||
| 7 | |||
| 8 | ; CHECK-NOT: zed | ||
| 9 | ; CHECK: Symbol { | ||
| 10 | ; CHECK: Name: bar | ||
| 11 | ; CHECK-NEXT: Value: | ||
| 12 | ; CHECK-NEXT: Size: | ||
| 13 | ; CHECK-NEXT: Binding: Global | ||
| 14 | ; CHECK-NEXT: Type: Function | ||
| 15 | ; CHECK-NEXT: Other: | ||
| 16 | ; CHECK-NEXT: Section: | ||
| 17 | ; CHECK-NEXT: } | ||
| 18 | ; CHECK-NOT: zed | ||
| 19 | |||
| 20 | target triple = "x86_64-unknown-linux-gnu" | ||
| 21 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 22 | |||
| 23 | define void @bar() { | ||
| 24 | ret void | ||
| 25 | } | ||
| 26 | |||
| 27 | define void @zed() { | ||
| 28 | ret void | ||
| 29 | } | ||
deps/lld/test/ELF/lto/opt-level.ll+17-4| ... | @@ -2,18 +2,31 @@ | ... | @@ -2,18 +2,31 @@ |
| 2 | ; RUN: llvm-as -o %t.o %s | 2 | ; RUN: llvm-as -o %t.o %s |
| 3 | ; RUN: ld.lld -o %t0 -m elf_x86_64 -e main --lto-O0 %t.o | 3 | ; RUN: ld.lld -o %t0 -m elf_x86_64 -e main --lto-O0 %t.o |
| 4 | ; RUN: llvm-nm %t0 | FileCheck --check-prefix=CHECK-O0 %s | 4 | ; RUN: llvm-nm %t0 | FileCheck --check-prefix=CHECK-O0 %s |
| 5 | ; RUN: ld.lld -o %t0 -m elf_x86_64 -e main --plugin-opt=O0 %t.o | ||
| 6 | ; RUN: llvm-nm %t0 | FileCheck --check-prefix=CHECK-O0 %s | ||
| 5 | ; RUN: ld.lld -o %t2 -m elf_x86_64 -e main --lto-O2 %t.o | 7 | ; RUN: ld.lld -o %t2 -m elf_x86_64 -e main --lto-O2 %t.o |
| 6 | ; RUN: llvm-nm %t2 | FileCheck --check-prefix=CHECK-O2 %s | 8 | ; RUN: llvm-nm %t2 | FileCheck --check-prefix=CHECK-O2 %s |
| 7 | ; RUN: ld.lld -o %t2a -m elf_x86_64 -e main %t.o | 9 | ; RUN: ld.lld -o %t2a -m elf_x86_64 -e main %t.o |
| 8 | ; RUN: llvm-nm %t2a | FileCheck --check-prefix=CHECK-O2 %s | 10 | ; RUN: llvm-nm %t2a | FileCheck --check-prefix=CHECK-O2 %s |
| 11 | ; RUN: ld.lld -o %t2 -m elf_x86_64 -e main --plugin-opt=O2 %t.o | ||
| 12 | ; RUN: llvm-nm %t2 | FileCheck --check-prefix=CHECK-O2 %s | ||
| 9 | 13 | ||
| 10 | ; Reject invalid optimization levels. | 14 | ; Reject invalid optimization levels. |
| 11 | ; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O6 %t.o 2>&1 | \ | 15 | ; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O6 %t.o 2>&1 | \ |
| 12 | ; RUN: FileCheck --check-prefix=INVALID %s | 16 | ; RUN: FileCheck --check-prefix=INVALID1 %s |
| 13 | ; INVALID: invalid optimization level for LTO: 6 | 17 | ; INVALID1: invalid optimization level for LTO: 6 |
| 18 | ; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --plugin-opt=O6 %t.o 2>&1 | \ | ||
| 19 | ; RUN: FileCheck --check-prefix=INVALID1 %s | ||
| 20 | ; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --plugin-opt=Ofoo %t.o 2>&1 | \ | ||
| 21 | ; RUN: FileCheck --check-prefix=INVALID2 %s | ||
| 22 | ; INVALID2: --plugin-opt: number expected, but got 'foo' | ||
| 23 | |||
| 14 | ; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O-1 %t.o 2>&1 | \ | 24 | ; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O-1 %t.o 2>&1 | \ |
| 15 | ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE %s | 25 | ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE1 %s |
| 16 | ; INVALIDNEGATIVE: invalid optimization level for LTO: -1 | 26 | ; INVALIDNEGATIVE1: invalid optimization level for LTO: 4294967295 |
| 27 | ; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --plugin-opt=O-1 %t.o 2>&1 | \ | ||
| 28 | ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE2 %s | ||
| 29 | ; INVALIDNEGATIVE2: invalid optimization level for LTO: 4294967295 | ||
| 17 | 30 | ||
| 18 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | 31 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| 19 | target triple = "x86_64-unknown-linux-gnu" | 32 | target triple = "x86_64-unknown-linux-gnu" |
deps/lld/test/ELF/lto/opt-remarks.ll+10-15| ... | @@ -15,13 +15,13 @@ | ... | @@ -15,13 +15,13 @@ |
| 15 | ; CHECK-NEXT: ret i32 %a.i | 15 | ; CHECK-NEXT: ret i32 %a.i |
| 16 | ; CHECK-NEXT: } | 16 | ; CHECK-NEXT: } |
| 17 | 17 | ||
| 18 | ; YAML: --- !Analysis | 18 | ; YAML: --- !Passed |
| 19 | ; YAML-NEXT: Pass: inline | 19 | ; YAML-NEXT: Pass: inline |
| 20 | ; YAML-NEXT: Name: CanBeInlined | 20 | ; YAML-NEXT: Name: Inlined |
| 21 | ; YAML-NEXT: Function: main | 21 | ; YAML-NEXT: Function: main |
| 22 | ; YAML-NEXT: Args: | 22 | ; YAML-NEXT: Args: |
| 23 | ; YAML-NEXT: - Callee: tinkywinky | 23 | ; YAML-NEXT: - Callee: tinkywinky |
| 24 | ; YAML-NEXT: - String: ' can be inlined into ' | 24 | ; YAML-NEXT: - String: ' inlined into ' |
| 25 | ; YAML-NEXT: - Caller: main | 25 | ; YAML-NEXT: - Caller: main |
| 26 | ; YAML-NEXT: - String: ' with cost=' | 26 | ; YAML-NEXT: - String: ' with cost=' |
| 27 | ; YAML-NEXT: - Cost: '0' | 27 | ; YAML-NEXT: - Cost: '0' |
| ... | @@ -29,19 +29,9 @@ | ... | @@ -29,19 +29,9 @@ |
| 29 | ; YAML-NEXT: - Threshold: '337' | 29 | ; YAML-NEXT: - Threshold: '337' |
| 30 | ; YAML-NEXT: - String: ')' | 30 | ; YAML-NEXT: - String: ')' |
| 31 | ; YAML-NEXT: ... | 31 | ; YAML-NEXT: ... |
| 32 | ; YAML-NEXT: --- !Passed | ||
| 33 | ; YAML-NEXT: Pass: inline | ||
| 34 | ; YAML-NEXT: Name: Inlined | ||
| 35 | ; YAML-NEXT: Function: main | ||
| 36 | ; YAML-NEXT: Args: | ||
| 37 | ; YAML-NEXT: - Callee: tinkywinky | ||
| 38 | ; YAML-NEXT: - String: ' inlined into ' | ||
| 39 | ; YAML-NEXT: - Caller: main | ||
| 40 | ; YAML-NEXT: ... | ||
| 41 | 32 | ||
| 42 | ; YAML-HOT: ... | 33 | ; YAML-HOT: --- !Passed |
| 43 | ; YAML-HOT: --- !Passed | 34 | ; YAML-HOT-NEXT: Pass: inline |
| 44 | ; YAML-HOT: Pass: inline | ||
| 45 | ; YAML-HOT-NEXT: Name: Inlined | 35 | ; YAML-HOT-NEXT: Name: Inlined |
| 46 | ; YAML-HOT-NEXT: Function: main | 36 | ; YAML-HOT-NEXT: Function: main |
| 47 | ; YAML-HOT-NEXT: Hotness: 300 | 37 | ; YAML-HOT-NEXT: Hotness: 300 |
| ... | @@ -49,6 +39,11 @@ | ... | @@ -49,6 +39,11 @@ |
| 49 | ; YAML-HOT-NEXT: - Callee: tinkywinky | 39 | ; YAML-HOT-NEXT: - Callee: tinkywinky |
| 50 | ; YAML-HOT-NEXT: - String: ' inlined into ' | 40 | ; YAML-HOT-NEXT: - String: ' inlined into ' |
| 51 | ; YAML-HOT-NEXT: - Caller: main | 41 | ; YAML-HOT-NEXT: - Caller: main |
| 42 | ; YAML-HOT-NEXT: - String: ' with cost=' | ||
| 43 | ; YAML-HOT-NEXT: - Cost: '0' | ||
| 44 | ; YAML-HOT-NEXT: - String: ' (threshold=' | ||
| 45 | ; YAML-HOT-NEXT: - Threshold: '337' | ||
| 46 | ; YAML-HOT-NEXT: - String: ')' | ||
| 52 | ; YAML-HOT-NEXT: ... | 47 | ; YAML-HOT-NEXT: ... |
| 53 | 48 | ||
| 54 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | 49 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
deps/lld/test/ELF/lto/relocatable.ll created+55| ... | @@ -0,0 +1,55 @@ | ||
| 1 | ; REQUIRES: x86 | ||
| 2 | ; RUN: llvm-as %s -o %t1.o | ||
| 3 | ; RUN: ld.lld %t1.o -r -o %t | ||
| 4 | ; RUN: llvm-readobj -symbols %t | FileCheck %s | ||
| 5 | |||
| 6 | ; CHECK: Symbols [ | ||
| 7 | ; CHECK-NEXT: Symbol { | ||
| 8 | ; CHECK-NEXT: Name: | ||
| 9 | ; CHECK-NEXT: Value: 0x0 | ||
| 10 | ; CHECK-NEXT: Size: 0 | ||
| 11 | ; CHECK-NEXT: Binding: Local | ||
| 12 | ; CHECK-NEXT: Type: None | ||
| 13 | ; CHECK-NEXT: Other: 0 | ||
| 14 | ; CHECK-NEXT: Section: Undefined | ||
| 15 | ; CHECK-NEXT: } | ||
| 16 | ; CHECK-NEXT: Symbol { | ||
| 17 | ; CHECK-NEXT: Name: | ||
| 18 | ; CHECK-NEXT: Value: 0x0 | ||
| 19 | ; CHECK-NEXT: Size: 0 | ||
| 20 | ; CHECK-NEXT: Binding: Local | ||
| 21 | ; CHECK-NEXT: Type: Section | ||
| 22 | ; CHECK-NEXT: Other: 0 | ||
| 23 | ; CHECK-NEXT: Section: .text | ||
| 24 | ; CHECK-NEXT: } | ||
| 25 | ; CHECK-NEXT: Symbol { | ||
| 26 | ; CHECK-NEXT: Name: | ||
| 27 | ; CHECK-NEXT: Value: 0x0 | ||
| 28 | ; CHECK-NEXT: Size: 0 | ||
| 29 | ; CHECK-NEXT: Binding: Local | ||
| 30 | ; CHECK-NEXT: Type: Section | ||
| 31 | ; CHECK-NEXT: Other: 0 | ||
| 32 | ; CHECK-NEXT: Section: .text.foo | ||
| 33 | ; CHECK-NEXT: } | ||
| 34 | ; CHECK-NEXT: Symbol { | ||
| 35 | ; CHECK-NEXT: Name: foo | ||
| 36 | ; CHECK-NEXT: Value: 0x0 | ||
| 37 | ; CHECK-NEXT: Size: 1 | ||
| 38 | ; CHECK-NEXT: Binding: Global | ||
| 39 | ; CHECK-NEXT: Type: Function | ||
| 40 | ; CHECK-NEXT: Other: 0 | ||
| 41 | ; CHECK-NEXT: Section: .text.foo | ||
| 42 | ; CHECK-NEXT: } | ||
| 43 | ; CHECK-NEXT: ] | ||
| 44 | |||
| 45 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 46 | target triple = "x86_64-unknown-linux-gnu" | ||
| 47 | |||
| 48 | define void @foo() { | ||
| 49 | call void @bar() | ||
| 50 | ret void | ||
| 51 | } | ||
| 52 | |||
| 53 | define internal void @bar() { | ||
| 54 | ret void | ||
| 55 | } | ||
deps/lld/test/ELF/lto/save-temps.ll+7| ... | @@ -9,6 +9,13 @@ | ... | @@ -9,6 +9,13 @@ |
| 9 | ; RUN: llvm-nm a.out.lto.o | FileCheck %s | 9 | ; RUN: llvm-nm a.out.lto.o | FileCheck %s |
| 10 | ; RUN: llvm-dis a.out.0.0.preopt.bc | 10 | ; RUN: llvm-dis a.out.0.0.preopt.bc |
| 11 | 11 | ||
| 12 | ; RUN: rm -f a.out a.out.lto.bc a.out.lto.o | ||
| 13 | ; RUN: ld.lld -shared -m elf_x86_64 %t.o %t2.o --plugin-opt=save-temps | ||
| 14 | ; RUN: llvm-nm a.out | FileCheck %s | ||
| 15 | ; RUN: llvm-nm a.out.0.0.preopt.bc | FileCheck %s | ||
| 16 | ; RUN: llvm-nm a.out.lto.o | FileCheck %s | ||
| 17 | ; RUN: llvm-dis a.out.0.0.preopt.bc | ||
| 18 | |||
| 12 | target triple = "x86_64-unknown-linux-gnu" | 19 | target triple = "x86_64-unknown-linux-gnu" |
| 13 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | 20 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| 14 | 21 |
deps/lld/test/ELF/lto/section-name.ll created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | ; REQUIRES: x86 | ||
| 2 | ; RUN: llvm-as %s -o %t.o | ||
| 3 | ; RUN: ld.lld %t.o -o %t.so -shared | ||
| 4 | ; RUN: llvm-readelf -s %t.so | FileCheck %s | ||
| 5 | ; RUN: ld.lld %t.o -o %t.so -shared --gc-sections | ||
| 6 | ; RUN: llvm-readelf -s %t.so | FileCheck --check-prefix=GC %s | ||
| 7 | |||
| 8 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| 9 | target triple = "x86_64-unknown-linux-gnu" | ||
| 10 | |||
| 11 | @foo = hidden global i32 42, section "foo_section" | ||
| 12 | @bar = hidden global i32 42, section "bar_section" | ||
| 13 | @zed = hidden global i32 42, section "zed_section" | ||
| 14 | |||
| 15 | @__start_foo_section = external global i32 | ||
| 16 | @__stop_bar_section = external global i32 | ||
| 17 | |||
| 18 | define hidden i32* @use1() { | ||
| 19 | ret i32* @__start_foo_section | ||
| 20 | } | ||
| 21 | |||
| 22 | define i32* @use2() { | ||
| 23 | ret i32* @__stop_bar_section | ||
| 24 | } | ||
| 25 | |||
| 26 | ; CHECK-NOT: zed_section | ||
| 27 | ; CHECK: foo_section PROGBITS | ||
| 28 | ; CHECK-NEXT: bar_section PROGBITS | ||
| 29 | ; CHECK-NOT: zed_section | ||
| 30 | |||
| 31 | ; GC-NOT: zed_section | ||
| 32 | ; GC-NOT: foo_section | ||
| 33 | ; GC: bar_section PROGBITS | ||
| 34 | ; GC-NOT: zed_section | ||
| 35 | ; GC-NOT: foo_section | ||
deps/lld/test/ELF/lto/shlib-undefined.ll+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | ; REQUIRES: x86 | 1 | ; REQUIRES: x86 |
| 2 | ; RUN: llvm-as %s -o %t.o | 2 | ; RUN: llvm-as %s -o %t.o |
| 3 | ; RUN: echo .global __progname > %t2.s | 3 | ; RUN: echo ".global __progname; .data; .dc.a __progname" > %t2.s |
| 4 | ; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o | 4 | ; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o |
| 5 | ; RUN: ld.lld -shared %t2.o -o %t2.so | 5 | ; RUN: ld.lld -shared %t2.o -o %t2.so |
| 6 | ; RUN: ld.lld -o %t %t.o %t2.so | 6 | ; RUN: ld.lld -o %t %t.o %t2.so |
deps/lld/test/ELF/lto/symbol-ordering-lto.s created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-scei-ps4 %s -o %t.o | ||
| 3 | # RUN: llvm-as %p/Inputs/symbol-ordering-lto.ll -o %t.bc | ||
| 4 | |||
| 5 | # Set up the symbol file | ||
| 6 | # RUN: echo "tin " > %t_order_lto.txt | ||
| 7 | # RUN: echo "_start " >> %t_order_lto.txt | ||
| 8 | # RUN: echo "pat " >> %t_order_lto.txt | ||
| 9 | |||
| 10 | # RUN: ld.lld --symbol-ordering-file %t_order_lto.txt %t.o %t.bc -o %t2.out | ||
| 11 | # RUN: llvm-readobj -elf-output-style=GNU -t %t2.out| FileCheck %s | ||
| 12 | |||
| 13 | # Check that the order is tin -> _start -> pat. | ||
| 14 | |||
| 15 | # CHECK: Symbol table '.symtab' contains 4 entries: | ||
| 16 | # CHECK-NEXT: Num: Value Size Type Bind Vis Ndx Name | ||
| 17 | # CHECK-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND | ||
| 18 | # CHECK-NEXT: 1: 0000000000201008 0 NOTYPE GLOBAL DEFAULT 1 _start | ||
| 19 | # CHECK-NEXT: 2: 0000000000201020 6 FUNC GLOBAL DEFAULT 1 pat | ||
| 20 | # CHECK-NEXT: 3: 0000000000201000 6 FUNC GLOBAL DEFAULT 1 tin | ||
| 21 | |||
| 22 | .globl _start | ||
| 23 | _start: | ||
| 24 | call pat | ||
| 25 | call tin | ||
deps/lld/test/ELF/lto/thinlto.ll+4-4| ... | @@ -6,14 +6,14 @@ | ... | @@ -6,14 +6,14 @@ |
| 6 | ; First force single-threaded mode | 6 | ; First force single-threaded mode |
| 7 | ; RUN: rm -f %t.lto.o %t1.lto.o | 7 | ; RUN: rm -f %t.lto.o %t1.lto.o |
| 8 | ; RUN: ld.lld -save-temps --thinlto-jobs=1 -shared %t.o %t2.o -o %t | 8 | ; RUN: ld.lld -save-temps --thinlto-jobs=1 -shared %t.o %t2.o -o %t |
| 9 | ; RUN: llvm-nm %t.lto.o | FileCheck %s --check-prefix=NM1 | 9 | ; RUN: llvm-nm %t1.lto.o | FileCheck %s --check-prefix=NM1 |
| 10 | ; RUN: llvm-nm %t1.lto.o | FileCheck %s --check-prefix=NM2 | 10 | ; RUN: llvm-nm %t2.lto.o | FileCheck %s --check-prefix=NM2 |
| 11 | 11 | ||
| 12 | ; Next force multi-threaded mode | 12 | ; Next force multi-threaded mode |
| 13 | ; RUN: rm -f %t2.lto.o %t21.lto.o | 13 | ; RUN: rm -f %t2.lto.o %t21.lto.o |
| 14 | ; RUN: ld.lld -save-temps --thinlto-jobs=2 -shared %t.o %t2.o -o %t2 | 14 | ; RUN: ld.lld -save-temps --thinlto-jobs=2 -shared %t.o %t2.o -o %t2 |
| 15 | ; RUN: llvm-nm %t2.lto.o | FileCheck %s --check-prefix=NM1 | 15 | ; RUN: llvm-nm %t21.lto.o | FileCheck %s --check-prefix=NM1 |
| 16 | ; RUN: llvm-nm %t21.lto.o | FileCheck %s --check-prefix=NM2 | 16 | ; RUN: llvm-nm %t22.lto.o | FileCheck %s --check-prefix=NM2 |
| 17 | 17 | ||
| 18 | ; NM1: T f | 18 | ; NM1: T f |
| 19 | ; NM1-NOT: U g | 19 | ; NM1-NOT: U g |
deps/lld/test/ELF/lto/verify-invalid.ll+2| ... | @@ -4,6 +4,8 @@ | ... | @@ -4,6 +4,8 @@ |
| 4 | ; RUN: 2>&1 | FileCheck -check-prefix=DEFAULT %s | 4 | ; RUN: 2>&1 | FileCheck -check-prefix=DEFAULT %s |
| 5 | ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -mllvm -debug-pass=Arguments \ | 5 | ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -mllvm -debug-pass=Arguments \ |
| 6 | ; RUN: -disable-verify 2>&1 | FileCheck -check-prefix=DISABLE %s | 6 | ; RUN: -disable-verify 2>&1 | FileCheck -check-prefix=DISABLE %s |
| 7 | ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -mllvm -debug-pass=Arguments \ | ||
| 8 | ; RUN: --plugin-opt=disable-verify 2>&1 | FileCheck -check-prefix=DISABLE %s | ||
| 7 | 9 | ||
| 8 | target triple = "x86_64-unknown-linux-gnu" | 10 | target triple = "x86_64-unknown-linux-gnu" |
| 9 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | 11 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
deps/lld/test/ELF/lto/wrap-1.ll+1-1| ... | @@ -19,7 +19,7 @@ | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 | ||
| 20 | ; Make sure that the 'r' (linker redefined) bit is set for bar and __wrap_bar | 20 | ; Make sure that the 'r' (linker redefined) bit is set for bar and __wrap_bar |
| 21 | ; in the resolutions file. | 21 | ; in the resolutions file. |
| 22 | ; RESOLS: ,bar,r | 22 | ; RESOLS: ,bar,xr |
| 23 | ; RESOLS: ,__wrap_bar,px | 23 | ; RESOLS: ,__wrap_bar,px |
| 24 | ; RESOLS: ,__real_bar,pxr | 24 | ; RESOLS: ,__real_bar,pxr |
| 25 | 25 |
deps/lld/test/ELF/lto/wrap-2.ll+2-2| ... | @@ -28,11 +28,11 @@ | ... | @@ -28,11 +28,11 @@ |
| 28 | ; THIN-NEXT: jmp{{.*}}<bar> | 28 | ; THIN-NEXT: jmp{{.*}}<bar> |
| 29 | 29 | ||
| 30 | ; Check that bar and __wrap_bar retain their original binding. | 30 | ; Check that bar and __wrap_bar retain their original binding. |
| 31 | ; BIND: Name: bar | 31 | ; BIND: Name: __wrap_bar |
| 32 | ; BIND-NEXT: Value: | 32 | ; BIND-NEXT: Value: |
| 33 | ; BIND-NEXT: Size: | 33 | ; BIND-NEXT: Size: |
| 34 | ; BIND-NEXT: Binding: Local | 34 | ; BIND-NEXT: Binding: Local |
| 35 | ; BIND: Name: __wrap_bar | 35 | ; BIND: Name: bar |
| 36 | ; BIND-NEXT: Value: | 36 | ; BIND-NEXT: Value: |
| 37 | ; BIND-NEXT: Size: | 37 | ; BIND-NEXT: Size: |
| 38 | ; BIND-NEXT: Binding: Local | 38 | ; BIND-NEXT: Binding: Local |
deps/lld/test/ELF/many-alloc-sections.s+1-2| ... | @@ -1,8 +1,7 @@ | ... | @@ -1,8 +1,7 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o |
| 3 | // RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script | 3 | // RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script |
| 4 | // FIXME: threads are disable because the test is too slow with them (PR32942). | 4 | // RUN: ld.lld -T %t.script %t.o -o %t |
| 5 | // RUN: ld.lld -T %t.script %t.o -o %t --no-threads | ||
| 6 | // RUN: llvm-readobj -t %t | FileCheck %s | 5 | // RUN: llvm-readobj -t %t | FileCheck %s |
| 7 | 6 | ||
| 8 | // Test that _start is in the correct section. | 7 | // Test that _start is in the correct section. |
deps/lld/test/ELF/many-sections.s+2-5| ... | @@ -11,15 +11,12 @@ | ... | @@ -11,15 +11,12 @@ |
| 11 | // CHECK-NEXT: Other: 0 | 11 | // CHECK-NEXT: Other: 0 |
| 12 | // CHECK-NEXT: Section: dm (0xFF00) | 12 | // CHECK-NEXT: Section: dm (0xFF00) |
| 13 | 13 | ||
| 14 | 14 | // RUN: ld.lld %t -o %t2 | |
| 15 | // FIXME: threads are disable because the test is too slow with them (PR32942). | ||
| 16 | // RUN: ld.lld %t -o %t2 --no-threads | ||
| 17 | // RUN: llvm-readobj -t %t2 | FileCheck --check-prefix=LINKED %s | 15 | // RUN: llvm-readobj -t %t2 | FileCheck --check-prefix=LINKED %s |
| 18 | 16 | ||
| 19 | // Test also with a linker script. | 17 | // Test also with a linker script. |
| 20 | // RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script | 18 | // RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script |
| 21 | // FIXME: threads are disable because the test is too slow with them (PR32942). | 19 | // RUN: ld.lld -T %t.script %t -o %t2 |
| 22 | // RUN: ld.lld -T %t.script %t -o %t2 --no-threads | ||
| 23 | // RUN: llvm-readobj -t %t2 | FileCheck --check-prefix=LINKED %s | 20 | // RUN: llvm-readobj -t %t2 | FileCheck --check-prefix=LINKED %s |
| 24 | 21 | ||
| 25 | // Test that _start is in the correct section. | 22 | // Test that _start is in the correct section. |
deps/lld/test/ELF/map-file.s+60-26| ... | @@ -4,15 +4,21 @@ | ... | @@ -4,15 +4,21 @@ |
| 4 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file2.s -o %t2.o | 4 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file2.s -o %t2.o |
| 5 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file3.s -o %t3.o | 5 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file3.s -o %t3.o |
| 6 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file4.s -o %t4.o | 6 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file4.s -o %t4.o |
| 7 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file5.s -o %t5.o | ||
| 8 | // RUN: ld.lld -shared %t5.o -o %t5.so -soname dso | ||
| 7 | // RUN: rm -f %t4.a | 9 | // RUN: rm -f %t4.a |
| 8 | // RUN: llvm-ar rc %t4.a %t4.o | 10 | // RUN: llvm-ar rc %t4.a %t4.o |
| 9 | // RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -M | FileCheck -strict-whitespace %s | 11 | // RUN: ld.lld %t1.o %t2.o %t3.o %t4.a %t5.so -o %t -M | FileCheck -strict-whitespace %s |
| 10 | // RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -print-map | FileCheck -strict-whitespace %s | 12 | // RUN: ld.lld %t1.o %t2.o %t3.o %t4.a %t5.so -o %t -print-map | FileCheck -strict-whitespace %s |
| 11 | // RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -Map=%t.map | 13 | // RUN: ld.lld %t1.o %t2.o %t3.o %t4.a %t5.so -o %t -Map=%t.map |
| 12 | // RUN: FileCheck -strict-whitespace %s < %t.map | 14 | // RUN: FileCheck -strict-whitespace %s < %t.map |
| 13 | 15 | ||
| 14 | .global _start | 16 | .global _start |
| 15 | _start: | 17 | _start: |
| 18 | .quad sharedFoo | ||
| 19 | .quad sharedBar | ||
| 20 | callq sharedFunc1 | ||
| 21 | callq sharedFunc2 | ||
| 16 | call baz | 22 | call baz |
| 17 | .global _Z1fi | 23 | .global _Z1fi |
| 18 | _Z1fi: | 24 | _Z1fi: |
| ... | @@ -25,34 +31,62 @@ bar: | ... | @@ -25,34 +31,62 @@ bar: |
| 25 | .long zed - . | 31 | .long zed - . |
| 26 | local: | 32 | local: |
| 27 | .comm common,4,16 | 33 | .comm common,4,16 |
| 34 | .global abs | ||
| 35 | abs = 0xAB5 | ||
| 36 | labs = 0x1AB5 | ||
| 28 | 37 | ||
| 29 | // CHECK: Address Size Align Out In Symbol | 38 | // CHECK: Address Size Align Out In Symbol |
| 30 | // CHECK-NEXT: 0000000000200158 0000000000000030 8 .eh_frame | 39 | // CHECK-NEXT: 00000000002001c8 0000000000000078 8 .dynsym |
| 31 | // CHECK-NEXT: 0000000000200158 0000000000000030 8 <internal>:(.eh_frame) | 40 | // CHECK-NEXT: 00000000002001c8 0000000000000078 8 <internal>:(.dynsym) |
| 32 | // CHECK-NEXT: 0000000000201000 0000000000000015 4 .text | 41 | // CHECK-NEXT: 0000000000200240 000000000000002c 8 .gnu.hash |
| 33 | // CHECK-NEXT: 0000000000201000 000000000000000e 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.text) | 42 | // CHECK-NEXT: 0000000000200240 000000000000002c 8 <internal>:(.gnu.hash) |
| 43 | // CHECK-NEXT: 000000000020026c 0000000000000030 4 .hash | ||
| 44 | // CHECK-NEXT: 000000000020026c 0000000000000030 4 <internal>:(.hash) | ||
| 45 | // CHECK-NEXT: 000000000020029c 0000000000000031 1 .dynstr | ||
| 46 | // CHECK-NEXT: 000000000020029c 0000000000000031 1 <internal>:(.dynstr) | ||
| 47 | // CHECK-NEXT: 00000000002002d0 0000000000000030 8 .rela.dyn | ||
| 48 | // CHECK-NEXT: 00000000002002d0 0000000000000030 8 <internal>:(.rela.dyn) | ||
| 49 | // CHECK-NEXT: 0000000000200300 0000000000000030 8 .rela.plt | ||
| 50 | // CHECK-NEXT: 0000000000200300 0000000000000030 8 <internal>:(.rela.plt) | ||
| 51 | // CHECK-NEXT: 0000000000200330 0000000000000030 8 .eh_frame | ||
| 52 | // CHECK-NEXT: 0000000000200330 0000000000000030 8 <internal>:(.eh_frame) | ||
| 53 | // CHECK-NEXT: 0000000000201000 000000000000002d 4 .text | ||
| 54 | // CHECK-NEXT: 0000000000201000 0000000000000028 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.text) | ||
| 34 | // CHECK-NEXT: 0000000000201000 0000000000000000 0 _start | 55 | // CHECK-NEXT: 0000000000201000 0000000000000000 0 _start |
| 35 | // CHECK-NEXT: 0000000000201005 0000000000000000 0 f(int) | 56 | // CHECK-NEXT: 000000000020101f 0000000000000000 0 f(int) |
| 36 | // CHECK-NEXT: 000000000020100e 0000000000000000 0 local | 57 | // CHECK-NEXT: 0000000000201028 0000000000000000 0 local |
| 37 | // CHECK-NEXT: 0000000000201010 0000000000000002 4 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.text) | 58 | // CHECK-NEXT: 0000000000201028 0000000000000002 4 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.text) |
| 38 | // CHECK-NEXT: 0000000000201010 0000000000000000 0 foo | 59 | // CHECK-NEXT: 0000000000201028 0000000000000000 0 foo |
| 39 | // CHECK-NEXT: 0000000000201011 0000000000000000 0 bar | 60 | // CHECK-NEXT: 0000000000201029 0000000000000000 0 bar |
| 40 | // CHECK-NEXT: 0000000000201012 0000000000000000 1 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.text.zed) | 61 | // CHECK-NEXT: 000000000020102a 0000000000000000 1 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.text.zed) |
| 41 | // CHECK-NEXT: 0000000000201012 0000000000000000 0 zed | 62 | // CHECK-NEXT: 000000000020102a 0000000000000000 0 zed |
| 42 | // CHECK-NEXT: 0000000000201014 0000000000000000 4 {{.*}}{{/|\\}}map-file.s.tmp3.o:(.text) | 63 | // CHECK-NEXT: 000000000020102c 0000000000000000 4 {{.*}}{{/|\\}}map-file.s.tmp3.o:(.text) |
| 43 | // CHECK-NEXT: 0000000000201014 0000000000000000 0 bah | 64 | // CHECK-NEXT: 000000000020102c 0000000000000000 0 bah |
| 44 | // CHECK-NEXT: 0000000000201014 0000000000000001 4 {{.*}}{{/|\\}}map-file.s.tmp4.a(map-file.s.tmp4.o):(.text) | 65 | // CHECK-NEXT: 000000000020102c 0000000000000001 4 {{.*}}{{/|\\}}map-file.s.tmp4.a(map-file.s.tmp4.o):(.text) |
| 45 | // CHECK-NEXT: 0000000000201014 0000000000000000 0 baz | 66 | // CHECK-NEXT: 000000000020102c 0000000000000000 0 baz |
| 46 | // CHECK-NEXT: 0000000000202000 0000000000000004 16 .bss | 67 | // CHECK-NEXT: 0000000000201030 0000000000000030 16 .plt |
| 47 | // CHECK-NEXT: 0000000000202000 0000000000000004 16 <internal>:(COMMON) | 68 | // CHECK-NEXT: 0000000000201030 0000000000000030 16 <internal>:(.plt) |
| 69 | // CHECK-NEXT: 0000000000201040 0000000000000000 0 sharedFunc1 | ||
| 70 | // CHECK-NEXT: 0000000000201050 0000000000000000 0 sharedFunc2 | ||
| 71 | // CHECK-NEXT: 0000000000202000 0000000000000028 8 .got.plt | ||
| 72 | // CHECK-NEXT: 0000000000202000 0000000000000028 8 <internal>:(.got.plt) | ||
| 73 | // CHECK-NEXT: 0000000000203000 0000000000000100 8 .dynamic | ||
| 74 | // CHECK-NEXT: 0000000000203000 0000000000000100 8 <internal>:(.dynamic) | ||
| 75 | // CHECK-NEXT: 0000000000204000 0000000000000010 16 .bss | ||
| 76 | // CHECK-NEXT: 0000000000204000 0000000000000004 16 {{.*}}{{/|\\}}map-file.s.tmp1.o:(COMMON) | ||
| 77 | // CHECK-NEXT: 0000000000204000 0000000000000004 0 common | ||
| 78 | // CHECK-NEXT: 0000000000204004 0000000000000004 1 <internal>:(.bss) | ||
| 79 | // CHECK-NEXT: 0000000000204004 0000000000000004 0 sharedFoo | ||
| 80 | // CHECK-NEXT: 0000000000204008 0000000000000008 1 <internal>:(.bss) | ||
| 81 | // CHECK-NEXT: 0000000000204008 0000000000000008 0 sharedBar | ||
| 48 | // CHECK-NEXT: 0000000000000000 0000000000000008 1 .comment | 82 | // CHECK-NEXT: 0000000000000000 0000000000000008 1 .comment |
| 49 | // CHECK-NEXT: 0000000000000000 0000000000000008 1 <internal>:(.comment) | 83 | // CHECK-NEXT: 0000000000000000 0000000000000008 1 <internal>:(.comment) |
| 50 | // CHECK-NEXT: 0000000000000000 00000000000000f0 8 .symtab | 84 | // CHECK-NEXT: 0000000000000000 0000000000000198 8 .symtab |
| 51 | // CHECK-NEXT: 0000000000000000 00000000000000f0 8 <internal>:(.symtab) | 85 | // CHECK-NEXT: 0000000000000000 0000000000000198 8 <internal>:(.symtab) |
| 52 | // CHECK-NEXT: 0000000000000000 0000000000000039 1 .shstrtab | 86 | // CHECK-NEXT: 0000000000000000 0000000000000084 1 .shstrtab |
| 53 | // CHECK-NEXT: 0000000000000000 0000000000000039 1 <internal>:(.shstrtab) | 87 | // CHECK-NEXT: 0000000000000000 0000000000000084 1 <internal>:(.shstrtab) |
| 54 | // CHECK-NEXT: 0000000000000000 000000000000002f 1 .strtab | 88 | // CHECK-NEXT: 0000000000000000 000000000000006d 1 .strtab |
| 55 | // CHECK-NEXT: 0000000000000000 000000000000002f 1 <internal>:(.strtab) | 89 | // CHECK-NEXT: 0000000000000000 000000000000006d 1 <internal>:(.strtab) |
| 56 | 90 | ||
| 57 | // RUN: not ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -Map=/ 2>&1 \ | 91 | // RUN: not ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -Map=/ 2>&1 \ |
| 58 | // RUN: | FileCheck -check-prefix=FAIL %s | 92 | // RUN: | FileCheck -check-prefix=FAIL %s |
deps/lld/test/ELF/merge-align.s created+34| ... | @@ -0,0 +1,34 @@ | ||
| 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.so -shared | ||
| 4 | // RUN: llvm-readobj -s -section-data %t.so | FileCheck %s | ||
| 5 | |||
| 6 | .section .rodata.foo,"aM",@progbits,1 | ||
| 7 | .align 16 | ||
| 8 | .byte 0x42 | ||
| 9 | |||
| 10 | .section .rodata.bar,"aM",@progbits,1 | ||
| 11 | .align 16 | ||
| 12 | .byte 0x42 | ||
| 13 | |||
| 14 | .section .rodata.zed,"aM",@progbits,1 | ||
| 15 | .align 16 | ||
| 16 | .byte 0x41 | ||
| 17 | |||
| 18 | // CHECK: Name: .rodata ( | ||
| 19 | // CHECK-NEXT: Type: SHT_PROGBITS | ||
| 20 | // CHECK-NEXT: Flags [ | ||
| 21 | // CHECK-NEXT: SHF_ALLOC | ||
| 22 | // CHECK-NEXT: SHF_MERGE | ||
| 23 | // CHECK-NEXT: ] | ||
| 24 | // CHECK-NEXT: Address: | ||
| 25 | // CHECK-NEXT: Offset: | ||
| 26 | // CHECK-NEXT: Size: 17 | ||
| 27 | // CHECK-NEXT: Link: 0 | ||
| 28 | // CHECK-NEXT: Info: 0 | ||
| 29 | // CHECK-NEXT: AddressAlignment: 16 | ||
| 30 | // CHECK-NEXT: EntrySize: 1 | ||
| 31 | // CHECK-NEXT: SectionData ( | ||
| 32 | // CHECK-NEXT: 0000: 42000000 00000000 00000000 00000000 | | ||
| 33 | // CHECK-NEXT: 0010: 41 | | ||
| 34 | // CHECK-NEXT: ) | ||
deps/lld/test/ELF/merge-entsize.s created+27| ... | @@ -0,0 +1,27 @@ | ||
| 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-readobj -s %t | FileCheck %s | ||
| 5 | |||
| 6 | .section .rodata.1,"aM",@progbits,1 | ||
| 7 | .byte 0x42 | ||
| 8 | |||
| 9 | .section .rodata.2,"aM",@progbits,2 | ||
| 10 | .short 0x42 | ||
| 11 | |||
| 12 | // 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. | ||
| 14 | |||
| 15 | // CHECK: Name: .rodata ( | ||
| 16 | // CHECK-NEXT: Type: SHT_PROGBITS | ||
| 17 | // CHECK-NEXT: Flags [ | ||
| 18 | // CHECK-NEXT: SHF_ALLOC | ||
| 19 | // CHECK-NEXT: SHF_MERGE | ||
| 20 | // CHECK-NEXT: ] | ||
| 21 | // CHECK-NEXT: Address: | ||
| 22 | // CHECK-NEXT: Offset: | ||
| 23 | // CHECK-NEXT: Size: | ||
| 24 | // CHECK-NEXT: Link: | ||
| 25 | // CHECK-NEXT: Info: | ||
| 26 | // CHECK-NEXT: AddressAlignment: | ||
| 27 | // CHECK-NEXT: EntrySize: 0 | ||
deps/lld/test/ELF/merge-reloc.s+9-10| ... | @@ -3,14 +3,13 @@ | ... | @@ -3,14 +3,13 @@ |
| 3 | # RUN: ld.lld %t.o -r -o %t-rel | 3 | # RUN: ld.lld %t.o -r -o %t-rel |
| 4 | # RUN: llvm-readobj -s -section-data %t-rel | FileCheck %s | 4 | # RUN: llvm-readobj -s -section-data %t-rel | FileCheck %s |
| 5 | 5 | ||
| 6 | # When linker generates a relocatable object it should keep "merge" | 6 | # When linker generates a relocatable object it does string merging in the same |
| 7 | # sections as-is: do not merge content, do not join regular and | 7 | # way as for regular link. It should keep SHF_MERGE flag and set proper sh_entsize |
| 8 | # "merge" sections, do not joint "merge" sections with different | 8 | # value so that final link can perform the final merging optimization. |
| 9 | # entry size. | ||
| 10 | 9 | ||
| 11 | # CHECK: Section { | 10 | # CHECK: Section { |
| 12 | # CHECK: Index: | 11 | # CHECK: Index: |
| 13 | # CHECK: Name: .rodata | 12 | # CHECK: Name: .rodata.1 ( |
| 14 | # CHECK-NEXT: Type: SHT_PROGBITS | 13 | # CHECK-NEXT: Type: SHT_PROGBITS |
| 15 | # CHECK-NEXT: Flags [ | 14 | # CHECK-NEXT: Flags [ |
| 16 | # CHECK-NEXT: SHF_ALLOC | 15 | # CHECK-NEXT: SHF_ALLOC |
| ... | @@ -18,18 +17,18 @@ | ... | @@ -18,18 +17,18 @@ |
| 18 | # CHECK-NEXT: ] | 17 | # CHECK-NEXT: ] |
| 19 | # CHECK-NEXT: Address: | 18 | # CHECK-NEXT: Address: |
| 20 | # CHECK-NEXT: Offset: | 19 | # CHECK-NEXT: Offset: |
| 21 | # CHECK-NEXT: Size: 12 | 20 | # CHECK-NEXT: Size: 4 |
| 22 | # CHECK-NEXT: Link: 0 | 21 | # CHECK-NEXT: Link: 0 |
| 23 | # CHECK-NEXT: Info: 0 | 22 | # CHECK-NEXT: Info: 0 |
| 24 | # CHECK-NEXT: AddressAlignment: 4 | 23 | # CHECK-NEXT: AddressAlignment: 4 |
| 25 | # CHECK-NEXT: EntrySize: 4 | 24 | # CHECK-NEXT: EntrySize: 4 |
| 26 | # CHECK-NEXT: SectionData ( | 25 | # CHECK-NEXT: SectionData ( |
| 27 | # CHECK-NEXT: 0000: 42000000 42000000 42000000 | 26 | # CHECK-NEXT: 0000: 42000000 |
| 28 | # CHECK-NEXT: ) | 27 | # CHECK-NEXT: ) |
| 29 | # CHECK-NEXT: } | 28 | # CHECK-NEXT: } |
| 30 | # CHECK: Section { | 29 | # CHECK: Section { |
| 31 | # CHECK: Index: | 30 | # CHECK: Index: |
| 32 | # CHECK: Name: .rodata | 31 | # CHECK: Name: .rodata.2 ( |
| 33 | # CHECK-NEXT: Type: SHT_PROGBITS | 32 | # CHECK-NEXT: Type: SHT_PROGBITS |
| 34 | # CHECK-NEXT: Flags [ | 33 | # CHECK-NEXT: Flags [ |
| 35 | # CHECK-NEXT: SHF_ALLOC | 34 | # CHECK-NEXT: SHF_ALLOC |
| ... | @@ -37,13 +36,13 @@ | ... | @@ -37,13 +36,13 @@ |
| 37 | # CHECK-NEXT: ] | 36 | # CHECK-NEXT: ] |
| 38 | # CHECK-NEXT: Address: | 37 | # CHECK-NEXT: Address: |
| 39 | # CHECK-NEXT: Offset: | 38 | # CHECK-NEXT: Offset: |
| 40 | # CHECK-NEXT: Size: 16 | 39 | # CHECK-NEXT: Size: 8 |
| 41 | # CHECK-NEXT: Link: 0 | 40 | # CHECK-NEXT: Link: 0 |
| 42 | # CHECK-NEXT: Info: 0 | 41 | # CHECK-NEXT: Info: 0 |
| 43 | # CHECK-NEXT: AddressAlignment: 8 | 42 | # CHECK-NEXT: AddressAlignment: 8 |
| 44 | # CHECK-NEXT: EntrySize: 8 | 43 | # CHECK-NEXT: EntrySize: 8 |
| 45 | # CHECK-NEXT: SectionData ( | 44 | # CHECK-NEXT: SectionData ( |
| 46 | # CHECK-NEXT: 0000: 42000000 42000000 42000000 42000000 | 45 | # CHECK-NEXT: 0000: 42000000 42000000 |
| 47 | # CHECK-NEXT: ) | 46 | # CHECK-NEXT: ) |
| 48 | # CHECK-NEXT: } | 47 | # CHECK-NEXT: } |
| 49 | # CHECK: Section { | 48 | # CHECK: Section { |
deps/lld/test/ELF/merge-string.s+7-7| ... | @@ -1,10 +1,10 @@ | ... | @@ -1,10 +1,10 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld -O2 %t.o -o %t.so -shared | 3 | // RUN: ld.lld -O 2 %t.o -o %t.so -shared |
| 4 | // RUN: llvm-readobj -s -section-data -t %t.so | FileCheck %s | 4 | // RUN: llvm-readobj -s -section-data -t %t.so | FileCheck %s |
| 5 | // RUN: ld.lld -O1 %t.o -o %t.so -shared | 5 | // 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 %s | 6 | // RUN: llvm-readobj -s -section-data -t %t.so | FileCheck --check-prefix=NOTAIL %s |
| 7 | // RUN: ld.lld -O0 %t.o -o %t.so -shared | 7 | // 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 %s | 8 | // RUN: llvm-readobj -s -section-data -t %t.so | FileCheck --check-prefix=NOMERGE %s |
| 9 | 9 | ||
| 10 | .section	.rodata1,"aMS",@progbits,1 | 10 | .section	.rodata1,"aMS",@progbits,1 |
| ... | @@ -34,7 +34,7 @@ zed: | ... | @@ -34,7 +34,7 @@ zed: |
| 34 | // CHECK-NEXT: Link: 0 | 34 | // CHECK-NEXT: Link: 0 |
| 35 | // CHECK-NEXT: Info: 0 | 35 | // CHECK-NEXT: Info: 0 |
| 36 | // CHECK-NEXT: AddressAlignment: 1 | 36 | // CHECK-NEXT: AddressAlignment: 1 |
| 37 | // CHECK-NEXT: EntrySize: 0 | 37 | // CHECK-NEXT: EntrySize: 1 |
| 38 | // CHECK-NEXT: SectionData ( | 38 | // CHECK-NEXT: SectionData ( |
| 39 | // CHECK-NEXT: 0000: 61626300 |abc.| | 39 | // CHECK-NEXT: 0000: 61626300 |abc.| |
| 40 | // CHECK-NEXT: ) | 40 | // CHECK-NEXT: ) |
| ... | @@ -52,9 +52,9 @@ zed: | ... | @@ -52,9 +52,9 @@ zed: |
| 52 | // NOTAIL-NEXT: Link: 0 | 52 | // NOTAIL-NEXT: Link: 0 |
| 53 | // NOTAIL-NEXT: Info: 0 | 53 | // NOTAIL-NEXT: Info: 0 |
| 54 | // NOTAIL-NEXT: AddressAlignment: 1 | 54 | // NOTAIL-NEXT: AddressAlignment: 1 |
| 55 | // NOTAIL-NEXT: EntrySize: 0 | 55 | // NOTAIL-NEXT: EntrySize: 1 |
| 56 | // NOTAIL-NEXT: SectionData ( | 56 | // NOTAIL-NEXT: SectionData ( |
| 57 | // NOTAIL-NEXT: 0000: 61626300 626300 |abc.bc.| | 57 | // NOTAIL-NEXT: 0000: 62630061 626300 |bc.abc.| |
| 58 | // NOTAIL-NEXT: ) | 58 | // NOTAIL-NEXT: ) |
| 59 | 59 | ||
| 60 | // NOMERGE: Name: .rodata1 | 60 | // NOMERGE: Name: .rodata1 |
| ... | @@ -88,7 +88,7 @@ zed: | ... | @@ -88,7 +88,7 @@ zed: |
| 88 | // CHECK-NEXT: Link: 0 | 88 | // CHECK-NEXT: Link: 0 |
| 89 | // CHECK-NEXT: Info: 0 | 89 | // CHECK-NEXT: Info: 0 |
| 90 | // CHECK-NEXT: AddressAlignment: 2 | 90 | // CHECK-NEXT: AddressAlignment: 2 |
| 91 | // CHECK-NEXT: EntrySize: 0 | 91 | // CHECK-NEXT: EntrySize: 2 |
| 92 | // CHECK-NEXT: SectionData ( | 92 | // CHECK-NEXT: SectionData ( |
| 93 | // CHECK-NEXT: 0000: 14000000 |....| | 93 | // CHECK-NEXT: 0000: 14000000 |....| |
| 94 | // CHECK-NEXT: ) | 94 | // CHECK-NEXT: ) |
deps/lld/test/ELF/merge.s+1-1| ... | @@ -29,7 +29,7 @@ zed: | ... | @@ -29,7 +29,7 @@ zed: |
| 29 | // CHECK-NEXT: Link: 0 | 29 | // CHECK-NEXT: Link: 0 |
| 30 | // CHECK-NEXT: Info: 0 | 30 | // CHECK-NEXT: Info: 0 |
| 31 | // CHECK-NEXT: AddressAlignment: 4 | 31 | // CHECK-NEXT: AddressAlignment: 4 |
| 32 | // CHECK-NEXT: EntrySize: 0 | 32 | // CHECK-NEXT: EntrySize: 4 |
| 33 | // CHECK-NEXT: SectionData ( | 33 | // CHECK-NEXT: SectionData ( |
| 34 | // CHECK-NEXT: 0000: 10000000 42000000 | 34 | // CHECK-NEXT: 0000: 10000000 42000000 |
| 35 | // CHECK-NEXT: ) | 35 | // CHECK-NEXT: ) |
deps/lld/test/ELF/mips-26-n32-n64.s created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | # Check R_MIPS_26 relocation handling in case of N64 ABIs. | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \ | ||
| 4 | # RUN: %S/Inputs/mips-dynamic.s -o %t-so.o | ||
| 5 | # RUN: ld.lld %t-so.o -shared -o %t.so | ||
| 6 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o | ||
| 7 | # RUN: ld.lld %t.o %t.so -o %t.exe | ||
| 8 | # RUN: llvm-objdump -d %t.exe | FileCheck %s | ||
| 9 | |||
| 10 | # REQUIRES: mips | ||
| 11 | |||
| 12 | # CHECK: Disassembly of section .text: | ||
| 13 | # CHECK-NEXT: __start: | ||
| 14 | # CHECK-NEXT: 20000: 0c 00 80 0c jal 131120 | ||
| 15 | # CHECK-NEXT: 20004: 00 00 00 00 nop | ||
| 16 | # CHECK-NEXT: Disassembly of section .plt: | ||
| 17 | # CHECK-NEXT: .plt: | ||
| 18 | # CHECK-NEXT: 20010: 3c 0e 00 03 lui $14, 3 | ||
| 19 | # CHECK-NEXT: 20014: dd d9 00 08 ld $25, 8($14) | ||
| 20 | # CHECK-NEXT: 20018: 25 ce 00 08 addiu $14, $14, 8 | ||
| 21 | # CHECK-NEXT: 2001c: 03 0e c0 23 subu $24, $24, $14 | ||
| 22 | # CHECK-NEXT: 20020: 03 e0 78 25 move $15, $ra | ||
| 23 | # CHECK-NEXT: 20024: 00 18 c0 c2 srl $24, $24, 3 | ||
| 24 | # CHECK-NEXT: 20028: 03 20 f8 09 jalr $25 | ||
| 25 | # CHECK-NEXT: 2002c: 27 18 ff fe addiu $24, $24, -2 | ||
| 26 | # CHECK-NEXT: 20030: 3c 0f 00 03 lui $15, 3 | ||
| 27 | # CHECK-NEXT: 20034: 8d f9 00 18 lw $25, 24($15) | ||
| 28 | # CHECK-NEXT: 20038: 03 20 00 08 jr $25 | ||
| 29 | # CHECK-NEXT: 2003c: 25 f8 00 18 addiu $24, $15, 24 | ||
| 30 | |||
| 31 | .text | ||
| 32 | .option pic0 | ||
| 33 | .global __start | ||
| 34 | __start: | ||
| 35 | jal foo0 | ||
deps/lld/test/ELF/mips-64-gprel-so.s+1-1| ... | @@ -12,7 +12,7 @@ | ... | @@ -12,7 +12,7 @@ |
| 12 | # CHECK-NEXT: 10004: 03 99 e0 2d daddu $gp, $gp, $25 | 12 | # CHECK-NEXT: 10004: 03 99 e0 2d daddu $gp, $gp, $25 |
| 13 | # CHECK-NEXT: 10008: 67 9c 7f f0 daddiu $gp, $gp, 32752 | 13 | # CHECK-NEXT: 10008: 67 9c 7f f0 daddiu $gp, $gp, 32752 |
| 14 | 14 | ||
| 15 | # CHECK: 0000000000027ff0 *ABS* 00000000 .hidden _gp | 15 | # CHECK: 0000000000027ff0 .got 00000000 .hidden _gp |
| 16 | # CHECK: 0000000000010000 .text 00000000 foo | 16 | # CHECK: 0000000000010000 .text 00000000 foo |
| 17 | 17 | ||
| 18 | .text | 18 | .text |
deps/lld/test/ELF/mips-64-rels.s+3-3| ... | @@ -20,11 +20,11 @@ | ... | @@ -20,11 +20,11 @@ |
| 20 | # ^-- %lo(0x17ff0) | 20 | # ^-- %lo(0x17ff0) |
| 21 | 21 | ||
| 22 | # CHECK: Contents of section .rodata: | 22 | # CHECK: Contents of section .rodata: |
| 23 | # CHECK-NEXT: 10158 ffffffff fffe8014 | 23 | # CHECK-NEXT: {{[0-9a-f]+}} ffffffff fffe8014 |
| 24 | # ^-- 0x20004 - 0x37ff0 = 0xfffffffffffe8014 | 24 | # ^-- 0x20004 - 0x37ff0 = 0xfffffffffffe8014 |
| 25 | 25 | ||
| 26 | # CHECK: 0000000000020004 .text 00000000 loc | 26 | # CHECK: 0000000000020004 .text 00000000 loc |
| 27 | # CHECK: 0000000000037ff0 *ABS* 00000000 .hidden _gp | 27 | # CHECK: 0000000000037ff0 .got 00000000 .hidden _gp |
| 28 | # CHECK: 0000000000020000 .text 00000000 __start | 28 | # CHECK: 0000000000020000 .text 00000000 __start |
| 29 | 29 | ||
| 30 | # REL: Relocations [ | 30 | # REL: Relocations [ |
deps/lld/test/ELF/mips-align-err.s+1-1| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | 4 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ |
| 5 | # RUN: -mcpu=mips32r6 %S/Inputs/mips-align-err.s -o %t2.o | 5 | # RUN: -mcpu=mips32r6 %S/Inputs/mips-align-err.s -o %t2.o |
| 6 | # RUN: not ld.lld %t.o %t2.o -o %t.exe 2>&1 | FileCheck %s | 6 | # RUN: not ld.lld %t.o %t2.o -o %t.exe 2>&1 | FileCheck %s |
| 7 | # CHECK: {{.*}}:(.text+0x1): improper alignment for relocation R_MIPS_PC16 | 7 | # CHECK: {{.*}}:(.text+0x1): improper alignment for relocation R_MIPS_PC16: 0xB is not aligned to 4 bytes |
| 8 | 8 | ||
| 9 | .globl __start | 9 | .globl __start |
| 10 | __start: | 10 | __start: |
deps/lld/test/ELF/mips-elf-flags-err.s+8-2| ... | @@ -71,8 +71,14 @@ __start: | ... | @@ -71,8 +71,14 @@ __start: |
| 71 | # R1R2-NEXT: EF_MIPS_CPIC | 71 | # R1R2-NEXT: EF_MIPS_CPIC |
| 72 | # R1R2-NEXT: ] | 72 | # R1R2-NEXT: ] |
| 73 | 73 | ||
| 74 | # R3R32: target ISA 'mips3' is incompatible with 'mips32': {{.*}}mips-elf-flags-err.s.tmp2.o | 74 | # R3R32: error: incompatible target ISA: |
| 75 | # R6OCTEON: target ISA 'mips64r6' is incompatible with 'octeon': {{.*}}mips-elf-flags-err.s.tmp2.o | 75 | # R3R32-NEXT: >>> {{.+}}mips-elf-flags-err.s.tmp1.o: mips3 |
| 76 | # R3R32-NEXT: >>> {{.+}}mips-elf-flags-err.s.tmp2.o: mips32 | ||
| 77 | |||
| 78 | # R6OCTEON: error: incompatible target ISA: | ||
| 79 | # R6OCTEON-NEXT: >>> {{.+}}mips-elf-flags-err.s.tmp1.o: mips64r6 | ||
| 80 | # R6OCTEON-NEXT: >>> {{.+}}mips-elf-flags-err.s.tmp2.o: mips64r2 (octeon) | ||
| 81 | |||
| 76 | # FPABI: target floating point ABI '-mdouble-float' is incompatible with '-mgp32 -mfp64': {{.*}}mips-elf-flags-err.s.tmp2.o | 82 | # FPABI: target floating point ABI '-mdouble-float' is incompatible with '-mgp32 -mfp64': {{.*}}mips-elf-flags-err.s.tmp2.o |
| 77 | 83 | ||
| 78 | # OCTEON: Flags [ | 84 | # OCTEON: Flags [ |
deps/lld/test/ELF/mips-elf-flags.s+29| ... | @@ -35,6 +35,12 @@ | ... | @@ -35,6 +35,12 @@ |
| 35 | # RUN: llvm-readobj -h -mips-abi-flags %t.exe \ | 35 | # RUN: llvm-readobj -h -mips-abi-flags %t.exe \ |
| 36 | # RUN: | FileCheck -check-prefix=OCTEON %s | 36 | # RUN: | FileCheck -check-prefix=OCTEON %s |
| 37 | 37 | ||
| 38 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o | ||
| 39 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 40 | # RUN: -mattr=micromips %S/Inputs/mips-fpic.s -o %t-mm.o | ||
| 41 | # RUN: ld.lld %t.o %t-mm.o -o %t.exe | ||
| 42 | # RUN: llvm-readobj -h -mips-abi-flags %t.exe | FileCheck -check-prefix=MICRO %s | ||
| 43 | |||
| 38 | # REQUIRES: mips | 44 | # REQUIRES: mips |
| 39 | 45 | ||
| 40 | .text | 46 | .text |
| ... | @@ -170,3 +176,26 @@ __start: | ... | @@ -170,3 +176,26 @@ __start: |
| 170 | # OCTEON-NEXT: ] | 176 | # OCTEON-NEXT: ] |
| 171 | # OCTEON-NEXT: Flags 2: 0x0 | 177 | # OCTEON-NEXT: Flags 2: 0x0 |
| 172 | # OCTEON-NEXT: } | 178 | # OCTEON-NEXT: } |
| 179 | |||
| 180 | # MICRO: Flags [ | ||
| 181 | # MICRO-NEXT: EF_MIPS_ABI_O32 | ||
| 182 | # MICRO-NEXT: EF_MIPS_ARCH_32 | ||
| 183 | # MICRO-NEXT: EF_MIPS_CPIC | ||
| 184 | # MICRO-NEXT: EF_MIPS_MICROMIPS | ||
| 185 | # MICRO-NEXT: ] | ||
| 186 | # MICRO: MIPS ABI Flags { | ||
| 187 | # MICRO-NEXT: Version: 0 | ||
| 188 | # MICRO-NEXT: ISA: MIPS32 | ||
| 189 | # MICRO-NEXT: ISA Extension: None | ||
| 190 | # MICRO-NEXT: ASEs [ | ||
| 191 | # MICRO-NEXT: microMIPS | ||
| 192 | # MICRO-NEXT: ] | ||
| 193 | # MICRO-NEXT: FP ABI: Hard float (double precision) | ||
| 194 | # MICRO-NEXT: GPR size: 32 | ||
| 195 | # MICRO-NEXT: CPR1 size: 32 | ||
| 196 | # MICRO-NEXT: CPR2 size: 0 | ||
| 197 | # MICRO-NEXT: Flags 1 [ | ||
| 198 | # MICRO-NEXT: ODDSPREG | ||
| 199 | # MICRO-NEXT: ] | ||
| 200 | # MICRO-NEXT: Flags 2: 0x0 | ||
| 201 | # MICRO-NEXT: } |
deps/lld/test/ELF/mips-got-page-script.s created+65| ... | @@ -0,0 +1,65 @@ | ||
| 1 | # Check calculation of MIPS GOT page address entries number | ||
| 2 | # when a linker script is provided. | ||
| 3 | |||
| 4 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -o %t.o %s | ||
| 5 | # RUN: echo "SECTIONS { \ | ||
| 6 | # RUN: .text : { *(.text) } \ | ||
| 7 | # RUN: .data 0x10000 : { *(.data) } }" > %t.script | ||
| 8 | # RUN: ld.lld -shared --script %t.script -o %t.so %t.o | ||
| 9 | # RUN: llvm-readobj -t -mips-plt-got %t.so | FileCheck %s | ||
| 10 | |||
| 11 | # REQUIRES: mips | ||
| 12 | |||
| 13 | # CHECK: Name: foo1 | ||
| 14 | # CHECK-NEXT: Value: 0x10000 | ||
| 15 | # CHECK: Name: foo2 | ||
| 16 | # CHECK-NEXT: Value: 0x20000 | ||
| 17 | # CHECK: Name: foo3 | ||
| 18 | # CHECK-NEXT: Value: 0x30000 | ||
| 19 | # CHECK: Name: foo4 | ||
| 20 | # CHECK-NEXT: Value: 0x40000 | ||
| 21 | |||
| 22 | # CHECK: Local entries [ | ||
| 23 | # CHECK-BEXT: Entry { | ||
| 24 | # CHECK-BEXT: Address: | ||
| 25 | # CHECK-BEXT: Access: | ||
| 26 | # CHECK-BEXT: Initial: 0x10000 | ||
| 27 | # CHECK-BEXT: } | ||
| 28 | # CHECK-BEXT: Entry { | ||
| 29 | # CHECK-BEXT: Address: | ||
| 30 | # CHECK-BEXT: Access: | ||
| 31 | # CHECK-BEXT: Initial: 0x20000 | ||
| 32 | # CHECK-BEXT: } | ||
| 33 | # CHECK-BEXT: Entry { | ||
| 34 | # CHECK-BEXT: Address: | ||
| 35 | # CHECK-BEXT: Access: | ||
| 36 | # CHECK-BEXT: Initial: 0x30000 | ||
| 37 | # CHECK-BEXT: } | ||
| 38 | # CHECK-BEXT: Entry { | ||
| 39 | # CHECK-BEXT: Address: | ||
| 40 | # CHECK-BEXT: Access: | ||
| 41 | # CHECK-BEXT: Initial: 0x40000 | ||
| 42 | # CHECK-BEXT: } | ||
| 43 | # CHECK-BEXT: Entry { | ||
| 44 | # CHECK-BEXT: Address: | ||
| 45 | # CHECK-BEXT: Access: | ||
| 46 | # CHECK-BEXT: Initial: 0x50000 | ||
| 47 | # CHECK-BEXT: } | ||
| 48 | # CHECK-BEXT: ] | ||
| 49 | |||
| 50 | .option pic2 | ||
| 51 | .text | ||
| 52 | ld $v0,%got_page(foo1)($gp) | ||
| 53 | ld $v0,%got_page(foo2)($gp) | ||
| 54 | ld $v0,%got_page(foo3)($gp) | ||
| 55 | ld $v0,%got_page(foo4)($gp) | ||
| 56 | |||
| 57 | .data | ||
| 58 | foo1: | ||
| 59 | .space 0x10000 | ||
| 60 | foo2: | ||
| 61 | .space 0x10000 | ||
| 62 | foo3: | ||
| 63 | .space 0x10000 | ||
| 64 | foo4: | ||
| 65 | .word 0 | ||
deps/lld/test/ELF/mips-got-relocs.s+2-2| ... | @@ -47,7 +47,7 @@ v1: | ... | @@ -47,7 +47,7 @@ v1: |
| 47 | # EXE_SYM: Sections: | 47 | # EXE_SYM: Sections: |
| 48 | # EXE_SYM: .got 0000000c 0000000000030010 DATA | 48 | # EXE_SYM: .got 0000000c 0000000000030010 DATA |
| 49 | # EXE_SYM: SYMBOL TABLE: | 49 | # EXE_SYM: SYMBOL TABLE: |
| 50 | # EXE_SYM: 00038000 *ABS* 00000000 .hidden _gp | 50 | # EXE_SYM: 00038000 .got 00000000 .hidden _gp |
| 51 | # ^-- .got + GP offset (0x7ff0) | 51 | # ^-- .got + GP offset (0x7ff0) |
| 52 | # EXE_SYM: 00030000 g .data		 00000004 v1 | 52 | # EXE_SYM: 00030000 g .data		 00000004 v1 |
| 53 | 53 | ||
| ... | @@ -71,7 +71,7 @@ v1: | ... | @@ -71,7 +71,7 @@ v1: |
| 71 | # DSO_SYM: Sections: | 71 | # DSO_SYM: Sections: |
| 72 | # DSO_SYM: .got 0000000c 0000000000020010 DATA | 72 | # DSO_SYM: .got 0000000c 0000000000020010 DATA |
| 73 | # DSO_SYM: SYMBOL TABLE: | 73 | # DSO_SYM: SYMBOL TABLE: |
| 74 | # DSO_SYM: 00028000 *ABS* 00000000 .hidden _gp | 74 | # DSO_SYM: 00028000 .got 00000000 .hidden _gp |
| 75 | # ^-- .got + GP offset (0x7ff0) | 75 | # ^-- .got + GP offset (0x7ff0) |
| 76 | # DSO_SYM: 00020000 g .data		 00000004 v1 | 76 | # DSO_SYM: 00020000 g .data		 00000004 v1 |
| 77 | 77 |
deps/lld/test/ELF/mips-got-script.s created+47| ... | @@ -0,0 +1,47 @@ | ||
| 1 | # Check number of got entries is adjusted for linker script-added space. | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o | ||
| 4 | # RUN: echo "SECTIONS { .data : { *(.data.1); . += 0x10000; *(.data.2) } }" > %t.script | ||
| 5 | # RUN: ld.lld %t.o -shared -o %t.so -T %t.script | ||
| 6 | # RUN: llvm-readobj -mips-plt-got -dynamic-table %t.so | FileCheck %s | ||
| 7 | |||
| 8 | # REQUIRES: mips | ||
| 9 | |||
| 10 | # CHECK: 0x7000000A MIPS_LOCAL_GOTNO 5 | ||
| 11 | # ^-- 2 * header + 3 local entries | ||
| 12 | # CHECK: Local entries [ | ||
| 13 | # CHECK-NEXT: Entry { | ||
| 14 | # CHECK-NEXT: Address: | ||
| 15 | # CHECK-NEXT: Access: -32744 | ||
| 16 | # CHECK-NEXT: Initial: 0x0 | ||
| 17 | # ^-- loc1 | ||
| 18 | # CHECK-NEXT: } | ||
| 19 | # CHECK-NEXT: Entry { | ||
| 20 | # CHECK-NEXT: Address: | ||
| 21 | # CHECK-NEXT: Access: -32740 | ||
| 22 | # CHECK-NEXT: Initial: 0x10000 | ||
| 23 | # ^-- loc2 | ||
| 24 | # CHECK-NEXT: } | ||
| 25 | # CHECK-NEXT: Entry { | ||
| 26 | # CHECK-NEXT: Address: | ||
| 27 | # CHECK-NEXT: Access: -32736 | ||
| 28 | # CHECK-NEXT: Initial: 0x20000 | ||
| 29 | # ^-- redundant | ||
| 30 | # CHECK-NEXT: } | ||
| 31 | # CHECK-NEXT: ] | ||
| 32 | |||
| 33 | .text | ||
| 34 | .globl foo | ||
| 35 | foo: | ||
| 36 | lw $t0, %got(loc1)($gp) | ||
| 37 | addi $t0, $t0, %lo(loc1) | ||
| 38 | lw $t0, %got(loc2)($gp) | ||
| 39 | addi $t0, $t0, %lo(loc2) | ||
| 40 | |||
| 41 | .section .data.1,"aw",%progbits | ||
| 42 | loc1: | ||
| 43 | .word 0 | ||
| 44 | |||
| 45 | .section .data.2,"aw",%progbits | ||
| 46 | loc2: | ||
| 47 | .word 0 | ||
deps/lld/test/ELF/mips-gp-disp.s+1-1| ... | @@ -24,7 +24,7 @@ | ... | @@ -24,7 +24,7 @@ |
| 24 | # DIS-NEXT: 10000: 3c 08 00 01 lui $8, 1 | 24 | # DIS-NEXT: 10000: 3c 08 00 01 lui $8, 1 |
| 25 | # DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752 | 25 | # DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752 |
| 26 | # ^-- 0x37ff0 & 0xffff | 26 | # ^-- 0x37ff0 & 0xffff |
| 27 | # DIS: 00027ff0 *ABS* 00000000 .hidden _gp | 27 | # DIS: 00027ff0 .got 00000000 .hidden _gp |
| 28 | 28 | ||
| 29 | # REL: Relocations [ | 29 | # REL: Relocations [ |
| 30 | # REL-NEXT: ] | 30 | # REL-NEXT: ] |
deps/lld/test/ELF/mips-gp-ext.s+7| ... | @@ -10,6 +10,13 @@ | ... | @@ -10,6 +10,13 @@ |
| 10 | # RUN: ld.lld -shared -o %t.rel.so --script %t.rel.script %t.o | 10 | # RUN: ld.lld -shared -o %t.rel.so --script %t.rel.script %t.o |
| 11 | # RUN: llvm-objdump -s -t %t.rel.so | FileCheck --check-prefix=REL %s | 11 | # RUN: llvm-objdump -s -t %t.rel.so | FileCheck --check-prefix=REL %s |
| 12 | 12 | ||
| 13 | # RUN: echo "SECTIONS { \ | ||
| 14 | # RUN: .text : { *(.text) } \ | ||
| 15 | # RUN: _gp = 0x100 + ABSOLUTE(.); \ | ||
| 16 | # RUN: .got : { *(.got) } }" > %t.rel.script | ||
| 17 | # RUN: ld.lld -shared -o %t.rel.so --script %t.rel.script %t.o | ||
| 18 | # RUN: llvm-objdump -s -t %t.rel.so | FileCheck --check-prefix=REL %s | ||
| 19 | |||
| 13 | # RUN: echo "SECTIONS { \ | 20 | # RUN: echo "SECTIONS { \ |
| 14 | # RUN: .text : { *(.text) } \ | 21 | # RUN: .text : { *(.text) } \ |
| 15 | # RUN: _gp = 0x200; \ | 22 | # RUN: _gp = 0x200; \ |
deps/lld/test/ELF/mips-gp-local.s+1-1| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | # CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 3 | 11 | # CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 3 |
| 12 | # CHECK-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752 | 12 | # CHECK-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752 |
| 13 | 13 | ||
| 14 | # CHECK: 00037ff0 *ABS* 00000000 .hidden _gp | 14 | # CHECK: 00037ff0 .got 00000000 .hidden _gp |
| 15 | 15 | ||
| 16 | .text | 16 | .text |
| 17 | .globl __start | 17 | .globl __start |
deps/lld/test/ELF/mips-gprel32-relocs-gp0.s+4-4| ... | @@ -22,14 +22,14 @@ | ... | @@ -22,14 +22,14 @@ |
| 22 | # DSO: GP: 0x27FF0 | 22 | # DSO: GP: 0x27FF0 |
| 23 | 23 | ||
| 24 | # DUMP: Contents of section .rodata: | 24 | # DUMP: Contents of section .rodata: |
| 25 | # DUMP: 00f4 ffff0004 ffff0008 | 25 | # DUMP: {{[0-9a-f]+}} ffff0004 ffff0008 |
| 26 | # ^ 0x10004 + 0x7ff0 - 0x27ff0 | 26 | # ^ 0x10004 + 0x7ff0 - 0x27ff0 |
| 27 | # ^ 0x10008 + 0x7ff0 - 0x27ff0 | 27 | # ^ 0x10008 + 0x7ff0 - 0x27ff0 |
| 28 | 28 | ||
| 29 | # DUMP: SYMBOL TABLE: | 29 | # DUMP: SYMBOL TABLE: |
| 30 | # DUMP: 00010008 .text 00000000 bar | 30 | # DUMP: 00010008 .text 00000000 bar |
| 31 | # DUMP: 00010004 .text 00000000 foo | 31 | # DUMP: 00010004 .text 00000000 foo |
| 32 | # DUMP: 00027ff0 *ABS* 00000000 .hidden _gp | 32 | # DUMP: 00027ff0 .got 00000000 .hidden _gp |
| 33 | 33 | ||
| 34 | # ERR: error: {{.*}}mips-gp0-non-zero.o: unsupported non-zero ri_gp_value | 34 | # ERR: error: {{.*}}mips-gp0-non-zero.o: unsupported non-zero ri_gp_value |
| 35 | 35 |
deps/lld/test/ELF/mips-gprel32-relocs.s+4-4| ... | @@ -21,11 +21,11 @@ v1: | ... | @@ -21,11 +21,11 @@ v1: |
| 21 | .gpword bar | 21 | .gpword bar |
| 22 | 22 | ||
| 23 | # CHECK: Contents of section .rodata: | 23 | # CHECK: Contents of section .rodata: |
| 24 | # CHECK: 00f4 fffe8014 fffe8018 | 24 | # CHECK: {{[0-9a-f]+}} fffe8014 fffe8018 |
| 25 | # ^ 0x10004 - 0x27ff0 | 25 | # ^ 0x10004 - 0x27ff0 |
| 26 | # ^ 0x10008 - 0x27ff0 | 26 | # ^ 0x10008 - 0x27ff0 |
| 27 | 27 | ||
| 28 | # CHECK: SYMBOL TABLE: | 28 | # CHECK: SYMBOL TABLE: |
| 29 | # CHECK: 00010008 .text 00000000 bar | 29 | # CHECK: 00010008 .text 00000000 bar |
| 30 | # CHECK: 00010004 .text 00000000 foo | 30 | # CHECK: 00010004 .text 00000000 foo |
| 31 | # CHECK: 00027ff0 *ABS* 00000000 .hidden _gp | 31 | # CHECK: 00027ff0 .got 00000000 .hidden _gp |
deps/lld/test/ELF/mips-hilo-gp-disp.s+2-2| ... | @@ -34,7 +34,7 @@ bar: | ... | @@ -34,7 +34,7 @@ bar: |
| 34 | 34 | ||
| 35 | # EXE: SYMBOL TABLE: | 35 | # EXE: SYMBOL TABLE: |
| 36 | # EXE: 0002000c .text 00000000 bar | 36 | # EXE: 0002000c .text 00000000 bar |
| 37 | # EXE: 00038000 *ABS* 00000000 .hidden _gp | 37 | # EXE: 00038000 .got 00000000 .hidden _gp |
| 38 | # EXE: 00020000 .text 00000000 __start | 38 | # EXE: 00020000 .text 00000000 __start |
| 39 | 39 | ||
| 40 | # SO: Disassembly of section .text: | 40 | # SO: Disassembly of section .text: |
| ... | @@ -51,5 +51,5 @@ bar: | ... | @@ -51,5 +51,5 @@ bar: |
| 51 | 51 | ||
| 52 | # SO: SYMBOL TABLE: | 52 | # SO: SYMBOL TABLE: |
| 53 | # SO: 0001000c .text 00000000 bar | 53 | # SO: 0001000c .text 00000000 bar |
| 54 | # SO: 00028000 *ABS* 00000000 .hidden _gp | 54 | # SO: 00028000 .got 00000000 .hidden _gp |
| 55 | # SO: 00010000 .text 00000000 __start | 55 | # SO: 00010000 .text 00000000 __start |
deps/lld/test/ELF/mips-hilo-hi-only.s+1-1| ... | @@ -18,7 +18,7 @@ _label: | ... | @@ -18,7 +18,7 @@ _label: |
| 18 | 18 | ||
| 19 | # CHECK: Disassembly of section .text: | 19 | # CHECK: Disassembly of section .text: |
| 20 | # CHECK-NEXT: __start: | 20 | # CHECK-NEXT: __start: |
| 21 | # CHECK-NEXT: 20000: 3c 08 00 02 lui $8, 2 | 21 | # CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 3 |
| 22 | # ^-- %hi(__start) w/o addend | 22 | # ^-- %hi(__start) w/o addend |
| 23 | # CHECK-NEXT 20004: 21 08 00 08 addi $8, $8, 8 | 23 | # CHECK-NEXT 20004: 21 08 00 08 addi $8, $8, 8 |
| 24 | # ^-- %lo(_label) | 24 | # ^-- %lo(_label) |
deps/lld/test/ELF/mips-micro-got.s created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | # Check microMIPS GOT relocations for O32 ABI. | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mattr=micromips \ | ||
| 4 | # RUN: %s -o %t1.o | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mattr=micromips \ | ||
| 6 | # RUN: %S/Inputs/mips-dynamic.s -o %t2.o | ||
| 7 | # RUN: ld.lld %t2.o -shared -o %t.so | ||
| 8 | # RUN: ld.lld %t1.o %t.so -o %t.exe | ||
| 9 | # RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck %s | ||
| 10 | |||
| 11 | # REQUIRES: mips | ||
| 12 | |||
| 13 | # CHECK: Local entries [ | ||
| 14 | # CHECK-NEXT: Entry { | ||
| 15 | # CHECK-NEXT: Address: | ||
| 16 | # CHECK-NEXT: Access: -32744 | ||
| 17 | # CHECK-NEXT: Initial: 0x30000 | ||
| 18 | # CHECK-NEXT: } | ||
| 19 | # CHECK-NEXT: Entry { | ||
| 20 | # CHECK-NEXT: Address: | ||
| 21 | # CHECK-NEXT: Access: -32740 | ||
| 22 | # CHECK-NEXT: Initial: 0x40000 | ||
| 23 | # CHECK-NEXT: } | ||
| 24 | # CHECK-NEXT: ] | ||
| 25 | # CHECK-NEXT: Global entries [ | ||
| 26 | # CHECK-NEXT: Entry { | ||
| 27 | # CHECK-NEXT: Address: | ||
| 28 | # CHECK-NEXT: Access: -32736 | ||
| 29 | # CHECK-NEXT: Initial: 0x0 | ||
| 30 | # CHECK-NEXT: Value: 0x0 | ||
| 31 | # CHECK-NEXT: Type: Function | ||
| 32 | # CHECK-NEXT: Section: Undefined | ||
| 33 | # CHECK-NEXT: Name: foo0 | ||
| 34 | # CHECK-NEXT: } | ||
| 35 | # CHECK-NEXT: ] | ||
| 36 | |||
| 37 | .text | ||
| 38 | .global __start | ||
| 39 | __start: | ||
| 40 | lw $4, %got(data)($28) | ||
| 41 | addiu $4, $4, %lo(data) | ||
| 42 | lw $25, %call16(foo0)($28) | ||
| 43 | |||
| 44 | .data | ||
| 45 | data: | ||
| 46 | .word 0 | ||
deps/lld/test/ELF/mips-micro-got64.s created+48| ... | @@ -0,0 +1,48 @@ | ||
| 1 | # Check microMIPS GOT relocations for N64 ABI. | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -mattr=micromips \ | ||
| 4 | # RUN: %s -o %t1.o | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -mattr=micromips \ | ||
| 6 | # RUN: %S/Inputs/mips-dynamic.s -o %t2.o | ||
| 7 | # RUN: ld.lld %t2.o -shared -o %t.so | ||
| 8 | # RUN: ld.lld %t1.o %t.so -o %t.exe | ||
| 9 | # RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck %s | ||
| 10 | |||
| 11 | # REQUIRES: mips | ||
| 12 | |||
| 13 | # CHECK: Local entries [ | ||
| 14 | # CHECK-NEXT: Entry { | ||
| 15 | # CHECK-NEXT: Address: | ||
| 16 | # CHECK-NEXT: Access: -32736 | ||
| 17 | # CHECK-NEXT: Initial: 0x30000 | ||
| 18 | # CHECK-NEXT: } | ||
| 19 | # CHECK-NEXT: Entry { | ||
| 20 | # CHECK-NEXT: Address: | ||
| 21 | # CHECK-NEXT: Access: -32728 | ||
| 22 | # CHECK-NEXT: Initial: 0x40000 | ||
| 23 | # CHECK-NEXT: } | ||
| 24 | # CHECK-NEXT: ] | ||
| 25 | # CHECK-NEXT: Global entries [ | ||
| 26 | # CHECK-NEXT: Entry { | ||
| 27 | # CHECK-NEXT: Address: | ||
| 28 | # CHECK-NEXT: Access: -32720 | ||
| 29 | # CHECK-NEXT: Initial: 0x0 | ||
| 30 | # CHECK-NEXT: Value: 0x0 | ||
| 31 | # CHECK-NEXT: Type: Function | ||
| 32 | # CHECK-NEXT: Section: Undefined | ||
| 33 | # CHECK-NEXT: Name: foo0 | ||
| 34 | # CHECK-NEXT: } | ||
| 35 | # CHECK-NEXT: ] | ||
| 36 | |||
| 37 | .text | ||
| 38 | .global __start | ||
| 39 | __start: | ||
| 40 | lui $28, %hi(%neg(%gp_rel(foo0))) | ||
| 41 | addiu $28, $28, %lo(%neg(%gp_rel(foo0))) | ||
| 42 | lw $4, %got_page(data)($28) | ||
| 43 | addiu $4, $4, %got_ofst(data) | ||
| 44 | lw $25, %call16(foo0)($28) | ||
| 45 | |||
| 46 | .data | ||
| 47 | data: | ||
| 48 | .word 0 | ||
deps/lld/test/ELF/mips-micro-jal.s created+155| ... | @@ -0,0 +1,155 @@ | ||
| 1 | # Check PLT creation for microMIPS to microMIPS calls. | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 4 | # RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1eb.o | ||
| 5 | # RUN: ld.lld -shared -o %teb.so %t1eb.o | ||
| 6 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 7 | # RUN: -mattr=micromips %s -o %t2eb.o | ||
| 8 | # RUN: ld.lld -o %teb.exe %t2eb.o %teb.so | ||
| 9 | # RUN: llvm-objdump -d -mattr=micromips %teb.exe | FileCheck --check-prefix=EB %s | ||
| 10 | # RUN: llvm-readobj -mips-plt-got %teb.exe | FileCheck --check-prefix=PLT %s | ||
| 11 | |||
| 12 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \ | ||
| 13 | # RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1el.o | ||
| 14 | # RUN: ld.lld -shared -o %tel.so %t1el.o | ||
| 15 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \ | ||
| 16 | # RUN: -mattr=micromips %s -o %t2el.o | ||
| 17 | # RUN: ld.lld -o %tel.exe %t2el.o %tel.so | ||
| 18 | # RUN: llvm-objdump -d -mattr=micromips %tel.exe | FileCheck --check-prefix=EL %s | ||
| 19 | # RUN: llvm-readobj -mips-plt-got %tel.exe | FileCheck --check-prefix=PLT %s | ||
| 20 | |||
| 21 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 22 | # RUN: -mattr=micromips -mcpu=mips32r6 %S/Inputs/mips-micro.s -o %t1eb.o | ||
| 23 | # RUN: ld.lld -shared -o %teb.so %t1eb.o | ||
| 24 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 25 | # RUN: -mattr=micromips -mcpu=mips32r6 %s -o %t2eb.o | ||
| 26 | # RUN: ld.lld -o %teb.exe %t2eb.o %teb.so | ||
| 27 | # RUN: llvm-objdump -d -mattr=micromips %teb.exe | FileCheck --check-prefix=EBR6 %s | ||
| 28 | |||
| 29 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \ | ||
| 30 | # RUN: -mattr=micromips -mcpu=mips32r6 %S/Inputs/mips-micro.s -o %t1el.o | ||
| 31 | # RUN: ld.lld -shared -o %tel.so %t1el.o | ||
| 32 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \ | ||
| 33 | # RUN: -mattr=micromips -mcpu=mips32r6 %s -o %t2el.o | ||
| 34 | # RUN: ld.lld -o %tel.exe %t2el.o %tel.so | ||
| 35 | # RUN: llvm-objdump -d -mattr=micromips %tel.exe | FileCheck --check-prefix=ELR6 %s | ||
| 36 | |||
| 37 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 38 | # RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1eb.o | ||
| 39 | # RUN: ld.lld -shared -o %teb.so %t1eb.o | ||
| 40 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 41 | # RUN: %S/Inputs/mips-fpic.s -o %t-reg.o | ||
| 42 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 43 | # RUN: -mattr=micromips %s -o %t2eb.o | ||
| 44 | # RUN: ld.lld --no-threads -o %teb.exe %t-reg.o %t2eb.o %teb.so | ||
| 45 | # RUN: llvm-objdump -d -mattr=micromips %teb.exe \ | ||
| 46 | # RUN: | FileCheck --check-prefix=MIXED %s | ||
| 47 | |||
| 48 | # REQUIRES: mips | ||
| 49 | |||
| 50 | # EB: Disassembly of section .plt: | ||
| 51 | # EB-NEXT: .plt: | ||
| 52 | # EB-NEXT: 20010: 79 80 3f fd addiupc $3, 65524 | ||
| 53 | # EB-NEXT: 20014: ff 23 00 00 lw $25, 0($3) | ||
| 54 | # EB-NEXT: 20018: 05 35 subu16 $2, $2, $3 | ||
| 55 | # EB-NEXT: 2001a: 25 25 srl16 $2, $2, 2 | ||
| 56 | # EB-NEXT: 2001c: 33 02 ff fe addiu $24, $2, -2 | ||
| 57 | # EB-NEXT: 20020: 0d ff move $15, $ra | ||
| 58 | # EB-NEXT: 20022: 45 f9 jalrs16 $25 | ||
| 59 | # EB-NEXT: 20024: 0f 83 move $gp, $3 | ||
| 60 | # EB-NEXT: 20026: 0c 00 nop | ||
| 61 | # EB-NEXT: 20028: 00 00 00 00 nop | ||
| 62 | # EB-NEXT: 2002c: 00 00 00 00 nop | ||
| 63 | |||
| 64 | # EB-NEXT: 20030: 79 00 3f f7 addiupc $2, 65500 | ||
| 65 | # EB-NEXT: 20034: ff 22 00 00 lw $25, 0($2) | ||
| 66 | # EB-NEXT: 20038: 45 99 jr16 $25 | ||
| 67 | # EB-NEXT: 2003a: 0f 02 move $24, $2 | ||
| 68 | |||
| 69 | # EL: Disassembly of section .plt: | ||
| 70 | # EL-NEXT: .plt: | ||
| 71 | # EL-NEXT: 20010: 80 79 fd 3f addiupc $3, 65524 | ||
| 72 | # EL-NEXT: 20014: 23 ff 00 00 lw $25, 0($3) | ||
| 73 | # EL-NEXT: 20018: 35 05 subu16 $2, $2, $3 | ||
| 74 | # EL-NEXT: 2001a: 25 25 srl16 $2, $2, 2 | ||
| 75 | # EL-NEXT: 2001c: 02 33 fe ff addiu $24, $2, -2 | ||
| 76 | # EL-NEXT: 20020: ff 0d move $15, $ra | ||
| 77 | # EL-NEXT: 20022: f9 45 jalrs16 $25 | ||
| 78 | # EL-NEXT: 20024: 83 0f move $gp, $3 | ||
| 79 | # EL-NEXT: 20026: 00 0c nop | ||
| 80 | # EL-NEXT: 20028: 00 00 00 00 nop | ||
| 81 | # EL-NEXT: 2002c: 00 00 00 00 nop | ||
| 82 | |||
| 83 | # EL-NEXT: 20030: 00 79 f7 3f addiupc $2, 65500 | ||
| 84 | # EL-NEXT: 20034: 22 ff 00 00 lw $25, 0($2) | ||
| 85 | # EL-NEXT: 20038: 99 45 jr16 $25 | ||
| 86 | # EL-NEXT: 2003a: 02 0f move $24, $2 | ||
| 87 | |||
| 88 | # EBR6: Disassembly of section .plt: | ||
| 89 | # EBR6-NEXT: .plt: | ||
| 90 | # EBR6-NEXT: 20010: 78 60 3f fd lapc $3, 65524 | ||
| 91 | # EBR6-NEXT: 20014: ff 23 00 00 lw $25, 0($3) | ||
| 92 | # EBR6-NEXT: 20018: 05 35 subu16 $2, $2, $3 | ||
| 93 | # EBR6-NEXT: 2001a: 25 25 srl16 $2, $2, 2 | ||
| 94 | # EBR6-NEXT: 2001c: 33 02 ff fe addiu $24, $2, -2 | ||
| 95 | # EBR6-NEXT: 20020: 0d ff move16 $15, $ra | ||
| 96 | # EBR6-NEXT: 20022: 0f 83 move16 $gp, $3 | ||
| 97 | # EBR6-NEXT: 20024: 47 2b jalr $25 | ||
| 98 | |||
| 99 | # EBR6: 20030: 78 40 3f f7 lapc $2, 65500 | ||
| 100 | # EBR6-NEXT: 20034: ff 22 00 00 lw $25, 0($2) | ||
| 101 | # EBR6-NEXT: 20038: 0f 02 move16 $24, $2 | ||
| 102 | # EBR6-NEXT: 2003a: 47 23 jrc16 $25 | ||
| 103 | |||
| 104 | # ELR6: Disassembly of section .plt: | ||
| 105 | # ELR6-NEXT: .plt: | ||
| 106 | # ELR6-NEXT: 20010: 60 78 fd 3f lapc $3, 65524 | ||
| 107 | # ELR6-NEXT: 20014: 23 ff 00 00 lw $25, 0($3) | ||
| 108 | # ELR6-NEXT: 20018: 35 05 subu16 $2, $2, $3 | ||
| 109 | # ELR6-NEXT: 2001a: 25 25 srl16 $2, $2, 2 | ||
| 110 | # ELR6-NEXT: 2001c: 02 33 fe ff addiu $24, $2, -2 | ||
| 111 | # ELR6-NEXT: 20020: ff 0d move16 $15, $ra | ||
| 112 | # ELR6-NEXT: 20022: 83 0f move16 $gp, $3 | ||
| 113 | # ELR6-NEXT: 20024: 2b 47 jalr $25 | ||
| 114 | |||
| 115 | # ELR6: 20030: 40 78 f7 3f lapc $2, 65500 | ||
| 116 | # ELR6-NEXT: 20034: 22 ff 00 00 lw $25, 0($2) | ||
| 117 | # ELR6-NEXT: 20038: 02 0f move16 $24, $2 | ||
| 118 | # ELR6-NEXT: 2003a: 23 47 jrc16 $25 | ||
| 119 | |||
| 120 | # MIXED: Disassembly of section .plt: | ||
| 121 | # MIXED-NEXT: .plt: | ||
| 122 | # MIXED-NEXT: 20020: 79 80 3f f9 addiupc $3, 65508 | ||
| 123 | # MIXED-NEXT: 20024: ff 23 00 00 lw $25, 0($3) | ||
| 124 | # MIXED-NEXT: 20028: 05 35 subu16 $2, $2, $3 | ||
| 125 | # MIXED-NEXT: 2002a: 25 25 srl16 $2, $2, 2 | ||
| 126 | # MIXED-NEXT: 2002c: 33 02 ff fe addiu $24, $2, -2 | ||
| 127 | # MIXED-NEXT: 20030: 0d ff move $15, $ra | ||
| 128 | # MIXED-NEXT: 20032: 45 f9 jalrs16 $25 | ||
| 129 | # MIXED-NEXT: 20034: 0f 83 move $gp, $3 | ||
| 130 | # MIXED-NEXT: 20036: 0c 00 nop | ||
| 131 | # MIXED-NEXT: 20038: 00 00 00 00 nop | ||
| 132 | # MIXED-NEXT: 2003c: 00 00 00 00 nop | ||
| 133 | |||
| 134 | # MIXED-NEXT: 20040: 79 00 3f f3 addiupc $2, 65484 | ||
| 135 | # MIXED-NEXT: 20044: ff 22 00 00 lw $25, 0($2) | ||
| 136 | # MIXED-NEXT: 20048: 45 99 jr16 $25 | ||
| 137 | # MIXED-NEXT: 2004a: 0f 02 move $24, $2 | ||
| 138 | |||
| 139 | # PLT: Entries [ | ||
| 140 | # PLT-NEXT: Entry { | ||
| 141 | # PLT-NEXT: Address: 0x3000C | ||
| 142 | # ^ 0x20030 + 65500 | ||
| 143 | # PLT-NEXT: Initial: | ||
| 144 | # PLT-NEXT: Value: 0x0 | ||
| 145 | # PLT-NEXT: Type: Function | ||
| 146 | # PLT-NEXT: Section: Undefined | ||
| 147 | # PLT-NEXT: Name: foo | ||
| 148 | # PLT-NEXT: } | ||
| 149 | # PLT-NEXT: ] | ||
| 150 | |||
| 151 | .text | ||
| 152 | .set micromips | ||
| 153 | .global __start | ||
| 154 | __start: | ||
| 155 | jal foo | ||
deps/lld/test/ELF/mips-micro-plt.s created+91| ... | @@ -0,0 +1,91 @@ | ||
| 1 | # Check less-significant bit setup for microMIPS PLT. | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 4 | # RUN: -mattr=micromips %S/Inputs/mips-dynamic.s -o %t-dso.o | ||
| 5 | # RUN: ld.lld %t-dso.o -shared -o %t.so | ||
| 6 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 7 | # RUN: -mattr=micromips %s -o %t-exe.o | ||
| 8 | # RUN: ld.lld %t-exe.o %t.so -o %t.exe | ||
| 9 | # RUN: llvm-readobj -t -dt -mips-plt-got %t.exe | FileCheck %s | ||
| 10 | |||
| 11 | # REQUIRES: mips | ||
| 12 | |||
| 13 | # CHECK: Symbols [ | ||
| 14 | # CHECK: Symbol { | ||
| 15 | # CHECK: Name: foo | ||
| 16 | # CHECK-NEXT: Value: 0x20008 | ||
| 17 | # CHECK-NEXT: Size: | ||
| 18 | # CHECK-NEXT: Binding: Local | ||
| 19 | # CHECK-NEXT: Type: None | ||
| 20 | # CHECK-NEXT: Other [ | ||
| 21 | # CHECK-NEXT: STO_MIPS_MICROMIPS | ||
| 22 | # CHECK-NEXT: STV_HIDDEN | ||
| 23 | # CHECK-NEXT: ] | ||
| 24 | # CHECK-NEXT: Section: .text | ||
| 25 | # CHECK-NEXT: } | ||
| 26 | # CHECK: Symbol { | ||
| 27 | # CHECK: Name: __start | ||
| 28 | # CHECK-NEXT: Value: 0x20000 | ||
| 29 | # CHECK-NEXT: Size: | ||
| 30 | # CHECK-NEXT: Binding: Global | ||
| 31 | # CHECK-NEXT: Type: None | ||
| 32 | # CHECK-NEXT: Other [ | ||
| 33 | # CHECK-NEXT: STO_MIPS_MICROMIPS | ||
| 34 | # CHECK-NEXT: ] | ||
| 35 | # CHECK-NEXT: Section: .text | ||
| 36 | # CHECK-NEXT: } | ||
| 37 | # CHECK: Symbol { | ||
| 38 | # CHECK: Name: foo0 | ||
| 39 | # CHECK-NEXT: Value: 0x0 | ||
| 40 | # CHECK-NEXT: Size: | ||
| 41 | # CHECK-NEXT: Binding: Global | ||
| 42 | # CHECK-NEXT: Type: Function | ||
| 43 | # CHECK-NEXT: Other: 0 | ||
| 44 | # CHECK-NEXT: Section: Undefined | ||
| 45 | # CHECK-NEXT: } | ||
| 46 | # CHECK-NEXT: ] | ||
| 47 | # CHECK: DynamicSymbols [ | ||
| 48 | # CHECK: Symbol { | ||
| 49 | # CHECK: Name: foo0 | ||
| 50 | # CHECK-NEXT: Value: 0x0 | ||
| 51 | # CHECK-NEXT: Size: | ||
| 52 | # CHECK-NEXT: Binding: Global | ||
| 53 | # CHECK-NEXT: Type: Function | ||
| 54 | # CHECK-NEXT: Other: 0 | ||
| 55 | # CHECK-NEXT: Section: Undefined | ||
| 56 | # CHECK-NEXT: } | ||
| 57 | # CHECK-NEXT: ] | ||
| 58 | |||
| 59 | # CHECK: Primary GOT { | ||
| 60 | # CHECK: Local entries [ | ||
| 61 | # CHECK-NEXT: Entry { | ||
| 62 | # CHECK-NEXT: Address: | ||
| 63 | # CHECK-NEXT: Access: | ||
| 64 | # CHECK-NEXT: Initial: 0x20009 | ||
| 65 | # CHECK-NEXT: } | ||
| 66 | # CHECK: ] | ||
| 67 | # CHECK: } | ||
| 68 | |||
| 69 | # CHECK: PLT GOT { | ||
| 70 | # CHECK: Entries [ | ||
| 71 | # CHECK-NEXT: Entry { | ||
| 72 | # CHECK-NEXT: Address: | ||
| 73 | # CHECK-NEXT: Initial: 0x20011 | ||
| 74 | # CHECK-NEXT: Value: 0x0 | ||
| 75 | # CHECK-NEXT: Type: Function | ||
| 76 | # CHECK-NEXT: Section: Undefined | ||
| 77 | # CHECK-NEXT: Name: foo0@ | ||
| 78 | # CHECK-NEXT: } | ||
| 79 | # CHECK-NEXT: ] | ||
| 80 | # CHECK-NEXT: } | ||
| 81 | |||
| 82 | .text | ||
| 83 | .set micromips | ||
| 84 | .global foo | ||
| 85 | .hidden foo | ||
| 86 | .global __start | ||
| 87 | __start: | ||
| 88 | lw $t0,%got(foo)($gp) | ||
| 89 | addi $t0,$t0,%lo(foo) | ||
| 90 | foo: | ||
| 91 | jal foo0 | ||
deps/lld/test/ELF/mips-micro-relocs.s created+59| ... | @@ -0,0 +1,59 @@ | ||
| 1 | # Check handling of microMIPS relocations. | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 4 | # RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1eb.o | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 6 | # RUN: -mattr=micromips %s -o %t2eb.o | ||
| 7 | # RUN: ld.lld -o %teb.exe %t1eb.o %t2eb.o | ||
| 8 | # RUN: llvm-objdump -d -t -mattr=micromips %teb.exe \ | ||
| 9 | # RUN: | FileCheck --check-prefixes=EB,SYM %s | ||
| 10 | |||
| 11 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \ | ||
| 12 | # RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1el.o | ||
| 13 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \ | ||
| 14 | # RUN: -mattr=micromips %s -o %t2el.o | ||
| 15 | # RUN: ld.lld -o %tel.exe %t1el.o %t2el.o | ||
| 16 | # RUN: llvm-objdump -d -t -mattr=micromips %tel.exe \ | ||
| 17 | # RUN: | FileCheck --check-prefixes=EL,SYM %s | ||
| 18 | |||
| 19 | # REQUIRES: mips | ||
| 20 | |||
| 21 | # EB: __start: | ||
| 22 | # EB-NEXT: 20010: 41 a3 00 01 lui $3, 1 | ||
| 23 | # EB-NEXT: 20014: 30 63 7f df addiu $3, $3, 32735 | ||
| 24 | # EB-NEXT: 20018: fc 7c 80 18 lw $3, -32744($gp) | ||
| 25 | # EB-NEXT: 2001c: fc 63 80 18 lw $3, -32744($3) | ||
| 26 | # EB-NEXT: 20020: 8f 70 beqz16 $6, -32 | ||
| 27 | # EB-NEXT: 20022: 00 7e 00 00 sll $3, $fp, 0 | ||
| 28 | # EB-NEXT: 20026: cf ec b16 -40 | ||
| 29 | # EB-NEXT: 20028: 00 00 00 00 nop | ||
| 30 | # EB-NEXT: 2002c: 94 00 ff e8 b -44 | ||
| 31 | |||
| 32 | # EL: __start: | ||
| 33 | # EL-NEXT: 20010: a3 41 01 00 lui $3, 1 | ||
| 34 | # EL-NEXT: 20014: 63 30 df 7f addiu $3, $3, 32735 | ||
| 35 | # EL-NEXT: 20018: 7c fc 18 80 lw $3, -32744($gp) | ||
| 36 | # EL-NEXT: 2001c: 63 fc 18 80 lw $3, -32744($3) | ||
| 37 | # EL-NEXT: 20020: 70 8f beqz16 $6, -32 | ||
| 38 | # EL-NEXT: 20022: 7e 00 00 00 sll $3, $fp, 0 | ||
| 39 | # EL-NEXT: 20026: ec cf b16 -40 | ||
| 40 | # EL-NEXT: 20028: 00 00 00 00 nop | ||
| 41 | # EL-NEXT: 2002c: 00 94 e8 ff b -44 | ||
| 42 | |||
| 43 | # SYM: 00037ff0 .got 00000000 .hidden _gp | ||
| 44 | # SYM: 00020000 g F .text 00000000 foo | ||
| 45 | # SYM: 00020010 .text 00000000 __start | ||
| 46 | |||
| 47 | .text | ||
| 48 | .set micromips | ||
| 49 | .global __start | ||
| 50 | __start: | ||
| 51 | lui $3, %hi(_gp_disp) # R_MICROMIPS_HI16 | ||
| 52 | addiu $3, $3, %lo(_gp_disp) # R_MICROMIPS_LO16 | ||
| 53 | |||
| 54 | lw $3, %call16(foo)($gp) # R_MICROMIPS_CALL16 | ||
| 55 | lw $3, %got(foo)($3) # R_MICROMIPS_GOT16 | ||
| 56 | |||
| 57 | beqz16 $6, foo # R_MICROMIPS_PC7_S1 | ||
| 58 | b16 foo # R_MICROMIPS_PC10_S1 | ||
| 59 | b foo # R_MICROMIPS_PC16_S1 | ||
deps/lld/test/ELF/mips-micro-thunks.s created+47| ... | @@ -0,0 +1,47 @@ | ||
| 1 | # Check microMIPS thunk generation. | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 4 | # RUN: -mattr=micromips %s -o %t-eb.o | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ | ||
| 6 | # RUN: -position-independent -mattr=micromips \ | ||
| 7 | # RUN: %S/Inputs/mips-micro.s -o %t-eb-pic.o | ||
| 8 | # RUN: ld.lld -o %t-eb.exe %t-eb.o %t-eb-pic.o | ||
| 9 | # RUN: llvm-objdump -d -mattr=+micromips %t-eb.exe \ | ||
| 10 | # RUN: | FileCheck --check-prefix=EB %s | ||
| 11 | |||
| 12 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \ | ||
| 13 | # RUN: -mattr=micromips %s -o %t-el.o | ||
| 14 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \ | ||
| 15 | # RUN: -position-independent -mattr=micromips \ | ||
| 16 | # RUN: %S/Inputs/mips-micro.s -o %t-el-pic.o | ||
| 17 | # RUN: ld.lld -o %t-el.exe %t-el.o %t-el-pic.o | ||
| 18 | # RUN: llvm-objdump -d -mattr=+micromips %t-el.exe \ | ||
| 19 | # RUN: | FileCheck --check-prefix=EL %s | ||
| 20 | |||
| 21 | # REQUIRES: mips | ||
| 22 | |||
| 23 | # EB: __start: | ||
| 24 | # EB-NEXT: 20000: f4 01 00 04 jal 131080 <__microLA25Thunk_foo> | ||
| 25 | # EB-NEXT: 20004: 00 00 00 00 nop | ||
| 26 | |||
| 27 | # EB: __microLA25Thunk_foo: | ||
| 28 | # EB-NEXT: 20008: 41 b9 00 02 lui $25, 2 | ||
| 29 | # EB-NEXT: 2000c: d4 01 00 10 j 131104 | ||
| 30 | # EB-NEXT: 20010: 33 39 00 21 addiu $25, $25, 33 | ||
| 31 | # EB-NEXT: 20014: 0c 00 nop | ||
| 32 | |||
| 33 | # EL: __start: | ||
| 34 | # EL-NEXT: 20000: 01 f4 04 00 jal 131080 <__microLA25Thunk_foo> | ||
| 35 | # EL-NEXT: 20004: 00 00 00 00 nop | ||
| 36 | |||
| 37 | # EL: __microLA25Thunk_foo: | ||
| 38 | # EL-NEXT: 20008: b9 41 02 00 lui $25, 2 | ||
| 39 | # EL-NEXT: 2000c: 01 d4 10 00 j 131104 | ||
| 40 | # EL-NEXT: 20010: 39 33 21 00 addiu $25, $25, 33 | ||
| 41 | # EL-NEXT: 20014: 00 0c nop | ||
| 42 | |||
| 43 | .text | ||
| 44 | .set micromips | ||
| 45 | .global __start | ||
| 46 | __start: | ||
| 47 | jal foo | ||
deps/lld/test/ELF/mips-n32-rels.s+3-3| ... | @@ -38,11 +38,11 @@ | ... | @@ -38,11 +38,11 @@ |
| 38 | # ^-- %lo(0x17ff0) | 38 | # ^-- %lo(0x17ff0) |
| 39 | 39 | ||
| 40 | # CHECK: Contents of section .rodata: | 40 | # CHECK: Contents of section .rodata: |
| 41 | # CHECK-NEXT: 100d4 00020004 | 41 | # CHECK-NEXT: {{[0-9a-f]+}} 00020004 |
| 42 | # ^-- loc | 42 | # ^-- loc |
| 43 | 43 | ||
| 44 | # CHECK: 00020004 .text 00000000 loc | 44 | # CHECK: 00020004 .text 00000000 loc |
| 45 | # CHECK: 00037ff0 *ABS* 00000000 .hidden _gp | 45 | # CHECK: 00037ff0 .got 00000000 .hidden _gp |
| 46 | # CHECK: 00020000 g F .text 00000000 __start | 46 | # CHECK: 00020000 g F .text 00000000 __start |
| 47 | 47 | ||
| 48 | # ELF: Format: ELF32-mips | 48 | # ELF: Format: ELF32-mips |
deps/lld/test/ELF/mips-out-of-bounds-call16-reloc.s created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | # Check that we create an error on an out-of-bounds R_MIPS_CALL_16 | ||
| 2 | |||
| 3 | # REQUIRES: mips | ||
| 4 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t1.o | ||
| 5 | # RUN: not ld.lld %t1.o -o %t.exe 2>&1 | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: relocation R_MIPS_CALL16 out of range: 32768 is not in [-32768, 32767] | ||
| 8 | |||
| 9 | .macro generate_values | ||
| 10 | .irp i, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | ||
| 11 | .irp j, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | ||
| 12 | .irp k, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | ||
| 13 | .irp l, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | ||
| 14 | .text | ||
| 15 | .globl sym_\i\j\k\l | ||
| 16 | sym_\i\j\k\l: | ||
| 17 | nop | ||
| 18 | lw $25,%call16(sym_\i\j\k\l)($28) | ||
| 19 | .endr | ||
| 20 | .endr | ||
| 21 | .endr | ||
| 22 | .endr | ||
| 23 | .endm | ||
| 24 | |||
| 25 | generate_values | ||
| 26 | |||
| 27 | .globl __start | ||
| 28 | __start: | ||
| 29 | nop | ||
deps/lld/test/ELF/no-inhibit-exec.s+4| ... | @@ -2,12 +2,16 @@ | ... | @@ -2,12 +2,16 @@ |
| 2 | # RUN: not ld.lld %t -o %t2 | 2 | # RUN: not ld.lld %t -o %t2 |
| 3 | # RUN: ld.lld %t --noinhibit-exec -o %t2 | 3 | # RUN: ld.lld %t --noinhibit-exec -o %t2 |
| 4 | # RUN: llvm-objdump -d %t2 | FileCheck %s | 4 | # RUN: llvm-objdump -d %t2 | FileCheck %s |
| 5 | # RUN: llvm-readobj -r %t2 | FileCheck %s --check-prefix=RELOC | ||
| 5 | # REQUIRES: x86 | 6 | # REQUIRES: x86 |
| 6 | 7 | ||
| 7 | # CHECK: Disassembly of section .text: | 8 | # CHECK: Disassembly of section .text: |
| 8 | # CHECK-NEXT: _start | 9 | # CHECK-NEXT: _start |
| 9 | # CHECK-NEXT: 201000: {{.*}} callq -2101253 | 10 | # CHECK-NEXT: 201000: {{.*}} callq -2101253 |
| 10 | 11 | ||
| 12 | # RELOC: Relocations [ | ||
| 13 | # RELOC-NEXT: ] | ||
| 14 | |||
| 11 | # next code will not link without noinhibit-exec flag | 15 | # next code will not link without noinhibit-exec flag |
| 12 | # because of undefined symbol _bar | 16 | # because of undefined symbol _bar |
| 13 | .globl _start | 17 | .globl _start |
deps/lld/test/ELF/non-abs-reloc.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s | 3 | // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s |
| 4 | // CHECK: {{.*}}:(.dummy+0x0): has non-ABS reloc | 4 | // CHECK: {{.*}}:(.dummy+0x0): has non-ABS relocation R_X86_64_GOTPCREL against symbol 'foo' |
| 5 | 5 | ||
| 6 | .globl _start | 6 | .globl _start |
| 7 | _start: | 7 | _start: |
deps/lld/test/ELF/noplt-pie.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.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o | 3 | # 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 | 4 | # RUN: ld.lld -shared %t2.o -o %t2.so |
| 5 | # RUN: ld.lld %t1.o %t2.so -o %t.out | 5 | # RUN: ld.lld --hash-style=sysv %t1.o %t2.so -o %t.out |
| 6 | # RUN: llvm-readobj -s -r %t.out | FileCheck %s | 6 | # RUN: llvm-readobj -s -r %t.out | FileCheck %s |
| 7 | 7 | ||
| 8 | # CHECK: Section { | 8 | # CHECK: Section { |
deps/lld/test/ELF/pack-dyn-relocs.s created+210| ... | @@ -0,0 +1,210 @@ | ||
| 1 | // REQUIRES: arm, aarch64 | ||
| 2 | |||
| 3 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-shared.s -o %t.a32.so.o | ||
| 4 | // 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.a32 | ||
| 6 | // 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 %s | ||
| 8 | // RUN: ld.lld -pie --pack-dyn-relocs=android %t.a32 %t.a32.so -o %t3.a32 | ||
| 9 | // RUN: llvm-readobj -s -dynamic-table %t3.a32 | FileCheck --check-prefix=PACKED32-HEADERS %s | ||
| 10 | // RUN: llvm-readobj -relocations %t3.a32 | FileCheck --check-prefix=PACKED32 %s | ||
| 11 | |||
| 12 | // Unpacked should have the relative relocations in their natural order. | ||
| 13 | // UNPACKED32: 0x1000 R_ARM_RELATIVE - 0x0 | ||
| 14 | // UNPACKED32-NEXT: 0x1004 R_ARM_RELATIVE - 0x0 | ||
| 15 | // UNPACKED32-NEXT: 0x1008 R_ARM_RELATIVE - 0x0 | ||
| 16 | // UNPACKED32-NEXT: 0x100C R_ARM_RELATIVE - 0x0 | ||
| 17 | // UNPACKED32-NEXT: 0x1010 R_ARM_RELATIVE - 0x0 | ||
| 18 | // UNPACKED32-NEXT: 0x1014 R_ARM_RELATIVE - 0x0 | ||
| 19 | // UNPACKED32-NEXT: 0x1018 R_ARM_RELATIVE - 0x0 | ||
| 20 | // UNPACKED32-NEXT: 0x101C R_ARM_RELATIVE - 0x0 | ||
| 21 | |||
| 22 | // UNPACKED32-NEXT: 0x1024 R_ARM_RELATIVE - 0x0 | ||
| 23 | // UNPACKED32-NEXT: 0x1028 R_ARM_RELATIVE - 0x0 | ||
| 24 | // UNPACKED32-NEXT: 0x102C R_ARM_RELATIVE - 0x0 | ||
| 25 | // UNPACKED32-NEXT: 0x1030 R_ARM_RELATIVE - 0x0 | ||
| 26 | // UNPACKED32-NEXT: 0x1034 R_ARM_RELATIVE - 0x0 | ||
| 27 | // UNPACKED32-NEXT: 0x1038 R_ARM_RELATIVE - 0x0 | ||
| 28 | // UNPACKED32-NEXT: 0x103C R_ARM_RELATIVE - 0x0 | ||
| 29 | |||
| 30 | // UNPACKED32-NEXT: 0x1044 R_ARM_RELATIVE - 0x0 | ||
| 31 | // UNPACKED32-NEXT: 0x1048 R_ARM_RELATIVE - 0x0 | ||
| 32 | // UNPACKED32-NEXT: 0x104C R_ARM_RELATIVE - 0x0 | ||
| 33 | // UNPACKED32-NEXT: 0x1050 R_ARM_RELATIVE - 0x0 | ||
| 34 | // UNPACKED32-NEXT: 0x1054 R_ARM_RELATIVE - 0x0 | ||
| 35 | // UNPACKED32-NEXT: 0x1058 R_ARM_RELATIVE - 0x0 | ||
| 36 | // UNPACKED32-NEXT: 0x105C R_ARM_RELATIVE - 0x0 | ||
| 37 | // UNPACKED32-NEXT: 0x1060 R_ARM_RELATIVE - 0x0 | ||
| 38 | // UNPACKED32-NEXT: 0x1064 R_ARM_RELATIVE - 0x0 | ||
| 39 | |||
| 40 | // UNPACKED32-NEXT: 0x1020 R_ARM_ABS32 bar2 0x0 | ||
| 41 | // UNPACKED32-NEXT: 0x1040 R_ARM_ABS32 zed2 0x0 | ||
| 42 | |||
| 43 | // PACKED32-HEADERS: Index: 1 | ||
| 44 | // PACKED32-HEADERS-NEXT: Name: .dynsym | ||
| 45 | |||
| 46 | // PACKED32-HEADERS: Name: .rel.dyn | ||
| 47 | // PACKED32-HEADERS-NEXT: Type: SHT_ANDROID_REL | ||
| 48 | // PACKED32-HEADERS-NEXT: Flags [ (0x2) | ||
| 49 | // PACKED32-HEADERS-NEXT: SHF_ALLOC (0x2) | ||
| 50 | // PACKED32-HEADERS-NEXT: ] | ||
| 51 | // PACKED32-HEADERS-NEXT: Address: [[ADDR:.*]] | ||
| 52 | // PACKED32-HEADERS-NEXT: Offset: [[ADDR]] | ||
| 53 | // PACKED32-HEADERS-NEXT: Size: [[SIZE:.*]] | ||
| 54 | // PACKED32-HEADERS-NEXT: Link: 1 | ||
| 55 | // PACKED32-HEADERS-NEXT: Info: 0 | ||
| 56 | // PACKED32-HEADERS-NEXT: AddressAlignment: 4 | ||
| 57 | // PACKED32-HEADERS-NEXT: EntrySize: 1 | ||
| 58 | |||
| 59 | // PACKED32-HEADERS: 0x6000000F ANDROID_REL [[ADDR]] | ||
| 60 | // PACKED32-HEADERS: 0x60000010 ANDROID_RELSZ [[SIZE]] | ||
| 61 | |||
| 62 | // Packed should have the larger groups of relative relocations first, | ||
| 63 | // i.e. the 8 and 9 followed by the 7. | ||
| 64 | // PACKED32: 0x1000 R_ARM_RELATIVE - 0x0 | ||
| 65 | // PACKED32-NEXT: 0x1004 R_ARM_RELATIVE - 0x0 | ||
| 66 | // PACKED32-NEXT: 0x1008 R_ARM_RELATIVE - 0x0 | ||
| 67 | // PACKED32-NEXT: 0x100C R_ARM_RELATIVE - 0x0 | ||
| 68 | // PACKED32-NEXT: 0x1010 R_ARM_RELATIVE - 0x0 | ||
| 69 | // PACKED32-NEXT: 0x1014 R_ARM_RELATIVE - 0x0 | ||
| 70 | // PACKED32-NEXT: 0x1018 R_ARM_RELATIVE - 0x0 | ||
| 71 | // PACKED32-NEXT: 0x101C R_ARM_RELATIVE - 0x0 | ||
| 72 | |||
| 73 | // PACKED32-NEXT: 0x1044 R_ARM_RELATIVE - 0x0 | ||
| 74 | // PACKED32-NEXT: 0x1048 R_ARM_RELATIVE - 0x0 | ||
| 75 | // PACKED32-NEXT: 0x104C R_ARM_RELATIVE - 0x0 | ||
| 76 | // PACKED32-NEXT: 0x1050 R_ARM_RELATIVE - 0x0 | ||
| 77 | // PACKED32-NEXT: 0x1054 R_ARM_RELATIVE - 0x0 | ||
| 78 | // PACKED32-NEXT: 0x1058 R_ARM_RELATIVE - 0x0 | ||
| 79 | // PACKED32-NEXT: 0x105C R_ARM_RELATIVE - 0x0 | ||
| 80 | // PACKED32-NEXT: 0x1060 R_ARM_RELATIVE - 0x0 | ||
| 81 | // PACKED32-NEXT: 0x1064 R_ARM_RELATIVE - 0x0 | ||
| 82 | |||
| 83 | // PACKED32-NEXT: 0x1024 R_ARM_RELATIVE - 0x0 | ||
| 84 | // PACKED32-NEXT: 0x1028 R_ARM_RELATIVE - 0x0 | ||
| 85 | // PACKED32-NEXT: 0x102C R_ARM_RELATIVE - 0x0 | ||
| 86 | // PACKED32-NEXT: 0x1030 R_ARM_RELATIVE - 0x0 | ||
| 87 | // PACKED32-NEXT: 0x1034 R_ARM_RELATIVE - 0x0 | ||
| 88 | // PACKED32-NEXT: 0x1038 R_ARM_RELATIVE - 0x0 | ||
| 89 | // PACKED32-NEXT: 0x103C R_ARM_RELATIVE - 0x0 | ||
| 90 | |||
| 91 | // PACKED32-NEXT: 0x1020 R_ARM_ABS32 bar2 0x0 | ||
| 92 | // PACKED32-NEXT: 0x1040 R_ARM_ABS32 zed2 0x0 | ||
| 93 | |||
| 94 | // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/shared2.s -o %t.a64.so.o | ||
| 95 | // RUN: ld.lld -shared %t.a64.so.o -o %t.a64.so | ||
| 96 | // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.a64 | ||
| 97 | // RUN: ld.lld -pie --pack-dyn-relocs=none %t.a64 %t.a64.so -o %t2.a64 | ||
| 98 | // RUN: llvm-readobj -relocations %t2.a64 | FileCheck --check-prefix=UNPACKED64 %s | ||
| 99 | // RUN: ld.lld -pie --pack-dyn-relocs=android %t.a64 %t.a64.so -o %t3.a64 | ||
| 100 | // RUN: llvm-readobj -s -dynamic-table %t3.a64 | FileCheck --check-prefix=PACKED64-HEADERS %s | ||
| 101 | // RUN: llvm-readobj -relocations %t3.a64 | FileCheck --check-prefix=PACKED64 %s | ||
| 102 | |||
| 103 | // UNPACKED64: 0x10000 R_AARCH64_RELATIVE - 0x1 | ||
| 104 | // UNPACKED64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x2 | ||
| 105 | // UNPACKED64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x3 | ||
| 106 | // UNPACKED64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x4 | ||
| 107 | // UNPACKED64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x5 | ||
| 108 | // UNPACKED64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x6 | ||
| 109 | // UNPACKED64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x7 | ||
| 110 | // UNPACKED64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x8 | ||
| 111 | |||
| 112 | // UNPACKED64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x1 | ||
| 113 | // UNPACKED64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x2 | ||
| 114 | // UNPACKED64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x3 | ||
| 115 | // UNPACKED64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x4 | ||
| 116 | // UNPACKED64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x5 | ||
| 117 | // UNPACKED64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x6 | ||
| 118 | // UNPACKED64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x7 | ||
| 119 | |||
| 120 | // UNPACKED64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x1 | ||
| 121 | // UNPACKED64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x2 | ||
| 122 | // UNPACKED64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x3 | ||
| 123 | // UNPACKED64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x4 | ||
| 124 | // UNPACKED64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x5 | ||
| 125 | // UNPACKED64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x6 | ||
| 126 | // UNPACKED64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x7 | ||
| 127 | // UNPACKED64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x8 | ||
| 128 | // UNPACKED64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x9 | ||
| 129 | |||
| 130 | // UNPACKED64-NEXT: 0x10040 R_AARCH64_ABS64 bar2 0x1 | ||
| 131 | // UNPACKED64-NEXT: 0x10080 R_AARCH64_ABS64 zed2 0x0 | ||
| 132 | |||
| 133 | // PACKED64: 0x10000 R_AARCH64_RELATIVE - 0x1 | ||
| 134 | // PACKED64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x2 | ||
| 135 | // PACKED64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x3 | ||
| 136 | // PACKED64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x4 | ||
| 137 | // PACKED64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x5 | ||
| 138 | // PACKED64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x6 | ||
| 139 | // PACKED64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x7 | ||
| 140 | // PACKED64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x8 | ||
| 141 | |||
| 142 | // PACKED64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x1 | ||
| 143 | // PACKED64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x2 | ||
| 144 | // PACKED64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x3 | ||
| 145 | // PACKED64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x4 | ||
| 146 | // PACKED64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x5 | ||
| 147 | // PACKED64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x6 | ||
| 148 | // PACKED64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x7 | ||
| 149 | // PACKED64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x8 | ||
| 150 | // PACKED64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x9 | ||
| 151 | |||
| 152 | // PACKED64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x1 | ||
| 153 | // PACKED64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x2 | ||
| 154 | // PACKED64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x3 | ||
| 155 | // PACKED64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x4 | ||
| 156 | // PACKED64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x5 | ||
| 157 | // PACKED64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x6 | ||
| 158 | // PACKED64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x7 | ||
| 159 | |||
| 160 | // PACKED64-NEXT: 0x10040 R_AARCH64_ABS64 bar2 0x1 | ||
| 161 | // PACKED64-NEXT: 0x10080 R_AARCH64_ABS64 zed2 0x0 | ||
| 162 | |||
| 163 | // PACKED64-HEADERS: Index: 1 | ||
| 164 | // PACKED64-HEADERS-NEXT: Name: .dynsym | ||
| 165 | |||
| 166 | // PACKED64-HEADERS: Name: .rela.dyn | ||
| 167 | // PACKED64-HEADERS-NEXT: Type: SHT_ANDROID_RELA | ||
| 168 | // PACKED64-HEADERS-NEXT: Flags [ (0x2) | ||
| 169 | // PACKED64-HEADERS-NEXT: SHF_ALLOC (0x2) | ||
| 170 | // PACKED64-HEADERS-NEXT: ] | ||
| 171 | // PACKED64-HEADERS-NEXT: Address: [[ADDR:.*]] | ||
| 172 | // PACKED64-HEADERS-NEXT: Offset: [[ADDR]] | ||
| 173 | // PACKED64-HEADERS-NEXT: Size: [[SIZE:.*]] | ||
| 174 | // PACKED64-HEADERS-NEXT: Link: 1 | ||
| 175 | // PACKED64-HEADERS-NEXT: Info: 0 | ||
| 176 | // PACKED64-HEADERS-NEXT: AddressAlignment: 8 | ||
| 177 | // PACKED64-HEADERS-NEXT: EntrySize: 1 | ||
| 178 | |||
| 179 | // PACKED64-HEADERS: 0x0000000060000011 ANDROID_RELA [[ADDR]] | ||
| 180 | // PACKED64-HEADERS: 0x0000000060000012 ANDROID_RELASZ [[SIZE]] | ||
| 181 | |||
| 182 | .data | ||
| 183 | .dc.a __ehdr_start + 1 | ||
| 184 | .dc.a __ehdr_start + 2 | ||
| 185 | .dc.a __ehdr_start + 3 | ||
| 186 | .dc.a __ehdr_start + 4 | ||
| 187 | .dc.a __ehdr_start + 5 | ||
| 188 | .dc.a __ehdr_start + 6 | ||
| 189 | .dc.a __ehdr_start + 7 | ||
| 190 | .dc.a __ehdr_start + 8 | ||
| 191 | .dc.a bar2 + 1 | ||
| 192 | |||
| 193 | .dc.a __ehdr_start + 1 | ||
| 194 | .dc.a __ehdr_start + 2 | ||
| 195 | .dc.a __ehdr_start + 3 | ||
| 196 | .dc.a __ehdr_start + 4 | ||
| 197 | .dc.a __ehdr_start + 5 | ||
| 198 | .dc.a __ehdr_start + 6 | ||
| 199 | .dc.a __ehdr_start + 7 | ||
| 200 | .dc.a zed2 | ||
| 201 | |||
| 202 | .dc.a __ehdr_start + 1 | ||
| 203 | .dc.a __ehdr_start + 2 | ||
| 204 | .dc.a __ehdr_start + 3 | ||
| 205 | .dc.a __ehdr_start + 4 | ||
| 206 | .dc.a __ehdr_start + 5 | ||
| 207 | .dc.a __ehdr_start + 6 | ||
| 208 | .dc.a __ehdr_start + 7 | ||
| 209 | .dc.a __ehdr_start + 8 | ||
| 210 | .dc.a __ehdr_start + 9 | ||
deps/lld/test/ELF/pie-weak.s+5-2| ... | @@ -1,10 +1,13 @@ | ... | @@ -1,10 +1,13 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -relax-relocations=false -triple=x86_64-unknown-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -relax-relocations=false -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | # RUN: ld.lld -pie %t.o -o %t | 3 | # RUN: ld.lld --hash-style=sysv -pie %t.o -o %t |
| 4 | # RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOCS %s | 4 | # RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOCS %s |
| 5 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s | 5 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s |
| 6 | 6 | ||
| 7 | # RELOCS: Relocations [ | 7 | # RELOCS: Relocations [ |
| 8 | # RELOCS-NEXT: Section ({{.*}}) .rela.dyn { | ||
| 9 | # RELOCS-NEXT: R_X86_64_GLOB_DAT foo 0x0 | ||
| 10 | # RELOCS-NEXT: } | ||
| 8 | # RELOCS-NEXT: ] | 11 | # RELOCS-NEXT: ] |
| 9 | 12 | ||
| 10 | .weak foo | 13 | .weak foo |
| ... | @@ -12,6 +15,6 @@ | ... | @@ -12,6 +15,6 @@ |
| 12 | .globl _start | 15 | .globl _start |
| 13 | _start: | 16 | _start: |
| 14 | # DISASM: _start: | 17 | # DISASM: _start: |
| 15 | # DISASM-NEXT: 1000: 48 8b 05 69 10 00 00 movq 4201(%rip), %rax | 18 | # DISASM-NEXT: 1000: 48 8b 05 99 10 00 00 movq 4249(%rip), %rax |
| 16 | # ^ .got - (.text + 7) | 19 | # ^ .got - (.text + 7) |
| 17 | mov foo@gotpcrel(%rip), %rax | 20 | mov foo@gotpcrel(%rip), %rax |
deps/lld/test/ELF/ppc-relocs.s+31-5| ... | @@ -17,6 +17,20 @@ msg: | ... | @@ -17,6 +17,20 @@ msg: |
| 17 | # CHECK: msg: | 17 | # CHECK: msg: |
| 18 | # CHECK: 11004: 66 6f 6f 00 oris 15, 19, 28416 | 18 | # CHECK: 11004: 66 6f 6f 00 oris 15, 19, 28416 |
| 19 | 19 | ||
| 20 | .section .R_PPC_ADDR16_HI,"ax",@progbits | ||
| 21 | .globl _starti | ||
| 22 | _starti: | ||
| 23 | lis 4,msgi@h | ||
| 24 | msgi: | ||
| 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 | |||
| 20 | .section .R_PPC_ADDR16_LO,"ax",@progbits | 34 | .section .R_PPC_ADDR16_LO,"ax",@progbits |
| 21 | addi 4, 4, msg@l | 35 | addi 4, 4, msg@l |
| 22 | mystr: | 36 | mystr: |
| ... | @@ -25,9 +39,9 @@ mystr: | ... | @@ -25,9 +39,9 @@ mystr: |
| 25 | 39 | ||
| 26 | # CHECK: Disassembly of section .R_PPC_ADDR16_LO: | 40 | # CHECK: Disassembly of section .R_PPC_ADDR16_LO: |
| 27 | # CHECK: .R_PPC_ADDR16_LO: | 41 | # CHECK: .R_PPC_ADDR16_LO: |
| 28 | # CHECK: 11008: 38 84 10 04 addi 4, 4, 4100 | 42 | # CHECK: 11010: 38 84 10 04 addi 4, 4, 4100 |
| 29 | # CHECK: mystr: | 43 | # CHECK: mystr: |
| 30 | # CHECK: 1100c: 62 6c 61 68 ori 12, 19, 24936 | 44 | # CHECK: 11014: 62 6c 61 68 ori 12, 19, 24936 |
| 31 | 45 | ||
| 32 | .align 2 | 46 | .align 2 |
| 33 | .section .R_PPC_REL24,"ax",@progbits | 47 | .section .R_PPC_REL24,"ax",@progbits |
| ... | @@ -39,7 +53,7 @@ mystr: | ... | @@ -39,7 +53,7 @@ mystr: |
| 39 | 53 | ||
| 40 | # CHECK: Disassembly of section .R_PPC_REL24: | 54 | # CHECK: Disassembly of section .R_PPC_REL24: |
| 41 | # CHECK: .FR_PPC_REL24: | 55 | # CHECK: .FR_PPC_REL24: |
| 42 | # CHECK: 11014: 48 00 00 04 b .+4 | 56 | # CHECK: 1101c: 48 00 00 04 b .+4 |
| 43 | 57 | ||
| 44 | .section .R_PPC_REL32,"ax",@progbits | 58 | .section .R_PPC_REL32,"ax",@progbits |
| 45 | .globl .FR_PPC_REL32 | 59 | .globl .FR_PPC_REL32 |
| ... | @@ -50,7 +64,7 @@ mystr: | ... | @@ -50,7 +64,7 @@ mystr: |
| 50 | 64 | ||
| 51 | # CHECK: Disassembly of section .R_PPC_REL32: | 65 | # CHECK: Disassembly of section .R_PPC_REL32: |
| 52 | # CHECK: .FR_PPC_REL32: | 66 | # CHECK: .FR_PPC_REL32: |
| 53 | # CHECK: 11018: 00 00 00 04 | 67 | # CHECK: 11020: 00 00 00 04 |
| 54 | 68 | ||
| 55 | .section .R_PPC_ADDR32,"ax",@progbits | 69 | .section .R_PPC_ADDR32,"ax",@progbits |
| 56 | .globl .FR_PPC_ADDR32 | 70 | .globl .FR_PPC_ADDR32 |
| ... | @@ -61,4 +75,16 @@ mystr: | ... | @@ -61,4 +75,16 @@ mystr: |
| 61 | 75 | ||
| 62 | # CHECK: Disassembly of section .R_PPC_ADDR32: | 76 | # CHECK: Disassembly of section .R_PPC_ADDR32: |
| 63 | # CHECK: .FR_PPC_ADDR32: | 77 | # CHECK: .FR_PPC_ADDR32: |
| 64 | # CHECK: 1101c: 00 01 10 20 | 78 | # CHECK: 11024: 00 01 10 28 |
| 79 | |||
| 80 | .align 2 | ||
| 81 | .section .R_PPC_PLTREL24,"ax",@progbits | ||
| 82 | .globl .R_PPC_PLTREL24 | ||
| 83 | .FR_PPC_PLTREL24: | ||
| 84 | b .Lfoox4@PLT | ||
| 85 | .section .R_PPC_PLTREL24_2,"ax",@progbits | ||
| 86 | .Lfoox4: | ||
| 87 | |||
| 88 | # CHECK: Disassembly of section .R_PPC_PLTREL24: | ||
| 89 | # CHECK: .R_PPC_PLTREL24: | ||
| 90 | # CHECK: 11028: 48 00 00 04 b .+4 |
deps/lld/test/ELF/ppc64-addr16-error.s+1-1| ... | @@ -5,4 +5,4 @@ | ... | @@ -5,4 +5,4 @@ |
| 5 | 5 | ||
| 6 | .short sym+65539 | 6 | .short sym+65539 |
| 7 | 7 | ||
| 8 | // CHECK: relocation R_PPC64_ADDR16 out of range | 8 | // CHECK: relocation R_PPC64_ADDR16 out of range: 65539 is not in [-32768, 32767] |
deps/lld/test/ELF/pr34660.s created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | # REQUIRES: aarch64 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o | ||
| 4 | # RUN: ld.lld --hash-style=sysv -shared %t.o -o %t | ||
| 5 | # RUN: llvm-objdump %t -d | FileCheck %s --check-prefix=DISASM | ||
| 6 | # RUN: llvm-readobj -elf-output-style=GNU %t -t | FileCheck %s --check-prefix=SYM | ||
| 7 | |||
| 8 | # It would be much easier to understand/read this test if llvm-objdump would print | ||
| 9 | # the immediates in hex. | ||
| 10 | # IMM = hex(65540) = 0x10004 | ||
| 11 | # PC = 0x10000 | ||
| 12 | # As the relocation is PC-relative, IMM + PC = 0x20004 which is the VA of the | ||
| 13 | # correct symbol. | ||
| 14 | |||
| 15 | # DISASM: Disassembly of section .text: | ||
| 16 | # DISASM-NEXT: $x.0: | ||
| 17 | # DISASM-NEXT: 10000: 28 00 08 58 ldr x8, #65540 | ||
| 18 | |||
| 19 | # SYM: Symbol table '.symtab' | ||
| 20 | # SYM: 0000000000020004 0 NOTYPE LOCAL DEFAULT 5 patatino | ||
| 21 | |||
| 22 | ldr x8, patatino | ||
| 23 | .data | ||
| 24 | .zero 4 | ||
| 25 | patatino: | ||
deps/lld/test/ELF/pr34872.s created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | # RUN: llvm-mc %s -filetype=obj -triple=x86_64-pc-linux -o %t.o | ||
| 2 | # RUN: llvm-mc %p/Inputs/undefined-error.s -filetype=obj \ | ||
| 3 | # RUN: -triple=x86_64-pc-linux -o %t2.o | ||
| 4 | # RUN: ld.lld -shared %t2.o -o %t2.so | ||
| 5 | # RUN: not ld.lld %t2.so %t.o 2>&1 | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: undefined symbol: fmod | ||
| 8 | # Check we're not emitting other diagnostics for this symbol. | ||
| 9 | # CHECK-NOT: fmod | ||
| 10 | |||
| 11 | .global main | ||
| 12 | |||
| 13 | main: | ||
| 14 | callq fmod | ||
deps/lld/test/ELF/progname.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: echo .global __progname > %t2.s | 3 | // RUN: echo ".global __progname; .data; .dc.a __progname" > %t2.s |
| 4 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o | 4 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o |
| 5 | // RUN: ld.lld -shared %t2.o -o %t2.so | 5 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 6 | // RUN: ld.lld -o %t %t.o %t2.so | 6 | // RUN: ld.lld -o %t %t.o %t2.so |
deps/lld/test/ELF/relocatable-comdat2.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: ld.lld -r %t.o -o %t | ||
| 4 | # RUN: llvm-readobj -elf-section-groups -s %t | FileCheck %s | ||
| 5 | |||
| 6 | ## Check .foo was not merged. | ||
| 7 | # CHECK: Sections [ | ||
| 8 | # CHECK: Name: .foo | ||
| 9 | # CHECK: Name: .foo | ||
| 10 | # CHECK: Name: .foo | ||
| 11 | |||
| 12 | # CHECK: Groups { | ||
| 13 | # CHECK-NEXT: Group { | ||
| 14 | # CHECK-NEXT: Name: .group | ||
| 15 | # CHECK-NEXT: Index: 2 | ||
| 16 | # CHECK-NEXT: Type: COMDAT | ||
| 17 | # CHECK-NEXT: Signature: bar | ||
| 18 | # CHECK-NEXT: Section(s) in group [ | ||
| 19 | # CHECK-NEXT: .foo (3) | ||
| 20 | # CHECK-NEXT: ] | ||
| 21 | # CHECK-NEXT: } | ||
| 22 | # CHECK-NEXT: Group { | ||
| 23 | # CHECK-NEXT: Name: .group | ||
| 24 | # CHECK-NEXT: Index: 4 | ||
| 25 | # CHECK-NEXT: Type: COMDAT | ||
| 26 | # CHECK-NEXT: Signature: zed | ||
| 27 | # CHECK-NEXT: Section(s) in group [ | ||
| 28 | # CHECK-NEXT: .foo (5) | ||
| 29 | # CHECK-NEXT: ] | ||
| 30 | # CHECK-NEXT: } | ||
| 31 | # CHECK-NEXT: } | ||
| 32 | |||
| 33 | .section .foo,"axG",@progbits,bar,comdat | ||
| 34 | .section .foo,"axG",@progbits,zed,comdat | ||
| 35 | .section .foo,"ax",@progbits | ||
deps/lld/test/ELF/relocatable-common.s+4-1| ... | @@ -30,7 +30,10 @@ | ... | @@ -30,7 +30,10 @@ |
| 30 | # DEFCOMM-NEXT: Binding: Global | 30 | # DEFCOMM-NEXT: Binding: Global |
| 31 | # DEFCOMM-NEXT: Type: Object | 31 | # DEFCOMM-NEXT: Type: Object |
| 32 | # DEFCOMM-NEXT: Other: 0 | 32 | # DEFCOMM-NEXT: Other: 0 |
| 33 | # DEFCOMM-NEXT: Section: COMMON (0x2) | 33 | # DEFCOMM-NEXT: Section: COMMON |
| 34 | # DEFCOMM-NEXT: } | 34 | # DEFCOMM-NEXT: } |
| 35 | 35 | ||
| 36 | # RUN: not ld.lld -shared --no-define-common %t1.o -o %t 2>&1 | FileCheck --check-prefix=ERROR %s | ||
| 37 | # ERROR: error: -no-define-common not supported in non relocatable output | ||
| 38 | |||
| 36 | .comm common,4,4 | 39 | .comm common,4,4 |
deps/lld/test/ELF/relocatable-compressed-input.s+5-5| ... | @@ -24,11 +24,11 @@ | ... | @@ -24,11 +24,11 @@ |
| 24 | # CHECK-NEXT: AddressAlignment: 1 | 24 | # CHECK-NEXT: AddressAlignment: 1 |
| 25 | # CHECK-NEXT: EntrySize: 1 | 25 | # CHECK-NEXT: EntrySize: 1 |
| 26 | # CHECK-NEXT: SectionData ( | 26 | # CHECK-NEXT: SectionData ( |
| 27 | # CHECK-NEXT: 0000: {{.*}} |short unsigned i| | 27 | # CHECK-NEXT: 0000: {{.*}} |long unsigned in| |
| 28 | # CHECK-NEXT: 0010: {{.*}} |nt.unsigned int.| | 28 | # CHECK-NEXT: 0010: {{.*}} |t.unsigned char.| |
| 29 | # CHECK-NEXT: 0020: {{.*}} |long unsigned in| | 29 | # CHECK-NEXT: 0020: {{.*}} |unsigned int.cha| |
| 30 | # CHECK-NEXT: 0030: {{.*}} |t.char.unsigned | | 30 | # CHECK-NEXT: 0030: {{.*}} |r.short unsigned| |
| 31 | # CHECK-NEXT: 0040: {{.*}} |char.| | 31 | # CHECK-NEXT: 0040: {{.*}} | int.| |
| 32 | # CHECK-NEXT: ) | 32 | # CHECK-NEXT: ) |
| 33 | # CHECK-NEXT: } | 33 | # CHECK-NEXT: } |
| 34 | 34 |
deps/lld/test/ELF/relocatable.s+1-1| ... | @@ -81,7 +81,7 @@ | ... | @@ -81,7 +81,7 @@ |
| 81 | # CHECKEXE-NEXT: Version: 1 | 81 | # CHECKEXE-NEXT: Version: 1 |
| 82 | # CHECKEXE-NEXT: Entry: 0x201000 | 82 | # CHECKEXE-NEXT: Entry: 0x201000 |
| 83 | # CHECKEXE-NEXT: ProgramHeaderOffset: 0x40 | 83 | # CHECKEXE-NEXT: ProgramHeaderOffset: 0x40 |
| 84 | # CHECKEXE-NEXT: SectionHeaderOffset: 0x11F8 | 84 | # CHECKEXE-NEXT: SectionHeaderOffset: 0x21A0 |
| 85 | # CHECKEXE-NEXT: Flags [ | 85 | # CHECKEXE-NEXT: Flags [ |
| 86 | # CHECKEXE-NEXT: ] | 86 | # CHECKEXE-NEXT: ] |
| 87 | # CHECKEXE-NEXT: HeaderSize: 64 | 87 | # CHECKEXE-NEXT: HeaderSize: 64 |
deps/lld/test/ELF/relocation-b-aarch64.test created+48| ... | @@ -0,0 +1,48 @@ | ||
| 1 | # REQUIRES: aarch64 | ||
| 2 | |||
| 3 | # RUN: yaml2obj %s -o %t.o | ||
| 4 | # RUN: ld.lld %t.o -o %t.out | ||
| 5 | # RUN: llvm-objdump -d -triple=aarch64-none-linux %t.out | FileCheck %s | ||
| 6 | |||
| 7 | # Check that the R_AARCH64_JUMP26 writes the branch opcode as well as the | ||
| 8 | # immediate. We use this property to overwrite instructions with a branch. | ||
| 9 | |||
| 10 | # CHECK: Disassembly of section .text: | ||
| 11 | # CHECK-NEXT: foo: | ||
| 12 | # CHECK-NEXT: 20000: 01 00 00 14 b #4 | ||
| 13 | # CHECK: bar: | ||
| 14 | # CHECK-NEXT: 20004: ff ff ff 17 b #-4 | ||
| 15 | |||
| 16 | !ELF | ||
| 17 | FileHeader: | ||
| 18 | Class: ELFCLASS64 | ||
| 19 | Data: ELFDATA2LSB | ||
| 20 | Type: ET_REL | ||
| 21 | Machine: EM_AARCH64 | ||
| 22 | Sections: | ||
| 23 | - Type: SHT_PROGBITS | ||
| 24 | Name: .text | ||
| 25 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | ||
| 26 | Content: "0000000000000000" | ||
| 27 | - Type: SHT_RELA | ||
| 28 | Name: .rela.text | ||
| 29 | Link: .symtab | ||
| 30 | Info: .text | ||
| 31 | Relocations: | ||
| 32 | - Offset: 0 | ||
| 33 | Symbol: bar | ||
| 34 | Type: R_AARCH64_JUMP26 | ||
| 35 | - Offset: 4 | ||
| 36 | Symbol: foo | ||
| 37 | Type: R_AARCH64_JUMP26 | ||
| 38 | |||
| 39 | Symbols: | ||
| 40 | Local: | ||
| 41 | - Type: STT_FUNC | ||
| 42 | Section: .text | ||
| 43 | Name: foo | ||
| 44 | Value: 0 | ||
| 45 | - Type: STT_FUNC | ||
| 46 | Section: .text | ||
| 47 | Name: bar | ||
| 48 | Value: 4 | ||
deps/lld/test/ELF/relocation-copy-alias.s+5-3| ... | @@ -1,8 +1,10 @@ | ... | @@ -1,8 +1,10 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 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/relocation-copy-alias.s -o %t2.o | 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy-alias.s -o %t2.o |
| 4 | // RUN: ld.lld -shared %t2.o -o %t.so | 4 | // RUN: ld.lld --hash-style=sysv -shared %t2.o -o %t.so |
| 5 | // RUN: ld.lld %t.o %t.so -o %t3 | 5 | // RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t3 |
| 6 | // RUN: llvm-readobj --dyn-symbols -r --expand-relocs %t3 | FileCheck %s | ||
| 7 | // RUN: ld.lld --hash-style=sysv --gc-sections %t.o %t.so -o %t3 | ||
| 6 | // RUN: llvm-readobj --dyn-symbols -r --expand-relocs %t3 | FileCheck %s | 8 | // RUN: llvm-readobj --dyn-symbols -r --expand-relocs %t3 | FileCheck %s |
| 7 | 9 | ||
| 8 | .global _start | 10 | .global _start |
| ... | @@ -61,7 +63,7 @@ movl $5, b2 | ... | @@ -61,7 +63,7 @@ movl $5, b2 |
| 61 | // CHECK: Name: b3 | 63 | // CHECK: Name: b3 |
| 62 | // CHECK-NEXT: Value: [[B]] | 64 | // CHECK-NEXT: Value: [[B]] |
| 63 | // CHECK-NEXT: Size: 1 | 65 | // CHECK-NEXT: Size: 1 |
| 64 | // CHECK-NEXT: Binding: Weak | 66 | // CHECK-NEXT: Binding: Global |
| 65 | // CHECK-NEXT: Type: Object (0x1) | 67 | // CHECK-NEXT: Type: Object (0x1) |
| 66 | // CHECK-NEXT: Other: 0 | 68 | // CHECK-NEXT: Other: 0 |
| 67 | // CHECK-NEXT: Section: .bss | 69 | // CHECK-NEXT: Section: .bss |
deps/lld/test/ELF/relocation-copy-align-common.s+1-1| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \ | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \ |
| 4 | # RUN: %p/Inputs/relocation-copy-align-common.s -o %t2.o | 4 | # RUN: %p/Inputs/relocation-copy-align-common.s -o %t2.o |
| 5 | # RUN: ld.lld -shared %t2.o -o %t.so | 5 | # RUN: ld.lld -shared %t2.o -o %t.so |
| 6 | # RUN: ld.lld %t.o %t.so -o %t3 | 6 | # RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t3 |
| 7 | # RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s | 7 | # RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s |
| 8 | 8 | ||
| 9 | # CHECK: Section { | 9 | # CHECK: Section { |
deps/lld/test/ELF/relocation-copy-flags.s+1-1| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 | // 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 -o %t.o |
| 4 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o | 4 | // 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 -shared | 5 | // RUN: ld.lld %t2.o -o %t2.so -shared |
| 6 | // RUN: ld.lld %t.o %t2.so -o %t.exe | 6 | // RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t.exe |
| 7 | // RUN: llvm-readobj -s -section-data -r %t.exe | FileCheck %s | 7 | // RUN: llvm-readobj -s -section-data -r %t.exe | FileCheck %s |
| 8 | 8 | ||
| 9 | .global _start | 9 | .global _start |
deps/lld/test/ELF/relocation-copy-relro.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.o | 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/relocation-copy-relro.s -o %t2.o | 3 | // 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.so | 4 | // RUN: ld.lld -shared %t2.o -o %t.so |
| 5 | // RUN: ld.lld %t.o %t.so -o %t3 | 5 | // RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t3 |
| 6 | // RUN: llvm-readobj -program-headers -s -r %t3 | FileCheck %s | 6 | // RUN: llvm-readobj -program-headers -s -r %t3 | FileCheck %s |
| 7 | 7 | ||
| 8 | // CHECK: Name: .bss.rel.ro (48) | 8 | // CHECK: Name: .bss.rel.ro (48) |
deps/lld/test/ELF/relocation-i686.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o |
| 3 | // RUN: ld.lld -shared %t2.o -o %t2.so | 3 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 4 | // RUN: ld.lld %t %t2.so -o %t2 | 4 | // RUN: ld.lld --hash-style=sysv %t %t2.so -o %t2 |
| 5 | // RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=ADDR %s | 5 | // RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=ADDR %s |
| 6 | // RUN: llvm-objdump -d %t2 | FileCheck %s | 6 | // RUN: llvm-objdump -d %t2 | FileCheck %s |
| 7 | // REQUIRES: x86 | 7 | // REQUIRES: x86 |
deps/lld/test/ELF/relocation-relative-weak.s+1| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | # RUN: llvm-readobj -dyn-relocations %t | FileCheck %s | 4 | # RUN: llvm-readobj -dyn-relocations %t | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: Dynamic Relocations { | 6 | # CHECK: Dynamic Relocations { |
| 7 | # CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT w 0x0 | ||
| 7 | # CHECK-NEXT: } | 8 | # CHECK-NEXT: } |
| 8 | 9 | ||
| 9 | .globl _start | 10 | .globl _start |
deps/lld/test/ELF/relocation-size-err.s created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s | ||
| 4 | |||
| 5 | // CHECK: error: can't create dynamic relocation R_X86_64_SIZE64 against symbol: foo in readonly segment; recompile object files with -fPIC | ||
| 6 | |||
| 7 | .global foo | ||
| 8 | foo: | ||
| 9 | .quad 42 | ||
| 10 | .size foo, 8 | ||
| 11 | |||
| 12 | .quad foo@SIZE | ||
deps/lld/test/ELF/relocation.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2 | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2 |
| 3 | // RUN: ld.lld %t2 -o %t2.so -shared | 3 | // RUN: ld.lld %t2 -o %t2.so -shared |
| 4 | // RUN: ld.lld %t %t2.so -o %t3 | 4 | // RUN: ld.lld --hash-style=sysv %t %t2.so -o %t3 |
| 5 | // RUN: llvm-readobj -s %t3 | FileCheck --check-prefix=SEC %s | 5 | // RUN: llvm-readobj -s %t3 | FileCheck --check-prefix=SEC %s |
| 6 | // RUN: llvm-objdump -s -d %t3 | FileCheck %s | 6 | // RUN: llvm-objdump -s -d %t3 | FileCheck %s |
| 7 | // REQUIRES: x86 | 7 | // REQUIRES: x86 |
deps/lld/test/ELF/relro-copyrel-bss-script.s created+40| ... | @@ -0,0 +1,40 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t.o | ||
| 3 | // 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.so | ||
| 5 | |||
| 6 | // A linker script that will map .bss.rel.ro into .bss. | ||
| 7 | // RUN: echo "SECTIONS { \ | ||
| 8 | // RUN: .bss : { *(.bss) *(.bss.*) } \ | ||
| 9 | // RUN: } " > %t.script | ||
| 10 | |||
| 11 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3.o | ||
| 12 | // RUN: ld.lld %t3.o %t.so -z relro -o %t --script=%t.script 2>&1 | ||
| 13 | // RUN: llvm-readobj --program-headers %t | FileCheck %s | ||
| 14 | .section .text, "ax", @progbits | ||
| 15 | .global bar | ||
| 16 | .global foo | ||
| 17 | .global _start | ||
| 18 | _start: | ||
| 19 | callq bar | ||
| 20 | // Will produce .bss.rel.ro that will match in .bss, this will lose | ||
| 21 | // the relro property of the copy relocation. | ||
| 22 | .quad foo | ||
| 23 | |||
| 24 | // Non relro bss | ||
| 25 | .bss | ||
| 26 | // make large enough to affect PT_GNU_RELRO MemSize if this was marked | ||
| 27 | // as relro. | ||
| 28 | .space 0x2000 | ||
| 29 | |||
| 30 | // CHECK: Type: PT_GNU_RELRO (0x6474E552) | ||
| 31 | // CHECK-NEXT: Offset: | ||
| 32 | // CHECK-NEXT: VirtualAddress: | ||
| 33 | // CHECK-NEXT: PhysicalAddress: | ||
| 34 | // CHECK-NEXT: FileSize: | ||
| 35 | // CHECK-NEXT: MemSize: 4096 | ||
| 36 | // CHECK-NEXT: Flags [ (0x4) | ||
| 37 | // CHECK-NEXT: PF_R (0x4) | ||
| 38 | // CHECK-NEXT: ] | ||
| 39 | // CHECK-NEXT: Alignment: 1 | ||
| 40 | // CHECK-NEXT: } | ||
deps/lld/test/ELF/relro-non-contiguous-script-data.s created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | |||
| 3 | // RUN: echo "SECTIONS { \ | ||
| 4 | // RUN: .dynamic : { *(.dynamic) } \ | ||
| 5 | // RUN: .non_ro : { . += 1; } \ | ||
| 6 | // RUN: .jcr : { *(.jcr) } \ | ||
| 7 | // RUN: } " > %t.script | ||
| 8 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 9 | // RUN: not ld.lld --export-dynamic %t.o -o %t --script=%t.script 2>&1 | FileCheck %s | ||
| 10 | |||
| 11 | // RUN: echo "SECTIONS { \ | ||
| 12 | // RUN: .dynamic : { *(.dynamic) } \ | ||
| 13 | // RUN: .non_ro : { BYTE(1); } \ | ||
| 14 | // RUN: .jcr : { *(.jcr) } \ | ||
| 15 | // RUN: } " > %t2.script | ||
| 16 | // RUN: not ld.lld --export-dynamic %t.o -o %t --script=%t2.script 2>&1 | FileCheck %s | ||
| 17 | |||
| 18 | // CHECK: error: section: .jcr is not contiguous with other relro sections | ||
| 19 | |||
| 20 | .global _start | ||
| 21 | _start: | ||
| 22 | |||
| 23 | // non-empty relro section | ||
| 24 | .section .jcr, "aw", @progbits | ||
| 25 | .quad 0 | ||
deps/lld/test/ELF/relro-non-contiguous.s created+28| ... | @@ -0,0 +1,28 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t.o | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/copy-in-shared.s -o %t2.o | ||
| 3 | // RUN: ld.lld -shared %t.o %t2.o -o %t.so | ||
| 4 | |||
| 5 | // Place the .got.plt (non relro) immediately after .dynamic. This is the | ||
| 6 | // reverse order of the non-linker script case. The linker created .bss.rel.ro | ||
| 7 | // section will be placed after .got.plt causing the relro to be non-contiguous. | ||
| 8 | // RUN: echo "SECTIONS { \ | ||
| 9 | // RUN: .dynamic : { *(.dynamic) } \ | ||
| 10 | // RUN: .got.plt : { *(.got.plt) } \ | ||
| 11 | // RUN: } " > %t.script | ||
| 12 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3.o | ||
| 13 | |||
| 14 | // Expect error for non-contiguous relro | ||
| 15 | // RUN: not ld.lld %t3.o %t.so -z relro -o %t --script=%t.script 2>&1 | FileCheck %s | ||
| 16 | // No error when we do not request relro. | ||
| 17 | // RUN: ld.lld %t3.o %t.so -z norelro -o %t --script=%t.script | ||
| 18 | // REQUIRES: x86 | ||
| 19 | |||
| 20 | // CHECK: error: section: .bss.rel.ro is not contiguous with other relro sections | ||
| 21 | .section .text, "ax", @progbits | ||
| 22 | .global _start | ||
| 23 | .global bar | ||
| 24 | .global foo | ||
| 25 | _start: | ||
| 26 | .quad bar | ||
| 27 | .quad foo | ||
| 28 | |||
deps/lld/test/ELF/relro-omagic.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 1 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o |
| 3 | # RUN: ld.lld -shared %t2.o -o %t2.so -soname relro-omagic.s.tmp2.so | 3 | # RUN: ld.lld -shared %t2.o -o %t2.so -soname relro-omagic.s.tmp2.so |
| 4 | # RUN: ld.lld -N %t.o %t2.so -o %t | 4 | # RUN: ld.lld --hash-style=sysv -N %t.o %t2.so -o %t |
| 5 | # RUN: llvm-objdump -section-headers %t | FileCheck --check-prefix=NORELRO %s | 5 | # RUN: llvm-objdump -section-headers %t | FileCheck --check-prefix=NORELRO %s |
| 6 | # RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=NOPHDRS %s | 6 | # RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=NOPHDRS %s |
| 7 | 7 |
deps/lld/test/ELF/relro-script.s created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t.o | ||
| 3 | // 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.so | ||
| 5 | |||
| 6 | // ld.bfd and gold use .data.rel.ro rather than .bss.rel.ro. When a linker | ||
| 7 | // script, such as ld.bfd's internal linker script has a .data.rel.ro | ||
| 8 | // OutputSection we rename .bss.rel.ro to .data.rel.ro.bss in order to match in | ||
| 9 | // .data.rel.ro. This keeps the relro sections contiguous. | ||
| 10 | |||
| 11 | // Use the same sections and ordering as the ld.bfd internal linker script. | ||
| 12 | // RUN: echo "SECTIONS { \ | ||
| 13 | // RUN: .data.rel.ro : { *(.data.rel.ro .data.rel.ro.*) } \ | ||
| 14 | // RUN: .dynamic : { *(.dynamic) } \ | ||
| 15 | // RUN: .got : { *(.got) } \ | ||
| 16 | // RUN: .got.plt : { *(.got.plt) } \ | ||
| 17 | // RUN: } " > %t.script | ||
| 18 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3.o | ||
| 19 | // RUN: ld.lld %t3.o %t.so -o %t --script=%t.script --print-map | FileCheck %s | ||
| 20 | |||
| 21 | // CHECK: .data.rel.ro | ||
| 22 | // CHECK-NEXT: <internal>:(.bss.rel.ro) | ||
| 23 | .section .text, "ax", @progbits | ||
| 24 | .global _start | ||
| 25 | .global bar | ||
| 26 | .global foo | ||
| 27 | _start: | ||
| 28 | .quad bar | ||
| 29 | .quad foo | ||
deps/lld/test/ELF/reproduce-thin-archive.s+6| ... | @@ -5,11 +5,17 @@ | ... | @@ -5,11 +5,17 @@ |
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.dir/foo.o | 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.dir/foo.o |
| 6 | # RUN: cd %t.dir | 6 | # RUN: cd %t.dir |
| 7 | # RUN: llvm-ar --format=gnu rcT foo.a foo.o | 7 | # RUN: llvm-ar --format=gnu rcT foo.a foo.o |
| 8 | |||
| 8 | # RUN: ld.lld -m elf_x86_64 foo.a -o bar --reproduce repro.tar | 9 | # RUN: ld.lld -m elf_x86_64 foo.a -o bar --reproduce repro.tar |
| 9 | # RUN: tar xf repro.tar | 10 | # RUN: tar xf repro.tar |
| 10 | # RUN: diff foo.a repro/%:t.dir/foo.a | 11 | # RUN: diff foo.a repro/%:t.dir/foo.a |
| 11 | # RUN: diff foo.o repro/%:t.dir/foo.o | 12 | # RUN: diff foo.o repro/%:t.dir/foo.o |
| 12 | 13 | ||
| 14 | # RUN: ld.lld -m elf_x86_64 --whole-archive foo.a -o bar --reproduce repro2.tar | ||
| 15 | # RUN: tar xf repro2.tar | ||
| 16 | # RUN: diff foo.a repro2/%:t.dir/foo.a | ||
| 17 | # RUN: diff foo.o repro2/%:t.dir/foo.o | ||
| 18 | |||
| 13 | .globl _start | 19 | .globl _start |
| 14 | _start: | 20 | _start: |
| 15 | nop | 21 | nop |
deps/lld/test/ELF/reproduce.s+20-11| ... | @@ -33,27 +33,36 @@ | ... | @@ -33,27 +33,36 @@ |
| 33 | # RUN: echo "{};" > dyn | 33 | # RUN: echo "{};" > dyn |
| 34 | # RUN: echo > file | 34 | # RUN: echo > file |
| 35 | # RUN: echo > file2 | 35 | # RUN: echo > file2 |
| 36 | # RUN: echo "_start" > order | ||
| 37 | # RUN: mkdir "sysroot with spaces" | ||
| 36 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o 'foo bar' | 38 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o 'foo bar' |
| 37 | # RUN: ld.lld --reproduce repro2.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 \ | 39 | # RUN: ld.lld --reproduce repro2.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 \ |
| 38 | # RUN: --dynamic-list dyn -rpath file --script=file --version-script ver \ | 40 | # RUN: --dynamic-list dyn -rpath file --script=file --symbol-ordering-file order \ |
| 39 | # RUN: --dynamic-linker "some unusual/path" -soname 'foo bar' -soname='foo bar' | 41 | # RUN: --sysroot "sysroot with spaces" --sysroot="sysroot with spaces" \ |
| 42 | # RUN: --version-script ver --dynamic-linker "some unusual/path" -soname 'foo bar' \ | ||
| 43 | # RUN: -soname='foo bar' | ||
| 40 | # RUN: tar xf repro2.tar | 44 | # RUN: tar xf repro2.tar |
| 41 | # RUN: FileCheck %s --check-prefix=RSP2 < repro2/response.txt | 45 | # RUN: FileCheck %s --check-prefix=RSP2 < repro2/response.txt |
| 46 | # RSP2: --chroot . | ||
| 42 | # RSP2: "{{.*}}foo bar" | 47 | # RSP2: "{{.*}}foo bar" |
| 43 | # RSP2-NEXT: -L "{{.*}}foo bar" | 48 | # RSP2-NEXT: --library-path "[[BASEDIR:.+]]/foo bar" |
| 44 | # RSP2-NEXT: -L {{.+}}file | 49 | # RSP2-NEXT: --library-path [[BASEDIR]]/file |
| 45 | # RSP2-NEXT: --script {{.+}}file2 | 50 | # RSP2-NEXT: --script [[BASEDIR]]/file2 |
| 46 | # RSP2-NEXT: --dynamic-list {{.+}}dyn | 51 | # RSP2-NEXT: --dynamic-list [[BASEDIR]]/dyn |
| 47 | # RSP2-NEXT: -rpath {{.+}}file | 52 | # RSP2-NEXT: -rpath [[BASEDIR]]/file |
| 48 | # RSP2-NEXT: --script {{.+}}file | 53 | # RSP2-NEXT: --script [[BASEDIR]]/file |
| 49 | # RSP2-NEXT: --version-script [[PATH:.*]]ver | 54 | # RSP2-NEXT: --symbol-ordering-file [[BASEDIR]]/order |
| 55 | # RSP2-NEXT: --sysroot "[[BASEDIR]]/sysroot with spaces" | ||
| 56 | # RSP2-NEXT: --sysroot "[[BASEDIR]]/sysroot with spaces" | ||
| 57 | # RSP2-NEXT: --version-script [[BASEDIR]]/ver | ||
| 50 | # RSP2-NEXT: --dynamic-linker "some unusual/path" | 58 | # RSP2-NEXT: --dynamic-linker "some unusual/path" |
| 51 | # RSP2-NEXT: -soname="foo bar" | 59 | # RSP2-NEXT: -soname "foo bar" |
| 52 | # RSP2-NEXT: -soname="foo bar" | 60 | # RSP2-NEXT: -soname "foo bar" |
| 53 | 61 | ||
| 54 | # RUN: tar tf repro2.tar | FileCheck %s | 62 | # RUN: tar tf repro2.tar | FileCheck %s |
| 55 | # CHECK: repro2/response.txt | 63 | # CHECK: repro2/response.txt |
| 56 | # CHECK-NEXT: repro2/version.txt | 64 | # CHECK-NEXT: repro2/version.txt |
| 65 | # CHECK-NEXT: repro2/{{.*}}/order | ||
| 57 | # CHECK-NEXT: repro2/{{.*}}/dyn | 66 | # CHECK-NEXT: repro2/{{.*}}/dyn |
| 58 | # CHECK-NEXT: repro2/{{.*}}/ver | 67 | # CHECK-NEXT: repro2/{{.*}}/ver |
| 59 | # CHECK-NEXT: repro2/{{.*}}/foo bar | 68 | # CHECK-NEXT: repro2/{{.*}}/foo bar |
deps/lld/test/ELF/resolution-end.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | 1 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution-end.s -o %t2.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution-end.s -o %t2.o |
| 3 | # RUN: ld.lld -shared -o %t2.so %t2.o | 3 | # RUN: ld.lld -shared -o %t2.so %t2.o |
| 4 | # RUN: ld.lld %t1.o %t2.so -o %t | 4 | # RUN: ld.lld --hash-style=sysv %t1.o %t2.so -o %t |
| 5 | # RUN: llvm-readobj -t -s -section-data %t | FileCheck %s | 5 | # RUN: llvm-readobj -t -s -section-data %t | FileCheck %s |
| 6 | # REQUIRES: x86 | 6 | # REQUIRES: x86 |
| 7 | 7 |
deps/lld/test/ELF/retain-symbols-file.s+2-2| ... | @@ -2,11 +2,11 @@ | ... | @@ -2,11 +2,11 @@ |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t |
| 3 | # RUN: echo "bar" > %t_retain.txt | 3 | # RUN: echo "bar" > %t_retain.txt |
| 4 | # RUN: echo "foo" >> %t_retain.txt | 4 | # RUN: echo "foo" >> %t_retain.txt |
| 5 | # RUN: ld.lld -shared --retain-symbols-file=%t_retain.txt %t -o %t2 | 5 | # RUN: ld.lld --hash-style=sysv -shared --retain-symbols-file=%t_retain.txt %t -o %t2 |
| 6 | # RUN: llvm-readobj --dyn-symbols %t2 | FileCheck %s | 6 | # RUN: llvm-readobj --dyn-symbols %t2 | FileCheck %s |
| 7 | 7 | ||
| 8 | ## Check separate form. | 8 | ## Check separate form. |
| 9 | # RUN: ld.lld -shared --retain-symbols-file %t_retain.txt %t -o %t2 | 9 | # RUN: ld.lld --hash-style=sysv -shared --retain-symbols-file %t_retain.txt %t -o %t2 |
| 10 | # RUN: llvm-readobj --dyn-symbols %t2 | FileCheck %s | 10 | # RUN: llvm-readobj --dyn-symbols %t2 | FileCheck %s |
| 11 | 11 | ||
| 12 | # CHECK: DynamicSymbols [ | 12 | # CHECK: DynamicSymbols [ |
deps/lld/test/ELF/section-metadata-err.s+1-1| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 | # 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 -o %t.o |
| 4 | # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s | 4 | # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s |
| 5 | 5 | ||
| 6 | # CHECK: error: Merge and .eh_frame sections are not supported with SHF_LINK_ORDER {{.*}}section-metadata-err.s.tmp.o:(.foo) | 6 | # CHECK: error: a section with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err.s.tmp.o:(.foo) |
| 7 | 7 | ||
| 8 | .global _start | 8 | .global _start |
| 9 | _start: | 9 | _start: |
deps/lld/test/ELF/segments.s+5| ... | @@ -1,7 +1,10 @@ | ... | @@ -1,7 +1,10 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 3 | |||
| 3 | # RUN: ld.lld %t -o %t1 | 4 | # RUN: ld.lld %t -o %t1 |
| 4 | # RUN: llvm-readobj --program-headers %t1 | FileCheck --check-prefix=ROSEGMENT %s | 5 | # RUN: llvm-readobj --program-headers %t1 | FileCheck --check-prefix=ROSEGMENT %s |
| 6 | # RUN: ld.lld --omagic --no-omagic %t -o %t1 | ||
| 7 | # RUN: llvm-readobj --program-headers %t1 | FileCheck --check-prefix=ROSEGMENT %s | ||
| 5 | 8 | ||
| 6 | # ROSEGMENT: ProgramHeader { | 9 | # ROSEGMENT: ProgramHeader { |
| 7 | # ROSEGMENT: Type: PT_LOAD | 10 | # ROSEGMENT: Type: PT_LOAD |
| ... | @@ -76,6 +79,8 @@ | ... | @@ -76,6 +79,8 @@ |
| 76 | 79 | ||
| 77 | # RUN: ld.lld -N %t -o %t3 | 80 | # RUN: ld.lld -N %t -o %t3 |
| 78 | # RUN: llvm-readobj --program-headers %t3 | FileCheck --check-prefix=OMAGIC %s | 81 | # RUN: llvm-readobj --program-headers %t3 | FileCheck --check-prefix=OMAGIC %s |
| 82 | # RUN: ld.lld --omagic %t -o %t3 | ||
| 83 | # RUN: llvm-readobj --program-headers %t3 | FileCheck --check-prefix=OMAGIC %s | ||
| 79 | 84 | ||
| 80 | # OMAGIC: ProgramHeader { | 85 | # OMAGIC: ProgramHeader { |
| 81 | # OMAGIC: Type: PT_LOAD | 86 | # OMAGIC: Type: PT_LOAD |
deps/lld/test/ELF/shared-lazy.s created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | ||
| 2 | // RUN: rm -f %t1.a | ||
| 3 | // RUN: llvm-ar rc %t1.a %t1.o | ||
| 4 | // RUN: ld.lld %t1.o -o %t1.so -shared | ||
| 5 | // RUN: echo ".global foo" > %t2.s | ||
| 6 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o | ||
| 7 | // RUN: ld.lld %t1.a %t1.so %t2.o -o %t.so -shared | ||
| 8 | // RUN: llvm-readelf --dyn-symbols %t.so | FileCheck %s | ||
| 9 | |||
| 10 | // Test that 'foo' from %t1.so is used and we don't fetch a member | ||
| 11 | // from the archive. | ||
| 12 | |||
| 13 | // CHECK: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND foo | ||
| 14 | |||
| 15 | .global foo | ||
| 16 | foo: | ||
deps/lld/test/ELF/shared.s+3-3| ... | @@ -1,10 +1,10 @@ | ... | @@ -1,10 +1,10 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o |
| 3 | // RUN: ld.lld -shared %t2.o -o %t2.so | 3 | // RUN: ld.lld --hash-style=sysv -shared %t2.o -o %t2.so |
| 4 | // RUN: llvm-readobj -s %t2.so | FileCheck --check-prefix=SO %s | 4 | // RUN: llvm-readobj -s %t2.so | FileCheck --check-prefix=SO %s |
| 5 | // RUN: ld.lld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t | 5 | // 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 |
| 6 | // RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data -hash-table %t | FileCheck %s | 6 | // RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data -hash-table %t | FileCheck %s |
| 7 | // RUN: ld.lld %t.o %t2.so %t2.so -o %t2 | 7 | // RUN: ld.lld --hash-style=sysv %t.o %t2.so %t2.so -o %t2 |
| 8 | // RUN: llvm-readobj -dyn-symbols %t2 | FileCheck --check-prefix=DONT_EXPORT %s | 8 | // RUN: llvm-readobj -dyn-symbols %t2 | FileCheck --check-prefix=DONT_EXPORT %s |
| 9 | // REQUIRES: x86 | 9 | // REQUIRES: x86 |
| 10 | 10 |
deps/lld/test/ELF/shlib-undefined-shared.s created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -o %t1.o %S/Inputs/shlib-undefined-ref.s | ||
| 4 | # RUN: ld.lld -shared -o %t1.so %t1.o | ||
| 5 | |||
| 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -o %t2.o %s | ||
| 7 | # RUN: echo "{ local: *; };" > %t.script | ||
| 8 | # RUN: ld.lld -shared -version-script %t.script -o %t2.so %t2.o %t1.so | ||
| 9 | # RUN: llvm-nm -g %t2.so | FileCheck -allow-empty %s | ||
| 10 | |||
| 11 | # CHECK-NOT: should_not_be_exported | ||
| 12 | |||
| 13 | .globl should_not_be_exported | ||
| 14 | should_not_be_exported: | ||
| 15 | 	ret | ||
deps/lld/test/ELF/silent-ignore.test created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | RUN: ld.lld --version \ | ||
| 2 | RUN: -allow-shlib-undefined \ | ||
| 3 | RUN: -cref \ | ||
| 4 | RUN: -g \ | ||
| 5 | RUN: -no-add-needed \ | ||
| 6 | RUN: -no-allow-shlib-undefined \ | ||
| 7 | RUN: -no-copy-dt-needed-entries \ | ||
| 8 | RUN: -no-ctors-in-init-array \ | ||
| 9 | RUN: -no-keep-memory \ | ||
| 10 | RUN: -no-warn-common \ | ||
| 11 | RUN: -no-warn-mismatch \ | ||
| 12 | RUN: -sort-common \ | ||
| 13 | RUN: -stats \ | ||
| 14 | RUN: -warn-execstack \ | ||
| 15 | RUN: -warn-once \ | ||
| 16 | RUN: -warn-shared-textrel \ | ||
| 17 | RUN: -EB \ | ||
| 18 | RUN: -EL \ | ||
| 19 | RUN: -Qy | ||
| 20 | RUN: not ld.lld --version --not-an-ignored-argument | ||
deps/lld/test/ELF/sort-norosegment.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t |
| 3 | 3 | ||
| 4 | # RUN: ld.lld -no-rosegment -o %t1 %t -shared | 4 | # RUN: ld.lld --hash-style=sysv -no-rosegment -o %t1 %t -shared |
| 5 | # RUN: llvm-readobj -elf-output-style=GNU -s %t1 | FileCheck %s | 5 | # RUN: llvm-readobj -elf-output-style=GNU -s %t1 | FileCheck %s |
| 6 | 6 | ||
| 7 | # CHECK: .text {{.*}} AX | 7 | # CHECK: .text {{.*}} AX |
deps/lld/test/ELF/startstop-gccollect.s+9-3| ... | @@ -11,21 +11,27 @@ | ... | @@ -11,21 +11,27 @@ |
| 11 | # RUN: ld.lld %t --gc-sections -o %tout | 11 | # RUN: ld.lld %t --gc-sections -o %tout |
| 12 | # RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s | 12 | # RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s |
| 13 | 13 | ||
| 14 | # RUN: echo ".global __start_foo; __start_foo:" > %t2.s | ||
| 15 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o | ||
| 16 | # RUN: ld.lld -shared %t2.o -o %t2.so | ||
| 17 | # RUN: ld.lld %t --gc-sections -o %tout %t2.so | ||
| 18 | # RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s | ||
| 19 | |||
| 14 | # DISASM: _start: | 20 | # DISASM: _start: |
| 15 | # 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> |
| 16 | # DISASM-NEXT: 201005: e8 01 00 00 00 callq 1 <__start_bar> | 22 | # DISASM-NEXT: 201005: e8 02 00 00 00 callq 2 <__stop_bar> |
| 17 | # DISASM-NEXT: Disassembly of section foo: | 23 | # DISASM-NEXT: Disassembly of section foo: |
| 18 | # DISASM-NEXT: __start_foo: | 24 | # DISASM-NEXT: __start_foo: |
| 19 | # DISASM-NEXT: 20100a: 90 nop | 25 | # DISASM-NEXT: 20100a: 90 nop |
| 20 | # DISASM-NEXT: Disassembly of section bar: | 26 | # DISASM-NEXT: Disassembly of section bar: |
| 21 | # DISASM-NEXT: __start_bar: | 27 | # DISASM-NEXT: bar: |
| 22 | # DISASM-NEXT: 20100b: 90 nop | 28 | # DISASM-NEXT: 20100b: 90 nop |
| 23 | 29 | ||
| 24 | .global _start | 30 | .global _start |
| 25 | .text | 31 | .text |
| 26 | _start: | 32 | _start: |
| 27 | callq __start_foo | 33 | callq __start_foo |
| 28 | callq __start_bar | 34 | callq __stop_bar |
| 29 | 35 | ||
| 30 | .section foo,"ax" | 36 | .section foo,"ax" |
| 31 | nop | 37 | nop |
deps/lld/test/ELF/startstop.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 3 | // RUN: ld.lld %t -o %tout -shared | 3 | // RUN: ld.lld --hash-style=sysv %t -o %tout -shared |
| 4 | // RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s | 4 | // RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s |
| 5 | // RUN: llvm-readobj -symbols -r %tout | FileCheck -check-prefix=SYMBOL %s | 5 | // RUN: llvm-readobj -symbols -r %tout | FileCheck -check-prefix=SYMBOL %s |
| 6 | 6 |
deps/lld/test/ELF/string-gc.s+2-2| ... | @@ -14,7 +14,7 @@ | ... | @@ -14,7 +14,7 @@ |
| 14 | // CHECK-NEXT: } | 14 | // CHECK-NEXT: } |
| 15 | // CHECK-NEXT: Symbol { | 15 | // CHECK-NEXT: Symbol { |
| 16 | // CHECK-NEXT: Name: s3 | 16 | // CHECK-NEXT: Name: s3 |
| 17 | // CHECK-NEXT: Value: 0x200125 | 17 | // CHECK-NEXT: Value: 0x200120 |
| 18 | // CHECK-NEXT: Size: 0 | 18 | // CHECK-NEXT: Size: 0 |
| 19 | // CHECK-NEXT: Binding: Local (0x0) | 19 | // CHECK-NEXT: Binding: Local (0x0) |
| 20 | // CHECK-NEXT: Type: Object (0x1) | 20 | // CHECK-NEXT: Type: Object (0x1) |
| ... | @@ -23,7 +23,7 @@ | ... | @@ -23,7 +23,7 @@ |
| 23 | // CHECK-NEXT: } | 23 | // CHECK-NEXT: } |
| 24 | // CHECK-NEXT: Symbol { | 24 | // CHECK-NEXT: Symbol { |
| 25 | // CHECK-NEXT: Name: s1 | 25 | // CHECK-NEXT: Name: s1 |
| 26 | // CHECK-NEXT: Value: 0x200120 | 26 | // CHECK-NEXT: Value: 0x200125 |
| 27 | // CHECK-NEXT: Size: 0 | 27 | // CHECK-NEXT: Size: 0 |
| 28 | // CHECK-NEXT: Binding: Local (0x0) | 28 | // CHECK-NEXT: Binding: Local (0x0) |
| 29 | // CHECK-NEXT: Type: Object (0x1) | 29 | // CHECK-NEXT: Type: Object (0x1) |
deps/lld/test/ELF/strip-debug.s+8-19| ... | @@ -1,25 +1,14 @@ | ... | @@ -1,25 +1,14 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -g %s -o %t | ||
| 4 | # RUN: ld.lld %t -o %t2 | ||
| 5 | # RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=DEFAULT %s | ||
| 6 | # RUN: ld.lld %t -o %t2 --strip-debug | 3 | # RUN: ld.lld %t -o %t2 --strip-debug |
| 7 | # RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=STRIP %s | 4 | # RUN: llvm-readobj -sections %t2 | FileCheck %s |
| 8 | # RUN: ld.lld %t -o %t2 -S | 5 | # RUN: ld.lld %t -o %t2 -S |
| 9 | # RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=STRIP %s | 6 | # RUN: llvm-readobj -sections %t2 | FileCheck %s |
| 10 | # RUN: ld.lld %t -o %t2 --strip-all | 7 | # RUN: ld.lld %t -o %t2 --strip-all |
| 11 | # RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=STRIP %s | 8 | # RUN: llvm-readobj -sections %t2 | FileCheck %s |
| 12 | |||
| 13 | # DEFAULT: Name: .debug_info | ||
| 14 | # DEFAULT: Name: .debug_abbrev | ||
| 15 | # DEFAULT: Name: .debug_aranges | ||
| 16 | # DEFAULT: Name: .debug_line | ||
| 17 | 9 | ||
| 18 | # STRIP-NOT: Name: .debug_info | 10 | # CHECK-NOT: Foo |
| 19 | # STRIP-NOT: Name: .debug_abbrev | 11 | # CHECK-NOT: Bar |
| 20 | # STRIP-NOT: Name: .debug_aranges | ||
| 21 | # STRIP-NOT: Name: .debug_line | ||
| 22 | 12 | ||
| 23 | .globl _start | 13 | .section .debug_Foo,"",@progbits |
| 24 | _start: | 14 | .section .zdebug_Bar,"",@progbits |
| 25 | ret |
deps/lld/test/ELF/symbol-ordering-file2.s created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: echo "bar" > %t.order | ||
| 4 | # RUN: ld.lld --symbol-ordering-file %t.order -shared %t.o -o %t.so | ||
| 5 | # RUN: llvm-nm %t.so | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: 0000000000002000 d _DYNAMIC | ||
| 8 | # CHECK-NEXT: 0000000000001000 T bar | ||
| 9 | # CHECK-NEXT: 0000000000001004 T foo | ||
| 10 | |||
| 11 | .section .text.foo,"ax",@progbits | ||
| 12 | .align 4 | ||
| 13 | .global foo | ||
| 14 | foo: | ||
| 15 | retq | ||
| 16 | |||
| 17 | .section .text.bar,"ax",@progbits | ||
| 18 | .align 4 | ||
| 19 | .global bar | ||
| 20 | bar: | ||
| 21 | retq | ||
deps/lld/test/ELF/synthetic-got.s+2-2| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 3 | # RUN: echo "SECTIONS { }" > %t0.script | 3 | # RUN: echo "SECTIONS { }" > %t0.script |
| 4 | # RUN: ld.lld -shared %t.o -o %t0.out --script %t0.script | 4 | # RUN: ld.lld --hash-style=sysv -shared %t.o -o %t0.out --script %t0.script |
| 5 | # RUN: llvm-objdump -section-headers %t0.out | FileCheck %s --check-prefix=GOT | 5 | # RUN: llvm-objdump -section-headers %t0.out | FileCheck %s --check-prefix=GOT |
| 6 | # RUN: llvm-objdump -s -section=.got -section=.got.plt %t0.out \ | 6 | # RUN: llvm-objdump -s -section=.got -section=.got.plt %t0.out \ |
| 7 | # RUN: | FileCheck %s --check-prefix=GOTDATA | 7 | # RUN: | FileCheck %s --check-prefix=GOTDATA |
| ... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
| 16 | # GOTDATA-NEXT: 01d0 00000000 00000000 | 16 | # GOTDATA-NEXT: 01d0 00000000 00000000 |
| 17 | 17 | ||
| 18 | # RUN: echo "SECTIONS { .mygot : { *(.got) *(.got.plt) } }" > %t1.script | 18 | # RUN: echo "SECTIONS { .mygot : { *(.got) *(.got.plt) } }" > %t1.script |
| 19 | # RUN: ld.lld -shared %t.o -o %t1.out --script %t1.script | 19 | # RUN: ld.lld --hash-style=sysv -shared %t.o -o %t1.out --script %t1.script |
| 20 | # RUN: llvm-objdump -section-headers %t1.out | FileCheck %s --check-prefix=MYGOT | 20 | # RUN: llvm-objdump -section-headers %t1.out | FileCheck %s --check-prefix=MYGOT |
| 21 | # RUN: llvm-objdump -s -section=.mygot %t1.out | FileCheck %s --check-prefix=MYGOTDATA | 21 | # RUN: llvm-objdump -s -section=.mygot %t1.out | FileCheck %s --check-prefix=MYGOTDATA |
| 22 | 22 |
deps/lld/test/ELF/sysroot.s+2| ... | @@ -28,6 +28,8 @@ | ... | @@ -28,6 +28,8 @@ |
| 28 | // Should substitute SysRoot if specified | 28 | // Should substitute SysRoot if specified |
| 29 | // RUN: ld.lld -o %t/r %t/m.o --sysroot=%t -L=lib -l:libls.a | 29 | // RUN: ld.lld -o %t/r %t/m.o --sysroot=%t -L=lib -l:libls.a |
| 30 | // RUN: ld.lld -o %t/r %t/m.o --sysroot=%t -L=/lib -l:libls.a | 30 | // RUN: ld.lld -o %t/r %t/m.o --sysroot=%t -L=/lib -l:libls.a |
| 31 | // Check alias. | ||
| 32 | // RUN: ld.lld -o %t/r %t/m.o --sysroot %t -L=lib -l:libls.a | ||
| 31 | 33 | ||
| 32 | // Should not substitute SysRoot if the directory name does not start with '=' | 34 | // Should not substitute SysRoot if the directory name does not start with '=' |
| 33 | // RUN: not ld.lld -o %t/r %r/m.o --sysroot=%t -Llib -l:libls.a | 35 | // RUN: not ld.lld -o %t/r %r/m.o --sysroot=%t -Llib -l:libls.a |
deps/lld/test/ELF/sysv-hash-no-rosegment.s created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld -shared --no-rosegment -o %t %t.o | ||
| 4 | # RUN: llvm-readobj -hash-table %t | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: HashTable { | ||
| 7 | # CHECK-NEXT: Num Buckets: 2 | ||
| 8 | # CHECK-NEXT: Num Chains: 2 | ||
| 9 | # CHECK-NEXT: Buckets: [1, 0] | ||
| 10 | # CHECK-NEXT: Chains: [0, 0] | ||
| 11 | # CHECK-NEXT: } | ||
| 12 | |||
| 13 | callq undef@PLT | ||
deps/lld/test/ELF/tls-dynamic-i686.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t |
| 3 | // RUN: ld.lld -shared %t -o %tout | 3 | // RUN: ld.lld --hash-style=sysv -shared %t -o %tout |
| 4 | // RUN: llvm-readobj -sections -relocations %tout | FileCheck %s | 4 | // RUN: llvm-readobj -sections -relocations %tout | FileCheck %s |
| 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS | 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS |
| 6 | 6 |
deps/lld/test/ELF/tls-dynamic.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 3 | // RUN: ld.lld -shared %t -o %tout | 3 | // RUN: ld.lld --hash-style=sysv -shared %t -o %tout |
| 4 | // RUN: llvm-readobj -sections -relocations %tout | FileCheck %s | 4 | // RUN: llvm-readobj -sections -relocations %tout | FileCheck %s |
| 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS | 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS |
| 6 | 6 |
deps/lld/test/ELF/tls-got.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-got.s -o %t2.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-got.s -o %t2.o |
| 3 | // RUN: ld.lld -shared %t2.o -o %t2.so | 3 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 4 | // RUN: ld.lld -e main %t1.o %t2.so -o %t3 | 4 | // RUN: ld.lld --hash-style=sysv -e main %t1.o %t2.so -o %t3 |
| 5 | // RUN: llvm-readobj -s -r %t3 | FileCheck %s | 5 | // RUN: llvm-readobj -s -r %t3 | FileCheck %s |
| 6 | // RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM %s | 6 | // RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM %s |
| 7 | 7 |
deps/lld/test/ELF/tls-i686.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t |
| 3 | // RUN: ld.lld %t -o %tout | 3 | // RUN: ld.lld %t -o %tout |
| 4 | // RUN: ld.lld %t -shared -o %tsharedout | 4 | // RUN: ld.lld --hash-style=sysv %t -shared -o %tsharedout |
| 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS | 5 | // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS |
| 6 | // RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC | 6 | // RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC |
| 7 | // RUN: llvm-objdump -d %tsharedout | FileCheck %s --check-prefix=DISSHARED | 7 | // RUN: llvm-objdump -d %tsharedout | FileCheck %s --check-prefix=DISSHARED |
deps/lld/test/ELF/tls-initial-exec-local.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld -shared %t.o -o %t | 3 | // RUN: ld.lld --hash-style=sysv -shared %t.o -o %t |
| 4 | // RUN: llvm-readobj -r -s %t | FileCheck %s | 4 | // RUN: llvm-readobj -r -s %t | FileCheck %s |
| 5 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s | 5 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s |
| 6 | 6 |
deps/lld/test/ELF/tls-opt-gdie.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o |
| 3 | // RUN: ld.lld -shared %tso.o -o %t.so | 3 | // RUN: ld.lld -shared %tso.o -o %t.so |
| 4 | // RUN: ld.lld %t.o %t.so -o %t1 | 4 | // RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t1 |
| 5 | // RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=RELOC %s | 5 | // RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=RELOC %s |
| 6 | // RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s | 6 | // RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s |
| 7 | 7 |
deps/lld/test/ELF/tls-opt-gdiele-i686.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-gdiele-i686.s -o %tso.o | 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-gdiele-i686.s -o %tso.o |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld -shared %tso.o -o %tso | 3 | // RUN: ld.lld -shared %tso.o -o %tso |
| 4 | // RUN: ld.lld %t.o %tso -o %tout | 4 | // RUN: ld.lld --hash-style=sysv %t.o %tso -o %tout |
| 5 | // RUN: llvm-readobj -r %tout | FileCheck --check-prefix=NORELOC %s | 5 | // RUN: llvm-readobj -r %tout | FileCheck --check-prefix=NORELOC %s |
| 6 | // RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s | 6 | // RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s |
| 7 | 7 |
deps/lld/test/ELF/tls-opt-iele-i686-nopic.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o | 1 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o | 2 | // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o |
| 3 | // RUN: ld.lld -shared %tso.o -o %tso | 3 | // RUN: ld.lld -shared %tso.o -o %tso |
| 4 | // RUN: ld.lld %t.o %tso -o %t1 | 4 | // RUN: ld.lld --hash-style=sysv %t.o %tso -o %t1 |
| 5 | // RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTREL %s | 5 | // RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTREL %s |
| 6 | // RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s | 6 | // RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s |
| 7 | 7 |
deps/lld/test/ELF/tls-static.s+12-4| ... | @@ -3,12 +3,20 @@ | ... | @@ -3,12 +3,20 @@ |
| 3 | // RUN: ld.lld -static %t -o %tout | 3 | // RUN: ld.lld -static %t -o %tout |
| 4 | // RUN: ld.lld %t -o %tout | 4 | // RUN: ld.lld %t -o %tout |
| 5 | // RUN: ld.lld -shared %tso -o %tshared | 5 | // RUN: ld.lld -shared %tso -o %tshared |
| 6 | // RUN: not ld.lld -static %t %tshared -o %tout 2>&1 | FileCheck %s | 6 | // RUN: ld.lld -static %t %tshared -o %tout |
| 7 | // REQUIRES: x86 | 7 | // REQUIRES: x86 |
| 8 | 8 | ||
| 9 | .global _start | 9 | .global _start |
| 10 | _start: | 10 | _start: |
| 11 | call __tls_get_addr | 11 | data16 |
| 12 | leaq foobar@TLSGD(%rip), %rdi | ||
| 13 | data16 | ||
| 14 | data16 | ||
| 15 | rex64 | ||
| 16 | callq __tls_get_addr@PLT | ||
| 12 | 17 | ||
| 13 | // CHECK: error: undefined symbol: __tls_get_addr | 18 | |
| 14 | // CHECK: >>> referenced by {{.*}}:(.text+0x1) | 19 | .section .tdata,"awT",@progbits |
| 20 | .global foobar | ||
| 21 | foobar: | ||
| 22 | .long 42 |
deps/lld/test/ELF/tls-two-relocs.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 3 | // RUN: ld.lld %t -o %tout -shared | 3 | // RUN: ld.lld --hash-style=sysv %t -o %tout -shared |
| 4 | // RUN: llvm-readobj -r %tout | FileCheck %s | 4 | // RUN: llvm-readobj -r %tout | FileCheck %s |
| 5 | 5 | ||
| 6 | data16 | 6 | data16 |
deps/lld/test/ELF/trace-symbols.s+9-5| ... | @@ -31,19 +31,23 @@ | ... | @@ -31,19 +31,23 @@ |
| 31 | # RUN: %t %t2 %t1 -o %t4 2>&1 | FileCheck -check-prefix=OBJECTD2FOO %s | 31 | # RUN: %t %t2 %t1 -o %t4 2>&1 | FileCheck -check-prefix=OBJECTD2FOO %s |
| 32 | # RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 2>&1 | \ | 32 | # RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 2>&1 | \ |
| 33 | # RUN: FileCheck -check-prefix=OBJECTD2FOO %s | 33 | # RUN: FileCheck -check-prefix=OBJECTD2FOO %s |
| 34 | # RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 2>&1 | \ | ||
| 35 | # RUN: FileCheck -check-prefix=OBJECTD2FOO %s | ||
| 36 | # OBJECTD2FOO: trace-symbols.s.tmp2: definition of foo | 34 | # OBJECTD2FOO: trace-symbols.s.tmp2: definition of foo |
| 37 | 35 | ||
| 36 | # RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 2>&1 | \ | ||
| 37 | # RUN: FileCheck -check-prefix=FOO_AND_COMMON %s | ||
| 38 | # FOO_AND_COMMON: trace-symbols.s.tmp: reference to foo | ||
| 39 | # FOO_AND_COMMON: trace-symbols.s.tmp2: definition of foo | ||
| 40 | # FOO_AND_COMMON: trace-symbols.s.tmp1.a: lazy definition of common | ||
| 41 | |||
| 38 | # RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 2>&1 | \ | 42 | # RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 2>&1 | \ |
| 39 | # RUN: FileCheck -check-prefix=SHLIBDCOMMON %s | 43 | # RUN: FileCheck -check-prefix=SHLIBDCOMMON %s |
| 40 | # SHLIBDCOMMON: trace-symbols.s.tmp1.so: definition of common | 44 | # SHLIBDCOMMON: trace-symbols.s.tmp1.so: shared definition of common |
| 41 | 45 | ||
| 42 | # RUN: ld.lld -y foo -y common %t %t2.so %t1.so -o %t3 2>&1 | \ | 46 | # RUN: ld.lld -y foo -y common %t %t2.so %t1.so -o %t3 2>&1 | \ |
| 43 | # RUN: FileCheck -check-prefix=SHLIBD2FOO %s | 47 | # RUN: FileCheck -check-prefix=SHLIBD2FOO %s |
| 44 | # RUN: ld.lld -y foo %t %t1.a %t2.so -o %t3 | \ | 48 | # RUN: ld.lld -y foo %t %t1.a %t2.so -o %t3 | \ |
| 45 | # RUN: FileCheck -check-prefix=NO-SHLIBD2FOO %s | 49 | # RUN: FileCheck -check-prefix=NO-SHLIBD2FOO %s |
| 46 | # SHLIBD2FOO: trace-symbols.s.tmp2.so: definition of foo | 50 | # SHLIBD2FOO: trace-symbols.s.tmp2.so: shared definition of foo |
| 47 | # NO-SHLIBD2FOO-NOT: trace-symbols.s.tmp2.so: definition of foo | 51 | # NO-SHLIBD2FOO-NOT: trace-symbols.s.tmp2.so: definition of foo |
| 48 | 52 | ||
| 49 | # RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 2>&1 | \ | 53 | # RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 2>&1 | \ |
| ... | @@ -61,7 +65,7 @@ | ... | @@ -61,7 +65,7 @@ |
| 61 | 65 | ||
| 62 | # RUN: ld.lld -y bar %t %t1.so %t2.so -o %t3 | \ | 66 | # RUN: ld.lld -y bar %t %t1.so %t2.so -o %t3 | \ |
| 63 | # RUN: FileCheck -check-prefix=SHLIBDBAR %s | 67 | # RUN: FileCheck -check-prefix=SHLIBDBAR %s |
| 64 | # SHLIBDBAR: trace-symbols.s.tmp2.so: definition of bar | 68 | # SHLIBDBAR: trace-symbols.s.tmp2.so: shared definition of bar |
| 65 | 69 | ||
| 66 | # RUN: ld.lld -y foo -y bar %t %t1.so %t2.so -o %t3 | \ | 70 | # RUN: ld.lld -y foo -y bar %t %t1.so %t2.so -o %t3 | \ |
| 67 | # RUN: FileCheck -check-prefix=SHLIBRBAR %s | 71 | # RUN: FileCheck -check-prefix=SHLIBRBAR %s |
deps/lld/test/ELF/typed-undef.s created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # We used to crash on this, check that we don't | ||
| 4 | |||
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 6 | # RUN: ld.lld %t.o -o %t -pie --unresolved-symbols=ignore-all | ||
| 7 | |||
| 8 | .global _start | ||
| 9 | _start: | ||
| 10 | .quad foo - . | ||
| 11 | .type foo, @object | ||
deps/lld/test/ELF/undef-broken-debug.test created+47| ... | @@ -0,0 +1,47 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: yaml2obj %s -o %t.o | ||
| 3 | # RUN: not ld.lld %t.o -o %t.exe 2>&1 | FileCheck %s | ||
| 4 | |||
| 5 | # The debug info has a broken relocation. Check that we don't crash | ||
| 6 | # and still report the undefined symbol. | ||
| 7 | |||
| 8 | # CHECK: error: unsupported relocation target while parsing debug info | ||
| 9 | # CHECK: error: undefined symbol: bar | ||
| 10 | |||
| 11 | --- !ELF | ||
| 12 | FileHeader: | ||
| 13 | Class: ELFCLASS64 | ||
| 14 | Data: ELFDATA2LSB | ||
| 15 | Type: ET_REL | ||
| 16 | Machine: EM_X86_64 | ||
| 17 | Sections: | ||
| 18 | - Name: .text | ||
| 19 | Type: SHT_PROGBITS | ||
| 20 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | ||
| 21 | Content: '0000000000000000' | ||
| 22 | - Name: .rela.text | ||
| 23 | Type: SHT_RELA | ||
| 24 | AddressAlign: 8 | ||
| 25 | Link: .symtab | ||
| 26 | Info: .text | ||
| 27 | Relocations: | ||
| 28 | - Offset: 0x0000000000000000 | ||
| 29 | Symbol: bar | ||
| 30 | Type: R_X86_64_64 | ||
| 31 | - Name: .debug_line | ||
| 32 | Type: SHT_PROGBITS | ||
| 33 | Content: 3300000002001C0000000101FB0E0D000101010100000001000001006162632E7300000000000009020000000000000000140208000101 | ||
| 34 | - Name: .rela.debug_line | ||
| 35 | AddressAlign: 8 | ||
| 36 | Type: SHT_RELA | ||
| 37 | Link: .symtab | ||
| 38 | Info: .debug_line | ||
| 39 | Relocations: | ||
| 40 | - Offset: 0x0000000000000029 | ||
| 41 | Symbol: bar | ||
| 42 | Type: R_X86_64_64 | ||
| 43 | Symbols: | ||
| 44 | Global: | ||
| 45 | - Name: _start | ||
| 46 | Section: .text | ||
| 47 | - Name: bar | ||
deps/lld/test/ELF/undef-version-script.s+3-3| ... | @@ -3,9 +3,6 @@ | ... | @@ -3,9 +3,6 @@ |
| 3 | # RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so | 3 | # RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so |
| 4 | # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s | 4 | # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s |
| 5 | 5 | ||
| 6 | # This does not match gold's behavior because gold does not create undefined | ||
| 7 | # symbols in dynsym without an appropriate (e.g. PLT) relocation in the input. | ||
| 8 | |||
| 9 | # CHECK: DynamicSymbols [ | 6 | # CHECK: DynamicSymbols [ |
| 10 | # CHECK-NEXT: Symbol { | 7 | # CHECK-NEXT: Symbol { |
| 11 | # CHECK-NEXT: Name: @ | 8 | # CHECK-NEXT: Name: @ |
| ... | @@ -38,3 +35,6 @@ | ... | @@ -38,3 +35,6 @@ |
| 38 | 35 | ||
| 39 | .global foo | 36 | .global foo |
| 40 | .weak bar | 37 | .weak bar |
| 38 | .data | ||
| 39 | .dc.a foo | ||
| 40 | .dc.a bar |
deps/lld/test/ELF/unresolved-symbols.s+3| ... | @@ -13,6 +13,9 @@ | ... | @@ -13,6 +13,9 @@ |
| 13 | # RUN: not ld.lld %t1.o %t2.o -o %t --unresolved-symbols=xxx 2>&1 | \ | 13 | # RUN: not ld.lld %t1.o %t2.o -o %t --unresolved-symbols=xxx 2>&1 | \ |
| 14 | # RUN: FileCheck -check-prefix=ERR1 %s | 14 | # RUN: FileCheck -check-prefix=ERR1 %s |
| 15 | # ERR1: unknown --unresolved-symbols value: xxx | 15 | # ERR1: unknown --unresolved-symbols value: xxx |
| 16 | ## Check alias. | ||
| 17 | # RUN: not ld.lld %t1.o %t2.o -o %t --unresolved-symbols xxx 2>&1 | \ | ||
| 18 | # RUN: FileCheck -check-prefix=ERR1 %s | ||
| 16 | 19 | ||
| 17 | ## Ignore all should not produce error for symbols from object except | 20 | ## Ignore all should not produce error for symbols from object except |
| 18 | ## case when --no-undefined specified. | 21 | ## case when --no-undefined specified. |
deps/lld/test/ELF/verdef-defaultver.s+2-2| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/verdef-defaultver.s -o %t1 | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/verdef-defaultver.s -o %t1 |
| 4 | # RUN: echo "V1 { global: a; local: *; };" > %t.script | 4 | # RUN: echo "V1 { global: a; local: *; };" > %t.script |
| 5 | # RUN: echo "V2 { global: b; c; } V1;" >> %t.script | 5 | # RUN: echo "V2 { global: b; c; } V1;" >> %t.script |
| 6 | # RUN: ld.lld -shared -soname shared %t1 --version-script %t.script -o %t.so | 6 | # 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 %s | 7 | # RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s |
| 8 | 8 | ||
| 9 | # DSO: DynamicSymbols [ | 9 | # DSO: DynamicSymbols [ |
| ... | @@ -107,7 +107,7 @@ | ... | @@ -107,7 +107,7 @@ |
| 107 | 107 | ||
| 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 %t2 | 109 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2 |
| 110 | # RUN: ld.lld %t2 %t.so -o %t3 | 110 | # RUN: ld.lld --hash-style=sysv %t2 %t.so -o %t3 |
| 111 | # RUN: llvm-readobj -V -dyn-symbols %t3 | FileCheck --check-prefix=EXE %s | 111 | # RUN: llvm-readobj -V -dyn-symbols %t3 | FileCheck --check-prefix=EXE %s |
| 112 | 112 | ||
| 113 | # EXE: DynamicSymbols [ | 113 | # EXE: DynamicSymbols [ |
deps/lld/test/ELF/verdef.s+3-3| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 | # RUN: echo "LIBSAMPLE_1.0 { global: a; local: *; };" > %t.script | 3 | # RUN: echo "LIBSAMPLE_1.0 { global: a; local: *; };" > %t.script |
| 4 | # RUN: echo "LIBSAMPLE_2.0 { global: b; local: *; };" >> %t.script | 4 | # RUN: echo "LIBSAMPLE_2.0 { global: b; local: *; };" >> %t.script |
| 5 | # RUN: echo "LIBSAMPLE_3.0 { global: c; local: *; };" >> %t.script | 5 | # RUN: echo "LIBSAMPLE_3.0 { global: c; local: *; };" >> %t.script |
| 6 | # RUN: ld.lld --version-script %t.script -shared -soname shared %t.o -o %t.so | 6 | # 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 %s | 7 | # RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s |
| 8 | 8 | ||
| 9 | # DSO: Version symbols { | 9 | # DSO: Version symbols { |
| ... | @@ -65,7 +65,7 @@ | ... | @@ -65,7 +65,7 @@ |
| 65 | 65 | ||
| 66 | ## Check that we can link agains DSO we produced. | 66 | ## Check that we can link agains DSO we produced. |
| 67 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/verdef.s -o %tmain.o | 67 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/verdef.s -o %tmain.o |
| 68 | # RUN: ld.lld %tmain.o %t.so -o %tout | 68 | # RUN: ld.lld --hash-style=sysv %tmain.o %t.so -o %tout |
| 69 | # RUN: llvm-readobj -V %tout | FileCheck --check-prefix=MAIN %s | 69 | # RUN: llvm-readobj -V %tout | FileCheck --check-prefix=MAIN %s |
| 70 | 70 | ||
| 71 | # MAIN: Version symbols { | 71 | # MAIN: Version symbols { |
| ... | @@ -100,7 +100,7 @@ | ... | @@ -100,7 +100,7 @@ |
| 100 | # RUN: echo "LIBSAMPLE_2.0 { global: b; local: *; };" >> %t.script | 100 | # RUN: echo "LIBSAMPLE_2.0 { global: b; local: *; };" >> %t.script |
| 101 | # RUN: echo "LIBSAMPLE_3.0 { global: c; local: *; };" >> %t.script | 101 | # RUN: echo "LIBSAMPLE_3.0 { global: c; local: *; };" >> %t.script |
| 102 | # RUN: echo "}" >> %t.script | 102 | # RUN: echo "}" >> %t.script |
| 103 | # RUN: ld.lld --script %t.script -shared -soname shared %t.o -o %t2.so | 103 | # 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 %s | 104 | # RUN: llvm-readobj -V -dyn-symbols %t2.so | FileCheck --check-prefix=DSO %s |
| 105 | 105 | ||
| 106 | .globl a | 106 | .globl a |
deps/lld/test/ELF/verneed-as-needed-weak.s+5-1| ... | @@ -1,6 +1,10 @@ | ... | @@ -1,6 +1,10 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/verneed1.s -o %t1.o | ||
| 3 | # RUN: echo "v1 {}; v2 {}; v3 { local: *; };" > %t.script | ||
| 4 | # RUN: ld.lld -shared %t1.o --version-script %t.script -o %t.so | ||
| 5 | |||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | # RUN: ld.lld %t.o --as-needed %S/Inputs/verneed1.so -o %t | 7 | # RUN: ld.lld %t.o --as-needed %t.so -o %t |
| 4 | # RUN: llvm-readobj -V %t | FileCheck %s | 8 | # RUN: llvm-readobj -V %t | FileCheck %s |
| 5 | 9 | ||
| 6 | # CHECK: SHT_GNU_verneed { | 10 | # CHECK: SHT_GNU_verneed { |
deps/lld/test/ELF/verneed-local.s+5-1| ... | @@ -1,6 +1,10 @@ | ... | @@ -1,6 +1,10 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/verneed1.s -o %t1.o | ||
| 3 | # RUN: echo "v1 {}; v2 {}; v3 { local: *; };" > %t.script | ||
| 4 | # RUN: ld.lld -shared %t1.o --version-script %t.script -o %t.so | ||
| 5 | |||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 6 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | # RUN: not ld.lld %t.o %S/Inputs/verneed1.so -o %t 2>&1 | FileCheck %s | 7 | # RUN: not ld.lld %t.o %t.so -o %t 2>&1 | FileCheck %s |
| 4 | 8 | ||
| 5 | # CHECK: error: undefined symbol: f3 | 9 | # CHECK: error: undefined symbol: f3 |
| 6 | # CHECK: >>> referenced by {{.*}}:(.text+0x1) | 10 | # CHECK: >>> referenced by {{.*}}:(.text+0x1) |
deps/lld/test/ELF/verneed.s+7-1| ... | @@ -1,6 +1,12 @@ | ... | @@ -1,6 +1,12 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/verneed1.s -o %t1.o | ||
| 3 | # RUN: echo "v1 {}; v2 {}; v3 { local: *; };" > %t.script | ||
| 4 | # RUN: ld.lld -shared %t1.o --version-script %t.script -o %t1.so -soname verneed1.so.0 | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/verneed2.s -o %t2.o | ||
| 6 | # RUN: ld.lld -shared %t2.o --version-script %t.script -o %t2.so -soname verneed2.so.0 | ||
| 7 | |||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 8 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | # RUN: ld.lld %t.o %S/Inputs/verneed1.so %S/Inputs/verneed2.so -o %t | 9 | # RUN: ld.lld --hash-style=sysv %t.o %t1.so %t2.so -o %t |
| 4 | # RUN: llvm-readobj -V -sections -section-data -dyn-symbols -dynamic-table %t | FileCheck %s | 10 | # RUN: llvm-readobj -V -sections -section-data -dyn-symbols -dynamic-table %t | FileCheck %s |
| 5 | 11 | ||
| 6 | # CHECK: Section { | 12 | # CHECK: Section { |
deps/lld/test/ELF/version-script-err.s-1| ... | @@ -8,4 +8,3 @@ | ... | @@ -8,4 +8,3 @@ |
| 8 | // RUN: not ld.lld --version-script %terr1.script -shared %t.o -o %t.so 2>&1 | \ | 8 | // RUN: not ld.lld --version-script %terr1.script -shared %t.o -o %t.so 2>&1 | \ |
| 9 | // RUN: FileCheck -check-prefix=ERR1 %s | 9 | // RUN: FileCheck -check-prefix=ERR1 %s |
| 10 | // ERR1: {{.*}}:1: unclosed quote | 10 | // ERR1: {{.*}}:1: unclosed quote |
| 11 | // ERR1-NEXT: {{.*}}: unexpected EOF |
deps/lld/test/ELF/version-script-extern.s+1-1| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | # RUN: echo "LIBSAMPLE_2.0 { global:" >> %t.script | 7 | # RUN: echo "LIBSAMPLE_2.0 { global:" >> %t.script |
| 8 | # RUN: echo ' extern "C" { _Z3bari; };' >> %t.script | 8 | # RUN: echo ' extern "C" { _Z3bari; };' >> %t.script |
| 9 | # RUN: echo "};" >> %t.script | 9 | # RUN: echo "};" >> %t.script |
| 10 | # RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so | 10 | # RUN: ld.lld --hash-style=sysv --version-script %t.script -shared %t.o -o %t.so |
| 11 | # RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s | 11 | # RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s |
| 12 | 12 | ||
| 13 | # DSO: DynamicSymbols [ | 13 | # DSO: DynamicSymbols [ |
deps/lld/test/ELF/version-script-twice.s+4| ... | @@ -7,7 +7,11 @@ | ... | @@ -7,7 +7,11 @@ |
| 7 | 7 | ||
| 8 | .weak	openat | 8 | .weak	openat |
| 9 | openat: | 9 | openat: |
| 10 | |||
| 11 | .global openat@FBSD_1.1 | ||
| 10 | openat@FBSD_1.1 = openat | 12 | openat@FBSD_1.1 = openat |
| 13 | |||
| 14 | .global openat@@FBSD_1.2 | ||
| 11 | openat@@FBSD_1.2 = openat | 15 | openat@@FBSD_1.2 = openat |
| 12 | 16 | ||
| 13 | # CHECK-DAG: openat@FBSD_1.1 | 17 | # CHECK-DAG: openat@FBSD_1.1 |
deps/lld/test/ELF/version-script.s+8-2| ... | @@ -42,6 +42,12 @@ | ... | @@ -42,6 +42,12 @@ |
| 42 | # RUN: ld.lld --version-script %t.script --dynamic-list %t.list %t.o %t2.so -o %t2 | 42 | # RUN: ld.lld --version-script %t.script --dynamic-list %t.list %t.o %t2.so -o %t2 |
| 43 | # RUN: llvm-readobj %t2 > /dev/null | 43 | # RUN: llvm-readobj %t2 > /dev/null |
| 44 | 44 | ||
| 45 | ## Check that we can handle multiple "--version-script" options. | ||
| 46 | # RUN: echo "VERSION_1.0 { global : foo1; local : *; };" > %t7a.script | ||
| 47 | # 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.so | ||
| 49 | # RUN: llvm-readobj -dyn-symbols %t7.so | FileCheck --check-prefix=VERDSO %s | ||
| 50 | |||
| 45 | # DSO: DynamicSymbols [ | 51 | # DSO: DynamicSymbols [ |
| 46 | # DSO-NEXT: Symbol { | 52 | # DSO-NEXT: Symbol { |
| 47 | # DSO-NEXT: Name: @ | 53 | # DSO-NEXT: Name: @ |
| ... | @@ -142,12 +148,12 @@ | ... | @@ -142,12 +148,12 @@ |
| 142 | # VERDSO-NEXT: ] | 148 | # VERDSO-NEXT: ] |
| 143 | 149 | ||
| 144 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 150 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 145 | # RUN: ld.lld -shared %t.o %t2.so -o %t.so | 151 | # RUN: ld.lld --hash-style=sysv -shared %t.o %t2.so -o %t.so |
| 146 | # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s | 152 | # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s |
| 147 | 153 | ||
| 148 | # RUN: echo "{ global: foo1; foo3; };" > %t2.script | 154 | # RUN: echo "{ global: foo1; foo3; };" > %t2.script |
| 149 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | 155 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 150 | # RUN: ld.lld --version-script %t2.script -shared %t.o %t2.so -o %t.so | 156 | # RUN: ld.lld --hash-style=sysv --version-script %t2.script -shared %t.o %t2.so -o %t.so |
| 151 | # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s | 157 | # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s |
| 152 | 158 | ||
| 153 | # ALL: DynamicSymbols [ | 159 | # ALL: DynamicSymbols [ |
deps/lld/test/ELF/weak-entry.s created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | ||
| 3 | # RUN: ld.lld %t -o %tout | ||
| 4 | # RUN: llvm-nm %tout | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: w _start | ||
| 7 | # CHECK-NEXT: T foo | ||
| 8 | |||
| 9 | .global foo | ||
| 10 | .weak _start | ||
| 11 | .text | ||
| 12 | foo: | ||
| 13 | 	.dc.a _start | ||
deps/lld/test/ELF/weak-undef-export.s created+31| ... | @@ -0,0 +1,31 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # Test that we don't fail with foo being undefined. | ||
| 4 | |||
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 6 | # RUN: ld.lld --export-dynamic %t.o -o %t | ||
| 7 | # RUN: llvm-readobj -dyn-symbols %t | FileCheck %s | ||
| 8 | |||
| 9 | # CHECK: DynamicSymbols [ | ||
| 10 | # CHECK-NEXT: Symbol { | ||
| 11 | # CHECK-NEXT: Name: @ (0) | ||
| 12 | # CHECK-NEXT: Value: 0x0 | ||
| 13 | # CHECK-NEXT: Size: 0 | ||
| 14 | # CHECK-NEXT: Binding: Local (0x0) | ||
| 15 | # CHECK-NEXT: Type: None (0x0) | ||
| 16 | # CHECK-NEXT: Other: 0 | ||
| 17 | # CHECK-NEXT: Section: Undefined (0x0) | ||
| 18 | # CHECK-NEXT: } | ||
| 19 | # CHECK-NEXT: Symbol { | ||
| 20 | # CHECK-NEXT: Name: foo@ (1) | ||
| 21 | # CHECK-NEXT: Value: 0x0 | ||
| 22 | # CHECK-NEXT: Size: 0 | ||
| 23 | # CHECK-NEXT: Binding: Weak (0x2) | ||
| 24 | # CHECK-NEXT: Type: None (0x0) | ||
| 25 | # CHECK-NEXT: Other: 0 | ||
| 26 | # CHECK-NEXT: Section: Undefined (0x0) | ||
| 27 | # CHECK-NEXT: } | ||
| 28 | # CHECK-NEXT: ] | ||
| 29 | |||
| 30 | .weak foo | ||
| 31 | .quad foo | ||
deps/lld/test/ELF/weak-undef-lazy.s created+11| ... | @@ -0,0 +1,11 @@ | ||
| 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/weak-undef-lazy.s -o %t2.o | ||
| 4 | # RUN: rm -f %t2.a | ||
| 5 | # RUN: llvm-ar rc %t2.a %t2.o | ||
| 6 | # RUN: ld.lld %t.o %t2.a -o %t --export-dynamic | ||
| 7 | |||
| 8 | .global _start | ||
| 9 | _start: | ||
| 10 | .weak foobar | ||
| 11 | .quad foobar | ||
deps/lld/test/ELF/weak-undef-rw.s created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: ld.lld %t.o -o %t --export-dynamic | ||
| 4 | # RUN: llvm-readobj -r %t | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: R_X86_64_64 foobar 0x0 | ||
| 7 | |||
| 8 | .global _start | ||
| 9 | _start: | ||
| 10 | .data | ||
| 11 | .weak foobar | ||
| 12 | .quad foobar | ||
deps/lld/test/ELF/weak-undef-val.s created+26| ... | @@ -0,0 +1,26 @@ | ||
| 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 --export-dynamic | ||
| 4 | # RUN: llvm-readobj -s -section-data %t | FileCheck %s | ||
| 5 | |||
| 6 | # CHECK: Name: .text | ||
| 7 | # CHECK-NEXT: Type: SHT_PROGBITS | ||
| 8 | # CHECK-NEXT: Flags [ | ||
| 9 | # CHECK-NEXT: SHF_ALLOC | ||
| 10 | # CHECK-NEXT: SHF_EXECINSTR | ||
| 11 | # CHECK-NEXT: ] | ||
| 12 | # CHECK-NEXT: Address: 0x201000 | ||
| 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: 00F0DFFF | | ||
| 21 | # CHECK-NEXT: ) | ||
| 22 | |||
| 23 | .global _start | ||
| 24 | _start: | ||
| 25 | .weak foobar | ||
| 26 | .long foobar - . | ||
deps/lld/test/ELF/weak-undef.s+12| ... | @@ -13,9 +13,21 @@ | ... | @@ -13,9 +13,21 @@ |
| 13 | # CHECK-NEXT: Other: 0 | 13 | # CHECK-NEXT: Other: 0 |
| 14 | # CHECK-NEXT: Section: Undefined (0x0) | 14 | # CHECK-NEXT: Section: Undefined (0x0) |
| 15 | # CHECK-NEXT: } | 15 | # CHECK-NEXT: } |
| 16 | # CHECK-NEXT: Symbol { | ||
| 17 | # CHECK-NEXT: Name: foo@ | ||
| 18 | # CHECK-NEXT: Value: 0x0 | ||
| 19 | # CHECK-NEXT: Size: 0 | ||
| 20 | # CHECK-NEXT: Binding: Weak | ||
| 21 | # CHECK-NEXT: Type: None | ||
| 22 | # CHECK-NEXT: Other: 0 | ||
| 23 | # CHECK-NEXT: Section: Undefined | ||
| 24 | # CHECK-NEXT: } | ||
| 16 | # CHECK-NEXT: ] | 25 | # CHECK-NEXT: ] |
| 17 | 26 | ||
| 18 | .weak foo | 27 | .weak foo |
| 19 | 28 | ||
| 20 | .globl _start | 29 | .globl _start |
| 21 | _start: | 30 | _start: |
| 31 | |||
| 32 | .data | ||
| 33 | .dc.a foo |
deps/lld/test/ELF/wrap-no-real.s created+77| ... | @@ -0,0 +1,77 @@ | ||
| 1 | // REQUIRES: x86 | ||
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/wrap-no-real.s -o %t2.o | ||
| 4 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/wrap-no-real2.s -o %t3.o | ||
| 5 | // RUN: ld.lld -o %t3.so -shared %t3.o | ||
| 6 | |||
| 7 | // RUN: ld.lld -o %t %t1.o %t2.o -wrap foo | ||
| 8 | // RUN: llvm-objdump -d -print-imm-hex %t | FileCheck %s | ||
| 9 | |||
| 10 | // RUN: ld.lld -o %t %t1.o %t2.o %t3.so -wrap foo | ||
| 11 | // RUN: llvm-objdump -d -print-imm-hex %t | FileCheck %s | ||
| 12 | |||
| 13 | // CHECK: _start: | ||
| 14 | // CHECK-NEXT: movl $0x11010, %edx | ||
| 15 | // CHECK-NEXT: movl $0x11010, %edx | ||
| 16 | // CHECK-NEXT: movl $0x11000, %edx | ||
| 17 | |||
| 18 | // RUN: llvm-readobj -t %t | FileCheck -check-prefix=SYM %s | ||
| 19 | |||
| 20 | // Test the full symbol table. It is verbose, but lld at times | ||
| 21 | // produced duplicated symbols which are hard to test otherwise. | ||
| 22 | |||
| 23 | // SYM: Symbols [ | ||
| 24 | // SYM-NEXT: Symbol { | ||
| 25 | // SYM-NEXT: Name: (0) | ||
| 26 | // SYM-NEXT: Value: | ||
| 27 | // SYM-NEXT: Size: | ||
| 28 | // SYM-NEXT: Binding: | ||
| 29 | // SYM-NEXT: Type | ||
| 30 | // SYM-NEXT: Other: | ||
| 31 | // SYM-NEXT: Section: | ||
| 32 | // SYM-NEXT: } | ||
| 33 | // SYM-NEXT: Symbol { | ||
| 34 | // SYM-NEXT: Name: _DYNAMIC | ||
| 35 | // SYM-NEXT: Value: | ||
| 36 | // SYM-NEXT: Size: | ||
| 37 | // SYM-NEXT: Binding: | ||
| 38 | // SYM-NEXT: Type: | ||
| 39 | // SYM-NEXT: Other [ | ||
| 40 | // SYM-NEXT: STV_HIDDEN | ||
| 41 | // SYM-NEXT: ] | ||
| 42 | // SYM-NEXT: Section: .dynamic | ||
| 43 | // SYM-NEXT: } | ||
| 44 | // SYM-NEXT: Symbol { | ||
| 45 | // SYM-NEXT: Name: foo | ||
| 46 | // SYM-NEXT: Value: 0x11000 | ||
| 47 | // SYM-NEXT: Size: | ||
| 48 | // SYM-NEXT: Binding: | ||
| 49 | // SYM-NEXT: Type: | ||
| 50 | // SYM-NEXT: Other: | ||
| 51 | // SYM-NEXT: Section: | ||
| 52 | // SYM-NEXT: } | ||
| 53 | // SYM-NEXT: Symbol { | ||
| 54 | // SYM-NEXT: Name: _start | ||
| 55 | // SYM-NEXT: Value: | ||
| 56 | // SYM-NEXT: Size: | ||
| 57 | // SYM-NEXT: Binding: | ||
| 58 | // SYM-NEXT: Type | ||
| 59 | // SYM-NEXT: Other: | ||
| 60 | // SYM-NEXT: Section: | ||
| 61 | // SYM-NEXT: } | ||
| 62 | // SYM-NEXT: Symbol { | ||
| 63 | // SYM-NEXT: Name: __wrap_foo | ||
| 64 | // SYM-NEXT: Value: 0x11010 | ||
| 65 | // SYM-NEXT: Size: | ||
| 66 | // SYM-NEXT: Binding: | ||
| 67 | // SYM-NEXT: Type: | ||
| 68 | // SYM-NEXT: Other: | ||
| 69 | // SYM-NEXT: Section: | ||
| 70 | // SYM-NEXT: } | ||
| 71 | // SYM-NEXT: ] | ||
| 72 | |||
| 73 | .global _start | ||
| 74 | _start: | ||
| 75 | movl $foo, %edx | ||
| 76 | movl $__wrap_foo, %edx | ||
| 77 | movl $__real_foo, %edx | ||
deps/lld/test/ELF/wrap.s+24-10| ... | @@ -12,17 +12,31 @@ | ... | @@ -12,17 +12,31 @@ |
| 12 | // CHECK-NEXT: movl $0x11010, %edx | 12 | // CHECK-NEXT: movl $0x11010, %edx |
| 13 | // CHECK-NEXT: movl $0x11000, %edx | 13 | // CHECK-NEXT: movl $0x11000, %edx |
| 14 | 14 | ||
| 15 | // This shows an oddity of our implementation. The symbol foo gets | 15 | // RUN: llvm-readobj -t %t3 > %t4.dump |
| 16 | // mapped to __wrap_foo, but stays in the symbol table. This results | 16 | // RUN: FileCheck --check-prefix=SYM1 %s < %t4.dump |
| 17 | // in it showing up twice in the output. | 17 | // RUN: FileCheck --check-prefix=SYM2 %s < %t4.dump |
| 18 | // RUN: FileCheck --check-prefix=SYM3 %s < %t4.dump | ||
| 18 | 19 | ||
| 19 | // RUN: llvm-readobj -t -s %t3 | FileCheck -check-prefix=SYM %s | 20 | // SYM1: Name: foo |
| 20 | // SYM: Name: foo | 21 | // SYM1-NEXT: Value: 0x11000 |
| 21 | // SYM-NEXT: Value: 0x11000 | 22 | // SYM1-NEXT: Size: |
| 22 | // SYM: Name: __wrap_foo | 23 | // SYM1-NEXT: Binding: Global |
| 23 | // SYM-NEXT: Value: 0x11010 | 24 | // SYM1-NEXT: Type: None |
| 24 | // SYM: Name: __wrap_foo | 25 | // SYM1-NEXT: Other: 0 |
| 25 | // SYM-NEXT: Value: 0x11010 | 26 | // SYM2: Name: __wrap_foo |
| 27 | // SYM2-NEXT: Value: 0x11010 | ||
| 28 | // SYM2-NEXT: Size: | ||
| 29 | // SYM2-NEXT: Binding: Weak | ||
| 30 | // SYM2-NEXT: Type: None | ||
| 31 | // SYM2-NEXT: Other [ | ||
| 32 | // SYM2-NEXT: STV_PROTECTED | ||
| 33 | // SYM2-NEXT: ] | ||
| 34 | // SYM3: Name: __real_foo | ||
| 35 | // SYM3-NEXT: Value: 0x11020 | ||
| 36 | // SYM3-NEXT: Size: | ||
| 37 | // SYM3-NEXT: Binding: Global | ||
| 38 | // SYM3-NEXT: Type: None | ||
| 39 | // SYM3-NEXT: Other: 0 | ||
| 26 | 40 | ||
| 27 | .global _start | 41 | .global _start |
| 28 | _start: | 42 | _start: |
deps/lld/test/ELF/writable-sec-plt-reloc.s created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux | ||
| 3 | # RUN: llvm-mc %p/Inputs/writable-sec-plt-reloc.s -o %t2.o -filetype=obj -triple=x86_64-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-readelf --symbols -r %t | FileCheck %s | ||
| 7 | |||
| 8 | # CHECK: R_X86_64_JUMP_SLOT {{.*}} foo + 0 | ||
| 9 | # CHECK: 0000000000201010 0 FUNC GLOBAL DEFAULT UND foo | ||
| 10 | |||
| 11 | .section .bar,"awx" | ||
| 12 | .global _start | ||
| 13 | _start: | ||
| 14 | call foo | ||
deps/lld/test/ELF/x86-64-dyn-rel-error.s+4-2| ... | @@ -2,11 +2,13 @@ | ... | @@ -2,11 +2,13 @@ |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 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/shared.s -o %t2.o | 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2.o |
| 4 | // RUN: ld.lld %t2.o -shared -o %t2.so | 4 | // RUN: ld.lld %t2.o -shared -o %t2.so |
| 5 | // RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s | 5 | // RUN: not ld.lld -shared %t.o %t2.so -o %t 2>&1 | FileCheck %s |
| 6 | 6 | ||
| 7 | .global _start | 7 | .global _start |
| 8 | _start: | 8 | _start: |
| 9 | .data | 9 | .data |
| 10 | .long bar | 10 | .long zed |
| 11 | 11 | ||
| 12 | // CHECK: relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC | 12 | // CHECK: relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC |
| 13 | |||
| 14 | // RUN: ld.lld --noinhibit-exec %t.o %t2.so -o %t 2>&1 | FileCheck %s |
deps/lld/test/ELF/x86-64-dyn-rel-error2.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.o | 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/shared.s -o %t2.o | 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2.o |
| 4 | // RUN: ld.lld %t2.o -shared -o %t2.so | 4 | // RUN: ld.lld %t2.o -shared -o %t2.so |
| 5 | // RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s | 5 | // RUN: not ld.lld -shared %t.o %t2.so -o %t 2>&1 | FileCheck %s |
| 6 | 6 | ||
| 7 | // CHECK: relocation R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC | 7 | // CHECK: relocation R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC |
| 8 | // CHECK: >>> defined in {{.*}}.so | 8 | // CHECK: >>> defined in {{.*}}.so |
| ... | @@ -11,4 +11,4 @@ | ... | @@ -11,4 +11,4 @@ |
| 11 | .global _start | 11 | .global _start |
| 12 | _start: | 12 | _start: |
| 13 | .data | 13 | .data |
| 14 | .long bar - . | 14 | .long zed - . |
deps/lld/test/ELF/x86-64-relax-got-abs.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %s \ | 2 | // RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %s \ |
| 3 | // RUN: -o %t.o | 3 | // RUN: -o %t.o |
| 4 | // RUN: ld.lld %t.o -o %t.so -shared | 4 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 5 | // RUN: llvm-objdump -d %t.so | FileCheck %s | 5 | // RUN: llvm-objdump -d %t.so | FileCheck %s |
| 6 | 6 | ||
| 7 | // We used to fail trying to relax this into a pc relocation to an absolute | 7 | // We used to fail trying to relax this into a pc relocation to an absolute |
deps/lld/test/ELF/x86-64-reloc-16.s+1-1| ... | @@ -9,6 +9,6 @@ | ... | @@ -9,6 +9,6 @@ |
| 9 | // CHECK-NEXT: 200000 42 | 9 | // CHECK-NEXT: 200000 42 |
| 10 | 10 | ||
| 11 | // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s | 11 | // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s |
| 12 | // ERROR: relocation R_X86_64_16 out of range | 12 | // ERROR: relocation R_X86_64_16 out of range: 65536 is not in [0, 65535] |
| 13 | 13 | ||
| 14 | .short foo | 14 | .short foo |
deps/lld/test/ELF/x86-64-reloc-8.s+1-1| ... | @@ -9,6 +9,6 @@ | ... | @@ -9,6 +9,6 @@ |
| 9 | // CHECK-NEXT: 200000 42 | 9 | // CHECK-NEXT: 200000 42 |
| 10 | 10 | ||
| 11 | // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s | 11 | // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s |
| 12 | // ERROR: relocation R_X86_64_8 out of range | 12 | // ERROR: relocation R_X86_64_8 out of range: 256 is not in [0, 255] |
| 13 | 13 | ||
| 14 | .byte foo | 14 | .byte foo |
deps/lld/test/ELF/x86-64-reloc-error.s+2-2| ... | @@ -6,5 +6,5 @@ | ... | @@ -6,5 +6,5 @@ |
| 6 | movl $big, %edx | 6 | movl $big, %edx |
| 7 | movq $foo - 0x1000000000000, %rdx | 7 | movq $foo - 0x1000000000000, %rdx |
| 8 | 8 | ||
| 9 | # CHECK: {{.*}}:(.text+0x1): relocation R_X86_64_32 out of range | 9 | # CHECK: {{.*}}:(.text+0x1): relocation R_X86_64_32 out of range: 68719476736 is not in [0, 4294967295] |
| 10 | # CHECK: {{.*}}:(.text+0x8): relocation R_X86_64_32S out of range | 10 | # CHECK: {{.*}}:(.text+0x8): relocation R_X86_64_32S out of range: -281474976710656 is not in [-2147483648, 2147483647] |
deps/lld/test/ELF/x86-64-reloc-range.s+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // RUN: llvm-mc %s -o %t.o -triple x86_64-pc-linux -filetype=obj | 1 | // RUN: llvm-mc %s -o %t.o -triple x86_64-pc-linux -filetype=obj |
| 2 | // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s | 2 | // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s |
| 3 | 3 | ||
| 4 | // CHECK: {{.*}}:(.text+0x3): relocation R_X86_64_PC32 out of range | 4 | // CHECK: {{.*}}:(.text+0x3): relocation R_X86_64_PC32 out of range: 2147483648 is not in [-2147483648, 2147483647] |
| 5 | // CHECK-NOT: relocation | 5 | // CHECK-NOT: relocation |
| 6 | 6 | ||
| 7 | lea foo(%rip), %rax | 7 | lea foo(%rip), %rax |
deps/lld/test/ELF/x86-64-tls-gd-local.s+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // REQUIRES: x86 | 1 | // REQUIRES: x86 |
| 2 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux | 2 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux |
| 3 | // RUN: ld.lld %t.o -o %t.so -shared | 3 | // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared |
| 4 | // RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s | 4 | // RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s |
| 5 | 5 | ||
| 6 | .byte 0x66 | 6 | .byte 0x66 |
deps/lld/test/ELF/znotext-copy-relocation.s created+16| ... | @@ -0,0 +1,16 @@ | ||
| 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/znotext-copy-relocations.s -o %t2.o | ||
| 4 | # RUN: ld.lld %t2.o -o %t2.so -shared | ||
| 5 | # RUN: ld.lld -z notext %t.o %t2.so -o %t | ||
| 6 | # RUN: llvm-readobj -r %t | FileCheck %s | ||
| 7 | |||
| 8 | # CHECK: Relocations [ | ||
| 9 | # CHECK-NEXT: Section ({{.*}}) .rela.dyn { | ||
| 10 | # CHECK-NEXT: R_X86_64_COPY foo 0x0 | ||
| 11 | # CHECK-NEXT: } | ||
| 12 | # CHECK-NEXT: ] | ||
| 13 | |||
| 14 | .global _start | ||
| 15 | _start: | ||
| 16 | .long foo | ||
deps/lld/test/ELF/znotext-plt-relocations-protected.s created+11| ... | @@ -0,0 +1,11 @@ | ||
| 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/znotext-plt-relocations-protected.s -o %t2.o | ||
| 4 | # RUN: ld.lld %t2.o -o %t2.so -shared | ||
| 5 | # RUN: not ld.lld -z notext %t.o %t2.so -o %t 2>&1 | FileCheck %s | ||
| 6 | |||
| 7 | # CHECK: error: cannot preempt symbol: foo | ||
| 8 | |||
| 9 | .global _start | ||
| 10 | _start: | ||
| 11 | callq foo | ||
deps/lld/test/ELF/znotext-plt-relocations.s created+20| ... | @@ -0,0 +1,20 @@ | ||
| 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/znotext-plt-relocations.s -o %t2.o | ||
| 4 | # RUN: ld.lld %t2.o -o %t2.so -shared | ||
| 5 | # RUN: ld.lld -z notext %t.o %t2.so -o %t | ||
| 6 | # RUN: llvm-readobj -r %t | FileCheck %s | ||
| 7 | |||
| 8 | # CHECK: Relocations [ | ||
| 9 | # CHECK-NEXT: Section {{.*}} .rela.dyn { | ||
| 10 | # CHECK-NEXT: R_X86_64_64 foo 0x0 | ||
| 11 | # CHECK-NEXT: } | ||
| 12 | # CHECK-NEXT: Section {{.*}} .rela.plt { | ||
| 13 | # CHECK-NEXT: R_X86_64_JUMP_SLOT atexit 0x0 | ||
| 14 | # CHECK-NEXT: } | ||
| 15 | # CHECK-NEXT: ] | ||
| 16 | |||
| 17 | .text | ||
| 18 | _start: | ||
| 19 | callq atexit | ||
| 20 | .quad foo | ||
deps/lld/test/ELF/znotext-weak-undef.s created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | ||
| 3 | # RUN: not ld.lld -z notext -shared %t.o -o %t 2>&1 | FileCheck %s | ||
| 4 | # CHECK: relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC | ||
| 5 | |||
| 6 | # RUN: ld.lld -z notext %t.o -o %t | ||
| 7 | # RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=EXE | ||
| 8 | # EXE: Relocations [ | ||
| 9 | # EXE-NEXT: ] | ||
| 10 | |||
| 11 | .text | ||
| 12 | .global foo | ||
| 13 | .weak foo | ||
| 14 | |||
| 15 | _start: | ||
| 16 | mov $foo,%eax | ||
deps/lld/test/MinGW/driver.test created+126| ... | @@ -0,0 +1,126 @@ | ||
| 1 | RUN: ld.lld -### foo.o -m i386pe | FileCheck -check-prefix=X86 %s | ||
| 2 | X86: -out:a.exe | ||
| 3 | X86-SAME: -machine:x86 | ||
| 4 | X86-SAME: -alternatename:__image_base__=___ImageBase | ||
| 5 | X86-SAME: foo.o | ||
| 6 | |||
| 7 | RUN: ld.lld -### foo.o -m i386pep | FileCheck -check-prefix=X64 %s | ||
| 8 | X64: -out:a.exe | ||
| 9 | X64-SAME: -machine:x64 | ||
| 10 | X64-SAME: -alternatename:__image_base__=__ImageBase | ||
| 11 | X64-SAME: foo.o | ||
| 12 | |||
| 13 | RUN: ld.lld -### foo.o -m thumb2pe | FileCheck -check-prefix=ARM %s | ||
| 14 | ARM: -out:a.exe | ||
| 15 | ARM-SAME: -machine:arm | ||
| 16 | ARM-SAME: -alternatename:__image_base__=__ImageBase | ||
| 17 | ARM-SAME: foo.o | ||
| 18 | |||
| 19 | RUN: ld.lld -### foo.o -m arm64pe | FileCheck -check-prefix=ARM64 %s | ||
| 20 | ARM64: -out:a.exe | ||
| 21 | ARM64-SAME: -machine:arm64 | ||
| 22 | ARM64-SAME: -alternatename:__image_base__=__ImageBase | ||
| 23 | ARM64-SAME: foo.o | ||
| 24 | |||
| 25 | RUN: ld.lld -### foo.o -m i386pep -shared | FileCheck -check-prefix=SHARED %s | ||
| 26 | RUN: ld.lld -### foo.o -m i386pep --shared | FileCheck -check-prefix=SHARED %s | ||
| 27 | SHARED: -out:a.dll | ||
| 28 | SHARED-SAME: -dll | ||
| 29 | |||
| 30 | RUN: ld.lld -### foo.o -m i386pep -shared foo.def | FileCheck -check-prefix=DEF1 %s | ||
| 31 | DEF1: -def:foo.def | ||
| 32 | |||
| 33 | RUN: ld.lld -### foo.o -m i386pep -shared FOO.DEF | FileCheck -check-prefix=DEF2 %s | ||
| 34 | DEF2: -def:FOO.DEF | ||
| 35 | |||
| 36 | RUN: ld.lld -### foo.o -m i386pep -obar.exe | FileCheck -check-prefix=OUT %s | ||
| 37 | RUN: ld.lld -### foo.o -m i386pep -o bar.exe | FileCheck -check-prefix=OUT %s | ||
| 38 | OUT: -out:bar.exe | ||
| 39 | |||
| 40 | RUN: ld.lld -### foo.o -m i386pep --out-implib bar | FileCheck -check-prefix=IMPLIB %s | ||
| 41 | RUN: ld.lld -### foo.o -m i386pep --out-implib=bar | FileCheck -check-prefix=IMPLIB %s | ||
| 42 | IMPLIB: -implib:bar | ||
| 43 | |||
| 44 | RUN: ld.lld -### foo.o -m i386pep -out-implib bar | FileCheck -check-prefix=NOIMPLIB %s | ||
| 45 | NOIMPLIB: -out:ut-implib | ||
| 46 | |||
| 47 | RUN: ld.lld -### foo.o -m i386pep -e bar | FileCheck -check-prefix=ENTRY %s | ||
| 48 | RUN: ld.lld -### foo.o -m i386pep -entry bar | FileCheck -check-prefix=ENTRY %s | ||
| 49 | RUN: ld.lld -### foo.o -m i386pep --entry bar | FileCheck -check-prefix=ENTRY %s | ||
| 50 | ENTRY: -entry:bar | ||
| 51 | |||
| 52 | RUN: ld.lld -### foo.o -m i386pep -mllvm bar -mllvm baz | FileCheck -check-prefix=MLLVM %s | ||
| 53 | MLLVM: -mllvm:bar -mllvm:baz | ||
| 54 | |||
| 55 | RUN: ld.lld -### foo.o -m i386pep -subsystem console | FileCheck -check-prefix=SUBSYSTEM %s | ||
| 56 | RUN: ld.lld -### foo.o -m i386pep --subsystem console | FileCheck -check-prefix=SUBSYSTEM %s | ||
| 57 | SUBSYSTEM: -subsystem:console | ||
| 58 | |||
| 59 | RUN: ld.lld -### foo.o -m i386pep -stack 4194304,8192 | FileCheck -check-prefix=STACK %s | ||
| 60 | RUN: ld.lld -### foo.o -m i386pep --stack 4194304,8192 | FileCheck -check-prefix=STACK %s | ||
| 61 | STACK: -stack:4194304,8192 | ||
| 62 | |||
| 63 | RUN: ld.lld -### foo.o -m i386pep -verbose | FileCheck -check-prefix=VERBOSE %s | ||
| 64 | RUN: ld.lld -### foo.o -m i386pep --verbose | FileCheck -check-prefix=VERBOSE %s | ||
| 65 | VERBOSE: -verbose | ||
| 66 | |||
| 67 | RUN: ld.lld -### -shared -m i386pe -e _DllMainCRTStartup@12 foo.o | FileCheck -check-prefix I386-ENTRY %s | ||
| 68 | I386-ENTRY: -entry:DllMainCRTStartup@12 | ||
| 69 | |||
| 70 | RUN: ld.lld -### -m i386pep foo.o --whole-archive bar.a --no-whole-archive baz.a | FileCheck -check-prefix WHOLE-ARCHIVE %s | ||
| 71 | RUN: ld.lld -### -m i386pep foo.o -whole-archive bar.a -no-whole-archive baz.a | FileCheck -check-prefix WHOLE-ARCHIVE %s | ||
| 72 | WHOLE-ARCHIVE: foo.o -wholearchive:bar.a baz.a | ||
| 73 | |||
| 74 | RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix MINGW-FLAG %s | ||
| 75 | MINGW-FLAG: -lldmingw | ||
| 76 | |||
| 77 | RUN: ld.lld -### -m i386pep foo.o --export-all-symbols | FileCheck -check-prefix EXPORT-ALL %s | ||
| 78 | EXPORT-ALL: -export-all-symbols | ||
| 79 | |||
| 80 | RUN: ld.lld -### -m i386pep foo.o --output-def out.def | FileCheck -check-prefix OUTPUT-DEF %s | ||
| 81 | OUTPUT-DEF: -output-def:out.def | ||
| 82 | |||
| 83 | RUN: ld.lld -### -m i386pep foo.o -Xlink=-lldmap | FileCheck -check-prefix XLINK %s | ||
| 84 | XLINK: -lldmap | ||
| 85 | |||
| 86 | RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix DEBUG %s | ||
| 87 | DEBUG: -debug:dwarf | ||
| 88 | |||
| 89 | RUN: ld.lld -### -m i386pep foo.o -s | FileCheck -check-prefix STRIP %s | ||
| 90 | RUN: ld.lld -### -m i386pep foo.o --strip-all | FileCheck -check-prefix STRIP %s | ||
| 91 | STRIP-NOT: -debug:dwarf | ||
| 92 | |||
| 93 | RUN: ld.lld -### -m i386pep foo.o --large-address-aware | FileCheck -check-prefix LARGE-ADDRESS-AWARE %s | ||
| 94 | LARGE-ADDRESS-AWARE: -largeaddressaware | ||
| 95 | |||
| 96 | RUN: ld.lld -### -m i386pe foo.o | FileCheck -check-prefix DEFAULT-DISABLE-FLAGS %s | ||
| 97 | RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix DEFAULT-DISABLE-FLAGS %s | ||
| 98 | DEFAULT-DISABLE-FLAGS: -dynamicbase:no | ||
| 99 | RUN: ld.lld -### -m i386pe --dynamicbase foo.o | FileCheck -check-prefix NO-DEFAULT-DISABLE-FLAGS %s | ||
| 100 | RUN: ld.lld -### -m i386pep -dynamicbase foo.o | FileCheck -check-prefix NO-DEFAULT-DISABLE-FLAGS %s | ||
| 101 | RUN: ld.lld -### -m thumb2pe foo.o | FileCheck -check-prefix NO-DEFAULT-DISABLE-FLAGS %s | ||
| 102 | RUN: ld.lld -### -m arm64pe foo.o | FileCheck -check-prefix NO-DEFAULT-DISABLE-FLAGS %s | ||
| 103 | NO-DEFAULT-DISABLE-FLAGS-NOT: -dynamicbase:no | ||
| 104 | |||
| 105 | RUN: ld.lld -### -m i386pep foo.o --image-base 0x1230000 | FileCheck -check-prefix IMAGE-BASE %s | ||
| 106 | RUN: ld.lld -### -m i386pep foo.o -image-base 0x1230000 | FileCheck -check-prefix IMAGE-BASE %s | ||
| 107 | IMAGE-BASE: -base:0x1230000 | ||
| 108 | |||
| 109 | RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix NO-GC-SECTIONS %s | ||
| 110 | RUN: ld.lld -### -m i386pep foo.o --gc-sections --no-gc-sections | FileCheck -check-prefix NO-GC-SECTIONS %s | ||
| 111 | NO-GC-SECTIONS: -opt:noref | ||
| 112 | |||
| 113 | RUN: ld.lld -### -m i386pep foo.o --gc-sections | FileCheck -check-prefix GC-SECTIONS %s | ||
| 114 | RUN: ld.lld -### -m i386pep foo.o -gc-sections | FileCheck -check-prefix GC-SECTIONS %s | ||
| 115 | GC-SECTIONS: -opt:ref | ||
| 116 | |||
| 117 | RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix ICF-NONE %s | ||
| 118 | RUN: ld.lld -### -m i386pep foo.o --icf=none | FileCheck -check-prefix ICF-NONE %s | ||
| 119 | RUN: ld.lld -### -m i386pep foo.o -icf=none | FileCheck -check-prefix ICF-NONE %s | ||
| 120 | RUN: ld.lld -### -m i386pep foo.o --icf=safe | FileCheck -check-prefix ICF-NONE %s | ||
| 121 | RUN: ld.lld -### -m i386pep foo.o -icf=safe | FileCheck -check-prefix ICF-NONE %s | ||
| 122 | ICF-NONE: -opt:noicf | ||
| 123 | |||
| 124 | RUN: ld.lld -### -m i386pep foo.o --icf=all | FileCheck -check-prefix ICF %s | ||
| 125 | RUN: ld.lld -### -m i386pep foo.o -icf=all | FileCheck -check-prefix ICF %s | ||
| 126 | ICF: -opt:icf | ||
deps/lld/test/MinGW/lib.test created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | RUN: rm -rf %t/lib | ||
| 2 | RUN: mkdir -p %t/lib | ||
| 3 | RUN: not ld.lld -### -m i386pep -lfoo -L%t/lib 2>&1 | FileCheck -check-prefix=LIB1 %s | ||
| 4 | LIB1: unable to find library -lfoo | ||
| 5 | |||
| 6 | RUN: echo > %t/lib/libfoo.dll.a | ||
| 7 | RUN: ld.lld -### -m i386pep -lfoo -L%t/lib | FileCheck -check-prefix=LIB2 %s | ||
| 8 | LIB2: libfoo.dll.a | ||
| 9 | |||
| 10 | RUN: not ld.lld -### -m i386pep -Bstatic -lfoo -L%t/lib 2>&1 | FileCheck -check-prefix=LIB3 %s | ||
| 11 | LIB3: unable to find library -lfoo | ||
| 12 | |||
| 13 | RUN: echo > %t/lib/libfoo.a | ||
| 14 | RUN: ld.lld -### -m i386pep -Bstatic -lfoo -L%t/lib | FileCheck -check-prefix=LIB4 %s | ||
| 15 | LIB4: libfoo.a | ||
| 16 | |||
| 17 | RUN: echo > %t/lib/libbar.dll.a | ||
| 18 | RUN: echo > %t/lib/libbar.a | ||
| 19 | RUN: ld.lld -### -m i386pep -Bstatic -lfoo -Bdynamic -lbar -L%t/lib | FileCheck -check-prefix=LIB5 %s | ||
| 20 | LIB5: libfoo.a | ||
| 21 | LIB5-SAME: libbar.dll.a | ||
deps/lld/test/Unit/lit.cfg deleted-23| ... | @@ -1,23 +0,0 @@ | ||
| 1 | # -*- Python -*- | ||
| 2 | |||
| 3 | # Configuration file for the 'lit' test runner. | ||
| 4 | |||
| 5 | import os | ||
| 6 | |||
| 7 | import lit.formats | ||
| 8 | |||
| 9 | # name: The name of this test suite. | ||
| 10 | config.name = 'lld-Unit' | ||
| 11 | |||
| 12 | # suffixes: A list of file extensions to treat as test files. | ||
| 13 | config.suffixes = [] | ||
| 14 | |||
| 15 | # test_source_root: The root path where unit test binaries are located. | ||
| 16 | # test_exec_root: The root path where tests should be run. | ||
| 17 | config.test_source_root = os.path.join(config.lld_obj_root, 'unittests') | ||
| 18 | config.test_exec_root = config.test_source_root | ||
| 19 | |||
| 20 | # testFormat: The test format to use to interpret tests. | ||
| 21 | if not hasattr(config, 'llvm_build_mode'): | ||
| 22 | lit_config.fatal("unable to find llvm_build_mode value on config") | ||
| 23 | config.test_format = lit.formats.GoogleTest(config.llvm_build_mode, 'Tests') | ||
deps/lld/test/Unit/lit.cfg.py created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | # -*- Python -*- | ||
| 2 | |||
| 3 | # Configuration file for the 'lit' test runner. | ||
| 4 | |||
| 5 | import os | ||
| 6 | |||
| 7 | import lit.formats | ||
| 8 | |||
| 9 | # name: The name of this test suite. | ||
| 10 | config.name = 'lld-Unit' | ||
| 11 | |||
| 12 | # suffixes: A list of file extensions to treat as test files. | ||
| 13 | config.suffixes = [] | ||
| 14 | |||
| 15 | # test_source_root: The root path where unit test binaries are located. | ||
| 16 | # test_exec_root: The root path where tests should be run. | ||
| 17 | config.test_source_root = os.path.join(config.lld_obj_root, 'unittests') | ||
| 18 | config.test_exec_root = config.test_source_root | ||
| 19 | |||
| 20 | |||
| 21 | # Tweak the PATH to include the tools dir. | ||
| 22 | path = os.path.pathsep.join((config.lld_tools_dir, config.llvm_tools_dir, config.environment['PATH'])) | ||
| 23 | config.environment['PATH'] = path | ||
| 24 | |||
| 25 | path = os.path.pathsep.join((config.lld_libs_dir, config.llvm_libs_dir, | ||
| 26 | config.environment.get('LD_LIBRARY_PATH',''))) | ||
| 27 | config.environment['LD_LIBRARY_PATH'] = path | ||
| 28 | |||
| 29 | # Propagate LLVM_SRC_ROOT into the environment. | ||
| 30 | config.environment['LLVM_SRC_ROOT'] = config.llvm_src_root | ||
| 31 | |||
| 32 | # Propagate PYTHON_EXECUTABLE into the environment | ||
| 33 | config.environment['PYTHON_EXECUTABLE'] = sys.executable | ||
| 34 | |||
| 35 | |||
| 36 | # testFormat: The test format to use to interpret tests. | ||
| 37 | config.test_format = lit.formats.GoogleTest(config.llvm_build_mode, 'Tests') | ||
deps/lld/test/Unit/lit.site.cfg.in deleted-25| ... | @@ -1,25 +0,0 @@ | ||
| 1 | @LIT_SITE_CFG_IN_HEADER@ | ||
| 2 | |||
| 3 | config.llvm_src_root = "@LLVM_SOURCE_DIR@" | ||
| 4 | config.llvm_obj_root = "@LLVM_BINARY_DIR@" | ||
| 5 | config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" | ||
| 6 | config.llvm_libs_dir = "@LLVM_LIBS_DIR@" | ||
| 7 | config.llvm_build_mode = "@LLVM_BUILD_MODE@" | ||
| 8 | config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" | ||
| 9 | config.lld_obj_root = "@LLD_BINARY_DIR@" | ||
| 10 | config.lld_src_root = "@LLD_SOURCE_DIR@" | ||
| 11 | config.target_triple = "@TARGET_TRIPLE@" | ||
| 12 | config.python_executable = "@PYTHON_EXECUTABLE@" | ||
| 13 | |||
| 14 | # Support substitution of the tools and libs dirs with user parameters. This is | ||
| 15 | # used when we can't determine the tool dir at configuration time. | ||
| 16 | try: | ||
| 17 | config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params | ||
| 18 | config.llvm_libs_dir = config.llvm_libs_dir % lit_config.params | ||
| 19 | config.llvm_build_mode = config.llvm_build_mode % lit_config.params | ||
| 20 | except KeyError as e: | ||
| 21 | key, = e.args | ||
| 22 | lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) | ||
| 23 | |||
| 24 | # Let the main config do the real work. | ||
| 25 | lit_config.load_config(config, "@LLD_SOURCE_DIR@/test/Unit/lit.cfg") | ||
deps/lld/test/Unit/lit.site.cfg.py.in created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | @LIT_SITE_CFG_IN_HEADER@ | ||
| 2 | |||
| 3 | config.llvm_src_root = "@LLVM_SOURCE_DIR@" | ||
| 4 | config.llvm_obj_root = "@LLVM_BINARY_DIR@" | ||
| 5 | config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" | ||
| 6 | config.llvm_libs_dir = "@LLVM_LIBS_DIR@" | ||
| 7 | config.llvm_build_mode = "@LLVM_BUILD_MODE@" | ||
| 8 | config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" | ||
| 9 | config.lld_obj_root = "@LLD_BINARY_DIR@" | ||
| 10 | config.lld_src_root = "@LLD_SOURCE_DIR@" | ||
| 11 | config.lld_libs_dir = "@LLVM_LIBRARY_OUTPUT_INTDIR@" | ||
| 12 | config.lld_tools_dir = "@LLVM_RUNTIME_OUTPUT_INTDIR@" | ||
| 13 | config.target_triple = "@TARGET_TRIPLE@" | ||
| 14 | config.python_executable = "@PYTHON_EXECUTABLE@" | ||
| 15 | |||
| 16 | # Support substitution of the tools and libs dirs with user parameters. This is | ||
| 17 | # used when we can't determine the tool dir at configuration time. | ||
| 18 | try: | ||
| 19 | config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params | ||
| 20 | config.llvm_libs_dir = config.llvm_libs_dir % lit_config.params | ||
| 21 | config.llvm_build_mode = config.llvm_build_mode % lit_config.params | ||
| 22 | except KeyError as e: | ||
| 23 | key, = e.args | ||
| 24 | lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) | ||
| 25 | |||
| 26 | # Let the main config do the real work. | ||
| 27 | lit_config.load_config(config, "@LLD_SOURCE_DIR@/test/Unit/lit.cfg.py") | ||
deps/lld/test/lit.cfg deleted-270| ... | @@ -1,270 +0,0 @@ | ||
| 1 | # -*- Python -*- | ||
| 2 | |||
| 3 | import os | ||
| 4 | import platform | ||
| 5 | import re | ||
| 6 | import subprocess | ||
| 7 | import locale | ||
| 8 | |||
| 9 | import lit.formats | ||
| 10 | import lit.util | ||
| 11 | |||
| 12 | # Configuration file for the 'lit' test runner. | ||
| 13 | |||
| 14 | # name: The name of this test suite. | ||
| 15 | config.name = 'lld' | ||
| 16 | |||
| 17 | # Tweak PATH for Win32 | ||
| 18 | if sys.platform in ['win32']: | ||
| 19 | # Seek sane tools in directories and set to $PATH. | ||
| 20 | path = getattr(config, 'lit_tools_dir', None) | ||
| 21 | path = lit_config.getToolsPath(path, | ||
| 22 | config.environment['PATH'], | ||
| 23 | ['cmp.exe', 'grep.exe', 'sed.exe']) | ||
| 24 | if path is not None: | ||
| 25 | path = os.path.pathsep.join((path, | ||
| 26 | config.environment['PATH'])) | ||
| 27 | config.environment['PATH'] = path | ||
| 28 | |||
| 29 | # Choose between lit's internal shell pipeline runner and a real shell. If | ||
| 30 | # LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override. | ||
| 31 | use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") | ||
| 32 | if use_lit_shell: | ||
| 33 | # 0 is external, "" is default, and everything else is internal. | ||
| 34 | execute_external = (use_lit_shell == "0") | ||
| 35 | else: | ||
| 36 | # Otherwise we default to internal on Windows and external elsewhere, as | ||
| 37 | # bash on Windows is usually very slow. | ||
| 38 | execute_external = (not sys.platform in ['win32']) | ||
| 39 | |||
| 40 | |||
| 41 | # testFormat: The test format to use to interpret tests. | ||
| 42 | # | ||
| 43 | # For now we require '&&' between commands, until they get globally killed and | ||
| 44 | # the test runner updated. | ||
| 45 | config.test_format = lit.formats.ShTest(execute_external) | ||
| 46 | |||
| 47 | # suffixes: A list of file extensions to treat as test files. | ||
| 48 | config.suffixes = ['.ll', '.s', '.test', '.yaml', '.objtxt'] | ||
| 49 | |||
| 50 | # excludes: A list of directories to exclude from the testsuite. The 'Inputs' | ||
| 51 | # subdirectories contain auxiliary inputs for various tests in their parent | ||
| 52 | # directories. | ||
| 53 | config.excludes = ['Inputs'] | ||
| 54 | |||
| 55 | # test_source_root: The root path where tests are located. | ||
| 56 | config.test_source_root = os.path.dirname(__file__) | ||
| 57 | |||
| 58 | # test_exec_root: The root path where tests should be run. | ||
| 59 | lld_obj_root = getattr(config, 'lld_obj_root', None) | ||
| 60 | if lld_obj_root is not None: | ||
| 61 | config.test_exec_root = os.path.join(lld_obj_root, 'test') | ||
| 62 | |||
| 63 | # Set llvm_{src,obj}_root for use by others. | ||
| 64 | config.llvm_src_root = getattr(config, 'llvm_src_root', None) | ||
| 65 | config.llvm_obj_root = getattr(config, 'llvm_obj_root', None) | ||
| 66 | |||
| 67 | # Tweak the PATH to include the tools dir and the scripts dir. | ||
| 68 | if lld_obj_root is not None: | ||
| 69 | lld_tools_dir = getattr(config, 'lld_tools_dir', None) | ||
| 70 | if not lld_tools_dir: | ||
| 71 | lit_config.fatal('No LLD tools dir set!') | ||
| 72 | llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) | ||
| 73 | if not llvm_tools_dir: | ||
| 74 | lit_config.fatal('No LLVM tools dir set!') | ||
| 75 | path = os.path.pathsep.join((lld_tools_dir, llvm_tools_dir, config.environment['PATH'])) | ||
| 76 | path = os.path.pathsep.join((os.path.join(getattr(config, 'llvm_src_root', None),'test','Scripts'),path)) | ||
| 77 | |||
| 78 | config.environment['PATH'] = path | ||
| 79 | |||
| 80 | lld_libs_dir = getattr(config, 'lld_libs_dir', None) | ||
| 81 | if not lld_libs_dir: | ||
| 82 | lit_config.fatal('No LLD libs dir set!') | ||
| 83 | llvm_libs_dir = getattr(config, 'llvm_libs_dir', None) | ||
| 84 | if not llvm_libs_dir: | ||
| 85 | lit_config.fatal('No LLVM libs dir set!') | ||
| 86 | path = os.path.pathsep.join((lld_libs_dir, llvm_libs_dir, | ||
| 87 | config.environment.get('LD_LIBRARY_PATH',''))) | ||
| 88 | config.environment['LD_LIBRARY_PATH'] = path | ||
| 89 | |||
| 90 | # Propagate LLVM_SRC_ROOT into the environment. | ||
| 91 | config.environment['LLVM_SRC_ROOT'] = getattr(config, 'llvm_src_root', '') | ||
| 92 | |||
| 93 | # Propagate PYTHON_EXECUTABLE into the environment | ||
| 94 | config.environment['PYTHON_EXECUTABLE'] = getattr(config, 'python_executable', | ||
| 95 | '') | ||
| 96 | ### | ||
| 97 | |||
| 98 | # Check that the object root is known. | ||
| 99 | if config.test_exec_root is None: | ||
| 100 | # Otherwise, we haven't loaded the site specific configuration (the user is | ||
| 101 | # probably trying to run on a test file directly, and either the site | ||
| 102 | # configuration hasn't been created by the build system, or we are in an | ||
| 103 | # out-of-tree build situation). | ||
| 104 | |||
| 105 | # Check for 'lld_site_config' user parameter, and use that if available. | ||
| 106 | site_cfg = lit_config.params.get('lld_site_config', None) | ||
| 107 | if site_cfg and os.path.exists(site_cfg): | ||
| 108 | lit_config.load_config(config, site_cfg) | ||
| 109 | raise SystemExit | ||
| 110 | |||
| 111 | # Try to detect the situation where we are using an out-of-tree build by | ||
| 112 | # looking for 'llvm-config'. | ||
| 113 | # | ||
| 114 | # FIXME: I debated (i.e., wrote and threw away) adding logic to | ||
| 115 | # automagically generate the lit.site.cfg if we are in some kind of fresh | ||
| 116 | # build situation. This means knowing how to invoke the build system though, | ||
| 117 | # and I decided it was too much magic. We should solve this by just having | ||
| 118 | # the .cfg files generated during the configuration step. | ||
| 119 | |||
| 120 | llvm_config = lit.util.which('llvm-config', config.environment['PATH']) | ||
| 121 | if not llvm_config: | ||
| 122 | lit_config.fatal('No site specific configuration available!') | ||
| 123 | |||
| 124 | # Get the source and object roots. | ||
| 125 | llvm_src_root = subprocess.check_output(['llvm-config', '--src-root']).strip() | ||
| 126 | llvm_obj_root = subprocess.check_output(['llvm-config', '--obj-root']).strip() | ||
| 127 | lld_src_root = os.path.join(llvm_src_root, "tools", "lld") | ||
| 128 | lld_obj_root = os.path.join(llvm_obj_root, "tools", "lld") | ||
| 129 | |||
| 130 | # Validate that we got a tree which points to here, using the standard | ||
| 131 | # tools/lld layout. | ||
| 132 | this_src_root = os.path.dirname(config.test_source_root) | ||
| 133 | if os.path.realpath(lld_src_root) != os.path.realpath(this_src_root): | ||
| 134 | lit_config.fatal('No site specific configuration available!') | ||
| 135 | |||
| 136 | # Check that the site specific configuration exists. | ||
| 137 | site_cfg = os.path.join(lld_obj_root, 'test', 'lit.site.cfg') | ||
| 138 | if not os.path.exists(site_cfg): | ||
| 139 | lit_config.fatal( | ||
| 140 | 'No site specific configuration available! You may need to ' | ||
| 141 | 'run "make test" in your lld build directory.') | ||
| 142 | |||
| 143 | # Okay, that worked. Notify the user of the automagic, and reconfigure. | ||
| 144 | lit_config.note('using out-of-tree build at %r' % lld_obj_root) | ||
| 145 | lit_config.load_config(config, site_cfg) | ||
| 146 | raise SystemExit | ||
| 147 | |||
| 148 | # For each occurrence of a lld tool name as its own word, replace it | ||
| 149 | # with the full path to the build directory holding that tool. This | ||
| 150 | # ensures that we are testing the tools just built and not some random | ||
| 151 | # tools that might happen to be in the user's PATH. | ||
| 152 | |||
| 153 | # Regex assertions to reject neighbor hyphens/dots (seen in some tests). | ||
| 154 | # For example, we want to prefix 'lld' and 'ld.lld' but not the 'lld' inside | ||
| 155 | # of 'ld.lld'. | ||
| 156 | NoPreJunk = r"(?<!(-|\.|/))" | ||
| 157 | NoPostJunk = r"(?!(-|\.))" | ||
| 158 | |||
| 159 | config.substitutions.append( (r"\bld.lld\b", 'ld.lld --full-shutdown') ) | ||
| 160 | |||
| 161 | tool_patterns = [r"\bFileCheck\b", | ||
| 162 | r"\bnot\b", | ||
| 163 | NoPreJunk + r"\blld\b" + NoPostJunk, | ||
| 164 | r"\bld.lld\b", | ||
| 165 | r"\blld-link\b", | ||
| 166 | r"\bllvm-as\b", | ||
| 167 | r"\bllvm-mc\b", | ||
| 168 | r"\bllvm-nm\b", | ||
| 169 | r"\bllvm-objdump\b", | ||
| 170 | r"\bllvm-pdbutil\b", | ||
| 171 | r"\bllvm-readobj\b", | ||
| 172 | r"\bobj2yaml\b", | ||
| 173 | r"\byaml2obj\b"] | ||
| 174 | |||
| 175 | for pattern in tool_patterns: | ||
| 176 | # Extract the tool name from the pattern. This relies on the tool | ||
| 177 | # name being surrounded by \b word match operators. If the | ||
| 178 | # pattern starts with "| ", include it in the string to be | ||
| 179 | # substituted. | ||
| 180 | tool_match = re.match(r"^(\\)?((\| )?)\W+b([0-9A-Za-z-_\.]+)\\b\W*$", | ||
| 181 | pattern) | ||
| 182 | tool_pipe = tool_match.group(2) | ||
| 183 | tool_name = tool_match.group(4) | ||
| 184 | tool_path = lit.util.which(tool_name, config.environment['PATH']) | ||
| 185 | if not tool_path: | ||
| 186 | # Warn, but still provide a substitution. | ||
| 187 | lit_config.note('Did not find ' + tool_name + ' in ' + path) | ||
| 188 | tool_path = llvm_tools_dir + '/' + tool_name | ||
| 189 | config.substitutions.append((pattern, tool_pipe + tool_path)) | ||
| 190 | |||
| 191 | # Add site-specific substitutions. | ||
| 192 | config.substitutions.append( ('%python', config.python_executable) ) | ||
| 193 | |||
| 194 | ### | ||
| 195 | |||
| 196 | # When running under valgrind, we mangle '-vg' onto the end of the triple so we | ||
| 197 | # can check it with XFAIL and XTARGET. | ||
| 198 | if lit_config.useValgrind: | ||
| 199 | config.target_triple += '-vg' | ||
| 200 | |||
| 201 | # Shell execution | ||
| 202 | if execute_external: | ||
| 203 | config.available_features.add('shell') | ||
| 204 | |||
| 205 | # zlib compression library | ||
| 206 | if config.have_zlib: | ||
| 207 | config.available_features.add("zlib") | ||
| 208 | |||
| 209 | # Running on Darwin OS | ||
| 210 | if platform.system() in ['Darwin']: | ||
| 211 | config.available_features.add('system-linker-mach-o') | ||
| 212 | |||
| 213 | # Running on ELF based *nix | ||
| 214 | if platform.system() in ['FreeBSD', 'Linux']: | ||
| 215 | config.available_features.add('system-linker-elf') | ||
| 216 | |||
| 217 | # Running on Windows | ||
| 218 | if platform.system() in ['Windows']: | ||
| 219 | config.available_features.add('system-windows') | ||
| 220 | |||
| 221 | # Set if host-cxxabi's demangler can handle target's symbols. | ||
| 222 | if platform.system() not in ['Windows']: | ||
| 223 | config.available_features.add('demangler') | ||
| 224 | |||
| 225 | # llvm-config knows whether it is compiled with asserts (and) | ||
| 226 | # whether we are operating in release/debug mode. | ||
| 227 | import subprocess | ||
| 228 | try: | ||
| 229 | llvm_config_cmd = \ | ||
| 230 | subprocess.Popen([os.path.join(llvm_tools_dir, 'llvm-config'), | ||
| 231 | '--build-mode', '--assertion-mode', '--targets-built'], | ||
| 232 | stdout = subprocess.PIPE) | ||
| 233 | except OSError as why: | ||
| 234 | print("Could not find llvm-config in " + llvm_tools_dir) | ||
| 235 | exit(42) | ||
| 236 | |||
| 237 | llvm_config_output = llvm_config_cmd.stdout.read().decode('utf_8') | ||
| 238 | llvm_config_output_list = llvm_config_output.split("\n") | ||
| 239 | |||
| 240 | if re.search(r'DEBUG', llvm_config_output_list[0]): | ||
| 241 | config.available_features.add('debug') | ||
| 242 | if re.search(r'ON', llvm_config_output_list[1]): | ||
| 243 | config.available_features.add('asserts') | ||
| 244 | |||
| 245 | archs = llvm_config_output_list[2] | ||
| 246 | if re.search(r'AArch64', archs): | ||
| 247 | config.available_features.add('aarch64') | ||
| 248 | if re.search(r'AMDGPU', archs): | ||
| 249 | config.available_features.add('amdgpu') | ||
| 250 | if re.search(r'ARM', archs): | ||
| 251 | config.available_features.add('arm') | ||
| 252 | if re.search(r'AVR', archs): | ||
| 253 | config.available_features.add('avr') | ||
| 254 | if re.search(r'Mips', archs): | ||
| 255 | config.available_features.add('mips') | ||
| 256 | if re.search(r'PowerPC', archs): | ||
| 257 | config.available_features.add('ppc') | ||
| 258 | if re.search(r'Sparc', archs): | ||
| 259 | config.available_features.add('sparc') | ||
| 260 | if re.search(r'X86', archs): | ||
| 261 | config.available_features.add('x86') | ||
| 262 | llvm_config_cmd.wait() | ||
| 263 | |||
| 264 | # Set a fake constant version so that we get consitent output. | ||
| 265 | config.environment['LLD_VERSION'] = 'LLD 1.0' | ||
| 266 | |||
| 267 | # Indirectly check if the mt.exe Microsoft utility exists by searching for | ||
| 268 | # cvtres, which always accompanies it. | ||
| 269 | if lit.util.which('cvtres', config.environment['PATH']): | ||
| 270 | config.available_features.add('win_mt') | ||
deps/lld/test/lit.cfg.py created+93| ... | @@ -0,0 +1,93 @@ | ||
| 1 | # -*- Python -*- | ||
| 2 | |||
| 3 | import os | ||
| 4 | import platform | ||
| 5 | import re | ||
| 6 | import subprocess | ||
| 7 | import locale | ||
| 8 | |||
| 9 | import lit.formats | ||
| 10 | import lit.util | ||
| 11 | |||
| 12 | from lit.llvm import llvm_config | ||
| 13 | |||
| 14 | # Configuration file for the 'lit' test runner. | ||
| 15 | |||
| 16 | # name: The name of this test suite. | ||
| 17 | config.name = 'lld' | ||
| 18 | |||
| 19 | # testFormat: The test format to use to interpret tests. | ||
| 20 | # | ||
| 21 | # For now we require '&&' between commands, until they get globally killed and | ||
| 22 | # the test runner updated. | ||
| 23 | config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) | ||
| 24 | |||
| 25 | # suffixes: A list of file extensions to treat as test files. | ||
| 26 | config.suffixes = ['.ll', '.s', '.test', '.yaml', '.objtxt'] | ||
| 27 | |||
| 28 | # excludes: A list of directories to exclude from the testsuite. The 'Inputs' | ||
| 29 | # subdirectories contain auxiliary inputs for various tests in their parent | ||
| 30 | # directories. | ||
| 31 | config.excludes = ['Inputs'] | ||
| 32 | |||
| 33 | # test_source_root: The root path where tests are located. | ||
| 34 | config.test_source_root = os.path.dirname(__file__) | ||
| 35 | |||
| 36 | config.test_exec_root = os.path.join(config.lld_obj_root, 'test') | ||
| 37 | |||
| 38 | llvm_config.use_default_substitutions() | ||
| 39 | llvm_config.use_lld() | ||
| 40 | |||
| 41 | tool_patterns = [ | ||
| 42 | 'llc', 'llvm-as', 'llvm-mc', 'llvm-nm', | ||
| 43 | 'llvm-objdump', 'llvm-pdbutil', 'llvm-readobj', 'obj2yaml', 'yaml2obj'] | ||
| 44 | |||
| 45 | llvm_config.add_tool_substitutions(tool_patterns) | ||
| 46 | |||
| 47 | # When running under valgrind, we mangle '-vg' onto the end of the triple so we | ||
| 48 | # can check it with XFAIL and XTARGET. | ||
| 49 | if lit_config.useValgrind: | ||
| 50 | config.target_triple += '-vg' | ||
| 51 | |||
| 52 | # Running on ELF based *nix | ||
| 53 | if platform.system() in ['FreeBSD', 'Linux']: | ||
| 54 | config.available_features.add('system-linker-elf') | ||
| 55 | |||
| 56 | # Set if host-cxxabi's demangler can handle target's symbols. | ||
| 57 | if platform.system() not in ['Windows']: | ||
| 58 | config.available_features.add('demangler') | ||
| 59 | |||
| 60 | llvm_config.feature_config( | ||
| 61 | [('--build-mode', {'DEBUG': 'debug'}), | ||
| 62 | ('--assertion-mode', {'ON': 'asserts'}), | ||
| 63 | ('--targets-built', {'AArch64': 'aarch64', | ||
| 64 | 'AMDGPU': 'amdgpu', | ||
| 65 | 'ARM': 'arm', | ||
| 66 | 'AVR': 'avr', | ||
| 67 | 'Mips': 'mips', | ||
| 68 | 'PowerPC': 'ppc', | ||
| 69 | 'Sparc': 'sparc', | ||
| 70 | 'WebAssembly': 'wasm', | ||
| 71 | 'X86': 'x86'}) | ||
| 72 | ]) | ||
| 73 | |||
| 74 | # Set a fake constant version so that we get consitent output. | ||
| 75 | config.environment['LLD_VERSION'] = 'LLD 1.0' | ||
| 76 | |||
| 77 | # Indirectly check if the mt.exe Microsoft utility exists by searching for | ||
| 78 | # cvtres, which always accompanies it. Alternatively, check if we can use | ||
| 79 | # libxml2 to merge manifests. | ||
| 80 | if (lit.util.which('cvtres', config.environment['PATH'])) or \ | ||
| 81 | (config.llvm_libxml2_enabled == '1'): | ||
| 82 | config.available_features.add('manifest_tool') | ||
| 83 | |||
| 84 | if (config.llvm_libxml2_enabled == '1'): | ||
| 85 | config.available_features.add('libxml2') | ||
| 86 | |||
| 87 | tar_executable = lit.util.which('tar', config.environment['PATH']) | ||
| 88 | if tar_executable: | ||
| 89 | tar_version = subprocess.Popen( | ||
| 90 | [tar_executable, '--version'], stdout=subprocess.PIPE, env={'LANG': 'C'}) | ||
| 91 | if 'GNU tar' in tar_version.stdout.read().decode(): | ||
| 92 | config.available_features.add('gnutar') | ||
| 93 | tar_version.wait() | ||
deps/lld/test/lit.site.cfg.in deleted-25| ... | @@ -1,25 +0,0 @@ | ||
| 1 | @LIT_SITE_CFG_IN_HEADER@ | ||
| 2 | |||
| 3 | config.llvm_src_root = "@LLVM_SOURCE_DIR@" | ||
| 4 | config.llvm_obj_root = "@LLVM_BINARY_DIR@" | ||
| 5 | config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" | ||
| 6 | config.llvm_libs_dir = "@LLVM_LIBS_DIR@" | ||
| 7 | config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" | ||
| 8 | config.lld_obj_root = "@LLD_BINARY_DIR@" | ||
| 9 | config.lld_libs_dir = "@LLVM_LIBRARY_OUTPUT_INTDIR@" | ||
| 10 | config.lld_tools_dir = "@LLVM_RUNTIME_OUTPUT_INTDIR@" | ||
| 11 | config.target_triple = "@TARGET_TRIPLE@" | ||
| 12 | config.python_executable = "@PYTHON_EXECUTABLE@" | ||
| 13 | config.have_zlib = @HAVE_LIBZ@ | ||
| 14 | |||
| 15 | # Support substitution of the tools and libs dirs with user parameters. This is | ||
| 16 | # used when we can't determine the tool dir at configuration time. | ||
| 17 | try: | ||
| 18 | config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params | ||
| 19 | config.llvm_libs_dir = config.llvm_libs_dir % lit_config.params | ||
| 20 | except KeyError as e: | ||
| 21 | key, = e.args | ||
| 22 | lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) | ||
| 23 | |||
| 24 | # Let the main config do the real work. | ||
| 25 | lit_config.load_config(config, "@LLD_SOURCE_DIR@/test/lit.cfg") | ||
deps/lld/test/lit.site.cfg.py.in created+28| ... | @@ -0,0 +1,28 @@ | ||
| 1 | @LIT_SITE_CFG_IN_HEADER@ | ||
| 2 | |||
| 3 | config.llvm_src_root = "@LLVM_SOURCE_DIR@" | ||
| 4 | config.llvm_obj_root = "@LLVM_BINARY_DIR@" | ||
| 5 | config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" | ||
| 6 | config.llvm_libs_dir = "@LLVM_LIBS_DIR@" | ||
| 7 | config.llvm_libxml2_enabled = "@LLVM_LIBXML2_ENABLED@" | ||
| 8 | config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" | ||
| 9 | config.lld_obj_root = "@LLD_BINARY_DIR@" | ||
| 10 | config.lld_libs_dir = "@LLVM_LIBRARY_OUTPUT_INTDIR@" | ||
| 11 | config.lld_tools_dir = "@LLVM_RUNTIME_OUTPUT_INTDIR@" | ||
| 12 | config.target_triple = "@TARGET_TRIPLE@" | ||
| 13 | config.python_executable = "@PYTHON_EXECUTABLE@" | ||
| 14 | config.have_zlib = @HAVE_LIBZ@ | ||
| 15 | |||
| 16 | # Support substitution of the tools and libs dirs with user parameters. This is | ||
| 17 | # used when we can't determine the tool dir at configuration time. | ||
| 18 | try: | ||
| 19 | config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params | ||
| 20 | config.llvm_libs_dir = config.llvm_libs_dir % lit_config.params | ||
| 21 | except KeyError as e: | ||
| 22 | key, = e.args | ||
| 23 | lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) | ||
| 24 | |||
| 25 | @LIT_SITE_CFG_IN_FOOTER@ | ||
| 26 | |||
| 27 | # Let the main config do the real work. | ||
| 28 | lit_config.load_config(config, "@LLD_SOURCE_DIR@/test/lit.cfg.py") | ||
deps/lld/test/wasm/Inputs/archive1.ll created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | declare i32 @bar() local_unnamed_addr #1 | ||
| 2 | |||
| 3 | define i32 @foo() local_unnamed_addr #0 { | ||
| 4 | entry: | ||
| 5 | %call = tail call i32 @bar() #2 | ||
| 6 | ret i32 %call | ||
| 7 | } | ||
deps/lld/test/wasm/Inputs/archive2.ll created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | declare i32 @foo() local_unnamed_addr #1 | ||
| 2 | |||
| 3 | define i32 @bar() local_unnamed_addr #0 { | ||
| 4 | entry: | ||
| 5 | %call = tail call i32 @foo() #2 | ||
| 6 | ret i32 %call | ||
| 7 | } | ||
deps/lld/test/wasm/Inputs/call-indirect.ll created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | @indirect_bar = internal local_unnamed_addr global i32 ()* @bar, align 4 | ||
| 2 | @indirect_foo = internal local_unnamed_addr global i32 ()* @foo, align 4 | ||
| 3 | |||
| 4 | declare i32 @foo() local_unnamed_addr | ||
| 5 | |||
| 6 | define i32 @bar() { | ||
| 7 | entry: | ||
| 8 | ret i32 1 | ||
| 9 | } | ||
| 10 | |||
| 11 | define void @call_bar_indirect() local_unnamed_addr #1 { | ||
| 12 | entry: | ||
| 13 | %0 = load i32 ()*, i32 ()** @indirect_bar, align 4 | ||
| 14 | %1 = load i32 ()*, i32 ()** @indirect_foo, align 4 | ||
| 15 | %call = tail call i32 %0() #2 | ||
| 16 | ret void | ||
| 17 | } | ||
deps/lld/test/wasm/Inputs/global-ctor-dtor.ll created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | define hidden void @myctor() { | ||
| 2 | entry: | ||
| 3 | ret void | ||
| 4 | } | ||
| 5 | |||
| 6 | define hidden void @mydtor() { | ||
| 7 | entry: | ||
| 8 | %ptr = alloca i32 | ||
| 9 | ret void | ||
| 10 | } | ||
| 11 | |||
| 12 | @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @myctor, i8* null }] | ||
| 13 | |||
| 14 | @llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @mydtor, i8* null }] | ||
deps/lld/test/wasm/Inputs/hello.ll created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | ; Wasm module generated from the following C code: | ||
| 2 | ; void puts(const char*); | ||
| 3 | ; void hello() { puts("hello\n"); } | ||
| 4 | |||
| 5 | @hello_str = unnamed_addr constant [7 x i8] c"hello\0A\00", align 1 | ||
| 6 | |||
| 7 | ; Function Attrs: nounwind | ||
| 8 | define hidden void @hello() local_unnamed_addr #0 { | ||
| 9 | entry: | ||
| 10 | tail call void @puts(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @hello_str, i32 0, i32 0)) | ||
| 11 | ret void | ||
| 12 | } | ||
| 13 | |||
| 14 | ; Function Attrs: nounwind | ||
| 15 | declare void @puts(i8* nocapture readonly) local_unnamed_addr #1 | ||
deps/lld/test/wasm/Inputs/hidden.ll created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | ; Function Attrs: norecurse nounwind readnone | ||
| 2 | define hidden i32 @archiveHidden() #0 { | ||
| 3 | entry: | ||
| 4 | ret i32 0 | ||
| 5 | } | ||
| 6 | |||
| 7 | ; Function Attrs: norecurse nounwind readnone | ||
| 8 | define i32 @archiveDefault() #1 { | ||
| 9 | entry: | ||
| 10 | ret i32 0 | ||
| 11 | } | ||
deps/lld/test/wasm/Inputs/many-funcs.ll created+776| ... | @@ -0,0 +1,776 @@ | ||
| 1 | @g0 = global i32 1, align 4 | ||
| 2 | @foo = global i32 1, align 4 | ||
| 3 | |||
| 4 | define i32 @f1() { | ||
| 5 | entry: | ||
| 6 | %0 = load i32, i32* @foo, align 4 | ||
| 7 | ret i32 %0 | ||
| 8 | } | ||
| 9 | |||
| 10 | define i32 @f2() { | ||
| 11 | entry: | ||
| 12 | %0 = load i32, i32* @foo, align 4 | ||
| 13 | ret i32 %0 | ||
| 14 | } | ||
| 15 | |||
| 16 | define i32 @f3() { | ||
| 17 | entry: | ||
| 18 | %0 = load i32, i32* @foo, align 4 | ||
| 19 | ret i32 %0 | ||
| 20 | } | ||
| 21 | |||
| 22 | define i32 @f4() { | ||
| 23 | entry: | ||
| 24 | %0 = load i32, i32* @foo, align 4 | ||
| 25 | ret i32 %0 | ||
| 26 | } | ||
| 27 | |||
| 28 | define i32 @f5() { | ||
| 29 | entry: | ||
| 30 | %0 = load i32, i32* @foo, align 4 | ||
| 31 | ret i32 %0 | ||
| 32 | } | ||
| 33 | |||
| 34 | define i32 @f6() { | ||
| 35 | entry: | ||
| 36 | %0 = load i32, i32* @foo, align 4 | ||
| 37 | ret i32 %0 | ||
| 38 | } | ||
| 39 | |||
| 40 | define i32 @f7() { | ||
| 41 | entry: | ||
| 42 | %0 = load i32, i32* @foo, align 4 | ||
| 43 | ret i32 %0 | ||
| 44 | } | ||
| 45 | |||
| 46 | define i32 @f8() { | ||
| 47 | entry: | ||
| 48 | %0 = load i32, i32* @foo, align 4 | ||
| 49 | ret i32 %0 | ||
| 50 | } | ||
| 51 | |||
| 52 | define i32 @f9() { | ||
| 53 | entry: | ||
| 54 | %0 = load i32, i32* @foo, align 4 | ||
| 55 | ret i32 %0 | ||
| 56 | } | ||
| 57 | |||
| 58 | define i32 @f10() { | ||
| 59 | entry: | ||
| 60 | %0 = load i32, i32* @foo, align 4 | ||
| 61 | ret i32 %0 | ||
| 62 | } | ||
| 63 | |||
| 64 | define i32 @f11() { | ||
| 65 | entry: | ||
| 66 | %0 = load i32, i32* @foo, align 4 | ||
| 67 | ret i32 %0 | ||
| 68 | } | ||
| 69 | |||
| 70 | define i32 @f12() { | ||
| 71 | entry: | ||
| 72 | %0 = load i32, i32* @foo, align 4 | ||
| 73 | ret i32 %0 | ||
| 74 | } | ||
| 75 | |||
| 76 | define i32 @f13() { | ||
| 77 | entry: | ||
| 78 | %0 = load i32, i32* @foo, align 4 | ||
| 79 | ret i32 %0 | ||
| 80 | } | ||
| 81 | |||
| 82 | define i32 @f14() { | ||
| 83 | entry: | ||
| 84 | %0 = load i32, i32* @foo, align 4 | ||
| 85 | ret i32 %0 | ||
| 86 | } | ||
| 87 | |||
| 88 | define i32 @f15() { | ||
| 89 | entry: | ||
| 90 | %0 = load i32, i32* @foo, align 4 | ||
| 91 | ret i32 %0 | ||
| 92 | } | ||
| 93 | |||
| 94 | define i32 @f16() { | ||
| 95 | entry: | ||
| 96 | %0 = load i32, i32* @foo, align 4 | ||
| 97 | ret i32 %0 | ||
| 98 | } | ||
| 99 | |||
| 100 | define i32 @f17() { | ||
| 101 | entry: | ||
| 102 | %0 = load i32, i32* @foo, align 4 | ||
| 103 | ret i32 %0 | ||
| 104 | } | ||
| 105 | |||
| 106 | define i32 @f18() { | ||
| 107 | entry: | ||
| 108 | %0 = load i32, i32* @foo, align 4 | ||
| 109 | ret i32 %0 | ||
| 110 | } | ||
| 111 | |||
| 112 | define i32 @f19() { | ||
| 113 | entry: | ||
| 114 | %0 = load i32, i32* @foo, align 4 | ||
| 115 | ret i32 %0 | ||
| 116 | } | ||
| 117 | |||
| 118 | define i32 @f20() { | ||
| 119 | entry: | ||
| 120 | %0 = load i32, i32* @foo, align 4 | ||
| 121 | ret i32 %0 | ||
| 122 | } | ||
| 123 | |||
| 124 | define i32 @f21() { | ||
| 125 | entry: | ||
| 126 | %0 = load i32, i32* @foo, align 4 | ||
| 127 | ret i32 %0 | ||
| 128 | } | ||
| 129 | |||
| 130 | define i32 @f22() { | ||
| 131 | entry: | ||
| 132 | %0 = load i32, i32* @foo, align 4 | ||
| 133 | ret i32 %0 | ||
| 134 | } | ||
| 135 | |||
| 136 | define i32 @f23() { | ||
| 137 | entry: | ||
| 138 | %0 = load i32, i32* @foo, align 4 | ||
| 139 | ret i32 %0 | ||
| 140 | } | ||
| 141 | |||
| 142 | define i32 @f24() { | ||
| 143 | entry: | ||
| 144 | %0 = load i32, i32* @foo, align 4 | ||
| 145 | ret i32 %0 | ||
| 146 | } | ||
| 147 | |||
| 148 | define i32 @f25() { | ||
| 149 | entry: | ||
| 150 | %0 = load i32, i32* @foo, align 4 | ||
| 151 | ret i32 %0 | ||
| 152 | } | ||
| 153 | |||
| 154 | define i32 @f26() { | ||
| 155 | entry: | ||
| 156 | %0 = load i32, i32* @foo, align 4 | ||
| 157 | ret i32 %0 | ||
| 158 | } | ||
| 159 | |||
| 160 | define i32 @f27() { | ||
| 161 | entry: | ||
| 162 | %0 = load i32, i32* @foo, align 4 | ||
| 163 | ret i32 %0 | ||
| 164 | } | ||
| 165 | |||
| 166 | define i32 @f28() { | ||
| 167 | entry: | ||
| 168 | %0 = load i32, i32* @foo, align 4 | ||
| 169 | ret i32 %0 | ||
| 170 | } | ||
| 171 | |||
| 172 | define i32 @f29() { | ||
| 173 | entry: | ||
| 174 | %0 = load i32, i32* @foo, align 4 | ||
| 175 | ret i32 %0 | ||
| 176 | } | ||
| 177 | |||
| 178 | define i32 @f30() { | ||
| 179 | entry: | ||
| 180 | %0 = load i32, i32* @foo, align 4 | ||
| 181 | ret i32 %0 | ||
| 182 | } | ||
| 183 | |||
| 184 | define i32 @f31() { | ||
| 185 | entry: | ||
| 186 | %0 = load i32, i32* @foo, align 4 | ||
| 187 | ret i32 %0 | ||
| 188 | } | ||
| 189 | |||
| 190 | define i32 @f32() { | ||
| 191 | entry: | ||
| 192 | %0 = load i32, i32* @foo, align 4 | ||
| 193 | ret i32 %0 | ||
| 194 | } | ||
| 195 | |||
| 196 | define i32 @f33() { | ||
| 197 | entry: | ||
| 198 | %0 = load i32, i32* @foo, align 4 | ||
| 199 | ret i32 %0 | ||
| 200 | } | ||
| 201 | |||
| 202 | define i32 @f34() { | ||
| 203 | entry: | ||
| 204 | %0 = load i32, i32* @foo, align 4 | ||
| 205 | ret i32 %0 | ||
| 206 | } | ||
| 207 | |||
| 208 | define i32 @f35() { | ||
| 209 | entry: | ||
| 210 | %0 = load i32, i32* @foo, align 4 | ||
| 211 | ret i32 %0 | ||
| 212 | } | ||
| 213 | |||
| 214 | define i32 @f36() { | ||
| 215 | entry: | ||
| 216 | %0 = load i32, i32* @foo, align 4 | ||
| 217 | ret i32 %0 | ||
| 218 | } | ||
| 219 | |||
| 220 | define i32 @f37() { | ||
| 221 | entry: | ||
| 222 | %0 = load i32, i32* @foo, align 4 | ||
| 223 | ret i32 %0 | ||
| 224 | } | ||
| 225 | |||
| 226 | define i32 @f38() { | ||
| 227 | entry: | ||
| 228 | %0 = load i32, i32* @foo, align 4 | ||
| 229 | ret i32 %0 | ||
| 230 | } | ||
| 231 | |||
| 232 | define i32 @f39() { | ||
| 233 | entry: | ||
| 234 | %0 = load i32, i32* @foo, align 4 | ||
| 235 | ret i32 %0 | ||
| 236 | } | ||
| 237 | |||
| 238 | define i32 @f40() { | ||
| 239 | entry: | ||
| 240 | %0 = load i32, i32* @foo, align 4 | ||
| 241 | ret i32 %0 | ||
| 242 | } | ||
| 243 | |||
| 244 | define i32 @f41() { | ||
| 245 | entry: | ||
| 246 | %0 = load i32, i32* @foo, align 4 | ||
| 247 | ret i32 %0 | ||
| 248 | } | ||
| 249 | |||
| 250 | define i32 @f42() { | ||
| 251 | entry: | ||
| 252 | %0 = load i32, i32* @foo, align 4 | ||
| 253 | ret i32 %0 | ||
| 254 | } | ||
| 255 | |||
| 256 | define i32 @f43() { | ||
| 257 | entry: | ||
| 258 | %0 = load i32, i32* @foo, align 4 | ||
| 259 | ret i32 %0 | ||
| 260 | } | ||
| 261 | |||
| 262 | define i32 @f44() { | ||
| 263 | entry: | ||
| 264 | %0 = load i32, i32* @foo, align 4 | ||
| 265 | ret i32 %0 | ||
| 266 | } | ||
| 267 | |||
| 268 | define i32 @f45() { | ||
| 269 | entry: | ||
| 270 | %0 = load i32, i32* @foo, align 4 | ||
| 271 | ret i32 %0 | ||
| 272 | } | ||
| 273 | |||
| 274 | define i32 @f46() { | ||
| 275 | entry: | ||
| 276 | %0 = load i32, i32* @foo, align 4 | ||
| 277 | ret i32 %0 | ||
| 278 | } | ||
| 279 | |||
| 280 | define i32 @f47() { | ||
| 281 | entry: | ||
| 282 | %0 = load i32, i32* @foo, align 4 | ||
| 283 | ret i32 %0 | ||
| 284 | } | ||
| 285 | |||
| 286 | define i32 @f48() { | ||
| 287 | entry: | ||
| 288 | %0 = load i32, i32* @foo, align 4 | ||
| 289 | ret i32 %0 | ||
| 290 | } | ||
| 291 | |||
| 292 | define i32 @f49() { | ||
| 293 | entry: | ||
| 294 | %0 = load i32, i32* @foo, align 4 | ||
| 295 | ret i32 %0 | ||
| 296 | } | ||
| 297 | |||
| 298 | define i32 @f50() { | ||
| 299 | entry: | ||
| 300 | %0 = load i32, i32* @foo, align 4 | ||
| 301 | ret i32 %0 | ||
| 302 | } | ||
| 303 | |||
| 304 | define i32 @f51() { | ||
| 305 | entry: | ||
| 306 | %0 = load i32, i32* @foo, align 4 | ||
| 307 | ret i32 %0 | ||
| 308 | } | ||
| 309 | |||
| 310 | define i32 @f52() { | ||
| 311 | entry: | ||
| 312 | %0 = load i32, i32* @foo, align 4 | ||
| 313 | ret i32 %0 | ||
| 314 | } | ||
| 315 | |||
| 316 | define i32 @f53() { | ||
| 317 | entry: | ||
| 318 | %0 = load i32, i32* @foo, align 4 | ||
| 319 | ret i32 %0 | ||
| 320 | } | ||
| 321 | |||
| 322 | define i32 @f54() { | ||
| 323 | entry: | ||
| 324 | %0 = load i32, i32* @foo, align 4 | ||
| 325 | ret i32 %0 | ||
| 326 | } | ||
| 327 | |||
| 328 | define i32 @f55() { | ||
| 329 | entry: | ||
| 330 | %0 = load i32, i32* @foo, align 4 | ||
| 331 | ret i32 %0 | ||
| 332 | } | ||
| 333 | |||
| 334 | define i32 @f56() { | ||
| 335 | entry: | ||
| 336 | %0 = load i32, i32* @foo, align 4 | ||
| 337 | ret i32 %0 | ||
| 338 | } | ||
| 339 | |||
| 340 | define i32 @f57() { | ||
| 341 | entry: | ||
| 342 | %0 = load i32, i32* @foo, align 4 | ||
| 343 | ret i32 %0 | ||
| 344 | } | ||
| 345 | |||
| 346 | define i32 @f58() { | ||
| 347 | entry: | ||
| 348 | %0 = load i32, i32* @foo, align 4 | ||
| 349 | ret i32 %0 | ||
| 350 | } | ||
| 351 | |||
| 352 | define i32 @f59() { | ||
| 353 | entry: | ||
| 354 | %0 = load i32, i32* @foo, align 4 | ||
| 355 | ret i32 %0 | ||
| 356 | } | ||
| 357 | |||
| 358 | define i32 @f60() { | ||
| 359 | entry: | ||
| 360 | %0 = load i32, i32* @foo, align 4 | ||
| 361 | ret i32 %0 | ||
| 362 | } | ||
| 363 | |||
| 364 | define i32 @f61() { | ||
| 365 | entry: | ||
| 366 | %0 = load i32, i32* @foo, align 4 | ||
| 367 | ret i32 %0 | ||
| 368 | } | ||
| 369 | |||
| 370 | define i32 @f62() { | ||
| 371 | entry: | ||
| 372 | %0 = load i32, i32* @foo, align 4 | ||
| 373 | ret i32 %0 | ||
| 374 | } | ||
| 375 | |||
| 376 | define i32 @f63() { | ||
| 377 | entry: | ||
| 378 | %0 = load i32, i32* @foo, align 4 | ||
| 379 | ret i32 %0 | ||
| 380 | } | ||
| 381 | |||
| 382 | define i32 @f64() { | ||
| 383 | entry: | ||
| 384 | %0 = load i32, i32* @foo, align 4 | ||
| 385 | ret i32 %0 | ||
| 386 | } | ||
| 387 | |||
| 388 | define i32 @f65() { | ||
| 389 | entry: | ||
| 390 | %0 = load i32, i32* @foo, align 4 | ||
| 391 | ret i32 %0 | ||
| 392 | } | ||
| 393 | |||
| 394 | define i32 @f66() { | ||
| 395 | entry: | ||
| 396 | %0 = load i32, i32* @foo, align 4 | ||
| 397 | ret i32 %0 | ||
| 398 | } | ||
| 399 | |||
| 400 | define i32 @f67() { | ||
| 401 | entry: | ||
| 402 | %0 = load i32, i32* @foo, align 4 | ||
| 403 | ret i32 %0 | ||
| 404 | } | ||
| 405 | |||
| 406 | define i32 @f68() { | ||
| 407 | entry: | ||
| 408 | %0 = load i32, i32* @foo, align 4 | ||
| 409 | ret i32 %0 | ||
| 410 | } | ||
| 411 | |||
| 412 | define i32 @f69() { | ||
| 413 | entry: | ||
| 414 | %0 = load i32, i32* @foo, align 4 | ||
| 415 | ret i32 %0 | ||
| 416 | } | ||
| 417 | |||
| 418 | define i32 @f70() { | ||
| 419 | entry: | ||
| 420 | %0 = load i32, i32* @foo, align 4 | ||
| 421 | ret i32 %0 | ||
| 422 | } | ||
| 423 | |||
| 424 | define i32 @f71() { | ||
| 425 | entry: | ||
| 426 | %0 = load i32, i32* @foo, align 4 | ||
| 427 | ret i32 %0 | ||
| 428 | } | ||
| 429 | |||
| 430 | define i32 @f72() { | ||
| 431 | entry: | ||
| 432 | %0 = load i32, i32* @foo, align 4 | ||
| 433 | ret i32 %0 | ||
| 434 | } | ||
| 435 | |||
| 436 | define i32 @f73() { | ||
| 437 | entry: | ||
| 438 | %0 = load i32, i32* @foo, align 4 | ||
| 439 | ret i32 %0 | ||
| 440 | } | ||
| 441 | |||
| 442 | define i32 @f74() { | ||
| 443 | entry: | ||
| 444 | %0 = load i32, i32* @foo, align 4 | ||
| 445 | ret i32 %0 | ||
| 446 | } | ||
| 447 | |||
| 448 | define i32 @f75() { | ||
| 449 | entry: | ||
| 450 | %0 = load i32, i32* @foo, align 4 | ||
| 451 | ret i32 %0 | ||
| 452 | } | ||
| 453 | |||
| 454 | define i32 @f76() { | ||
| 455 | entry: | ||
| 456 | %0 = load i32, i32* @foo, align 4 | ||
| 457 | ret i32 %0 | ||
| 458 | } | ||
| 459 | |||
| 460 | define i32 @f77() { | ||
| 461 | entry: | ||
| 462 | %0 = load i32, i32* @foo, align 4 | ||
| 463 | ret i32 %0 | ||
| 464 | } | ||
| 465 | |||
| 466 | define i32 @f78() { | ||
| 467 | entry: | ||
| 468 | %0 = load i32, i32* @foo, align 4 | ||
| 469 | ret i32 %0 | ||
| 470 | } | ||
| 471 | |||
| 472 | define i32 @f79() { | ||
| 473 | entry: | ||
| 474 | %0 = load i32, i32* @foo, align 4 | ||
| 475 | ret i32 %0 | ||
| 476 | } | ||
| 477 | |||
| 478 | define i32 @f80() { | ||
| 479 | entry: | ||
| 480 | %0 = load i32, i32* @foo, align 4 | ||
| 481 | ret i32 %0 | ||
| 482 | } | ||
| 483 | |||
| 484 | define i32 @f81() { | ||
| 485 | entry: | ||
| 486 | %0 = load i32, i32* @foo, align 4 | ||
| 487 | ret i32 %0 | ||
| 488 | } | ||
| 489 | |||
| 490 | define i32 @f82() { | ||
| 491 | entry: | ||
| 492 | %0 = load i32, i32* @foo, align 4 | ||
| 493 | ret i32 %0 | ||
| 494 | } | ||
| 495 | |||
| 496 | define i32 @f83() { | ||
| 497 | entry: | ||
| 498 | %0 = load i32, i32* @foo, align 4 | ||
| 499 | ret i32 %0 | ||
| 500 | } | ||
| 501 | |||
| 502 | define i32 @f84() { | ||
| 503 | entry: | ||
| 504 | %0 = load i32, i32* @foo, align 4 | ||
| 505 | ret i32 %0 | ||
| 506 | } | ||
| 507 | |||
| 508 | define i32 @f85() { | ||
| 509 | entry: | ||
| 510 | %0 = load i32, i32* @foo, align 4 | ||
| 511 | ret i32 %0 | ||
| 512 | } | ||
| 513 | |||
| 514 | define i32 @f86() { | ||
| 515 | entry: | ||
| 516 | %0 = load i32, i32* @foo, align 4 | ||
| 517 | ret i32 %0 | ||
| 518 | } | ||
| 519 | |||
| 520 | define i32 @f87() { | ||
| 521 | entry: | ||
| 522 | %0 = load i32, i32* @foo, align 4 | ||
| 523 | ret i32 %0 | ||
| 524 | } | ||
| 525 | |||
| 526 | define i32 @f88() { | ||
| 527 | entry: | ||
| 528 | %0 = load i32, i32* @foo, align 4 | ||
| 529 | ret i32 %0 | ||
| 530 | } | ||
| 531 | |||
| 532 | define i32 @f89() { | ||
| 533 | entry: | ||
| 534 | %0 = load i32, i32* @foo, align 4 | ||
| 535 | ret i32 %0 | ||
| 536 | } | ||
| 537 | |||
| 538 | define i32 @f90() { | ||
| 539 | entry: | ||
| 540 | %0 = load i32, i32* @foo, align 4 | ||
| 541 | ret i32 %0 | ||
| 542 | } | ||
| 543 | |||
| 544 | define i32 @f91() { | ||
| 545 | entry: | ||
| 546 | %0 = load i32, i32* @foo, align 4 | ||
| 547 | ret i32 %0 | ||
| 548 | } | ||
| 549 | |||
| 550 | define i32 @f92() { | ||
| 551 | entry: | ||
| 552 | %0 = load i32, i32* @foo, align 4 | ||
| 553 | ret i32 %0 | ||
| 554 | } | ||
| 555 | |||
| 556 | define i32 @f93() { | ||
| 557 | entry: | ||
| 558 | %0 = load i32, i32* @foo, align 4 | ||
| 559 | ret i32 %0 | ||
| 560 | } | ||
| 561 | |||
| 562 | define i32 @f94() { | ||
| 563 | entry: | ||
| 564 | %0 = load i32, i32* @foo, align 4 | ||
| 565 | ret i32 %0 | ||
| 566 | } | ||
| 567 | |||
| 568 | define i32 @f95() { | ||
| 569 | entry: | ||
| 570 | %0 = load i32, i32* @foo, align 4 | ||
| 571 | ret i32 %0 | ||
| 572 | } | ||
| 573 | |||
| 574 | define i32 @f96() { | ||
| 575 | entry: | ||
| 576 | %0 = load i32, i32* @foo, align 4 | ||
| 577 | ret i32 %0 | ||
| 578 | } | ||
| 579 | |||
| 580 | define i32 @f97() { | ||
| 581 | entry: | ||
| 582 | %0 = load i32, i32* @foo, align 4 | ||
| 583 | ret i32 %0 | ||
| 584 | } | ||
| 585 | |||
| 586 | define i32 @f98() { | ||
| 587 | entry: | ||
| 588 | %0 = load i32, i32* @foo, align 4 | ||
| 589 | ret i32 %0 | ||
| 590 | } | ||
| 591 | |||
| 592 | define i32 @f99() { | ||
| 593 | entry: | ||
| 594 | %0 = load i32, i32* @foo, align 4 | ||
| 595 | ret i32 %0 | ||
| 596 | } | ||
| 597 | |||
| 598 | define i32 @f100() { | ||
| 599 | entry: | ||
| 600 | %0 = load i32, i32* @foo, align 4 | ||
| 601 | ret i32 %0 | ||
| 602 | } | ||
| 603 | |||
| 604 | define i32 @f101() { | ||
| 605 | entry: | ||
| 606 | %0 = load i32, i32* @foo, align 4 | ||
| 607 | ret i32 %0 | ||
| 608 | } | ||
| 609 | |||
| 610 | define i32 @f102() { | ||
| 611 | entry: | ||
| 612 | %0 = load i32, i32* @foo, align 4 | ||
| 613 | ret i32 %0 | ||
| 614 | } | ||
| 615 | |||
| 616 | define i32 @f103() { | ||
| 617 | entry: | ||
| 618 | %0 = load i32, i32* @foo, align 4 | ||
| 619 | ret i32 %0 | ||
| 620 | } | ||
| 621 | |||
| 622 | define i32 @f104() { | ||
| 623 | entry: | ||
| 624 | %0 = load i32, i32* @foo, align 4 | ||
| 625 | ret i32 %0 | ||
| 626 | } | ||
| 627 | |||
| 628 | define i32 @f105() { | ||
| 629 | entry: | ||
| 630 | %0 = load i32, i32* @foo, align 4 | ||
| 631 | ret i32 %0 | ||
| 632 | } | ||
| 633 | |||
| 634 | define i32 @f106() { | ||
| 635 | entry: | ||
| 636 | %0 = load i32, i32* @foo, align 4 | ||
| 637 | ret i32 %0 | ||
| 638 | } | ||
| 639 | |||
| 640 | define i32 @f107() { | ||
| 641 | entry: | ||
| 642 | %0 = load i32, i32* @foo, align 4 | ||
| 643 | ret i32 %0 | ||
| 644 | } | ||
| 645 | |||
| 646 | define i32 @f108() { | ||
| 647 | entry: | ||
| 648 | %0 = load i32, i32* @foo, align 4 | ||
| 649 | ret i32 %0 | ||
| 650 | } | ||
| 651 | |||
| 652 | define i32 @f109() { | ||
| 653 | entry: | ||
| 654 | %0 = load i32, i32* @foo, align 4 | ||
| 655 | ret i32 %0 | ||
| 656 | } | ||
| 657 | |||
| 658 | define i32 @f110() { | ||
| 659 | entry: | ||
| 660 | %0 = load i32, i32* @foo, align 4 | ||
| 661 | ret i32 %0 | ||
| 662 | } | ||
| 663 | |||
| 664 | define i32 @f111() { | ||
| 665 | entry: | ||
| 666 | %0 = load i32, i32* @foo, align 4 | ||
| 667 | ret i32 %0 | ||
| 668 | } | ||
| 669 | |||
| 670 | define i32 @f112() { | ||
| 671 | entry: | ||
| 672 | %0 = load i32, i32* @foo, align 4 | ||
| 673 | ret i32 %0 | ||
| 674 | } | ||
| 675 | |||
| 676 | define i32 @f113() { | ||
| 677 | entry: | ||
| 678 | %0 = load i32, i32* @foo, align 4 | ||
| 679 | ret i32 %0 | ||
| 680 | } | ||
| 681 | |||
| 682 | define i32 @f114() { | ||
| 683 | entry: | ||
| 684 | %0 = load i32, i32* @foo, align 4 | ||
| 685 | ret i32 %0 | ||
| 686 | } | ||
| 687 | |||
| 688 | define i32 @f115() { | ||
| 689 | entry: | ||
| 690 | %0 = load i32, i32* @foo, align 4 | ||
| 691 | ret i32 %0 | ||
| 692 | } | ||
| 693 | |||
| 694 | define i32 @f116() { | ||
| 695 | entry: | ||
| 696 | %0 = load i32, i32* @foo, align 4 | ||
| 697 | ret i32 %0 | ||
| 698 | } | ||
| 699 | |||
| 700 | define i32 @f117() { | ||
| 701 | entry: | ||
| 702 | %0 = load i32, i32* @foo, align 4 | ||
| 703 | ret i32 %0 | ||
| 704 | } | ||
| 705 | |||
| 706 | define i32 @f118() { | ||
| 707 | entry: | ||
| 708 | %0 = load i32, i32* @foo, align 4 | ||
| 709 | ret i32 %0 | ||
| 710 | } | ||
| 711 | |||
| 712 | define i32 @f119() { | ||
| 713 | entry: | ||
| 714 | %0 = load i32, i32* @foo, align 4 | ||
| 715 | ret i32 %0 | ||
| 716 | } | ||
| 717 | |||
| 718 | define i32 @f120() { | ||
| 719 | entry: | ||
| 720 | %0 = load i32, i32* @foo, align 4 | ||
| 721 | ret i32 %0 | ||
| 722 | } | ||
| 723 | |||
| 724 | define i32 @f121() { | ||
| 725 | entry: | ||
| 726 | %0 = load i32, i32* @foo, align 4 | ||
| 727 | ret i32 %0 | ||
| 728 | } | ||
| 729 | |||
| 730 | define i32 @f122() { | ||
| 731 | entry: | ||
| 732 | %0 = load i32, i32* @foo, align 4 | ||
| 733 | ret i32 %0 | ||
| 734 | } | ||
| 735 | |||
| 736 | define i32 @f123() { | ||
| 737 | entry: | ||
| 738 | %0 = load i32, i32* @foo, align 4 | ||
| 739 | ret i32 %0 | ||
| 740 | } | ||
| 741 | |||
| 742 | define i32 @f124() { | ||
| 743 | entry: | ||
| 744 | %0 = load i32, i32* @foo, align 4 | ||
| 745 | ret i32 %0 | ||
| 746 | } | ||
| 747 | |||
| 748 | define i32 @f125() { | ||
| 749 | entry: | ||
| 750 | %0 = load i32, i32* @foo, align 4 | ||
| 751 | ret i32 %0 | ||
| 752 | } | ||
| 753 | |||
| 754 | define i32 @f126() { | ||
| 755 | entry: | ||
| 756 | %0 = load i32, i32* @foo, align 4 | ||
| 757 | ret i32 %0 | ||
| 758 | } | ||
| 759 | |||
| 760 | define i32 @f127() { | ||
| 761 | entry: | ||
| 762 | %0 = load i32, i32* @foo, align 4 | ||
| 763 | ret i32 %0 | ||
| 764 | } | ||
| 765 | |||
| 766 | define i32 @f128() { | ||
| 767 | entry: | ||
| 768 | %0 = load i32, i32* @g0, align 4 | ||
| 769 | ret i32 %0 | ||
| 770 | } | ||
| 771 | |||
| 772 | define i32 @f129() { | ||
| 773 | entry: | ||
| 774 | %0 = load i32, i32* @g0, align 4 | ||
| 775 | ret i32 %0 | ||
| 776 | } | ||
deps/lld/test/wasm/Inputs/ret32.ll created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | ; Function Attrs: norecurse nounwind readnone | ||
| 2 | define i32 @ret32(float %arg) #0 { | ||
| 3 | entry: | ||
| 4 | ret i32 0 | ||
| 5 | ; ptrtoint (i32 (float)* @ret32 to i32) | ||
| 6 | } | ||
deps/lld/test/wasm/Inputs/ret64.ll created+4| ... | @@ -0,0 +1,4 @@ | ||
| 1 | define i64 @ret64(double %arg) local_unnamed_addr #0 { | ||
| 2 | entry: | ||
| 3 | ret i64 1 | ||
| 4 | } | ||
deps/lld/test/wasm/Inputs/weak-alias.ll created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | ; Function Attrs: norecurse nounwind readnone | ||
| 2 | define i32 @direct_fn() #0 { | ||
| 3 | entry: | ||
| 4 | ret i32 0 | ||
| 5 | } | ||
| 6 | |||
| 7 | @alias_fn = weak alias i32 (), i32 ()* @direct_fn | ||
| 8 | |||
| 9 | define i32 @call_direct() #0 { | ||
| 10 | entry: | ||
| 11 | %call = call i32 @direct_fn() | ||
| 12 | ret i32 %call | ||
| 13 | } | ||
| 14 | |||
| 15 | define i32 @call_alias() #0 { | ||
| 16 | entry: | ||
| 17 | %call = call i32 @alias_fn() | ||
| 18 | ret i32 %call | ||
| 19 | } | ||
| 20 | |||
| 21 | define i32 @call_alias_ptr() #0 { | ||
| 22 | entry: | ||
| 23 | %fnptr = alloca i32 ()*, align 8 | ||
| 24 | store i32 ()* @alias_fn, i32 ()** %fnptr, align 8 | ||
| 25 | %0 = load i32 ()*, i32 ()** %fnptr, align 8 | ||
| 26 | %call = call i32 %0() | ||
| 27 | ret i32 %call | ||
| 28 | } | ||
| 29 | |||
| 30 | define i32 @call_direct_ptr() #0 { | ||
| 31 | entry: | ||
| 32 | %fnptr = alloca i32 ()*, align 8 | ||
| 33 | store i32 ()* @direct_fn, i32 ()** %fnptr, align 8 | ||
| 34 | %0 = load i32 ()*, i32 ()** %fnptr, align 8 | ||
| 35 | %call = call i32 %0() | ||
| 36 | ret i32 %call | ||
| 37 | } | ||
deps/lld/test/wasm/Inputs/weak-symbol1.ll created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | define weak i32 @weakFn() #0 { | ||
| 2 | entry: | ||
| 3 | ret i32 1 | ||
| 4 | } | ||
| 5 | |||
| 6 | define i32 @exportWeak1() { | ||
| 7 | entry: | ||
| 8 | ret i32 ptrtoint (i32 ()* @weakFn to i32) | ||
| 9 | } | ||
| 10 | |||
| 11 | @weakGlobal = weak global i32 1 | ||
deps/lld/test/wasm/Inputs/weak-symbol2.ll created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | define weak i32 @weakFn() #0 { | ||
| 2 | entry: | ||
| 3 | ret i32 2 | ||
| 4 | } | ||
| 5 | |||
| 6 | define i32 @exportWeak2() { | ||
| 7 | entry: | ||
| 8 | ret i32 ptrtoint (i32 ()* @weakFn to i32) | ||
| 9 | } | ||
| 10 | |||
| 11 | @weakGlobal = weak global i32 2 | ||
deps/lld/test/wasm/archive.ll created+31| ... | @@ -0,0 +1,31 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/archive1.ll -o %t.a1.o | ||
| 3 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/archive2.ll -o %t.a2.o | ||
| 4 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/hello.ll -o %t.a3.o | ||
| 5 | ; RUN: llvm-ar rcs %t.a %t.a1.o %t.a2.o %t.a3.o | ||
| 6 | ; RUN: lld -flavor wasm %t.a %t.o -o %t.wasm | ||
| 7 | ; RUN: llvm-nm -a %t.wasm | FileCheck %s | ||
| 8 | |||
| 9 | declare i32 @foo() local_unnamed_addr #1 | ||
| 10 | |||
| 11 | define i32 @_start() local_unnamed_addr #0 { | ||
| 12 | entry: | ||
| 13 | %call = tail call i32 @foo() #2 | ||
| 14 | ret i32 %call | ||
| 15 | } | ||
| 16 | |||
| 17 | ; Verify that multually dependant object files in an archive is handled | ||
| 18 | ; correctly. | ||
| 19 | |||
| 20 | ; CHECK: 00000002 T _start | ||
| 21 | ; CHECK-NEXT: 00000002 T _start | ||
| 22 | ; CHECK-NEXT: 00000000 T bar | ||
| 23 | ; CHECK-NEXT: 00000000 T bar | ||
| 24 | ; CHECK-NEXT: 00000001 T foo | ||
| 25 | ; CHECK-NEXT: 00000001 T foo | ||
| 26 | |||
| 27 | ; Verify that symbols from unused objects don't appear in the symbol table | ||
| 28 | ; CHECK-NOT: hello | ||
| 29 | |||
| 30 | ; Specifying the same archive twice is allowed. | ||
| 31 | ; RUN: lld -flavor wasm %t.a %t.a %t.o -o %t.wasm | ||
deps/lld/test/wasm/call-indirect.ll created+132| ... | @@ -0,0 +1,132 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/call-indirect.ll -o %t2.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 3 | ; RUN: lld -flavor wasm -o %t.wasm %t2.o %t.o | ||
| 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | ; bitcode generated from the following C code: | ||
| 7 | ; int foo(void) { return 1; } | ||
| 8 | ; int (*indirect_func)(void) = &foo; | ||
| 9 | ; void _start(void) { indirect_func(); } | ||
| 10 | |||
| 11 | @indirect_func = local_unnamed_addr global i32 ()* @foo, align 4 | ||
| 12 | |||
| 13 | ; Function Attrs: norecurse nounwind readnone | ||
| 14 | define i32 @foo() #0 { | ||
| 15 | entry: | ||
| 16 | ret i32 2 | ||
| 17 | } | ||
| 18 | |||
| 19 | ; Function Attrs: nounwind | ||
| 20 | define i32 @_start() local_unnamed_addr #1 { | ||
| 21 | entry: | ||
| 22 | %0 = load i32 ()*, i32 ()** @indirect_func, align 4 | ||
| 23 | %call = call i32 %0() #2 | ||
| 24 | ret i32 0 | ||
| 25 | } | ||
| 26 | |||
| 27 | ; Indirect function call where no function actually has this type. | ||
| 28 | ; Ensures that the type entry is still created in this case. | ||
| 29 | define void @call_ptr(i64 (i64)* %arg) { | ||
| 30 | %1 = call i64 %arg(i64 1) | ||
| 31 | ret void | ||
| 32 | } | ||
| 33 | |||
| 34 | ; CHECK: !WASM | ||
| 35 | ; CHECK-NEXT: FileHeader: | ||
| 36 | ; CHECK-NEXT: Version: 0x00000001 | ||
| 37 | ; CHECK-NEXT: Sections: | ||
| 38 | ; CHECK-NEXT: - Type: TYPE | ||
| 39 | ; CHECK-NEXT: Signatures: | ||
| 40 | ; CHECK-NEXT: - Index: 0 | ||
| 41 | ; CHECK-NEXT: ReturnType: I32 | ||
| 42 | ; CHECK-NEXT: ParamTypes: | ||
| 43 | ; CHECK-NEXT: - Index: 1 | ||
| 44 | ; CHECK-NEXT: ReturnType: NORESULT | ||
| 45 | ; CHECK-NEXT: ParamTypes: | ||
| 46 | ; CHECK-NEXT: - Index: 2 | ||
| 47 | ; CHECK-NEXT: ReturnType: NORESULT | ||
| 48 | ; CHECK-NEXT: ParamTypes: | ||
| 49 | ; CHECK-NEXT: - I32 | ||
| 50 | ; CHECK-NEXT: - Index: 3 | ||
| 51 | ; CHECK-NEXT: ReturnType: I64 | ||
| 52 | ; CHECK-NEXT: ParamTypes: | ||
| 53 | ; CHECK-NEXT: - I64 | ||
| 54 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 55 | ; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 2 ] | ||
| 56 | ; CHECK-NEXT: - Type: TABLE | ||
| 57 | ; CHECK-NEXT: Tables: | ||
| 58 | ; CHECK-NEXT: - ElemType: ANYFUNC | ||
| 59 | ; CHECK-NEXT: Limits: | ||
| 60 | ; CHECK-NEXT: Flags: [ HAS_MAX ] | ||
| 61 | ; CHECK-NEXT: Initial: 0x00000003 | ||
| 62 | ; CHECK-NEXT: Maximum: 0x00000003 | ||
| 63 | ; CHECK-NEXT: - Type: MEMORY | ||
| 64 | ; CHECK-NEXT: Memories: | ||
| 65 | ; CHECK-NEXT: - Initial: 0x00000002 | ||
| 66 | ; CHECK-NEXT: - Type: GLOBAL | ||
| 67 | ; CHECK-NEXT: Globals: | ||
| 68 | ; CHECK-NEXT: - Type: I32 | ||
| 69 | ; CHECK-NEXT: Mutable: true | ||
| 70 | ; CHECK-NEXT: InitExpr: | ||
| 71 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 72 | ; CHECK-NEXT: Value: 66576 | ||
| 73 | ; CHECK-NEXT: - Type: EXPORT | ||
| 74 | ; CHECK-NEXT: Exports: | ||
| 75 | ; CHECK-NEXT: - Name: memory | ||
| 76 | ; CHECK-NEXT: Kind: MEMORY | ||
| 77 | ; CHECK-NEXT: Index: 0 | ||
| 78 | ; CHECK-NEXT: - Name: _start | ||
| 79 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 80 | ; CHECK-NEXT: Index: 3 | ||
| 81 | ; CHECK-NEXT: - Name: foo | ||
| 82 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 83 | ; CHECK-NEXT: Index: 2 | ||
| 84 | ; CHECK-NEXT: - Name: bar | ||
| 85 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 86 | ; CHECK-NEXT: Index: 0 | ||
| 87 | ; CHECK-NEXT: - Name: call_bar_indirect | ||
| 88 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 89 | ; CHECK-NEXT: Index: 1 | ||
| 90 | ; CHECK-NEXT: - Name: call_ptr | ||
| 91 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 92 | ; CHECK-NEXT: Index: 4 | ||
| 93 | ; CHECK-NEXT: - Type: ELEM | ||
| 94 | ; CHECK-NEXT: Segments: | ||
| 95 | ; CHECK-NEXT: - Offset: | ||
| 96 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 97 | ; CHECK-NEXT: Value: 1 | ||
| 98 | ; CHECK-NEXT: Functions: [ 0, 2 ] | ||
| 99 | ; CHECK-NEXT: - Type: CODE | ||
| 100 | ; CHECK-NEXT: Functions: | ||
| 101 | ; CHECK-NEXT: - Locals: | ||
| 102 | ; CHECK-NEXT: Body: 41010B | ||
| 103 | ; CHECK-NEXT: - Locals: | ||
| 104 | ; CHECK-NEXT: Body: 410028028088808000118080808000001A0B | ||
| 105 | ; CHECK-NEXT: - Locals: | ||
| 106 | ; CHECK-NEXT: Body: 41020B | ||
| 107 | ; CHECK-NEXT: - Locals: | ||
| 108 | ; CHECK-NEXT: Body: 410028028888808000118080808000001A41000B | ||
| 109 | ; CHECK-NEXT: - Locals: | ||
| 110 | ; CHECK-NEXT: Body: 42012000118380808000001A0B | ||
| 111 | ; CHECK-NEXT: - Type: DATA | ||
| 112 | ; CHECK-NEXT: Segments: | ||
| 113 | ; CHECK-NEXT: - SectionOffset: 7 | ||
| 114 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 115 | ; CHECK-NEXT: Offset: | ||
| 116 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 117 | ; CHECK-NEXT: Value: 1024 | ||
| 118 | ; CHECK-NEXT: Content: '010000000200000002000000' | ||
| 119 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 120 | ; CHECK-NEXT: Name: linking | ||
| 121 | ; CHECK-NEXT: DataSize: 12 | ||
| 122 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 123 | ; CHECK-NEXT: Name: name | ||
| 124 | ; CHECK-NEXT: FunctionNames: | ||
| 125 | ; CHECK-NEXT: - Index: 0 | ||
| 126 | ; CHECK-NEXT: Name: bar | ||
| 127 | ; CHECK-NEXT: - Index: 1 | ||
| 128 | ; CHECK-NEXT: Name: call_bar_indirect | ||
| 129 | ; CHECK-NEXT: - Index: 2 | ||
| 130 | ; CHECK-NEXT: Name: foo | ||
| 131 | ; CHECK-NEXT: - Index: 3 | ||
| 132 | ; CHECK-NEXT: Name: _start | ||
deps/lld/test/wasm/conflict.test created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | # RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 2 | # RUN: not lld -flavor wasm -o %t.wasm %t.ret32.o %t.ret32.o 2>&1 | FileCheck %s | ||
| 3 | |||
| 4 | # CHECK: duplicate symbol: ret32 | ||
| 5 | # CHECK-NEXT: >>> defined in {{.*}}conflict.test.tmp.ret32.o | ||
| 6 | # CHECK-NEXT: >>> defined in {{.*}}conflict.test.tmp.ret32.o | ||
deps/lld/test/wasm/data-layout.ll created+61| ... | @@ -0,0 +1,61 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/hello.ll -o %t.hello.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 3 | ; RUN: lld -flavor wasm --emit-relocs --allow-undefined --no-entry -o %t.wasm %t.o %t.hello.o | ||
| 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | @foo = hidden global i32 1, align 4 | ||
| 7 | @aligned_bar = hidden global i32 3, align 16 | ||
| 8 | |||
| 9 | @hello_str = external global i8* | ||
| 10 | @external_ref = global i8** @hello_str, align 8 | ||
| 11 | |||
| 12 | ; CHECK: - Type: GLOBAL | ||
| 13 | ; CHECK-NEXT: Globals: | ||
| 14 | ; CHECK-NEXT: - Type: I32 | ||
| 15 | ; CHECK-NEXT: Mutable: true | ||
| 16 | ; CHECK-NEXT: InitExpr: | ||
| 17 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 18 | ; CHECK-NEXT: Value: 66608 | ||
| 19 | ; CHECK-NEXT: - Type: I32 | ||
| 20 | ; CHECK-NEXT: Mutable: false | ||
| 21 | ; CHECK-NEXT: InitExpr: | ||
| 22 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 23 | ; CHECK-NEXT: Value: 1024 | ||
| 24 | ; CHECK-NEXT: - Type: I32 | ||
| 25 | ; CHECK-NEXT: Mutable: false | ||
| 26 | ; CHECK-NEXT: InitExpr: | ||
| 27 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 28 | ; CHECK-NEXT: Value: 1040 | ||
| 29 | ; CHECK-NEXT: - Type: I32 | ||
| 30 | ; CHECK-NEXT: Mutable: false | ||
| 31 | ; CHECK-NEXT: InitExpr: | ||
| 32 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 33 | ; CHECK-NEXT: Value: 1048 | ||
| 34 | ; CHECK-NEXT: - Type: I32 | ||
| 35 | ; CHECK-NEXT: Mutable: false | ||
| 36 | ; CHECK-NEXT: InitExpr: | ||
| 37 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 38 | ; CHECK-NEXT: Value: 1052 | ||
| 39 | |||
| 40 | ; CHECK: - Type: DATA | ||
| 41 | ; CHECK-NEXT: Relocations: | ||
| 42 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 | ||
| 43 | ; CHECK-NEXT: Index: 4 | ||
| 44 | ; CHECK-NEXT: Offset: 0x0000001F | ||
| 45 | ; CHECK-NEXT: Segments: | ||
| 46 | ; CHECK-NEXT: - SectionOffset: 7 | ||
| 47 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 48 | ; CHECK-NEXT: Offset: | ||
| 49 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 50 | ; CHECK-NEXT: Value: 1024 | ||
| 51 | ; CHECK-NEXT: Content: 0100000000000000000000000000000003000000000000001C040000 | ||
| 52 | ; CHECK-NEXT: - SectionOffset: 41 | ||
| 53 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 54 | ; CHECK-NEXT: Offset: | ||
| 55 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 56 | ; CHECK-NEXT: Value: 1052 | ||
| 57 | ; CHECK-NEXT: Content: 68656C6C6F0A00 | ||
| 58 | |||
| 59 | ; CHECK: - Type: CUSTOM | ||
| 60 | ; CHECK-NEXT: Name: linking | ||
| 61 | ; CHECK-NEXT: DataSize: 35 | ||
deps/lld/test/wasm/entry.ll created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 2 | ; RUN: lld -flavor wasm -e entry -o %t.wasm %t.o | ||
| 3 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 4 | ; RUN: lld -flavor wasm --entry=entry -o %t.wasm %t.o | ||
| 5 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 6 | |||
| 7 | define void @entry() local_unnamed_addr #0 { | ||
| 8 | entry: | ||
| 9 | ret void | ||
| 10 | } | ||
| 11 | |||
| 12 | ; CHECK: - Type: EXPORT | ||
| 13 | ; CHECK: Exports: | ||
| 14 | ; CHECK: - Name: memory | ||
| 15 | ; CHECK: Kind: MEMORY | ||
| 16 | ; CHECK: Index: 0 | ||
| 17 | ; CHECK: - Name: entry | ||
| 18 | ; CHECK: Kind: FUNCTION | ||
| 19 | ; CHECK: Index: 0 | ||
deps/lld/test/wasm/function-imports-first.ll created+42| ... | @@ -0,0 +1,42 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 3 | ; RUN: lld -flavor wasm -o %t.wasm %t.o %t.ret32.o | ||
| 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | ; Function Attrs: nounwind | ||
| 7 | define hidden void @_start() local_unnamed_addr #0 { | ||
| 8 | entry: | ||
| 9 | %call = tail call i32 @ret32(float 0.000000e+00) #2 | ||
| 10 | ret void | ||
| 11 | } | ||
| 12 | |||
| 13 | declare i32 @ret32(float) local_unnamed_addr #1 | ||
| 14 | |||
| 15 | ; CHECK: - Type: TYPE | ||
| 16 | ; CHECK: Signatures: | ||
| 17 | ; CHECK-NEXT: - Index: 0 | ||
| 18 | ; CHECK-NEXT: ReturnType: NORESULT | ||
| 19 | ; CHECK-NEXT: ParamTypes: | ||
| 20 | ; CHECK-NEXT: - Index: 1 | ||
| 21 | ; CHECK-NEXT: ReturnType: I32 | ||
| 22 | ; CHECK-NEXT: ParamTypes: | ||
| 23 | ; CHECK-NEXT: - F32 | ||
| 24 | ; CHECK: - Type: FUNCTION | ||
| 25 | ; CHECK-NEXT: FunctionTypes: [ 0, 1 ] | ||
| 26 | ; CHECK: - Type: CODE | ||
| 27 | ; CHECK-NEXT: Functions: | ||
| 28 | ; CHECK-NEXT: - Locals: | ||
| 29 | ; CHECK-NEXT: Body: 43000000001081808080001A0B | ||
| 30 | ; CHECK-NEXT: - Locals: | ||
| 31 | ; CHECK-NEXT: Body: 41000B | ||
| 32 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 33 | ; CHECK-NEXT: Name: linking | ||
| 34 | ; CHECK-NEXT: DataSize: 0 | ||
| 35 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 36 | ; CHECK-NEXT: Name: name | ||
| 37 | ; CHECK-NEXT: FunctionNames: | ||
| 38 | ; CHECK-NEXT: - Index: 0 | ||
| 39 | ; CHECK-NEXT: Name: _start | ||
| 40 | ; CHECK-NEXT: - Index: 1 | ||
| 41 | ; CHECK-NEXT: Name: ret32 | ||
| 42 | ; CHECK-NEXT: ... | ||
deps/lld/test/wasm/function-imports.ll created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 3 | ; RUN: lld -flavor wasm -o %t.wasm %t.ret32.o %t.o | ||
| 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | ; Function Attrs: nounwind | ||
| 7 | define hidden void @_start() local_unnamed_addr #0 { | ||
| 8 | entry: | ||
| 9 | %call = tail call i32 @ret32(float 0.000000e+00) #2 | ||
| 10 | ret void | ||
| 11 | } | ||
| 12 | |||
| 13 | declare i32 @ret32(float) local_unnamed_addr #1 | ||
| 14 | |||
| 15 | ; CHECK: Sections: | ||
| 16 | ; CHECK: - Type: TYPE | ||
| 17 | ; CHECK-NEXT: Signatures: | ||
| 18 | ; CHECK-NEXT: - Index: 0 | ||
| 19 | ; CHECK-NEXT: ReturnType: I32 | ||
| 20 | ; CHECK-NEXT: ParamTypes: | ||
| 21 | ; CHECK-NEXT: - F32 | ||
| 22 | ; CHECK-NEXT: - Index: 1 | ||
| 23 | ; CHECK-NEXT: ReturnType: NORESULT | ||
| 24 | ; CHECK-NEXT: ParamTypes: | ||
| 25 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 26 | ; CHECK-NEXT: FunctionTypes: [ 0, 1 ] | ||
| 27 | ; CHECK: - Type: CODE | ||
| 28 | ; CHECK-NEXT: Functions: | ||
| 29 | ; CHECK: - Locals: | ||
| 30 | ; CHECK: - Locals: | ||
| 31 | ; CHECK: Name: name | ||
| 32 | ; CHECK-NEXT: FunctionNames: | ||
| 33 | ; CHECK-NEXT: - Index: 0 | ||
| 34 | ; CHECK-NEXT: Name: ret32 | ||
| 35 | ; CHECK-NEXT: - Index: 1 | ||
| 36 | ; CHECK-NEXT: Name: _start | ||
| 37 | ; CHECK-NEXT: ... | ||
deps/lld/test/wasm/function-index.test created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | # RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 2 | # RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret64.ll -o %t.ret64.o | ||
| 3 | # RUN: lld -flavor wasm -r -o %t.wasm %t.ret32.o %t.ret64.o | ||
| 4 | # RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | CHECK: Sections: | ||
| 7 | CHECK: - Type: TYPE | ||
| 8 | CHECK: Signatures: | ||
| 9 | CHECK: - Index: 0 | ||
| 10 | CHECK: ReturnType: I32 | ||
| 11 | CHECK: ParamTypes: | ||
| 12 | CHECK: - F32 | ||
| 13 | CHECK: - Index: 1 | ||
| 14 | CHECK: ReturnType: I64 | ||
| 15 | CHECK: ParamTypes: | ||
| 16 | CHECK: - F64 | ||
| 17 | CHECK: - Type: FUNCTION | ||
| 18 | CHECK: FunctionTypes: [ 0, 1 ] | ||
deps/lld/test/wasm/import-memory.test created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | # RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 2 | # RUN: lld -flavor wasm -entry ret32 --import-memory -o %t.wasm %t.ret32.o | ||
| 3 | # RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 4 | |||
| 5 | # Verify the --import-memory flag creates a memory import | ||
| 6 | |||
| 7 | # CHECK: - Type: IMPORT | ||
| 8 | # CHECK-NEXT: Imports: | ||
| 9 | # CHECK-NEXT: - Module: env | ||
| 10 | # CHECK-NEXT: Field: memory | ||
| 11 | # CHECK-NEXT: Kind: MEMORY | ||
| 12 | # CHECK-NEXT: Memory: | ||
| 13 | # CHECK-NEXT: Initial: 0x00000002 | ||
deps/lld/test/wasm/init-fini.ll created+99| ... | @@ -0,0 +1,99 @@ | ||
| 1 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s | ||
| 2 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj %S/Inputs/global-ctor-dtor.ll -o %t.global-ctor-dtor.o | ||
| 3 | |||
| 4 | define hidden void @func1() { | ||
| 5 | entry: | ||
| 6 | ret void | ||
| 7 | } | ||
| 8 | |||
| 9 | define hidden void @func2() { | ||
| 10 | entry: | ||
| 11 | ret void | ||
| 12 | } | ||
| 13 | |||
| 14 | define void @__cxa_atexit() { | ||
| 15 | ret void | ||
| 16 | } | ||
| 17 | |||
| 18 | define hidden void @_start() { | ||
| 19 | entry: | ||
| 20 | ret void | ||
| 21 | } | ||
| 22 | |||
| 23 | @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @func1, i8* null }] | ||
| 24 | |||
| 25 | @llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @func2, i8* null }] | ||
| 26 | |||
| 27 | ; RUN: lld -flavor wasm %t.o %t.global-ctor-dtor.o -o %t.wasm | ||
| 28 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 29 | |||
| 30 | ; CHECK: Name: linking | ||
| 31 | ; CHECK-NEXT: DataSize: 0 | ||
| 32 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 33 | ; CHECK-NEXT: Name: name | ||
| 34 | ; CHECK-NEXT: FunctionNames: | ||
| 35 | ; CHECK-NEXT: - Index: 0 | ||
| 36 | ; CHECK-NEXT: Name: func1 | ||
| 37 | ; CHECK-NEXT: - Index: 1 | ||
| 38 | ; CHECK-NEXT: Name: func2 | ||
| 39 | ; CHECK-NEXT: - Index: 2 | ||
| 40 | ; CHECK-NEXT: Name: __cxa_atexit | ||
| 41 | ; CHECK-NEXT: - Index: 3 | ||
| 42 | ; CHECK-NEXT: Name: _start | ||
| 43 | ; CHECK-NEXT: - Index: 4 | ||
| 44 | ; CHECK-NEXT: Name: .Lcall_dtors | ||
| 45 | ; CHECK-NEXT: - Index: 5 | ||
| 46 | ; CHECK-NEXT: Name: .Lregister_call_dtors | ||
| 47 | ; CHECK-NEXT: - Index: 6 | ||
| 48 | ; CHECK-NEXT: Name: .Lbitcast | ||
| 49 | ; CHECK-NEXT: - Index: 7 | ||
| 50 | ; CHECK-NEXT: Name: myctor | ||
| 51 | ; CHECK-NEXT: - Index: 8 | ||
| 52 | ; CHECK-NEXT: Name: mydtor | ||
| 53 | ; CHECK-NEXT: - Index: 9 | ||
| 54 | ; CHECK-NEXT: Name: .Lcall_dtors | ||
| 55 | ; CHECK-NEXT: - Index: 10 | ||
| 56 | ; CHECK-NEXT: Name: .Lregister_call_dtors | ||
| 57 | ; CHECK-NEXT: ... | ||
| 58 | |||
| 59 | |||
| 60 | ; RUN: lld -flavor wasm -r %t.o %t.global-ctor-dtor.o -o %t.reloc.wasm | ||
| 61 | ; RUN: obj2yaml %t.reloc.wasm | FileCheck -check-prefix=RELOC %s | ||
| 62 | |||
| 63 | ; RELOC: Name: linking | ||
| 64 | ; RELOC-NEXT: DataSize: 0 | ||
| 65 | ; RELOC-NEXT: InitFunctions: | ||
| 66 | ; RELOC-NEXT: - Priority: 65535 | ||
| 67 | ; RELOC-NEXT: FunctionIndex: 0 | ||
| 68 | ; RELOC-NEXT: - Priority: 65535 | ||
| 69 | ; RELOC-NEXT: FunctionIndex: 5 | ||
| 70 | ; RELOC-NEXT: - Priority: 65535 | ||
| 71 | ; RELOC-NEXT: FunctionIndex: 7 | ||
| 72 | ; RELOC-NEXT: - Priority: 65535 | ||
| 73 | ; RELOC-NEXT: FunctionIndex: 10 | ||
| 74 | ; RELOC-NEXT: - Type: CUSTOM | ||
| 75 | ; RELOC-NEXT: Name: name | ||
| 76 | ; RELOC-NEXT: FunctionNames: | ||
| 77 | ; RELOC-NEXT: - Index: 0 | ||
| 78 | ; RELOC-NEXT: Name: func1 | ||
| 79 | ; RELOC-NEXT: - Index: 1 | ||
| 80 | ; RELOC-NEXT: Name: func2 | ||
| 81 | ; RELOC-NEXT: - Index: 2 | ||
| 82 | ; RELOC-NEXT: Name: __cxa_atexit | ||
| 83 | ; RELOC-NEXT: - Index: 3 | ||
| 84 | ; RELOC-NEXT: Name: _start | ||
| 85 | ; RELOC-NEXT: - Index: 4 | ||
| 86 | ; RELOC-NEXT: Name: .Lcall_dtors | ||
| 87 | ; RELOC-NEXT: - Index: 5 | ||
| 88 | ; RELOC-NEXT: Name: .Lregister_call_dtors | ||
| 89 | ; RELOC-NEXT: - Index: 6 | ||
| 90 | ; RELOC-NEXT: Name: .Lbitcast | ||
| 91 | ; RELOC-NEXT: - Index: 7 | ||
| 92 | ; RELOC-NEXT: Name: myctor | ||
| 93 | ; RELOC-NEXT: - Index: 8 | ||
| 94 | ; RELOC-NEXT: Name: mydtor | ||
| 95 | ; RELOC-NEXT: - Index: 9 | ||
| 96 | ; RELOC-NEXT: Name: .Lcall_dtors | ||
| 97 | ; RELOC-NEXT: - Index: 10 | ||
| 98 | ; RELOC-NEXT: Name: .Lregister_call_dtors | ||
| 99 | ; RELOC-NEXT: ... | ||
deps/lld/test/wasm/invalid-stack-size.test created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj %s -o %t.o | ||
| 2 | ; RUN: not lld -flavor wasm -o %t.wasm -z stack-size=1 %t.o 2>&1 | FileCheck %s | ||
| 3 | |||
| 4 | define i32 @_start() local_unnamed_addr #1 { | ||
| 5 | entry: | ||
| 6 | ret i32 0 | ||
| 7 | } | ||
| 8 | |||
| 9 | ; CHECK: error: stack size must be 16-byte aligned | ||
deps/lld/test/wasm/lit.local.cfg created+4| ... | @@ -0,0 +1,4 @@ | ||
| 1 | if 'wasm' not in config.available_features: | ||
| 2 | config.unsupported = True | ||
| 3 | |||
| 4 | config.suffixes = ['.test', '.yaml', '.ll'] | ||
deps/lld/test/wasm/load-undefined.ll created+38| ... | @@ -0,0 +1,38 @@ | ||
| 1 | ; Verify that the -u / --undefined option is able to pull in symbols from | ||
| 2 | ; an archive, and doesn't error when uses to pull in a symbol already loaded. | ||
| 3 | ; | ||
| 4 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/ret64.ll -o %t.o | ||
| 5 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %S/Inputs/ret32.ll -o %t2.o | ||
| 6 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t3.o | ||
| 7 | ; RUN: llvm-ar rcs %t2.a %t2.o | ||
| 8 | ; RUN: lld -flavor wasm %t3.o %t2.a %t.o -o %t.wasm -u ret32 --undefined ret64 | ||
| 9 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 10 | |||
| 11 | define i32 @_start() local_unnamed_addr { | ||
| 12 | entry: | ||
| 13 | ret i32 1 | ||
| 14 | } | ||
| 15 | |||
| 16 | ; CHECK: - Type: EXPORT | ||
| 17 | ; CHECK-NEXT: Exports: | ||
| 18 | ; CHECK-NEXT: - Name: memory | ||
| 19 | ; CHECK-NEXT: Kind: MEMORY | ||
| 20 | ; CHECK-NEXT: Index: 0 | ||
| 21 | ; CHECK-NEXT: - Name: _start | ||
| 22 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 23 | ; CHECK-NEXT: Index: 0 | ||
| 24 | ; CHECK-NEXT: - Name: ret32 | ||
| 25 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 26 | ; CHECK-NEXT: Index: 1 | ||
| 27 | ; CHECK-NEXT: - Name: ret64 | ||
| 28 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 29 | ; CHECK-NEXT: Index: 2 | ||
| 30 | ; CHECK-NEXT: - Type: | ||
| 31 | |||
| 32 | |||
| 33 | ; Verify that referencing a symbol that doesn't exist won't work | ||
| 34 | ; RUN: not lld -flavor wasm %t3.o -o %t.wasm -u symboldoesnotexist 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED1 %s | ||
| 35 | ; CHECK-UNDEFINED1: error: undefined symbol: symboldoesnotexist | ||
| 36 | |||
| 37 | ; RUN: not lld -flavor wasm %t3.o -o %t.wasm --undefined symboldoesnotexist --allow-undefined 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED2 %s | ||
| 38 | ; CHECK-UNDEFINED2: function forced with --undefined not found: symboldoesnotexist | ||
deps/lld/test/wasm/local-symbols.ll created+78| ... | @@ -0,0 +1,78 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 2 | ; RUN: lld -flavor wasm -o %t.wasm %t.o | ||
| 3 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 4 | |||
| 5 | @foo = default global i32 1, align 4 | ||
| 6 | @bar = internal default global i32 3, align 4 | ||
| 7 | |||
| 8 | define internal i32 @baz() local_unnamed_addr { | ||
| 9 | entry: | ||
| 10 | ret i32 2 | ||
| 11 | } | ||
| 12 | |||
| 13 | define i32 @_start() local_unnamed_addr { | ||
| 14 | entry: | ||
| 15 | ret i32 1 | ||
| 16 | } | ||
| 17 | |||
| 18 | ; CHECK: --- !WASM | ||
| 19 | ; CHECK-NEXT: FileHeader: | ||
| 20 | ; CHECK-NEXT: Version: 0x00000001 | ||
| 21 | ; CHECK-NEXT: Sections: | ||
| 22 | ; CHECK-NEXT: - Type: TYPE | ||
| 23 | ; CHECK-NEXT: Signatures: | ||
| 24 | ; CHECK-NEXT: - Index: 0 | ||
| 25 | ; CHECK-NEXT: ReturnType: I32 | ||
| 26 | ; CHECK-NEXT: ParamTypes: | ||
| 27 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 28 | ; CHECK-NEXT: FunctionTypes: [ 0, 0 ] | ||
| 29 | ; CHECK-NEXT: - Type: TABLE | ||
| 30 | ; CHECK-NEXT: Tables: | ||
| 31 | ; CHECK-NEXT: - ElemType: ANYFUNC | ||
| 32 | ; CHECK-NEXT: Limits: | ||
| 33 | ; CHECK-NEXT: Flags: [ HAS_MAX ] | ||
| 34 | ; CHECK-NEXT: Initial: 0x00000001 | ||
| 35 | ; CHECK-NEXT: Maximum: 0x00000001 | ||
| 36 | ; CHECK-NEXT: - Type: MEMORY | ||
| 37 | ; CHECK-NEXT: Memories: | ||
| 38 | ; CHECK-NEXT: - Initial: 0x00000002 | ||
| 39 | ; CHECK-NEXT: - Type: GLOBAL | ||
| 40 | ; CHECK-NEXT: Globals: | ||
| 41 | ; CHECK-NEXT: - Type: I32 | ||
| 42 | ; CHECK-NEXT: Mutable: true | ||
| 43 | ; CHECK-NEXT: InitExpr: | ||
| 44 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 45 | ; CHECK-NEXT: Value: 66576 | ||
| 46 | ; CHECK-NEXT: - Type: EXPORT | ||
| 47 | ; CHECK-NEXT: Exports: | ||
| 48 | ; CHECK-NEXT: - Name: memory | ||
| 49 | ; CHECK-NEXT: Kind: MEMORY | ||
| 50 | ; CHECK-NEXT: Index: 0 | ||
| 51 | ; CHECK-NEXT: - Name: _start | ||
| 52 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 53 | ; CHECK-NEXT: Index: 1 | ||
| 54 | ; CHECK-NEXT: - Type: CODE | ||
| 55 | ; CHECK-NEXT: Functions: | ||
| 56 | ; CHECK-NEXT: - Locals: | ||
| 57 | ; CHECK-NEXT: Body: 41020B | ||
| 58 | ; CHECK-NEXT: - Locals: | ||
| 59 | ; CHECK-NEXT: Body: 41010B | ||
| 60 | ; CHECK-NEXT: - Type: DATA | ||
| 61 | ; CHECK-NEXT: Segments: | ||
| 62 | ; CHECK-NEXT: - SectionOffset: 7 | ||
| 63 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 64 | ; CHECK-NEXT: Offset: | ||
| 65 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 66 | ; CHECK-NEXT: Value: 1024 | ||
| 67 | ; CHECK-NEXT: Content: '0100000003000000' | ||
| 68 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 69 | ; CHECK-NEXT: Name: linking | ||
| 70 | ; CHECK-NEXT: DataSize: 8 | ||
| 71 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 72 | ; CHECK-NEXT: Name: name | ||
| 73 | ; CHECK-NEXT: FunctionNames: | ||
| 74 | ; CHECK-NEXT: - Index: 0 | ||
| 75 | ; CHECK-NEXT: Name: baz | ||
| 76 | ; CHECK-NEXT: - Index: 1 | ||
| 77 | ; CHECK-NEXT: Name: _start | ||
| 78 | ; CHECK-NEXT: ... | ||
deps/lld/test/wasm/many-functions.ll created+695| ... | @@ -0,0 +1,695 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/many-funcs.ll -o %t.many.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 3 | ; RUN: lld -flavor wasm -r -o %t.wasm %t.many.o %t.o | ||
| 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | ; Test that relocations within the CODE section correctly handle | ||
| 7 | ; linking object with different header sizes. many-funcs.ll has | ||
| 8 | ; 128 function and so the final output requires a 2-byte LEB in | ||
| 9 | ; the CODE section header to store the function count. | ||
| 10 | |||
| 11 | define i32 @func() { | ||
| 12 | entry: | ||
| 13 | %call = tail call i32 @func() | ||
| 14 | ret i32 %call | ||
| 15 | } | ||
| 16 | |||
| 17 | ; CHECK: - Type: CODE | ||
| 18 | ; CHECK-NEXT: Relocations: | ||
| 19 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 20 | ; CHECK-NEXT: Index: 0 | ||
| 21 | ; CHECK-NEXT: Offset: 0x00000008 | ||
| 22 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 23 | ; CHECK-NEXT: Index: 0 | ||
| 24 | ; CHECK-NEXT: Offset: 0x00000014 | ||
| 25 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 26 | ; CHECK-NEXT: Index: 0 | ||
| 27 | ; CHECK-NEXT: Offset: 0x00000020 | ||
| 28 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 29 | ; CHECK-NEXT: Index: 0 | ||
| 30 | ; CHECK-NEXT: Offset: 0x0000002C | ||
| 31 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 32 | ; CHECK-NEXT: Index: 0 | ||
| 33 | ; CHECK-NEXT: Offset: 0x00000038 | ||
| 34 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 35 | ; CHECK-NEXT: Index: 0 | ||
| 36 | ; CHECK-NEXT: Offset: 0x00000044 | ||
| 37 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 38 | ; CHECK-NEXT: Index: 0 | ||
| 39 | ; CHECK-NEXT: Offset: 0x00000050 | ||
| 40 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 41 | ; CHECK-NEXT: Index: 0 | ||
| 42 | ; CHECK-NEXT: Offset: 0x0000005C | ||
| 43 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 44 | ; CHECK-NEXT: Index: 0 | ||
| 45 | ; CHECK-NEXT: Offset: 0x00000068 | ||
| 46 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 47 | ; CHECK-NEXT: Index: 0 | ||
| 48 | ; CHECK-NEXT: Offset: 0x00000074 | ||
| 49 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 50 | ; CHECK-NEXT: Index: 0 | ||
| 51 | ; CHECK-NEXT: Offset: 0x00000080 | ||
| 52 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 53 | ; CHECK-NEXT: Index: 0 | ||
| 54 | ; CHECK-NEXT: Offset: 0x0000008C | ||
| 55 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 56 | ; CHECK-NEXT: Index: 0 | ||
| 57 | ; CHECK-NEXT: Offset: 0x00000098 | ||
| 58 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 59 | ; CHECK-NEXT: Index: 0 | ||
| 60 | ; CHECK-NEXT: Offset: 0x000000A4 | ||
| 61 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 62 | ; CHECK-NEXT: Index: 0 | ||
| 63 | ; CHECK-NEXT: Offset: 0x000000B0 | ||
| 64 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 65 | ; CHECK-NEXT: Index: 0 | ||
| 66 | ; CHECK-NEXT: Offset: 0x000000BC | ||
| 67 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 68 | ; CHECK-NEXT: Index: 0 | ||
| 69 | ; CHECK-NEXT: Offset: 0x000000C8 | ||
| 70 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 71 | ; CHECK-NEXT: Index: 0 | ||
| 72 | ; CHECK-NEXT: Offset: 0x000000D4 | ||
| 73 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 74 | ; CHECK-NEXT: Index: 0 | ||
| 75 | ; CHECK-NEXT: Offset: 0x000000E0 | ||
| 76 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 77 | ; CHECK-NEXT: Index: 0 | ||
| 78 | ; CHECK-NEXT: Offset: 0x000000EC | ||
| 79 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 80 | ; CHECK-NEXT: Index: 0 | ||
| 81 | ; CHECK-NEXT: Offset: 0x000000F8 | ||
| 82 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 83 | ; CHECK-NEXT: Index: 0 | ||
| 84 | ; CHECK-NEXT: Offset: 0x00000104 | ||
| 85 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 86 | ; CHECK-NEXT: Index: 0 | ||
| 87 | ; CHECK-NEXT: Offset: 0x00000110 | ||
| 88 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 89 | ; CHECK-NEXT: Index: 0 | ||
| 90 | ; CHECK-NEXT: Offset: 0x0000011C | ||
| 91 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 92 | ; CHECK-NEXT: Index: 0 | ||
| 93 | ; CHECK-NEXT: Offset: 0x00000128 | ||
| 94 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 95 | ; CHECK-NEXT: Index: 0 | ||
| 96 | ; CHECK-NEXT: Offset: 0x00000134 | ||
| 97 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 98 | ; CHECK-NEXT: Index: 0 | ||
| 99 | ; CHECK-NEXT: Offset: 0x00000140 | ||
| 100 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 101 | ; CHECK-NEXT: Index: 0 | ||
| 102 | ; CHECK-NEXT: Offset: 0x0000014C | ||
| 103 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 104 | ; CHECK-NEXT: Index: 0 | ||
| 105 | ; CHECK-NEXT: Offset: 0x00000158 | ||
| 106 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 107 | ; CHECK-NEXT: Index: 0 | ||
| 108 | ; CHECK-NEXT: Offset: 0x00000164 | ||
| 109 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 110 | ; CHECK-NEXT: Index: 0 | ||
| 111 | ; CHECK-NEXT: Offset: 0x00000170 | ||
| 112 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 113 | ; CHECK-NEXT: Index: 0 | ||
| 114 | ; CHECK-NEXT: Offset: 0x0000017C | ||
| 115 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 116 | ; CHECK-NEXT: Index: 0 | ||
| 117 | ; CHECK-NEXT: Offset: 0x00000188 | ||
| 118 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 119 | ; CHECK-NEXT: Index: 0 | ||
| 120 | ; CHECK-NEXT: Offset: 0x00000194 | ||
| 121 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 122 | ; CHECK-NEXT: Index: 0 | ||
| 123 | ; CHECK-NEXT: Offset: 0x000001A0 | ||
| 124 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 125 | ; CHECK-NEXT: Index: 0 | ||
| 126 | ; CHECK-NEXT: Offset: 0x000001AC | ||
| 127 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 128 | ; CHECK-NEXT: Index: 0 | ||
| 129 | ; CHECK-NEXT: Offset: 0x000001B8 | ||
| 130 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 131 | ; CHECK-NEXT: Index: 0 | ||
| 132 | ; CHECK-NEXT: Offset: 0x000001C4 | ||
| 133 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 134 | ; CHECK-NEXT: Index: 0 | ||
| 135 | ; CHECK-NEXT: Offset: 0x000001D0 | ||
| 136 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 137 | ; CHECK-NEXT: Index: 0 | ||
| 138 | ; CHECK-NEXT: Offset: 0x000001DC | ||
| 139 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 140 | ; CHECK-NEXT: Index: 0 | ||
| 141 | ; CHECK-NEXT: Offset: 0x000001E8 | ||
| 142 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 143 | ; CHECK-NEXT: Index: 0 | ||
| 144 | ; CHECK-NEXT: Offset: 0x000001F4 | ||
| 145 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 146 | ; CHECK-NEXT: Index: 0 | ||
| 147 | ; CHECK-NEXT: Offset: 0x00000200 | ||
| 148 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 149 | ; CHECK-NEXT: Index: 0 | ||
| 150 | ; CHECK-NEXT: Offset: 0x0000020C | ||
| 151 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 152 | ; CHECK-NEXT: Index: 0 | ||
| 153 | ; CHECK-NEXT: Offset: 0x00000218 | ||
| 154 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 155 | ; CHECK-NEXT: Index: 0 | ||
| 156 | ; CHECK-NEXT: Offset: 0x00000224 | ||
| 157 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 158 | ; CHECK-NEXT: Index: 0 | ||
| 159 | ; CHECK-NEXT: Offset: 0x00000230 | ||
| 160 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 161 | ; CHECK-NEXT: Index: 0 | ||
| 162 | ; CHECK-NEXT: Offset: 0x0000023C | ||
| 163 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 164 | ; CHECK-NEXT: Index: 0 | ||
| 165 | ; CHECK-NEXT: Offset: 0x00000248 | ||
| 166 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 167 | ; CHECK-NEXT: Index: 0 | ||
| 168 | ; CHECK-NEXT: Offset: 0x00000254 | ||
| 169 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 170 | ; CHECK-NEXT: Index: 0 | ||
| 171 | ; CHECK-NEXT: Offset: 0x00000260 | ||
| 172 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 173 | ; CHECK-NEXT: Index: 0 | ||
| 174 | ; CHECK-NEXT: Offset: 0x0000026C | ||
| 175 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 176 | ; CHECK-NEXT: Index: 0 | ||
| 177 | ; CHECK-NEXT: Offset: 0x00000278 | ||
| 178 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 179 | ; CHECK-NEXT: Index: 0 | ||
| 180 | ; CHECK-NEXT: Offset: 0x00000284 | ||
| 181 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 182 | ; CHECK-NEXT: Index: 0 | ||
| 183 | ; CHECK-NEXT: Offset: 0x00000290 | ||
| 184 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 185 | ; CHECK-NEXT: Index: 0 | ||
| 186 | ; CHECK-NEXT: Offset: 0x0000029C | ||
| 187 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 188 | ; CHECK-NEXT: Index: 0 | ||
| 189 | ; CHECK-NEXT: Offset: 0x000002A8 | ||
| 190 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 191 | ; CHECK-NEXT: Index: 0 | ||
| 192 | ; CHECK-NEXT: Offset: 0x000002B4 | ||
| 193 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 194 | ; CHECK-NEXT: Index: 0 | ||
| 195 | ; CHECK-NEXT: Offset: 0x000002C0 | ||
| 196 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 197 | ; CHECK-NEXT: Index: 0 | ||
| 198 | ; CHECK-NEXT: Offset: 0x000002CC | ||
| 199 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 200 | ; CHECK-NEXT: Index: 0 | ||
| 201 | ; CHECK-NEXT: Offset: 0x000002D8 | ||
| 202 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 203 | ; CHECK-NEXT: Index: 0 | ||
| 204 | ; CHECK-NEXT: Offset: 0x000002E4 | ||
| 205 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 206 | ; CHECK-NEXT: Index: 0 | ||
| 207 | ; CHECK-NEXT: Offset: 0x000002F0 | ||
| 208 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 209 | ; CHECK-NEXT: Index: 0 | ||
| 210 | ; CHECK-NEXT: Offset: 0x000002FC | ||
| 211 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 212 | ; CHECK-NEXT: Index: 0 | ||
| 213 | ; CHECK-NEXT: Offset: 0x00000308 | ||
| 214 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 215 | ; CHECK-NEXT: Index: 0 | ||
| 216 | ; CHECK-NEXT: Offset: 0x00000314 | ||
| 217 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 218 | ; CHECK-NEXT: Index: 0 | ||
| 219 | ; CHECK-NEXT: Offset: 0x00000320 | ||
| 220 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 221 | ; CHECK-NEXT: Index: 0 | ||
| 222 | ; CHECK-NEXT: Offset: 0x0000032C | ||
| 223 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 224 | ; CHECK-NEXT: Index: 0 | ||
| 225 | ; CHECK-NEXT: Offset: 0x00000338 | ||
| 226 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 227 | ; CHECK-NEXT: Index: 0 | ||
| 228 | ; CHECK-NEXT: Offset: 0x00000344 | ||
| 229 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 230 | ; CHECK-NEXT: Index: 0 | ||
| 231 | ; CHECK-NEXT: Offset: 0x00000350 | ||
| 232 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 233 | ; CHECK-NEXT: Index: 0 | ||
| 234 | ; CHECK-NEXT: Offset: 0x0000035C | ||
| 235 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 236 | ; CHECK-NEXT: Index: 0 | ||
| 237 | ; CHECK-NEXT: Offset: 0x00000368 | ||
| 238 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 239 | ; CHECK-NEXT: Index: 0 | ||
| 240 | ; CHECK-NEXT: Offset: 0x00000374 | ||
| 241 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 242 | ; CHECK-NEXT: Index: 0 | ||
| 243 | ; CHECK-NEXT: Offset: 0x00000380 | ||
| 244 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 245 | ; CHECK-NEXT: Index: 0 | ||
| 246 | ; CHECK-NEXT: Offset: 0x0000038C | ||
| 247 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 248 | ; CHECK-NEXT: Index: 0 | ||
| 249 | ; CHECK-NEXT: Offset: 0x00000398 | ||
| 250 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 251 | ; CHECK-NEXT: Index: 0 | ||
| 252 | ; CHECK-NEXT: Offset: 0x000003A4 | ||
| 253 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 254 | ; CHECK-NEXT: Index: 0 | ||
| 255 | ; CHECK-NEXT: Offset: 0x000003B0 | ||
| 256 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 257 | ; CHECK-NEXT: Index: 0 | ||
| 258 | ; CHECK-NEXT: Offset: 0x000003BC | ||
| 259 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 260 | ; CHECK-NEXT: Index: 0 | ||
| 261 | ; CHECK-NEXT: Offset: 0x000003C8 | ||
| 262 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 263 | ; CHECK-NEXT: Index: 0 | ||
| 264 | ; CHECK-NEXT: Offset: 0x000003D4 | ||
| 265 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 266 | ; CHECK-NEXT: Index: 0 | ||
| 267 | ; CHECK-NEXT: Offset: 0x000003E0 | ||
| 268 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 269 | ; CHECK-NEXT: Index: 0 | ||
| 270 | ; CHECK-NEXT: Offset: 0x000003EC | ||
| 271 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 272 | ; CHECK-NEXT: Index: 0 | ||
| 273 | ; CHECK-NEXT: Offset: 0x000003F8 | ||
| 274 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 275 | ; CHECK-NEXT: Index: 0 | ||
| 276 | ; CHECK-NEXT: Offset: 0x00000404 | ||
| 277 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 278 | ; CHECK-NEXT: Index: 0 | ||
| 279 | ; CHECK-NEXT: Offset: 0x00000410 | ||
| 280 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 281 | ; CHECK-NEXT: Index: 0 | ||
| 282 | ; CHECK-NEXT: Offset: 0x0000041C | ||
| 283 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 284 | ; CHECK-NEXT: Index: 0 | ||
| 285 | ; CHECK-NEXT: Offset: 0x00000428 | ||
| 286 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 287 | ; CHECK-NEXT: Index: 0 | ||
| 288 | ; CHECK-NEXT: Offset: 0x00000434 | ||
| 289 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 290 | ; CHECK-NEXT: Index: 0 | ||
| 291 | ; CHECK-NEXT: Offset: 0x00000440 | ||
| 292 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 293 | ; CHECK-NEXT: Index: 0 | ||
| 294 | ; CHECK-NEXT: Offset: 0x0000044C | ||
| 295 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 296 | ; CHECK-NEXT: Index: 0 | ||
| 297 | ; CHECK-NEXT: Offset: 0x00000458 | ||
| 298 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 299 | ; CHECK-NEXT: Index: 0 | ||
| 300 | ; CHECK-NEXT: Offset: 0x00000464 | ||
| 301 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 302 | ; CHECK-NEXT: Index: 0 | ||
| 303 | ; CHECK-NEXT: Offset: 0x00000470 | ||
| 304 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 305 | ; CHECK-NEXT: Index: 0 | ||
| 306 | ; CHECK-NEXT: Offset: 0x0000047C | ||
| 307 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 308 | ; CHECK-NEXT: Index: 0 | ||
| 309 | ; CHECK-NEXT: Offset: 0x00000488 | ||
| 310 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 311 | ; CHECK-NEXT: Index: 0 | ||
| 312 | ; CHECK-NEXT: Offset: 0x00000494 | ||
| 313 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 314 | ; CHECK-NEXT: Index: 0 | ||
| 315 | ; CHECK-NEXT: Offset: 0x000004A0 | ||
| 316 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 317 | ; CHECK-NEXT: Index: 0 | ||
| 318 | ; CHECK-NEXT: Offset: 0x000004AC | ||
| 319 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 320 | ; CHECK-NEXT: Index: 0 | ||
| 321 | ; CHECK-NEXT: Offset: 0x000004B8 | ||
| 322 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 323 | ; CHECK-NEXT: Index: 0 | ||
| 324 | ; CHECK-NEXT: Offset: 0x000004C4 | ||
| 325 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 326 | ; CHECK-NEXT: Index: 0 | ||
| 327 | ; CHECK-NEXT: Offset: 0x000004D0 | ||
| 328 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 329 | ; CHECK-NEXT: Index: 0 | ||
| 330 | ; CHECK-NEXT: Offset: 0x000004DC | ||
| 331 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 332 | ; CHECK-NEXT: Index: 0 | ||
| 333 | ; CHECK-NEXT: Offset: 0x000004E8 | ||
| 334 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 335 | ; CHECK-NEXT: Index: 0 | ||
| 336 | ; CHECK-NEXT: Offset: 0x000004F4 | ||
| 337 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 338 | ; CHECK-NEXT: Index: 0 | ||
| 339 | ; CHECK-NEXT: Offset: 0x00000500 | ||
| 340 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 341 | ; CHECK-NEXT: Index: 0 | ||
| 342 | ; CHECK-NEXT: Offset: 0x0000050C | ||
| 343 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 344 | ; CHECK-NEXT: Index: 0 | ||
| 345 | ; CHECK-NEXT: Offset: 0x00000518 | ||
| 346 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 347 | ; CHECK-NEXT: Index: 0 | ||
| 348 | ; CHECK-NEXT: Offset: 0x00000524 | ||
| 349 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 350 | ; CHECK-NEXT: Index: 0 | ||
| 351 | ; CHECK-NEXT: Offset: 0x00000530 | ||
| 352 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 353 | ; CHECK-NEXT: Index: 0 | ||
| 354 | ; CHECK-NEXT: Offset: 0x0000053C | ||
| 355 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 356 | ; CHECK-NEXT: Index: 0 | ||
| 357 | ; CHECK-NEXT: Offset: 0x00000548 | ||
| 358 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 359 | ; CHECK-NEXT: Index: 0 | ||
| 360 | ; CHECK-NEXT: Offset: 0x00000554 | ||
| 361 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 362 | ; CHECK-NEXT: Index: 0 | ||
| 363 | ; CHECK-NEXT: Offset: 0x00000560 | ||
| 364 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 365 | ; CHECK-NEXT: Index: 0 | ||
| 366 | ; CHECK-NEXT: Offset: 0x0000056C | ||
| 367 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 368 | ; CHECK-NEXT: Index: 0 | ||
| 369 | ; CHECK-NEXT: Offset: 0x00000578 | ||
| 370 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 371 | ; CHECK-NEXT: Index: 0 | ||
| 372 | ; CHECK-NEXT: Offset: 0x00000584 | ||
| 373 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 374 | ; CHECK-NEXT: Index: 0 | ||
| 375 | ; CHECK-NEXT: Offset: 0x00000590 | ||
| 376 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 377 | ; CHECK-NEXT: Index: 0 | ||
| 378 | ; CHECK-NEXT: Offset: 0x0000059C | ||
| 379 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 380 | ; CHECK-NEXT: Index: 0 | ||
| 381 | ; CHECK-NEXT: Offset: 0x000005A8 | ||
| 382 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 383 | ; CHECK-NEXT: Index: 0 | ||
| 384 | ; CHECK-NEXT: Offset: 0x000005B4 | ||
| 385 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 386 | ; CHECK-NEXT: Index: 0 | ||
| 387 | ; CHECK-NEXT: Offset: 0x000005C0 | ||
| 388 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 389 | ; CHECK-NEXT: Index: 0 | ||
| 390 | ; CHECK-NEXT: Offset: 0x000005CC | ||
| 391 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 392 | ; CHECK-NEXT: Index: 0 | ||
| 393 | ; CHECK-NEXT: Offset: 0x000005D8 | ||
| 394 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 395 | ; CHECK-NEXT: Index: 0 | ||
| 396 | ; CHECK-NEXT: Offset: 0x000005E4 | ||
| 397 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 398 | ; CHECK-NEXT: Index: 0 | ||
| 399 | ; CHECK-NEXT: Offset: 0x000005F0 | ||
| 400 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 401 | ; CHECK-NEXT: Index: 1 | ||
| 402 | ; CHECK-NEXT: Offset: 0x000005FC | ||
| 403 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB | ||
| 404 | ; CHECK-NEXT: Index: 1 | ||
| 405 | ; CHECK-NEXT: Offset: 0x00000608 | ||
| 406 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB | ||
| 407 | ; CHECK-NEXT: Index: 129 | ||
| 408 | ; CHECK-NEXT: Offset: 0x00000611 | ||
| 409 | ; CHECK-NEXT: Functions: | ||
| 410 | ; CHECK-NEXT: - Locals: | ||
| 411 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 412 | ; CHECK-NEXT: - Locals: | ||
| 413 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 414 | ; CHECK-NEXT: - Locals: | ||
| 415 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 416 | ; CHECK-NEXT: - Locals: | ||
| 417 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 418 | ; CHECK-NEXT: - Locals: | ||
| 419 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 420 | ; CHECK-NEXT: - Locals: | ||
| 421 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 422 | ; CHECK-NEXT: - Locals: | ||
| 423 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 424 | ; CHECK-NEXT: - Locals: | ||
| 425 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 426 | ; CHECK-NEXT: - Locals: | ||
| 427 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 428 | ; CHECK-NEXT: - Locals: | ||
| 429 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 430 | ; CHECK-NEXT: - Locals: | ||
| 431 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 432 | ; CHECK-NEXT: - Locals: | ||
| 433 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 434 | ; CHECK-NEXT: - Locals: | ||
| 435 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 436 | ; CHECK-NEXT: - Locals: | ||
| 437 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 438 | ; CHECK-NEXT: - Locals: | ||
| 439 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 440 | ; CHECK-NEXT: - Locals: | ||
| 441 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 442 | ; CHECK-NEXT: - Locals: | ||
| 443 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 444 | ; CHECK-NEXT: - Locals: | ||
| 445 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 446 | ; CHECK-NEXT: - Locals: | ||
| 447 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 448 | ; CHECK-NEXT: - Locals: | ||
| 449 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 450 | ; CHECK-NEXT: - Locals: | ||
| 451 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 452 | ; CHECK-NEXT: - Locals: | ||
| 453 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 454 | ; CHECK-NEXT: - Locals: | ||
| 455 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 456 | ; CHECK-NEXT: - Locals: | ||
| 457 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 458 | ; CHECK-NEXT: - Locals: | ||
| 459 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 460 | ; CHECK-NEXT: - Locals: | ||
| 461 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 462 | ; CHECK-NEXT: - Locals: | ||
| 463 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 464 | ; CHECK-NEXT: - Locals: | ||
| 465 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 466 | ; CHECK-NEXT: - Locals: | ||
| 467 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 468 | ; CHECK-NEXT: - Locals: | ||
| 469 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 470 | ; CHECK-NEXT: - Locals: | ||
| 471 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 472 | ; CHECK-NEXT: - Locals: | ||
| 473 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 474 | ; CHECK-NEXT: - Locals: | ||
| 475 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 476 | ; CHECK-NEXT: - Locals: | ||
| 477 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 478 | ; CHECK-NEXT: - Locals: | ||
| 479 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 480 | ; CHECK-NEXT: - Locals: | ||
| 481 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 482 | ; CHECK-NEXT: - Locals: | ||
| 483 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 484 | ; CHECK-NEXT: - Locals: | ||
| 485 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 486 | ; CHECK-NEXT: - Locals: | ||
| 487 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 488 | ; CHECK-NEXT: - Locals: | ||
| 489 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 490 | ; CHECK-NEXT: - Locals: | ||
| 491 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 492 | ; CHECK-NEXT: - Locals: | ||
| 493 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 494 | ; CHECK-NEXT: - Locals: | ||
| 495 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 496 | ; CHECK-NEXT: - Locals: | ||
| 497 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 498 | ; CHECK-NEXT: - Locals: | ||
| 499 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 500 | ; CHECK-NEXT: - Locals: | ||
| 501 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 502 | ; CHECK-NEXT: - Locals: | ||
| 503 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 504 | ; CHECK-NEXT: - Locals: | ||
| 505 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 506 | ; CHECK-NEXT: - Locals: | ||
| 507 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 508 | ; CHECK-NEXT: - Locals: | ||
| 509 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 510 | ; CHECK-NEXT: - Locals: | ||
| 511 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 512 | ; CHECK-NEXT: - Locals: | ||
| 513 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 514 | ; CHECK-NEXT: - Locals: | ||
| 515 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 516 | ; CHECK-NEXT: - Locals: | ||
| 517 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 518 | ; CHECK-NEXT: - Locals: | ||
| 519 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 520 | ; CHECK-NEXT: - Locals: | ||
| 521 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 522 | ; CHECK-NEXT: - Locals: | ||
| 523 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 524 | ; CHECK-NEXT: - Locals: | ||
| 525 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 526 | ; CHECK-NEXT: - Locals: | ||
| 527 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 528 | ; CHECK-NEXT: - Locals: | ||
| 529 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 530 | ; CHECK-NEXT: - Locals: | ||
| 531 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 532 | ; CHECK-NEXT: - Locals: | ||
| 533 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 534 | ; CHECK-NEXT: - Locals: | ||
| 535 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 536 | ; CHECK-NEXT: - Locals: | ||
| 537 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 538 | ; CHECK-NEXT: - Locals: | ||
| 539 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 540 | ; CHECK-NEXT: - Locals: | ||
| 541 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 542 | ; CHECK-NEXT: - Locals: | ||
| 543 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 544 | ; CHECK-NEXT: - Locals: | ||
| 545 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 546 | ; CHECK-NEXT: - Locals: | ||
| 547 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 548 | ; CHECK-NEXT: - Locals: | ||
| 549 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 550 | ; CHECK-NEXT: - Locals: | ||
| 551 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 552 | ; CHECK-NEXT: - Locals: | ||
| 553 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 554 | ; CHECK-NEXT: - Locals: | ||
| 555 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 556 | ; CHECK-NEXT: - Locals: | ||
| 557 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 558 | ; CHECK-NEXT: - Locals: | ||
| 559 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 560 | ; CHECK-NEXT: - Locals: | ||
| 561 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 562 | ; CHECK-NEXT: - Locals: | ||
| 563 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 564 | ; CHECK-NEXT: - Locals: | ||
| 565 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 566 | ; CHECK-NEXT: - Locals: | ||
| 567 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 568 | ; CHECK-NEXT: - Locals: | ||
| 569 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 570 | ; CHECK-NEXT: - Locals: | ||
| 571 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 572 | ; CHECK-NEXT: - Locals: | ||
| 573 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 574 | ; CHECK-NEXT: - Locals: | ||
| 575 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 576 | ; CHECK-NEXT: - Locals: | ||
| 577 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 578 | ; CHECK-NEXT: - Locals: | ||
| 579 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 580 | ; CHECK-NEXT: - Locals: | ||
| 581 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 582 | ; CHECK-NEXT: - Locals: | ||
| 583 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 584 | ; CHECK-NEXT: - Locals: | ||
| 585 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 586 | ; CHECK-NEXT: - Locals: | ||
| 587 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 588 | ; CHECK-NEXT: - Locals: | ||
| 589 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 590 | ; CHECK-NEXT: - Locals: | ||
| 591 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 592 | ; CHECK-NEXT: - Locals: | ||
| 593 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 594 | ; CHECK-NEXT: - Locals: | ||
| 595 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 596 | ; CHECK-NEXT: - Locals: | ||
| 597 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 598 | ; CHECK-NEXT: - Locals: | ||
| 599 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 600 | ; CHECK-NEXT: - Locals: | ||
| 601 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 602 | ; CHECK-NEXT: - Locals: | ||
| 603 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 604 | ; CHECK-NEXT: - Locals: | ||
| 605 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 606 | ; CHECK-NEXT: - Locals: | ||
| 607 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 608 | ; CHECK-NEXT: - Locals: | ||
| 609 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 610 | ; CHECK-NEXT: - Locals: | ||
| 611 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 612 | ; CHECK-NEXT: - Locals: | ||
| 613 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 614 | ; CHECK-NEXT: - Locals: | ||
| 615 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 616 | ; CHECK-NEXT: - Locals: | ||
| 617 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 618 | ; CHECK-NEXT: - Locals: | ||
| 619 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 620 | ; CHECK-NEXT: - Locals: | ||
| 621 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 622 | ; CHECK-NEXT: - Locals: | ||
| 623 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 624 | ; CHECK-NEXT: - Locals: | ||
| 625 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 626 | ; CHECK-NEXT: - Locals: | ||
| 627 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 628 | ; CHECK-NEXT: - Locals: | ||
| 629 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 630 | ; CHECK-NEXT: - Locals: | ||
| 631 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 632 | ; CHECK-NEXT: - Locals: | ||
| 633 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 634 | ; CHECK-NEXT: - Locals: | ||
| 635 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 636 | ; CHECK-NEXT: - Locals: | ||
| 637 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 638 | ; CHECK-NEXT: - Locals: | ||
| 639 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 640 | ; CHECK-NEXT: - Locals: | ||
| 641 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 642 | ; CHECK-NEXT: - Locals: | ||
| 643 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 644 | ; CHECK-NEXT: - Locals: | ||
| 645 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 646 | ; CHECK-NEXT: - Locals: | ||
| 647 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 648 | ; CHECK-NEXT: - Locals: | ||
| 649 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 650 | ; CHECK-NEXT: - Locals: | ||
| 651 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 652 | ; CHECK-NEXT: - Locals: | ||
| 653 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 654 | ; CHECK-NEXT: - Locals: | ||
| 655 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 656 | ; CHECK-NEXT: - Locals: | ||
| 657 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 658 | ; CHECK-NEXT: - Locals: | ||
| 659 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 660 | ; CHECK-NEXT: - Locals: | ||
| 661 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 662 | ; CHECK-NEXT: - Locals: | ||
| 663 | ; CHECK-NEXT: Body: 4100280284808080000B | ||
| 664 | ; CHECK-NEXT: - Locals: | ||
| 665 | ; CHECK-NEXT: Body: 4100280280808080000B | ||
| 666 | ; CHECK-NEXT: - Locals: | ||
| 667 | ; CHECK-NEXT: Body: 4100280280808080000B | ||
| 668 | ; CHECK-NEXT: - Locals: | ||
| 669 | ; CHECK-NEXT: Body: 1081818080000B | ||
| 670 | ; CHECK-NEXT: - Type: DATA | ||
| 671 | ; CHECK-NEXT: Segments: | ||
| 672 | ; CHECK-NEXT: - SectionOffset: 6 | ||
| 673 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 674 | ; CHECK-NEXT: Offset: | ||
| 675 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 676 | ; CHECK-NEXT: Value: 0 | ||
| 677 | ; CHECK-NEXT: Content: '01000000' | ||
| 678 | ; CHECK-NEXT: - SectionOffset: 15 | ||
| 679 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 680 | ; CHECK-NEXT: Offset: | ||
| 681 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 682 | ; CHECK-NEXT: Value: 4 | ||
| 683 | ; CHECK-NEXT: Content: '01000000' | ||
| 684 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 685 | ; CHECK-NEXT: Name: linking | ||
| 686 | ; CHECK-NEXT: DataSize: 8 | ||
| 687 | ; CHECK-NEXT: SegmentInfo: | ||
| 688 | ; CHECK-NEXT: - Index: 0 | ||
| 689 | ; CHECK-NEXT: Name: .data.g0 | ||
| 690 | ; CHECK-NEXT: Alignment: 4 | ||
| 691 | ; CHECK-NEXT: Flags: [ ] | ||
| 692 | ; CHECK-NEXT: - Index: 1 | ||
| 693 | ; CHECK-NEXT: Name: .data.foo | ||
| 694 | ; CHECK-NEXT: Alignment: 4 | ||
| 695 | ; CHECK-NEXT: Flags: [ ] | ||
deps/lld/test/wasm/relocatable.ll created+194| ... | @@ -0,0 +1,194 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/hello.ll -o %t.hello.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 3 | ; RUN: lld -flavor wasm -r -o %t.wasm %t.hello.o %t.o | ||
| 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | ; Function Attrs: nounwind | ||
| 7 | define hidden i32 @my_func() local_unnamed_addr { | ||
| 8 | entry: | ||
| 9 | %call = tail call i32 @foo_import() | ||
| 10 | ret i32 1 | ||
| 11 | } | ||
| 12 | |||
| 13 | declare i32 @foo_import() local_unnamed_addr | ||
| 14 | @data_import = external global i64 | ||
| 15 | |||
| 16 | @func_addr1 = hidden global i32()* @my_func, align 4 | ||
| 17 | @func_addr2 = hidden global i32()* @foo_import, align 4 | ||
| 18 | @data_addr1 = hidden global i64* @data_import, align 8 | ||
| 19 | |||
| 20 | ; CHECK: --- !WASM | ||
| 21 | ; CHECK-NEXT: FileHeader: | ||
| 22 | ; CHECK-NEXT: Version: 0x00000001 | ||
| 23 | ; CHECK-NEXT: Sections: | ||
| 24 | ; CHECK-NEXT: - Type: TYPE | ||
| 25 | ; CHECK-NEXT: Signatures: | ||
| 26 | ; CHECK-NEXT: - Index: 0 | ||
| 27 | ; CHECK-NEXT: ReturnType: NORESULT | ||
| 28 | ; CHECK-NEXT: ParamTypes: | ||
| 29 | ; CHECK-NEXT: - Index: 1 | ||
| 30 | ; CHECK-NEXT: ReturnType: NORESULT | ||
| 31 | ; CHECK-NEXT: ParamTypes: | ||
| 32 | ; CHECK-NEXT: - I32 | ||
| 33 | ; CHECK-NEXT: - Index: 2 | ||
| 34 | ; CHECK-NEXT: ReturnType: I32 | ||
| 35 | ; CHECK-NEXT: ParamTypes: | ||
| 36 | ; CHECK-NEXT: - Type: IMPORT | ||
| 37 | ; CHECK-NEXT: Imports: | ||
| 38 | ; CHECK-NEXT: - Module: env | ||
| 39 | ; CHECK-NEXT: Field: puts | ||
| 40 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 41 | ; CHECK-NEXT: SigIndex: 1 | ||
| 42 | ; CHECK-NEXT: - Module: env | ||
| 43 | ; CHECK-NEXT: Field: foo_import | ||
| 44 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 45 | ; CHECK-NEXT: SigIndex: 2 | ||
| 46 | ; CHECK-NEXT: - Module: env | ||
| 47 | ; CHECK-NEXT: Field: data_import | ||
| 48 | ; CHECK-NEXT: Kind: GLOBAL | ||
| 49 | ; CHECK-NEXT: GlobalType: I32 | ||
| 50 | ; CHECK-NEXT: GlobalMutable: false | ||
| 51 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 52 | ; CHECK-NEXT: FunctionTypes: [ 0, 2 ] | ||
| 53 | ; CHECK-NEXT: - Type: TABLE | ||
| 54 | ; CHECK-NEXT: Tables: | ||
| 55 | ; CHECK-NEXT: - ElemType: ANYFUNC | ||
| 56 | ; CHECK-NEXT: Limits: | ||
| 57 | ; CHECK-NEXT: Flags: [ HAS_MAX ] | ||
| 58 | ; CHECK-NEXT: Initial: 0x00000002 | ||
| 59 | ; CHECK-NEXT: Maximum: 0x00000002 | ||
| 60 | ; CHECK-NEXT: - Type: MEMORY | ||
| 61 | ; CHECK-NEXT: Memories: | ||
| 62 | ; CHECK-NEXT: - Initial: 0x00000001 | ||
| 63 | ; CHECK-NEXT: - Type: GLOBAL | ||
| 64 | ; CHECK-NEXT: Globals: | ||
| 65 | ; CHECK-NEXT: - Type: I32 | ||
| 66 | ; CHECK-NEXT: Mutable: false | ||
| 67 | ; CHECK-NEXT: InitExpr: | ||
| 68 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 69 | ; CHECK-NEXT: Value: 0 | ||
| 70 | ; CHECK-NEXT: - Type: I32 | ||
| 71 | ; CHECK-NEXT: Mutable: false | ||
| 72 | ; CHECK-NEXT: InitExpr: | ||
| 73 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 74 | ; CHECK-NEXT: Value: 8 | ||
| 75 | ; CHECK-NEXT: - Type: I32 | ||
| 76 | ; CHECK-NEXT: Mutable: false | ||
| 77 | ; CHECK-NEXT: InitExpr: | ||
| 78 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 79 | ; CHECK-NEXT: Value: 12 | ||
| 80 | ; CHECK-NEXT: - Type: I32 | ||
| 81 | ; CHECK-NEXT: Mutable: false | ||
| 82 | ; CHECK-NEXT: InitExpr: | ||
| 83 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 84 | ; CHECK-NEXT: Value: 16 | ||
| 85 | ; CHECK-NEXT: - Type: EXPORT | ||
| 86 | ; CHECK-NEXT: Exports: | ||
| 87 | ; CHECK-NEXT: - Name: hello | ||
| 88 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 89 | ; CHECK-NEXT: Index: 2 | ||
| 90 | ; CHECK-NEXT: - Name: my_func | ||
| 91 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 92 | ; CHECK-NEXT: Index: 3 | ||
| 93 | ; CHECK-NEXT: - Name: hello_str | ||
| 94 | ; CHECK-NEXT: Kind: GLOBAL | ||
| 95 | ; CHECK-NEXT: Index: 1 | ||
| 96 | ; CHECK-NEXT: - Name: func_addr1 | ||
| 97 | ; CHECK-NEXT: Kind: GLOBAL | ||
| 98 | ; CHECK-NEXT: Index: 2 | ||
| 99 | ; CHECK-NEXT: - Name: func_addr2 | ||
| 100 | ; CHECK-NEXT: Kind: GLOBAL | ||
| 101 | ; CHECK-NEXT: Index: 3 | ||
| 102 | ; CHECK-NEXT: - Name: data_addr1 | ||
| 103 | ; CHECK-NEXT: Kind: GLOBAL | ||
| 104 | ; CHECK-NEXT: Index: 4 | ||
| 105 | ; CHECK-NEXT: - Type: ELEM | ||
| 106 | ; CHECK-NEXT: Segments: | ||
| 107 | ; CHECK-NEXT: - Offset: | ||
| 108 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 109 | ; CHECK-NEXT: Value: 0 | ||
| 110 | ; CHECK-NEXT: Functions: [ 3, 1 ] | ||
| 111 | ; CHECK-NEXT: - Type: CODE | ||
| 112 | ; CHECK-NEXT: Relocations: | ||
| 113 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB | ||
| 114 | ; CHECK-NEXT: Index: 1 | ||
| 115 | ; CHECK-NEXT: Offset: 0x00000004 | ||
| 116 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB | ||
| 117 | ; CHECK-NEXT: Index: 0 | ||
| 118 | ; CHECK-NEXT: Offset: 0x0000000A | ||
| 119 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB | ||
| 120 | ; CHECK-NEXT: Index: 1 | ||
| 121 | ; CHECK-NEXT: Offset: 0x00000013 | ||
| 122 | ; CHECK-NEXT: Functions: | ||
| 123 | ; CHECK-NEXT: - Locals: | ||
| 124 | ; CHECK-NEXT: Body: 4180808080001080808080000B | ||
| 125 | ; CHECK-NEXT: - Locals: | ||
| 126 | ; CHECK-NEXT: Body: 1081808080001A41010B | ||
| 127 | ; CHECK-NEXT: - Type: DATA | ||
| 128 | ; CHECK-NEXT: Relocations: | ||
| 129 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 | ||
| 130 | ; CHECK-NEXT: Index: 0 | ||
| 131 | ; CHECK-NEXT: Offset: 0x00000012 | ||
| 132 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 | ||
| 133 | ; CHECK-NEXT: Index: 1 | ||
| 134 | ; CHECK-NEXT: Offset: 0x0000001B | ||
| 135 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 | ||
| 136 | ; CHECK-NEXT: Index: 0 | ||
| 137 | ; CHECK-NEXT: Offset: 0x00000024 | ||
| 138 | ; CHECK-NEXT: Segments: | ||
| 139 | ; CHECK-NEXT: - SectionOffset: 6 | ||
| 140 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 141 | ; CHECK-NEXT: Offset: | ||
| 142 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 143 | ; CHECK-NEXT: Value: 0 | ||
| 144 | ; CHECK-NEXT: Content: 68656C6C6F0A00 | ||
| 145 | ; CHECK-NEXT: - SectionOffset: 18 | ||
| 146 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 147 | ; CHECK-NEXT: Offset: | ||
| 148 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 149 | ; CHECK-NEXT: Value: 8 | ||
| 150 | ; CHECK-NEXT: Content: '00000000' | ||
| 151 | ; CHECK-NEXT: - SectionOffset: 27 | ||
| 152 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 153 | ; CHECK-NEXT: Offset: | ||
| 154 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 155 | ; CHECK-NEXT: Value: 12 | ||
| 156 | ; CHECK-NEXT: Content: '01000000' | ||
| 157 | ; CHECK-NEXT: - SectionOffset: 36 | ||
| 158 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 159 | ; CHECK-NEXT: Offset: | ||
| 160 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 161 | ; CHECK-NEXT: Value: 16 | ||
| 162 | ; CHECK-NEXT: Content: FFFFFFFF | ||
| 163 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 164 | ; CHECK-NEXT: Name: linking | ||
| 165 | ; CHECK-NEXT: DataSize: 20 | ||
| 166 | ; CHECK-NEXT: SegmentInfo: | ||
| 167 | ; CHECK-NEXT: - Index: 0 | ||
| 168 | ; CHECK-NEXT: Name: .rodata.hello_str | ||
| 169 | ; CHECK-NEXT: Alignment: 1 | ||
| 170 | ; CHECK-NEXT: Flags: [ ] | ||
| 171 | ; CHECK-NEXT: - Index: 1 | ||
| 172 | ; CHECK-NEXT: Name: .data.func_addr1 | ||
| 173 | ; CHECK-NEXT: Alignment: 4 | ||
| 174 | ; CHECK-NEXT: Flags: [ ] | ||
| 175 | ; CHECK-NEXT: - Index: 2 | ||
| 176 | ; CHECK-NEXT: Name: .data.func_addr2 | ||
| 177 | ; CHECK-NEXT: Alignment: 4 | ||
| 178 | ; CHECK-NEXT: Flags: [ ] | ||
| 179 | ; CHECK-NEXT: - Index: 3 | ||
| 180 | ; CHECK-NEXT: Name: .data.data_addr1 | ||
| 181 | ; CHECK-NEXT: Alignment: 8 | ||
| 182 | ; CHECK-NEXT: Flags: [ ] | ||
| 183 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 184 | ; CHECK-NEXT: Name: name | ||
| 185 | ; CHECK-NEXT: FunctionNames: | ||
| 186 | ; CHECK-NEXT: - Index: 0 | ||
| 187 | ; CHECK-NEXT: Name: puts | ||
| 188 | ; CHECK-NEXT: - Index: 1 | ||
| 189 | ; CHECK-NEXT: Name: foo_import | ||
| 190 | ; CHECK-NEXT: - Index: 2 | ||
| 191 | ; CHECK-NEXT: Name: hello | ||
| 192 | ; CHECK-NEXT: - Index: 3 | ||
| 193 | ; CHECK-NEXT: Name: my_func | ||
| 194 | ; CHECK-NEXT: ... | ||
deps/lld/test/wasm/signature-mismatch.ll created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.main.o | ||
| 3 | ; RUN: not lld -flavor wasm --check-signatures -o %t.wasm %t.main.o %t.ret32.o 2>&1 | FileCheck %s | ||
| 4 | |||
| 5 | ; Function Attrs: nounwind | ||
| 6 | define hidden void @_start() local_unnamed_addr #0 { | ||
| 7 | entry: | ||
| 8 | %call = tail call i32 @ret32(i32 1, i64 2, i32 3) #2 | ||
| 9 | ret void | ||
| 10 | } | ||
| 11 | |||
| 12 | declare i32 @ret32(i32, i64, i32) local_unnamed_addr #1 | ||
| 13 | |||
| 14 | ; CHECK: error: function signature mismatch: ret32 | ||
| 15 | ; CHECK-NEXT: >>> defined as (I32, I64, I32) -> I32 in {{.*}}.main.o | ||
| 16 | ; CHECK-NEXT: >>> defined as (F32) -> I32 in {{.*}}.ret32.o | ||
deps/lld/test/wasm/stack-pointer.ll created+64| ... | @@ -0,0 +1,64 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 2 | ; RUN: lld -flavor wasm --emit-relocs -o %t.wasm %t.o | ||
| 3 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 4 | |||
| 5 | ; Function Attrs: nounwind | ||
| 6 | define hidden i32 @_start() local_unnamed_addr { | ||
| 7 | entry: | ||
| 8 | %retval = alloca i32, align 4 | ||
| 9 | ret i32 0 | ||
| 10 | } | ||
| 11 | |||
| 12 | ; CHECK: --- !WASM | ||
| 13 | ; CHECK-NEXT: FileHeader: | ||
| 14 | ; CHECK-NEXT: Version: 0x00000001 | ||
| 15 | ; CHECK-NEXT: Sections: | ||
| 16 | ; CHECK-NEXT: - Type: TYPE | ||
| 17 | ; CHECK-NEXT: Signatures: | ||
| 18 | ; CHECK-NEXT: - Index: 0 | ||
| 19 | ; CHECK-NEXT: ReturnType: I32 | ||
| 20 | ; CHECK-NEXT: ParamTypes: | ||
| 21 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 22 | ; CHECK-NEXT: FunctionTypes: [ 0 ] | ||
| 23 | ; CHECK-NEXT: - Type: TABLE | ||
| 24 | ; CHECK-NEXT: Tables: | ||
| 25 | ; CHECK-NEXT: - ElemType: ANYFUNC | ||
| 26 | ; CHECK-NEXT: Limits: | ||
| 27 | ; CHECK-NEXT: Flags: [ HAS_MAX ] | ||
| 28 | ; CHECK-NEXT: Initial: 0x00000001 | ||
| 29 | ; CHECK-NEXT: Maximum: 0x00000001 | ||
| 30 | ; CHECK-NEXT: - Type: MEMORY | ||
| 31 | ; CHECK-NEXT: Memories: | ||
| 32 | ; CHECK-NEXT: - Initial: 0x00000002 | ||
| 33 | ; CHECK-NEXT: - Type: GLOBAL | ||
| 34 | ; CHECK-NEXT: Globals: | ||
| 35 | ; CHECK-NEXT: - Type: I32 | ||
| 36 | ; CHECK-NEXT: Mutable: true | ||
| 37 | ; CHECK-NEXT: InitExpr: | ||
| 38 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 39 | ; CHECK-NEXT: Value: 66560 | ||
| 40 | ; CHECK-NEXT: - Type: EXPORT | ||
| 41 | ; CHECK-NEXT: Exports: | ||
| 42 | ; CHECK-NEXT: - Name: memory | ||
| 43 | ; CHECK-NEXT: Kind: MEMORY | ||
| 44 | ; CHECK-NEXT: Index: 0 | ||
| 45 | ; CHECK-NEXT: - Name: _start | ||
| 46 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 47 | ; CHECK-NEXT: Index: 0 | ||
| 48 | ; CHECK-NEXT: - Type: CODE | ||
| 49 | ; CHECK-NEXT: Relocations: | ||
| 50 | ; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB | ||
| 51 | ; CHECK-NEXT: Index: 0 | ||
| 52 | ; CHECK-NEXT: Offset: 0x00000004 | ||
| 53 | ; CHECK-NEXT: Functions: | ||
| 54 | ; CHECK-NEXT: - Locals: | ||
| 55 | ; CHECK-NEXT: Body: 23808080800041106B1A41000B | ||
| 56 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 57 | ; CHECK-NEXT: Name: linking | ||
| 58 | ; CHECK-NEXT: DataSize: 0 | ||
| 59 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 60 | ; CHECK-NEXT: Name: name | ||
| 61 | ; CHECK-NEXT: FunctionNames: | ||
| 62 | ; CHECK-NEXT: - Index: 0 | ||
| 63 | ; CHECK-NEXT: Name: _start | ||
| 64 | ; CHECK-NEXT: ... | ||
deps/lld/test/wasm/strip-debug.test created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 2 | RUN: lld -flavor wasm --strip-debug --entry=ret32 -o %t.wasm %t.ret32.o | ||
| 3 | RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 4 | |||
| 5 | # Check that there is no name section | ||
| 6 | CHECK-NOT: Name: name | ||
deps/lld/test/wasm/symbol-type-mismatch.ll created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 3 | ; RUN: not lld -flavor wasm -o %t.wasm %t.o %t.ret32.o 2>&1 | FileCheck %s | ||
| 4 | |||
| 5 | @ret32 = extern_weak global i32, align 4 | ||
| 6 | |||
| 7 | ; CHECK: error: symbol type mismatch: ret32 | ||
| 8 | ; CHECK: >>> defined as Global in {{.*}}symbol-type-mismatch.ll.tmp.o | ||
| 9 | ; CHECK: >>> defined as Function in {{.*}}.ret32.o | ||
deps/lld/test/wasm/undefined-entry.test created+4| ... | @@ -0,0 +1,4 @@ | ||
| 1 | RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/ret32.ll -o %t.ret32.o | ||
| 2 | RUN: not lld -flavor wasm -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s | ||
| 3 | |||
| 4 | CHECK: error: undefined symbol: _start | ||
deps/lld/test/wasm/undefined.ll created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 2 | ; RUN: lld -flavor wasm --allow-undefined -o %t.wasm %t.o | ||
| 3 | |||
| 4 | ; Fails due to undefined 'foo' | ||
| 5 | ; RUN: not lld -flavor wasm -o %t.wasm %t.o 2>&1 | FileCheck %s | ||
| 6 | ; CHECK: error: {{.*}}.o: undefined symbol: foo | ||
| 7 | |||
| 8 | ; But succeeds if we pass a file containing 'foo' as --allow-undefined-file. | ||
| 9 | ; RUN: echo 'foo' > %t.txt | ||
| 10 | ; RUN: lld -flavor wasm --allow-undefined-file=%t.txt -o %t.wasm %t.o | ||
| 11 | |||
| 12 | ; Takes the address of the external foo() resulting in undefined external | ||
| 13 | @bar = hidden local_unnamed_addr global i8* bitcast (i32 ()* @foo to i8*), align 4 | ||
| 14 | |||
| 15 | declare i32 @foo() #0 | ||
| 16 | |||
| 17 | define hidden void @_start() local_unnamed_addr #0 { | ||
| 18 | entry: | ||
| 19 | ret void | ||
| 20 | } | ||
deps/lld/test/wasm/version.ll created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 2 | ; RUN: lld -flavor wasm -o %t.wasm %t.o | ||
| 3 | ; RUN: llvm-readobj -file-headers %t.wasm | FileCheck %s | ||
| 4 | |||
| 5 | define hidden void @_start() local_unnamed_addr #0 { | ||
| 6 | entry: | ||
| 7 | ret void | ||
| 8 | } | ||
| 9 | |||
| 10 | ; CHECK: Format: WASM | ||
| 11 | ; CHECK: Arch: wasm32 | ||
| 12 | ; CHECK: AddressSize: 32bit | ||
| 13 | ; CHECK: Version: 0x1 | ||
deps/lld/test/wasm/visibility-hidden.ll created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s | ||
| 2 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj %S/Inputs/hidden.ll -o %t2.o | ||
| 3 | ; RUN: llvm-ar rcs %t2.a %t2.o | ||
| 4 | ; RUN: lld -flavor wasm %t.o %t2.a -o %t.wasm | ||
| 5 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 6 | |||
| 7 | ; Test that hidden symbols are not exported, whether pulled in from an archive | ||
| 8 | ; or directly. | ||
| 9 | |||
| 10 | define hidden i32 @objectHidden() { | ||
| 11 | entry: | ||
| 12 | ret i32 0 | ||
| 13 | } | ||
| 14 | |||
| 15 | define i32 @objectDefault() { | ||
| 16 | entry: | ||
| 17 | ret i32 0 | ||
| 18 | } | ||
| 19 | |||
| 20 | declare i32 @archiveHidden() | ||
| 21 | declare i32 @archiveDefault() | ||
| 22 | |||
| 23 | define i32 @_start() { | ||
| 24 | entry: | ||
| 25 | %call1 = call i32 @objectHidden() | ||
| 26 | %call2 = call i32 @objectDefault() | ||
| 27 | %call3 = call i32 @archiveHidden() | ||
| 28 | %call4 = call i32 @archiveDefault() | ||
| 29 | ret i32 0 | ||
| 30 | } | ||
| 31 | |||
| 32 | ; CHECK: - Type: EXPORT | ||
| 33 | ; CHECK-NEXT: Exports: | ||
| 34 | ; CHECK-NEXT: - Name: memory | ||
| 35 | ; CHECK-NEXT: Kind: MEMORY | ||
| 36 | ; CHECK-NEXT: Index: 0 | ||
| 37 | ; CHECK-NEXT: - Name: _start | ||
| 38 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 39 | ; CHECK-NEXT: Index: 2 | ||
| 40 | ; CHECK-NEXT: - Name: archiveDefault | ||
| 41 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 42 | ; CHECK-NEXT: Index: 4 | ||
| 43 | ; CHECK-NEXT: - Name: objectDefault | ||
| 44 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 45 | ; CHECK-NEXT: Index: 1 | ||
| 46 | ; CHECK-NEXT: - Type: | ||
deps/lld/test/wasm/weak-alias-overide.ll created+123| ... | @@ -0,0 +1,123 @@ | ||
| 1 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s | ||
| 2 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj %S/Inputs/weak-alias.ll -o %t2.o | ||
| 3 | ; RUN: lld -flavor wasm %t.o %t2.o -o %t.wasm | ||
| 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | ; Test that the strongly defined alias_fn from this file is used both here | ||
| 7 | ; and in call_alias. | ||
| 8 | |||
| 9 | define i32 @alias_fn() local_unnamed_addr #1 { | ||
| 10 | ret i32 1 | ||
| 11 | } | ||
| 12 | |||
| 13 | ; Function Attrs: nounwind uwtable | ||
| 14 | define void @_start() local_unnamed_addr #1 { | ||
| 15 | entry: | ||
| 16 | %call = tail call i32 @alias_fn() #2 | ||
| 17 | ret void | ||
| 18 | } | ||
| 19 | |||
| 20 | ; CHECK: --- !WASM | ||
| 21 | ; CHECK-NEXT: FileHeader: | ||
| 22 | ; CHECK-NEXT: Version: 0x00000001 | ||
| 23 | ; CHECK-NEXT: Sections: | ||
| 24 | ; CHECK-NEXT: - Type: TYPE | ||
| 25 | ; CHECK-NEXT: Signatures: | ||
| 26 | ; CHECK-NEXT: - Index: 0 | ||
| 27 | ; CHECK-NEXT: ReturnType: I32 | ||
| 28 | ; CHECK-NEXT: ParamTypes: | ||
| 29 | ; CHECK-NEXT: - Index: 1 | ||
| 30 | ; CHECK-NEXT: ReturnType: NORESULT | ||
| 31 | ; CHECK-NEXT: ParamTypes: | ||
| 32 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 33 | ; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 0, 0, 0 ] | ||
| 34 | ; CHECK-NEXT: - Type: TABLE | ||
| 35 | ; CHECK-NEXT: Tables: | ||
| 36 | ; CHECK-NEXT: - ElemType: ANYFUNC | ||
| 37 | ; CHECK-NEXT: Limits: | ||
| 38 | ; CHECK-NEXT: Flags: [ HAS_MAX ] | ||
| 39 | ; CHECK-NEXT: Initial: 0x00000003 | ||
| 40 | ; CHECK-NEXT: Maximum: 0x00000003 | ||
| 41 | ; CHECK-NEXT: - Type: MEMORY | ||
| 42 | ; CHECK-NEXT: Memories: | ||
| 43 | ; CHECK-NEXT: - Initial: 0x00000002 | ||
| 44 | ; CHECK-NEXT: - Type: GLOBAL | ||
| 45 | ; CHECK-NEXT: Globals: | ||
| 46 | ; CHECK-NEXT: - Type: I32 | ||
| 47 | ; CHECK-NEXT: Mutable: true | ||
| 48 | ; CHECK-NEXT: InitExpr: | ||
| 49 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 50 | ; CHECK-NEXT: Value: 66560 | ||
| 51 | ; CHECK-NEXT: - Type: EXPORT | ||
| 52 | ; CHECK-NEXT: Exports: | ||
| 53 | ; CHECK-NEXT: - Name: memory | ||
| 54 | ; CHECK-NEXT: Kind: MEMORY | ||
| 55 | ; CHECK-NEXT: Index: 0 | ||
| 56 | ; CHECK-NEXT: - Name: _start | ||
| 57 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 58 | ; CHECK-NEXT: Index: 1 | ||
| 59 | ; CHECK-NEXT: - Name: alias_fn | ||
| 60 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 61 | ; CHECK-NEXT: Index: 0 | ||
| 62 | ; CHECK-NEXT: - Name: direct_fn | ||
| 63 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 64 | ; CHECK-NEXT: Index: 2 | ||
| 65 | ; CHECK-NEXT: - Name: call_direct | ||
| 66 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 67 | ; CHECK-NEXT: Index: 3 | ||
| 68 | ; CHECK-NEXT: - Name: call_alias | ||
| 69 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 70 | ; CHECK-NEXT: Index: 4 | ||
| 71 | ; CHECK-NEXT: - Name: call_alias_ptr | ||
| 72 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 73 | ; CHECK-NEXT: Index: 5 | ||
| 74 | ; CHECK-NEXT: - Name: call_direct_ptr | ||
| 75 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 76 | ; CHECK-NEXT: Index: 6 | ||
| 77 | ; CHECK-NEXT: - Type: ELEM | ||
| 78 | ; CHECK-NEXT: Segments: | ||
| 79 | ; CHECK-NEXT: - Offset: | ||
| 80 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 81 | ; CHECK-NEXT: Value: 1 | ||
| 82 | ; CHECK-NEXT: Functions: [ 0, 2 ] | ||
| 83 | ; CHECK-NEXT: - Type: CODE | ||
| 84 | ; CHECK-NEXT: Functions: | ||
| 85 | ; CHECK-NEXT: - Locals: | ||
| 86 | ; CHECK-NEXT: Body: 41010B | ||
| 87 | ; CHECK-NEXT: - Locals: | ||
| 88 | ; CHECK-NEXT: Body: 1080808080001A0B | ||
| 89 | ; CHECK-NEXT: - Locals: | ||
| 90 | ; CHECK-NEXT: Body: 41000B | ||
| 91 | ; CHECK-NEXT: - Locals: | ||
| 92 | ; CHECK-NEXT: Body: 1082808080000B | ||
| 93 | ; CHECK-NEXT: - Locals: | ||
| 94 | ; CHECK-NEXT: Body: 1080808080000B | ||
| 95 | ; CHECK-NEXT: - Locals: | ||
| 96 | ; CHECK-NEXT: - Type: I32 | ||
| 97 | ; CHECK-NEXT: Count: 2 | ||
| 98 | ; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081080808080002101200041106A24808080800020010B | ||
| 99 | ; CHECK-NEXT: - Locals: | ||
| 100 | ; CHECK-NEXT: - Type: I32 | ||
| 101 | ; CHECK-NEXT: Count: 2 | ||
| 102 | ; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081082808080002101200041106A24808080800020010B | ||
| 103 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 104 | ; CHECK-NEXT: Name: linking | ||
| 105 | ; CHECK-NEXT: DataSize: 0 | ||
| 106 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 107 | ; CHECK-NEXT: Name: name | ||
| 108 | ; CHECK-NEXT: FunctionNames: | ||
| 109 | ; CHECK-NEXT: - Index: 0 | ||
| 110 | ; CHECK-NEXT: Name: alias_fn | ||
| 111 | ; CHECK-NEXT: - Index: 1 | ||
| 112 | ; CHECK-NEXT: Name: _start | ||
| 113 | ; CHECK-NEXT: - Index: 2 | ||
| 114 | ; CHECK-NEXT: Name: direct_fn | ||
| 115 | ; CHECK-NEXT: - Index: 3 | ||
| 116 | ; CHECK-NEXT: Name: call_direct | ||
| 117 | ; CHECK-NEXT: - Index: 4 | ||
| 118 | ; CHECK-NEXT: Name: call_alias | ||
| 119 | ; CHECK-NEXT: - Index: 5 | ||
| 120 | ; CHECK-NEXT: Name: call_alias_ptr | ||
| 121 | ; CHECK-NEXT: - Index: 6 | ||
| 122 | ; CHECK-NEXT: Name: call_direct_ptr | ||
| 123 | ; CHECK-NEXT: ... | ||
deps/lld/test/wasm/weak-alias.ll created+113| ... | @@ -0,0 +1,113 @@ | ||
| 1 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s | ||
| 2 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj %S/Inputs/weak-alias.ll -o %t2.o | ||
| 3 | ; RUN: lld -flavor wasm %t.o %t2.o -o %t.wasm | ||
| 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 5 | |||
| 6 | ; Test that weak aliases (alias_fn is a weak alias of direct_fn) are linked correctly | ||
| 7 | |||
| 8 | declare i32 @alias_fn() local_unnamed_addr #1 | ||
| 9 | |||
| 10 | ; Function Attrs: nounwind uwtable | ||
| 11 | define i32 @_start() local_unnamed_addr #1 { | ||
| 12 | entry: | ||
| 13 | %call = tail call i32 @alias_fn() #2 | ||
| 14 | ret i32 %call | ||
| 15 | } | ||
| 16 | |||
| 17 | ; CHECK: --- !WASM | ||
| 18 | ; CHECK-NEXT: FileHeader: | ||
| 19 | ; CHECK-NEXT: Version: 0x00000001 | ||
| 20 | ; CHECK-NEXT: Sections: | ||
| 21 | ; CHECK-NEXT: - Type: TYPE | ||
| 22 | ; CHECK-NEXT: Signatures: | ||
| 23 | ; CHECK-NEXT: - Index: 0 | ||
| 24 | ; CHECK-NEXT: ReturnType: I32 | ||
| 25 | ; CHECK-NEXT: ParamTypes: | ||
| 26 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 27 | ; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0 ] | ||
| 28 | ; CHECK-NEXT: - Type: TABLE | ||
| 29 | ; CHECK-NEXT: Tables: | ||
| 30 | ; CHECK-NEXT: - ElemType: ANYFUNC | ||
| 31 | ; CHECK-NEXT: Limits: | ||
| 32 | ; CHECK-NEXT: Flags: [ HAS_MAX ] | ||
| 33 | ; CHECK-NEXT: Initial: 0x00000003 | ||
| 34 | ; CHECK-NEXT: Maximum: 0x00000003 | ||
| 35 | ; CHECK-NEXT: - Type: MEMORY | ||
| 36 | ; CHECK-NEXT: Memories: | ||
| 37 | ; CHECK-NEXT: - Initial: 0x00000002 | ||
| 38 | ; CHECK-NEXT: - Type: GLOBAL | ||
| 39 | ; CHECK-NEXT: Globals: | ||
| 40 | ; CHECK-NEXT: - Type: I32 | ||
| 41 | ; CHECK-NEXT: Mutable: true | ||
| 42 | ; CHECK-NEXT: InitExpr: | ||
| 43 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 44 | ; CHECK-NEXT: Value: 66560 | ||
| 45 | ; CHECK-NEXT: - Type: EXPORT | ||
| 46 | ; CHECK-NEXT: Exports: | ||
| 47 | ; CHECK-NEXT: - Name: memory | ||
| 48 | ; CHECK-NEXT: Kind: MEMORY | ||
| 49 | ; CHECK-NEXT: Index: 0 | ||
| 50 | ; CHECK-NEXT: - Name: _start | ||
| 51 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 52 | ; CHECK-NEXT: Index: 0 | ||
| 53 | ; CHECK-NEXT: - Name: alias_fn | ||
| 54 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 55 | ; CHECK-NEXT: Index: 1 | ||
| 56 | ; CHECK-NEXT: - Name: direct_fn | ||
| 57 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 58 | ; CHECK-NEXT: Index: 1 | ||
| 59 | ; CHECK-NEXT: - Name: call_direct | ||
| 60 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 61 | ; CHECK-NEXT: Index: 2 | ||
| 62 | ; CHECK-NEXT: - Name: call_alias | ||
| 63 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 64 | ; CHECK-NEXT: Index: 3 | ||
| 65 | ; CHECK-NEXT: - Name: call_alias_ptr | ||
| 66 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 67 | ; CHECK-NEXT: Index: 4 | ||
| 68 | ; CHECK-NEXT: - Name: call_direct_ptr | ||
| 69 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 70 | ; CHECK-NEXT: Index: 5 | ||
| 71 | ; CHECK-NEXT: - Type: ELEM | ||
| 72 | ; CHECK-NEXT: Segments: | ||
| 73 | ; CHECK-NEXT: - Offset: | ||
| 74 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 75 | ; CHECK-NEXT: Value: 1 | ||
| 76 | ; CHECK-NEXT: Functions: [ 1, 1 ] | ||
| 77 | ; CHECK-NEXT: - Type: CODE | ||
| 78 | ; CHECK-NEXT: Functions: | ||
| 79 | ; CHECK-NEXT: - Locals: | ||
| 80 | ; CHECK-NEXT: Body: 1081808080000B | ||
| 81 | ; CHECK-NEXT: - Locals: | ||
| 82 | ; CHECK-NEXT: Body: 41000B | ||
| 83 | ; CHECK-NEXT: - Locals: | ||
| 84 | ; CHECK-NEXT: Body: 1081808080000B | ||
| 85 | ; CHECK-NEXT: - Locals: | ||
| 86 | ; CHECK-NEXT: Body: 1081808080000B | ||
| 87 | ; CHECK-NEXT: - Locals: | ||
| 88 | ; CHECK-NEXT: - Type: I32 | ||
| 89 | ; CHECK-NEXT: Count: 2 | ||
| 90 | ; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B | ||
| 91 | ; CHECK-NEXT: - Locals: | ||
| 92 | ; CHECK-NEXT: - Type: I32 | ||
| 93 | ; CHECK-NEXT: Count: 2 | ||
| 94 | ; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081081808080002101200041106A24808080800020010B | ||
| 95 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 96 | ; CHECK-NEXT: Name: linking | ||
| 97 | ; CHECK-NEXT: DataSize: 0 | ||
| 98 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 99 | ; CHECK-NEXT: Name: name | ||
| 100 | ; CHECK-NEXT: FunctionNames: | ||
| 101 | ; CHECK-NEXT: - Index: 0 | ||
| 102 | ; CHECK-NEXT: Name: _start | ||
| 103 | ; CHECK-NEXT: - Index: 1 | ||
| 104 | ; CHECK-NEXT: Name: direct_fn | ||
| 105 | ; CHECK-NEXT: - Index: 2 | ||
| 106 | ; CHECK-NEXT: Name: call_direct | ||
| 107 | ; CHECK-NEXT: - Index: 3 | ||
| 108 | ; CHECK-NEXT: Name: call_alias | ||
| 109 | ; CHECK-NEXT: - Index: 4 | ||
| 110 | ; CHECK-NEXT: Name: call_alias_ptr | ||
| 111 | ; CHECK-NEXT: - Index: 5 | ||
| 112 | ; CHECK-NEXT: Name: call_direct_ptr | ||
| 113 | ; CHECK-NEXT: ... | ||
deps/lld/test/wasm/weak-external.ll created+86| ... | @@ -0,0 +1,86 @@ | ||
| 1 | ; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s | ||
| 2 | ; RUN: lld -flavor wasm -strip-debug %t.o -o %t.wasm | ||
| 3 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 4 | |||
| 5 | ; Test that undefined weak externals (global_var) and (foo) don't cause | ||
| 6 | ; link failures and resolve to zero. | ||
| 7 | |||
| 8 | @global_var = extern_weak global i32, align 4 | ||
| 9 | |||
| 10 | declare extern_weak i32 @foo() | ||
| 11 | |||
| 12 | define i8* @get_address_of_foo() #0 { | ||
| 13 | entry: | ||
| 14 | ret i8* bitcast (i32 ()* @foo to i8*) | ||
| 15 | } | ||
| 16 | |||
| 17 | define i32* @get_address_of_global_var() #0 { | ||
| 18 | ret i32* @global_var | ||
| 19 | } | ||
| 20 | |||
| 21 | define i32 @_start() #0 { | ||
| 22 | entry: | ||
| 23 | %0 = load i32, i32* @global_var, align 4 | ||
| 24 | ret i32 %0 | ||
| 25 | } | ||
| 26 | |||
| 27 | ; CHECK: --- !WASM | ||
| 28 | ; CHECK-NEXT: FileHeader: | ||
| 29 | ; CHECK-NEXT: Version: 0x00000001 | ||
| 30 | ; CHECK-NEXT: Sections: | ||
| 31 | ; CHECK-NEXT: - Type: TYPE | ||
| 32 | ; CHECK-NEXT: Signatures: | ||
| 33 | ; CHECK-NEXT: - Index: 0 | ||
| 34 | ; CHECK-NEXT: ReturnType: I32 | ||
| 35 | ; CHECK-NEXT: ParamTypes: | ||
| 36 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 37 | ; CHECK-NEXT: FunctionTypes: [ 0, 0, 0 ] | ||
| 38 | ; CHECK-NEXT: - Type: TABLE | ||
| 39 | ; CHECK-NEXT: Tables: | ||
| 40 | ; CHECK-NEXT: - ElemType: ANYFUNC | ||
| 41 | ; CHECK-NEXT: Limits: | ||
| 42 | ; CHECK-NEXT: Flags: [ HAS_MAX ] | ||
| 43 | ; CHECK-NEXT: Initial: 0x00000002 | ||
| 44 | ; CHECK-NEXT: Maximum: 0x00000002 | ||
| 45 | ; CHECK-NEXT: - Type: MEMORY | ||
| 46 | ; CHECK-NEXT: Memories: | ||
| 47 | ; CHECK-NEXT: - Initial: 0x00000002 | ||
| 48 | ; CHECK-NEXT: - Type: GLOBAL | ||
| 49 | ; CHECK-NEXT: Globals: | ||
| 50 | ; CHECK-NEXT: - Type: I32 | ||
| 51 | ; CHECK-NEXT: Mutable: true | ||
| 52 | ; CHECK-NEXT: InitExpr: | ||
| 53 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 54 | ; CHECK-NEXT: Value: 66560 | ||
| 55 | ; CHECK-NEXT: - Type: EXPORT | ||
| 56 | ; CHECK-NEXT: Exports: | ||
| 57 | ; CHECK-NEXT: - Name: memory | ||
| 58 | ; CHECK-NEXT: Kind: MEMORY | ||
| 59 | ; CHECK-NEXT: Index: 0 | ||
| 60 | ; CHECK-NEXT: - Name: _start | ||
| 61 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 62 | ; CHECK-NEXT: Index: 2 | ||
| 63 | ; CHECK-NEXT: - Name: get_address_of_foo | ||
| 64 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 65 | ; CHECK-NEXT: Index: 0 | ||
| 66 | ; CHECK-NEXT: - Name: get_address_of_global_var | ||
| 67 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 68 | ; CHECK-NEXT: Index: 1 | ||
| 69 | ; CHECK-NEXT: - Type: ELEM | ||
| 70 | ; CHECK-NEXT: Segments: | ||
| 71 | ; CHECK-NEXT: - Offset: | ||
| 72 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 73 | ; CHECK-NEXT: Value: 1 | ||
| 74 | ; CHECK-NEXT: Functions: [ 0 ] | ||
| 75 | ; CHECK-NEXT: - Type: CODE | ||
| 76 | ; CHECK-NEXT: Functions: | ||
| 77 | ; CHECK-NEXT: - Locals: | ||
| 78 | ; CHECK-NEXT: Body: 4181808080000B | ||
| 79 | ; CHECK-NEXT: - Locals: | ||
| 80 | ; CHECK-NEXT: Body: 41FFFFFFFF7F0B | ||
| 81 | ; CHECK-NEXT: - Locals: | ||
| 82 | ; CHECK-NEXT: Body: 41002802FFFFFFFF0F0B | ||
| 83 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 84 | ; CHECK-NEXT: Name: linking | ||
| 85 | ; CHECK-NEXT: DataSize: 0 | ||
| 86 | ; CHECK-NEXT: ... | ||
deps/lld/test/wasm/weak-symbols.ll created+100| ... | @@ -0,0 +1,100 @@ | ||
| 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/weak-symbol1.ll -o %t1.o | ||
| 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %p/Inputs/weak-symbol2.ll -o %t2.o | ||
| 3 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm %s -o %t.o | ||
| 4 | ; RUN: lld -flavor wasm -o %t.wasm %t.o %t1.o %t2.o | ||
| 5 | ; RUN: obj2yaml %t.wasm | FileCheck %s | ||
| 6 | |||
| 7 | declare i32 @weakFn() local_unnamed_addr | ||
| 8 | @weakGlobal = external global i32 | ||
| 9 | |||
| 10 | define i32 @_start() local_unnamed_addr { | ||
| 11 | entry: | ||
| 12 | %call = call i32 @weakFn() | ||
| 13 | %val = load i32, i32* @weakGlobal, align 4 | ||
| 14 | ret i32 %val | ||
| 15 | } | ||
| 16 | |||
| 17 | ; CHECK: --- !WASM | ||
| 18 | ; CHECK-NEXT: FileHeader: | ||
| 19 | ; CHECK-NEXT: Version: 0x00000001 | ||
| 20 | ; CHECK-NEXT: Sections: | ||
| 21 | ; CHECK-NEXT: - Type: TYPE | ||
| 22 | ; CHECK-NEXT: Signatures: | ||
| 23 | ; CHECK-NEXT: - Index: 0 | ||
| 24 | ; CHECK-NEXT: ReturnType: I32 | ||
| 25 | ; CHECK-NEXT: ParamTypes: | ||
| 26 | ; CHECK-NEXT: - Type: FUNCTION | ||
| 27 | ; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ] | ||
| 28 | ; CHECK-NEXT: - Type: TABLE | ||
| 29 | ; CHECK-NEXT: Tables: | ||
| 30 | ; CHECK-NEXT: - ElemType: ANYFUNC | ||
| 31 | ; CHECK-NEXT: Limits: | ||
| 32 | ; CHECK-NEXT: Flags: [ HAS_MAX ] | ||
| 33 | ; CHECK-NEXT: Initial: 0x00000002 | ||
| 34 | ; CHECK-NEXT: Maximum: 0x00000002 | ||
| 35 | ; CHECK-NEXT: - Type: MEMORY | ||
| 36 | ; CHECK-NEXT: Memories: | ||
| 37 | ; CHECK-NEXT: - Initial: 0x00000002 | ||
| 38 | ; CHECK-NEXT: - Type: GLOBAL | ||
| 39 | ; CHECK-NEXT: Globals: | ||
| 40 | ; CHECK-NEXT: - Type: I32 | ||
| 41 | ; CHECK-NEXT: Mutable: true | ||
| 42 | ; CHECK-NEXT: InitExpr: | ||
| 43 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 44 | ; CHECK-NEXT: Value: 66576 | ||
| 45 | ; CHECK-NEXT: - Type: EXPORT | ||
| 46 | ; CHECK-NEXT: Exports: | ||
| 47 | ; CHECK-NEXT: - Name: memory | ||
| 48 | ; CHECK-NEXT: Kind: MEMORY | ||
| 49 | ; CHECK-NEXT: Index: 0 | ||
| 50 | ; CHECK-NEXT: - Name: _start | ||
| 51 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 52 | ; CHECK-NEXT: Index: 0 | ||
| 53 | ; CHECK-NEXT: - Name: weakFn | ||
| 54 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 55 | ; CHECK-NEXT: Index: 1 | ||
| 56 | ; CHECK-NEXT: - Name: exportWeak1 | ||
| 57 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 58 | ; CHECK-NEXT: Index: 2 | ||
| 59 | ; CHECK-NEXT: - Name: exportWeak2 | ||
| 60 | ; CHECK-NEXT: Kind: FUNCTION | ||
| 61 | ; CHECK-NEXT: Index: 4 | ||
| 62 | ; CHECK-NEXT: - Type: ELEM | ||
| 63 | ; CHECK-NEXT: Segments: | ||
| 64 | ; CHECK-NEXT: - Offset: | ||
| 65 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 66 | ; CHECK-NEXT: Value: 1 | ||
| 67 | ; CHECK-NEXT: Functions: [ 1 ] | ||
| 68 | ; CHECK-NEXT: - Type: CODE | ||
| 69 | ; CHECK-NEXT: Functions: | ||
| 70 | ; CHECK-NEXT: - Locals: | ||
| 71 | ; CHECK-NEXT: Body: 1081808080001A4100280280888080000B | ||
| 72 | ; CHECK-NEXT: - Locals: | ||
| 73 | ; CHECK-NEXT: Body: 41010B | ||
| 74 | ; CHECK-NEXT: - Locals: | ||
| 75 | ; CHECK-NEXT: Body: 4181808080000B | ||
| 76 | ; CHECK-NEXT: - Locals: | ||
| 77 | ; CHECK-NEXT: Body: 41020B | ||
| 78 | ; CHECK-NEXT: - Locals: | ||
| 79 | ; CHECK-NEXT: Body: 4181808080000B | ||
| 80 | ; CHECK-NEXT: - Type: DATA | ||
| 81 | ; CHECK-NEXT: Segments: | ||
| 82 | ; CHECK-NEXT: - SectionOffset: 7 | ||
| 83 | ; CHECK-NEXT: MemoryIndex: 0 | ||
| 84 | ; CHECK-NEXT: Offset: | ||
| 85 | ; CHECK-NEXT: Opcode: I32_CONST | ||
| 86 | ; CHECK-NEXT: Value: 1024 | ||
| 87 | ; CHECK-NEXT: Content: '0100000002000000' | ||
| 88 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 89 | ; CHECK-NEXT: Name: linking | ||
| 90 | ; CHECK-NEXT: DataSize: 8 | ||
| 91 | ; CHECK-NEXT: - Type: CUSTOM | ||
| 92 | ; CHECK-NEXT: Name: name | ||
| 93 | ; CHECK-NEXT: FunctionNames: | ||
| 94 | ; CHECK-NEXT: - Index: 0 | ||
| 95 | ; CHECK-NEXT: Name: _start | ||
| 96 | ; CHECK-NEXT: - Index: 2 | ||
| 97 | ; CHECK-NEXT: Name: exportWeak1 | ||
| 98 | ; CHECK-NEXT: - Index: 4 | ||
| 99 | ; CHECK-NEXT: Name: exportWeak2 | ||
| 100 | ; CHECK-NEXT: ... | ||
deps/lld/tools/lld/CMakeLists.txt+5-2| ... | @@ -7,16 +7,19 @@ add_lld_tool(lld | ... | @@ -7,16 +7,19 @@ add_lld_tool(lld |
| 7 | ) | 7 | ) |
| 8 | 8 | ||
| 9 | target_link_libraries(lld | 9 | target_link_libraries(lld |
| 10 | lldDriver | 10 | PRIVATE |
| 11 | lldCOFF | 11 | lldCOFF |
| 12 | lldDriver | ||
| 12 | lldELF | 13 | lldELF |
| 14 | lldMinGW | ||
| 15 | lldWasm | ||
| 13 | ) | 16 | ) |
| 14 | 17 | ||
| 15 | install(TARGETS lld | 18 | install(TARGETS lld |
| 16 | RUNTIME DESTINATION bin) | 19 | RUNTIME DESTINATION bin) |
| 17 | 20 | ||
| 18 | if(NOT LLD_SYMLINKS_TO_CREATE) | 21 | if(NOT LLD_SYMLINKS_TO_CREATE) |
| 19 | set(LLD_SYMLINKS_TO_CREATE lld-link ld.lld) | 22 | set(LLD_SYMLINKS_TO_CREATE lld-link ld.lld ld64.lld wasm-ld) |
| 20 | endif() | 23 | endif() |
| 21 | 24 | ||
| 22 | foreach(link ${LLD_SYMLINKS_TO_CREATE}) | 25 | foreach(link ${LLD_SYMLINKS_TO_CREATE}) |
deps/lld/tools/lld/lld.cpp+18-2| ... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
| 16 | // | 16 | // |
| 17 | //===----------------------------------------------------------------------===// | 17 | //===----------------------------------------------------------------------===// |
| 18 | 18 | ||
| 19 | #include "lld/Driver/Driver.h" | 19 | #include "lld/Common/Driver.h" |
| 20 | #include "llvm/ADT/STLExtras.h" | 20 | #include "llvm/ADT/STLExtras.h" |
| 21 | #include "llvm/ADT/StringSwitch.h" | 21 | #include "llvm/ADT/StringSwitch.h" |
| 22 | #include "llvm/ADT/Twine.h" | 22 | #include "llvm/ADT/Twine.h" |
| ... | @@ -34,6 +34,7 @@ enum Flavor { | ... | @@ -34,6 +34,7 @@ enum Flavor { |
| 34 | Gnu, // -flavor gnu | 34 | Gnu, // -flavor gnu |
| 35 | WinLink, // -flavor link | 35 | WinLink, // -flavor link |
| 36 | Darwin, // -flavor darwin | 36 | Darwin, // -flavor darwin |
| 37 | Wasm, // -flavor wasm | ||
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| 39 | LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) { | 40 | LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) { |
| ... | @@ -44,11 +45,22 @@ LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) { | ... | @@ -44,11 +45,22 @@ LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) { |
| 44 | static Flavor getFlavor(StringRef S) { | 45 | static Flavor getFlavor(StringRef S) { |
| 45 | return StringSwitch<Flavor>(S) | 46 | return StringSwitch<Flavor>(S) |
| 46 | .CasesLower("ld", "ld.lld", "gnu", Gnu) | 47 | .CasesLower("ld", "ld.lld", "gnu", Gnu) |
| 48 | .CasesLower("wasm", "ld-wasm", Wasm) | ||
| 47 | .CaseLower("link", WinLink) | 49 | .CaseLower("link", WinLink) |
| 48 | .CaseLower("darwin", Darwin) | 50 | .CasesLower("ld64", "ld64.lld", "darwin", Darwin) |
| 49 | .Default(Invalid); | 51 | .Default(Invalid); |
| 50 | } | 52 | } |
| 51 | 53 | ||
| 54 | static bool isPETarget(const std::vector<const char *> &V) { | ||
| 55 | for (auto It = V.begin(); It + 1 != V.end(); ++It) { | ||
| 56 | if (StringRef(*It) != "-m") | ||
| 57 | continue; | ||
| 58 | StringRef S = *(It + 1); | ||
| 59 | return S == "i386pe" || S == "i386pep" || S == "thumb2pe" || S == "arm64pe"; | ||
| 60 | } | ||
| 61 | return false; | ||
| 62 | } | ||
| 63 | |||
| 52 | static Flavor parseProgname(StringRef Progname) { | 64 | static Flavor parseProgname(StringRef Progname) { |
| 53 | #if __APPLE__ | 65 | #if __APPLE__ |
| 54 | // Use Darwin driver for "ld" on Darwin. | 66 | // Use Darwin driver for "ld" on Darwin. |
| ... | @@ -101,11 +113,15 @@ int main(int Argc, const char **Argv) { | ... | @@ -101,11 +113,15 @@ int main(int Argc, const char **Argv) { |
| 101 | std::vector<const char *> Args(Argv, Argv + Argc); | 113 | std::vector<const char *> Args(Argv, Argv + Argc); |
| 102 | switch (parseFlavor(Args)) { | 114 | switch (parseFlavor(Args)) { |
| 103 | case Gnu: | 115 | case Gnu: |
| 116 | if (isPETarget(Args)) | ||
| 117 | return !mingw::link(Args); | ||
| 104 | return !elf::link(Args, true); | 118 | return !elf::link(Args, true); |
| 105 | case WinLink: | 119 | case WinLink: |
| 106 | return !coff::link(Args, true); | 120 | return !coff::link(Args, true); |
| 107 | case Darwin: | 121 | case Darwin: |
| 108 | return !mach_o::link(Args); | 122 | return !mach_o::link(Args); |
| 123 | case Wasm: | ||
| 124 | return !wasm::link(Args, true); | ||
| 109 | default: | 125 | default: |
| 110 | die("lld is a generic driver.\n" | 126 | die("lld is a generic driver.\n" |
| 111 | "Invoke ld.lld (Unix), ld (macOS) or lld-link (Windows) instead."); | 127 | "Invoke ld.lld (Unix), ld (macOS) or lld-link (Windows) instead."); |
deps/lld/unittests/DriverTests/CMakeLists.txt+1| ... | @@ -3,6 +3,7 @@ add_lld_unittest(DriverTests | ... | @@ -3,6 +3,7 @@ add_lld_unittest(DriverTests |
| 3 | ) | 3 | ) |
| 4 | 4 | ||
| 5 | target_link_libraries(DriverTests | 5 | target_link_libraries(DriverTests |
| 6 | PRIVATE | ||
| 6 | lldDriver | 7 | lldDriver |
| 7 | lldMachO | 8 | lldMachO |
| 8 | ) | 9 | ) |
deps/lld/unittests/DriverTests/DarwinLdDriverTest.cpp+1-1| ... | @@ -12,7 +12,7 @@ | ... | @@ -12,7 +12,7 @@ |
| 12 | /// | 12 | /// |
| 13 | //===----------------------------------------------------------------------===// | 13 | //===----------------------------------------------------------------------===// |
| 14 | 14 | ||
| 15 | #include "lld/Driver/Driver.h" | 15 | #include "lld/Common/Driver.h" |
| 16 | #include "lld/ReaderWriter/MachOLinkingContext.h" | 16 | #include "lld/ReaderWriter/MachOLinkingContext.h" |
| 17 | #include "llvm/BinaryFormat/MachO.h" | 17 | #include "llvm/BinaryFormat/MachO.h" |
| 18 | #include "llvm/Support/raw_ostream.h" | 18 | #include "llvm/Support/raw_ostream.h" |
deps/lld/unittests/MachOTests/CMakeLists.txt+1| ... | @@ -7,6 +7,7 @@ add_lld_unittest(lldMachOTests | ... | @@ -7,6 +7,7 @@ add_lld_unittest(lldMachOTests |
| 7 | ) | 7 | ) |
| 8 | 8 | ||
| 9 | target_link_libraries(lldMachOTests | 9 | target_link_libraries(lldMachOTests |
| 10 | PRIVATE | ||
| 10 | lldDriver | 11 | lldDriver |
| 11 | lldMachO | 12 | lldMachO |
| 12 | lldYAML | 13 | lldYAML |
deps/lld/utils/benchmark.py created+135| ... | @@ -0,0 +1,135 @@ | ||
| 1 | #!/usr/bin/env python | ||
| 2 | # | ||
| 3 | # The LLVM Compiler Infrastructure | ||
| 4 | # | ||
| 5 | # This file is distributed under the University of Illinois Open Source | ||
| 6 | # License. See LICENSE.TXT for details. | ||
| 7 | # | ||
| 8 | # ==------------------------------------------------------------------------==# | ||
| 9 | |||
| 10 | import os | ||
| 11 | import glob | ||
| 12 | import re | ||
| 13 | import subprocess | ||
| 14 | import json | ||
| 15 | import datetime | ||
| 16 | import argparse | ||
| 17 | import urllib | ||
| 18 | import urllib2 | ||
| 19 | |||
| 20 | parser = argparse.ArgumentParser() | ||
| 21 | parser.add_argument('benchmark_directory') | ||
| 22 | parser.add_argument('--runs', type=int, default=10) | ||
| 23 | parser.add_argument('--wrapper', default='') | ||
| 24 | parser.add_argument('--machine', required=True) | ||
| 25 | parser.add_argument('--revision', required=True) | ||
| 26 | parser.add_argument('--threads', action='store_true') | ||
| 27 | parser.add_argument('--url', help='The lnt server url to send the results to', | ||
| 28 | default='http://localhost:8000/db_default/v4/link/submitRun') | ||
| 29 | args = parser.parse_args() | ||
| 30 | |||
| 31 | class Bench: | ||
| 32 | def __init__(self, directory, variant): | ||
| 33 | self.directory = directory | ||
| 34 | self.variant = variant | ||
| 35 | def __str__(self): | ||
| 36 | if not self.variant: | ||
| 37 | return self.directory | ||
| 38 | return '%s-%s' % (self.directory, self.variant) | ||
| 39 | |||
| 40 | def getBenchmarks(): | ||
| 41 | ret = [] | ||
| 42 | for i in glob.glob('*/response*.txt'): | ||
| 43 | m = re.match('response-(.*)\.txt', os.path.basename(i)) | ||
| 44 | variant = m.groups()[0] if m else None | ||
| 45 | ret.append(Bench(os.path.dirname(i), variant)) | ||
| 46 | return ret | ||
| 47 | |||
| 48 | def parsePerfNum(num): | ||
| 49 | num = num.replace(b',',b'') | ||
| 50 | try: | ||
| 51 | return int(num) | ||
| 52 | except ValueError: | ||
| 53 | return float(num) | ||
| 54 | |||
| 55 | def parsePerfLine(line): | ||
| 56 | ret = {} | ||
| 57 | line = line.split(b'#')[0].strip() | ||
| 58 | if len(line) != 0: | ||
| 59 | p = line.split() | ||
| 60 | ret[p[1].strip().decode('ascii')] = parsePerfNum(p[0]) | ||
| 61 | return ret | ||
| 62 | |||
| 63 | def parsePerf(output): | ||
| 64 | ret = {} | ||
| 65 | lines = [x.strip() for x in output.split(b'\n')] | ||
| 66 | |||
| 67 | seconds = [x for x in lines if b'seconds time elapsed' in x][0] | ||
| 68 | seconds = seconds.strip().split()[0].strip() | ||
| 69 | ret['seconds-elapsed'] = parsePerfNum(seconds) | ||
| 70 | |||
| 71 | measurement_lines = [x for x in lines if b'#' in x] | ||
| 72 | for l in measurement_lines: | ||
| 73 | ret.update(parsePerfLine(l)) | ||
| 74 | return ret | ||
| 75 | |||
| 76 | def run(cmd): | ||
| 77 | try: | ||
| 78 | return subprocess.check_output(cmd, stderr=subprocess.STDOUT) | ||
| 79 | except subprocess.CalledProcessError as e: | ||
| 80 | print(e.output) | ||
| 81 | raise e | ||
| 82 | |||
| 83 | def combinePerfRun(acc, d): | ||
| 84 | for k,v in d.items(): | ||
| 85 | a = acc.get(k, []) | ||
| 86 | a.append(v) | ||
| 87 | acc[k] = a | ||
| 88 | |||
| 89 | def perf(cmd): | ||
| 90 | # Discard the first run to warm up any system cache. | ||
| 91 | run(cmd) | ||
| 92 | |||
| 93 | ret = {} | ||
| 94 | wrapper_args = [x for x in args.wrapper.split(',') if x] | ||
| 95 | for i in range(args.runs): | ||
| 96 | os.unlink('t') | ||
| 97 | out = run(wrapper_args + ['perf', 'stat'] + cmd) | ||
| 98 | r = parsePerf(out) | ||
| 99 | combinePerfRun(ret, r) | ||
| 100 | os.unlink('t') | ||
| 101 | return ret | ||
| 102 | |||
| 103 | def runBench(bench): | ||
| 104 | thread_arg = [] if args.threads else ['--no-threads'] | ||
| 105 | os.chdir(bench.directory) | ||
| 106 | suffix = '-%s' % bench.variant if bench.variant else '' | ||
| 107 | response = 'response' + suffix + '.txt' | ||
| 108 | ret = perf(['../ld.lld', '@' + response, '-o', 't'] + thread_arg) | ||
| 109 | ret['name'] = str(bench) | ||
| 110 | os.chdir('..') | ||
| 111 | return ret | ||
| 112 | |||
| 113 | def buildLntJson(benchmarks): | ||
| 114 | start = datetime.datetime.utcnow().isoformat() | ||
| 115 | tests = [runBench(b) for b in benchmarks] | ||
| 116 | end = datetime.datetime.utcnow().isoformat() | ||
| 117 | ret = { | ||
| 118 | 'format_version' : 2, | ||
| 119 | 'machine' : { 'name' : args.machine }, | ||
| 120 | 'run' : { | ||
| 121 | 'end_time' : start, | ||
| 122 | 'start_time' : end, | ||
| 123 | 'llvm_project_revision': args.revision | ||
| 124 | }, | ||
| 125 | 'tests' : tests | ||
| 126 | } | ||
| 127 | return json.dumps(ret, sort_keys=True, indent=4) | ||
| 128 | |||
| 129 | def submitToServer(data): | ||
| 130 | data2 = urllib.urlencode({ 'input_data' : data }).encode('ascii') | ||
| 131 | urllib2.urlopen(urllib2.Request(args.url, data2)) | ||
| 132 | |||
| 133 | os.chdir(args.benchmark_directory) | ||
| 134 | data = buildLntJson(getBenchmarks()) | ||
| 135 | submitToServer(data) | ||
deps/lld/utils/link.yaml created+39| ... | @@ -0,0 +1,39 @@ | ||
| 1 | format_version: '2' | ||
| 2 | name: link | ||
| 3 | run_fields: | ||
| 4 | - name: llvm_project_revision | ||
| 5 | order: true | ||
| 6 | machine_fields: | ||
| 7 | - name: hardware | ||
| 8 | - name: os | ||
| 9 | metrics: | ||
| 10 | - name: branch-misses | ||
| 11 | bigger_is_better: false | ||
| 12 | type: Real | ||
| 13 | - name: stalled-cycles-frontend | ||
| 14 | bigger_is_better: false | ||
| 15 | type: Real | ||
| 16 | - name: branches | ||
| 17 | bigger_is_better: false | ||
| 18 | type: Real | ||
| 19 | - name: context-switches | ||
| 20 | bigger_is_better: false | ||
| 21 | type: Real | ||
| 22 | - name: cpu-migrations | ||
| 23 | bigger_is_better: false | ||
| 24 | type: Real | ||
| 25 | - name: cycles | ||
| 26 | bigger_is_better: false | ||
| 27 | type: Real | ||
| 28 | - name: instructions | ||
| 29 | bigger_is_better: false | ||
| 30 | type: Real | ||
| 31 | - name: seconds-elapsed | ||
| 32 | bigger_is_better: false | ||
| 33 | type: Real | ||
| 34 | - name: page-faults | ||
| 35 | bigger_is_better: false | ||
| 36 | type: Real | ||
| 37 | - name: task-clock | ||
| 38 | bigger_is_better: false | ||
| 39 | type: Real | ||
deps/lld/wasm/CMakeLists.txt created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | set(LLVM_TARGET_DEFINITIONS Options.td) | ||
| 2 | tablegen(LLVM Options.inc -gen-opt-parser-defs) | ||
| 3 | add_public_tablegen_target(WasmOptionsTableGen) | ||
| 4 | |||
| 5 | add_lld_library(lldWasm | ||
| 6 | Driver.cpp | ||
| 7 | InputFiles.cpp | ||
| 8 | InputSegment.cpp | ||
| 9 | OutputSections.cpp | ||
| 10 | SymbolTable.cpp | ||
| 11 | Symbols.cpp | ||
| 12 | Writer.cpp | ||
| 13 | WriterUtils.cpp | ||
| 14 | |||
| 15 | LINK_COMPONENTS | ||
| 16 | ${LLVM_TARGETS_TO_BUILD} | ||
| 17 | BinaryFormat | ||
| 18 | Core | ||
| 19 | Demangle | ||
| 20 | Object | ||
| 21 | Option | ||
| 22 | Support | ||
| 23 | |||
| 24 | LINK_LIBS | ||
| 25 | lldCommon | ||
| 26 | ) | ||
deps/lld/wasm/Config.h created+51| ... | @@ -0,0 +1,51 @@ | ||
| 1 | //===- Config.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_WASM_CONFIG_H | ||
| 11 | #define LLD_WASM_CONFIG_H | ||
| 12 | |||
| 13 | #include "llvm/ADT/StringRef.h" | ||
| 14 | #include "llvm/ADT/StringSet.h" | ||
| 15 | #include "llvm/BinaryFormat/Wasm.h" | ||
| 16 | |||
| 17 | #include "Symbols.h" | ||
| 18 | |||
| 19 | using llvm::wasm::WasmGlobal; | ||
| 20 | |||
| 21 | namespace lld { | ||
| 22 | namespace wasm { | ||
| 23 | |||
| 24 | struct Configuration { | ||
| 25 | bool AllowUndefined; | ||
| 26 | bool CheckSignatures; | ||
| 27 | bool Demangle; | ||
| 28 | bool EmitRelocs; | ||
| 29 | bool ImportMemory; | ||
| 30 | bool Relocatable; | ||
| 31 | bool StripAll; | ||
| 32 | bool StripDebug; | ||
| 33 | uint32_t GlobalBase; | ||
| 34 | uint32_t InitialMemory; | ||
| 35 | uint32_t MaxMemory; | ||
| 36 | uint32_t ZStackSize; | ||
| 37 | llvm::StringRef Entry; | ||
| 38 | llvm::StringRef OutputFile; | ||
| 39 | |||
| 40 | llvm::StringSet<> AllowUndefinedSymbols; | ||
| 41 | std::vector<llvm::StringRef> SearchPaths; | ||
| 42 | Symbol *StackPointerSymbol = nullptr; | ||
| 43 | }; | ||
| 44 | |||
| 45 | // The only instance of Configuration struct. | ||
| 46 | extern Configuration *Config; | ||
| 47 | |||
| 48 | } // namespace wasm | ||
| 49 | } // namespace lld | ||
| 50 | |||
| 51 | #endif | ||
deps/lld/wasm/Driver.cpp created+321| ... | @@ -0,0 +1,321 @@ | ||
| 1 | //===- Driver.cpp ---------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "lld/Common/Driver.h" | ||
| 11 | #include "Config.h" | ||
| 12 | #include "SymbolTable.h" | ||
| 13 | #include "Writer.h" | ||
| 14 | #include "lld/Common/Args.h" | ||
| 15 | #include "lld/Common/ErrorHandler.h" | ||
| 16 | #include "lld/Common/Memory.h" | ||
| 17 | #include "lld/Common/Threads.h" | ||
| 18 | #include "lld/Common/Version.h" | ||
| 19 | #include "llvm/ADT/Twine.h" | ||
| 20 | #include "llvm/Object/Wasm.h" | ||
| 21 | #include "llvm/Option/ArgList.h" | ||
| 22 | #include "llvm/Support/CommandLine.h" | ||
| 23 | #include "llvm/Support/Path.h" | ||
| 24 | #include "llvm/Support/Process.h" | ||
| 25 | |||
| 26 | using namespace llvm; | ||
| 27 | using namespace llvm::sys; | ||
| 28 | using namespace llvm::wasm; | ||
| 29 | |||
| 30 | using namespace lld; | ||
| 31 | using namespace lld::wasm; | ||
| 32 | |||
| 33 | namespace { | ||
| 34 | |||
| 35 | // Parses command line options. | ||
| 36 | class WasmOptTable : public llvm::opt::OptTable { | ||
| 37 | public: | ||
| 38 | WasmOptTable(); | ||
| 39 | llvm::opt::InputArgList parse(ArrayRef<const char *> Argv); | ||
| 40 | }; | ||
| 41 | |||
| 42 | // Create enum with OPT_xxx values for each option in Options.td | ||
| 43 | enum { | ||
| 44 | OPT_INVALID = 0, | ||
| 45 | #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, | ||
| 46 | #include "Options.inc" | ||
| 47 | #undef OPTION | ||
| 48 | }; | ||
| 49 | |||
| 50 | class LinkerDriver { | ||
| 51 | public: | ||
| 52 | void link(ArrayRef<const char *> ArgsArr); | ||
| 53 | |||
| 54 | private: | ||
| 55 | void createFiles(llvm::opt::InputArgList &Args); | ||
| 56 | void addFile(StringRef Path); | ||
| 57 | void addLibrary(StringRef Name); | ||
| 58 | std::vector<InputFile *> Files; | ||
| 59 | }; | ||
| 60 | |||
| 61 | } // anonymous namespace | ||
| 62 | |||
| 63 | Configuration *lld::wasm::Config; | ||
| 64 | |||
| 65 | bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly, | ||
| 66 | raw_ostream &Error) { | ||
| 67 | errorHandler().LogName = Args[0]; | ||
| 68 | errorHandler().ErrorOS = &Error; | ||
| 69 | errorHandler().ColorDiagnostics = Error.has_colors(); | ||
| 70 | errorHandler().ErrorLimitExceededMsg = | ||
| 71 | "too many errors emitted, stopping now (use " | ||
| 72 | "-error-limit=0 to see all errors)"; | ||
| 73 | |||
| 74 | Config = make<Configuration>(); | ||
| 75 | Symtab = make<SymbolTable>(); | ||
| 76 | |||
| 77 | LinkerDriver().link(Args); | ||
| 78 | |||
| 79 | // Exit immediately if we don't need to return to the caller. | ||
| 80 | // This saves time because the overhead of calling destructors | ||
| 81 | // for all globally-allocated objects is not negligible. | ||
| 82 | if (CanExitEarly) | ||
| 83 | exitLld(errorCount() ? 1 : 0); | ||
| 84 | |||
| 85 | freeArena(); | ||
| 86 | return !errorCount(); | ||
| 87 | } | ||
| 88 | |||
| 89 | // Create OptTable | ||
| 90 | |||
| 91 | // Create prefix string literals used in Options.td | ||
| 92 | #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; | ||
| 93 | #include "Options.inc" | ||
| 94 | #undef PREFIX | ||
| 95 | |||
| 96 | // Create table mapping all options defined in Options.td | ||
| 97 | static const opt::OptTable::Info OptInfo[] = { | ||
| 98 | #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ | ||
| 99 | {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ | ||
| 100 | X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, | ||
| 101 | #include "Options.inc" | ||
| 102 | #undef OPTION | ||
| 103 | }; | ||
| 104 | |||
| 105 | // Set color diagnostics according to -color-diagnostics={auto,always,never} | ||
| 106 | // or -no-color-diagnostics flags. | ||
| 107 | static void handleColorDiagnostics(opt::InputArgList &Args) { | ||
| 108 | auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, | ||
| 109 | OPT_no_color_diagnostics); | ||
| 110 | if (!Arg) | ||
| 111 | return; | ||
| 112 | |||
| 113 | if (Arg->getOption().getID() == OPT_color_diagnostics) | ||
| 114 | errorHandler().ColorDiagnostics = true; | ||
| 115 | else if (Arg->getOption().getID() == OPT_no_color_diagnostics) | ||
| 116 | errorHandler().ColorDiagnostics = false; | ||
| 117 | else { | ||
| 118 | StringRef S = Arg->getValue(); | ||
| 119 | if (S == "always") | ||
| 120 | errorHandler().ColorDiagnostics = true; | ||
| 121 | if (S == "never") | ||
| 122 | errorHandler().ColorDiagnostics = false; | ||
| 123 | if (S != "auto") | ||
| 124 | error("unknown option: -color-diagnostics=" + S); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | // Find a file by concatenating given paths. | ||
| 129 | static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) { | ||
| 130 | SmallString<128> S; | ||
| 131 | path::append(S, Path1, Path2); | ||
| 132 | if (fs::exists(S)) | ||
| 133 | return S.str().str(); | ||
| 134 | return None; | ||
| 135 | } | ||
| 136 | |||
| 137 | // Inject a new undefined symbol into the link. This will cause the link to | ||
| 138 | // fail unless this symbol can be found. | ||
| 139 | static void addSyntheticUndefinedFunction(StringRef Name, | ||
| 140 | const WasmSignature *Type) { | ||
| 141 | log("injecting undefined func: " + Name); | ||
| 142 | Symtab->addUndefinedFunction(Name, Type); | ||
| 143 | } | ||
| 144 | |||
| 145 | static void printHelp(const char *Argv0) { | ||
| 146 | WasmOptTable().PrintHelp(outs(), Argv0, "LLVM Linker", false); | ||
| 147 | } | ||
| 148 | |||
| 149 | WasmOptTable::WasmOptTable() : OptTable(OptInfo) {} | ||
| 150 | |||
| 151 | opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) { | ||
| 152 | SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); | ||
| 153 | |||
| 154 | unsigned MissingIndex; | ||
| 155 | unsigned MissingCount; | ||
| 156 | opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); | ||
| 157 | |||
| 158 | handleColorDiagnostics(Args); | ||
| 159 | for (auto *Arg : Args.filtered(OPT_UNKNOWN)) | ||
| 160 | error("unknown argument: " + Arg->getSpelling()); | ||
| 161 | return Args; | ||
| 162 | } | ||
| 163 | |||
| 164 | void LinkerDriver::addFile(StringRef Path) { | ||
| 165 | Optional<MemoryBufferRef> Buffer = readFile(Path); | ||
| 166 | if (!Buffer.hasValue()) | ||
| 167 | return; | ||
| 168 | MemoryBufferRef MBRef = *Buffer; | ||
| 169 | |||
| 170 | if (identify_magic(MBRef.getBuffer()) == file_magic::archive) | ||
| 171 | Files.push_back(make<ArchiveFile>(MBRef)); | ||
| 172 | else | ||
| 173 | Files.push_back(make<ObjFile>(MBRef)); | ||
| 174 | } | ||
| 175 | |||
| 176 | // Add a given library by searching it from input search paths. | ||
| 177 | void LinkerDriver::addLibrary(StringRef Name) { | ||
| 178 | for (StringRef Dir : Config->SearchPaths) { | ||
| 179 | if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) { | ||
| 180 | addFile(*S); | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | error("unable to find library -l" + Name); | ||
| 186 | } | ||
| 187 | |||
| 188 | void LinkerDriver::createFiles(opt::InputArgList &Args) { | ||
| 189 | for (auto *Arg : Args) { | ||
| 190 | switch (Arg->getOption().getUnaliasedOption().getID()) { | ||
| 191 | case OPT_l: | ||
| 192 | addLibrary(Arg->getValue()); | ||
| 193 | break; | ||
| 194 | case OPT_INPUT: | ||
| 195 | addFile(Arg->getValue()); | ||
| 196 | break; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | if (Files.empty()) | ||
| 201 | error("no input files"); | ||
| 202 | } | ||
| 203 | |||
| 204 | static StringRef getEntry(opt::InputArgList &Args, StringRef Default) { | ||
| 205 | auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry); | ||
| 206 | if (!Arg) | ||
| 207 | return Default; | ||
| 208 | if (Arg->getOption().getID() == OPT_no_entry) | ||
| 209 | return ""; | ||
| 210 | return Arg->getValue(); | ||
| 211 | } | ||
| 212 | |||
| 213 | void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ||
| 214 | WasmOptTable Parser; | ||
| 215 | opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); | ||
| 216 | |||
| 217 | // Handle --help | ||
| 218 | if (Args.hasArg(OPT_help)) { | ||
| 219 | printHelp(ArgsArr[0]); | ||
| 220 | return; | ||
| 221 | } | ||
| 222 | |||
| 223 | // Parse and evaluate -mllvm options. | ||
| 224 | std::vector<const char *> V; | ||
| 225 | V.push_back("wasm-ld (LLVM option parsing)"); | ||
| 226 | for (auto *Arg : Args.filtered(OPT_mllvm)) | ||
| 227 | V.push_back(Arg->getValue()); | ||
| 228 | cl::ParseCommandLineOptions(V.size(), V.data()); | ||
| 229 | |||
| 230 | errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); | ||
| 231 | |||
| 232 | if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) { | ||
| 233 | outs() << getLLDVersion() << "\n"; | ||
| 234 | return; | ||
| 235 | } | ||
| 236 | |||
| 237 | Config->AllowUndefined = Args.hasArg(OPT_allow_undefined); | ||
| 238 | Config->CheckSignatures = | ||
| 239 | Args.hasFlag(OPT_check_signatures, OPT_no_check_signatures, false); | ||
| 240 | Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); | ||
| 241 | Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start"); | ||
| 242 | Config->ImportMemory = Args.hasArg(OPT_import_memory); | ||
| 243 | Config->OutputFile = Args.getLastArgValue(OPT_o); | ||
| 244 | Config->Relocatable = Args.hasArg(OPT_relocatable); | ||
| 245 | Config->SearchPaths = args::getStrings(Args, OPT_L); | ||
| 246 | Config->StripAll = Args.hasArg(OPT_strip_all); | ||
| 247 | Config->StripDebug = Args.hasArg(OPT_strip_debug); | ||
| 248 | errorHandler().Verbose = Args.hasArg(OPT_verbose); | ||
| 249 | ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); | ||
| 250 | if (Config->Relocatable) | ||
| 251 | Config->EmitRelocs = true; | ||
| 252 | |||
| 253 | Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0); | ||
| 254 | Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024); | ||
| 255 | Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0); | ||
| 256 | Config->ZStackSize = | ||
| 257 | args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize); | ||
| 258 | |||
| 259 | if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) | ||
| 260 | if (Optional<MemoryBufferRef> Buf = readFile(Arg->getValue())) | ||
| 261 | for (StringRef Sym : args::getLines(*Buf)) | ||
| 262 | Config->AllowUndefinedSymbols.insert(Sym); | ||
| 263 | |||
| 264 | if (Config->OutputFile.empty()) | ||
| 265 | error("no output file specified"); | ||
| 266 | |||
| 267 | if (!Args.hasArg(OPT_INPUT)) | ||
| 268 | error("no input files"); | ||
| 269 | |||
| 270 | if (Config->Relocatable && !Config->Entry.empty()) | ||
| 271 | error("entry point specified for relocatable output file"); | ||
| 272 | if (Config->Relocatable && Args.hasArg(OPT_undefined)) | ||
| 273 | error("undefined symbols specified for relocatable output file"); | ||
| 274 | |||
| 275 | if (!Config->Relocatable) { | ||
| 276 | if (!Config->Entry.empty()) { | ||
| 277 | static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; | ||
| 278 | addSyntheticUndefinedFunction(Config->Entry, &Signature); | ||
| 279 | } | ||
| 280 | |||
| 281 | // Handle the `--undefined <sym>` options. | ||
| 282 | for (StringRef S : args::getStrings(Args, OPT_undefined)) | ||
| 283 | addSyntheticUndefinedFunction(S, nullptr); | ||
| 284 | |||
| 285 | Config->StackPointerSymbol = Symtab->addDefinedGlobal("__stack_pointer"); | ||
| 286 | } | ||
| 287 | |||
| 288 | createFiles(Args); | ||
| 289 | if (errorCount()) | ||
| 290 | return; | ||
| 291 | |||
| 292 | // Add all files to the symbol table. This will add almost all | ||
| 293 | // symbols that we need to the symbol table. | ||
| 294 | for (InputFile *F : Files) | ||
| 295 | Symtab->addFile(F); | ||
| 296 | |||
| 297 | // Make sure we have resolved all symbols. | ||
| 298 | if (!Config->Relocatable && !Config->AllowUndefined) { | ||
| 299 | Symtab->reportRemainingUndefines(); | ||
| 300 | } else { | ||
| 301 | // When we allow undefined symbols we cannot include those defined in | ||
| 302 | // -u/--undefined since these undefined symbols have only names and no | ||
| 303 | // function signature, which means they cannot be written to the final | ||
| 304 | // output. | ||
| 305 | for (StringRef S : args::getStrings(Args, OPT_undefined)) { | ||
| 306 | Symbol *Sym = Symtab->find(S); | ||
| 307 | if (!Sym->isDefined()) | ||
| 308 | error("function forced with --undefined not found: " + Sym->getName()); | ||
| 309 | } | ||
| 310 | } | ||
| 311 | if (errorCount()) | ||
| 312 | return; | ||
| 313 | |||
| 314 | if (!Config->Entry.empty() && !Symtab->find(Config->Entry)->isDefined()) | ||
| 315 | error("entry point not found: " + Config->Entry); | ||
| 316 | if (errorCount()) | ||
| 317 | return; | ||
| 318 | |||
| 319 | // Write the result to the file. | ||
| 320 | writeResult(); | ||
| 321 | } | ||
deps/lld/wasm/InputFiles.cpp created+312| ... | @@ -0,0 +1,312 @@ | ||
| 1 | //===- InputFiles.cpp -----------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "InputFiles.h" | ||
| 11 | |||
| 12 | #include "Config.h" | ||
| 13 | #include "InputSegment.h" | ||
| 14 | #include "SymbolTable.h" | ||
| 15 | #include "lld/Common/ErrorHandler.h" | ||
| 16 | #include "lld/Common/Memory.h" | ||
| 17 | #include "llvm/Object/Binary.h" | ||
| 18 | #include "llvm/Object/Wasm.h" | ||
| 19 | #include "llvm/Support/raw_ostream.h" | ||
| 20 | |||
| 21 | #define DEBUG_TYPE "lld" | ||
| 22 | |||
| 23 | using namespace lld; | ||
| 24 | using namespace lld::wasm; | ||
| 25 | |||
| 26 | using namespace llvm; | ||
| 27 | using namespace llvm::object; | ||
| 28 | using namespace llvm::wasm; | ||
| 29 | |||
| 30 | Optional<MemoryBufferRef> lld::wasm::readFile(StringRef Path) { | ||
| 31 | log("Loading: " + Path); | ||
| 32 | |||
| 33 | auto MBOrErr = MemoryBuffer::getFile(Path); | ||
| 34 | if (auto EC = MBOrErr.getError()) { | ||
| 35 | error("cannot open " + Path + ": " + EC.message()); | ||
| 36 | return None; | ||
| 37 | } | ||
| 38 | std::unique_ptr<MemoryBuffer> &MB = *MBOrErr; | ||
| 39 | MemoryBufferRef MBRef = MB->getMemBufferRef(); | ||
| 40 | make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership | ||
| 41 | |||
| 42 | return MBRef; | ||
| 43 | } | ||
| 44 | |||
| 45 | void ObjFile::dumpInfo() const { | ||
| 46 | log("reloc info for: " + getName() + "\n" + | ||
| 47 | " FunctionIndexOffset : " + Twine(FunctionIndexOffset) + "\n" + | ||
| 48 | " NumFunctionImports : " + Twine(NumFunctionImports()) + "\n" + | ||
| 49 | " NumGlobalImports : " + Twine(NumGlobalImports()) + "\n"); | ||
| 50 | } | ||
| 51 | |||
| 52 | bool ObjFile::isImportedFunction(uint32_t Index) const { | ||
| 53 | return Index < NumFunctionImports(); | ||
| 54 | } | ||
| 55 | |||
| 56 | Symbol *ObjFile::getFunctionSymbol(uint32_t Index) const { | ||
| 57 | return FunctionSymbols[Index]; | ||
| 58 | } | ||
| 59 | |||
| 60 | Symbol *ObjFile::getTableSymbol(uint32_t Index) const { | ||
| 61 | return TableSymbols[Index]; | ||
| 62 | } | ||
| 63 | |||
| 64 | Symbol *ObjFile::getGlobalSymbol(uint32_t Index) const { | ||
| 65 | return GlobalSymbols[Index]; | ||
| 66 | } | ||
| 67 | |||
| 68 | uint32_t ObjFile::getRelocatedAddress(uint32_t Index) const { | ||
| 69 | return getGlobalSymbol(Index)->getVirtualAddress(); | ||
| 70 | } | ||
| 71 | |||
| 72 | uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const { | ||
| 73 | Symbol *Sym = getFunctionSymbol(Original); | ||
| 74 | uint32_t Index = Sym->getOutputIndex(); | ||
| 75 | DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": " | ||
| 76 | << Original << " -> " << Index << "\n"); | ||
| 77 | return Index; | ||
| 78 | } | ||
| 79 | |||
| 80 | uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const { | ||
| 81 | return TypeMap[Original]; | ||
| 82 | } | ||
| 83 | |||
| 84 | uint32_t ObjFile::relocateTableIndex(uint32_t Original) const { | ||
| 85 | Symbol *Sym = getTableSymbol(Original); | ||
| 86 | uint32_t Index = Sym->getTableIndex(); | ||
| 87 | DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original | ||
| 88 | << " -> " << Index << "\n"); | ||
| 89 | return Index; | ||
| 90 | } | ||
| 91 | |||
| 92 | uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const { | ||
| 93 | Symbol *Sym = getGlobalSymbol(Original); | ||
| 94 | uint32_t Index = Sym->getOutputIndex(); | ||
| 95 | DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original | ||
| 96 | << " -> " << Index << "\n"); | ||
| 97 | return Index; | ||
| 98 | } | ||
| 99 | |||
| 100 | void ObjFile::parse() { | ||
| 101 | // Parse a memory buffer as a wasm file. | ||
| 102 | DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n"); | ||
| 103 | std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), toString(this)); | ||
| 104 | |||
| 105 | auto *Obj = dyn_cast<WasmObjectFile>(Bin.get()); | ||
| 106 | if (!Obj) | ||
| 107 | fatal(toString(this) + ": not a wasm file"); | ||
| 108 | if (!Obj->isRelocatableObject()) | ||
| 109 | fatal(toString(this) + ": not a relocatable wasm file"); | ||
| 110 | |||
| 111 | Bin.release(); | ||
| 112 | WasmObj.reset(Obj); | ||
| 113 | |||
| 114 | // Find the code and data sections. Wasm objects can have at most one code | ||
| 115 | // and one data section. | ||
| 116 | for (const SectionRef &Sec : WasmObj->sections()) { | ||
| 117 | const WasmSection &Section = WasmObj->getWasmSection(Sec); | ||
| 118 | if (Section.Type == WASM_SEC_CODE) | ||
| 119 | CodeSection = &Section; | ||
| 120 | else if (Section.Type == WASM_SEC_DATA) | ||
| 121 | DataSection = &Section; | ||
| 122 | } | ||
| 123 | |||
| 124 | initializeSymbols(); | ||
| 125 | } | ||
| 126 | |||
| 127 | // Return the InputSegment in which a given symbol is defined. | ||
| 128 | InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) { | ||
| 129 | uint32_t Address = WasmObj->getWasmSymbolValue(WasmSym); | ||
| 130 | for (InputSegment *Segment : Segments) { | ||
| 131 | if (Address >= Segment->startVA() && Address < Segment->endVA()) { | ||
| 132 | DEBUG(dbgs() << "Found symbol in segment: " << WasmSym.Name << " -> " | ||
| 133 | << Segment->getName() << "\n"); | ||
| 134 | |||
| 135 | return Segment; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | error("symbol not found in any segment: " + WasmSym.Name); | ||
| 139 | return nullptr; | ||
| 140 | } | ||
| 141 | |||
| 142 | static void copyRelocationsRange(std::vector<WasmRelocation> &To, | ||
| 143 | ArrayRef<WasmRelocation> From, size_t Start, | ||
| 144 | size_t End) { | ||
| 145 | for (const WasmRelocation &R : From) | ||
| 146 | if (R.Offset >= Start && R.Offset < End) | ||
| 147 | To.push_back(R); | ||
| 148 | } | ||
| 149 | |||
| 150 | void ObjFile::initializeSymbols() { | ||
| 151 | Symbols.reserve(WasmObj->getNumberOfSymbols()); | ||
| 152 | |||
| 153 | for (const WasmImport &Import : WasmObj->imports()) { | ||
| 154 | switch (Import.Kind) { | ||
| 155 | case WASM_EXTERNAL_FUNCTION: | ||
| 156 | ++FunctionImports; | ||
| 157 | break; | ||
| 158 | case WASM_EXTERNAL_GLOBAL: | ||
| 159 | ++GlobalImports; | ||
| 160 | break; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | FunctionSymbols.resize(FunctionImports + WasmObj->functions().size()); | ||
| 165 | GlobalSymbols.resize(GlobalImports + WasmObj->globals().size()); | ||
| 166 | |||
| 167 | for (const WasmSegment &S : WasmObj->dataSegments()) { | ||
| 168 | InputSegment *Seg = make<InputSegment>(&S, this); | ||
| 169 | copyRelocationsRange(Seg->Relocations, DataSection->Relocations, | ||
| 170 | Seg->getInputSectionOffset(), | ||
| 171 | Seg->getInputSectionOffset() + Seg->getSize()); | ||
| 172 | Segments.emplace_back(Seg); | ||
| 173 | } | ||
| 174 | |||
| 175 | // Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols | ||
| 176 | // in the object | ||
| 177 | for (const SymbolRef &Sym : WasmObj->symbols()) { | ||
| 178 | const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl()); | ||
| 179 | Symbol *S; | ||
| 180 | switch (WasmSym.Type) { | ||
| 181 | case WasmSymbol::SymbolType::FUNCTION_IMPORT: | ||
| 182 | case WasmSymbol::SymbolType::GLOBAL_IMPORT: | ||
| 183 | S = createUndefined(WasmSym); | ||
| 184 | break; | ||
| 185 | case WasmSymbol::SymbolType::GLOBAL_EXPORT: | ||
| 186 | S = createDefined(WasmSym, getSegment(WasmSym)); | ||
| 187 | break; | ||
| 188 | case WasmSymbol::SymbolType::FUNCTION_EXPORT: | ||
| 189 | S = createDefined(WasmSym); | ||
| 190 | break; | ||
| 191 | case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: | ||
| 192 | // These are for debugging only, no need to create linker symbols for them | ||
| 193 | continue; | ||
| 194 | } | ||
| 195 | |||
| 196 | Symbols.push_back(S); | ||
| 197 | if (WasmSym.isFunction()) { | ||
| 198 | DEBUG(dbgs() << "Function: " << WasmSym.ElementIndex << " -> " | ||
| 199 | << toString(*S) << "\n"); | ||
| 200 | FunctionSymbols[WasmSym.ElementIndex] = S; | ||
| 201 | if (WasmSym.HasAltIndex) | ||
| 202 | FunctionSymbols[WasmSym.AltIndex] = S; | ||
| 203 | } else { | ||
| 204 | DEBUG(dbgs() << "Global: " << WasmSym.ElementIndex << " -> " | ||
| 205 | << toString(*S) << "\n"); | ||
| 206 | GlobalSymbols[WasmSym.ElementIndex] = S; | ||
| 207 | if (WasmSym.HasAltIndex) | ||
| 208 | GlobalSymbols[WasmSym.AltIndex] = S; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | DEBUG(for (size_t I = 0; I < FunctionSymbols.size(); ++I) | ||
| 213 | assert(FunctionSymbols[I] != nullptr); | ||
| 214 | for (size_t I = 0; I < GlobalSymbols.size(); ++I) | ||
| 215 | assert(GlobalSymbols[I] != nullptr);); | ||
| 216 | |||
| 217 | // Populate `TableSymbols` with all symbols that are called indirectly | ||
| 218 | uint32_t SegmentCount = WasmObj->elements().size(); | ||
| 219 | if (SegmentCount) { | ||
| 220 | if (SegmentCount > 1) | ||
| 221 | fatal(getName() + ": contains more than one element segment"); | ||
| 222 | const WasmElemSegment &Segment = WasmObj->elements()[0]; | ||
| 223 | if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST) | ||
| 224 | fatal(getName() + ": unsupported element segment"); | ||
| 225 | if (Segment.TableIndex != 0) | ||
| 226 | fatal(getName() + ": unsupported table index in elem segment"); | ||
| 227 | if (Segment.Offset.Value.Int32 != 0) | ||
| 228 | fatal(getName() + ": unsupported element segment offset"); | ||
| 229 | TableSymbols.reserve(Segment.Functions.size()); | ||
| 230 | for (uint64_t FunctionIndex : Segment.Functions) | ||
| 231 | TableSymbols.push_back(getFunctionSymbol(FunctionIndex)); | ||
| 232 | } | ||
| 233 | |||
| 234 | DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n"); | ||
| 235 | DEBUG(dbgs() << "Functions : " << FunctionSymbols.size() << "\n"); | ||
| 236 | DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n"); | ||
| 237 | } | ||
| 238 | |||
| 239 | Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) { | ||
| 240 | return Symtab->addUndefined(this, &Sym); | ||
| 241 | } | ||
| 242 | |||
| 243 | Symbol *ObjFile::createDefined(const WasmSymbol &Sym, | ||
| 244 | const InputSegment *Segment) { | ||
| 245 | Symbol *S; | ||
| 246 | if (Sym.isLocal()) { | ||
| 247 | S = make<Symbol>(Sym.Name, true); | ||
| 248 | Symbol::Kind Kind; | ||
| 249 | if (Sym.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT) | ||
| 250 | Kind = Symbol::Kind::DefinedFunctionKind; | ||
| 251 | else if (Sym.Type == WasmSymbol::SymbolType::GLOBAL_EXPORT) | ||
| 252 | Kind = Symbol::Kind::DefinedGlobalKind; | ||
| 253 | else | ||
| 254 | llvm_unreachable("invalid local symbol type"); | ||
| 255 | S->update(Kind, this, &Sym, Segment); | ||
| 256 | return S; | ||
| 257 | } | ||
| 258 | return Symtab->addDefined(this, &Sym, Segment); | ||
| 259 | } | ||
| 260 | |||
| 261 | void ArchiveFile::parse() { | ||
| 262 | // Parse a MemoryBufferRef as an archive file. | ||
| 263 | DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n"); | ||
| 264 | File = CHECK(Archive::create(MB), toString(this)); | ||
| 265 | |||
| 266 | // Read the symbol table to construct Lazy symbols. | ||
| 267 | int Count = 0; | ||
| 268 | for (const Archive::Symbol &Sym : File->symbols()) { | ||
| 269 | Symtab->addLazy(this, &Sym); | ||
| 270 | ++Count; | ||
| 271 | } | ||
| 272 | DEBUG(dbgs() << "Read " << Count << " symbols\n"); | ||
| 273 | } | ||
| 274 | |||
| 275 | void ArchiveFile::addMember(const Archive::Symbol *Sym) { | ||
| 276 | const Archive::Child &C = | ||
| 277 | CHECK(Sym->getMember(), | ||
| 278 | "could not get the member for symbol " + Sym->getName()); | ||
| 279 | |||
| 280 | // Don't try to load the same member twice (this can happen when members | ||
| 281 | // mutually reference each other). | ||
| 282 | if (!Seen.insert(C.getChildOffset()).second) | ||
| 283 | return; | ||
| 284 | |||
| 285 | DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n"); | ||
| 286 | DEBUG(dbgs() << "from archive: " << toString(this) << "\n"); | ||
| 287 | |||
| 288 | MemoryBufferRef MB = | ||
| 289 | CHECK(C.getMemoryBufferRef(), | ||
| 290 | "could not get the buffer for the member defining symbol " + | ||
| 291 | Sym->getName()); | ||
| 292 | |||
| 293 | if (identify_magic(MB.getBuffer()) != file_magic::wasm_object) { | ||
| 294 | error("unknown file type: " + MB.getBufferIdentifier()); | ||
| 295 | return; | ||
| 296 | } | ||
| 297 | |||
| 298 | InputFile *Obj = make<ObjFile>(MB); | ||
| 299 | Obj->ParentName = ParentName; | ||
| 300 | Symtab->addFile(Obj); | ||
| 301 | } | ||
| 302 | |||
| 303 | // Returns a string in the format of "foo.o" or "foo.a(bar.o)". | ||
| 304 | std::string lld::toString(const wasm::InputFile *File) { | ||
| 305 | if (!File) | ||
| 306 | return "<internal>"; | ||
| 307 | |||
| 308 | if (File->ParentName.empty()) | ||
| 309 | return File->getName(); | ||
| 310 | |||
| 311 | return (File->ParentName + "(" + File->getName() + ")").str(); | ||
| 312 | } | ||
deps/lld/wasm/InputFiles.h created+153| ... | @@ -0,0 +1,153 @@ | ||
| 1 | //===- InputFiles.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_WASM_INPUT_FILES_H | ||
| 11 | #define LLD_WASM_INPUT_FILES_H | ||
| 12 | |||
| 13 | #include "lld/Common/LLVM.h" | ||
| 14 | #include "llvm/ADT/DenseMap.h" | ||
| 15 | #include "llvm/ADT/DenseSet.h" | ||
| 16 | #include "llvm/Object/Archive.h" | ||
| 17 | #include "llvm/Object/Wasm.h" | ||
| 18 | #include "llvm/Support/MemoryBuffer.h" | ||
| 19 | |||
| 20 | #include "WriterUtils.h" | ||
| 21 | |||
| 22 | #include <vector> | ||
| 23 | |||
| 24 | using llvm::object::Archive; | ||
| 25 | using llvm::object::WasmObjectFile; | ||
| 26 | using llvm::object::WasmSection; | ||
| 27 | using llvm::object::WasmSymbol; | ||
| 28 | using llvm::wasm::WasmImport; | ||
| 29 | |||
| 30 | namespace lld { | ||
| 31 | namespace wasm { | ||
| 32 | |||
| 33 | class Symbol; | ||
| 34 | class InputSegment; | ||
| 35 | |||
| 36 | class InputFile { | ||
| 37 | public: | ||
| 38 | enum Kind { | ||
| 39 | ObjectKind, | ||
| 40 | ArchiveKind, | ||
| 41 | }; | ||
| 42 | |||
| 43 | virtual ~InputFile() {} | ||
| 44 | |||
| 45 | // Returns the filename. | ||
| 46 | StringRef getName() const { return MB.getBufferIdentifier(); } | ||
| 47 | |||
| 48 | // Reads a file (the constructor doesn't do that). | ||
| 49 | virtual void parse() = 0; | ||
| 50 | |||
| 51 | Kind kind() const { return FileKind; } | ||
| 52 | |||
| 53 | // An archive file name if this file is created from an archive. | ||
| 54 | StringRef ParentName; | ||
| 55 | |||
| 56 | protected: | ||
| 57 | InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} | ||
| 58 | MemoryBufferRef MB; | ||
| 59 | |||
| 60 | private: | ||
| 61 | const Kind FileKind; | ||
| 62 | }; | ||
| 63 | |||
| 64 | // .a file (ar archive) | ||
| 65 | class ArchiveFile : public InputFile { | ||
| 66 | public: | ||
| 67 | explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} | ||
| 68 | static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } | ||
| 69 | |||
| 70 | void addMember(const Archive::Symbol *Sym); | ||
| 71 | |||
| 72 | void parse() override; | ||
| 73 | |||
| 74 | private: | ||
| 75 | std::unique_ptr<Archive> File; | ||
| 76 | llvm::DenseSet<uint64_t> Seen; | ||
| 77 | }; | ||
| 78 | |||
| 79 | // .o file (wasm object file) | ||
| 80 | class ObjFile : public InputFile { | ||
| 81 | public: | ||
| 82 | explicit ObjFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {} | ||
| 83 | static bool classof(const InputFile *F) { return F->kind() == ObjectKind; } | ||
| 84 | |||
| 85 | void parse() override; | ||
| 86 | |||
| 87 | // Returns the underlying wasm file. | ||
| 88 | const WasmObjectFile *getWasmObj() const { return WasmObj.get(); } | ||
| 89 | |||
| 90 | void dumpInfo() const; | ||
| 91 | |||
| 92 | uint32_t relocateTypeIndex(uint32_t Original) const; | ||
| 93 | uint32_t relocateFunctionIndex(uint32_t Original) const; | ||
| 94 | uint32_t relocateGlobalIndex(uint32_t Original) const; | ||
| 95 | uint32_t relocateTableIndex(uint32_t Original) const; | ||
| 96 | uint32_t getRelocatedAddress(uint32_t Index) const; | ||
| 97 | |||
| 98 | // Returns true if the given function index is an imported function, | ||
| 99 | // as opposed to the locally defined function. | ||
| 100 | bool isImportedFunction(uint32_t Index) const; | ||
| 101 | |||
| 102 | size_t NumFunctionImports() const { return FunctionImports; } | ||
| 103 | size_t NumGlobalImports() const { return GlobalImports; } | ||
| 104 | |||
| 105 | int32_t FunctionIndexOffset = 0; | ||
| 106 | const WasmSection *CodeSection = nullptr; | ||
| 107 | std::vector<OutputRelocation> CodeRelocations; | ||
| 108 | int32_t CodeOffset = 0; | ||
| 109 | const WasmSection *DataSection = nullptr; | ||
| 110 | |||
| 111 | std::vector<uint32_t> TypeMap; | ||
| 112 | std::vector<InputSegment *> Segments; | ||
| 113 | |||
| 114 | ArrayRef<Symbol *> getSymbols() { return Symbols; } | ||
| 115 | ArrayRef<Symbol *> getTableSymbols() { return TableSymbols; } | ||
| 116 | |||
| 117 | private: | ||
| 118 | Symbol *createDefined(const WasmSymbol &Sym, | ||
| 119 | const InputSegment *Segment = nullptr); | ||
| 120 | Symbol *createUndefined(const WasmSymbol &Sym); | ||
| 121 | void initializeSymbols(); | ||
| 122 | InputSegment *getSegment(const WasmSymbol &WasmSym); | ||
| 123 | Symbol *getFunctionSymbol(uint32_t FunctionIndex) const; | ||
| 124 | Symbol *getTableSymbol(uint32_t TableIndex) const; | ||
| 125 | Symbol *getGlobalSymbol(uint32_t GlobalIndex) const; | ||
| 126 | |||
| 127 | // List of all symbols referenced or defined by this file. | ||
| 128 | std::vector<Symbol *> Symbols; | ||
| 129 | |||
| 130 | // List of all function symbols indexed by the function index space | ||
| 131 | std::vector<Symbol *> FunctionSymbols; | ||
| 132 | |||
| 133 | // List of all global symbols indexed by the global index space | ||
| 134 | std::vector<Symbol *> GlobalSymbols; | ||
| 135 | |||
| 136 | // List of all indirect symbols indexed by table index space. | ||
| 137 | std::vector<Symbol *> TableSymbols; | ||
| 138 | |||
| 139 | uint32_t GlobalImports = 0; | ||
| 140 | uint32_t FunctionImports = 0; | ||
| 141 | std::unique_ptr<WasmObjectFile> WasmObj; | ||
| 142 | }; | ||
| 143 | |||
| 144 | // Opens a given file. | ||
| 145 | llvm::Optional<MemoryBufferRef> readFile(StringRef Path); | ||
| 146 | |||
| 147 | } // namespace wasm | ||
| 148 | |||
| 149 | std::string toString(const wasm::InputFile *File); | ||
| 150 | |||
| 151 | } // namespace lld | ||
| 152 | |||
| 153 | #endif | ||
deps/lld/wasm/InputSegment.cpp created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | //===- InputSegment.cpp ---------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "InputSegment.h" | ||
| 11 | #include "OutputSegment.h" | ||
| 12 | #include "lld/Common/LLVM.h" | ||
| 13 | |||
| 14 | #define DEBUG_TYPE "lld" | ||
| 15 | |||
| 16 | using namespace llvm; | ||
| 17 | using namespace lld::wasm; | ||
| 18 | |||
| 19 | uint32_t InputSegment::translateVA(uint32_t Address) const { | ||
| 20 | assert(Address >= startVA() && Address < endVA()); | ||
| 21 | int32_t Delta = OutputSeg->StartVA + OutputSegmentOffset - startVA(); | ||
| 22 | DEBUG(dbgs() << "translateVA: " << getName() << " Delta=" << Delta | ||
| 23 | << " Address=" << Address << "\n"); | ||
| 24 | return Address + Delta; | ||
| 25 | } | ||
deps/lld/wasm/InputSegment.h created+76| ... | @@ -0,0 +1,76 @@ | ||
| 1 | //===- InputSegment.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 | // Represents a WebAssembly data segment which can be included as part of | ||
| 11 | // an output data segments. Note that in WebAssembly, unlike ELF and other | ||
| 12 | // formats, used the term "data segment" to refer to the continous regions of | ||
| 13 | // memory that make on the data section. See: | ||
| 14 | // https://webassembly.github.io/spec/syntax/modules.html#syntax-data | ||
| 15 | // | ||
| 16 | // For example, by default, clang will produce a separate data section for | ||
| 17 | // each global variable. | ||
| 18 | // | ||
| 19 | //===----------------------------------------------------------------------===// | ||
| 20 | |||
| 21 | #ifndef LLD_WASM_INPUT_SEGMENT_H | ||
| 22 | #define LLD_WASM_INPUT_SEGMENT_H | ||
| 23 | |||
| 24 | #include "WriterUtils.h" | ||
| 25 | #include "lld/Common/ErrorHandler.h" | ||
| 26 | #include "llvm/Object/Wasm.h" | ||
| 27 | |||
| 28 | using llvm::object::WasmSegment; | ||
| 29 | using llvm::wasm::WasmRelocation; | ||
| 30 | |||
| 31 | namespace lld { | ||
| 32 | namespace wasm { | ||
| 33 | |||
| 34 | class ObjFile; | ||
| 35 | class OutputSegment; | ||
| 36 | |||
| 37 | class InputSegment { | ||
| 38 | public: | ||
| 39 | InputSegment(const WasmSegment *Seg, const ObjFile *F) | ||
| 40 | : Segment(Seg), File(F) {} | ||
| 41 | |||
| 42 | // Translate an offset in the input segment to an offset in the output | ||
| 43 | // segment. | ||
| 44 | uint32_t translateVA(uint32_t Address) const; | ||
| 45 | |||
| 46 | const OutputSegment *getOutputSegment() const { return OutputSeg; } | ||
| 47 | |||
| 48 | uint32_t getOutputSegmentOffset() const { return OutputSegmentOffset; } | ||
| 49 | |||
| 50 | uint32_t getInputSectionOffset() const { return Segment->SectionOffset; } | ||
| 51 | |||
| 52 | void setOutputSegment(const OutputSegment *Segment, uint32_t Offset) { | ||
| 53 | OutputSeg = Segment; | ||
| 54 | OutputSegmentOffset = Offset; | ||
| 55 | } | ||
| 56 | |||
| 57 | uint32_t getSize() const { return Segment->Data.Content.size(); } | ||
| 58 | uint32_t getAlignment() const { return Segment->Data.Alignment; } | ||
| 59 | uint32_t startVA() const { return Segment->Data.Offset.Value.Int32; } | ||
| 60 | uint32_t endVA() const { return startVA() + getSize(); } | ||
| 61 | StringRef getName() const { return Segment->Data.Name; } | ||
| 62 | |||
| 63 | const WasmSegment *Segment; | ||
| 64 | const ObjFile *File; | ||
| 65 | std::vector<WasmRelocation> Relocations; | ||
| 66 | std::vector<OutputRelocation> OutRelocations; | ||
| 67 | |||
| 68 | protected: | ||
| 69 | const OutputSegment *OutputSeg = nullptr; | ||
| 70 | uint32_t OutputSegmentOffset = 0; | ||
| 71 | }; | ||
| 72 | |||
| 73 | } // namespace wasm | ||
| 74 | } // namespace lld | ||
| 75 | |||
| 76 | #endif // LLD_WASM_INPUT_SEGMENT_H | ||
deps/lld/wasm/Options.td created+103| ... | @@ -0,0 +1,103 @@ | ||
| 1 | include "llvm/Option/OptParser.td" | ||
| 2 | |||
| 3 | // For options whose names are multiple letters, either one dash or | ||
| 4 | // two can precede the option name except those that start with 'o'. | ||
| 5 | class F<string name>: Flag<["--", "-"], name>; | ||
| 6 | class J<string name>: Joined<["--", "-"], name>; | ||
| 7 | class S<string name>: Separate<["--", "-"], name>; | ||
| 8 | |||
| 9 | multiclass Eq<string name> { | ||
| 10 | def "": Separate<["--", "-"], name>; | ||
| 11 | def _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>; | ||
| 12 | } | ||
| 13 | |||
| 14 | def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">, | ||
| 15 | HelpText<"Add a directory to the library search path">; | ||
| 16 | |||
| 17 | def color_diagnostics: F<"color-diagnostics">, | ||
| 18 | HelpText<"Use colors in diagnostics">; | ||
| 19 | |||
| 20 | def color_diagnostics_eq: J<"color-diagnostics=">, | ||
| 21 | HelpText<"Use colors in diagnostics">; | ||
| 22 | |||
| 23 | // The follow flags are shared with the ELF linker | ||
| 24 | def help: F<"help">, HelpText<"Print option help">; | ||
| 25 | |||
| 26 | def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">, | ||
| 27 | HelpText<"Root name of library to use">; | ||
| 28 | |||
| 29 | def mllvm: S<"mllvm">, HelpText<"Options to pass to LLVM">; | ||
| 30 | |||
| 31 | def no_threads: F<"no-threads">, | ||
| 32 | HelpText<"Do not run the linker multi-threaded">; | ||
| 33 | |||
| 34 | def no_color_diagnostics: F<"no-color-diagnostics">, | ||
| 35 | HelpText<"Do not use colors in diagnostics">; | ||
| 36 | |||
| 37 | def no_check_signatures: F<"no-check-signatures">, HelpText<"Don't check function signatures">; | ||
| 38 | |||
| 39 | def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">, | ||
| 40 | HelpText<"Path to file to write output">; | ||
| 41 | |||
| 42 | def threads: F<"threads">, HelpText<"Run the linker multi-threaded">; | ||
| 43 | |||
| 44 | def check_signatures: F<"check-signatures">, HelpText<"Check function signatures">; | ||
| 45 | |||
| 46 | def v: Flag<["-"], "v">, HelpText<"Display the version number">; | ||
| 47 | |||
| 48 | def version: F<"version">, HelpText<"Display the version number and exit">; | ||
| 49 | |||
| 50 | def verbose: F<"verbose">, HelpText<"Verbose mode">; | ||
| 51 | |||
| 52 | def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">; | ||
| 53 | |||
| 54 | def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">; | ||
| 55 | |||
| 56 | def strip_all: F<"strip-all">, HelpText<"Strip all symbols">; | ||
| 57 | |||
| 58 | def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; | ||
| 59 | |||
| 60 | defm undefined: Eq<"undefined">, | ||
| 61 | HelpText<"Force undefined symbol during linking">; | ||
| 62 | |||
| 63 | def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">, | ||
| 64 | HelpText<"Linker option extensions">; | ||
| 65 | |||
| 66 | def entry: S<"entry">, MetaVarName<"<entry>">, | ||
| 67 | HelpText<"Name of entry point symbol">; | ||
| 68 | |||
| 69 | def no_entry: F<"no-entry">, | ||
| 70 | HelpText<"Do not output any entry point">; | ||
| 71 | |||
| 72 | def error_limit: J<"error-limit=">, | ||
| 73 | HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">; | ||
| 74 | |||
| 75 | // The follow flags are unique to wasm | ||
| 76 | |||
| 77 | def global_base: J<"global-base=">, | ||
| 78 | HelpText<"Where to start to place global data">; | ||
| 79 | |||
| 80 | def initial_memory: J<"initial-memory=">, | ||
| 81 | HelpText<"Initial size of the linear memory">; | ||
| 82 | |||
| 83 | def max_memory: J<"max-memory=">, | ||
| 84 | HelpText<"Maximum size of the linear memory">; | ||
| 85 | |||
| 86 | def import_memory: F<"import-memory">, | ||
| 87 | HelpText<"Import memory from the environment">; | ||
| 88 | |||
| 89 | def allow_undefined: F<"allow-undefined">, | ||
| 90 | HelpText<"Allow undefined symbols in linked binary">; | ||
| 91 | |||
| 92 | def allow_undefined_file: J<"allow-undefined-file=">, | ||
| 93 | HelpText<"Allow symbols listed in <file> to be undefined in linked binary">; | ||
| 94 | |||
| 95 | def allow_undefined_file_s: Separate<["-"], "allow-undefined-file">, Alias<allow_undefined_file>; | ||
| 96 | |||
| 97 | // Aliases | ||
| 98 | def alias_initial_memory_i: Flag<["-"], "i">, Alias<initial_memory>; | ||
| 99 | def alias_max_memory_m: Flag<["-"], "m">, Alias<max_memory>; | ||
| 100 | def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>; | ||
| 101 | def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; | ||
| 102 | def alias_entry_entry: J<"entry=">, Alias<entry>; | ||
| 103 | def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>; | ||
deps/lld/wasm/OutputSections.cpp created+348| ... | @@ -0,0 +1,348 @@ | ||
| 1 | //===- OutputSections.cpp -------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "OutputSections.h" | ||
| 11 | |||
| 12 | #include "Config.h" | ||
| 13 | #include "InputFiles.h" | ||
| 14 | #include "OutputSegment.h" | ||
| 15 | #include "SymbolTable.h" | ||
| 16 | #include "lld/Common/ErrorHandler.h" | ||
| 17 | #include "lld/Common/Memory.h" | ||
| 18 | #include "lld/Common/Threads.h" | ||
| 19 | #include "llvm/ADT/Twine.h" | ||
| 20 | #include "llvm/Support/LEB128.h" | ||
| 21 | |||
| 22 | #define DEBUG_TYPE "lld" | ||
| 23 | |||
| 24 | using namespace llvm; | ||
| 25 | using namespace llvm::wasm; | ||
| 26 | using namespace lld; | ||
| 27 | using namespace lld::wasm; | ||
| 28 | |||
| 29 | enum class RelocEncoding { | ||
| 30 | Uleb128, | ||
| 31 | Sleb128, | ||
| 32 | I32, | ||
| 33 | }; | ||
| 34 | |||
| 35 | static StringRef sectionTypeToString(uint32_t SectionType) { | ||
| 36 | switch (SectionType) { | ||
| 37 | case WASM_SEC_CUSTOM: | ||
| 38 | return "CUSTOM"; | ||
| 39 | case WASM_SEC_TYPE: | ||
| 40 | return "TYPE"; | ||
| 41 | case WASM_SEC_IMPORT: | ||
| 42 | return "IMPORT"; | ||
| 43 | case WASM_SEC_FUNCTION: | ||
| 44 | return "FUNCTION"; | ||
| 45 | case WASM_SEC_TABLE: | ||
| 46 | return "TABLE"; | ||
| 47 | case WASM_SEC_MEMORY: | ||
| 48 | return "MEMORY"; | ||
| 49 | case WASM_SEC_GLOBAL: | ||
| 50 | return "GLOBAL"; | ||
| 51 | case WASM_SEC_EXPORT: | ||
| 52 | return "EXPORT"; | ||
| 53 | case WASM_SEC_START: | ||
| 54 | return "START"; | ||
| 55 | case WASM_SEC_ELEM: | ||
| 56 | return "ELEM"; | ||
| 57 | case WASM_SEC_CODE: | ||
| 58 | return "CODE"; | ||
| 59 | case WASM_SEC_DATA: | ||
| 60 | return "DATA"; | ||
| 61 | default: | ||
| 62 | fatal("invalid section type"); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | std::string lld::toString(const OutputSection &Section) { | ||
| 67 | std::string rtn = Section.getSectionName(); | ||
| 68 | if (!Section.Name.empty()) | ||
| 69 | rtn += "(" + Section.Name + ")"; | ||
| 70 | return rtn; | ||
| 71 | } | ||
| 72 | |||
| 73 | static void applyRelocation(uint8_t *Buf, const OutputRelocation &Reloc) { | ||
| 74 | DEBUG(dbgs() << "write reloc: type=" << Reloc.Reloc.Type | ||
| 75 | << " index=" << Reloc.Reloc.Index << " value=" << Reloc.Value | ||
| 76 | << " offset=" << Reloc.Reloc.Offset << "\n"); | ||
| 77 | Buf += Reloc.Reloc.Offset; | ||
| 78 | int64_t ExistingValue; | ||
| 79 | switch (Reloc.Reloc.Type) { | ||
| 80 | case R_WEBASSEMBLY_TYPE_INDEX_LEB: | ||
| 81 | case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: | ||
| 82 | ExistingValue = decodeULEB128(Buf); | ||
| 83 | if (ExistingValue != Reloc.Reloc.Index) { | ||
| 84 | DEBUG(dbgs() << "existing value: " << decodeULEB128(Buf) << "\n"); | ||
| 85 | assert(decodeULEB128(Buf) == Reloc.Reloc.Index); | ||
| 86 | } | ||
| 87 | LLVM_FALLTHROUGH; | ||
| 88 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: | ||
| 89 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: | ||
| 90 | encodeULEB128(Reloc.Value, Buf, 5); | ||
| 91 | break; | ||
| 92 | case R_WEBASSEMBLY_TABLE_INDEX_SLEB: | ||
| 93 | ExistingValue = decodeSLEB128(Buf); | ||
| 94 | if (ExistingValue != Reloc.Reloc.Index) { | ||
| 95 | DEBUG(dbgs() << "existing value: " << decodeSLEB128(Buf) << "\n"); | ||
| 96 | assert(decodeSLEB128(Buf) == Reloc.Reloc.Index); | ||
| 97 | } | ||
| 98 | LLVM_FALLTHROUGH; | ||
| 99 | case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: | ||
| 100 | encodeSLEB128(static_cast<int32_t>(Reloc.Value), Buf, 5); | ||
| 101 | break; | ||
| 102 | case R_WEBASSEMBLY_TABLE_INDEX_I32: | ||
| 103 | case R_WEBASSEMBLY_MEMORY_ADDR_I32: | ||
| 104 | support::endian::write32<support::little>(Buf, Reloc.Value); | ||
| 105 | break; | ||
| 106 | default: | ||
| 107 | llvm_unreachable("unknown relocation type"); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | static void applyRelocations(uint8_t *Buf, ArrayRef<OutputRelocation> Relocs) { | ||
| 112 | if (!Relocs.size()) | ||
| 113 | return; | ||
| 114 | log("applyRelocations: count=" + Twine(Relocs.size())); | ||
| 115 | for (const OutputRelocation &Reloc : Relocs) | ||
| 116 | applyRelocation(Buf, Reloc); | ||
| 117 | } | ||
| 118 | |||
| 119 | // Relocations contain an index into the function, global or table index | ||
| 120 | // space of the input file. This function takes a relocation and returns the | ||
| 121 | // relocated index (i.e. translates from the input index space to the output | ||
| 122 | // index space). | ||
| 123 | static uint32_t calcNewIndex(const ObjFile &File, const WasmRelocation &Reloc) { | ||
| 124 | switch (Reloc.Type) { | ||
| 125 | case R_WEBASSEMBLY_TYPE_INDEX_LEB: | ||
| 126 | return File.relocateTypeIndex(Reloc.Index); | ||
| 127 | case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: | ||
| 128 | return File.relocateFunctionIndex(Reloc.Index); | ||
| 129 | case R_WEBASSEMBLY_TABLE_INDEX_I32: | ||
| 130 | case R_WEBASSEMBLY_TABLE_INDEX_SLEB: | ||
| 131 | return File.relocateTableIndex(Reloc.Index); | ||
| 132 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: | ||
| 133 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: | ||
| 134 | case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: | ||
| 135 | case R_WEBASSEMBLY_MEMORY_ADDR_I32: | ||
| 136 | return File.relocateGlobalIndex(Reloc.Index); | ||
| 137 | default: | ||
| 138 | llvm_unreachable("unknown relocation type"); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | // Take a vector of relocations from an input file and create output | ||
| 143 | // relocations based on them. Calculates the updated index and offset for | ||
| 144 | // each relocation as well as the value to write out in the final binary. | ||
| 145 | static void calcRelocations(const ObjFile &File, | ||
| 146 | ArrayRef<WasmRelocation> Relocs, | ||
| 147 | std::vector<OutputRelocation> &OutputRelocs, | ||
| 148 | int32_t OutputOffset) { | ||
| 149 | log("calcRelocations: " + File.getName() + " offset=" + Twine(OutputOffset)); | ||
| 150 | for (const WasmRelocation &Reloc : Relocs) { | ||
| 151 | OutputRelocation NewReloc; | ||
| 152 | NewReloc.Reloc = Reloc; | ||
| 153 | NewReloc.Reloc.Offset += OutputOffset; | ||
| 154 | DEBUG(dbgs() << "reloc: type=" << Reloc.Type << " index=" << Reloc.Index | ||
| 155 | << " offset=" << Reloc.Offset | ||
| 156 | << " newOffset=" << NewReloc.Reloc.Offset << "\n"); | ||
| 157 | |||
| 158 | if (Config->EmitRelocs) | ||
| 159 | NewReloc.NewIndex = calcNewIndex(File, Reloc); | ||
| 160 | else | ||
| 161 | NewReloc.NewIndex = UINT32_MAX; | ||
| 162 | |||
| 163 | switch (Reloc.Type) { | ||
| 164 | case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: | ||
| 165 | case R_WEBASSEMBLY_MEMORY_ADDR_I32: | ||
| 166 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: | ||
| 167 | NewReloc.Value = File.getRelocatedAddress(Reloc.Index); | ||
| 168 | if (NewReloc.Value != UINT32_MAX) | ||
| 169 | NewReloc.Value += Reloc.Addend; | ||
| 170 | break; | ||
| 171 | default: | ||
| 172 | NewReloc.Value = calcNewIndex(File, Reloc); | ||
| 173 | break; | ||
| 174 | } | ||
| 175 | |||
| 176 | OutputRelocs.emplace_back(NewReloc); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | std::string OutputSection::getSectionName() const { | ||
| 181 | return sectionTypeToString(Type); | ||
| 182 | } | ||
| 183 | |||
| 184 | std::string SubSection::getSectionName() const { | ||
| 185 | return std::string("subsection <type=") + std::to_string(Type) + ">"; | ||
| 186 | } | ||
| 187 | |||
| 188 | void OutputSection::createHeader(size_t BodySize) { | ||
| 189 | raw_string_ostream OS(Header); | ||
| 190 | debugWrite(OS.tell(), "section type [" + Twine(getSectionName()) + "]"); | ||
| 191 | writeUleb128(OS, Type, nullptr); | ||
| 192 | writeUleb128(OS, BodySize, "section size"); | ||
| 193 | OS.flush(); | ||
| 194 | log("createHeader: " + toString(*this) + " body=" + Twine(BodySize) + | ||
| 195 | " total=" + Twine(getSize())); | ||
| 196 | } | ||
| 197 | |||
| 198 | CodeSection::CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs) | ||
| 199 | : OutputSection(WASM_SEC_CODE), InputObjects(Objs) { | ||
| 200 | raw_string_ostream OS(CodeSectionHeader); | ||
| 201 | writeUleb128(OS, NumFunctions, "function count"); | ||
| 202 | OS.flush(); | ||
| 203 | BodySize = CodeSectionHeader.size(); | ||
| 204 | |||
| 205 | for (ObjFile *File : InputObjects) { | ||
| 206 | if (!File->CodeSection) | ||
| 207 | continue; | ||
| 208 | |||
| 209 | File->CodeOffset = BodySize; | ||
| 210 | ArrayRef<uint8_t> Content = File->CodeSection->Content; | ||
| 211 | unsigned HeaderSize = 0; | ||
| 212 | decodeULEB128(Content.data(), &HeaderSize); | ||
| 213 | |||
| 214 | calcRelocations(*File, File->CodeSection->Relocations, | ||
| 215 | File->CodeRelocations, BodySize - HeaderSize); | ||
| 216 | |||
| 217 | size_t PayloadSize = Content.size() - HeaderSize; | ||
| 218 | BodySize += PayloadSize; | ||
| 219 | } | ||
| 220 | |||
| 221 | createHeader(BodySize); | ||
| 222 | } | ||
| 223 | |||
| 224 | void CodeSection::writeTo(uint8_t *Buf) { | ||
| 225 | log("writing " + toString(*this)); | ||
| 226 | log(" size=" + Twine(getSize())); | ||
| 227 | Buf += Offset; | ||
| 228 | |||
| 229 | // Write section header | ||
| 230 | memcpy(Buf, Header.data(), Header.size()); | ||
| 231 | Buf += Header.size(); | ||
| 232 | |||
| 233 | uint8_t *ContentsStart = Buf; | ||
| 234 | |||
| 235 | // Write code section headers | ||
| 236 | memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size()); | ||
| 237 | Buf += CodeSectionHeader.size(); | ||
| 238 | |||
| 239 | // Write code section bodies | ||
| 240 | parallelForEach(InputObjects, [ContentsStart](ObjFile *File) { | ||
| 241 | if (!File->CodeSection) | ||
| 242 | return; | ||
| 243 | |||
| 244 | ArrayRef<uint8_t> Content(File->CodeSection->Content); | ||
| 245 | |||
| 246 | // Payload doesn't include the initial header (function count) | ||
| 247 | unsigned HeaderSize = 0; | ||
| 248 | decodeULEB128(Content.data(), &HeaderSize); | ||
| 249 | |||
| 250 | size_t PayloadSize = Content.size() - HeaderSize; | ||
| 251 | memcpy(ContentsStart + File->CodeOffset, Content.data() + HeaderSize, | ||
| 252 | PayloadSize); | ||
| 253 | |||
| 254 | log("applying relocations for: " + File->getName()); | ||
| 255 | applyRelocations(ContentsStart, File->CodeRelocations); | ||
| 256 | }); | ||
| 257 | } | ||
| 258 | |||
| 259 | uint32_t CodeSection::numRelocations() const { | ||
| 260 | uint32_t Count = 0; | ||
| 261 | for (ObjFile *File : InputObjects) | ||
| 262 | Count += File->CodeRelocations.size(); | ||
| 263 | return Count; | ||
| 264 | } | ||
| 265 | |||
| 266 | void CodeSection::writeRelocations(raw_ostream &OS) const { | ||
| 267 | for (ObjFile *File : InputObjects) | ||
| 268 | for (const OutputRelocation &Reloc : File->CodeRelocations) | ||
| 269 | writeReloc(OS, Reloc); | ||
| 270 | } | ||
| 271 | |||
| 272 | DataSection::DataSection(ArrayRef<OutputSegment *> Segments) | ||
| 273 | : OutputSection(WASM_SEC_DATA), Segments(Segments) { | ||
| 274 | raw_string_ostream OS(DataSectionHeader); | ||
| 275 | |||
| 276 | writeUleb128(OS, Segments.size(), "data segment count"); | ||
| 277 | OS.flush(); | ||
| 278 | BodySize = DataSectionHeader.size(); | ||
| 279 | |||
| 280 | for (OutputSegment *Segment : Segments) { | ||
| 281 | raw_string_ostream OS(Segment->Header); | ||
| 282 | writeUleb128(OS, 0, "memory index"); | ||
| 283 | writeUleb128(OS, WASM_OPCODE_I32_CONST, "opcode:i32const"); | ||
| 284 | writeSleb128(OS, Segment->StartVA, "memory offset"); | ||
| 285 | writeUleb128(OS, WASM_OPCODE_END, "opcode:end"); | ||
| 286 | writeUleb128(OS, Segment->Size, "segment size"); | ||
| 287 | OS.flush(); | ||
| 288 | Segment->setSectionOffset(BodySize); | ||
| 289 | BodySize += Segment->Header.size(); | ||
| 290 | log("Data segment: size=" + Twine(Segment->Size)); | ||
| 291 | for (InputSegment *InputSeg : Segment->InputSegments) { | ||
| 292 | uint32_t InputOffset = InputSeg->getInputSectionOffset(); | ||
| 293 | uint32_t OutputOffset = Segment->getSectionOffset() + | ||
| 294 | Segment->Header.size() + | ||
| 295 | InputSeg->getOutputSegmentOffset(); | ||
| 296 | calcRelocations(*InputSeg->File, InputSeg->Relocations, | ||
| 297 | InputSeg->OutRelocations, OutputOffset - InputOffset); | ||
| 298 | } | ||
| 299 | BodySize += Segment->Size; | ||
| 300 | } | ||
| 301 | |||
| 302 | createHeader(BodySize); | ||
| 303 | } | ||
| 304 | |||
| 305 | void DataSection::writeTo(uint8_t *Buf) { | ||
| 306 | log("writing " + toString(*this) + " size=" + Twine(getSize()) + | ||
| 307 | " body=" + Twine(BodySize)); | ||
| 308 | Buf += Offset; | ||
| 309 | |||
| 310 | // Write section header | ||
| 311 | memcpy(Buf, Header.data(), Header.size()); | ||
| 312 | Buf += Header.size(); | ||
| 313 | |||
| 314 | uint8_t *ContentsStart = Buf; | ||
| 315 | |||
| 316 | // Write data section headers | ||
| 317 | memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size()); | ||
| 318 | |||
| 319 | parallelForEach(Segments, [ContentsStart](const OutputSegment *Segment) { | ||
| 320 | // Write data segment header | ||
| 321 | uint8_t *SegStart = ContentsStart + Segment->getSectionOffset(); | ||
| 322 | memcpy(SegStart, Segment->Header.data(), Segment->Header.size()); | ||
| 323 | |||
| 324 | // Write segment data payload | ||
| 325 | for (const InputSegment *Input : Segment->InputSegments) { | ||
| 326 | ArrayRef<uint8_t> Content(Input->Segment->Data.Content); | ||
| 327 | memcpy(SegStart + Segment->Header.size() + | ||
| 328 | Input->getOutputSegmentOffset(), | ||
| 329 | Content.data(), Content.size()); | ||
| 330 | applyRelocations(ContentsStart, Input->OutRelocations); | ||
| 331 | } | ||
| 332 | }); | ||
| 333 | } | ||
| 334 | |||
| 335 | uint32_t DataSection::numRelocations() const { | ||
| 336 | uint32_t Count = 0; | ||
| 337 | for (const OutputSegment *Seg : Segments) | ||
| 338 | for (const InputSegment *InputSeg : Seg->InputSegments) | ||
| 339 | Count += InputSeg->OutRelocations.size(); | ||
| 340 | return Count; | ||
| 341 | } | ||
| 342 | |||
| 343 | void DataSection::writeRelocations(raw_ostream &OS) const { | ||
| 344 | for (const OutputSegment *Seg : Segments) | ||
| 345 | for (const InputSegment *InputSeg : Seg->InputSegments) | ||
| 346 | for (const OutputRelocation &Reloc : InputSeg->OutRelocations) | ||
| 347 | writeReloc(OS, Reloc); | ||
| 348 | } | ||
deps/lld/wasm/OutputSections.h created+136| ... | @@ -0,0 +1,136 @@ | ||
| 1 | //===- OutputSections.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_WASM_OUTPUT_SECTIONS_H | ||
| 11 | #define LLD_WASM_OUTPUT_SECTIONS_H | ||
| 12 | |||
| 13 | #include "InputSegment.h" | ||
| 14 | #include "WriterUtils.h" | ||
| 15 | #include "lld/Common/ErrorHandler.h" | ||
| 16 | #include "llvm/ADT/DenseMap.h" | ||
| 17 | |||
| 18 | using llvm::raw_ostream; | ||
| 19 | using llvm::raw_string_ostream; | ||
| 20 | |||
| 21 | namespace lld { | ||
| 22 | |||
| 23 | namespace wasm { | ||
| 24 | class OutputSection; | ||
| 25 | } | ||
| 26 | std::string toString(const wasm::OutputSection &Section); | ||
| 27 | |||
| 28 | namespace wasm { | ||
| 29 | |||
| 30 | class OutputSegment; | ||
| 31 | class ObjFile; | ||
| 32 | |||
| 33 | class OutputSection { | ||
| 34 | public: | ||
| 35 | OutputSection(uint32_t Type, std::string Name = "") | ||
| 36 | : Type(Type), Name(Name) {} | ||
| 37 | virtual ~OutputSection() = default; | ||
| 38 | |||
| 39 | std::string getSectionName() const; | ||
| 40 | void setOffset(size_t NewOffset) { | ||
| 41 | log("setOffset: " + toString(*this) + ": " + Twine(NewOffset)); | ||
| 42 | Offset = NewOffset; | ||
| 43 | } | ||
| 44 | void createHeader(size_t BodySize); | ||
| 45 | virtual size_t getSize() const = 0; | ||
| 46 | virtual void writeTo(uint8_t *Buf) = 0; | ||
| 47 | virtual void finalizeContents() {} | ||
| 48 | virtual uint32_t numRelocations() const { return 0; } | ||
| 49 | virtual void writeRelocations(raw_ostream &OS) const {} | ||
| 50 | |||
| 51 | std::string Header; | ||
| 52 | uint32_t Type; | ||
| 53 | std::string Name; | ||
| 54 | |||
| 55 | protected: | ||
| 56 | size_t Offset = 0; | ||
| 57 | }; | ||
| 58 | |||
| 59 | class SyntheticSection : public OutputSection { | ||
| 60 | public: | ||
| 61 | SyntheticSection(uint32_t Type, std::string Name = "") | ||
| 62 | : OutputSection(Type, Name), BodyOutputStream(Body) { | ||
| 63 | if (!Name.empty()) | ||
| 64 | writeStr(BodyOutputStream, Name); | ||
| 65 | } | ||
| 66 | |||
| 67 | void writeTo(uint8_t *Buf) override { | ||
| 68 | assert(Offset); | ||
| 69 | log("writing " + toString(*this)); | ||
| 70 | memcpy(Buf + Offset, Header.data(), Header.size()); | ||
| 71 | memcpy(Buf + Offset + Header.size(), Body.data(), Body.size()); | ||
| 72 | } | ||
| 73 | |||
| 74 | size_t getSize() const override { return Header.size() + Body.size(); } | ||
| 75 | |||
| 76 | void finalizeContents() override { | ||
| 77 | BodyOutputStream.flush(); | ||
| 78 | createHeader(Body.size()); | ||
| 79 | } | ||
| 80 | |||
| 81 | raw_ostream &getStream() { return BodyOutputStream; } | ||
| 82 | |||
| 83 | std::string Body; | ||
| 84 | |||
| 85 | protected: | ||
| 86 | raw_string_ostream BodyOutputStream; | ||
| 87 | }; | ||
| 88 | |||
| 89 | // Some synthetic sections (e.g. "name" and "linking") have subsections. | ||
| 90 | // Just like the synthetic sections themselves these need to be created before | ||
| 91 | // they can be written out (since they are preceded by their length). This | ||
| 92 | // class is used to create subsections and then write them into the stream | ||
| 93 | // of the parent section. | ||
| 94 | class SubSection : public SyntheticSection { | ||
| 95 | public: | ||
| 96 | explicit SubSection(uint32_t Type) : SyntheticSection(Type) {} | ||
| 97 | |||
| 98 | std::string getSectionName() const; | ||
| 99 | void writeToStream(raw_ostream &OS) { | ||
| 100 | writeBytes(OS, Header.data(), Header.size()); | ||
| 101 | writeBytes(OS, Body.data(), Body.size()); | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | |||
| 105 | class CodeSection : public OutputSection { | ||
| 106 | public: | ||
| 107 | explicit CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs); | ||
| 108 | size_t getSize() const override { return Header.size() + BodySize; } | ||
| 109 | void writeTo(uint8_t *Buf) override; | ||
| 110 | uint32_t numRelocations() const override; | ||
| 111 | void writeRelocations(raw_ostream &OS) const override; | ||
| 112 | |||
| 113 | protected: | ||
| 114 | ArrayRef<ObjFile *> InputObjects; | ||
| 115 | std::string CodeSectionHeader; | ||
| 116 | size_t BodySize = 0; | ||
| 117 | }; | ||
| 118 | |||
| 119 | class DataSection : public OutputSection { | ||
| 120 | public: | ||
| 121 | explicit DataSection(ArrayRef<OutputSegment *> Segments); | ||
| 122 | size_t getSize() const override { return Header.size() + BodySize; } | ||
| 123 | void writeTo(uint8_t *Buf) override; | ||
| 124 | uint32_t numRelocations() const override; | ||
| 125 | void writeRelocations(raw_ostream &OS) const override; | ||
| 126 | |||
| 127 | protected: | ||
| 128 | ArrayRef<OutputSegment *> Segments; | ||
| 129 | std::string DataSectionHeader; | ||
| 130 | size_t BodySize = 0; | ||
| 131 | }; | ||
| 132 | |||
| 133 | } // namespace wasm | ||
| 134 | } // namespace lld | ||
| 135 | |||
| 136 | #endif // LLD_WASM_OUTPUT_SECTIONS_H | ||
deps/lld/wasm/OutputSegment.h created+56| ... | @@ -0,0 +1,56 @@ | ||
| 1 | //===- OutputSegment.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_WASM_OUTPUT_SEGMENT_H | ||
| 11 | #define LLD_WASM_OUTPUT_SEGMENT_H | ||
| 12 | |||
| 13 | #include "InputSegment.h" | ||
| 14 | #include "lld/Common/ErrorHandler.h" | ||
| 15 | #include "llvm/Object/Wasm.h" | ||
| 16 | |||
| 17 | namespace lld { | ||
| 18 | namespace wasm { | ||
| 19 | |||
| 20 | class InputSegment; | ||
| 21 | |||
| 22 | class OutputSegment { | ||
| 23 | public: | ||
| 24 | OutputSegment(StringRef N) : Name(N) {} | ||
| 25 | |||
| 26 | void addInputSegment(InputSegment *Segment) { | ||
| 27 | Alignment = std::max(Alignment, Segment->getAlignment()); | ||
| 28 | InputSegments.push_back(Segment); | ||
| 29 | Size = llvm::alignTo(Size, Segment->getAlignment()); | ||
| 30 | Segment->setOutputSegment(this, Size); | ||
| 31 | Size += Segment->getSize(); | ||
| 32 | } | ||
| 33 | |||
| 34 | uint32_t getSectionOffset() const { return SectionOffset; } | ||
| 35 | |||
| 36 | void setSectionOffset(uint32_t Offset) { SectionOffset = Offset; } | ||
| 37 | |||
| 38 | StringRef Name; | ||
| 39 | uint32_t Alignment = 0; | ||
| 40 | uint32_t StartVA = 0; | ||
| 41 | std::vector<InputSegment *> InputSegments; | ||
| 42 | |||
| 43 | // Sum of the size of the all the input segments | ||
| 44 | uint32_t Size = 0; | ||
| 45 | |||
| 46 | // Segment header | ||
| 47 | std::string Header; | ||
| 48 | |||
| 49 | private: | ||
| 50 | uint32_t SectionOffset = 0; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace wasm | ||
| 54 | } // namespace lld | ||
| 55 | |||
| 56 | #endif // LLD_WASM_OUTPUT_SEGMENT_H | ||
deps/lld/wasm/SymbolTable.cpp created+237| ... | @@ -0,0 +1,237 @@ | ||
| 1 | //===- SymbolTable.cpp ----------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "SymbolTable.h" | ||
| 11 | |||
| 12 | #include "Config.h" | ||
| 13 | #include "WriterUtils.h" | ||
| 14 | #include "lld/Common/ErrorHandler.h" | ||
| 15 | #include "lld/Common/Memory.h" | ||
| 16 | |||
| 17 | #include <unordered_set> | ||
| 18 | |||
| 19 | #define DEBUG_TYPE "lld" | ||
| 20 | |||
| 21 | using namespace llvm; | ||
| 22 | using namespace lld; | ||
| 23 | using namespace lld::wasm; | ||
| 24 | |||
| 25 | SymbolTable *lld::wasm::Symtab; | ||
| 26 | |||
| 27 | void SymbolTable::addFile(InputFile *File) { | ||
| 28 | log("Processing: " + toString(File)); | ||
| 29 | File->parse(); | ||
| 30 | |||
| 31 | if (auto *F = dyn_cast<ObjFile>(File)) | ||
| 32 | ObjectFiles.push_back(F); | ||
| 33 | } | ||
| 34 | |||
| 35 | void SymbolTable::reportRemainingUndefines() { | ||
| 36 | std::unordered_set<Symbol *> Undefs; | ||
| 37 | for (Symbol *Sym : SymVector) { | ||
| 38 | if (Sym->isUndefined() && !Sym->isWeak() && | ||
| 39 | Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) { | ||
| 40 | Undefs.insert(Sym); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | if (Undefs.empty()) | ||
| 45 | return; | ||
| 46 | |||
| 47 | for (ObjFile *File : ObjectFiles) | ||
| 48 | for (Symbol *Sym : File->getSymbols()) | ||
| 49 | if (Undefs.count(Sym)) | ||
| 50 | error(toString(File) + ": undefined symbol: " + toString(*Sym)); | ||
| 51 | |||
| 52 | for (Symbol *Sym : Undefs) | ||
| 53 | if (!Sym->getFile()) | ||
| 54 | error("undefined symbol: " + toString(*Sym)); | ||
| 55 | } | ||
| 56 | |||
| 57 | Symbol *SymbolTable::find(StringRef Name) { | ||
| 58 | auto It = SymMap.find(CachedHashStringRef(Name)); | ||
| 59 | if (It == SymMap.end()) | ||
| 60 | return nullptr; | ||
| 61 | return It->second; | ||
| 62 | } | ||
| 63 | |||
| 64 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { | ||
| 65 | Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; | ||
| 66 | if (Sym) | ||
| 67 | return {Sym, false}; | ||
| 68 | Sym = make<Symbol>(Name, false); | ||
| 69 | SymVector.emplace_back(Sym); | ||
| 70 | return {Sym, true}; | ||
| 71 | } | ||
| 72 | |||
| 73 | void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) { | ||
| 74 | error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + | ||
| 75 | toString(Existing->getFile()) + "\n>>> defined in " + | ||
| 76 | toString(NewFile)); | ||
| 77 | } | ||
| 78 | |||
| 79 | // Get the signature for a given function symbol, either by looking | ||
| 80 | // it up in function sections (for defined functions), of the imports section | ||
| 81 | // (for imported functions). | ||
| 82 | static const WasmSignature *getFunctionSig(const ObjFile &Obj, | ||
| 83 | const WasmSymbol &Sym) { | ||
| 84 | DEBUG(dbgs() << "getFunctionSig: " << Sym.Name << "\n"); | ||
| 85 | const WasmObjectFile *WasmObj = Obj.getWasmObj(); | ||
| 86 | return &WasmObj->types()[Sym.FunctionType]; | ||
| 87 | } | ||
| 88 | |||
| 89 | // Check the type of new symbol matches that of the symbol is replacing. | ||
| 90 | // For functions this can also involve verifying that the signatures match. | ||
| 91 | static void checkSymbolTypes(const Symbol &Existing, const InputFile &F, | ||
| 92 | const WasmSymbol &New, | ||
| 93 | const WasmSignature *NewSig) { | ||
| 94 | if (Existing.isLazy()) | ||
| 95 | return; | ||
| 96 | |||
| 97 | bool NewIsFunction = New.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT || | ||
| 98 | New.Type == WasmSymbol::SymbolType::FUNCTION_IMPORT; | ||
| 99 | |||
| 100 | // First check the symbol types match (i.e. either both are function | ||
| 101 | // symbols or both are data symbols). | ||
| 102 | if (Existing.isFunction() != NewIsFunction) { | ||
| 103 | error("symbol type mismatch: " + New.Name + "\n>>> defined as " + | ||
| 104 | (Existing.isFunction() ? "Function" : "Global") + " in " + | ||
| 105 | toString(Existing.getFile()) + "\n>>> defined as " + | ||
| 106 | (NewIsFunction ? "Function" : "Global") + " in " + F.getName()); | ||
| 107 | return; | ||
| 108 | } | ||
| 109 | |||
| 110 | // For function symbols, optionally check the function signature matches too. | ||
| 111 | if (!NewIsFunction || !Config->CheckSignatures) | ||
| 112 | return; | ||
| 113 | // Skip the signature check if the existing function has no signature (e.g. | ||
| 114 | // if it is an undefined symbol generated by --undefined command line flag). | ||
| 115 | if (!Existing.hasFunctionType()) | ||
| 116 | return; | ||
| 117 | |||
| 118 | DEBUG(dbgs() << "checkSymbolTypes: " << New.Name << "\n"); | ||
| 119 | assert(NewSig); | ||
| 120 | |||
| 121 | const WasmSignature &OldSig = Existing.getFunctionType(); | ||
| 122 | if (*NewSig == OldSig) | ||
| 123 | return; | ||
| 124 | |||
| 125 | error("function signature mismatch: " + New.Name + "\n>>> defined as " + | ||
| 126 | toString(OldSig) + " in " + toString(Existing.getFile()) + | ||
| 127 | "\n>>> defined as " + toString(*NewSig) + " in " + F.getName()); | ||
| 128 | } | ||
| 129 | |||
| 130 | Symbol *SymbolTable::addDefinedGlobal(StringRef Name) { | ||
| 131 | DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n"); | ||
| 132 | Symbol *S; | ||
| 133 | bool WasInserted; | ||
| 134 | std::tie(S, WasInserted) = insert(Name); | ||
| 135 | if (WasInserted) | ||
| 136 | S->update(Symbol::DefinedGlobalKind); | ||
| 137 | else if (!S->isGlobal()) | ||
| 138 | error("symbol type mismatch: " + Name); | ||
| 139 | return S; | ||
| 140 | } | ||
| 141 | |||
| 142 | Symbol *SymbolTable::addDefined(InputFile *F, const WasmSymbol *Sym, | ||
| 143 | const InputSegment *Segment) { | ||
| 144 | DEBUG(dbgs() << "addDefined: " << Sym->Name << "\n"); | ||
| 145 | Symbol *S; | ||
| 146 | bool WasInserted; | ||
| 147 | Symbol::Kind Kind = Symbol::DefinedFunctionKind; | ||
| 148 | const WasmSignature *NewSig = nullptr; | ||
| 149 | if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_EXPORT) | ||
| 150 | Kind = Symbol::DefinedGlobalKind; | ||
| 151 | else | ||
| 152 | NewSig = getFunctionSig(*cast<ObjFile>(F), *Sym); | ||
| 153 | |||
| 154 | std::tie(S, WasInserted) = insert(Sym->Name); | ||
| 155 | if (WasInserted) { | ||
| 156 | S->update(Kind, F, Sym, Segment, NewSig); | ||
| 157 | } else if (S->isLazy()) { | ||
| 158 | // The existing symbol is lazy. Replace it without checking types since | ||
| 159 | // lazy symbols don't have any type information. | ||
| 160 | DEBUG(dbgs() << "replacing existing lazy symbol: " << Sym->Name << "\n"); | ||
| 161 | S->update(Kind, F, Sym, Segment, NewSig); | ||
| 162 | } else if (!S->isDefined()) { | ||
| 163 | // The existing symbol table entry is undefined. The new symbol replaces | ||
| 164 | // it, after checking the type matches | ||
| 165 | DEBUG(dbgs() << "resolving existing undefined symbol: " << Sym->Name | ||
| 166 | << "\n"); | ||
| 167 | checkSymbolTypes(*S, *F, *Sym, NewSig); | ||
| 168 | S->update(Kind, F, Sym, Segment, NewSig); | ||
| 169 | } else if (Sym->isWeak()) { | ||
| 170 | // the new symbol is weak we can ignore it | ||
| 171 | DEBUG(dbgs() << "existing symbol takes precedence\n"); | ||
| 172 | } else if (S->isWeak()) { | ||
| 173 | // the new symbol is not weak and the existing symbol is, so we replace | ||
| 174 | // it | ||
| 175 | DEBUG(dbgs() << "replacing existing weak symbol\n"); | ||
| 176 | checkSymbolTypes(*S, *F, *Sym, NewSig); | ||
| 177 | S->update(Kind, F, Sym, Segment, NewSig); | ||
| 178 | } else { | ||
| 179 | // neither symbol is week. They conflict. | ||
| 180 | reportDuplicate(S, F); | ||
| 181 | } | ||
| 182 | return S; | ||
| 183 | } | ||
| 184 | |||
| 185 | Symbol *SymbolTable::addUndefinedFunction(StringRef Name, | ||
| 186 | const WasmSignature *Type) { | ||
| 187 | Symbol *S; | ||
| 188 | bool WasInserted; | ||
| 189 | std::tie(S, WasInserted) = insert(Name); | ||
| 190 | if (WasInserted) { | ||
| 191 | S->update(Symbol::UndefinedFunctionKind, nullptr, nullptr, nullptr, Type); | ||
| 192 | } else if (!S->isFunction()) { | ||
| 193 | error("symbol type mismatch: " + Name); | ||
| 194 | } | ||
| 195 | return S; | ||
| 196 | } | ||
| 197 | |||
| 198 | Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym) { | ||
| 199 | DEBUG(dbgs() << "addUndefined: " << Sym->Name << "\n"); | ||
| 200 | Symbol *S; | ||
| 201 | bool WasInserted; | ||
| 202 | Symbol::Kind Kind = Symbol::UndefinedFunctionKind; | ||
| 203 | const WasmSignature *NewSig = nullptr; | ||
| 204 | if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_IMPORT) | ||
| 205 | Kind = Symbol::UndefinedGlobalKind; | ||
| 206 | else | ||
| 207 | NewSig = getFunctionSig(*cast<ObjFile>(F), *Sym); | ||
| 208 | std::tie(S, WasInserted) = insert(Sym->Name); | ||
| 209 | if (WasInserted) { | ||
| 210 | S->update(Kind, F, Sym, nullptr, NewSig); | ||
| 211 | } else if (S->isLazy()) { | ||
| 212 | DEBUG(dbgs() << "resolved by existing lazy\n"); | ||
| 213 | auto *AF = cast<ArchiveFile>(S->getFile()); | ||
| 214 | AF->addMember(&S->getArchiveSymbol()); | ||
| 215 | } else if (S->isDefined()) { | ||
| 216 | DEBUG(dbgs() << "resolved by existing\n"); | ||
| 217 | checkSymbolTypes(*S, *F, *Sym, NewSig); | ||
| 218 | } | ||
| 219 | return S; | ||
| 220 | } | ||
| 221 | |||
| 222 | void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) { | ||
| 223 | DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); | ||
| 224 | StringRef Name = Sym->getName(); | ||
| 225 | Symbol *S; | ||
| 226 | bool WasInserted; | ||
| 227 | std::tie(S, WasInserted) = insert(Name); | ||
| 228 | if (WasInserted) { | ||
| 229 | S->update(Symbol::LazyKind, F); | ||
| 230 | S->setArchiveSymbol(*Sym); | ||
| 231 | } else if (S->isUndefined()) { | ||
| 232 | // There is an existing undefined symbol. The can load from the | ||
| 233 | // archive. | ||
| 234 | DEBUG(dbgs() << "replacing existing undefined\n"); | ||
| 235 | F->addMember(Sym); | ||
| 236 | } | ||
| 237 | } | ||
deps/lld/wasm/SymbolTable.h created+71| ... | @@ -0,0 +1,71 @@ | ||
| 1 | //===- SymbolTable.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_WASM_SYMBOL_TABLE_H | ||
| 11 | #define LLD_WASM_SYMBOL_TABLE_H | ||
| 12 | |||
| 13 | #include "InputFiles.h" | ||
| 14 | #include "Symbols.h" | ||
| 15 | |||
| 16 | #include "llvm/ADT/CachedHashString.h" | ||
| 17 | #include "llvm/ADT/DenseMap.h" | ||
| 18 | #include "llvm/Support/raw_ostream.h" | ||
| 19 | |||
| 20 | using llvm::object::WasmSymbol; | ||
| 21 | using llvm::wasm::WasmSignature; | ||
| 22 | |||
| 23 | namespace lld { | ||
| 24 | namespace wasm { | ||
| 25 | |||
| 26 | class InputSegment; | ||
| 27 | |||
| 28 | // SymbolTable is a bucket of all known symbols, including defined, | ||
| 29 | // undefined, or lazy symbols (the last one is symbols in archive | ||
| 30 | // files whose archive members are not yet loaded). | ||
| 31 | // | ||
| 32 | // We put all symbols of all files to a SymbolTable, and the | ||
| 33 | // SymbolTable selects the "best" symbols if there are name | ||
| 34 | // conflicts. For example, obviously, a defined symbol is better than | ||
| 35 | // an undefined symbol. Or, if there's a conflict between a lazy and a | ||
| 36 | // undefined, it'll read an archive member to read a real definition | ||
| 37 | // to replace the lazy symbol. The logic is implemented in the | ||
| 38 | // add*() functions, which are called by input files as they are parsed. | ||
| 39 | // There is one add* function per symbol type. | ||
| 40 | class SymbolTable { | ||
| 41 | public: | ||
| 42 | void addFile(InputFile *File); | ||
| 43 | |||
| 44 | std::vector<ObjFile *> ObjectFiles; | ||
| 45 | |||
| 46 | void reportDuplicate(Symbol *Existing, InputFile *NewFile); | ||
| 47 | void reportRemainingUndefines(); | ||
| 48 | |||
| 49 | ArrayRef<Symbol *> getSymbols() const { return SymVector; } | ||
| 50 | Symbol *find(StringRef Name); | ||
| 51 | |||
| 52 | Symbol *addDefined(InputFile *F, const WasmSymbol *Sym, | ||
| 53 | const InputSegment *Segment = nullptr); | ||
| 54 | Symbol *addUndefined(InputFile *F, const WasmSymbol *Sym); | ||
| 55 | Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type); | ||
| 56 | Symbol *addDefinedGlobal(StringRef Name); | ||
| 57 | void addLazy(ArchiveFile *F, const Archive::Symbol *Sym); | ||
| 58 | |||
| 59 | private: | ||
| 60 | std::pair<Symbol *, bool> insert(StringRef Name); | ||
| 61 | |||
| 62 | llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> SymMap; | ||
| 63 | std::vector<Symbol *> SymVector; | ||
| 64 | }; | ||
| 65 | |||
| 66 | extern SymbolTable *Symtab; | ||
| 67 | |||
| 68 | } // namespace wasm | ||
| 69 | } // namespace lld | ||
| 70 | |||
| 71 | #endif | ||
deps/lld/wasm/Symbols.cpp created+114| ... | @@ -0,0 +1,114 @@ | ||
| 1 | //===- Symbols.cpp --------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "Symbols.h" | ||
| 11 | |||
| 12 | #include "Config.h" | ||
| 13 | #include "InputFiles.h" | ||
| 14 | #include "InputSegment.h" | ||
| 15 | #include "lld/Common/ErrorHandler.h" | ||
| 16 | #include "lld/Common/Strings.h" | ||
| 17 | |||
| 18 | #define DEBUG_TYPE "lld" | ||
| 19 | |||
| 20 | using namespace llvm; | ||
| 21 | using namespace lld; | ||
| 22 | using namespace lld::wasm; | ||
| 23 | |||
| 24 | uint32_t Symbol::getGlobalIndex() const { | ||
| 25 | assert(!Sym->isFunction()); | ||
| 26 | return Sym->ElementIndex; | ||
| 27 | } | ||
| 28 | |||
| 29 | uint32_t Symbol::getFunctionIndex() const { | ||
| 30 | assert(Sym->isFunction()); | ||
| 31 | return Sym->ElementIndex; | ||
| 32 | } | ||
| 33 | |||
| 34 | const WasmSignature &Symbol::getFunctionType() const { | ||
| 35 | assert(FunctionType != nullptr); | ||
| 36 | return *FunctionType; | ||
| 37 | } | ||
| 38 | |||
| 39 | uint32_t Symbol::getVirtualAddress() const { | ||
| 40 | assert(isGlobal()); | ||
| 41 | DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); | ||
| 42 | if (isUndefined()) | ||
| 43 | return UINT32_MAX; | ||
| 44 | if (VirtualAddress.hasValue()) | ||
| 45 | return VirtualAddress.getValue(); | ||
| 46 | |||
| 47 | assert(Sym != nullptr); | ||
| 48 | ObjFile *Obj = cast<ObjFile>(File); | ||
| 49 | const WasmGlobal &Global = | ||
| 50 | Obj->getWasmObj()->globals()[getGlobalIndex() - Obj->NumGlobalImports()]; | ||
| 51 | assert(Global.Type == llvm::wasm::WASM_TYPE_I32); | ||
| 52 | assert(Segment); | ||
| 53 | return Segment->translateVA(Global.InitExpr.Value.Int32); | ||
| 54 | } | ||
| 55 | |||
| 56 | uint32_t Symbol::getOutputIndex() const { | ||
| 57 | if (isUndefined() && isWeak()) | ||
| 58 | return 0; | ||
| 59 | return OutputIndex.getValue(); | ||
| 60 | } | ||
| 61 | |||
| 62 | void Symbol::setVirtualAddress(uint32_t Value) { | ||
| 63 | DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n"); | ||
| 64 | assert(!VirtualAddress.hasValue()); | ||
| 65 | VirtualAddress = Value; | ||
| 66 | } | ||
| 67 | |||
| 68 | void Symbol::setOutputIndex(uint32_t Index) { | ||
| 69 | DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n"); | ||
| 70 | assert(!OutputIndex.hasValue()); | ||
| 71 | OutputIndex = Index; | ||
| 72 | } | ||
| 73 | |||
| 74 | void Symbol::setTableIndex(uint32_t Index) { | ||
| 75 | DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n"); | ||
| 76 | assert(!TableIndex.hasValue()); | ||
| 77 | TableIndex = Index; | ||
| 78 | } | ||
| 79 | |||
| 80 | void Symbol::update(Kind K, InputFile *F, const WasmSymbol *WasmSym, | ||
| 81 | const InputSegment *Seg, const WasmSignature *Sig) { | ||
| 82 | SymbolKind = K; | ||
| 83 | File = F; | ||
| 84 | Sym = WasmSym; | ||
| 85 | Segment = Seg; | ||
| 86 | FunctionType = Sig; | ||
| 87 | } | ||
| 88 | |||
| 89 | bool Symbol::isWeak() const { return Sym && Sym->isWeak(); } | ||
| 90 | |||
| 91 | bool Symbol::isHidden() const { return Sym && Sym->isHidden(); } | ||
| 92 | |||
| 93 | std::string lld::toString(const wasm::Symbol &Sym) { | ||
| 94 | if (Config->Demangle) | ||
| 95 | if (Optional<std::string> S = demangleItanium(Sym.getName())) | ||
| 96 | return "`" + *S + "'"; | ||
| 97 | return Sym.getName(); | ||
| 98 | } | ||
| 99 | |||
| 100 | std::string lld::toString(wasm::Symbol::Kind Kind) { | ||
| 101 | switch (Kind) { | ||
| 102 | case wasm::Symbol::DefinedFunctionKind: | ||
| 103 | return "DefinedFunction"; | ||
| 104 | case wasm::Symbol::DefinedGlobalKind: | ||
| 105 | return "DefinedGlobal"; | ||
| 106 | case wasm::Symbol::UndefinedFunctionKind: | ||
| 107 | return "UndefinedFunction"; | ||
| 108 | case wasm::Symbol::UndefinedGlobalKind: | ||
| 109 | return "UndefinedGlobal"; | ||
| 110 | case wasm::Symbol::LazyKind: | ||
| 111 | return "LazyKind"; | ||
| 112 | } | ||
| 113 | llvm_unreachable("Invalid symbol kind!"); | ||
| 114 | } | ||
deps/lld/wasm/Symbols.h created+128| ... | @@ -0,0 +1,128 @@ | ||
| 1 | //===- Symbols.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_WASM_SYMBOLS_H | ||
| 11 | #define LLD_WASM_SYMBOLS_H | ||
| 12 | |||
| 13 | #include "lld/Common/LLVM.h" | ||
| 14 | #include "llvm/Object/Archive.h" | ||
| 15 | #include "llvm/Object/Wasm.h" | ||
| 16 | |||
| 17 | using llvm::object::Archive; | ||
| 18 | using llvm::object::WasmSymbol; | ||
| 19 | using llvm::wasm::WasmExport; | ||
| 20 | using llvm::wasm::WasmImport; | ||
| 21 | using llvm::wasm::WasmSignature; | ||
| 22 | |||
| 23 | namespace lld { | ||
| 24 | namespace wasm { | ||
| 25 | |||
| 26 | class InputFile; | ||
| 27 | class InputSegment; | ||
| 28 | |||
| 29 | class Symbol { | ||
| 30 | public: | ||
| 31 | enum Kind { | ||
| 32 | DefinedFunctionKind, | ||
| 33 | DefinedGlobalKind, | ||
| 34 | |||
| 35 | LazyKind, | ||
| 36 | UndefinedFunctionKind, | ||
| 37 | UndefinedGlobalKind, | ||
| 38 | |||
| 39 | LastDefinedKind = DefinedGlobalKind, | ||
| 40 | InvalidKind, | ||
| 41 | }; | ||
| 42 | |||
| 43 | Symbol(StringRef Name, bool IsLocal) | ||
| 44 | : WrittenToSymtab(0), WrittenToNameSec(0), IsLocal(IsLocal), Name(Name) {} | ||
| 45 | |||
| 46 | Kind getKind() const { return SymbolKind; } | ||
| 47 | |||
| 48 | bool isLazy() const { return SymbolKind == LazyKind; } | ||
| 49 | bool isDefined() const { return SymbolKind <= LastDefinedKind; } | ||
| 50 | bool isUndefined() const { | ||
| 51 | return SymbolKind == UndefinedGlobalKind || | ||
| 52 | SymbolKind == UndefinedFunctionKind; | ||
| 53 | } | ||
| 54 | bool isFunction() const { | ||
| 55 | return SymbolKind == DefinedFunctionKind || | ||
| 56 | SymbolKind == UndefinedFunctionKind; | ||
| 57 | } | ||
| 58 | bool isGlobal() const { return !isFunction(); } | ||
| 59 | bool isLocal() const { return IsLocal; } | ||
| 60 | bool isWeak() const; | ||
| 61 | bool isHidden() const; | ||
| 62 | |||
| 63 | // Returns the symbol name. | ||
| 64 | StringRef getName() const { return Name; } | ||
| 65 | |||
| 66 | // Returns the file from which this symbol was created. | ||
| 67 | InputFile *getFile() const { return File; } | ||
| 68 | |||
| 69 | uint32_t getGlobalIndex() const; | ||
| 70 | uint32_t getFunctionIndex() const; | ||
| 71 | |||
| 72 | bool hasFunctionType() const { return FunctionType != nullptr; } | ||
| 73 | const WasmSignature &getFunctionType() const; | ||
| 74 | uint32_t getOutputIndex() const; | ||
| 75 | uint32_t getTableIndex() const { return TableIndex.getValue(); } | ||
| 76 | |||
| 77 | // Returns the virtual address of a defined global. | ||
| 78 | // Only works for globals, not functions. | ||
| 79 | uint32_t getVirtualAddress() const; | ||
| 80 | |||
| 81 | // Set the output index of the symbol (in the function or global index | ||
| 82 | // space of the output object. | ||
| 83 | void setOutputIndex(uint32_t Index); | ||
| 84 | |||
| 85 | // Returns true if a table index has been set for this symbol | ||
| 86 | bool hasTableIndex() const { return TableIndex.hasValue(); } | ||
| 87 | |||
| 88 | // Set the table index of the symbol | ||
| 89 | void setTableIndex(uint32_t Index); | ||
| 90 | |||
| 91 | void setVirtualAddress(uint32_t VA); | ||
| 92 | |||
| 93 | void update(Kind K, InputFile *F = nullptr, const WasmSymbol *Sym = nullptr, | ||
| 94 | const InputSegment *Segment = nullptr, | ||
| 95 | const WasmSignature *Sig = nullptr); | ||
| 96 | |||
| 97 | void setArchiveSymbol(const Archive::Symbol &Sym) { ArchiveSymbol = Sym; } | ||
| 98 | const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; } | ||
| 99 | |||
| 100 | // This bit is used by Writer::writeNameSection() to prevent | ||
| 101 | // symbols from being written to the symbol table more than once. | ||
| 102 | unsigned WrittenToSymtab : 1; | ||
| 103 | unsigned WrittenToNameSec : 1; | ||
| 104 | |||
| 105 | protected: | ||
| 106 | unsigned IsLocal : 1; | ||
| 107 | |||
| 108 | StringRef Name; | ||
| 109 | Archive::Symbol ArchiveSymbol = {nullptr, 0, 0}; | ||
| 110 | Kind SymbolKind = InvalidKind; | ||
| 111 | InputFile *File = nullptr; | ||
| 112 | const WasmSymbol *Sym = nullptr; | ||
| 113 | const InputSegment *Segment = nullptr; | ||
| 114 | llvm::Optional<uint32_t> OutputIndex; | ||
| 115 | llvm::Optional<uint32_t> TableIndex; | ||
| 116 | llvm::Optional<uint32_t> VirtualAddress; | ||
| 117 | const WasmSignature *FunctionType; | ||
| 118 | }; | ||
| 119 | |||
| 120 | } // namespace wasm | ||
| 121 | |||
| 122 | // Returns a symbol name for an error message. | ||
| 123 | std::string toString(const wasm::Symbol &Sym); | ||
| 124 | std::string toString(wasm::Symbol::Kind Kind); | ||
| 125 | |||
| 126 | } // namespace lld | ||
| 127 | |||
| 128 | #endif | ||
deps/lld/wasm/Writer.cpp created+745| ... | @@ -0,0 +1,745 @@ | ||
| 1 | //===- Writer.cpp ---------------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "Writer.h" | ||
| 11 | |||
| 12 | #include "Config.h" | ||
| 13 | #include "OutputSections.h" | ||
| 14 | #include "OutputSegment.h" | ||
| 15 | #include "SymbolTable.h" | ||
| 16 | #include "WriterUtils.h" | ||
| 17 | #include "lld/Common/ErrorHandler.h" | ||
| 18 | #include "lld/Common/Memory.h" | ||
| 19 | #include "lld/Common/Threads.h" | ||
| 20 | #include "llvm/Support/FileOutputBuffer.h" | ||
| 21 | #include "llvm/Support/Format.h" | ||
| 22 | #include "llvm/Support/FormatVariadic.h" | ||
| 23 | #include "llvm/Support/LEB128.h" | ||
| 24 | |||
| 25 | #include <cstdarg> | ||
| 26 | |||
| 27 | #define DEBUG_TYPE "lld" | ||
| 28 | |||
| 29 | using namespace llvm; | ||
| 30 | using namespace llvm::wasm; | ||
| 31 | using namespace lld; | ||
| 32 | using namespace lld::wasm; | ||
| 33 | |||
| 34 | static constexpr int kStackAlignment = 16; | ||
| 35 | |||
| 36 | namespace { | ||
| 37 | |||
| 38 | // Traits for using WasmSignature in a DenseMap. | ||
| 39 | struct WasmSignatureDenseMapInfo { | ||
| 40 | static WasmSignature getEmptyKey() { | ||
| 41 | WasmSignature Sig; | ||
| 42 | Sig.ReturnType = 1; | ||
| 43 | return Sig; | ||
| 44 | } | ||
| 45 | static WasmSignature getTombstoneKey() { | ||
| 46 | WasmSignature Sig; | ||
| 47 | Sig.ReturnType = 2; | ||
| 48 | return Sig; | ||
| 49 | } | ||
| 50 | static unsigned getHashValue(const WasmSignature &Sig) { | ||
| 51 | uintptr_t Value = 0; | ||
| 52 | Value += DenseMapInfo<int32_t>::getHashValue(Sig.ReturnType); | ||
| 53 | for (int32_t Param : Sig.ParamTypes) | ||
| 54 | Value += DenseMapInfo<int32_t>::getHashValue(Param); | ||
| 55 | return Value; | ||
| 56 | } | ||
| 57 | static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) { | ||
| 58 | return LHS == RHS; | ||
| 59 | } | ||
| 60 | }; | ||
| 61 | |||
| 62 | // The writer writes a SymbolTable result to a file. | ||
| 63 | class Writer { | ||
| 64 | public: | ||
| 65 | void run(); | ||
| 66 | |||
| 67 | private: | ||
| 68 | void openFile(); | ||
| 69 | |||
| 70 | uint32_t getTypeIndex(const WasmSignature &Sig); | ||
| 71 | void assignSymbolIndexes(); | ||
| 72 | void calculateImports(); | ||
| 73 | void calculateOffsets(); | ||
| 74 | void calculateTypes(); | ||
| 75 | void createOutputSegments(); | ||
| 76 | void layoutMemory(); | ||
| 77 | void createHeader(); | ||
| 78 | void createSections(); | ||
| 79 | SyntheticSection *createSyntheticSection(uint32_t Type, | ||
| 80 | std::string Name = ""); | ||
| 81 | |||
| 82 | // Builtin sections | ||
| 83 | void createTypeSection(); | ||
| 84 | void createFunctionSection(); | ||
| 85 | void createTableSection(); | ||
| 86 | void createGlobalSection(); | ||
| 87 | void createExportSection(); | ||
| 88 | void createImportSection(); | ||
| 89 | void createMemorySection(); | ||
| 90 | void createElemSection(); | ||
| 91 | void createStartSection(); | ||
| 92 | void createCodeSection(); | ||
| 93 | void createDataSection(); | ||
| 94 | |||
| 95 | // Custom sections | ||
| 96 | void createRelocSections(); | ||
| 97 | void createLinkingSection(); | ||
| 98 | void createNameSection(); | ||
| 99 | |||
| 100 | void writeHeader(); | ||
| 101 | void writeSections(); | ||
| 102 | |||
| 103 | uint64_t FileSize = 0; | ||
| 104 | uint32_t DataSize = 0; | ||
| 105 | uint32_t NumFunctions = 0; | ||
| 106 | uint32_t NumMemoryPages = 0; | ||
| 107 | uint32_t InitialTableOffset = 0; | ||
| 108 | |||
| 109 | std::vector<const WasmSignature *> Types; | ||
| 110 | DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices; | ||
| 111 | std::vector<const Symbol *> FunctionImports; | ||
| 112 | std::vector<const Symbol *> GlobalImports; | ||
| 113 | std::vector<const Symbol *> DefinedGlobals; | ||
| 114 | std::vector<const Symbol *> IndirectFunctions; | ||
| 115 | |||
| 116 | // Elements that are used to construct the final output | ||
| 117 | std::string Header; | ||
| 118 | std::vector<OutputSection *> OutputSections; | ||
| 119 | |||
| 120 | std::unique_ptr<FileOutputBuffer> Buffer; | ||
| 121 | |||
| 122 | std::vector<OutputSegment *> Segments; | ||
| 123 | llvm::SmallDenseMap<StringRef, OutputSegment *> SegmentMap; | ||
| 124 | }; | ||
| 125 | |||
| 126 | } // anonymous namespace | ||
| 127 | |||
| 128 | static void debugPrint(const char *fmt, ...) { | ||
| 129 | if (!errorHandler().Verbose) | ||
| 130 | return; | ||
| 131 | fprintf(stderr, "lld: "); | ||
| 132 | va_list ap; | ||
| 133 | va_start(ap, fmt); | ||
| 134 | vfprintf(stderr, fmt, ap); | ||
| 135 | va_end(ap); | ||
| 136 | } | ||
| 137 | |||
| 138 | void Writer::createImportSection() { | ||
| 139 | uint32_t NumImports = FunctionImports.size() + GlobalImports.size(); | ||
| 140 | if (Config->ImportMemory) | ||
| 141 | ++NumImports; | ||
| 142 | |||
| 143 | if (NumImports == 0) | ||
| 144 | return; | ||
| 145 | |||
| 146 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_IMPORT); | ||
| 147 | raw_ostream &OS = Section->getStream(); | ||
| 148 | |||
| 149 | writeUleb128(OS, NumImports, "import count"); | ||
| 150 | |||
| 151 | for (const Symbol *Sym : FunctionImports) { | ||
| 152 | WasmImport Import; | ||
| 153 | Import.Module = "env"; | ||
| 154 | Import.Field = Sym->getName(); | ||
| 155 | Import.Kind = WASM_EXTERNAL_FUNCTION; | ||
| 156 | assert(TypeIndices.count(Sym->getFunctionType()) > 0); | ||
| 157 | Import.SigIndex = TypeIndices.lookup(Sym->getFunctionType()); | ||
| 158 | writeImport(OS, Import); | ||
| 159 | } | ||
| 160 | |||
| 161 | if (Config->ImportMemory) { | ||
| 162 | WasmImport Import; | ||
| 163 | Import.Module = "env"; | ||
| 164 | Import.Field = "memory"; | ||
| 165 | Import.Kind = WASM_EXTERNAL_MEMORY; | ||
| 166 | Import.Memory.Flags = 0; | ||
| 167 | Import.Memory.Initial = NumMemoryPages; | ||
| 168 | writeImport(OS, Import); | ||
| 169 | } | ||
| 170 | |||
| 171 | for (const Symbol *Sym : GlobalImports) { | ||
| 172 | WasmImport Import; | ||
| 173 | Import.Module = "env"; | ||
| 174 | Import.Field = Sym->getName(); | ||
| 175 | Import.Kind = WASM_EXTERNAL_GLOBAL; | ||
| 176 | Import.Global.Mutable = false; | ||
| 177 | Import.Global.Type = WASM_TYPE_I32; | ||
| 178 | writeImport(OS, Import); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | void Writer::createTypeSection() { | ||
| 183 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_TYPE); | ||
| 184 | raw_ostream &OS = Section->getStream(); | ||
| 185 | writeUleb128(OS, Types.size(), "type count"); | ||
| 186 | for (const WasmSignature *Sig : Types) | ||
| 187 | writeSig(OS, *Sig); | ||
| 188 | } | ||
| 189 | |||
| 190 | void Writer::createFunctionSection() { | ||
| 191 | if (!NumFunctions) | ||
| 192 | return; | ||
| 193 | |||
| 194 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION); | ||
| 195 | raw_ostream &OS = Section->getStream(); | ||
| 196 | |||
| 197 | writeUleb128(OS, NumFunctions, "function count"); | ||
| 198 | for (ObjFile *File : Symtab->ObjectFiles) | ||
| 199 | for (uint32_t Sig : File->getWasmObj()->functionTypes()) | ||
| 200 | writeUleb128(OS, File->relocateTypeIndex(Sig), "sig index"); | ||
| 201 | } | ||
| 202 | |||
| 203 | void Writer::createMemorySection() { | ||
| 204 | if (Config->ImportMemory) | ||
| 205 | return; | ||
| 206 | |||
| 207 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY); | ||
| 208 | raw_ostream &OS = Section->getStream(); | ||
| 209 | |||
| 210 | writeUleb128(OS, 1, "memory count"); | ||
| 211 | writeUleb128(OS, 0, "memory limits flags"); | ||
| 212 | writeUleb128(OS, NumMemoryPages, "initial pages"); | ||
| 213 | } | ||
| 214 | |||
| 215 | void Writer::createGlobalSection() { | ||
| 216 | if (DefinedGlobals.empty()) | ||
| 217 | return; | ||
| 218 | |||
| 219 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL); | ||
| 220 | raw_ostream &OS = Section->getStream(); | ||
| 221 | |||
| 222 | writeUleb128(OS, DefinedGlobals.size(), "global count"); | ||
| 223 | for (const Symbol *Sym : DefinedGlobals) { | ||
| 224 | WasmGlobal Global; | ||
| 225 | Global.Type = WASM_TYPE_I32; | ||
| 226 | Global.Mutable = Sym == Config->StackPointerSymbol; | ||
| 227 | Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; | ||
| 228 | Global.InitExpr.Value.Int32 = Sym->getVirtualAddress(); | ||
| 229 | writeGlobal(OS, Global); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | void Writer::createTableSection() { | ||
| 234 | // Always output a table section, even if there are no indirect calls. | ||
| 235 | // There are two reasons for this: | ||
| 236 | // 1. For executables it is useful to have an empty table slot at 0 | ||
| 237 | // which can be filled with a null function call handler. | ||
| 238 | // 2. If we don't do this, any program that contains a call_indirect but | ||
| 239 | // no address-taken function will fail at validation time since it is | ||
| 240 | // a validation error to include a call_indirect instruction if there | ||
| 241 | // is not table. | ||
| 242 | uint32_t TableSize = InitialTableOffset + IndirectFunctions.size(); | ||
| 243 | |||
| 244 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE); | ||
| 245 | raw_ostream &OS = Section->getStream(); | ||
| 246 | |||
| 247 | writeUleb128(OS, 1, "table count"); | ||
| 248 | writeSleb128(OS, WASM_TYPE_ANYFUNC, "table type"); | ||
| 249 | writeUleb128(OS, WASM_LIMITS_FLAG_HAS_MAX, "table flags"); | ||
| 250 | writeUleb128(OS, TableSize, "table initial size"); | ||
| 251 | writeUleb128(OS, TableSize, "table max size"); | ||
| 252 | } | ||
| 253 | |||
| 254 | void Writer::createExportSection() { | ||
| 255 | bool ExportMemory = !Config->Relocatable && !Config->ImportMemory; | ||
| 256 | Symbol *EntrySym = Symtab->find(Config->Entry); | ||
| 257 | bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined(); | ||
| 258 | bool ExportHidden = Config->EmitRelocs; | ||
| 259 | |||
| 260 | uint32_t NumExports = ExportMemory ? 1 : 0; | ||
| 261 | |||
| 262 | std::vector<const Symbol *> SymbolExports; | ||
| 263 | if (ExportEntry) | ||
| 264 | SymbolExports.emplace_back(EntrySym); | ||
| 265 | |||
| 266 | for (const Symbol *Sym : Symtab->getSymbols()) { | ||
| 267 | if (Sym->isUndefined() || Sym->isGlobal()) | ||
| 268 | continue; | ||
| 269 | if (Sym->isHidden() && !ExportHidden) | ||
| 270 | continue; | ||
| 271 | if (ExportEntry && Sym == EntrySym) | ||
| 272 | continue; | ||
| 273 | SymbolExports.emplace_back(Sym); | ||
| 274 | } | ||
| 275 | |||
| 276 | for (const Symbol *Sym : DefinedGlobals) { | ||
| 277 | // Can't export the SP right now because it mutable and mutable globals | ||
| 278 | // connot be exported. | ||
| 279 | if (Sym == Config->StackPointerSymbol) | ||
| 280 | continue; | ||
| 281 | SymbolExports.emplace_back(Sym); | ||
| 282 | } | ||
| 283 | |||
| 284 | NumExports += SymbolExports.size(); | ||
| 285 | if (!NumExports) | ||
| 286 | return; | ||
| 287 | |||
| 288 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_EXPORT); | ||
| 289 | raw_ostream &OS = Section->getStream(); | ||
| 290 | |||
| 291 | writeUleb128(OS, NumExports, "export count"); | ||
| 292 | |||
| 293 | if (ExportMemory) { | ||
| 294 | WasmExport MemoryExport; | ||
| 295 | MemoryExport.Name = "memory"; | ||
| 296 | MemoryExport.Kind = WASM_EXTERNAL_MEMORY; | ||
| 297 | MemoryExport.Index = 0; | ||
| 298 | writeExport(OS, MemoryExport); | ||
| 299 | } | ||
| 300 | |||
| 301 | for (const Symbol *Sym : SymbolExports) { | ||
| 302 | log("Export: " + Sym->getName()); | ||
| 303 | WasmExport Export; | ||
| 304 | Export.Name = Sym->getName(); | ||
| 305 | Export.Index = Sym->getOutputIndex(); | ||
| 306 | if (Sym->isFunction()) | ||
| 307 | Export.Kind = WASM_EXTERNAL_FUNCTION; | ||
| 308 | else | ||
| 309 | Export.Kind = WASM_EXTERNAL_GLOBAL; | ||
| 310 | writeExport(OS, Export); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | void Writer::createStartSection() {} | ||
| 315 | |||
| 316 | void Writer::createElemSection() { | ||
| 317 | if (IndirectFunctions.empty()) | ||
| 318 | return; | ||
| 319 | |||
| 320 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_ELEM); | ||
| 321 | raw_ostream &OS = Section->getStream(); | ||
| 322 | |||
| 323 | writeUleb128(OS, 1, "segment count"); | ||
| 324 | writeUleb128(OS, 0, "table index"); | ||
| 325 | WasmInitExpr InitExpr; | ||
| 326 | InitExpr.Opcode = WASM_OPCODE_I32_CONST; | ||
| 327 | InitExpr.Value.Int32 = InitialTableOffset; | ||
| 328 | writeInitExpr(OS, InitExpr); | ||
| 329 | writeUleb128(OS, IndirectFunctions.size(), "elem count"); | ||
| 330 | |||
| 331 | uint32_t TableIndex = InitialTableOffset; | ||
| 332 | for (const Symbol *Sym : IndirectFunctions) { | ||
| 333 | assert(Sym->getTableIndex() == TableIndex); | ||
| 334 | writeUleb128(OS, Sym->getOutputIndex(), "function index"); | ||
| 335 | ++TableIndex; | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | void Writer::createCodeSection() { | ||
| 340 | if (!NumFunctions) | ||
| 341 | return; | ||
| 342 | |||
| 343 | log("createCodeSection"); | ||
| 344 | |||
| 345 | auto Section = make<CodeSection>(NumFunctions, Symtab->ObjectFiles); | ||
| 346 | OutputSections.push_back(Section); | ||
| 347 | } | ||
| 348 | |||
| 349 | void Writer::createDataSection() { | ||
| 350 | if (!Segments.size()) | ||
| 351 | return; | ||
| 352 | |||
| 353 | log("createDataSection"); | ||
| 354 | auto Section = make<DataSection>(Segments); | ||
| 355 | OutputSections.push_back(Section); | ||
| 356 | } | ||
| 357 | |||
| 358 | // Create relocations sections in the final output. | ||
| 359 | // These are only created when relocatable output is requested. | ||
| 360 | void Writer::createRelocSections() { | ||
| 361 | log("createRelocSections"); | ||
| 362 | // Don't use iterator here since we are adding to OutputSection | ||
| 363 | size_t OrigSize = OutputSections.size(); | ||
| 364 | for (size_t i = 0; i < OrigSize; i++) { | ||
| 365 | OutputSection *S = OutputSections[i]; | ||
| 366 | const char *name; | ||
| 367 | uint32_t Count = S->numRelocations(); | ||
| 368 | if (!Count) | ||
| 369 | continue; | ||
| 370 | |||
| 371 | if (S->Type == WASM_SEC_DATA) | ||
| 372 | name = "reloc.DATA"; | ||
| 373 | else if (S->Type == WASM_SEC_CODE) | ||
| 374 | name = "reloc.CODE"; | ||
| 375 | else | ||
| 376 | llvm_unreachable("relocations only supported for code and data"); | ||
| 377 | |||
| 378 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, name); | ||
| 379 | raw_ostream &OS = Section->getStream(); | ||
| 380 | writeUleb128(OS, S->Type, "reloc section"); | ||
| 381 | writeUleb128(OS, Count, "reloc count"); | ||
| 382 | S->writeRelocations(OS); | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | // Create the custom "linking" section containing linker metadata. | ||
| 387 | // This is only created when relocatable output is requested. | ||
| 388 | void Writer::createLinkingSection() { | ||
| 389 | SyntheticSection *Section = | ||
| 390 | createSyntheticSection(WASM_SEC_CUSTOM, "linking"); | ||
| 391 | raw_ostream &OS = Section->getStream(); | ||
| 392 | |||
| 393 | SubSection DataSizeSubSection(WASM_DATA_SIZE); | ||
| 394 | writeUleb128(DataSizeSubSection.getStream(), DataSize, "data size"); | ||
| 395 | DataSizeSubSection.finalizeContents(); | ||
| 396 | DataSizeSubSection.writeToStream(OS); | ||
| 397 | |||
| 398 | if (!Config->Relocatable) | ||
| 399 | return; | ||
| 400 | |||
| 401 | if (Segments.size()) { | ||
| 402 | SubSection SubSection(WASM_SEGMENT_INFO); | ||
| 403 | writeUleb128(SubSection.getStream(), Segments.size(), "num data segments"); | ||
| 404 | for (const OutputSegment *S : Segments) { | ||
| 405 | writeStr(SubSection.getStream(), S->Name, "segment name"); | ||
| 406 | writeUleb128(SubSection.getStream(), S->Alignment, "alignment"); | ||
| 407 | writeUleb128(SubSection.getStream(), 0, "flags"); | ||
| 408 | } | ||
| 409 | SubSection.finalizeContents(); | ||
| 410 | SubSection.writeToStream(OS); | ||
| 411 | } | ||
| 412 | |||
| 413 | std::vector<WasmInitFunc> InitFunctions; | ||
| 414 | for (ObjFile *File : Symtab->ObjectFiles) { | ||
| 415 | const WasmLinkingData &L = File->getWasmObj()->linkingData(); | ||
| 416 | InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size()); | ||
| 417 | for (const WasmInitFunc &F : L.InitFunctions) | ||
| 418 | InitFunctions.emplace_back(WasmInitFunc{ | ||
| 419 | F.Priority, File->relocateFunctionIndex(F.FunctionIndex)}); | ||
| 420 | } | ||
| 421 | |||
| 422 | if (!InitFunctions.empty()) { | ||
| 423 | SubSection SubSection(WASM_INIT_FUNCS); | ||
| 424 | writeUleb128(SubSection.getStream(), InitFunctions.size(), | ||
| 425 | "num init functionsw"); | ||
| 426 | for (const WasmInitFunc &F : InitFunctions) { | ||
| 427 | writeUleb128(SubSection.getStream(), F.Priority, "priority"); | ||
| 428 | writeUleb128(SubSection.getStream(), F.FunctionIndex, "function index"); | ||
| 429 | } | ||
| 430 | SubSection.finalizeContents(); | ||
| 431 | SubSection.writeToStream(OS); | ||
| 432 | } | ||
| 433 | } | ||
| 434 | |||
| 435 | // Create the custom "name" section containing debug symbol names. | ||
| 436 | void Writer::createNameSection() { | ||
| 437 | // Create an array of all function sorted by function index space | ||
| 438 | std::vector<const Symbol *> Names; | ||
| 439 | |||
| 440 | for (ObjFile *File : Symtab->ObjectFiles) { | ||
| 441 | Names.reserve(Names.size() + File->getSymbols().size()); | ||
| 442 | for (Symbol *S : File->getSymbols()) { | ||
| 443 | if (!S->isFunction() || S->isWeak() || S->WrittenToNameSec) | ||
| 444 | continue; | ||
| 445 | S->WrittenToNameSec = true; | ||
| 446 | Names.emplace_back(S); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | |||
| 450 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name"); | ||
| 451 | |||
| 452 | std::sort(Names.begin(), Names.end(), [](const Symbol *A, const Symbol *B) { | ||
| 453 | return A->getOutputIndex() < B->getOutputIndex(); | ||
| 454 | }); | ||
| 455 | |||
| 456 | SubSection FunctionSubsection(WASM_NAMES_FUNCTION); | ||
| 457 | raw_ostream &OS = FunctionSubsection.getStream(); | ||
| 458 | writeUleb128(OS, Names.size(), "name count"); | ||
| 459 | |||
| 460 | // We have to iterate through the inputs twice so that all the imports | ||
| 461 | // appear first before any of the local function names. | ||
| 462 | for (const Symbol *S : Names) { | ||
| 463 | writeUleb128(OS, S->getOutputIndex(), "func index"); | ||
| 464 | writeStr(OS, S->getName(), "symbol name"); | ||
| 465 | } | ||
| 466 | |||
| 467 | FunctionSubsection.finalizeContents(); | ||
| 468 | FunctionSubsection.writeToStream(Section->getStream()); | ||
| 469 | } | ||
| 470 | |||
| 471 | void Writer::writeHeader() { | ||
| 472 | memcpy(Buffer->getBufferStart(), Header.data(), Header.size()); | ||
| 473 | } | ||
| 474 | |||
| 475 | void Writer::writeSections() { | ||
| 476 | uint8_t *Buf = Buffer->getBufferStart(); | ||
| 477 | parallelForEach(OutputSections, [Buf](OutputSection *S) { S->writeTo(Buf); }); | ||
| 478 | } | ||
| 479 | |||
| 480 | // Fix the memory layout of the output binary. This assigns memory offsets | ||
| 481 | // to each of the input data sections as well as the explicit stack region. | ||
| 482 | void Writer::layoutMemory() { | ||
| 483 | uint32_t MemoryPtr = 0; | ||
| 484 | if (!Config->Relocatable) { | ||
| 485 | MemoryPtr = Config->GlobalBase; | ||
| 486 | debugPrint("mem: global base = %d\n", Config->GlobalBase); | ||
| 487 | } | ||
| 488 | |||
| 489 | createOutputSegments(); | ||
| 490 | |||
| 491 | // Static data comes first | ||
| 492 | for (OutputSegment *Seg : Segments) { | ||
| 493 | MemoryPtr = alignTo(MemoryPtr, Seg->Alignment); | ||
| 494 | Seg->StartVA = MemoryPtr; | ||
| 495 | debugPrint("mem: %-10s offset=%-8d size=%-4d align=%d\n", | ||
| 496 | Seg->Name.str().c_str(), MemoryPtr, Seg->Size, Seg->Alignment); | ||
| 497 | MemoryPtr += Seg->Size; | ||
| 498 | } | ||
| 499 | |||
| 500 | DataSize = MemoryPtr; | ||
| 501 | if (!Config->Relocatable) | ||
| 502 | DataSize -= Config->GlobalBase; | ||
| 503 | debugPrint("mem: static data = %d\n", DataSize); | ||
| 504 | |||
| 505 | // Stack comes after static data | ||
| 506 | if (!Config->Relocatable) { | ||
| 507 | MemoryPtr = alignTo(MemoryPtr, kStackAlignment); | ||
| 508 | if (Config->ZStackSize != alignTo(Config->ZStackSize, kStackAlignment)) | ||
| 509 | error("stack size must be " + Twine(kStackAlignment) + "-byte aligned"); | ||
| 510 | debugPrint("mem: stack size = %d\n", Config->ZStackSize); | ||
| 511 | debugPrint("mem: stack base = %d\n", MemoryPtr); | ||
| 512 | MemoryPtr += Config->ZStackSize; | ||
| 513 | Config->StackPointerSymbol->setVirtualAddress(MemoryPtr); | ||
| 514 | debugPrint("mem: stack top = %d\n", MemoryPtr); | ||
| 515 | } | ||
| 516 | |||
| 517 | uint32_t MemSize = alignTo(MemoryPtr, WasmPageSize); | ||
| 518 | NumMemoryPages = MemSize / WasmPageSize; | ||
| 519 | debugPrint("mem: total pages = %d\n", NumMemoryPages); | ||
| 520 | } | ||
| 521 | |||
| 522 | SyntheticSection *Writer::createSyntheticSection(uint32_t Type, | ||
| 523 | std::string Name) { | ||
| 524 | auto Sec = make<SyntheticSection>(Type, Name); | ||
| 525 | log("createSection: " + toString(*Sec)); | ||
| 526 | OutputSections.push_back(Sec); | ||
| 527 | return Sec; | ||
| 528 | } | ||
| 529 | |||
| 530 | void Writer::createSections() { | ||
| 531 | // Known sections | ||
| 532 | createTypeSection(); | ||
| 533 | createImportSection(); | ||
| 534 | createFunctionSection(); | ||
| 535 | createTableSection(); | ||
| 536 | createMemorySection(); | ||
| 537 | createGlobalSection(); | ||
| 538 | createExportSection(); | ||
| 539 | createStartSection(); | ||
| 540 | createElemSection(); | ||
| 541 | createCodeSection(); | ||
| 542 | createDataSection(); | ||
| 543 | |||
| 544 | // Custom sections | ||
| 545 | if (Config->EmitRelocs) | ||
| 546 | createRelocSections(); | ||
| 547 | createLinkingSection(); | ||
| 548 | if (!Config->StripDebug && !Config->StripAll) | ||
| 549 | createNameSection(); | ||
| 550 | |||
| 551 | for (OutputSection *S : OutputSections) { | ||
| 552 | S->setOffset(FileSize); | ||
| 553 | S->finalizeContents(); | ||
| 554 | FileSize += S->getSize(); | ||
| 555 | } | ||
| 556 | } | ||
| 557 | |||
| 558 | void Writer::calculateOffsets() { | ||
| 559 | for (ObjFile *File : Symtab->ObjectFiles) { | ||
| 560 | const WasmObjectFile *WasmFile = File->getWasmObj(); | ||
| 561 | |||
| 562 | // Function Index | ||
| 563 | File->FunctionIndexOffset = | ||
| 564 | FunctionImports.size() - File->NumFunctionImports() + NumFunctions; | ||
| 565 | NumFunctions += WasmFile->functions().size(); | ||
| 566 | |||
| 567 | // Memory | ||
| 568 | if (WasmFile->memories().size() > 1) | ||
| 569 | fatal(File->getName() + ": contains more than one memory"); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 573 | void Writer::calculateImports() { | ||
| 574 | for (Symbol *Sym : Symtab->getSymbols()) { | ||
| 575 | if (!Sym->isUndefined() || Sym->isWeak()) | ||
| 576 | continue; | ||
| 577 | |||
| 578 | if (Sym->isFunction()) { | ||
| 579 | Sym->setOutputIndex(FunctionImports.size()); | ||
| 580 | FunctionImports.push_back(Sym); | ||
| 581 | } else { | ||
| 582 | Sym->setOutputIndex(GlobalImports.size()); | ||
| 583 | GlobalImports.push_back(Sym); | ||
| 584 | } | ||
| 585 | } | ||
| 586 | } | ||
| 587 | |||
| 588 | uint32_t Writer::getTypeIndex(const WasmSignature &Sig) { | ||
| 589 | auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size())); | ||
| 590 | if (Pair.second) | ||
| 591 | Types.push_back(&Sig); | ||
| 592 | return Pair.first->second; | ||
| 593 | } | ||
| 594 | |||
| 595 | void Writer::calculateTypes() { | ||
| 596 | for (ObjFile *File : Symtab->ObjectFiles) { | ||
| 597 | File->TypeMap.reserve(File->getWasmObj()->types().size()); | ||
| 598 | for (const WasmSignature &Sig : File->getWasmObj()->types()) | ||
| 599 | File->TypeMap.push_back(getTypeIndex(Sig)); | ||
| 600 | } | ||
| 601 | } | ||
| 602 | |||
| 603 | void Writer::assignSymbolIndexes() { | ||
| 604 | uint32_t GlobalIndex = GlobalImports.size(); | ||
| 605 | |||
| 606 | if (Config->StackPointerSymbol) { | ||
| 607 | DefinedGlobals.emplace_back(Config->StackPointerSymbol); | ||
| 608 | Config->StackPointerSymbol->setOutputIndex(GlobalIndex++); | ||
| 609 | } | ||
| 610 | |||
| 611 | if (Config->EmitRelocs) | ||
| 612 | DefinedGlobals.reserve(Symtab->getSymbols().size()); | ||
| 613 | |||
| 614 | uint32_t TableIndex = InitialTableOffset; | ||
| 615 | |||
| 616 | for (ObjFile *File : Symtab->ObjectFiles) { | ||
| 617 | DEBUG(dbgs() << "assignSymbolIndexes: " << File->getName() << "\n"); | ||
| 618 | |||
| 619 | for (Symbol *Sym : File->getSymbols()) { | ||
| 620 | // Assign indexes for symbols defined with this file. | ||
| 621 | if (!Sym->isDefined() || File != Sym->getFile()) | ||
| 622 | continue; | ||
| 623 | if (Sym->isFunction()) { | ||
| 624 | auto *Obj = cast<ObjFile>(Sym->getFile()); | ||
| 625 | Sym->setOutputIndex(Obj->FunctionIndexOffset + | ||
| 626 | Sym->getFunctionIndex()); | ||
| 627 | } else if (Config->EmitRelocs) { | ||
| 628 | DefinedGlobals.emplace_back(Sym); | ||
| 629 | Sym->setOutputIndex(GlobalIndex++); | ||
| 630 | } | ||
| 631 | } | ||
| 632 | |||
| 633 | for (Symbol *Sym : File->getTableSymbols()) { | ||
| 634 | if (!Sym->hasTableIndex()) { | ||
| 635 | Sym->setTableIndex(TableIndex++); | ||
| 636 | IndirectFunctions.emplace_back(Sym); | ||
| 637 | } | ||
| 638 | } | ||
| 639 | } | ||
| 640 | } | ||
| 641 | |||
| 642 | static StringRef getOutputDataSegmentName(StringRef Name) { | ||
| 643 | if (Config->Relocatable) | ||
| 644 | return Name; | ||
| 645 | |||
| 646 | for (StringRef V : | ||
| 647 | {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", | ||
| 648 | ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", | ||
| 649 | ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) { | ||
| 650 | StringRef Prefix = V.drop_back(); | ||
| 651 | if (Name.startswith(V) || Name == Prefix) | ||
| 652 | return Prefix; | ||
| 653 | } | ||
| 654 | |||
| 655 | return Name; | ||
| 656 | } | ||
| 657 | |||
| 658 | void Writer::createOutputSegments() { | ||
| 659 | for (ObjFile *File : Symtab->ObjectFiles) { | ||
| 660 | for (InputSegment *Segment : File->Segments) { | ||
| 661 | StringRef Name = getOutputDataSegmentName(Segment->getName()); | ||
| 662 | OutputSegment *&S = SegmentMap[Name]; | ||
| 663 | if (S == nullptr) { | ||
| 664 | DEBUG(dbgs() << "new segment: " << Name << "\n"); | ||
| 665 | S = make<OutputSegment>(Name); | ||
| 666 | Segments.push_back(S); | ||
| 667 | } | ||
| 668 | S->addInputSegment(Segment); | ||
| 669 | DEBUG(dbgs() << "added data: " << Name << ": " << S->Size << "\n"); | ||
| 670 | } | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | void Writer::run() { | ||
| 675 | if (!Config->Relocatable) | ||
| 676 | InitialTableOffset = 1; | ||
| 677 | |||
| 678 | log("-- calculateTypes"); | ||
| 679 | calculateTypes(); | ||
| 680 | log("-- calculateImports"); | ||
| 681 | calculateImports(); | ||
| 682 | log("-- calculateOffsets"); | ||
| 683 | calculateOffsets(); | ||
| 684 | |||
| 685 | if (errorHandler().Verbose) { | ||
| 686 | log("Defined Functions: " + Twine(NumFunctions)); | ||
| 687 | log("Defined Globals : " + Twine(DefinedGlobals.size())); | ||
| 688 | log("Function Imports : " + Twine(FunctionImports.size())); | ||
| 689 | log("Global Imports : " + Twine(GlobalImports.size())); | ||
| 690 | log("Total Imports : " + | ||
| 691 | Twine(FunctionImports.size() + GlobalImports.size())); | ||
| 692 | for (ObjFile *File : Symtab->ObjectFiles) | ||
| 693 | File->dumpInfo(); | ||
| 694 | } | ||
| 695 | |||
| 696 | log("-- assignSymbolIndexes"); | ||
| 697 | assignSymbolIndexes(); | ||
| 698 | log("-- layoutMemory"); | ||
| 699 | layoutMemory(); | ||
| 700 | |||
| 701 | createHeader(); | ||
| 702 | log("-- createSections"); | ||
| 703 | createSections(); | ||
| 704 | |||
| 705 | log("-- openFile"); | ||
| 706 | openFile(); | ||
| 707 | if (errorCount()) | ||
| 708 | return; | ||
| 709 | |||
| 710 | writeHeader(); | ||
| 711 | |||
| 712 | log("-- writeSections"); | ||
| 713 | writeSections(); | ||
| 714 | if (errorCount()) | ||
| 715 | return; | ||
| 716 | |||
| 717 | if (Error E = Buffer->commit()) | ||
| 718 | fatal("failed to write the output file: " + toString(std::move(E))); | ||
| 719 | } | ||
| 720 | |||
| 721 | // Open a result file. | ||
| 722 | void Writer::openFile() { | ||
| 723 | log("writing: " + Config->OutputFile); | ||
| 724 | ::remove(Config->OutputFile.str().c_str()); | ||
| 725 | |||
| 726 | Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = | ||
| 727 | FileOutputBuffer::create(Config->OutputFile, FileSize, | ||
| 728 | FileOutputBuffer::F_executable); | ||
| 729 | |||
| 730 | if (!BufferOrErr) | ||
| 731 | error("failed to open " + Config->OutputFile + ": " + | ||
| 732 | toString(BufferOrErr.takeError())); | ||
| 733 | else | ||
| 734 | Buffer = std::move(*BufferOrErr); | ||
| 735 | } | ||
| 736 | |||
| 737 | void Writer::createHeader() { | ||
| 738 | raw_string_ostream OS(Header); | ||
| 739 | writeBytes(OS, WasmMagic, sizeof(WasmMagic), "wasm magic"); | ||
| 740 | writeU32(OS, WasmVersion, "wasm version"); | ||
| 741 | OS.flush(); | ||
| 742 | FileSize += Header.size(); | ||
| 743 | } | ||
| 744 | |||
| 745 | void lld::wasm::writeResult() { Writer().run(); } | ||
deps/lld/wasm/Writer.h created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | //===- Writer.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_WASM_WRITER_H | ||
| 11 | #define LLD_WASM_WRITER_H | ||
| 12 | |||
| 13 | namespace lld { | ||
| 14 | namespace wasm { | ||
| 15 | |||
| 16 | void writeResult(); | ||
| 17 | |||
| 18 | } // namespace wasm | ||
| 19 | } // namespace lld | ||
| 20 | |||
| 21 | #endif | ||
deps/lld/wasm/WriterUtils.cpp created+215| ... | @@ -0,0 +1,215 @@ | ||
| 1 | //===- WriterUtils.cpp ----------------------------------------------------===// | ||
| 2 | // | ||
| 3 | // The LLVM Linker | ||
| 4 | // | ||
| 5 | // This file is distributed under the University of Illinois Open Source | ||
| 6 | // License. See LICENSE.TXT for details. | ||
| 7 | // | ||
| 8 | //===----------------------------------------------------------------------===// | ||
| 9 | |||
| 10 | #include "WriterUtils.h" | ||
| 11 | |||
| 12 | #include "lld/Common/ErrorHandler.h" | ||
| 13 | |||
| 14 | #include "llvm/Support/Debug.h" | ||
| 15 | #include "llvm/Support/EndianStream.h" | ||
| 16 | #include "llvm/Support/FormatVariadic.h" | ||
| 17 | #include "llvm/Support/LEB128.h" | ||
| 18 | |||
| 19 | #define DEBUG_TYPE "lld" | ||
| 20 | |||
| 21 | using namespace llvm; | ||
| 22 | using namespace llvm::wasm; | ||
| 23 | using namespace lld::wasm; | ||
| 24 | |||
| 25 | static const char *valueTypeToString(int32_t Type) { | ||
| 26 | switch (Type) { | ||
| 27 | case WASM_TYPE_I32: | ||
| 28 | return "i32"; | ||
| 29 | case WASM_TYPE_I64: | ||
| 30 | return "i64"; | ||
| 31 | case WASM_TYPE_F32: | ||
| 32 | return "f32"; | ||
| 33 | case WASM_TYPE_F64: | ||
| 34 | return "f64"; | ||
| 35 | default: | ||
| 36 | llvm_unreachable("invalid value type"); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | namespace lld { | ||
| 41 | |||
| 42 | void wasm::debugWrite(uint64_t offset, Twine msg) { | ||
| 43 | DEBUG(dbgs() << format(" | %08" PRIx64 ": ", offset) << msg << "\n"); | ||
| 44 | } | ||
| 45 | |||
| 46 | void wasm::writeUleb128(raw_ostream &OS, uint32_t Number, const char *msg) { | ||
| 47 | if (msg) | ||
| 48 | debugWrite(OS.tell(), msg + formatv(" [{0:x}]", Number)); | ||
| 49 | encodeULEB128(Number, OS); | ||
| 50 | } | ||
| 51 | |||
| 52 | void wasm::writeSleb128(raw_ostream &OS, int32_t Number, const char *msg) { | ||
| 53 | if (msg) | ||
| 54 | debugWrite(OS.tell(), msg + formatv(" [{0:x}]", Number)); | ||
| 55 | encodeSLEB128(Number, OS); | ||
| 56 | } | ||
| 57 | |||
| 58 | void wasm::writeBytes(raw_ostream &OS, const char *bytes, size_t count, | ||
| 59 | const char *msg) { | ||
| 60 | if (msg) | ||
| 61 | debugWrite(OS.tell(), msg + formatv(" [data[{0}]]", count)); | ||
| 62 | OS.write(bytes, count); | ||
| 63 | } | ||
| 64 | |||
| 65 | void wasm::writeStr(raw_ostream &OS, const StringRef String, const char *msg) { | ||
| 66 | if (msg) | ||
| 67 | debugWrite(OS.tell(), | ||
| 68 | msg + formatv(" [str[{0}]: {1}]", String.size(), String)); | ||
| 69 | writeUleb128(OS, String.size(), nullptr); | ||
| 70 | writeBytes(OS, String.data(), String.size()); | ||
| 71 | } | ||
| 72 | |||
| 73 | void wasm::writeU8(raw_ostream &OS, uint8_t byte, const char *msg) { | ||
| 74 | OS << byte; | ||
| 75 | } | ||
| 76 | |||
| 77 | void wasm::writeU32(raw_ostream &OS, uint32_t Number, const char *msg) { | ||
| 78 | debugWrite(OS.tell(), msg + formatv("[{0:x}]", Number)); | ||
| 79 | support::endian::Writer<support::little>(OS).write(Number); | ||
| 80 | } | ||
| 81 | |||
| 82 | void wasm::writeValueType(raw_ostream &OS, int32_t Type, const char *msg) { | ||
| 83 | debugWrite(OS.tell(), msg + formatv("[type: {0}]", valueTypeToString(Type))); | ||
| 84 | writeSleb128(OS, Type, nullptr); | ||
| 85 | } | ||
| 86 | |||
| 87 | void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) { | ||
| 88 | writeSleb128(OS, WASM_TYPE_FUNC, "signature type"); | ||
| 89 | writeUleb128(OS, Sig.ParamTypes.size(), "param count"); | ||
| 90 | for (int32_t ParamType : Sig.ParamTypes) { | ||
| 91 | writeValueType(OS, ParamType, "param type"); | ||
| 92 | } | ||
| 93 | if (Sig.ReturnType == WASM_TYPE_NORESULT) { | ||
| 94 | writeUleb128(OS, 0, "result count"); | ||
| 95 | } else { | ||
| 96 | writeUleb128(OS, 1, "result count"); | ||
| 97 | writeValueType(OS, Sig.ReturnType, "result type"); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) { | ||
| 102 | writeU8(OS, InitExpr.Opcode, "opcode"); | ||
| 103 | switch (InitExpr.Opcode) { | ||
| 104 | case WASM_OPCODE_I32_CONST: | ||
| 105 | writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)"); | ||
| 106 | break; | ||
| 107 | case WASM_OPCODE_I64_CONST: | ||
| 108 | writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)"); | ||
| 109 | break; | ||
| 110 | case WASM_OPCODE_GET_GLOBAL: | ||
| 111 | writeUleb128(OS, InitExpr.Value.Global, "literal (global index)"); | ||
| 112 | break; | ||
| 113 | default: | ||
| 114 | fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode)); | ||
| 115 | } | ||
| 116 | writeU8(OS, WASM_OPCODE_END, "opcode:end"); | ||
| 117 | } | ||
| 118 | |||
| 119 | void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) { | ||
| 120 | writeUleb128(OS, Limits.Flags, "limits flags"); | ||
| 121 | writeUleb128(OS, Limits.Initial, "limits initial"); | ||
| 122 | if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX) | ||
| 123 | writeUleb128(OS, Limits.Maximum, "limits max"); | ||
| 124 | } | ||
| 125 | |||
| 126 | void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) { | ||
| 127 | writeValueType(OS, Global.Type, "global type"); | ||
| 128 | writeUleb128(OS, Global.Mutable, "global mutable"); | ||
| 129 | writeInitExpr(OS, Global.InitExpr); | ||
| 130 | } | ||
| 131 | |||
| 132 | void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) { | ||
| 133 | writeStr(OS, Import.Module, "import module name"); | ||
| 134 | writeStr(OS, Import.Field, "import field name"); | ||
| 135 | writeU8(OS, Import.Kind, "import kind"); | ||
| 136 | switch (Import.Kind) { | ||
| 137 | case WASM_EXTERNAL_FUNCTION: | ||
| 138 | writeUleb128(OS, Import.SigIndex, "import sig index"); | ||
| 139 | break; | ||
| 140 | case WASM_EXTERNAL_GLOBAL: | ||
| 141 | writeValueType(OS, Import.Global.Type, "import global type"); | ||
| 142 | writeUleb128(OS, Import.Global.Mutable, "import global mutable"); | ||
| 143 | break; | ||
| 144 | case WASM_EXTERNAL_MEMORY: | ||
| 145 | writeLimits(OS, Import.Memory); | ||
| 146 | break; | ||
| 147 | default: | ||
| 148 | fatal("unsupported import type: " + Twine(Import.Kind)); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) { | ||
| 153 | writeStr(OS, Export.Name, "export name"); | ||
| 154 | writeU8(OS, Export.Kind, "export kind"); | ||
| 155 | switch (Export.Kind) { | ||
| 156 | case WASM_EXTERNAL_FUNCTION: | ||
| 157 | writeUleb128(OS, Export.Index, "function index"); | ||
| 158 | break; | ||
| 159 | case WASM_EXTERNAL_GLOBAL: | ||
| 160 | writeUleb128(OS, Export.Index, "global index"); | ||
| 161 | break; | ||
| 162 | case WASM_EXTERNAL_MEMORY: | ||
| 163 | writeUleb128(OS, Export.Index, "memory index"); | ||
| 164 | break; | ||
| 165 | default: | ||
| 166 | fatal("unsupported export type: " + Twine(Export.Kind)); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | void wasm::writeReloc(raw_ostream &OS, const OutputRelocation &Reloc) { | ||
| 171 | writeUleb128(OS, Reloc.Reloc.Type, "reloc type"); | ||
| 172 | writeUleb128(OS, Reloc.Reloc.Offset, "reloc offset"); | ||
| 173 | writeUleb128(OS, Reloc.NewIndex, "reloc index"); | ||
| 174 | |||
| 175 | switch (Reloc.Reloc.Type) { | ||
| 176 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: | ||
| 177 | case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: | ||
| 178 | case R_WEBASSEMBLY_MEMORY_ADDR_I32: | ||
| 179 | writeUleb128(OS, Reloc.Reloc.Addend, "reloc addend"); | ||
| 180 | break; | ||
| 181 | default: | ||
| 182 | break; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | } // namespace lld | ||
| 187 | |||
| 188 | std::string lld::toString(ValType Type) { | ||
| 189 | switch (Type) { | ||
| 190 | case ValType::I32: | ||
| 191 | return "I32"; | ||
| 192 | case ValType::I64: | ||
| 193 | return "I64"; | ||
| 194 | case ValType::F32: | ||
| 195 | return "F32"; | ||
| 196 | case ValType::F64: | ||
| 197 | return "F64"; | ||
| 198 | } | ||
| 199 | llvm_unreachable("Invalid wasm::ValType"); | ||
| 200 | } | ||
| 201 | |||
| 202 | std::string lld::toString(const WasmSignature &Sig) { | ||
| 203 | SmallString<128> S("("); | ||
| 204 | for (uint32_t Type : Sig.ParamTypes) { | ||
| 205 | if (S.size() != 1) | ||
| 206 | S += ", "; | ||
| 207 | S += toString(static_cast<ValType>(Type)); | ||
| 208 | } | ||
| 209 | S += ") -> "; | ||
| 210 | if (Sig.ReturnType == WASM_TYPE_NORESULT) | ||
| 211 | S += "void"; | ||
| 212 | else | ||
| 213 | S += toString(static_cast<ValType>(Sig.ReturnType)); | ||
| 214 | return S.str(); | ||
| 215 | } | ||
deps/lld/wasm/WriterUtils.h created+78| ... | @@ -0,0 +1,78 @@ | ||
| 1 | //===- WriterUtils.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_WASM_WRITERUTILS_H | ||
| 11 | #define LLD_WASM_WRITERUTILS_H | ||
| 12 | |||
| 13 | #include "llvm/ADT/Twine.h" | ||
| 14 | #include "llvm/Object/Wasm.h" | ||
| 15 | #include "llvm/Support/raw_ostream.h" | ||
| 16 | |||
| 17 | using llvm::raw_ostream; | ||
| 18 | |||
| 19 | // Needed for WasmSignatureDenseMapInfo | ||
| 20 | inline bool operator==(const llvm::wasm::WasmSignature &LHS, | ||
| 21 | const llvm::wasm::WasmSignature &RHS) { | ||
| 22 | return LHS.ReturnType == RHS.ReturnType && LHS.ParamTypes == RHS.ParamTypes; | ||
| 23 | } | ||
| 24 | |||
| 25 | inline bool operator!=(const llvm::wasm::WasmSignature &LHS, | ||
| 26 | const llvm::wasm::WasmSignature &RHS) { | ||
| 27 | return !(LHS == RHS); | ||
| 28 | } | ||
| 29 | |||
| 30 | namespace lld { | ||
| 31 | namespace wasm { | ||
| 32 | |||
| 33 | struct OutputRelocation { | ||
| 34 | llvm::wasm::WasmRelocation Reloc; | ||
| 35 | uint32_t NewIndex; | ||
| 36 | uint32_t Value; | ||
| 37 | }; | ||
| 38 | |||
| 39 | void debugWrite(uint64_t offset, llvm::Twine msg); | ||
| 40 | |||
| 41 | void writeUleb128(raw_ostream &OS, uint32_t Number, const char *msg); | ||
| 42 | |||
| 43 | void writeSleb128(raw_ostream &OS, int32_t Number, const char *msg); | ||
| 44 | |||
| 45 | void writeBytes(raw_ostream &OS, const char *bytes, size_t count, | ||
| 46 | const char *msg = nullptr); | ||
| 47 | |||
| 48 | void writeStr(raw_ostream &OS, const llvm::StringRef String, | ||
| 49 | const char *msg = nullptr); | ||
| 50 | |||
| 51 | void writeU8(raw_ostream &OS, uint8_t byte, const char *msg); | ||
| 52 | |||
| 53 | void writeU32(raw_ostream &OS, uint32_t Number, const char *msg); | ||
| 54 | |||
| 55 | void writeValueType(raw_ostream &OS, int32_t Type, const char *msg); | ||
| 56 | |||
| 57 | void writeSig(raw_ostream &OS, const llvm::wasm::WasmSignature &Sig); | ||
| 58 | |||
| 59 | void writeInitExpr(raw_ostream &OS, const llvm::wasm::WasmInitExpr &InitExpr); | ||
| 60 | |||
| 61 | void writeLimits(raw_ostream &OS, const llvm::wasm::WasmLimits &Limits); | ||
| 62 | |||
| 63 | void writeGlobal(raw_ostream &OS, const llvm::wasm::WasmGlobal &Global); | ||
| 64 | |||
| 65 | void writeImport(raw_ostream &OS, const llvm::wasm::WasmImport &Import); | ||
| 66 | |||
| 67 | void writeExport(raw_ostream &OS, const llvm::wasm::WasmExport &Export); | ||
| 68 | |||
| 69 | void writeReloc(raw_ostream &OS, const OutputRelocation &Reloc); | ||
| 70 | |||
| 71 | } // namespace wasm | ||
| 72 | |||
| 73 | std::string toString(const llvm::wasm::ValType Type); | ||
| 74 | std::string toString(const llvm::wasm::WasmSignature &Sig); | ||
| 75 | |||
| 76 | } // namespace lld | ||
| 77 | |||
| 78 | #endif // LLD_WASM_WRITERUTILS_H | ||