aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:48:50 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:48:50 +0000
commit1c98619801a5705c688e683be3ef9d70169a0686 (patch)
tree8422105cd1a94c368315f2db16b9ac746cf7c000
parentf4f3ce4613680903220815690ad79fc7ba0a2e26 (diff)
downloadsrc-vendor/lld/lld-release_39-r276489.tar.gz
src-vendor/lld/lld-release_39-r276489.zip
Vendor import of lld release_39 branch r276489:vendor/lld/lld-release_39-r276489
-rw-r--r--.arcconfig2
-rw-r--r--CMakeLists.txt2
-rw-r--r--COFF/CMakeLists.txt3
-rw-r--r--COFF/Chunks.cpp13
-rw-r--r--COFF/Chunks.h10
-rw-r--r--COFF/Config.h4
-rw-r--r--COFF/DLL.cpp2
-rw-r--r--COFF/Driver.cpp55
-rw-r--r--COFF/Driver.h5
-rw-r--r--COFF/DriverUtils.cpp332
-rw-r--r--COFF/Error.cpp13
-rw-r--r--COFF/Error.h18
-rw-r--r--COFF/ICF.cpp6
-rw-r--r--COFF/InputFiles.cpp119
-rw-r--r--COFF/InputFiles.h9
-rw-r--r--COFF/Librarian.cpp489
-rw-r--r--COFF/ModuleDef.cpp14
-rw-r--r--COFF/Options.td2
-rw-r--r--COFF/PDB.cpp3
-rw-r--r--COFF/README.md266
-rw-r--r--COFF/SymbolTable.cpp33
-rw-r--r--COFF/SymbolTable.h2
-rw-r--r--COFF/Symbols.cpp28
-rw-r--r--COFF/Symbols.h4
-rw-r--r--COFF/Writer.cpp72
-rw-r--r--ELF/CMakeLists.txt28
-rw-r--r--ELF/Config.h63
-rw-r--r--ELF/Driver.cpp463
-rw-r--r--ELF/Driver.h65
-rw-r--r--ELF/DriverUtils.cpp234
-rw-r--r--ELF/EhFrame.cpp167
-rw-r--r--ELF/EhFrame.h22
-rw-r--r--ELF/Error.cpp49
-rw-r--r--ELF/Error.h39
-rw-r--r--ELF/ICF.cpp345
-rw-r--r--ELF/ICF.h19
-rw-r--r--ELF/InputFiles.cpp775
-rw-r--r--ELF/InputFiles.h187
-rw-r--r--ELF/InputSection.cpp779
-rw-r--r--ELF/InputSection.h206
-rw-r--r--ELF/LTO.cpp325
-rw-r--r--ELF/LTO.h54
-rw-r--r--ELF/LinkerScript.cpp566
-rw-r--r--ELF/LinkerScript.h103
-rw-r--r--ELF/MarkLive.cpp167
-rw-r--r--ELF/Options.td283
-rw-r--r--ELF/OutputSections.cpp2176
-rw-r--r--ELF/OutputSections.h596
-rw-r--r--ELF/README.md22
-rw-r--r--ELF/Relocations.cpp704
-rw-r--r--ELF/Relocations.h93
-rw-r--r--ELF/ScriptParser.cpp163
-rw-r--r--ELF/ScriptParser.h49
-rw-r--r--ELF/Strings.cpp98
-rw-r--r--ELF/Strings.h29
-rw-r--r--ELF/SymbolListFile.cpp168
-rw-r--r--ELF/SymbolListFile.h27
-rw-r--r--ELF/SymbolTable.cpp717
-rw-r--r--ELF/SymbolTable.h99
-rw-r--r--ELF/Symbols.cpp369
-rw-r--r--ELF/Symbols.h470
-rw-r--r--ELF/Target.cpp2678
-rw-r--r--ELF/Target.h151
-rw-r--r--ELF/Thunks.cpp268
-rw-r--r--ELF/Thunks.h56
-rw-r--r--ELF/Writer.cpp1564
-rw-r--r--ELF/Writer.h20
-rw-r--r--LICENSE.TXT2
-rw-r--r--docs/AtomLLD.rst61
-rw-r--r--docs/NewLLD.rst350
-rw-r--r--docs/ReleaseNotes.rst35
-rw-r--r--docs/conf.py3
-rw-r--r--docs/design.rst31
-rw-r--r--docs/index.rst72
-rw-r--r--docs/open_projects.rst5
-rw-r--r--include/lld/Core/Alias.h100
-rw-r--r--include/lld/Core/ArchiveLibraryFile.h15
-rw-r--r--include/lld/Core/Atom.h53
-rw-r--r--include/lld/Core/DefinedAtom.h50
-rw-r--r--include/lld/Core/Error.h42
-rw-r--r--include/lld/Core/File.h120
-rw-r--r--include/lld/Core/LLVM.h6
-rw-r--r--include/lld/Core/LinkingContext.h150
-rw-r--r--include/lld/Core/Node.h6
-rw-r--r--include/lld/Core/Parallel.h36
-rw-r--r--include/lld/Core/Pass.h4
-rw-r--r--include/lld/Core/PassManager.h7
-rw-r--r--include/lld/Core/Reader.h9
-rw-r--r--include/lld/Core/Reference.h18
-rw-r--r--include/lld/Core/Resolver.h41
-rw-r--r--include/lld/Core/STDExtras.h29
-rw-r--r--include/lld/Core/SharedLibraryAtom.h4
-rw-r--r--include/lld/Core/SharedLibraryFile.h21
-rw-r--r--include/lld/Core/Simple.h150
-rw-r--r--include/lld/Core/SymbolTable.h11
-rw-r--r--include/lld/Core/UndefinedAtom.h10
-rw-r--r--include/lld/Core/Writer.h11
-rw-r--r--include/lld/Core/range.h738
-rw-r--r--include/lld/Driver/Driver.h138
-rw-r--r--include/lld/ReaderWriter/AtomLayout.h39
-rw-r--r--include/lld/ReaderWriter/CoreLinkingContext.h47
-rw-r--r--include/lld/ReaderWriter/ELFLinkingContext.h422
-rw-r--r--include/lld/ReaderWriter/LinkerScript.h1471
-rw-r--r--include/lld/ReaderWriter/MachOLinkingContext.h133
-rw-r--r--lib/Config/Version.cpp27
-rw-r--r--lib/Core/DefinedAtom.cpp11
-rw-r--r--lib/Core/Error.cpp48
-rw-r--r--lib/Core/File.cpp2
-rw-r--r--lib/Core/LinkingContext.cpp47
-rw-r--r--lib/Core/Reader.cpp1
-rw-r--r--lib/Core/Resolver.cpp330
-rw-r--r--lib/Core/SymbolTable.cpp92
-rw-r--r--lib/Driver/CMakeLists.txt21
-rw-r--r--lib/Driver/CoreDriver.cpp173
-rw-r--r--lib/Driver/CoreOptions.td15
-rw-r--r--lib/Driver/DarwinLdDriver.cpp387
-rw-r--r--lib/Driver/DarwinLdOptions.td35
-rw-r--r--lib/Driver/Driver.cpp142
-rw-r--r--lib/Driver/GnuLdDriver.cpp782
-rw-r--r--lib/Driver/GnuLdOptions.td378
-rw-r--r--lib/Driver/TODO.rst99
-rw-r--r--lib/Driver/UniversalDriver.cpp225
-rw-r--r--lib/Driver/UniversalDriverOptions.td19
-rw-r--r--lib/ReaderWriter/CMakeLists.txt3
-rw-r--r--lib/ReaderWriter/CoreLinkingContext.cpp50
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h45
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp52
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h38
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp45
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h101
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp556
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h36
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp612
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h32
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp39
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h37
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp51
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h90
-rw-r--r--lib/ReaderWriter/ELF/AArch64/CMakeLists.txt14
-rw-r--r--lib/ReaderWriter/ELF/AArch64/TODO.rst15
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h49
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMELFFile.h154
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMELFWriters.h120
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h68
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp64
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h80
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp680
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h35
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp985
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationPass.h31
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h59
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp32
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h174
-rw-r--r--lib/ReaderWriter/ELF/ARM/CMakeLists.txt12
-rw-r--r--lib/ReaderWriter/ELF/ARM/TODO.rst21
-rw-r--r--lib/ReaderWriter/ELF/Atoms.cpp297
-rw-r--r--lib/ReaderWriter/ELF/Atoms.h493
-rw-r--r--lib/ReaderWriter/ELF/CMakeLists.txt29
-rw-r--r--lib/ReaderWriter/ELF/Chunk.h111
-rw-r--r--lib/ReaderWriter/ELF/DynamicFile.cpp146
-rw-r--r--lib/ReaderWriter/ELF/DynamicFile.h59
-rw-r--r--lib/ReaderWriter/ELF/DynamicLibraryWriter.h86
-rw-r--r--lib/ReaderWriter/ELF/ELFFile.cpp829
-rw-r--r--lib/ReaderWriter/ELF/ELFFile.h395
-rw-r--r--lib/ReaderWriter/ELF/ELFLinkingContext.cpp263
-rw-r--r--lib/ReaderWriter/ELF/ELFReader.h47
-rw-r--r--lib/ReaderWriter/ELF/ExecutableWriter.h157
-rw-r--r--lib/ReaderWriter/ELF/FileCommon.cpp66
-rw-r--r--lib/ReaderWriter/ELF/FileCommon.h45
-rw-r--r--lib/ReaderWriter/ELF/HeaderChunks.cpp205
-rw-r--r--lib/ReaderWriter/ELF/HeaderChunks.h154
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt11
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h67
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h149
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h638
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h73
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp47
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h61
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp330
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h33
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp382
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h134
-rw-r--r--lib/ReaderWriter/ELF/Mips/CMakeLists.txt18
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp675
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h83
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp76
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h25
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h124
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp348
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFile.h126
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp292
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFWriters.h102
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp164
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h56
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp687
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h31
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp1415
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h25
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp264
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h150
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp166
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h73
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp111
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h71
-rw-r--r--lib/ReaderWriter/ELF/OrderPass.h31
-rw-r--r--lib/ReaderWriter/ELF/OutputELFWriter.cpp514
-rw-r--r--lib/ReaderWriter/ELF/OutputELFWriter.h153
-rw-r--r--lib/ReaderWriter/ELF/Reader.cpp43
-rw-r--r--lib/ReaderWriter/ELF/SectionChunks.cpp996
-rw-r--r--lib/ReaderWriter/ELF/SectionChunks.h616
-rw-r--r--lib/ReaderWriter/ELF/SegmentChunks.cpp519
-rw-r--r--lib/ReaderWriter/ELF/SegmentChunks.h246
-rw-r--r--lib/ReaderWriter/ELF/TODO.txt18
-rw-r--r--lib/ReaderWriter/ELF/TargetHandler.h35
-rw-r--r--lib/ReaderWriter/ELF/TargetLayout.cpp747
-rw-r--r--lib/ReaderWriter/ELF/TargetLayout.h327
-rw-r--r--lib/ReaderWriter/ELF/Writer.cpp23
-rw-r--r--lib/ReaderWriter/ELF/Writer.h35
-rw-r--r--lib/ReaderWriter/ELF/X86/CMakeLists.txt11
-rw-r--r--lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h44
-rw-r--r--lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h39
-rw-r--r--lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp39
-rw-r--r--lib/ReaderWriter/ELF/X86/X86LinkingContext.h44
-rw-r--r--lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp54
-rw-r--r--lib/ReaderWriter/ELF/X86/X86RelocationHandler.h28
-rw-r--r--lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp36
-rw-r--r--lib/ReaderWriter/ELF/X86/X86TargetHandler.h48
-rw-r--r--lib/ReaderWriter/ELF/X86_64/CMakeLists.txt17
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt11
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp35
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.h31
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp22
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h31
-rw-r--r--lib/ReaderWriter/ELF/X86_64/TODO.rst46
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h45
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h57
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp50
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h103
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp147
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h37
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp513
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.h32
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp37
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h36
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp34
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h104
-rw-r--r--lib/ReaderWriter/FileArchive.cpp173
-rw-r--r--lib/ReaderWriter/LinkerScript.cpp2895
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler.h29
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm.cpp131
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm64.cpp122
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_x86.cpp74
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp178
-rw-r--r--lib/ReaderWriter/MachO/Atoms.h32
-rw-r--r--lib/ReaderWriter/MachO/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/MachO/CompactUnwindPass.cpp33
-rw-r--r--lib/ReaderWriter/MachO/ExecutableAtoms.h108
-rw-r--r--lib/ReaderWriter/MachO/File.h93
-rw-r--r--lib/ReaderWriter/MachO/FlatNamespaceFile.h28
-rw-r--r--lib/ReaderWriter/MachO/GOTPass.cpp12
-rw-r--r--lib/ReaderWriter/MachO/LayoutPass.cpp47
-rw-r--r--lib/ReaderWriter/MachO/LayoutPass.h39
-rw-r--r--lib/ReaderWriter/MachO/MachOLinkingContext.cpp216
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFile.h32
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp44
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h46
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp461
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp268
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp608
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp81
-rw-r--r--lib/ReaderWriter/MachO/MachOPasses.h1
-rw-r--r--lib/ReaderWriter/MachO/ObjCPass.cpp128
-rw-r--r--lib/ReaderWriter/MachO/SectCreateFile.h19
-rw-r--r--lib/ReaderWriter/MachO/ShimPass.cpp13
-rw-r--r--lib/ReaderWriter/MachO/StubsPass.cpp40
-rw-r--r--lib/ReaderWriter/MachO/TLVPass.cpp14
-rw-r--r--lib/ReaderWriter/MachO/WriterMachO.cpp9
-rw-r--r--lib/ReaderWriter/YAML/ReaderWriterYAML.cpp302
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/COFF/Inputs/armnt-executable.obj.yaml2
-rw-r--r--test/COFF/Inputs/export.yaml4
-rw-r--r--test/COFF/Inputs/export2.yaml2
-rw-r--r--test/COFF/Inputs/hello32.yaml2
-rw-r--r--test/COFF/Inputs/import.yaml2
-rw-r--r--test/COFF/Inputs/include1a.yaml4
-rw-r--r--test/COFF/Inputs/include1b.yaml4
-rw-r--r--test/COFF/Inputs/include1c.yaml2
-rw-r--r--test/COFF/Inputs/machine-x64.yaml2
-rw-r--r--test/COFF/Inputs/machine-x86.yaml2
-rw-r--r--test/COFF/Inputs/manifestinput.test13
-rw-r--r--test/COFF/Inputs/ret42.yaml2
-rw-r--r--test/COFF/alternatename.test4
-rw-r--r--test/COFF/ar-comdat.test2
-rw-r--r--test/COFF/armnt-blx23t.test2
-rw-r--r--test/COFF/armnt-branch24t.test2
-rw-r--r--test/COFF/armnt-imports.test2
-rw-r--r--test/COFF/armnt-mov32t-exec.test2
-rw-r--r--test/COFF/armnt-movt32t.test2
-rw-r--r--test/COFF/base.test2
-rw-r--r--test/COFF/baserel.test2
-rw-r--r--test/COFF/common.test2
-rw-r--r--test/COFF/conflict.test2
-rw-r--r--test/COFF/debug.test2
-rw-r--r--test/COFF/dllorder.test65
-rw-r--r--test/COFF/entry-inference.test2
-rw-r--r--test/COFF/entry-inference2.test4
-rw-r--r--test/COFF/entry-inference32.test2
-rw-r--r--test/COFF/entry-mangled.test2
-rw-r--r--test/COFF/export32.test4
-rw-r--r--test/COFF/force.test2
-rw-r--r--test/COFF/icf-circular.test2
-rw-r--r--test/COFF/icf-circular2.test2
-rw-r--r--test/COFF/icf-different-align.test2
-rw-r--r--test/COFF/icf-local.test2
-rw-r--r--test/COFF/icf-simple.test2
-rw-r--r--test/COFF/imports-mangle.test2
-rw-r--r--test/COFF/include.test4
-rw-r--r--test/COFF/internal.test2
-rw-r--r--test/COFF/invalid-obj.test2
-rw-r--r--test/COFF/loadcfg.ll2
-rw-r--r--test/COFF/loadcfg.test22
-rw-r--r--test/COFF/loadcfg32.test20
-rw-r--r--test/COFF/locally-imported.test2
-rw-r--r--test/COFF/locally-imported32.test2
-rw-r--r--test/COFF/long-section-name.test2
-rw-r--r--test/COFF/manifestinput.test10
-rw-r--r--test/COFF/merge.test2
-rw-r--r--test/COFF/opt.test2
-rw-r--r--test/COFF/out.test6
-rw-r--r--test/COFF/reloc-arm.test2
-rw-r--r--test/COFF/reloc-x64.test2
-rw-r--r--test/COFF/reloc-x86.test2
-rw-r--r--test/COFF/safeseh.test2
-rw-r--r--test/COFF/section.test62
-rw-r--r--test/COFF/seh.test2
-rw-r--r--test/COFF/sort-debug.test2
-rw-r--r--test/COFF/subsystem-inference.test2
-rw-r--r--test/COFF/symtab.test2
-rw-r--r--test/COFF/tls.test2
-rw-r--r--test/COFF/tls32.test4
-rw-r--r--test/COFF/unwind.test2
-rw-r--r--test/COFF/weak-external.test2
-rw-r--r--test/COFF/weak-external2.test2
-rw-r--r--test/COFF/weak-external3.test2
-rw-r--r--test/Driver/def-lib-search.test8
-rw-r--r--test/Driver/flavor-option.test8
-rw-r--r--test/Driver/lib-search.test24
-rw-r--r--test/Driver/so-whole-archive.test63
-rw-r--r--test/Driver/trivial-driver.test5
-rw-r--r--test/Driver/undef-basic.objtxt22
-rw-r--r--test/ELF/Inputs/aarch64-copy2.s5
-rw-r--r--test/ELF/Inputs/aarch64-tls-gdie.s4
-rw-r--r--test/ELF/Inputs/abs-hidden.s3
-rw-r--r--test/ELF/Inputs/allow-shlib-undefined.s2
-rw-r--r--test/ELF/Inputs/archive.s4
-rw-r--r--test/ELF/Inputs/arm-plt-reloc.s14
-rw-r--r--test/ELF/Inputs/arm-thumb-blx-targets.s36
-rw-r--r--test/ELF/Inputs/arm-thumb-narrow-branch.s18
-rw-r--r--test/ELF/Inputs/conflict.s7
-rw-r--r--test/ELF/Inputs/copy-in-shared.s4
-rw-r--r--test/ELF/Inputs/copy-rel-corrupted.s4
-rw-r--r--test/ELF/Inputs/copy-rel-pie.s9
-rw-r--r--test/ELF/Inputs/ctors_dtors_priority1.s5
-rw-r--r--test/ELF/Inputs/ctors_dtors_priority2.s5
-rw-r--r--test/ELF/Inputs/ctors_dtors_priority3.s5
-rw-r--r--test/ELF/Inputs/duplicated-plt-entry.s3
-rw-r--r--test/ELF/Inputs/dynamic-reloc-weak.s11
-rw-r--r--test/ELF/Inputs/ehframe-relocation.s2
-rw-r--r--test/ELF/Inputs/empty-ver.ver2
-rw-r--r--test/ELF/Inputs/far-arm-abs.s13
-rw-r--r--test/ELF/Inputs/far-arm-thumb-abs.s24
-rw-r--r--test/ELF/Inputs/gc-sections-weak.s8
-rw-r--r--test/ELF/Inputs/gnu-ifunc-gotpcrel.s4
-rw-r--r--test/ELF/Inputs/gotpc-relax-und-dso.s4
-rw-r--r--test/ELF/Inputs/icf2.s5
-rw-r--r--test/ELF/Inputs/invalid-cie-version2.elfbin0 -> 1128 bytes
-rw-r--r--test/ELF/Inputs/libsearch-dyn.s2
-rw-r--r--test/ELF/Inputs/libsearch-st.s2
-rw-r--r--test/ELF/Inputs/mips-align-err.s2
-rw-r--r--test/ELF/Inputs/mips-dynamic.s24
-rw-r--r--test/ELF/Inputs/mips-gp-disp.sobin131832 -> 131828 bytes
-rw-r--r--test/ELF/Inputs/mips-nonalloc.s2
-rw-r--r--test/ELF/Inputs/mips-pic.s19
-rw-r--r--test/ELF/Inputs/mips-tls.s5
-rw-r--r--test/ELF/Inputs/plt-aarch64.s5
-rw-r--r--test/ELF/Inputs/ppc64-addr16-error.s3
-rw-r--r--test/ELF/Inputs/protected-shared.s10
-rw-r--r--test/ELF/Inputs/relocatable-ehframe.s14
-rw-r--r--test/ELF/Inputs/relocatable.s22
-rw-r--r--test/ELF/Inputs/relocatable2.s22
-rw-r--r--test/ELF/Inputs/relocation-copy-alias.s25
-rw-r--r--test/ELF/Inputs/relocation-copy-arm.s22
-rw-r--r--test/ELF/Inputs/resolution-shared.s2
-rw-r--r--test/ELF/Inputs/shared.s4
-rw-r--r--test/ELF/Inputs/start-lib-comdat.s5
-rw-r--r--test/ELF/Inputs/start-lib1.s3
-rw-r--r--test/ELF/Inputs/start-lib2.s2
-rw-r--r--test/ELF/Inputs/symbol-override.s16
-rw-r--r--test/ELF/Inputs/tls-got-entry.s13
-rw-r--r--test/ELF/Inputs/tls-in-archive.s3
-rw-r--r--test/ELF/Inputs/trace-ar1.s2
-rw-r--r--test/ELF/Inputs/trace-ar2.s2
-rw-r--r--test/ELF/Inputs/trace-symbols-foo-strong.s14
-rw-r--r--test/ELF/Inputs/trace-symbols-foo-weak.s12
-rw-r--r--test/ELF/Inputs/undef-with-plt-addr.s7
-rw-r--r--test/ELF/Inputs/undef.s3
-rw-r--r--test/ELF/Inputs/unresolved-symbols.s3
-rw-r--r--test/ELF/Inputs/verdef-defaultver.s22
-rw-r--r--test/ELF/Inputs/verdef.s6
-rwxr-xr-xtest/ELF/Inputs/verneed.so.sh58
-rw-r--r--test/ELF/Inputs/version-script-err.script4
-rw-r--r--test/ELF/Inputs/version-use.script6
-rw-r--r--test/ELF/Inputs/visibility.s1
-rw-r--r--test/ELF/Inputs/warn-common.s2
-rw-r--r--test/ELF/Inputs/warn-common2.s8
-rw-r--r--test/ELF/Inputs/whole-archive.s2
-rw-r--r--test/ELF/Inputs/x86-64-relax-offset.s7
-rw-r--r--test/ELF/Inputs/x86-64-reloc-error.s7
-rw-r--r--test/ELF/Inputs/x86-64-tls-gd-got.s6
-rw-r--r--test/ELF/aarch64-abs64-dyn.s27
-rw-r--r--test/ELF/aarch64-copy.s38
-rw-r--r--test/ELF/aarch64-copy2.s27
-rw-r--r--test/ELF/aarch64-fpic-abs16.s2
-rw-r--r--test/ELF/aarch64-fpic-add_abs_lo12_nc.s2
-rw-r--r--test/ELF/aarch64-fpic-adr_prel_lo21.s2
-rw-r--r--test/ELF/aarch64-fpic-adr_prel_pg_hi21.s2
-rw-r--r--test/ELF/aarch64-fpic-got.s18
-rw-r--r--test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s2
-rw-r--r--test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s2
-rw-r--r--test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s2
-rw-r--r--test/ELF/aarch64-fpic-prel16.s2
-rw-r--r--test/ELF/aarch64-fpic-prel32.s2
-rw-r--r--test/ELF/aarch64-fpic-prel64.s2
-rw-r--r--test/ELF/aarch64-gnu-ifunc-nosym.s6
-rw-r--r--test/ELF/aarch64-gnu-ifunc.s16
-rw-r--r--test/ELF/aarch64-got-relocations.s21
-rw-r--r--test/ELF/aarch64-got.s18
-rw-r--r--test/ELF/aarch64-relative.s26
-rw-r--r--test/ELF/aarch64-relocs.s30
-rw-r--r--test/ELF/aarch64-tls-gdie.s34
-rw-r--r--test/ELF/aarch64-tls-gdle.s26
-rw-r--r--test/ELF/aarch64-tls-ie.s3
-rw-r--r--test/ELF/aarch64-tls-iele.s33
-rw-r--r--test/ELF/aarch64-tls-le.s31
-rw-r--r--test/ELF/aarch64-tls-pie.s28
-rw-r--r--test/ELF/aarch64-tls-static.s37
-rw-r--r--test/ELF/aarch64-tlsdesc.s24
-rw-r--r--test/ELF/abs-hidden.s46
-rw-r--r--test/ELF/allow-shlib-undefined.s2
-rw-r--r--test/ELF/amdgpu-entry.s2
-rw-r--r--test/ELF/amdgpu-globals.s20
-rw-r--r--test/ELF/amdgpu-kernels.s10
-rw-r--r--test/ELF/amdgpu-relocs.s33
-rw-r--r--test/ELF/archive.s4
-rw-r--r--test/ELF/arm-abs32-dyn.s32
-rw-r--r--test/ELF/arm-attributes-remove.s45
-rw-r--r--test/ELF/arm-blx.s113
-rw-r--r--test/ELF/arm-branch-error.s19
-rw-r--r--test/ELF/arm-branch.s59
-rw-r--r--test/ELF/arm-copy.s81
-rw-r--r--test/ELF/arm-data-prel.s63
-rw-r--r--test/ELF/arm-data-relocs.s20
-rw-r--r--test/ELF/arm-fpic-got.s63
-rw-r--r--test/ELF/arm-gnu-ifunc-nosym.s27
-rw-r--r--test/ELF/arm-gnu-ifunc.s131
-rw-r--r--test/ELF/arm-got-relative.s53
-rw-r--r--test/ELF/arm-gotoff.s74
-rw-r--r--test/ELF/arm-mov-relocs.s94
-rw-r--r--test/ELF/arm-plt-reloc.s90
-rw-r--r--test/ELF/arm-thumb-blx.s85
-rw-r--r--test/ELF/arm-thumb-branch-error.s19
-rw-r--r--test/ELF/arm-thumb-branch.s59
-rw-r--r--test/ELF/arm-thumb-interwork-thunk.s375
-rw-r--r--test/ELF/arm-thumb-narrow-branch-check.s72
-rw-r--r--test/ELF/arm-thumb-plt-reloc.s101
-rw-r--r--test/ELF/as-needed-no-reloc.s23
-rw-r--r--test/ELF/as-needed.s5
-rw-r--r--test/ELF/avoid-empty-program-headers.s78
-rw-r--r--test/ELF/basic-aarch64.s2
-rw-r--r--test/ELF/basic-mips.s99
-rw-r--r--test/ELF/basic-ppc.s13
-rw-r--r--test/ELF/basic.s22
-rw-r--r--test/ELF/basic32.s4
-rw-r--r--test/ELF/basic64be.s76
-rw-r--r--test/ELF/bsymbolic-undef.s26
-rw-r--r--test/ELF/bsymbolic.s34
-rw-r--r--test/ELF/build-id.s38
-rw-r--r--test/ELF/combrelocs.s92
-rw-r--r--test/ELF/comdat.s11
-rw-r--r--test/ELF/common.s3
-rw-r--r--test/ELF/compressed-debug-input.s61
-rw-r--r--test/ELF/conflict.s26
-rw-r--r--test/ELF/copy-errors.s15
-rw-r--r--test/ELF/copy-in-shared.s10
-rw-r--r--test/ELF/copy-rel-corrupted.s10
-rw-r--r--test/ELF/copy-rel-pie-error.s12
-rw-r--r--test/ELF/copy-rel-pie.s44
-rw-r--r--test/ELF/ctors_dtors_priority.s41
-rw-r--r--test/ELF/default-output.s2
-rw-r--r--test/ELF/discard-merge-locals.s11
-rw-r--r--test/ELF/discard-merge-unnamed.s11
-rw-r--r--test/ELF/discard-none.s2
-rw-r--r--test/ELF/dont-export-hidden.s39
-rw-r--r--test/ELF/driver.test49
-rw-r--r--test/ELF/duplicate-internal.s2
-rw-r--r--test/ELF/duplicated-plt-entry.s17
-rw-r--r--test/ELF/dynamic-list.s110
-rw-r--r--test/ELF/dynamic-reloc-in-ro.s8
-rw-r--r--test/ELF/dynamic-reloc-weak.s14
-rw-r--r--test/ELF/dynamic-reloc.s2
-rw-r--r--test/ELF/dynamic.s44
-rw-r--r--test/ELF/dynsym-pie.s36
-rw-r--r--test/ELF/edata-etext.s117
-rw-r--r--test/ELF/eh-frame-dyn-rel.s10
-rw-r--r--test/ELF/eh-frame-gc.s20
-rw-r--r--test/ELF/eh-frame-hdr-abs-fde.s33
-rw-r--r--test/ELF/eh-frame-hdr-augmentation.s38
-rw-r--r--test/ELF/eh-frame-hdr-icf.s27
-rw-r--r--test/ELF/eh-frame-hdr-no-out.s6
-rw-r--r--test/ELF/eh-frame-hdr-no-out2.s19
-rw-r--r--test/ELF/eh-frame-hdr.s127
-rw-r--r--test/ELF/eh-frame-marker.s6
-rw-r--r--test/ELF/eh-frame-merge.s2
-rw-r--r--test/ELF/eh-frame-multilpe-cie.s12
-rw-r--r--test/ELF/eh-frame-type.test5
-rw-r--r--test/ELF/ehframe-relocation.s8
-rw-r--r--test/ELF/empty-ver.s25
-rw-r--r--test/ELF/emulation.s118
-rw-r--r--test/ELF/end.s8
-rw-r--r--test/ELF/entry.s4
-rw-r--r--test/ELF/fatal-warnings.s16
-rw-r--r--test/ELF/file-sym.s12
-rw-r--r--test/ELF/gc-merge-local-sym.s34
-rw-r--r--test/ELF/gc-sections-eh.s13
-rw-r--r--test/ELF/gc-sections-local-sym.s57
-rw-r--r--test/ELF/gc-sections-lsda.s21
-rw-r--r--test/ELF/gc-sections-merge-addend.s39
-rw-r--r--test/ELF/gc-sections-merge-implicit-addend.s39
-rw-r--r--test/ELF/gc-sections-merge.s61
-rw-r--r--test/ELF/gc-sections-protected.s18
-rw-r--r--test/ELF/gc-sections-shared.s34
-rw-r--r--test/ELF/gc-sections-weak.s24
-rw-r--r--test/ELF/global_offset_table_shared.s9
-rw-r--r--test/ELF/gnu-ifunc-gotpcrel.s14
-rw-r--r--test/ELF/gnu-ifunc-i386.s16
-rw-r--r--test/ELF/gnu-ifunc-nosym-i386.s6
-rw-r--r--test/ELF/gnu-ifunc-nosym.s6
-rw-r--r--test/ELF/gnu-ifunc-relative.s23
-rw-r--r--test/ELF/gnu-ifunc.s18
-rw-r--r--test/ELF/gnu-unique.s33
-rw-r--r--test/ELF/got-plt-header.s30
-rw-r--r--test/ELF/gotpc-relax-nopic.s81
-rw-r--r--test/ELF/gotpc-relax-und-dso.s72
-rw-r--r--test/ELF/gotpc-relax.s98
-rw-r--r--test/ELF/gotpcrelx.s30
-rw-r--r--test/ELF/i386-got-and-copy.s25
-rw-r--r--test/ELF/i386-gotpc.s20
-rw-r--r--test/ELF/i386-merge.s50
-rw-r--r--test/ELF/i386-relative.s14
-rw-r--r--test/ELF/i386-relax-reloc.s12
-rw-r--r--test/ELF/i386-tls-ie-shared.s110
-rw-r--r--test/ELF/icf1.s23
-rw-r--r--test/ELF/icf2.s17
-rw-r--r--test/ELF/icf3.s19
-rw-r--r--test/ELF/icf4.s19
-rw-r--r--test/ELF/icf5.s19
-rw-r--r--test/ELF/icf6.s23
-rw-r--r--test/ELF/icf7.s29
-rw-r--r--test/ELF/image-base.s60
-rw-r--r--test/ELF/incompatible.s1
-rw-r--r--test/ELF/init-fini.s2
-rw-r--r--test/ELF/init_fini_priority.s37
-rw-r--r--test/ELF/invalid-cie-length.s2
-rw-r--r--test/ELF/invalid-cie-length3.s2
-rw-r--r--test/ELF/invalid-cie-length4.s2
-rw-r--r--test/ELF/invalid-cie-length5.s2
-rw-r--r--test/ELF/invalid-cie-reference.s2
-rw-r--r--test/ELF/invalid-dynamic-list.test37
-rw-r--r--test/ELF/invalid-elf.test13
-rw-r--r--test/ELF/invalid-linkerscript.test54
-rw-r--r--test/ELF/invalid-relocations.test5
-rw-r--r--test/ELF/libsearch.s12
-rw-r--r--test/ELF/linkerscript-align.s41
-rw-r--r--test/ELF/linkerscript-diagnostic.s66
-rw-r--r--test/ELF/linkerscript-locationcounter.s340
-rw-r--r--test/ELF/linkerscript-orphans.s31
-rw-r--r--test/ELF/linkerscript-phdr-check.s15
-rw-r--r--test/ELF/linkerscript-repsection-va.s24
-rw-r--r--test/ELF/linkerscript-sections-keep.s80
-rw-r--r--test/ELF/linkerscript-sections-padding.s44
-rw-r--r--test/ELF/linkerscript-sections.s10
-rw-r--r--test/ELF/linkerscript-symbol-conflict.s11
-rw-r--r--test/ELF/linkerscript-symbols.s11
-rw-r--r--test/ELF/linkerscript-va.s24
-rw-r--r--test/ELF/linkerscript.s38
-rw-r--r--test/ELF/linkerscript2.s8
-rw-r--r--test/ELF/lit.local.cfg2
-rw-r--r--test/ELF/llvm33-rela-outside-group.s11
-rw-r--r--test/ELF/local-dynamic.s11
-rw-r--r--test/ELF/local-got-pie.s36
-rw-r--r--test/ELF/local-undefined-symbol.s13
-rw-r--r--test/ELF/lto/Inputs/archive-2.ll6
-rw-r--r--test/ELF/lto/Inputs/archive-3.ll5
-rw-r--r--test/ELF/lto/Inputs/archive.ll6
-rw-r--r--test/ELF/lto/Inputs/available-externally.ll6
-rw-r--r--test/ELF/lto/Inputs/comdat.s5
-rw-r--r--test/ELF/lto/Inputs/common.s1
-rw-r--r--test/ELF/lto/Inputs/drop-debug-info.bcbin0 -> 1152 bytes
-rw-r--r--test/ELF/lto/Inputs/drop-linkage.ll12
-rw-r--r--test/ELF/lto/Inputs/dynsym.s3
-rw-r--r--test/ELF/lto/Inputs/internalize-exportdyn.ll6
-rw-r--r--test/ELF/lto/Inputs/internalize-undef.ll6
-rw-r--r--test/ELF/lto/Inputs/irmover-error.ll6
-rw-r--r--test/ELF/lto/Inputs/linkonce-odr.ll6
-rw-r--r--test/ELF/lto/Inputs/linkonce.ll6
-rw-r--r--test/ELF/lto/Inputs/resolution.s4
-rw-r--r--test/ELF/lto/Inputs/save-temps.ll6
-rw-r--r--test/ELF/lto/Inputs/shared.s7
-rw-r--r--test/ELF/lto/Inputs/start-lib1.ll8
-rw-r--r--test/ELF/lto/Inputs/start-lib2.ll6
-rw-r--r--test/ELF/lto/Inputs/tls-mixed.s4
-rw-r--r--test/ELF/lto/Inputs/type-merge.ll8
-rw-r--r--test/ELF/lto/Inputs/type-merge2.ll8
-rw-r--r--test/ELF/lto/Inputs/undef-mixed.s3
-rw-r--r--test/ELF/lto/Inputs/unnamed-addr-lib.s6
-rw-r--r--test/ELF/lto/Inputs/visibility.s8
-rw-r--r--test/ELF/lto/archive-2.ll28
-rw-r--r--test/ELF/lto/archive-3.ll19
-rw-r--r--test/ELF/lto/archive.ll37
-rw-r--r--test/ELF/lto/asmundef.ll25
-rw-r--r--test/ELF/lto/available-externally.ll22
-rw-r--r--test/ELF/lto/combined-lto-object-name.ll14
-rw-r--r--test/ELF/lto/comdat.ll21
-rw-r--r--test/ELF/lto/comdat2.ll40
-rw-r--r--test/ELF/lto/common.ll31
-rw-r--r--test/ELF/lto/common2.ll24
-rw-r--r--test/ELF/lto/ctors.ll18
-rw-r--r--test/ELF/lto/discard-value-names.ll23
-rw-r--r--test/ELF/lto/drop-debug-info.ll9
-rw-r--r--test/ELF/lto/drop-linkage.ll14
-rw-r--r--test/ELF/lto/duplicated.ll10
-rw-r--r--test/ELF/lto/dynamic-list.ll25
-rw-r--r--test/ELF/lto/dynsym.ll25
-rw-r--r--test/ELF/lto/inline-asm.ll11
-rw-r--r--test/ELF/lto/internalize-basic.ll21
-rw-r--r--test/ELF/lto/internalize-exportdyn.ll47
-rw-r--r--test/ELF/lto/internalize-llvmused.ll20
-rw-r--r--test/ELF/lto/internalize-undef.ll16
-rw-r--r--test/ELF/lto/internalize-version-script.ll22
-rw-r--r--test/ELF/lto/invalid-bitcode.ll12
-rw-r--r--test/ELF/lto/irmover-error.ll12
-rw-r--r--test/ELF/lto/linkage.ll20
-rw-r--r--test/ELF/lto/linkonce-odr.ll17
-rw-r--r--test/ELF/lto/linkonce.ll17
-rw-r--r--test/ELF/lto/lto-start.ll23
-rw-r--r--test/ELF/lto/ltopasses-basic.ll18
-rw-r--r--test/ELF/lto/ltopasses-custom.ll30
-rw-r--r--test/ELF/lto/metadata.ll13
-rw-r--r--test/ELF/lto/mix-platforms.ll10
-rw-r--r--test/ELF/lto/module-asm.ll19
-rw-r--r--test/ELF/lto/opt-level.ll29
-rw-r--r--test/ELF/lto/parallel-internalize.ll57
-rw-r--r--test/ELF/lto/parallel.ll24
-rw-r--r--test/ELF/lto/pic.ll20
-rw-r--r--test/ELF/lto/relax-relocs.ll15
-rw-r--r--test/ELF/lto/resolution.ll27
-rw-r--r--test/ELF/lto/save-temps.ll20
-rw-r--r--test/ELF/lto/shlib-undefined.ll27
-rw-r--r--test/ELF/lto/start-lib.ll27
-rw-r--r--test/ELF/lto/tls-mixed.ll10
-rw-r--r--test/ELF/lto/tls-preserve.ll25
-rw-r--r--test/ELF/lto/type-merge.ll26
-rw-r--r--test/ELF/lto/type-merge2.ll27
-rw-r--r--test/ELF/lto/undef-mixed.ll22
-rw-r--r--test/ELF/lto/undef-weak.ll29
-rw-r--r--test/ELF/lto/undef.ll20
-rw-r--r--test/ELF/lto/undefined-puts.ll28
-rw-r--r--test/ELF/lto/unnamed-addr-comdat.ll11
-rw-r--r--test/ELF/lto/unnamed-addr-lib.ll21
-rw-r--r--test/ELF/lto/unnamed-addr.ll14
-rw-r--r--test/ELF/lto/verify-invalid.ll17
-rw-r--r--test/ELF/lto/version-script.ll50
-rw-r--r--test/ELF/lto/visibility.ll35
-rw-r--r--test/ELF/lto/weak.ll16
-rw-r--r--test/ELF/merge-shared-str.s28
-rw-r--r--test/ELF/merge-shared.s2
-rw-r--r--test/ELF/merge-string-align.s25
-rw-r--r--test/ELF/merge-string-error.s4
-rw-r--r--test/ELF/merge-string-no-null.s2
-rw-r--r--test/ELF/merge-string.s26
-rw-r--r--test/ELF/merge.s6
-rw-r--r--test/ELF/mips-26.s95
-rw-r--r--test/ELF/mips-32.s78
-rw-r--r--test/ELF/mips-64-disp.s89
-rw-r--r--test/ELF/mips-64-got.s87
-rw-r--r--test/ELF/mips-64-gprel-so.s23
-rw-r--r--test/ELF/mips-64-rels.s46
-rw-r--r--test/ELF/mips-64.s63
-rw-r--r--test/ELF/mips-align-err.s12
-rw-r--r--test/ELF/mips-dynamic.s19
-rw-r--r--test/ELF/mips-gnu-hash.s2
-rw-r--r--test/ELF/mips-got-and-copy.s57
-rw-r--r--test/ELF/mips-got-extsym.s59
-rw-r--r--test/ELF/mips-got-redundant.s58
-rw-r--r--test/ELF/mips-got-relocs.s5
-rw-r--r--test/ELF/mips-got-weak.s172
-rw-r--r--test/ELF/mips-got16.s120
-rw-r--r--test/ELF/mips-gp-disp.s9
-rw-r--r--test/ELF/mips-gp-local.s20
-rw-r--r--test/ELF/mips-gprel32-relocs-gp0.test31
-rw-r--r--test/ELF/mips-gprel32-relocs.s2
-rw-r--r--test/ELF/mips-hilo-gp-disp.s21
-rw-r--r--test/ELF/mips-hilo-hi-only.s2
-rw-r--r--test/ELF/mips-hilo.s10
-rw-r--r--test/ELF/mips-jalr.test7
-rw-r--r--test/ELF/mips-lo16-not-relative.s23
-rw-r--r--test/ELF/mips-nonalloc.s21
-rw-r--r--test/ELF/mips-npic-call-pic.s144
-rw-r--r--test/ELF/mips-options-r.test19
-rw-r--r--test/ELF/mips-options.s28
-rw-r--r--test/ELF/mips-pc-relocs.s15
-rw-r--r--test/ELF/mips-plt-copy.s85
-rw-r--r--test/ELF/mips-relocs.s42
-rw-r--r--test/ELF/mips-sto-plt.s66
-rw-r--r--test/ELF/mips-tls-64.s86
-rw-r--r--test/ELF/mips-tls-hilo.s52
-rw-r--r--test/ELF/mips-tls.s77
-rw-r--r--test/ELF/no-augmentation.s19
-rw-r--r--test/ELF/no-inhibit-exec.s4
-rw-r--r--test/ELF/no-plt-shared.s17
-rw-r--r--test/ELF/no-undefined.s2
-rw-r--r--test/ELF/noplt-pie.s21
-rw-r--r--test/ELF/note.s18
-rw-r--r--test/ELF/phdr-align.s82
-rw-r--r--test/ELF/pie-weak.s16
-rw-r--r--test/ELF/pie.s102
-rw-r--r--test/ELF/plt-aarch64.s2
-rw-r--r--test/ELF/plt-i686.s20
-rw-r--r--test/ELF/plt.s2
-rw-r--r--test/ELF/ppc64-addr16-error.s5
-rw-r--r--test/ELF/ppc64-relocs.s4
-rw-r--r--test/ELF/ppc64-toc-restore.s4
-rw-r--r--test/ELF/pre_init_fini_array.s24
-rw-r--r--test/ELF/progname.s21
-rw-r--r--test/ELF/protected-shared.s52
-rw-r--r--test/ELF/rel-offset.s15
-rw-r--r--test/ELF/relative-dynamic-reloc-pie.s26
-rw-r--r--test/ELF/relative-dynamic-reloc-ppc64.s7
-rw-r--r--test/ELF/relative-dynamic-reloc.s7
-rw-r--r--test/ELF/relocatable-bss.s40
-rw-r--r--test/ELF/relocatable-ehframe.s51
-rw-r--r--test/ELF/relocatable-reloc.s14
-rw-r--r--test/ELF/relocatable-symbols.s183
-rw-r--r--test/ELF/relocatable.s121
-rw-r--r--test/ELF/relocation-copy-alias.s67
-rw-r--r--test/ELF/relocation-copy-flags.s73
-rw-r--r--test/ELF/relocation-copy-i686.s2
-rw-r--r--test/ELF/relocation-copy.s2
-rw-r--r--test/ELF/relocation-i686.s24
-rw-r--r--test/ELF/relocation-in-merge.s2
-rw-r--r--test/ELF/relocation-non-alloc.s60
-rw-r--r--test/ELF/relocation-past-merge-end.s3
-rw-r--r--test/ELF/relocation-relative-absolute.s12
-rw-r--r--test/ELF/relocation-relative-synthetic.s11
-rw-r--r--test/ELF/relocation-relative-weak.s14
-rw-r--r--test/ELF/relocation-shared.s35
-rw-r--r--test/ELF/relocation-size-shared.s76
-rw-r--r--test/ELF/relocation-size.s138
-rw-r--r--test/ELF/relocation.s21
-rw-r--r--test/ELF/relro-tls.s23
-rw-r--r--test/ELF/relro.s2
-rw-r--r--test/ELF/reproduce-error.s15
-rw-r--r--test/ELF/reproduce-linkerscript.s17
-rw-r--r--test/ELF/reproduce-thin-archive.s15
-rw-r--r--test/ELF/reproduce-windows.s12
-rw-r--r--test/ELF/reproduce.s67
-rw-r--r--test/ELF/resolution-shared.s15
-rw-r--r--test/ELF/resolution.s2
-rw-r--r--test/ELF/section-align-0.test3
-rw-r--r--test/ELF/section-name.s6
-rw-r--r--test/ELF/section-symbol.s13
-rw-r--r--test/ELF/shared-be.s7
-rw-r--r--test/ELF/shared.s19
-rw-r--r--test/ELF/soname.s2
-rw-r--r--test/ELF/splitstacks.s11
-rw-r--r--test/ELF/start-lib-comdat.s23
-rw-r--r--test/ELF/start-lib.s25
-rw-r--r--test/ELF/startstop-gccollect.s32
-rw-r--r--test/ELF/startstop-shared.s20
-rw-r--r--test/ELF/startstop.s16
-rw-r--r--test/ELF/string-gc.s73
-rw-r--r--test/ELF/string-table.s5
-rw-r--r--test/ELF/strip-all.s6
-rw-r--r--test/ELF/strip-debug.s25
-rw-r--r--test/ELF/symbol-override.s46
-rw-r--r--test/ELF/symbols.s14
-rw-r--r--test/ELF/sysroot.s4
-rw-r--r--test/ELF/tail-merge-string-align.s35
-rw-r--r--test/ELF/tls-archive.s10
-rw-r--r--test/ELF/tls-dynamic-i686.s24
-rw-r--r--test/ELF/tls-dynamic.s10
-rw-r--r--test/ELF/tls-got-entry.s25
-rw-r--r--test/ELF/tls-got.s2
-rw-r--r--test/ELF/tls-i686.s54
-rw-r--r--test/ELF/tls-in-archive.s11
-rw-r--r--test/ELF/tls-initial-exec-local.s36
-rw-r--r--test/ELF/tls-offset.s56
-rw-r--r--test/ELF/tls-opt-gdie.s27
-rw-r--r--test/ELF/tls-opt-iele-i686-nopic.s59
-rw-r--r--test/ELF/tls-opt-no-plt.s34
-rw-r--r--test/ELF/tls-opt.s74
-rw-r--r--test/ELF/tls-two-relocs.s30
-rw-r--r--test/ELF/trace-ar.s21
-rw-r--r--test/ELF/trace-symbols.s78
-rw-r--r--test/ELF/trace.s9
-rw-r--r--test/ELF/undef-shared.s14
-rw-r--r--test/ELF/undef-version-script.s40
-rw-r--r--test/ELF/undef-with-plt-addr-i686.s23
-rw-r--r--test/ELF/undef-with-plt-addr.s45
-rw-r--r--test/ELF/undef.s15
-rw-r--r--test/ELF/undefined-opt.s13
-rw-r--r--test/ELF/unresolved-symbols.s63
-rw-r--r--test/ELF/user_def_init_array_start.s10
-rw-r--r--test/ELF/valid-cie-length-dw64.s13
-rw-r--r--test/ELF/verdef-defaultver.s205
-rw-r--r--test/ELF/verdef-dependency.s44
-rw-r--r--test/ELF/verdef.s117
-rw-r--r--test/ELF/verneed-as-needed-weak.s14
-rw-r--r--test/ELF/verneed-local.s8
-rw-r--r--test/ELF/verneed.s173
-rw-r--r--test/ELF/version-script-err.s10
-rw-r--r--test/ELF/version-script-extern.s97
-rw-r--r--test/ELF/version-script-noundef.s22
-rw-r--r--test/ELF/version-script.s274
-rw-r--r--test/ELF/version-undef-sym.s42
-rw-r--r--test/ELF/version-use.s9
-rw-r--r--test/ELF/version-wildcard.test114
-rw-r--r--test/ELF/visibility.s31
-rw-r--r--test/ELF/warn-common.s25
-rw-r--r--test/ELF/weak-undef-hidden.s29
-rw-r--r--test/ELF/weak-undef-shared.s19
-rw-r--r--test/ELF/weak-undef.s21
-rw-r--r--test/ELF/whole-archive.s8
-rw-r--r--test/ELF/wildcards.s80
-rw-r--r--test/ELF/writable-merge.s4
-rw-r--r--test/ELF/x86-64-dyn-rel-error.s12
-rw-r--r--test/ELF/x86-64-dyn-rel-error2.s12
-rw-r--r--test/ELF/x86-64-rela.s11
-rw-r--r--test/ELF/x86-64-relax-offset.s13
-rw-r--r--test/ELF/x86-64-reloc-32-error.s8
-rw-r--r--test/ELF/x86-64-reloc-32-fpic.s7
-rw-r--r--test/ELF/x86-64-reloc-32S-error.s7
-rw-r--r--test/ELF/x86-64-reloc-error.s10
-rw-r--r--test/ELF/x86-64-reloc-pc32-fpic.s7
-rw-r--r--test/ELF/x86-64-reloc-range.s13
-rw-r--r--test/ELF/x86-64-tls-gd-got.s19
-rw-r--r--test/ELF/x86-64-tls-gd-local.s52
-rw-r--r--test/ELF/x86-64-tls-pie.s26
-rw-r--r--test/ELF/zdefs.s7
-rw-r--r--test/LinkerScript/expr-precedence.test34
-rw-r--r--test/LinkerScript/extern-bad-symbol.test22
-rw-r--r--test/LinkerScript/extern-empty.test19
-rw-r--r--test/LinkerScript/extern-valid.test29
-rw-r--r--test/LinkerScript/incomplete-ternary.test25
-rw-r--r--test/LinkerScript/libname-err-1.test11
-rw-r--r--test/LinkerScript/libname-err-2.test11
-rw-r--r--test/LinkerScript/linker-script-outputformat.test12
-rw-r--r--test/LinkerScript/linker-script.test46
-rw-r--r--test/LinkerScript/memory-empty.test17
-rw-r--r--test/LinkerScript/memory-missing-attrs.test32
-rw-r--r--test/LinkerScript/memory-missing-length.test29
-rw-r--r--test/LinkerScript/memory-missing-name.test31
-rw-r--r--test/LinkerScript/memory-missing-origin.test30
-rw-r--r--test/LinkerScript/memory-valid.test56
-rw-r--r--test/LinkerScript/missing-entry-symbol.test21
-rw-r--r--test/LinkerScript/missing-input-file-name.test25
-rw-r--r--test/LinkerScript/missing-input-sections.test27
-rw-r--r--test/LinkerScript/missing-operand.test24
-rw-r--r--test/LinkerScript/missing-output-section-name.test25
-rw-r--r--test/LinkerScript/missing-symbol.test24
-rw-r--r--test/LinkerScript/phdrs-sections.test29
-rw-r--r--test/LinkerScript/sections.test624
-rw-r--r--test/Unit/lit.site.cfg.in4
-rw-r--r--test/core/Inputs/archive-basic.objtxt21
-rw-r--r--test/core/Inputs/archive-chain.objtxt24
-rw-r--r--test/core/Inputs/archive-chain2.objtxt21
-rw-r--r--test/core/Inputs/archive-tentdef-search.objtxt11
-rw-r--r--test/core/Inputs/associates.objtxt8
-rw-r--r--test/core/Inputs/auto-hide-coalesce.objtxt20
-rw-r--r--test/core/Inputs/code-model-attributes.objtxt4
-rw-r--r--test/core/Inputs/code-model-attributes2.objtxt4
-rw-r--r--test/core/Inputs/code-model-attributes3.objtxt4
-rw-r--r--test/core/Inputs/code-model-attributes4.objtxt4
-rw-r--r--test/core/Inputs/code-model-attributes5.objtxt4
-rw-r--r--test/core/Inputs/constants-coalesce.objtxt9
-rw-r--r--test/core/Inputs/constants-coalesce2.objtxt10
-rw-r--r--test/core/Inputs/cstring-coalesce.objtxt6
-rw-r--r--test/core/Inputs/cstring-coalesce2.objtxt6
-rw-r--r--test/core/Inputs/custom-section-coalesce.objtxt15
-rw-r--r--test/core/Inputs/custom-section-coalesce2.objtxt13
-rw-r--r--test/core/Inputs/dead-strip-attributes.objtxt4
-rw-r--r--test/core/Inputs/dead-strip-attributes2.objtxt4
-rw-r--r--test/core/Inputs/dead-strip-basic.objtxt9
-rw-r--r--test/core/Inputs/dead-strip-basic2.objtxt8
-rw-r--r--test/core/Inputs/dead-strip-globals.objtxt9
-rw-r--r--test/core/Inputs/dead-strip-globals2.objtxt8
-rw-r--r--test/core/Inputs/error-duplicate-absolutes.objtxt5
-rw-r--r--test/core/Inputs/gnulinkonce-rearrange-resolve.objtxt26
-rw-r--r--test/core/Inputs/gnulinkonce-remaining-undef.objtxt34
-rw-r--r--test/core/Inputs/gnulinkonce-remaining-undef2.objtxt4
-rw-r--r--test/core/Inputs/gnulinkonce-resolve.objtxt25
-rw-r--r--test/core/Inputs/gnulinkonce-simple.objtxt4
-rw-r--r--test/core/Inputs/inline-coalesce.objtxt6
-rw-r--r--test/core/Inputs/inline-coalesce2.objtxt6
-rw-r--r--test/core/Inputs/multiple-def-error.objtxt5
-rw-r--r--test/core/Inputs/sectiongroup-deadstrip.objtxt3
-rw-r--r--test/core/Inputs/sectiongroup-gnulinkonce-error.objtxt26
-rw-r--r--test/core/Inputs/sectiongroup-rearrange-resolve.objtxt25
-rw-r--r--test/core/Inputs/sectiongroup-remaining-undef.objtxt34
-rw-r--r--test/core/Inputs/sectiongroup-remaining-undef2.objtxt4
-rw-r--r--test/core/Inputs/sectiongroup-resolve.objtxt26
-rw-r--r--test/core/Inputs/sectiongroup-simple.objtxt4
-rw-r--r--test/core/Inputs/shared-library-coalesce.objtxt28
-rw-r--r--test/core/Inputs/tent-merge.objtxt6
-rw-r--r--test/core/Inputs/undef-coalesce-error.objtxt8
-rw-r--r--test/core/Inputs/undef-coalesce-error2.objtxt8
-rw-r--r--test/core/Inputs/undef-coalesce.objtxt8
-rw-r--r--test/core/Inputs/undef-coalesce2.objtxt8
-rw-r--r--test/core/Inputs/undef-fallback.objtxt7
-rw-r--r--test/core/Inputs/undef-weak-coalesce.objtxt20
-rw-r--r--test/core/Inputs/weak-coalesce.objtxt5
-rw-r--r--test/core/Inputs/weak-coalesce2.objtxt6
-rw-r--r--test/core/absolute-basic.objtxt23
-rw-r--r--test/core/absolute-local.objtxt25
-rw-r--r--test/core/archive-basic.objtxt23
-rw-r--r--test/core/archive-chain.objtxt23
-rw-r--r--test/core/archive-tentdef-search.objtxt30
-rw-r--r--test/core/associates.objtxt21
-rw-r--r--test/core/auto-hide-coalesce.objtxt39
-rw-r--r--test/core/code-model-attributes.objtxt33
-rw-r--r--test/core/constants-coalesce.objtxt42
-rw-r--r--test/core/cstring-coalesce.objtxt29
-rw-r--r--test/core/custom-section-coalesce.objtxt50
-rw-r--r--test/core/custom-section.objtxt34
-rw-r--r--test/core/dead-strip-attributes.objtxt22
-rw-r--r--test/core/dead-strip-basic.objtxt45
-rw-r--r--test/core/dead-strip-globals.objtxt43
-rw-r--r--test/core/dead-strip-reverse.objtxt25
-rw-r--r--test/core/error-atom-attribute.objtxt19
-rw-r--r--test/core/error-atom-content-byte-value.objtxt18
-rw-r--r--test/core/error-atom-content-bytes.objtxt19
-rw-r--r--test/core/error-atom-type.objtxt19
-rw-r--r--test/core/error-atom-undefined-wrong-attribue.objtxt17
-rw-r--r--test/core/error-duplicate-absolutes.objtxt19
-rw-r--r--test/core/error-file-attribute.objtxt17
-rw-r--r--test/core/error-fixup-attribute.objtxt21
-rw-r--r--test/core/error-fixup-target.objtxt26
-rw-r--r--test/core/fixups-addend.objtxt50
-rw-r--r--test/core/fixups-dup-named.objtxt31
-rw-r--r--test/core/fixups-named.objtxt36
-rw-r--r--test/core/fixups-unnamed.objtxt40
-rw-r--r--test/core/gnulinkonce-rearrange-resolve.objtxt53
-rw-r--r--test/core/gnulinkonce-remaining-undef.objtxt43
-rw-r--r--test/core/gnulinkonce-resolve.objtxt63
-rw-r--r--test/core/gnulinkonce-simple.objtxt76
-rw-r--r--test/core/inline-coalesce.objtxt19
-rw-r--r--test/core/multiple-def-error.objtxt14
-rw-r--r--test/core/permissions.objtxt57
-rw-r--r--test/core/sectiongroup-deadstrip.objtxt84
-rw-r--r--test/core/sectiongroup-gnulinkonce-error.objtxt38
-rw-r--r--test/core/sectiongroup-rearrange-resolve.objtxt53
-rw-r--r--test/core/sectiongroup-remaining-undef.objtxt42
-rw-r--r--test/core/sectiongroup-resolve.objtxt64
-rw-r--r--test/core/sectiongroup-simple.objtxt76
-rw-r--r--test/core/shared-library-basic.objtxt40
-rw-r--r--test/core/shared-library-coalesce.objtxt55
-rw-r--r--test/core/tent-merge.objtxt19
-rw-r--r--test/core/undef-coalesce-error.objtxt31
-rw-r--r--test/core/undef-coalesce.objtxt26
-rw-r--r--test/core/undef-fallback.objtxt29
-rw-r--r--test/core/undef-weak-coalesce.objtxt52
-rw-r--r--test/core/weak-coalesce.objtxt16
-rw-r--r--test/darwin/cmdline-objc_gc.objtxt15
-rw-r--r--test/darwin/cmdline-objc_gc_compaction.objtxt15
-rw-r--r--test/darwin/cmdline-objc_gc_only.objtxt15
-rw-r--r--test/lit.cfg13
-rw-r--r--test/lit.site.cfg.in5
-rw-r--r--test/mach-o/Inputs/no-version-min-load-command-object.yaml22
-rw-r--r--test/mach-o/Inputs/swift-version-1.yaml18
-rw-r--r--test/mach-o/arm-interworking-movw.yaml6
-rw-r--r--test/mach-o/arm64-relocs-errors-delta64-offset.yaml2
-rw-r--r--test/mach-o/data-in-code-load-command.yaml35
-rw-r--r--test/mach-o/dead-strip-globals.yaml27
-rw-r--r--test/mach-o/dependency_info.yaml13
-rw-r--r--test/mach-o/do-not-emit-unwind-fde-arm64.yaml8
-rw-r--r--test/mach-o/dso_handle.yaml2
-rw-r--r--test/mach-o/eh-frame-relocs-arm64.yaml318
-rw-r--r--test/mach-o/error-simulator-vs-macosx.yaml30
-rw-r--r--test/mach-o/function-starts-load-command.yaml32
-rw-r--r--test/mach-o/hello-world-x86_64.yaml5
-rw-r--r--test/mach-o/interposing-section.yaml2
-rw-r--r--test/mach-o/lazy-bind-x86_64.yaml11
-rw-r--r--test/mach-o/mach_header-cpusubtype.yaml34
-rw-r--r--test/mach-o/mh_bundle_header.yaml9
-rw-r--r--test/mach-o/mh_dylib_header.yaml2
-rw-r--r--test/mach-o/objc-category-list-atom.yaml70
-rw-r--r--test/mach-o/objc-image-info-host-vs-simulator.yaml23
-rw-r--r--test/mach-o/objc-image-info-invalid-size.yaml20
-rw-r--r--test/mach-o/objc-image-info-invalid-version.yaml20
-rw-r--r--test/mach-o/objc-image-info-mismatched-swift-version.yaml20
-rw-r--r--test/mach-o/objc-image-info-pass-output.yaml30
-rw-r--r--test/mach-o/objc-image-info-simulator-vs-host.yaml23
-rw-r--r--test/mach-o/objc-image-info-unsupported-gc.yaml20
-rw-r--r--test/mach-o/objc_export_list.yaml2
-rw-r--r--test/mach-o/parse-cfstring32.yaml2
-rw-r--r--test/mach-o/parse-compact-unwind64.yaml2
-rw-r--r--test/mach-o/parse-data-relocs-x86_64.yaml126
-rw-r--r--test/mach-o/parse-data.yaml4
-rw-r--r--test/mach-o/parse-eh-frame.yaml2
-rw-r--r--test/mach-o/sdk-version-error.yaml22
-rw-r--r--test/mach-o/sectattrs.yaml30
-rw-r--r--test/mach-o/seg-protection-arm64.yaml78
-rw-r--r--test/mach-o/seg-protection-x86_64.yaml78
-rw-r--r--test/mach-o/source-version.yaml28
-rw-r--r--test/mach-o/subsections-via-symbols-default.yaml28
-rw-r--r--test/mach-o/unwind-info-simple-arm64.yaml2
-rw-r--r--test/mach-o/unwind-info-simple-x86_64.yaml4
-rw-r--r--test/mach-o/version-min-load-command-object.yaml35
-rw-r--r--test/mach-o/version-min-load-command.yaml43
-rw-r--r--test/old-elf/AArch64/Inputs/fn.c4
-rw-r--r--test/old-elf/AArch64/Inputs/fn.obin899 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/general-dyn-tls-0.yaml64
-rw-r--r--test/old-elf/AArch64/Inputs/initfini-option.c12
-rw-r--r--test/old-elf/AArch64/Inputs/initfini-option.obin1552 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/initfini.c13
-rw-r--r--test/old-elf/AArch64/Inputs/initfini.obin2056 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/initial-exec-tls-1.yaml77
-rw-r--r--test/old-elf/AArch64/Inputs/main.c4
-rw-r--r--test/old-elf/AArch64/Inputs/main.obin1064 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/no-interp-section.c1
-rw-r--r--test/old-elf/AArch64/Inputs/no-interp-section.obin903 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/zerosizedsection.obin816 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/zerosizedsection.s3
-rw-r--r--test/old-elf/AArch64/defsym.test22
-rw-r--r--test/old-elf/AArch64/dontignorezerosize-sections.test9
-rw-r--r--test/old-elf/AArch64/dynamicvars.test113
-rw-r--r--test/old-elf/AArch64/dynlib-nointerp-section.test5
-rw-r--r--test/old-elf/AArch64/general-dyn-tls-0.test103
-rw-r--r--test/old-elf/AArch64/initfini.test23
-rw-r--r--test/old-elf/AArch64/initial-exec-tls-0.test146
-rw-r--r--test/old-elf/AArch64/local-tls.test184
-rw-r--r--test/old-elf/AArch64/rel-abs16-overflow.test44
-rw-r--r--test/old-elf/AArch64/rel-abs16.test53
-rw-r--r--test/old-elf/AArch64/rel-abs32-overflow.test53
-rw-r--r--test/old-elf/AArch64/rel-abs32.test59
-rw-r--r--test/old-elf/AArch64/rel-abs64.test59
-rw-r--r--test/old-elf/AArch64/rel-adr_prel_lo21-overflow.test45
-rw-r--r--test/old-elf/AArch64/rel-adr_prel_lo21.test51
-rw-r--r--test/old-elf/AArch64/rel-adr_prel_pg_hi21-overflow.test45
-rw-r--r--test/old-elf/AArch64/rel-adr_prel_pg_hi21.test52
-rw-r--r--test/old-elf/AArch64/rel-bad.test44
-rw-r--r--test/old-elf/AArch64/rel-prel16-overflow.test53
-rw-r--r--test/old-elf/AArch64/rel-prel16.test59
-rw-r--r--test/old-elf/AArch64/rel-prel32-overflow.test53
-rw-r--r--test/old-elf/AArch64/rel-prel32.test59
-rw-r--r--test/old-elf/AArch64/rel-prel64.test59
-rw-r--r--test/old-elf/ARM/Inputs/fn.c1
-rwxr-xr-xtest/old-elf/ARM/Inputs/libfn.sobin4972 -> 0 bytes
-rwxr-xr-xtest/old-elf/ARM/Inputs/libobj.sobin5067 -> 0 bytes
-rw-r--r--test/old-elf/ARM/Inputs/obj.c4
-rw-r--r--test/old-elf/ARM/arm-symbols.test51
-rw-r--r--test/old-elf/ARM/defsym.test50
-rw-r--r--test/old-elf/ARM/dynamic-symbols.test83
-rw-r--r--test/old-elf/ARM/entry-point.test113
-rw-r--r--test/old-elf/ARM/exidx.test254
-rw-r--r--test/old-elf/ARM/header-flags.test57
-rw-r--r--test/old-elf/ARM/mapping-code-model.test160
-rw-r--r--test/old-elf/ARM/mapping-symbols.test122
-rw-r--r--test/old-elf/ARM/missing-symbol.test38
-rw-r--r--test/old-elf/ARM/plt-dynamic.test200
-rw-r--r--test/old-elf/ARM/plt-ifunc-interwork.test396
-rw-r--r--test/old-elf/ARM/plt-ifunc-mapping.test109
-rw-r--r--test/old-elf/ARM/rel-abs32.test58
-rw-r--r--test/old-elf/ARM/rel-arm-call.test112
-rw-r--r--test/old-elf/ARM/rel-arm-jump24-veneer-b.test122
-rw-r--r--test/old-elf/ARM/rel-arm-jump24-veneer-bl.test120
-rw-r--r--test/old-elf/ARM/rel-arm-jump24.test108
-rw-r--r--test/old-elf/ARM/rel-arm-mov.test64
-rw-r--r--test/old-elf/ARM/rel-arm-prel31.test90
-rw-r--r--test/old-elf/ARM/rel-arm-target1.test114
-rw-r--r--test/old-elf/ARM/rel-arm-thm-interwork.test121
-rw-r--r--test/old-elf/ARM/rel-base-prel.test61
-rw-r--r--test/old-elf/ARM/rel-copy.test60
-rw-r--r--test/old-elf/ARM/rel-glob-dat.test57
-rw-r--r--test/old-elf/ARM/rel-got-brel.test63
-rw-r--r--test/old-elf/ARM/rel-group-relocs.test71
-rw-r--r--test/old-elf/ARM/rel-ifunc.test101
-rw-r--r--test/old-elf/ARM/rel-jump-slot.test50
-rw-r--r--test/old-elf/ARM/rel-rel32.test56
-rw-r--r--test/old-elf/ARM/rel-thm-call.test114
-rw-r--r--test/old-elf/ARM/rel-thm-jump11.test209
-rw-r--r--test/old-elf/ARM/rel-thm-jump24-veneer.test120
-rw-r--r--test/old-elf/ARM/rel-thm-jump24.test110
-rw-r--r--test/old-elf/ARM/rel-thm-mov.test70
-rw-r--r--test/old-elf/ARM/rel-tls-ie32.test125
-rw-r--r--test/old-elf/ARM/rel-tls-le32.test73
-rw-r--r--test/old-elf/ARM/rel-v4bx.test72
-rw-r--r--test/old-elf/ARM/thm-symbols.test51
-rw-r--r--test/old-elf/ARM/two-got-for-symbol.test62
-rw-r--r--test/old-elf/ARM/undef-lazy-symbol.test133
-rw-r--r--test/old-elf/ARM/veneer-mapping.test92
-rw-r--r--test/old-elf/ARM/weak-branch.test221
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj-data.c3
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj-data.obin916 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj.c26
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj.obin1288 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/got-plt-order.c6
-rw-r--r--test/old-elf/Hexagon/Inputs/got-plt-order.obin964 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/libMaxAlignment.abin1010 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sda-base.obin1469 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata1.c3
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata1.obin684 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata2.c6
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata2.obin829 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/use-shared.hexagonbin872 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/dynlib-data.test9
-rw-r--r--test/old-elf/Hexagon/dynlib-gotoff.test128
-rw-r--r--test/old-elf/Hexagon/dynlib-hash.test9
-rw-r--r--test/old-elf/Hexagon/dynlib-rela.test9
-rw-r--r--test/old-elf/Hexagon/dynlib-syms.test7
-rw-r--r--test/old-elf/Hexagon/dynlib.test36
-rw-r--r--test/old-elf/Hexagon/hexagon-got-plt-order.test5
-rw-r--r--test/old-elf/Hexagon/hexagon-plt-setup.test12
-rw-r--r--test/old-elf/Hexagon/maxalignment.test8
-rw-r--r--test/old-elf/Hexagon/rela-order.test9
-rw-r--r--test/old-elf/Hexagon/sda-base.test4
-rw-r--r--test/old-elf/Hexagon/zerofillquick-sdata.test18
-rw-r--r--test/old-elf/Inputs/abs-test.i386bin504 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/allowduplicates.objtxt12
-rw-r--r--test/old-elf/Inputs/bar.o.x86-64bin1240 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/branch-test.hexagonbin700 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/branch-test.ppcbin852 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/consecutive-weak-defs.o.yaml65
-rw-r--r--test/old-elf/Inputs/constants-merge.x86-64bin1232 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/constdata.x86-64bin1688 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/foo.o.x86-64bin1240 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/globalconst.c2
-rw-r--r--test/old-elf/Inputs/globalconst.o.x86-64bin1072 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/gotpcrel.S11
-rw-r--r--test/old-elf/Inputs/gotpcrel.x86-64bin904 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/group-cmd-search-1.ls1
-rw-r--r--test/old-elf/Inputs/group-cmd-search-2.ls1
-rw-r--r--test/old-elf/Inputs/group-cmd-search-3.ls1
-rw-r--r--test/old-elf/Inputs/ifunc.S21
-rw-r--r--test/old-elf/Inputs/ifunc.cpp3
-rw-r--r--test/old-elf/Inputs/ifunc.cpp.x86-64bin1224 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/ifunc.x86-64bin912 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/libfnarchive.abin2656 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/libifunc.x86-64.sobin2512 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/libundef.sobin11128 -> 0 bytes
-rwxr-xr-xtest/old-elf/Inputs/libweaksym.sobin2160 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/main-with-global-def.o.yaml55
-rw-r--r--test/old-elf/Inputs/mainobj.x86_64bin1360 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/no-unique-section-names.x86-64bin2128 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/object-test.elf-hexagonbin1532 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/object-test.elf-i386bin1784 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/phdr.i386bin17536 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-sort-test.o.elf-hexagonbin1385 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-sortcommon-test.o.elf-hexagonbin1469 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-test.elf-hexagonbin891 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/reloc-test.elf-i386bin1076 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/reloc-xb.x86bin568 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/reloc-xt.x86bin548 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/relocs-dynamic.x86-64bin864 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/relocs.x86-64bin1536 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/responsefile1
-rw-r--r--test/old-elf/Inputs/rodata-test.hexagonbin669 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/rodata-test.i386bin537 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/rodata.c4
-rw-r--r--test/old-elf/Inputs/rodata.obin1568 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/section-test.i386bin717 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/shared.c16
-rw-r--r--test/old-elf/Inputs/shared.so-x86-64bin7536 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/shndx.o-x86_64bin624 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/stripped-empty.x86_64bin416 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/target-test.hexagonbin676 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/target-test.ppcbin552 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/tls-tbss-size.yaml59
-rw-r--r--test/old-elf/Inputs/tls.S50
-rw-r--r--test/old-elf/Inputs/tls.c11
-rw-r--r--test/old-elf/Inputs/tls.x86-64bin1424 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/tlsAddr.x86-64bin1752 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/tlsaddr.c8
-rw-r--r--test/old-elf/Inputs/undef-from-main-so.c1
-rw-r--r--test/old-elf/Inputs/undef-from-main.c5
-rw-r--r--test/old-elf/Inputs/undef-pc32.obin1248 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/undef.obin1264 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/undef2-so.o.yaml49
-rw-r--r--test/old-elf/Inputs/use-shared-32s.c8
-rw-r--r--test/old-elf/Inputs/use-shared-32s.x86-64bin1336 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/use-shared.c7
-rw-r--r--test/old-elf/Inputs/use-shared.x86-64bin1376 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/weaksym.obin840 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/writersyms.obin868 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/x86-64-relocs.S12
-rw-r--r--test/old-elf/Mips/abi-flags-01.test35
-rw-r--r--test/old-elf/Mips/abi-flags-02.test92
-rw-r--r--test/old-elf/Mips/abi-flags-03.test149
-rw-r--r--test/old-elf/Mips/abi-flags-04.test125
-rw-r--r--test/old-elf/Mips/abi-flags-05.test186
-rw-r--r--test/old-elf/Mips/abi-flags-06.test79
-rw-r--r--test/old-elf/Mips/abi-flags-07.test60
-rw-r--r--test/old-elf/Mips/abi-flags-08.test71
-rw-r--r--test/old-elf/Mips/abi-flags-09.test67
-rw-r--r--test/old-elf/Mips/abi-flags-10.test60
-rw-r--r--test/old-elf/Mips/abi-flags-11.test59
-rw-r--r--test/old-elf/Mips/base-address-64.test80
-rw-r--r--test/old-elf/Mips/base-address.test95
-rw-r--r--test/old-elf/Mips/ctors-order.test164
-rw-r--r--test/old-elf/Mips/driver-hash-style.test15
-rw-r--r--test/old-elf/Mips/dt-textrel-64.test74
-rw-r--r--test/old-elf/Mips/dt-textrel.test74
-rw-r--r--test/old-elf/Mips/dynamic-linking.test22
-rw-r--r--test/old-elf/Mips/dynamic-sym.test41
-rw-r--r--test/old-elf/Mips/dynlib-dynamic.test110
-rw-r--r--test/old-elf/Mips/dynlib-dynsym-micro.test208
-rw-r--r--test/old-elf/Mips/dynlib-dynsym.test202
-rw-r--r--test/old-elf/Mips/dynlib-fileheader-64.test72
-rw-r--r--test/old-elf/Mips/dynlib-fileheader-micro-64.test75
-rw-r--r--test/old-elf/Mips/dynlib-fileheader-micro.test79
-rw-r--r--test/old-elf/Mips/dynlib-fileheader.test76
-rw-r--r--test/old-elf/Mips/dynsym-table-1.test127
-rw-r--r--test/old-elf/Mips/dynsym-table-2.test105
-rw-r--r--test/old-elf/Mips/e-flags-merge-1-64.test30
-rw-r--r--test/old-elf/Mips/e-flags-merge-1.test56
-rw-r--r--test/old-elf/Mips/e-flags-merge-10.test43
-rw-r--r--test/old-elf/Mips/e-flags-merge-11.test43
-rw-r--r--test/old-elf/Mips/e-flags-merge-12.test44
-rw-r--r--test/old-elf/Mips/e-flags-merge-2-64.test33
-rw-r--r--test/old-elf/Mips/e-flags-merge-2.test35
-rw-r--r--test/old-elf/Mips/e-flags-merge-3-64.test130
-rw-r--r--test/old-elf/Mips/e-flags-merge-3.test134
-rw-r--r--test/old-elf/Mips/e-flags-merge-4-64.test64
-rw-r--r--test/old-elf/Mips/e-flags-merge-4.test65
-rw-r--r--test/old-elf/Mips/e-flags-merge-5-64.test42
-rw-r--r--test/old-elf/Mips/e-flags-merge-5.test42
-rw-r--r--test/old-elf/Mips/e-flags-merge-6-64.test79
-rw-r--r--test/old-elf/Mips/e-flags-merge-6.test80
-rw-r--r--test/old-elf/Mips/e-flags-merge-7-64.test42
-rw-r--r--test/old-elf/Mips/e-flags-merge-7.test42
-rw-r--r--test/old-elf/Mips/e-flags-merge-8.test65
-rw-r--r--test/old-elf/Mips/e-flags-merge-9.test43
-rw-r--r--test/old-elf/Mips/entry-name.test26
-rw-r--r--test/old-elf/Mips/exe-dynamic.test110
-rw-r--r--test/old-elf/Mips/exe-dynsym-micro.test94
-rw-r--r--test/old-elf/Mips/exe-dynsym.test91
-rw-r--r--test/old-elf/Mips/exe-fileheader-02.test62
-rw-r--r--test/old-elf/Mips/exe-fileheader-03.test72
-rw-r--r--test/old-elf/Mips/exe-fileheader-64.test66
-rw-r--r--test/old-elf/Mips/exe-fileheader-be-64.test60
-rw-r--r--test/old-elf/Mips/exe-fileheader-be.test60
-rw-r--r--test/old-elf/Mips/exe-fileheader-micro-64.test68
-rw-r--r--test/old-elf/Mips/exe-fileheader-micro.test69
-rw-r--r--test/old-elf/Mips/exe-fileheader-n32.test65
-rw-r--r--test/old-elf/Mips/exe-fileheader.test105
-rw-r--r--test/old-elf/Mips/exe-got-micro.test115
-rw-r--r--test/old-elf/Mips/exe-got.test116
-rw-r--r--test/old-elf/Mips/got-page-32-micro.test251
-rw-r--r--test/old-elf/Mips/got-page-32.test244
-rw-r--r--test/old-elf/Mips/got-page-64-micro.test210
-rw-r--r--test/old-elf/Mips/got-page-64.test203
-rw-r--r--test/old-elf/Mips/got16-2.test73
-rw-r--r--test/old-elf/Mips/got16-micro.test165
-rw-r--r--test/old-elf/Mips/got16.test196
-rw-r--r--test/old-elf/Mips/gotsym.test43
-rw-r--r--test/old-elf/Mips/gp-sym-1-micro.test88
-rw-r--r--test/old-elf/Mips/gp-sym-1.test86
-rw-r--r--test/old-elf/Mips/gp-sym-2.test103
-rw-r--r--test/old-elf/Mips/hilo16-1.test40
-rw-r--r--test/old-elf/Mips/hilo16-2.test70
-rw-r--r--test/old-elf/Mips/hilo16-3-overflow.test44
-rw-r--r--test/old-elf/Mips/hilo16-3.test74
-rw-r--r--test/old-elf/Mips/hilo16-4.test93
-rw-r--r--test/old-elf/Mips/hilo16-5.test103
-rw-r--r--test/old-elf/Mips/hilo16-8-micro.test81
-rw-r--r--test/old-elf/Mips/hilo16-9-micro.test142
-rw-r--r--test/old-elf/Mips/initfini-micro.test45
-rw-r--r--test/old-elf/Mips/interpreter-64.test26
-rw-r--r--test/old-elf/Mips/interpreter-n32.test27
-rw-r--r--test/old-elf/Mips/interpreter.test26
-rw-r--r--test/old-elf/Mips/invalid-reginfo.test28
-rw-r--r--test/old-elf/Mips/jalx-align-err.test46
-rw-r--r--test/old-elf/Mips/jalx-jalr.test47
-rw-r--r--test/old-elf/Mips/jalx.test71
-rw-r--r--test/old-elf/Mips/jump-fix-err.test45
-rw-r--r--test/old-elf/Mips/la25-stub-be.test113
-rw-r--r--test/old-elf/Mips/la25-stub-micro-be.test121
-rw-r--r--test/old-elf/Mips/la25-stub-micro.test136
-rw-r--r--test/old-elf/Mips/la25-stub-npic-01.test153
-rw-r--r--test/old-elf/Mips/la25-stub-npic-02.test123
-rw-r--r--test/old-elf/Mips/la25-stub-npic-shared.test152
-rw-r--r--test/old-elf/Mips/la25-stub-pic.test144
-rw-r--r--test/old-elf/Mips/la25-stub.test133
-rw-r--r--test/old-elf/Mips/mips-options-01.test34
-rw-r--r--test/old-elf/Mips/mips-options-02.test104
-rw-r--r--test/old-elf/Mips/mips-options-03.test41
-rw-r--r--test/old-elf/Mips/mips-options-04.test77
-rw-r--r--test/old-elf/Mips/mips-options-05.test119
-rw-r--r--test/old-elf/Mips/mips-options-gp0.test77
-rw-r--r--test/old-elf/Mips/n32-rela-chain.test68
-rw-r--r--test/old-elf/Mips/n64-rel-chain.test204
-rw-r--r--test/old-elf/Mips/n64-rel-shift.test48
-rw-r--r--test/old-elf/Mips/opt-emulation.test43
-rw-r--r--test/old-elf/Mips/pc23-range.test54
-rw-r--r--test/old-elf/Mips/plt-entry-mixed-1.test114
-rw-r--r--test/old-elf/Mips/plt-entry-mixed-2.test93
-rw-r--r--test/old-elf/Mips/plt-entry-mixed-3.test98
-rw-r--r--test/old-elf/Mips/plt-entry-mixed-4.test85
-rw-r--r--test/old-elf/Mips/plt-entry-r6-be.test109
-rw-r--r--test/old-elf/Mips/plt-entry-r6.test109
-rw-r--r--test/old-elf/Mips/plt-header-be.test104
-rw-r--r--test/old-elf/Mips/plt-header-micro-be.test105
-rw-r--r--test/old-elf/Mips/plt-header-micro.test108
-rw-r--r--test/old-elf/Mips/plt-header-mixed.test105
-rw-r--r--test/old-elf/Mips/plt-header.test99
-rw-r--r--test/old-elf/Mips/r26-1-micro.test131
-rw-r--r--test/old-elf/Mips/r26-1.test132
-rw-r--r--test/old-elf/Mips/r26-2-micro.test31
-rw-r--r--test/old-elf/Mips/r26-2.test31
-rw-r--r--test/old-elf/Mips/reginfo-01.test30
-rw-r--r--test/old-elf/Mips/reginfo-02.test107
-rw-r--r--test/old-elf/Mips/reginfo-03.test45
-rw-r--r--test/old-elf/Mips/reginfo-04.test81
-rw-r--r--test/old-elf/Mips/reginfo-05.test123
-rw-r--r--test/old-elf/Mips/rel-16-overflow.test45
-rw-r--r--test/old-elf/Mips/rel-16.test51
-rw-r--r--test/old-elf/Mips/rel-32-be.test60
-rw-r--r--test/old-elf/Mips/rel-32.test59
-rw-r--r--test/old-elf/Mips/rel-64.test61
-rw-r--r--test/old-elf/Mips/rel-call-hilo-01.test109
-rw-r--r--test/old-elf/Mips/rel-call-hilo-micro.test154
-rw-r--r--test/old-elf/Mips/rel-copy-micro.test159
-rw-r--r--test/old-elf/Mips/rel-copy-pc.test113
-rw-r--r--test/old-elf/Mips/rel-copy.test177
-rw-r--r--test/old-elf/Mips/rel-dynamic-01-micro.test201
-rw-r--r--test/old-elf/Mips/rel-dynamic-01.test261
-rw-r--r--test/old-elf/Mips/rel-dynamic-02.test101
-rw-r--r--test/old-elf/Mips/rel-dynamic-03-micro.test133
-rw-r--r--test/old-elf/Mips/rel-dynamic-03.test129
-rw-r--r--test/old-elf/Mips/rel-dynamic-04-micro.test226
-rw-r--r--test/old-elf/Mips/rel-dynamic-04.test221
-rw-r--r--test/old-elf/Mips/rel-dynamic-05-micro.test192
-rw-r--r--test/old-elf/Mips/rel-dynamic-05.test188
-rw-r--r--test/old-elf/Mips/rel-dynamic-06-64.test114
-rw-r--r--test/old-elf/Mips/rel-dynamic-06.test115
-rw-r--r--test/old-elf/Mips/rel-dynamic-07-64.test348
-rw-r--r--test/old-elf/Mips/rel-dynamic-07.test363
-rw-r--r--test/old-elf/Mips/rel-dynamic-08-64.test275
-rw-r--r--test/old-elf/Mips/rel-dynamic-08-micro.test278
-rw-r--r--test/old-elf/Mips/rel-dynamic-08.test275
-rw-r--r--test/old-elf/Mips/rel-dynamic-09-micro.test109
-rw-r--r--test/old-elf/Mips/rel-dynamic-09.test107
-rw-r--r--test/old-elf/Mips/rel-dynamic-10-micro.test166
-rw-r--r--test/old-elf/Mips/rel-dynamic-10.test160
-rw-r--r--test/old-elf/Mips/rel-dynamic-11.test110
-rw-r--r--test/old-elf/Mips/rel-dynamic-12.test237
-rw-r--r--test/old-elf/Mips/rel-dynamic-13.test94
-rw-r--r--test/old-elf/Mips/rel-dynamic-14.test94
-rw-r--r--test/old-elf/Mips/rel-dynamic-15.test81
-rw-r--r--test/old-elf/Mips/rel-eh-01.test186
-rw-r--r--test/old-elf/Mips/rel-eh-02.test130
-rw-r--r--test/old-elf/Mips/rel-eh-03.test128
-rw-r--r--test/old-elf/Mips/rel-got-hilo-01.test109
-rw-r--r--test/old-elf/Mips/rel-got-hilo-micro.test154
-rw-r--r--test/old-elf/Mips/rel-gprel16-micro-overflow.test57
-rw-r--r--test/old-elf/Mips/rel-gprel16-micro.test78
-rw-r--r--test/old-elf/Mips/rel-gprel16-overflow.test48
-rw-r--r--test/old-elf/Mips/rel-gprel16.test104
-rw-r--r--test/old-elf/Mips/rel-gprel32-64.test84
-rw-r--r--test/old-elf/Mips/rel-gprel32.test84
-rw-r--r--test/old-elf/Mips/rel-gprel7-micro-overflow.test48
-rw-r--r--test/old-elf/Mips/rel-gprel7-micro.test65
-rw-r--r--test/old-elf/Mips/rel-hi0-lo16-micro.test58
-rw-r--r--test/old-elf/Mips/rel-high-01.test25
-rw-r--r--test/old-elf/Mips/rel-high-02.test25
-rw-r--r--test/old-elf/Mips/rel-jalr-01.test101
-rw-r--r--test/old-elf/Mips/rel-jalr-02.test68
-rw-r--r--test/old-elf/Mips/rel-lit-micro.test59
-rw-r--r--test/old-elf/Mips/rel-lit.test57
-rw-r--r--test/old-elf/Mips/rel-pc-hilo.test70
-rw-r--r--test/old-elf/Mips/rel-pc16-align.test43
-rw-r--r--test/old-elf/Mips/rel-pc16-overflow.test45
-rw-r--r--test/old-elf/Mips/rel-pc16.test53
-rw-r--r--test/old-elf/Mips/rel-pc18-s3-align.test44
-rw-r--r--test/old-elf/Mips/rel-pc18-s3-micro.test56
-rw-r--r--test/old-elf/Mips/rel-pc18-s3.test54
-rw-r--r--test/old-elf/Mips/rel-pc19-s2-align.test44
-rw-r--r--test/old-elf/Mips/rel-pc19-s2-micro.test56
-rw-r--r--test/old-elf/Mips/rel-pc19-s2.test54
-rw-r--r--test/old-elf/Mips/rel-pc21-s2-align.test44
-rw-r--r--test/old-elf/Mips/rel-pc21-s2-micro.test56
-rw-r--r--test/old-elf/Mips/rel-pc21-s2-overflow.test45
-rw-r--r--test/old-elf/Mips/rel-pc21-s2.test54
-rw-r--r--test/old-elf/Mips/rel-pc26-s2-align.test44
-rw-r--r--test/old-elf/Mips/rel-pc26-s2-micro.test56
-rw-r--r--test/old-elf/Mips/rel-pc26-s2.test54
-rw-r--r--test/old-elf/Mips/rel-pc32.test59
-rw-r--r--test/old-elf/Mips/rel-pc7-10-16-23.test86
-rw-r--r--test/old-elf/Mips/rel-sub-micro.test62
-rw-r--r--test/old-elf/Mips/rel-sub.test61
-rw-r--r--test/old-elf/Mips/rld_map.test42
-rw-r--r--test/old-elf/Mips/sign-rela.test54
-rw-r--r--test/old-elf/Mips/st-other.test90
-rw-r--r--test/old-elf/Mips/static-01.test119
-rw-r--r--test/old-elf/Mips/tls-1-micro.test65
-rw-r--r--test/old-elf/Mips/tls-1.test63
-rw-r--r--test/old-elf/Mips/tls-2-64-static.test71
-rw-r--r--test/old-elf/Mips/tls-2-64.test69
-rw-r--r--test/old-elf/Mips/tls-2-micro.test70
-rw-r--r--test/old-elf/Mips/tls-2-static.test125
-rw-r--r--test/old-elf/Mips/tls-2.test69
-rw-r--r--test/old-elf/Mips/tls-3-64-static.test70
-rw-r--r--test/old-elf/Mips/tls-3-micro.test183
-rw-r--r--test/old-elf/Mips/tls-3-static.test67
-rw-r--r--test/old-elf/Mips/tls-3.test180
-rw-r--r--test/old-elf/Mips/tls-4-64-static.test71
-rw-r--r--test/old-elf/Mips/tls-4-micro.test126
-rw-r--r--test/old-elf/Mips/tls-4-static.test68
-rw-r--r--test/old-elf/Mips/tls-4.test123
-rw-r--r--test/old-elf/Mips/tls-5-64.test71
-rw-r--r--test/old-elf/Mips/tls-5-micro.test70
-rw-r--r--test/old-elf/Mips/tls-5.test69
-rw-r--r--test/old-elf/Mips/validate-rel-01.test82
-rw-r--r--test/old-elf/Mips/validate-rel-03.test56
-rw-r--r--test/old-elf/X86_64/ExampleTarget/triple.test32
-rw-r--r--test/old-elf/X86_64/Inputs/constint.c1
-rw-r--r--test/old-elf/X86_64/Inputs/constint.obin1062 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/debug0.c5
-rw-r--r--test/old-elf/X86_64/Inputs/debug0.x86-64bin2704 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/debug1.c3
-rw-r--r--test/old-elf/X86_64/Inputs/debug1.x86-64bin2584 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/externtls.c6
-rw-r--r--test/old-elf/X86_64/Inputs/externtls.x86-64bin1424 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/fn.c4
-rw-r--r--test/old-elf/X86_64/Inputs/fn.obin1072 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/generaltls-so.o.yaml67
-rw-r--r--test/old-elf/X86_64/Inputs/group/1.c8
-rw-r--r--test/old-elf/X86_64/Inputs/group/1.obin1456 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn.c4
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn.obin1360 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn1.c3
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn1.obin1352 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn2.c3
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn2.obin1224 -> 0 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/group.sh38
-rw-r--r--test/old-elf/X86_64/Inputs/group/libfn.abin2792 -> 0 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/libfn.sobin2516 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/libfn1.abin1492 -> 0 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/libfn2.sobin9624 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/initfini-option.c13
-rw-r--r--test/old-elf/X86_64/Inputs/initfini-option.obin1824 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/initfini.c14
-rw-r--r--test/old-elf/X86_64/Inputs/initfini.obin2256 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/largebss.c3
-rw-r--r--test/old-elf/X86_64/Inputs/largebss.obin1131 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/1.c8
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/1.obin1448 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/2.c7
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/2.obin1320 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/3.c3
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/3.obin1216 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/lib2.abin1464 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/libfn.abin1364 -> 0 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/libfn.sobin2008 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/main.c4
-rw-r--r--test/old-elf/X86_64/Inputs/main.obin1360 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multi-ovrd.c10
-rw-r--r--test/old-elf/X86_64/Inputs/multi-ovrd.obin1648 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multi-weak.c20
-rw-r--r--test/old-elf/X86_64/Inputs/multi-weak.obin1856 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multiweaksyms.obin928 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/nmagic.c8
-rw-r--r--test/old-elf/X86_64/Inputs/nmagic.obin1528 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/no-interp-section.c1
-rw-r--r--test/old-elf/X86_64/Inputs/no-interp-section.obin975 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note.obin785 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note.s11
-rw-r--r--test/old-elf/X86_64/Inputs/note_ro_rw.obin905 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note_ro_rw.s21
-rw-r--r--test/old-elf/X86_64/Inputs/ovrd.c6
-rw-r--r--test/old-elf/X86_64/Inputs/ovrd.obin1488 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.c3
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.obin1584 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.s24
-rw-r--r--test/old-elf/X86_64/Inputs/rwint.c1
-rw-r--r--test/old-elf/X86_64/Inputs/rwint.obin963 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/sectionmap.c4
-rw-r--r--test/old-elf/X86_64/Inputs/sectionmap.obin1478 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/undefcpp.c1
-rw-r--r--test/old-elf/X86_64/Inputs/undefcpp.obin1344 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak-zero-sized.obin688 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak.c14
-rw-r--r--test/old-elf/X86_64/Inputs/weak.obin1712 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak.s21
-rw-r--r--test/old-elf/X86_64/Inputs/zerosizedsection.obin760 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/zerosizedsection.s3
-rw-r--r--test/old-elf/X86_64/alignoffset.test118
-rw-r--r--test/old-elf/X86_64/debug.test57
-rw-r--r--test/old-elf/X86_64/defsym.test22
-rw-r--r--test/old-elf/X86_64/demangle.test12
-rw-r--r--test/old-elf/X86_64/dontignorezerosize-sections.test9
-rw-r--r--test/old-elf/X86_64/dynamicvars.test123
-rw-r--r--test/old-elf/X86_64/dynlib-nointerp-section.test4
-rw-r--r--test/old-elf/X86_64/dynlib-search.test6
-rw-r--r--test/old-elf/X86_64/dynsym-weak.test118
-rw-r--r--test/old-elf/X86_64/extern-tls.test16
-rw-r--r--test/old-elf/X86_64/general-dynamic-tls.test128
-rw-r--r--test/old-elf/X86_64/imagebase.test94
-rw-r--r--test/old-elf/X86_64/initfini-order.test10
-rw-r--r--test/old-elf/X86_64/initfini.test23
-rw-r--r--test/old-elf/X86_64/largebss.test20
-rw-r--r--test/old-elf/X86_64/layoutpass-order.test14
-rw-r--r--test/old-elf/X86_64/maxpagesize.test113
-rw-r--r--test/old-elf/X86_64/mergesimilarstrings.test47
-rw-r--r--test/old-elf/X86_64/multi-weak-layout.test52
-rw-r--r--test/old-elf/X86_64/multi-weak-override.test16
-rw-r--r--test/old-elf/X86_64/multi-weak-syms-order.test13
-rw-r--r--test/old-elf/X86_64/nmagic.test91
-rw-r--r--test/old-elf/X86_64/noalignsegments.test95
-rw-r--r--test/old-elf/X86_64/note-sections-ro_plus_rw.test42
-rw-r--r--test/old-elf/X86_64/note-sections.test23
-rw-r--r--test/old-elf/X86_64/omagic.test237
-rw-r--r--test/old-elf/X86_64/outputsegments.test188
-rw-r--r--test/old-elf/X86_64/reloc_r_x86_64_16.test59
-rw-r--r--test/old-elf/X86_64/reloc_r_x86_64_pc16.test60
-rw-r--r--test/old-elf/X86_64/reloc_r_x86_64_pc64.test60
-rw-r--r--test/old-elf/X86_64/rodata.test9
-rw-r--r--test/old-elf/X86_64/sectionchoice.test7
-rw-r--r--test/old-elf/X86_64/sectionmap.test22
-rw-r--r--test/old-elf/X86_64/startGroupEndGroup.test48
-rw-r--r--test/old-elf/X86_64/startGroupEndGroupWithDynlib.test10
-rw-r--r--test/old-elf/X86_64/staticlib-search.test6
-rw-r--r--test/old-elf/X86_64/undef.test18
-rw-r--r--test/old-elf/X86_64/underscore-end.test81
-rw-r--r--test/old-elf/X86_64/weak-override.test45
-rw-r--r--test/old-elf/X86_64/weak-zero-sized.test26
-rw-r--r--test/old-elf/X86_64/weaksym.test77
-rw-r--r--test/old-elf/X86_64/yamlinput.test166
-rw-r--r--test/old-elf/abs-dup.objtxt19
-rw-r--r--test/old-elf/abs.test19
-rw-r--r--test/old-elf/allowduplicates.objtxt41
-rw-r--r--test/old-elf/archive-elf-forceload.test43
-rw-r--r--test/old-elf/archive-elf.test38
-rw-r--r--test/old-elf/as-needed.test15
-rw-r--r--test/old-elf/branch.test34
-rw-r--r--test/old-elf/check.test39
-rw-r--r--test/old-elf/checkrodata.test9
-rw-r--r--test/old-elf/common.test10
-rw-r--r--test/old-elf/consecutive-weak-sym-defs.test81
-rw-r--r--test/old-elf/defsym.objtxt31
-rw-r--r--test/old-elf/discard-all.test88
-rw-r--r--test/old-elf/discard-locals.test65
-rw-r--r--test/old-elf/dynamic-segorder.test17
-rw-r--r--test/old-elf/dynamic-undef.test38
-rw-r--r--test/old-elf/dynamic.test80
-rw-r--r--test/old-elf/eh_frame_hdr.test30
-rw-r--r--test/old-elf/entry.objtxt58
-rw-r--r--test/old-elf/export-dynamic.test98
-rw-r--r--test/old-elf/filenotfound.test3
-rw-r--r--test/old-elf/gnulinkonce/gnulinkonce-report-discarded-reference.test145
-rw-r--r--test/old-elf/gnulinkonce/gnulinkonce-report-undef.test127
-rw-r--r--test/old-elf/gnulinkonce/gnulinkonce.test149
-rw-r--r--test/old-elf/gotpcrel.test21
-rw-r--r--test/old-elf/gottpoff.test119
-rw-r--r--test/old-elf/group-cmd-search.test134
-rw-r--r--test/old-elf/hexagon-quickdata-sort.test12
-rw-r--r--test/old-elf/hexagon-quickdata-sortcommon.test16
-rw-r--r--test/old-elf/ifunc.test69
-rw-r--r--test/old-elf/ignore-unknownoption.test5
-rw-r--r--test/old-elf/init_array-order.test67
-rw-r--r--test/old-elf/init_array.test127
-rw-r--r--test/old-elf/initfini-options.test-1.test33
-rw-r--r--test/old-elf/initfini-options.test-2.test47
-rw-r--r--test/old-elf/initfini-options.test-3.test53
-rw-r--r--test/old-elf/librarynotfound.test5
-rw-r--r--test/old-elf/linker-as-ld.test16
-rw-r--r--test/old-elf/linkerscript/Inputs/externs.ls3
-rw-r--r--test/old-elf/linkerscript/Inputs/invalid.ls1
-rw-r--r--test/old-elf/linkerscript/Inputs/prog1.o.yaml87
-rw-r--r--test/old-elf/linkerscript/Inputs/prog2.o.yaml88
-rw-r--r--test/old-elf/linkerscript/Inputs/prog3.o.yaml51
-rw-r--r--test/old-elf/linkerscript/Inputs/simple-pic.o.yaml32
-rw-r--r--test/old-elf/linkerscript/Inputs/simple.o.yaml51
-rw-r--r--test/old-elf/linkerscript/Inputs/valid.ls6
-rw-r--r--test/old-elf/linkerscript/externs.objtxt21
-rw-r--r--test/old-elf/linkerscript/filename-with-wildcards.test49
-rw-r--r--test/old-elf/linkerscript/invalid-script-cli-1.test10
-rw-r--r--test/old-elf/linkerscript/invalid-script-cli-2.test6
-rw-r--r--test/old-elf/linkerscript/invalid.test5
-rw-r--r--test/old-elf/linkerscript/phdrs-all-none.test26
-rw-r--r--test/old-elf/linkerscript/phdrs-custom-none.test36
-rw-r--r--test/old-elf/linkerscript/phdrs-default.test82
-rw-r--r--test/old-elf/linkerscript/phdrs-different.test45
-rw-r--r--test/old-elf/linkerscript/phdrs-extra-program.test27
-rw-r--r--test/old-elf/linkerscript/phdrs-flags.test46
-rw-r--r--test/old-elf/linkerscript/phdrs-has-program.test33
-rw-r--r--test/old-elf/linkerscript/phdrs-invalid.test63
-rw-r--r--test/old-elf/linkerscript/phdrs-misplaced-program.test26
-rw-r--r--test/old-elf/linkerscript/phdrs-no-program.test25
-rw-r--r--test/old-elf/linkerscript/phdrs-one-none.test36
-rw-r--r--test/old-elf/linkerscript/phdrs-program-flags.test33
-rw-r--r--test/old-elf/linkerscript/phdrs-program-good-phdrs.test34
-rw-r--r--test/old-elf/linkerscript/phdrs-program-no-phdrs.test26
-rw-r--r--test/old-elf/linkerscript/phdrs-program-wrong-phdrs.test26
-rw-r--r--test/old-elf/linkerscript/phdrs-same-flags.test35
-rw-r--r--test/old-elf/linkerscript/phdrs-same.test36
-rw-r--r--test/old-elf/linkerscript/phdrs/sections-empty-phdrs.script11
-rw-r--r--test/old-elf/linkerscript/phdrs/sections-no-phdrs.script7
-rw-r--r--test/old-elf/linkerscript/phdrs/sections-none-phdrs.script11
-rw-r--r--test/old-elf/linkerscript/phdrs/undef-empty-phdrs.script11
-rw-r--r--test/old-elf/linkerscript/phdrs/undef-id-phdrs.script12
-rw-r--r--test/old-elf/linkerscript/phdrs/undef-no-phdrs.script7
-rw-r--r--test/old-elf/linkerscript/sections-order.test113
-rw-r--r--test/old-elf/linkerscript/sections-with-wildcards.test88
-rw-r--r--test/old-elf/linkerscript/symbol-definition-so.test32
-rw-r--r--test/old-elf/linkerscript/symbol-definition.test54
-rw-r--r--test/old-elf/linkerscript/valid-script-cli.objtxt23
-rw-r--r--test/old-elf/loginputfiles.test28
-rw-r--r--test/old-elf/mergeatoms.test6
-rw-r--r--test/old-elf/mergeconstants.test20
-rw-r--r--test/old-elf/mergeglobalatoms.test11
-rw-r--r--test/old-elf/no-unique-section-names.test19
-rw-r--r--test/old-elf/note.test50
-rw-r--r--test/old-elf/options/dynamic-linker.test17
-rw-r--r--test/old-elf/options/target-specific-args.test5
-rw-r--r--test/old-elf/phdr.test99
-rw-r--r--test/old-elf/quickdata.test15
-rw-r--r--test/old-elf/reloc.test38
-rw-r--r--test/old-elf/responsefile.test6
-rw-r--r--test/old-elf/rodata.test5
-rw-r--r--test/old-elf/rosegment.test26
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-new-members.test151
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-simple.test144
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-undef-member-other.test156
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-undef-member.test142
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-with-globalsymbols.test250
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-with-undef-external-reference.test236
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-with-undef-signature.test219
-rw-r--r--test/old-elf/sections.test142
-rw-r--r--test/old-elf/sh_addralign.test37
-rw-r--r--test/old-elf/shndx.test18
-rw-r--r--test/old-elf/soname.test6
-rw-r--r--test/old-elf/start-stop-sym.test108
-rw-r--r--test/old-elf/strip-all.test108
-rw-r--r--test/old-elf/stripped-empty.test4
-rw-r--r--test/old-elf/symbols.test33
-rw-r--r--test/old-elf/tls-tbss-size.test176
-rw-r--r--test/old-elf/tls.test43
-rw-r--r--test/old-elf/tlsAddr.test7
-rw-r--r--test/old-elf/undef-from-dso-to-main.test52
-rw-r--r--test/old-elf/undef-from-main-dso.test43
-rw-r--r--test/old-elf/weaksym.test7
-rw-r--r--test/old-elf/wrap.test276
-rw-r--r--test/old-elf/x86-64-dynamic-relocs.test26
-rw-r--r--test/old-elf/x86-64-dynamic.test79
-rw-r--r--test/old-elf/x86.test38
-rw-r--r--test/old-elf/x86_64-kinds.test23
-rw-r--r--test/old-elf/zoption_dtflags.test89
-rw-r--r--tools/CMakeLists.txt2
-rw-r--r--tools/linker-script-test/CMakeLists.txt8
-rw-r--r--tools/linker-script-test/linker-script-test.cpp57
-rw-r--r--tools/lld/CMakeLists.txt1
-rw-r--r--tools/lld/TODO.txt2
-rw-r--r--tools/lld/lld.cpp108
-rw-r--r--unittests/CoreTests/CMakeLists.txt5
-rw-r--r--unittests/CoreTests/RangeTest.cpp240
-rw-r--r--unittests/DriverTests/CMakeLists.txt4
-rw-r--r--unittests/DriverTests/DarwinLdDriverTest.cpp153
-rw-r--r--unittests/DriverTests/DriverTest.h61
-rw-r--r--unittests/DriverTests/GnuLdDriverTest.cpp299
-rw-r--r--unittests/DriverTests/UniversalDriverTest.cpp33
-rw-r--r--unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp25
-rw-r--r--unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp18
-rw-r--r--unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp18
-rw-r--r--unittests/MachOTests/MachONormalizedFileYAMLTests.cpp23
1685 files changed, 30937 insertions, 78902 deletions
diff --git a/.arcconfig b/.arcconfig
index 787b339a9f20..ebf4a4a6f8b7 100644
--- a/.arcconfig
+++ b/.arcconfig
@@ -1,4 +1,4 @@
{
"project_id" : "lld",
- "conduit_uri" : "http://reviews.llvm.org/"
+ "conduit_uri" : "https://reviews.llvm.org/"
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7458de08fc16..46ca748f8fac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -94,7 +94,7 @@ endmacro(add_lld_library)
add_subdirectory(lib)
-add_subdirectory(tools)
+add_subdirectory(tools/lld)
if (LLVM_INCLUDE_TESTS)
add_subdirectory(test)
diff --git a/COFF/CMakeLists.txt b/COFF/CMakeLists.txt
index 3f31ba9ba1fb..3319f392efe1 100644
--- a/COFF/CMakeLists.txt
+++ b/COFF/CMakeLists.txt
@@ -10,6 +10,7 @@ add_lld_library(lldCOFF
Error.cpp
ICF.cpp
InputFiles.cpp
+ Librarian.cpp
MarkLive.cpp
ModuleDef.cpp
PDB.cpp
@@ -28,6 +29,8 @@ add_lld_library(lldCOFF
Target
Option
Support
+
+ LINK_LIBS ${PTHREAD_LIB}
)
add_dependencies(lldCOFF COFFOptionsTableGen)
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
index f9f768d69866..1c1b18176aa2 100644
--- a/COFF/Chunks.cpp
+++ b/COFF/Chunks.cpp
@@ -34,10 +34,7 @@ SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H)
// Initialize SectionName.
File->getCOFFObj()->getSectionName(Header, SectionName);
- // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1.
- unsigned Shift = (Header->Characteristics >> 20) & 0xF;
- if (Shift > 0)
- Align = uint32_t(1) << (Shift - 1);
+ Align = Header->getAlignment();
// Only COMDAT sections are subject of dead-stripping.
Live = !isCOMDAT();
@@ -64,7 +61,7 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_AMD64_SECTION: add16(Off, Sym->getSectionIndex()); break;
case IMAGE_REL_AMD64_SECREL: add32(Off, Sym->getSecrel()); break;
default:
- error("Unsupported relocation type");
+ fatal("unsupported relocation type");
}
}
@@ -79,7 +76,7 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_I386_SECTION: add16(Off, Sym->getSectionIndex()); break;
case IMAGE_REL_I386_SECREL: add32(Off, Sym->getSecrel()); break;
default:
- error("Unsupported relocation type");
+ fatal("unsupported relocation type");
}
}
@@ -123,7 +120,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, S - P - 4); break;
case IMAGE_REL_ARM_BLX23T: applyBranch24T(Off, S - P - 4); break;
default:
- error("Unsupported relocation type");
+ fatal("unsupported relocation type");
}
}
@@ -310,7 +307,7 @@ void SEHTableChunk::writeTo(uint8_t *Buf) const {
BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
// Block header consists of 4 byte page RVA and 4 byte block size.
// Each entry is 2 byte. Last entry may be padding.
- Data.resize(align((End - Begin) * 2 + 8, 4));
+ Data.resize(alignTo((End - Begin) * 2 + 8, 4));
uint8_t *P = Data.data();
write32le(P, Page);
write32le(P + 4, Data.size());
diff --git a/COFF/Chunks.h b/COFF/Chunks.h
index 274135516eb9..cd0e2e69ef5d 100644
--- a/COFF/Chunks.h
+++ b/COFF/Chunks.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/COFF.h"
#include <atomic>
+#include <utility>
#include <vector>
namespace lld {
@@ -138,6 +139,7 @@ public:
SectionChunk(ObjectFile *File, const coff_section *Header);
static bool classof(const Chunk *C) { return C->kind() == SectionKind; }
size_t getSize() const override { return Header->SizeOfRawData; }
+ ArrayRef<uint8_t> getContents() const;
void writeTo(uint8_t *Buf) const override;
bool hasData() const override;
uint32_t getPermissions() const override;
@@ -186,8 +188,6 @@ public:
uint32_t Checksum = 0;
private:
- ArrayRef<uint8_t> getContents() const;
-
// A file this chunk was created from.
ObjectFile *File;
@@ -295,7 +295,7 @@ private:
// functions. x86-only.
class SEHTableChunk : public Chunk {
public:
- explicit SEHTableChunk(std::set<Defined *> S) : Syms(S) {}
+ explicit SEHTableChunk(std::set<Defined *> S) : Syms(std::move(S)) {}
size_t getSize() const override { return Syms.size() * 4; }
void writeTo(uint8_t *Buf) const override;
@@ -326,10 +326,6 @@ public:
uint8_t Type;
};
-inline uint64_t align(uint64_t Value, uint64_t Align) {
- return llvm::RoundUpToAlignment(Value, Align);
-}
-
} // namespace coff
} // namespace lld
diff --git a/COFF/Config.h b/COFF/Config.h
index 9cfccadba5fa..a5472e937fa1 100644
--- a/COFF/Config.h
+++ b/COFF/Config.h
@@ -106,11 +106,15 @@ struct Configuration {
// Used for /merge:from=to (e.g. /merge:.rdata=.text)
std::map<StringRef, StringRef> Merge;
+ // Used for /section=.name,{DEKPRSW} to set section attributes.
+ std::map<StringRef, uint32_t> Section;
+
// Options for manifest files.
ManifestKind Manifest = SideBySide;
int ManifestID = 1;
StringRef ManifestDependency;
bool ManifestUAC = true;
+ std::vector<std::string> ManifestInput;
StringRef ManifestLevel = "'asInvoker'";
StringRef ManifestUIAccess = "'false'";
StringRef ManifestFile;
diff --git a/COFF/DLL.cpp b/COFF/DLL.cpp
index 8f3383d75c7b..9ac370c11d59 100644
--- a/COFF/DLL.cpp
+++ b/COFF/DLL.cpp
@@ -45,7 +45,7 @@ public:
size_t getSize() const override {
// Starts with 2 byte Hint field, followed by a null-terminated string,
// ends with 0 or 1 byte padding.
- return align(Name.size() + 3, 2);
+ return alignTo(Name.size() + 3, 2);
}
void writeTo(uint8_t *Buf) const override {
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
index 4cacf0ff552a..bb6a60e4fc4c 100644
--- a/COFF/Driver.cpp
+++ b/COFF/Driver.cpp
@@ -14,6 +14,7 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "Writer.h"
+#include "lld/Driver/Driver.h"
#include "llvm/ADT/Optional.h"
#include "llvm/LibDriver/LibDriver.h"
#include "llvm/Option/Arg.h"
@@ -40,27 +41,28 @@ namespace coff {
Configuration *Config;
LinkerDriver *Driver;
-void link(llvm::ArrayRef<const char *> Args) {
+bool link(llvm::ArrayRef<const char *> Args) {
Configuration C;
LinkerDriver D;
Config = &C;
Driver = &D;
- return Driver->link(Args);
+ Driver->link(Args);
+ return true;
}
-// Drop directory components and replace extension with ".exe".
+// Drop directory components and replace extension with ".exe" or ".dll".
static std::string getOutputPath(StringRef Path) {
auto P = Path.find_last_of("\\/");
StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1);
- return (S.substr(0, S.rfind('.')) + ".exe").str();
+ const char* E = Config->DLL ? ".dll" : ".exe";
+ return (S.substr(0, S.rfind('.')) + E).str();
}
// Opens a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
- auto MBOrErr = MemoryBuffer::getFile(Path);
- error(MBOrErr, Twine("Could not open ") + Path);
- std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
+ std::unique_ptr<MemoryBuffer> MB =
+ check(MemoryBuffer::getFile(Path), "could not open " + Path);
MemoryBufferRef MBRef = MB->getMemBufferRef();
OwningMBs.push_back(std::move(MB)); // take ownership
return MBRef;
@@ -116,12 +118,16 @@ void LinkerDriver::parseDirectives(StringRef S) {
case OPT_nodefaultlib:
Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
break;
+ case OPT_section:
+ parseSection(Arg->getValue());
+ break;
case OPT_editandcontinue:
+ case OPT_fastfail:
case OPT_guardsym:
case OPT_throwingnew:
break;
default:
- error(Twine(Arg->getSpelling()) + " is not allowed in .drectve");
+ fatal(Arg->getSpelling() + " is not allowed in .drectve");
}
}
}
@@ -246,7 +252,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// We call our own implementation of lib.exe that understands bitcode files.
if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib")) {
if (llvm::libDriverMain(ArgsArr.slice(1)) != 0)
- error("lib failed");
+ fatal("lib failed");
return;
}
@@ -268,7 +274,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
}
if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end())
- error("no input files.");
+ fatal("no input files");
// Construct search path list.
SearchPaths.push_back("");
@@ -295,7 +301,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Handle /noentry
if (Args.hasArg(OPT_noentry)) {
if (!Args.hasArg(OPT_dll))
- error("/noentry must be specified with /dll");
+ fatal("/noentry must be specified with /dll");
Config->NoEntry = true;
}
@@ -308,7 +314,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Handle /fixed
if (Args.hasArg(OPT_fixed)) {
if (Args.hasArg(OPT_dynamicbase))
- error("/fixed must not be specified with /dynamicbase");
+ fatal("/fixed must not be specified with /dynamicbase");
Config->Relocatable = false;
Config->DynamicBase = false;
}
@@ -382,17 +388,17 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
StringRef OptLevel = StringRef(S).substr(7);
if (OptLevel.getAsInteger(10, Config->LTOOptLevel) ||
Config->LTOOptLevel > 3)
- error("/opt:lldlto: invalid optimization level: " + OptLevel);
+ fatal("/opt:lldlto: invalid optimization level: " + OptLevel);
continue;
}
if (StringRef(S).startswith("lldltojobs=")) {
StringRef Jobs = StringRef(S).substr(11);
if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0)
- error("/opt:lldltojobs: invalid job count: " + Jobs);
+ fatal("/opt:lldltojobs: invalid job count: " + Jobs);
continue;
}
if (S != "ref" && S != "lbr" && S != "nolbr")
- error(Twine("/opt: unknown option: ") + S);
+ fatal("/opt: unknown option: " + S);
}
}
@@ -404,6 +410,10 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
for (auto *Arg : Args.filtered(OPT_merge))
parseMerge(Arg->getValue());
+ // Handle /section
+ for (auto *Arg : Args.filtered(OPT_section))
+ parseSection(Arg->getValue());
+
// Handle /manifest
if (auto *Arg = Args.getLastArg(OPT_manifest_colon))
parseManifest(Arg->getValue());
@@ -420,6 +430,10 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (auto *Arg = Args.getLastArg(OPT_manifestfile))
Config->ManifestFile = Arg->getValue();
+ // Handle /manifestinput
+ for (auto *Arg : Args.filtered(OPT_manifestinput))
+ Config->ManifestInput.push_back(Arg->getValue());
+
// Handle miscellaneous boolean flags.
if (Args.hasArg(OPT_allowbind_no))
Config->AllowBind = false;
@@ -485,7 +499,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
continue;
}
if (Config->Machine != MT)
- error(Twine(File->getShortName()) + ": machine type " + machineToStr(MT) +
+ fatal(File->getShortName() + ": machine type " + machineToStr(MT) +
" conflicts with " + machineToStr(Config->Machine));
}
if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
@@ -520,7 +534,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// infer that from user-defined entry name.
StringRef S = findDefaultEntry();
if (S.empty())
- error("entry point must be defined");
+ fatal("entry point must be defined");
Config->Entry = addUndefined(S);
if (Config->Verbose)
llvm::outs() << "Entry name inferred: " << S << "\n";
@@ -627,14 +641,14 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
Config->Subsystem = inferSubsystem();
if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
- error("subsystem must be defined");
+ fatal("subsystem must be defined");
}
// Handle /safeseh.
if (Args.hasArg(OPT_safeseh))
for (ObjectFile *File : Symtab.ObjectFiles)
if (!File->SEHCompat)
- error("/safeseh: " + File->getName() + " is not compatible with SEH");
+ fatal("/safeseh: " + File->getName() + " is not compatible with SEH");
// Windows specific -- when we are creating a .dll file, we also
// need to create a .lib file.
@@ -668,7 +682,8 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (auto *Arg = Args.getLastArg(OPT_lldmap)) {
std::error_code EC;
llvm::raw_fd_ostream Out(Arg->getValue(), EC, OpenFlags::F_Text);
- error(EC, "Could not create the symbol map");
+ if (EC)
+ fatal(EC, "could not create the symbol map");
Symtab.printMap(Out);
}
// Call exit to avoid calling destructors.
diff --git a/COFF/Driver.h b/COFF/Driver.h
index e50da20cbb04..23969ee802fb 100644
--- a/COFF/Driver.h
+++ b/COFF/Driver.h
@@ -34,9 +34,6 @@ using llvm::COFF::WindowsSubsystem;
using llvm::Optional;
class InputFile;
-// Entry point of the COFF linker.
-void link(llvm::ArrayRef<const char *> Args);
-
// Implemented in MarkLive.cpp.
void markLive(const std::vector<Chunk *> &Chunks);
@@ -136,6 +133,7 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
void parseAlternateName(StringRef);
void parseMerge(StringRef);
+void parseSection(StringRef);
// Parses a string in the form of "EMBED[,=<integer>]|NO".
void parseManifest(StringRef Arg);
@@ -163,7 +161,6 @@ void checkFailIfMismatch(StringRef Arg);
std::unique_ptr<MemoryBuffer>
convertResToCOFF(const std::vector<MemoryBufferRef> &MBs);
-void touchFile(StringRef Path);
void createPDB(StringRef Path);
// Create enum with OPT_xxx values for each option in Options.td
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
index 014fee7fefd7..5d7dc2bc65af 100644
--- a/COFF/DriverUtils.cpp
+++ b/COFF/DriverUtils.cpp
@@ -19,15 +19,12 @@
#include "Symbols.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Object/Archive.h"
-#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/COFF.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@@ -53,7 +50,8 @@ public:
void run() {
ErrorOr<std::string> ExeOrErr = llvm::sys::findProgramByName(Prog);
- error(ExeOrErr, Twine("unable to find ") + Prog + " in PATH: ");
+ if (auto EC = ExeOrErr.getError())
+ fatal(EC, "unable to find " + Prog + " in PATH: ");
const char *Exe = Saver.save(*ExeOrErr);
Args.insert(Args.begin(), Exe);
Args.push_back(nullptr);
@@ -61,7 +59,7 @@ public:
for (const char *S : Args)
if (S)
llvm::errs() << S << " ";
- error("failed");
+ fatal("ExecuteAndWait failed");
}
}
@@ -85,7 +83,7 @@ MachineTypes getMachineType(StringRef S) {
.Default(IMAGE_FILE_MACHINE_UNKNOWN);
if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
return MT;
- error(Twine("unknown /machine argument: ") + S);
+ fatal("unknown /machine argument: " + S);
}
StringRef machineToStr(MachineTypes MT) {
@@ -106,9 +104,9 @@ void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) {
StringRef S1, S2;
std::tie(S1, S2) = Arg.split(',');
if (S1.getAsInteger(0, *Addr))
- error(Twine("invalid number: ") + S1);
+ fatal("invalid number: " + S1);
if (Size && !S2.empty() && S2.getAsInteger(0, *Size))
- error(Twine("invalid number: ") + S2);
+ fatal("invalid number: " + S2);
}
// Parses a string in the form of "<integer>[.<integer>]".
@@ -117,10 +115,10 @@ void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) {
StringRef S1, S2;
std::tie(S1, S2) = Arg.split('.');
if (S1.getAsInteger(0, *Major))
- error(Twine("invalid number: ") + S1);
+ fatal("invalid number: " + S1);
*Minor = 0;
if (!S2.empty() && S2.getAsInteger(0, *Minor))
- error(Twine("invalid number: ") + S2);
+ fatal("invalid number: " + S2);
}
// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
@@ -140,7 +138,7 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
.Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI)
.Default(IMAGE_SUBSYSTEM_UNKNOWN);
if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN)
- error(Twine("unknown subsystem: ") + SysStr);
+ fatal("unknown subsystem: " + SysStr);
if (!Ver.empty())
parseVersion(Ver, Major, Minor);
}
@@ -151,10 +149,10 @@ void parseAlternateName(StringRef S) {
StringRef From, To;
std::tie(From, To) = S.split('=');
if (From.empty() || To.empty())
- error(Twine("/alternatename: invalid argument: ") + S);
+ fatal("/alternatename: invalid argument: " + S);
auto It = Config->AlternateNames.find(From);
if (It != Config->AlternateNames.end() && It->second != To)
- error(Twine("/alternatename: conflicts: ") + S);
+ fatal("/alternatename: conflicts: " + S);
Config->AlternateNames.insert(It, std::make_pair(From, To));
}
@@ -164,7 +162,7 @@ void parseMerge(StringRef S) {
StringRef From, To;
std::tie(From, To) = S.split('=');
if (From.empty() || To.empty())
- error(Twine("/merge: invalid argument: ") + S);
+ fatal("/merge: invalid argument: " + S);
auto Pair = Config->Merge.insert(std::make_pair(From, To));
bool Inserted = Pair.second;
if (!Inserted) {
@@ -175,6 +173,47 @@ void parseMerge(StringRef S) {
}
}
+static uint32_t parseSectionAttributes(StringRef S) {
+ uint32_t Ret = 0;
+ for (char C : S.lower()) {
+ switch (C) {
+ case 'd':
+ Ret |= IMAGE_SCN_MEM_DISCARDABLE;
+ break;
+ case 'e':
+ Ret |= IMAGE_SCN_MEM_EXECUTE;
+ break;
+ case 'k':
+ Ret |= IMAGE_SCN_MEM_NOT_CACHED;
+ break;
+ case 'p':
+ Ret |= IMAGE_SCN_MEM_NOT_PAGED;
+ break;
+ case 'r':
+ Ret |= IMAGE_SCN_MEM_READ;
+ break;
+ case 's':
+ Ret |= IMAGE_SCN_MEM_SHARED;
+ break;
+ case 'w':
+ Ret |= IMAGE_SCN_MEM_WRITE;
+ break;
+ default:
+ fatal("/section: invalid argument: " + S);
+ }
+ }
+ return Ret;
+}
+
+// Parses /section option argument.
+void parseSection(StringRef S) {
+ StringRef Name, Attrs;
+ std::tie(Name, Attrs) = S.split(',');
+ if (Name.empty() || Attrs.empty())
+ fatal("/section: invalid argument: " + S);
+ Config->Section[Name] = parseSectionAttributes(Attrs);
+}
+
// Parses a string in the form of "EMBED[,=<integer>]|NO".
// Results are directly written to Config.
void parseManifest(StringRef Arg) {
@@ -183,16 +222,16 @@ void parseManifest(StringRef Arg) {
return;
}
if (!Arg.startswith_lower("embed"))
- error(Twine("Invalid option ") + Arg);
+ fatal("invalid option " + Arg);
Config->Manifest = Configuration::Embed;
Arg = Arg.substr(strlen("embed"));
if (Arg.empty())
return;
if (!Arg.startswith_lower(",id="))
- error(Twine("Invalid option ") + Arg);
+ fatal("invalid option " + Arg);
Arg = Arg.substr(strlen(",id="));
if (Arg.getAsInteger(0, Config->ManifestID))
- error(Twine("Invalid option ") + Arg);
+ fatal("invalid option " + Arg);
}
// Parses a string in the form of "level=<string>|uiAccess=<string>|NO".
@@ -216,7 +255,7 @@ void parseManifestUAC(StringRef Arg) {
std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" ");
continue;
}
- error(Twine("Invalid option ") + Arg);
+ fatal("invalid option " + Arg);
}
}
@@ -240,10 +279,19 @@ static void quoteAndPrint(raw_ostream &Out, StringRef S) {
}
}
-// Create a manifest file contents.
-static std::string createManifestXml() {
- std::string S;
- llvm::raw_string_ostream OS(S);
+// Create the default manifest file as a temporary file.
+static std::string createDefaultXml() {
+ // Create a temporary file.
+ SmallString<128> Path;
+ if (auto EC = sys::fs::createTemporaryFile("tmp", "manifest", Path))
+ fatal(EC, "cannot create a temporary file");
+
+ // Open the temporary file for writing.
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(Path, EC, sys::fs::F_Text);
+ if (EC)
+ fatal(EC, "failed to open " + Path);
+
// Emit the XML. Note that we do *not* verify that the XML attributes are
// syntactically correct. This is intentional for link.exe compatibility.
OS << "<?xml version=\"1.0\" standalone=\"yes\"?>\n"
@@ -267,21 +315,57 @@ static std::string createManifestXml() {
}
}
OS << "</assembly>\n";
- OS.flush();
- return S;
+ OS.close();
+ return StringRef(Path);
+}
+
+static std::string readFile(StringRef Path) {
+ std::unique_ptr<MemoryBuffer> MB =
+ check(MemoryBuffer::getFile(Path), "could not open " + Path);
+ std::unique_ptr<MemoryBuffer> Buf(std::move(MB));
+ return Buf->getBuffer();
+}
+
+static std::string createManifestXml() {
+ // Create the default manifest file.
+ std::string Path1 = createDefaultXml();
+ if (Config->ManifestInput.empty())
+ return readFile(Path1);
+
+ // If manifest files are supplied by the user using /MANIFESTINPUT
+ // option, we need to merge them with the default manifest.
+ SmallString<128> Path2;
+ if (auto EC = sys::fs::createTemporaryFile("tmp", "manifest", Path2))
+ fatal(EC, "cannot create a temporary file");
+ FileRemover Remover1(Path1);
+ FileRemover Remover2(Path2);
+
+ Executor E("mt.exe");
+ E.add("/manifest");
+ E.add(Path1);
+ for (StringRef Filename : Config->ManifestInput) {
+ E.add("/manifest");
+ E.add(Filename);
+ }
+ E.add("/nologo");
+ E.add("/out:" + StringRef(Path2));
+ E.run();
+ return readFile(Path2);
}
// Create a resource file containing a manifest XML.
std::unique_ptr<MemoryBuffer> createManifestRes() {
// Create a temporary file for the resource script file.
SmallString<128> RCPath;
- std::error_code EC = sys::fs::createTemporaryFile("tmp", "rc", RCPath);
- error(EC, "cannot create a temporary file");
+ if (auto EC = sys::fs::createTemporaryFile("tmp", "rc", RCPath))
+ fatal(EC, "cannot create a temporary file");
FileRemover RCRemover(RCPath);
// Open the temporary file for writing.
+ std::error_code EC;
llvm::raw_fd_ostream Out(RCPath, EC, sys::fs::F_Text);
- error(EC, Twine("failed to open ") + RCPath);
+ if (EC)
+ fatal(EC, "failed to open " + RCPath);
// Write resource script to the RC file.
Out << "#define LANG_ENGLISH 9\n"
@@ -296,8 +380,8 @@ std::unique_ptr<MemoryBuffer> createManifestRes() {
// Create output resource file.
SmallString<128> ResPath;
- EC = sys::fs::createTemporaryFile("tmp", "res", ResPath);
- error(EC, "cannot create a temporary file");
+ if (auto EC = sys::fs::createTemporaryFile("tmp", "res", ResPath))
+ fatal(EC, "cannot create a temporary file");
Executor E("rc.exe");
E.add("/fo");
@@ -305,18 +389,17 @@ std::unique_ptr<MemoryBuffer> createManifestRes() {
E.add("/nologo");
E.add(RCPath.str());
E.run();
- ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(ResPath);
- error(Ret, Twine("Could not open ") + ResPath);
- return std::move(*Ret);
+ return check(MemoryBuffer::getFile(ResPath), "could not open " + ResPath);
}
void createSideBySideManifest() {
std::string Path = Config->ManifestFile;
if (Path == "")
- Path = (Twine(Config->OutputFile) + ".manifest").str();
+ Path = Config->OutputFile + ".manifest";
std::error_code EC;
llvm::raw_fd_ostream Out(Path, EC, llvm::sys::fs::F_Text);
- error(EC, "failed to create manifest");
+ if (EC)
+ fatal(EC, "failed to create manifest");
Out << createManifestXml();
}
@@ -380,7 +463,7 @@ Export parseExport(StringRef Arg) {
return E;
err:
- error(Twine("invalid /export: ") + Arg);
+ fatal("invalid /export: " + Arg);
}
static StringRef undecorate(StringRef Sym) {
@@ -398,7 +481,7 @@ void fixupExports() {
if (E.Ordinal == 0)
continue;
if (!Ords.insert(E.Ordinal).second)
- error("duplicate export ordinal: " + E.Name);
+ fatal("duplicate export ordinal: " + E.Name);
}
for (Export &E : Config->Exports) {
@@ -459,11 +542,11 @@ void checkFailIfMismatch(StringRef Arg) {
StringRef K, V;
std::tie(K, V) = Arg.split('=');
if (K.empty() || V.empty())
- error(Twine("/failifmismatch: invalid argument: ") + Arg);
+ fatal("/failifmismatch: invalid argument: " + Arg);
StringRef Existing = Config->MustMatch[K];
if (!Existing.empty() && V != Existing)
- error(Twine("/failifmismatch: mismatch detected: ") + Existing + " and " +
- V + " for key " + K);
+ fatal("/failifmismatch: mismatch detected: " + Existing + " and " + V +
+ " for key " + K);
Config->MustMatch[K] = V;
}
@@ -473,8 +556,8 @@ std::unique_ptr<MemoryBuffer>
convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
// Create an output file path.
SmallString<128> Path;
- if (llvm::sys::fs::createTemporaryFile("resource", "obj", Path))
- error("Could not create temporary file");
+ if (auto EC = llvm::sys::fs::createTemporaryFile("resource", "obj", Path))
+ fatal(EC, "could not create temporary file");
// Execute cvtres.exe.
Executor E("cvtres.exe");
@@ -485,170 +568,7 @@ convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
for (MemoryBufferRef MB : MBs)
E.add(MB.getBufferIdentifier());
E.run();
- ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(Path);
- error(Ret, Twine("Could not open ") + Path);
- return std::move(*Ret);
-}
-
-static std::string writeToTempFile(StringRef Contents) {
- SmallString<128> Path;
- int FD;
- if (llvm::sys::fs::createTemporaryFile("tmp", "def", FD, Path)) {
- llvm::errs() << "failed to create a temporary file\n";
- return "";
- }
- llvm::raw_fd_ostream OS(FD, /*shouldClose*/ true);
- OS << Contents;
- return Path.str();
-}
-
-void touchFile(StringRef Path) {
- int FD;
- std::error_code EC = sys::fs::openFileForWrite(Path, FD, sys::fs::F_Append);
- error(EC, "failed to create a file");
- sys::Process::SafelyCloseFileDescriptor(FD);
-}
-
-static std::string getImplibPath() {
- if (!Config->Implib.empty())
- return Config->Implib;
- SmallString<128> Out = StringRef(Config->OutputFile);
- sys::path::replace_extension(Out, ".lib");
- return Out.str();
-}
-
-static std::unique_ptr<MemoryBuffer> createEmptyImportLibrary() {
- std::string S = (Twine("LIBRARY \"") +
- llvm::sys::path::filename(Config->OutputFile) + "\"\n")
- .str();
- std::string Path1 = writeToTempFile(S);
- std::string Path2 = getImplibPath();
- llvm::FileRemover Remover1(Path1);
- llvm::FileRemover Remover2(Path2);
-
- Executor E("lib.exe");
- E.add("/nologo");
- E.add("/machine:" + machineToStr(Config->Machine));
- E.add(Twine("/def:") + Path1);
- E.add(Twine("/out:") + Path2);
- E.run();
-
- ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
- MemoryBuffer::getFile(Path2, -1, false);
- error(BufOrErr, Twine("Failed to open ") + Path2);
- return MemoryBuffer::getMemBufferCopy((*BufOrErr)->getBuffer());
-}
-
-static std::vector<NewArchiveIterator>
-readMembers(const object::Archive &Archive) {
- std::vector<NewArchiveIterator> V;
- for (const auto &ChildOrErr : Archive.children()) {
- error(ChildOrErr, "Archive::Child::getName failed");
- const object::Archive::Child C(*ChildOrErr);
- ErrorOr<StringRef> NameOrErr = C.getName();
- error(NameOrErr, "Archive::Child::getName failed");
- V.emplace_back(C, *NameOrErr);
- }
- return V;
-}
-
-// This class creates short import files which is described in
-// PE/COFF spec 7. Import Library Format.
-class ShortImportCreator {
-public:
- ShortImportCreator(object::Archive *A, StringRef S) : Parent(A), DLLName(S) {}
-
- NewArchiveIterator create(StringRef Sym, uint16_t Ordinal,
- ImportNameType NameType, bool isData) {
- size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs
- size_t Size = sizeof(object::ArchiveMemberHeader) +
- sizeof(coff_import_header) + ImpSize;
- char *Buf = Alloc.Allocate<char>(Size);
- memset(Buf, 0, Size);
- char *P = Buf;
-
- // Write archive member header
- auto *Hdr = reinterpret_cast<object::ArchiveMemberHeader *>(P);
- P += sizeof(*Hdr);
- sprintf(Hdr->Name, "%-12s", "dummy");
- sprintf(Hdr->LastModified, "%-12d", 0);
- sprintf(Hdr->UID, "%-6d", 0);
- sprintf(Hdr->GID, "%-6d", 0);
- sprintf(Hdr->AccessMode, "%-8d", 0644);
- sprintf(Hdr->Size, "%-10d", int(sizeof(coff_import_header) + ImpSize));
-
- // Write short import library.
- auto *Imp = reinterpret_cast<coff_import_header *>(P);
- P += sizeof(*Imp);
- Imp->Sig2 = 0xFFFF;
- Imp->Machine = Config->Machine;
- Imp->SizeOfData = ImpSize;
- if (Ordinal > 0)
- Imp->OrdinalHint = Ordinal;
- Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE);
- Imp->TypeInfo |= NameType << 2;
-
- // Write symbol name and DLL name.
- memcpy(P, Sym.data(), Sym.size());
- P += Sym.size() + 1;
- memcpy(P, DLLName.data(), DLLName.size());
-
- std::error_code EC;
- object::Archive::Child C(Parent, Buf, &EC);
- assert(!EC && "We created an invalid buffer");
- return NewArchiveIterator(C, DLLName);
- }
-
-private:
- BumpPtrAllocator Alloc;
- object::Archive *Parent;
- StringRef DLLName;
-};
-
-static ImportNameType getNameType(StringRef Sym, StringRef ExtName) {
- if (Sym != ExtName)
- return IMPORT_NAME_UNDECORATE;
- if (Config->Machine == I386 && Sym.startswith("_"))
- return IMPORT_NAME_NOPREFIX;
- return IMPORT_NAME;
-}
-
-static std::string replace(StringRef S, StringRef From, StringRef To) {
- size_t Pos = S.find(From);
- assert(Pos != StringRef::npos);
- return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
-}
-
-// Creates an import library for a DLL. In this function, we first
-// create an empty import library using lib.exe and then adds short
-// import files to that file.
-void writeImportLibrary() {
- std::unique_ptr<MemoryBuffer> Buf = createEmptyImportLibrary();
- std::error_code EC;
- object::Archive Archive(Buf->getMemBufferRef(), EC);
- error(EC, "Error reading an empty import file");
- std::vector<NewArchiveIterator> Members = readMembers(Archive);
-
- std::string DLLName = llvm::sys::path::filename(Config->OutputFile);
- ShortImportCreator ShortImport(&Archive, DLLName);
- for (Export &E : Config->Exports) {
- if (E.Private)
- continue;
- if (E.ExtName.empty()) {
- Members.push_back(ShortImport.create(
- E.SymbolName, E.Ordinal, getNameType(E.SymbolName, E.Name), E.Data));
- } else {
- Members.push_back(ShortImport.create(
- replace(E.SymbolName, E.Name, E.ExtName), E.Ordinal,
- getNameType(E.SymbolName, E.Name), E.Data));
- }
- }
-
- std::string Path = getImplibPath();
- std::pair<StringRef, std::error_code> Result =
- writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU,
- /*Deterministic*/ true, /*Thin*/ false);
- error(Result.second, Twine("Failed to write ") + Path);
+ return check(MemoryBuffer::getFile(Path), "could not open " + Path);
}
// Create OptTable
@@ -695,7 +615,7 @@ llvm::opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
}
if (MissingCount)
- error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
+ fatal("missing arg value for \"" + Twine(Args.getArgString(MissingIndex)) +
"\", expected " + Twine(MissingCount) +
(MissingCount == 1 ? " argument." : " arguments."));
for (auto *Arg : Args.filtered(OPT_UNKNOWN))
diff --git a/COFF/Error.cpp b/COFF/Error.cpp
index 255d9bbad9d8..602a8544ce2b 100644
--- a/COFF/Error.cpp
+++ b/COFF/Error.cpp
@@ -10,20 +10,23 @@
#include "Error.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
namespace lld {
namespace coff {
-void error(const Twine &Msg) {
+void fatal(const Twine &Msg) {
llvm::errs() << Msg << "\n";
exit(1);
}
-void error(std::error_code EC, const Twine &Prefix) {
- if (!EC)
- return;
- error(Prefix + ": " + EC.message());
+void fatal(std::error_code EC, const Twine &Msg) {
+ fatal(Msg + ": " + EC.message());
+}
+
+void fatal(llvm::Error &Err, const Twine &Msg) {
+ fatal(errorToErrorCode(std::move(Err)), Msg);
}
} // namespace coff
diff --git a/COFF/Error.h b/COFF/Error.h
index cb0a185f0917..c9f64c662580 100644
--- a/COFF/Error.h
+++ b/COFF/Error.h
@@ -11,15 +11,25 @@
#define LLD_COFF_ERROR_H
#include "lld/Core/LLVM.h"
+#include "llvm/Support/Error.h"
namespace lld {
namespace coff {
-LLVM_ATTRIBUTE_NORETURN void error(const Twine &Msg);
-void error(std::error_code EC, const Twine &Prefix);
+LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);
+LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix);
-template <typename T> void error(const ErrorOr<T> &V, const Twine &Prefix) {
- error(V.getError(), Prefix);
+template <class T> T check(ErrorOr<T> &&V, const Twine &Prefix) {
+ if (auto EC = V.getError())
+ fatal(EC, Prefix);
+ return std::move(*V);
+}
+
+template <class T> T check(Expected<T> E, const Twine &Prefix) {
+ if (llvm::Error Err = E.takeError())
+ fatal(Err, Prefix);
+ return std::move(*E);
}
} // namespace coff
diff --git a/COFF/ICF.cpp b/COFF/ICF.cpp
index f99b41624a84..a2c5a90334d0 100644
--- a/COFF/ICF.cpp
+++ b/COFF/ICF.cpp
@@ -70,7 +70,7 @@ private:
static bool equalsConstant(const SectionChunk *A, const SectionChunk *B);
static bool equalsVariable(const SectionChunk *A, const SectionChunk *B);
bool forEachGroup(std::vector<SectionChunk *> &Chunks, Comparator Eq);
- bool partition(ChunkIterator Begin, ChunkIterator End, Comparator Eq);
+ bool segregate(ChunkIterator Begin, ChunkIterator End, Comparator Eq);
std::atomic<uint64_t> NextID = { 1 };
};
@@ -148,7 +148,7 @@ bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) {
return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq);
}
-bool ICF::partition(ChunkIterator Begin, ChunkIterator End, Comparator Eq) {
+bool ICF::segregate(ChunkIterator Begin, ChunkIterator End, Comparator Eq) {
bool R = false;
for (auto It = Begin;;) {
SectionChunk *Head = *It;
@@ -171,7 +171,7 @@ bool ICF::forEachGroup(std::vector<SectionChunk *> &Chunks, Comparator Eq) {
auto Bound = std::find_if(It + 1, End, [&](SectionChunk *SC) {
return SC->GroupID != Head->GroupID;
});
- if (partition(It, Bound, Eq))
+ if (segregate(It, Bound, Eq))
R = true;
It = Bound;
}
diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp
index 23af1e89c34d..ff26826371fa 100644
--- a/COFF/InputFiles.cpp
+++ b/COFF/InputFiles.cpp
@@ -8,30 +8,41 @@
//===----------------------------------------------------------------------===//
#include "Chunks.h"
+#include "Config.h"
#include "Error.h"
#include "InputFiles.h"
#include "Symbols.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/LTO/LTOModule.h"
+#include "llvm/LTO/legacy/LTOModule.h"
+#include "llvm/Object/Binary.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/COFF.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm-c/lto.h"
+#include <cstring>
+#include <system_error>
+#include <utility>
using namespace llvm::COFF;
using namespace llvm::object;
using namespace llvm::support::endian;
+
using llvm::Triple;
using llvm::support::ulittle32_t;
-using llvm::sys::fs::file_magic;
-using llvm::sys::fs::identify_magic;
namespace lld {
namespace coff {
int InputFile::NextIndex = 0;
+llvm::LLVMContext BitcodeFile::Context;
// Returns the last element of a path, which is supposed to be a filename.
static StringRef getBasename(StringRef Path) {
@@ -52,9 +63,7 @@ std::string InputFile::getShortName() {
void ArchiveFile::parse() {
// Parse a MemoryBufferRef as an archive file.
- auto ArchiveOrErr = Archive::create(MB);
- error(ArchiveOrErr, "Failed to parse static library");
- File = std::move(*ArchiveOrErr);
+ File = check(Archive::create(MB), "failed to parse static library");
// Allocate a buffer for Lazy objects.
size_t NumSyms = File->getNumberOfSymbols();
@@ -67,40 +76,38 @@ void ArchiveFile::parse() {
// Seen is a map from member files to boolean values. Initially
// all members are mapped to false, which indicates all these files
// are not read yet.
- for (auto &ChildOrErr : File->children()) {
- error(ChildOrErr, "Failed to parse static library");
- const Archive::Child &Child = *ChildOrErr;
+ Error Err;
+ for (auto &Child : File->children(Err))
Seen[Child.getChildOffset()].clear();
- }
+ if (Err)
+ fatal(Err, "failed to parse static library");
}
// Returns a buffer pointing to a member file containing a given symbol.
// This function is thread-safe.
MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
- auto COrErr = Sym->getMember();
- error(COrErr, Twine("Could not get the member for symbol ") + Sym->getName());
- const Archive::Child &C = *COrErr;
+ const Archive::Child &C =
+ check(Sym->getMember(),
+ "could not get the member for symbol " + Sym->getName());
// Return an empty buffer if we have already returned the same buffer.
if (Seen[C.getChildOffset()].test_and_set())
return MemoryBufferRef();
- ErrorOr<MemoryBufferRef> Ret = C.getMemoryBufferRef();
- error(Ret, Twine("Could not get the buffer for the member defining symbol ") +
- Sym->getName());
- return *Ret;
+ return check(C.getMemoryBufferRef(),
+ "could not get the buffer for the member defining symbol " +
+ Sym->getName());
}
void ObjectFile::parse() {
// Parse a memory buffer as a COFF file.
- auto BinOrErr = createBinary(MB);
- error(BinOrErr, "Failed to parse object file");
- std::unique_ptr<Binary> Bin = std::move(*BinOrErr);
+ std::unique_ptr<Binary> Bin =
+ check(createBinary(MB), "failed to parse object file");
if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) {
Bin.release();
COFFObj.reset(Obj);
} else {
- error(Twine(getName()) + " is not a COFF file.");
+ fatal(getName() + " is not a COFF file");
}
// Read section and symbol tables.
@@ -116,10 +123,10 @@ void ObjectFile::initializeChunks() {
for (uint32_t I = 1; I < NumSections + 1; ++I) {
const coff_section *Sec;
StringRef Name;
- std::error_code EC = COFFObj->getSection(I, Sec);
- error(EC, Twine("getSection failed: #") + Twine(I));
- EC = COFFObj->getSectionName(Sec, Name);
- error(EC, Twine("getSectionName failed: #") + Twine(I));
+ if (auto EC = COFFObj->getSection(I, Sec))
+ fatal(EC, "getSection failed: #" + Twine(I));
+ if (auto EC = COFFObj->getSectionName(Sec, Name))
+ fatal(EC, "getSectionName failed: #" + Twine(I));
if (Name == ".sxdata") {
SXData = Sec;
continue;
@@ -149,14 +156,12 @@ void ObjectFile::initializeSymbols() {
uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
SymbolBodies.reserve(NumSymbols);
SparseSymbolBodies.resize(NumSymbols);
- llvm::SmallVector<Undefined *, 8> WeakAliases;
+ llvm::SmallVector<std::pair<Undefined *, uint32_t>, 8> WeakAliases;
int32_t LastSectionNumber = 0;
for (uint32_t I = 0; I < NumSymbols; ++I) {
// Get a COFFSymbolRef object.
- auto SymOrErr = COFFObj->getSymbol(I);
- error(SymOrErr, Twine("broken object file: ") + getName());
-
- COFFSymbolRef Sym = *SymOrErr;
+ COFFSymbolRef Sym =
+ check(COFFObj->getSymbol(I), "broken object file: " + getName());
const void *AuxP = nullptr;
if (Sym.getNumberOfAuxSymbols())
@@ -167,8 +172,10 @@ void ObjectFile::initializeSymbols() {
if (Sym.isUndefined()) {
Body = createUndefined(Sym);
} else if (Sym.isWeakExternal()) {
- Body = createWeakExternal(Sym, AuxP);
- WeakAliases.push_back((Undefined *)Body);
+ Body = createUndefined(Sym);
+ uint32_t TagIndex =
+ static_cast<const coff_aux_weak_external *>(AuxP)->TagIndex;
+ WeakAliases.emplace_back((Undefined *)Body, TagIndex);
} else {
Body = createDefined(Sym, AuxP, IsFirst);
}
@@ -179,8 +186,8 @@ void ObjectFile::initializeSymbols() {
I += Sym.getNumberOfAuxSymbols();
LastSectionNumber = Sym.getSectionNumber();
}
- for (Undefined *U : WeakAliases)
- U->WeakAlias = SparseSymbolBodies[(uintptr_t)U->WeakAlias];
+ for (auto WeakAlias : WeakAliases)
+ WeakAlias.first->WeakAlias = SparseSymbolBodies[WeakAlias.second];
}
Undefined *ObjectFile::createUndefined(COFFSymbolRef Sym) {
@@ -189,15 +196,6 @@ Undefined *ObjectFile::createUndefined(COFFSymbolRef Sym) {
return new (Alloc) Undefined(Name);
}
-Undefined *ObjectFile::createWeakExternal(COFFSymbolRef Sym, const void *AuxP) {
- StringRef Name;
- COFFObj->getSymbolName(Sym, Name);
- auto *U = new (Alloc) Undefined(Name);
- auto *Aux = (const coff_aux_weak_external *)AuxP;
- U->WeakAlias = (Undefined *)(uintptr_t)Aux->TagIndex;
- return U;
-}
-
Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
bool IsFirst) {
StringRef Name;
@@ -219,11 +217,21 @@ Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
}
return new (Alloc) DefinedAbsolute(Name, Sym);
}
- if (Sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_DEBUG)
+ int32_t SectionNumber = Sym.getSectionNumber();
+ if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
return nullptr;
+ // Reserved sections numbers don't have contents.
+ if (llvm::COFF::isReservedSectionNumber(SectionNumber))
+ fatal("broken object file: " + getName());
+
+ // This symbol references a section which is not present in the section
+ // header.
+ if ((uint32_t)SectionNumber >= SparseChunks.size())
+ fatal("broken object file: " + getName());
+
// Nothing else to do without a section chunk.
- auto *SC = cast_or_null<SectionChunk>(SparseChunks[Sym.getSectionNumber()]);
+ auto *SC = cast_or_null<SectionChunk>(SparseChunks[SectionNumber]);
if (!SC)
return nullptr;
@@ -250,7 +258,7 @@ void ObjectFile::initializeSEH() {
ArrayRef<uint8_t> A;
COFFObj->getSectionContents(SXData, A);
if (A.size() % 4 != 0)
- error(".sxdata must be an array of symbol table indices");
+ fatal(".sxdata must be an array of symbol table indices");
auto *I = reinterpret_cast<const ulittle32_t *>(A.data());
auto *E = reinterpret_cast<const ulittle32_t *>(A.data() + A.size());
for (; I != E; ++I)
@@ -276,11 +284,11 @@ void ImportFile::parse() {
// Check if the total size is valid.
if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData))
- error("broken import library");
+ fatal("broken import library");
// Read names and create an __imp_ symbol.
StringRef Name = StringAlloc.save(StringRef(Buf + sizeof(*Hdr)));
- StringRef ImpName = StringAlloc.save(Twine("__imp_") + Name);
+ StringRef ImpName = StringAlloc.save("__imp_" + Name);
const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1;
DLLName = StringRef(NameStart);
StringRef ExtName;
@@ -315,11 +323,10 @@ void BitcodeFile::parse() {
// Usually parse() is thread-safe, but bitcode file is an exception.
std::lock_guard<std::mutex> Lock(Mu);
- ErrorOr<std::unique_ptr<LTOModule>> ModOrErr =
- LTOModule::createFromBuffer(llvm::getGlobalContext(), MB.getBufferStart(),
- MB.getBufferSize(), llvm::TargetOptions());
- error(ModOrErr, "Could not create lto module");
- M = std::move(*ModOrErr);
+ Context.enableDebugTypeODRUniquing();
+ ErrorOr<std::unique_ptr<LTOModule>> ModOrErr = LTOModule::createFromBuffer(
+ Context, MB.getBufferStart(), MB.getBufferSize(), llvm::TargetOptions());
+ M = check(std::move(ModOrErr), "could not create LTO module");
llvm::StringSaver Saver(Alloc);
for (unsigned I = 0, E = M->getSymbolCount(); I != E; ++I) {
diff --git a/COFF/InputFiles.h b/COFF/InputFiles.h
index 6a263fbaddf6..0ec01b5075f9 100644
--- a/COFF/InputFiles.h
+++ b/COFF/InputFiles.h
@@ -12,7 +12,8 @@
#include "lld/Core/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/LTO/LTOModule.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/LTO/legacy/LTOModule.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/StringSaver.h"
@@ -103,7 +104,7 @@ public:
// All symbols returned by ArchiveFiles are of Lazy type.
std::vector<SymbolBody *> &getSymbols() override {
- llvm_unreachable("internal error");
+ llvm_unreachable("internal fatal");
}
private:
@@ -147,7 +148,6 @@ private:
Defined *createDefined(COFFSymbolRef Sym, const void *Aux, bool IsFirst);
Undefined *createUndefined(COFFSymbolRef Sym);
- Undefined *createWeakExternal(COFFSymbolRef Sym, const void *Aux);
std::unique_ptr<COFFObjectFile> COFFObj;
llvm::BumpPtrAllocator Alloc;
@@ -204,9 +204,10 @@ public:
static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
MachineTypes getMachineType() override;
-
std::unique_ptr<LTOModule> takeModule() { return std::move(M); }
+ static llvm::LLVMContext Context;
+
private:
void parse() override;
diff --git a/COFF/Librarian.cpp b/COFF/Librarian.cpp
new file mode 100644
index 000000000000..25fb4a87b3eb
--- /dev/null
+++ b/COFF/Librarian.cpp
@@ -0,0 +1,489 @@
+//===- Librarian.cpp ------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions for the Librarian. The librarian creates and
+// manages libraries of the Common Object File Format (COFF) object files. It
+// primarily is used for creating static libraries and import libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Config.h"
+#include "Driver.h"
+#include "Error.h"
+#include "Symbols.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ArchiveWriter.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Path.h"
+
+#include <vector>
+
+using namespace lld::coff;
+using namespace llvm::COFF;
+using namespace llvm::object;
+using namespace llvm;
+
+static bool is32bit() {
+ switch (Config->Machine) {
+ default:
+ llvm_unreachable("unsupported machine");
+ case IMAGE_FILE_MACHINE_AMD64:
+ return false;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ case IMAGE_FILE_MACHINE_I386:
+ return true;
+ }
+}
+
+static uint16_t getImgRelRelocation() {
+ switch (Config->Machine) {
+ default:
+ llvm_unreachable("unsupported machine");
+ case IMAGE_FILE_MACHINE_AMD64:
+ return IMAGE_REL_AMD64_ADDR32NB;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ return IMAGE_REL_ARM_ADDR32NB;
+ case IMAGE_FILE_MACHINE_I386:
+ return IMAGE_REL_I386_DIR32NB;
+ }
+}
+
+template <class T> void append(std::vector<uint8_t> &B, const T &Data) {
+ size_t S = B.size();
+ B.resize(S + sizeof(T));
+ memcpy(&B[S], &Data, sizeof(T));
+}
+
+static void writeStringTable(std::vector<uint8_t> &B,
+ ArrayRef<const std::string> Strings) {
+ // The COFF string table consists of a 4-byte value which is the size of the
+ // table, including the length field itself. This value is followed by the
+ // string content itself, which is an array of null-terminated C-style
+ // strings. The termination is important as they are referenced to by offset
+ // by the symbol entity in the file format.
+
+ std::vector<uint8_t>::size_type Pos = B.size();
+ std::vector<uint8_t>::size_type Offset = B.size();
+
+ // Skip over the length field, we will fill it in later as we will have
+ // computed the length while emitting the string content itself.
+ Pos += sizeof(uint32_t);
+
+ for (const auto &S : Strings) {
+ B.resize(Pos + S.length() + 1);
+ strcpy(reinterpret_cast<char *>(&B[Pos]), S.c_str());
+ Pos += S.length() + 1;
+ }
+
+ // Backfill the length of the table now that it has been computed.
+ support::ulittle32_t Length(B.size() - Offset);
+ memcpy(&B[Offset], &Length, sizeof(Length));
+}
+
+static std::string getImplibPath() {
+ if (!Config->Implib.empty())
+ return Config->Implib;
+ SmallString<128> Out = StringRef(Config->OutputFile);
+ sys::path::replace_extension(Out, ".lib");
+ return Out.str();
+}
+
+static ImportNameType getNameType(StringRef Sym, StringRef ExtName) {
+ if (Sym != ExtName)
+ return IMPORT_NAME_UNDECORATE;
+ if (Config->Machine == I386 && Sym.startswith("_"))
+ return IMPORT_NAME_NOPREFIX;
+ return IMPORT_NAME;
+}
+
+static std::string replace(StringRef S, StringRef From, StringRef To) {
+ size_t Pos = S.find(From);
+ assert(Pos != StringRef::npos);
+ return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
+}
+
+static const std::string NullImportDescriptorSymbolName =
+ "__NULL_IMPORT_DESCRIPTOR";
+
+namespace {
+// This class constructs various small object files necessary to support linking
+// symbols imported from a DLL. The contents are pretty strictly defined and
+// nearly entirely static. The details of the structures files are defined in
+// WINNT.h and the PE/COFF specification.
+class ObjectFactory {
+ using u16 = support::ulittle16_t;
+ using u32 = support::ulittle32_t;
+
+ BumpPtrAllocator Alloc;
+ StringRef DLLName;
+ StringRef Library;
+ std::string ImportDescriptorSymbolName;
+ std::string NullThunkSymbolName;
+
+public:
+ ObjectFactory(StringRef S)
+ : DLLName(S), Library(S.drop_back(4)),
+ ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
+ NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
+
+ // Creates an Import Descriptor. This is a small object file which contains a
+ // reference to the terminators and contains the library name (entry) for the
+ // import name table. It will force the linker to construct the necessary
+ // structure to import symbols from the DLL.
+ NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
+
+ // Creates a NULL import descriptor. This is a small object file whcih
+ // contains a NULL import descriptor. It is used to terminate the imports
+ // from a specific DLL.
+ NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
+
+ // Create a NULL Thunk Entry. This is a small object file which contains a
+ // NULL Import Address Table entry and a NULL Import Lookup Table Entry. It
+ // is used to terminate the IAT and ILT.
+ NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);
+
+ // Create a short import file which is described in PE/COFF spec 7. Import
+ // Library Format.
+ NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
+ ImportNameType NameType, bool isData);
+};
+}
+
+NewArchiveMember
+ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 2;
+ static const uint32_t NumberOfSymbols = 7;
+ static const uint32_t NumberOfRelocations = 3;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Config->Machine), u16(NumberOfSections), u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$2
+ sizeof(coff_import_directory_table_entry) +
+ NumberOfRelocations * sizeof(coff_relocation) +
+ // .idata$4
+ (DLLName.size() + 1)),
+ u32(NumberOfSymbols), u16(0),
+ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
+ u32(0),
+ u32(0),
+ u32(sizeof(coff_import_directory_table_entry)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ sizeof(coff_import_directory_table_entry)),
+ u32(0),
+ u16(NumberOfRelocations),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
+ u32(0),
+ u32(0),
+ u32(DLLName.size() + 1),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ sizeof(coff_import_directory_table_entry) +
+ NumberOfRelocations * sizeof(coff_relocation)),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$2
+ static const coff_import_directory_table_entry ImportDescriptor{
+ u32(0), u32(0), u32(0), u32(0), u32(0),
+ };
+ append(Buffer, ImportDescriptor);
+
+ static const coff_relocation RelocationTable[NumberOfRelocations] = {
+ {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
+ u16(getImgRelRelocation())},
+ {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
+ u32(3), u16(getImgRelRelocation())},
+ {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
+ u32(4), u16(getImgRelRelocation())},
+ };
+ append(Buffer, RelocationTable);
+
+ // .idata$6
+ auto S = Buffer.size();
+ Buffer.resize(S + DLLName.size() + 1);
+ memcpy(&Buffer[S], DLLName.data(), DLLName.size());
+ Buffer[S + DLLName.size()] = '\0';
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},
+ u32(0),
+ u16(2),
+ u16(0),
+ IMAGE_SYM_CLASS_STATIC,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ reinterpret_cast<StringTableOffset &>(SymbolTable[5].Name).Offset =
+ sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
+ reinterpret_cast<StringTableOffset &>(SymbolTable[6].Name).Offset =
+ sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
+ NullImportDescriptorSymbolName.length() + 1;
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer,
+ {ImportDescriptorSymbolName, NullImportDescriptorSymbolName,
+ NullThunkSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef(F, DLLName)};
+}
+
+NewArchiveMember
+ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 1;
+ static const uint32_t NumberOfSymbols = 1;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Config->Machine), u16(NumberOfSections), u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$3
+ sizeof(coff_import_directory_table_entry)),
+ u32(NumberOfSymbols), u16(0),
+ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
+ u32(0),
+ u32(0),
+ u32(sizeof(coff_import_directory_table_entry)),
+ u32(sizeof(coff_file_header) +
+ (NumberOfSections * sizeof(coff_section))),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$3
+ static const coff_import_directory_table_entry ImportDescriptor{
+ u32(0), u32(0), u32(0), u32(0), u32(0),
+ };
+ append(Buffer, ImportDescriptor);
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer, {NullImportDescriptorSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef(F, DLLName)};
+}
+
+NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 2;
+ static const uint32_t NumberOfSymbols = 1;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Config->Machine), u16(NumberOfSections), u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$5
+ sizeof(export_address_table_entry) +
+ // .idata$4
+ sizeof(export_address_table_entry)),
+ u32(NumberOfSymbols), u16(0),
+ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
+ u32(0),
+ u32(0),
+ u32(sizeof(export_address_table_entry)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
+ u32(0),
+ u32(0),
+ u32(sizeof(export_address_table_entry)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ sizeof(export_address_table_entry)),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$5
+ static const export_address_table_entry ILT{u32(0)};
+ append(Buffer, ILT);
+
+ // .idata$4
+ static const export_address_table_entry IAT{u32(0)};
+ append(Buffer, IAT);
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer, {NullThunkSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef{F, DLLName}};
+}
+
+NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
+ uint16_t Ordinal,
+ ImportNameType NameType,
+ bool isData) {
+ size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs
+ size_t Size = sizeof(coff_import_header) + ImpSize;
+ char *Buf = Alloc.Allocate<char>(Size);
+ memset(Buf, 0, Size);
+ char *P = Buf;
+
+ // Write short import library.
+ auto *Imp = reinterpret_cast<coff_import_header *>(P);
+ P += sizeof(*Imp);
+ Imp->Sig2 = 0xFFFF;
+ Imp->Machine = Config->Machine;
+ Imp->SizeOfData = ImpSize;
+ if (Ordinal > 0)
+ Imp->OrdinalHint = Ordinal;
+ Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE);
+ Imp->TypeInfo |= NameType << 2;
+
+ // Write symbol name and DLL name.
+ memcpy(P, Sym.data(), Sym.size());
+ P += Sym.size() + 1;
+ memcpy(P, DLLName.data(), DLLName.size());
+
+ return {MemoryBufferRef(StringRef(Buf, Size), DLLName)};
+}
+
+// Creates an import library for a DLL. In this function, we first
+// create an empty import library using lib.exe and then adds short
+// import files to that file.
+void lld::coff::writeImportLibrary() {
+ std::vector<NewArchiveMember> Members;
+
+ std::string Path = getImplibPath();
+ std::string DLLName = llvm::sys::path::filename(Config->OutputFile);
+ ObjectFactory OF(DLLName);
+
+ std::vector<uint8_t> ImportDescriptor;
+ Members.push_back(OF.createImportDescriptor(ImportDescriptor));
+
+ std::vector<uint8_t> NullImportDescriptor;
+ Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
+
+ std::vector<uint8_t> NullThunk;
+ Members.push_back(OF.createNullThunk(NullThunk));
+
+ for (Export &E : Config->Exports) {
+ if (E.Private)
+ continue;
+
+ ImportNameType Type = getNameType(E.SymbolName, E.Name);
+ std::string Name = E.ExtName.empty()
+ ? std::string(E.SymbolName)
+ : replace(E.SymbolName, E.Name, E.ExtName);
+ Members.push_back(OF.createShortImport(Name, E.Ordinal, Type, E.Data));
+ }
+
+ std::pair<StringRef, std::error_code> Result =
+ writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU,
+ /*Deterministic*/ true, /*Thin*/ false);
+ if (auto EC = Result.second)
+ fatal(EC, "failed to write " + Path);
+}
diff --git a/COFF/ModuleDef.cpp b/COFF/ModuleDef.cpp
index d117e961f89a..5e393f45d184 100644
--- a/COFF/ModuleDef.cpp
+++ b/COFF/ModuleDef.cpp
@@ -134,13 +134,13 @@ private:
void readAsInt(uint64_t *I) {
read();
if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I))
- error("integer expected");
+ fatal("integer expected");
}
void expect(Kind Expected, StringRef Msg) {
read();
if (Tok.K != Expected)
- error(Msg);
+ fatal(Msg);
}
void unget() { Stack.push_back(Tok); }
@@ -177,7 +177,7 @@ private:
parseVersion(&Config->MajorImageVersion, &Config->MinorImageVersion);
return;
default:
- error(Twine("unknown directive: ") + Tok.Value);
+ fatal("unknown directive: " + Tok.Value);
}
}
@@ -188,7 +188,7 @@ private:
if (Tok.K == Equal) {
read();
if (Tok.K != Identifier)
- error(Twine("identifier expected, but got ") + Tok.Value);
+ fatal("identifier expected, but got " + Tok.Value);
E.ExtName = E.Name;
E.Name = Tok.Value;
} else {
@@ -264,15 +264,15 @@ private:
void parseVersion(uint32_t *Major, uint32_t *Minor) {
read();
if (Tok.K != Identifier)
- error(Twine("identifier expected, but got ") + Tok.Value);
+ fatal("identifier expected, but got " + Tok.Value);
StringRef V1, V2;
std::tie(V1, V2) = Tok.Value.split('.');
if (V1.getAsInteger(10, *Major))
- error(Twine("integer expected, but got ") + Tok.Value);
+ fatal("integer expected, but got " + Tok.Value);
if (V2.empty())
*Minor = 0;
else if (V2.getAsInteger(10, *Minor))
- error(Twine("integer expected, but got ") + Tok.Value);
+ fatal("integer expected, but got " + Tok.Value);
}
Lexer Lex;
diff --git a/COFF/Options.td b/COFF/Options.td
index a21b8de76afb..e5c9c5b4635b 100644
--- a/COFF/Options.td
+++ b/COFF/Options.td
@@ -48,6 +48,7 @@ def manifestuac : P<"manifestuac", "User access control">;
def manifestfile : P<"manifestfile", "Manifest file path">;
def manifestdependency : P<"manifestdependency",
"Attributes for <dependency> in manifest file">;
+def manifestinput : P<"manifestinput", "Specify manifest file">;
// We cannot use multiclass P because class name "incl" is different
// from its command line option name. We do this because "include" is
@@ -110,6 +111,7 @@ def no_incremental : F<"incremental:no">;
def nologo : F<"nologo">;
def throwingnew : F<"throwingnew">;
def editandcontinue : F<"editandcontinue">;
+def fastfail : F<"fastfail">;
def delay : QF<"delay">;
def errorreport : QF<"errorreport">;
diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp
index 786d28798bab..7606ccc680d3 100644
--- a/COFF/PDB.cpp
+++ b/COFF/PDB.cpp
@@ -38,7 +38,8 @@ void lld::coff::createPDB(StringRef Path) {
size_t FileSize = PageSize * 3;
ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
FileOutputBuffer::create(Path, FileSize);
- error(BufferOrErr, Twine("failed to open ") + Path);
+ if (auto EC = BufferOrErr.getError())
+ fatal(EC, "failed to open " + Path);
std::unique_ptr<FileOutputBuffer> Buffer = std::move(*BufferOrErr);
// Write the file header.
diff --git a/COFF/README.md b/COFF/README.md
index c1be560f4405..f1bfc9c15263 100644
--- a/COFF/README.md
+++ b/COFF/README.md
@@ -1,265 +1 @@
-The PE/COFF Linker
-==================
-
-This directory contains a linker for Windows operating system.
-Because the fundamental design of this port is different from
-the other ports of LLD, this port is separated to this directory.
-
-The linker is command-line compatible with MSVC linker and is
-generally 2x faster than that. It can be used to link real-world
-programs such as LLD itself or Clang, or even web browsers which
-are probably the largest open-source programs for Windows.
-
-This document is also applicable to ELF linker because the linker
-shares the same design as this COFF linker.
-
-Overall Design
---------------
-
-This is a list of important data types in this linker.
-
-* SymbolBody
-
- SymbolBody is a class for symbols. They may be created for symbols
- in object files or in archive file headers. The linker may create
- them out of nothing.
-
- There are mainly three types of SymbolBodies: Defined, Undefined, or
- Lazy. Defined symbols are for all symbols that are considered as
- "resolved", including real defined symbols, COMDAT symbols, common
- symbols, absolute symbols, linker-created symbols, etc. Undefined
- symbols are for undefined symbols, which need to be replaced by
- Defined symbols by the resolver. Lazy symbols represent symbols we
- found in archive file headers -- which can turn into Defined symbols
- if we read archieve members, but we haven't done that yet.
-
-* Symbol
-
- Symbol is a pointer to a SymbolBody. There's only one Symbol for
- each unique symbol name (this uniqueness is guaranteed by the symbol
- table). Because SymbolBodies are created for each file
- independently, there can be many SymbolBodies for the same
- name. Thus, the relationship between Symbols and SymbolBodies is 1:N.
-
- The resolver keeps the Symbol's pointer to always point to the "best"
- SymbolBody. Pointer mutation is the resolve operation in this
- linker.
-
- SymbolBodies have pointers to their Symbols. That means you can
- always find the best SymbolBody from any SymbolBody by following
- pointers twice. This structure makes it very easy to find
- replacements for symbols. For example, if you have an Undefined
- SymbolBody, you can find a Defined SymbolBody for that symbol just
- by going to its Symbol and then to SymbolBody, assuming the resolver
- have successfully resolved all undefined symbols.
-
-* Chunk
-
- Chunk represents a chunk of data that will occupy space in an
- output. Each regular section becomes a chunk.
- Chunks created for common or BSS symbols are not backed by sections.
- The linker may create chunks out of nothing to append additional
- data to an output.
-
- Chunks know about their size, how to copy their data to mmap'ed
- outputs, and how to apply relocations to them. Specifically,
- section-based chunks know how to read relocation tables and how to
- apply them.
-
-* SymbolTable
-
- SymbolTable is basically a hash table from strings to Symbols, with
- a logic to resolve symbol conflicts. It resolves conflicts by symbol
- type. For example, if we add Undefined and Defined symbols, the
- symbol table will keep the latter. If we add Defined and Lazy
- symbols, it will keep the former. If we add Lazy and Undefined, it
- will keep the former, but it will also trigger the Lazy symbol to
- load the archive member to actually resolve the symbol.
-
-* OutputSection
-
- OutputSection is a container of Chunks. A Chunk belongs to at most
- one OutputSection.
-
-There are mainly three actors in this linker.
-
-* InputFile
-
- InputFile is a superclass of file readers. We have a different
- subclass for each input file type, such as regular object file,
- archive file, etc. They are responsible for creating and owning
- SymbolBodies and Chunks.
-
-* Writer
-
- The writer is responsible for writing file headers and Chunks to a
- file. It creates OutputSections, put all Chunks into them, assign
- unique, non-overlapping addresses and file offsets to them, and then
- write them down to a file.
-
-* Driver
-
- The linking process is drived by the driver. The driver
-
- - processes command line options,
- - creates a symbol table,
- - creates an InputFile for each input file and put all symbols in it
- into the symbol table,
- - checks if there's no remaining undefined symbols,
- - creates a writer,
- - and passes the symbol table to the writer to write the result to a
- file.
-
-Performance
------------
-
-It's generally 2x faster than MSVC link.exe. It takes 3.5 seconds to
-self-host on my Xeon 2580 machine. MSVC linker takes 7.0 seconds to
-link the same executable. The resulting output is 65MB.
-The old LLD is buggy that it produces 120MB executable for some reason,
-and it takes 30 seconds to do that.
-
-We believe the performance difference comes from simplification and
-optimizations we made to the new port. Notable differences are listed
-below.
-
-* Reduced number of relocation table reads
-
- In the old design, relocation tables are read from beginning to
- construct graphs because they consist of graph edges. In the new
- design, they are not read until we actually apply relocations.
-
- This simplification has two benefits. One is that we don't create
- additional objects for relocations but instead consume relocation
- tables directly. The other is that it reduces number of relocation
- entries we have to read, because we won't read relocations for
- dead-stripped COMDAT sections. Large C++ programs tend to consist of
- lots of COMDAT sections. In the old design, the time to process
- relocation table is linear to size of input. In this new model, it's
- linear to size of output.
-
-* Reduced number of symbol table lookup
-
- Symbol table lookup can be a heavy operation because number of
- symbols can be very large and each symbol name can be very long
- (think of C++ mangled symbols -- time to compute a hash value for a
- string is linear to the length.)
-
- We look up the symbol table exactly only once for each symbol in the
- new design. This is I believe the minimum possible number. This is
- achieved by the separation of Symbol and SymbolBody. Once you get a
- pointer to a Symbol by looking up the symbol table, you can always
- get the latest symbol resolution result by just dereferencing a
- pointer. (I'm not sure if the idea is new to the linker. At least,
- all other linkers I've investigated so far seem to look up hash
- tables or sets more than once for each new symbol, but I may be
- wrong.)
-
-* Reduced number of file visits
-
- The symbol table implements the Windows linker semantics. We treat
- the symbol table as a bucket of all known symbols, including symbols
- in archive file headers. We put all symbols into one bucket as we
- visit new files. That means we visit each file only once.
-
- This is different from the Unix linker semantics, in which we only
- keep undefined symbols and visit each file one by one until we
- resolve all undefined symbols. In the Unix model, we have to visit
- archive files many times if there are circular dependencies between
- archives.
-
-* Avoiding creating additional objects or copying data
-
- The data structures described in the previous section are all thin
- wrappers for classes that LLVM libObject provides. We avoid copying
- data from libObject's objects to our objects. We read much less data
- than before. For example, we don't read symbol values until we apply
- relocations because these values are not relevant to symbol
- resolution. Again, COMDAT symbols may be discarded during symbol
- resolution, so reading their attributes too early could result in a
- waste. We use underlying objects directly where doing so makes
- sense.
-
-Parallelism
------------
-
-The abovementioned data structures are also chosen with
-multi-threading in mind. It should relatively be easy to make the
-symbol table a concurrent hash map, so that we let multiple workers
-work on symbol table concurrently. Symbol resolution in this design is
-a single pointer mutation, which allows the resolver work concurrently
-in a lock-free manner using atomic pointer compare-and-swap.
-
-It should also be easy to apply relocations and write chunks concurrently.
-
-We created an experimental multi-threaded linker using the Microsoft
-ConcRT concurrency library, and it was able to link itself in 0.5
-seconds, so we think the design is promising.
-
-Link-Time Optimization
-----------------------
-
-LTO is implemented by handling LLVM bitcode files as object files.
-The linker resolves symbols in bitcode files normally. If all symbols
-are successfully resolved, it then calls an LLVM libLTO function
-with all bitcode files to convert them to one big regular COFF file.
-Finally, the linker replaces bitcode symbols with COFF symbols,
-so that we can link the input files as if they were in the native
-format from the beginning.
-
-The details are described in this document.
-http://llvm.org/docs/LinkTimeOptimization.html
-
-Glossary
---------
-
-* RVA
-
- Short for Relative Virtual Address.
-
- Windows executables or DLLs are not position-independent; they are
- linked against a fixed address called an image base. RVAs are
- offsets from an image base.
-
- Default image bases are 0x140000000 for executables and 0x18000000
- for DLLs. For example, when we are creating an executable, we assume
- that the executable will be loaded at address 0x140000000 by the
- loader, so we apply relocations accordingly. Result texts and data
- will contain raw absolute addresses.
-
-* VA
-
- Short for Virtual Address. Equivalent to RVA + image base. It is
- rarely used. We almost always use RVAs instead.
-
-* Base relocations
-
- Relocation information for the loader. If the loader decides to map
- an executable or a DLL to a different address than their image
- bases, it fixes up binaries using information contained in the base
- relocation table. A base relocation table consists of a list of
- locations containing addresses. The loader adds a difference between
- RVA and actual load address to all locations listed there.
-
- Note that this run-time relocation mechanism is much simpler than ELF.
- There's no PLT or GOT. Images are relocated as a whole just
- by shifting entire images in memory by some offsets. Although doing
- this breaks text sharing, I think this mechanism is not actually bad
- on today's computers.
-
-* ICF
-
- Short for Identical COMDAT Folding.
-
- ICF is an optimization to reduce output size by merging COMDAT sections
- by not only their names but by their contents. If two COMDAT sections
- happen to have the same metadata, actual contents and relocations,
- they are merged by ICF. It is known as an effective technique,
- and it usually reduces C++ program's size by a few percent or more.
-
- Note that this is not entirely sound optimization. C/C++ require
- different functions have different addresses. If a program depends on
- that property, it would fail at runtime. However, that's not really an
- issue on Windows because MSVC link.exe enabled the optimization by
- default. As long as your program works with the linker's default
- settings, your program should be safe with ICF.
+See docs/NewLLD.rst
diff --git a/COFF/SymbolTable.cpp b/COFF/SymbolTable.cpp
index 5b7b89cd360a..df9da4c36650 100644
--- a/COFF/SymbolTable.cpp
+++ b/COFF/SymbolTable.cpp
@@ -14,7 +14,7 @@
#include "Symbols.h"
#include "lld/Core/Parallel.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/LTO/LTOCodeGenerator.h"
+#include "llvm/LTO/legacy/LTOCodeGenerator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>
@@ -164,7 +164,7 @@ void SymbolTable::reportRemainingUndefines(bool Resolve) {
llvm::errs() << File->getShortName() << ": undefined symbol: "
<< Sym->getName() << "\n";
if (!Config->Force)
- error("Link failed");
+ fatal("link failed");
}
void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
@@ -211,7 +211,7 @@ void SymbolTable::addSymbol(SymbolBody *New) {
// equivalent (conflicting), or more preferable, respectively.
int Comp = Existing->compare(New);
if (Comp == 0)
- error(Twine("duplicate symbol: ") + Existing->getDebugName() + " and " +
+ fatal("duplicate symbol: " + Existing->getDebugName() + " and " +
New->getDebugName());
if (Comp < 0)
Sym->Body = New;
@@ -338,21 +338,25 @@ void SymbolTable::addCombinedLTOObject(ObjectFile *Obj) {
// diagnose them later in reportRemainingUndefines().
StringRef Name = Body->getName();
Symbol *Sym = insert(Body);
+ SymbolBody *Existing = Sym->Body;
+
+ if (Existing == Body)
+ continue;
- if (isa<DefinedBitcode>(Sym->Body)) {
+ if (isa<DefinedBitcode>(Existing)) {
Sym->Body = Body;
continue;
}
- if (auto *L = dyn_cast<Lazy>(Sym->Body)) {
+ if (auto *L = dyn_cast<Lazy>(Existing)) {
// We may see new references to runtime library symbols such as __chkstk
// here. These symbols must be wholly defined in non-bitcode files.
addMemberFile(L);
continue;
}
- SymbolBody *Existing = Sym->Body;
+
int Comp = Existing->compare(Body);
if (Comp == 0)
- error(Twine("LTO: unexpected duplicate symbol: ") + Name);
+ fatal("LTO: unexpected duplicate symbol: " + Name);
if (Comp < 0)
Sym->Body = Body;
}
@@ -369,7 +373,7 @@ void SymbolTable::addCombinedLTOObjects() {
// Create an object file and add it to the symbol table by replacing any
// DefinedBitcode symbols with the definitions in the object file.
- LTOCodeGenerator CG(getGlobalContext());
+ LTOCodeGenerator CG(BitcodeFile::Context);
CG.setOptLevel(Config->LTOOptLevel);
std::vector<ObjectFile *> Objs = createLTOObjects(&CG);
@@ -379,7 +383,7 @@ void SymbolTable::addCombinedLTOObjects() {
size_t NumBitcodeFiles = BitcodeFiles.size();
run();
if (BitcodeFiles.size() != NumBitcodeFiles)
- error("LTO: late loaded symbol created new bitcode reference");
+ fatal("LTO: late loaded symbol created new bitcode reference");
}
// Combine and compile bitcode files and then return the result
@@ -414,24 +418,23 @@ std::vector<ObjectFile *> SymbolTable::createLTOObjects(LTOCodeGenerator *CG) {
DisableVerify = false;
#endif
if (!CG->optimize(DisableVerify, false, false, false))
- error(""); // optimize() should have emitted any error message.
+ fatal(""); // optimize() should have emitted any error message.
Objs.resize(Config->LTOJobs);
// Use std::list to avoid invalidation of pointers in OSPtrs.
std::list<raw_svector_ostream> OSs;
std::vector<raw_pwrite_stream *> OSPtrs;
- for (SmallVector<char, 0> &Obj : Objs) {
+ for (SmallString<0> &Obj : Objs) {
OSs.emplace_back(Obj);
OSPtrs.push_back(&OSs.back());
}
if (!CG->compileOptimized(OSPtrs))
- error(""); // compileOptimized() should have emitted any error message.
+ fatal(""); // compileOptimized() should have emitted any error message.
std::vector<ObjectFile *> ObjFiles;
- for (SmallVector<char, 0> &Obj : Objs) {
- auto *ObjFile = new ObjectFile(
- MemoryBufferRef(StringRef(Obj.data(), Obj.size()), "<LTO object>"));
+ for (SmallString<0> &Obj : Objs) {
+ auto *ObjFile = new ObjectFile(MemoryBufferRef(Obj, "<LTO object>"));
Files.emplace_back(ObjFile);
ObjectFiles.push_back(ObjFile);
ObjFile->parse();
diff --git a/COFF/SymbolTable.h b/COFF/SymbolTable.h
index ce305bfa8743..8bf4387cdfff 100644
--- a/COFF/SymbolTable.h
+++ b/COFF/SymbolTable.h
@@ -115,7 +115,7 @@ private:
std::vector<std::future<InputFile *>> ObjectQueue;
std::vector<BitcodeFile *> BitcodeFiles;
- std::vector<SmallVector<char, 0>> Objs;
+ std::vector<SmallString<0>> Objs;
llvm::BumpPtrAllocator Alloc;
};
diff --git a/COFF/Symbols.cpp b/COFF/Symbols.cpp
index d732d76cfb06..6e2db6631ce7 100644
--- a/COFF/Symbols.cpp
+++ b/COFF/Symbols.cpp
@@ -162,32 +162,6 @@ std::string SymbolBody::getDebugName() {
return N;
}
-uint64_t Defined::getFileOff() {
- switch (kind()) {
- case DefinedImportDataKind:
- return cast<DefinedImportData>(this)->getFileOff();
- case DefinedImportThunkKind:
- return cast<DefinedImportThunk>(this)->getFileOff();
- case DefinedLocalImportKind:
- return cast<DefinedLocalImport>(this)->getFileOff();
- case DefinedCommonKind:
- return cast<DefinedCommon>(this)->getFileOff();
- case DefinedRegularKind:
- return cast<DefinedRegular>(this)->getFileOff();
-
- case DefinedBitcodeKind:
- llvm_unreachable("There is no file offset for a bitcode symbol.");
- case DefinedAbsoluteKind:
- llvm_unreachable("Cannot get a file offset for an absolute symbol.");
- case DefinedRelativeKind:
- llvm_unreachable("Cannot get a file offset for a relative symbol.");
- case LazyKind:
- case UndefinedKind:
- llvm_unreachable("Cannot get a file offset for an undefined symbol.");
- }
- llvm_unreachable("unknown symbol kind");
-}
-
COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
size_t SymSize = File->getCOFFObj()->getSymbolTableEntrySize();
if (SymSize == sizeof(coff_symbol16))
@@ -225,7 +199,7 @@ std::unique_ptr<InputFile> Lazy::getMember() {
else if (Magic == file_magic::bitcode)
Obj.reset(new BitcodeFile(MBRef));
else
- error(Twine(File->getName()) + ": unknown file type");
+ fatal("unknown file type: " + File->getName());
Obj->setParentName(File->getName());
return Obj;
diff --git a/COFF/Symbols.h b/COFF/Symbols.h
index 7059fbc8bb15..f96c1fb3cc1d 100644
--- a/COFF/Symbols.h
+++ b/COFF/Symbols.h
@@ -125,10 +125,6 @@ public:
// writer sets and uses RVAs.
uint64_t getRVA();
- // Returns the file offset of this symbol in the final executable.
- // The writer uses this information to apply relocations.
- uint64_t getFileOff();
-
// Returns the RVA relative to the beginning of the output section.
// Used to implement SECREL relocation type.
uint64_t getSecrel();
diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp
index 5575c8d6b320..d8077df95701 100644
--- a/COFF/Writer.cpp
+++ b/COFF/Writer.cpp
@@ -59,6 +59,7 @@ private:
void openFile(StringRef OutputPath);
template <typename PEHeaderTy> void writeHeader();
void fixSafeSEHSymbols();
+ void setSectionPermissions();
void writeSections();
void sortExceptionTable();
void applyRelocations();
@@ -114,6 +115,7 @@ public:
StringRef getName() { return Name; }
std::vector<Chunk *> &getChunks() { return Chunks; }
void addPermissions(uint32_t C);
+ void setPermissions(uint32_t C);
uint32_t getPermissions() { return Header.Characteristics & PermMask; }
uint32_t getCharacteristics() { return Header.Characteristics; }
uint64_t getRVA() { return Header.VirtualAddress; }
@@ -163,19 +165,23 @@ void OutputSection::addChunk(Chunk *C) {
Chunks.push_back(C);
C->setOutputSection(this);
uint64_t Off = Header.VirtualSize;
- Off = align(Off, C->getAlign());
+ Off = alignTo(Off, C->getAlign());
C->setRVA(Off);
C->setOutputSectionOff(Off);
Off += C->getSize();
Header.VirtualSize = Off;
if (C->hasData())
- Header.SizeOfRawData = align(Off, SectorSize);
+ Header.SizeOfRawData = alignTo(Off, SectorSize);
}
void OutputSection::addPermissions(uint32_t C) {
Header.Characteristics |= C & PermMask;
}
+void OutputSection::setPermissions(uint32_t C) {
+ Header.Characteristics = C & PermMask;
+}
+
// Write the section header to a given buffer.
void OutputSection::writeHeaderTo(uint8_t *Buf) {
auto *Hdr = reinterpret_cast<coff_section *>(Buf);
@@ -193,13 +199,13 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) {
uint64_t Defined::getSecrel() {
if (auto *D = dyn_cast<DefinedRegular>(this))
return getRVA() - D->getChunk()->getOutputSection()->getRVA();
- error("SECREL relocation points to a non-regular symbol");
+ fatal("SECREL relocation points to a non-regular symbol");
}
uint64_t Defined::getSectionIndex() {
if (auto *D = dyn_cast<DefinedRegular>(this))
return D->getChunk()->getOutputSection()->SectionIndex;
- error("SECTION relocation points to a non-regular symbol");
+ fatal("SECTION relocation points to a non-regular symbol");
}
bool Defined::isExecutable() {
@@ -222,6 +228,7 @@ void Writer::run() {
createSection(".reloc");
assignAddresses();
removeEmptySections();
+ setSectionPermissions();
createSymbolAndStringTable();
openFile(Config->OutputFile);
if (Config->is64()) {
@@ -232,7 +239,8 @@ void Writer::run() {
fixSafeSEHSymbols();
writeSections();
sortExceptionTable();
- error(Buffer->commit(), "Failed to write the output file");
+ if (auto EC = Buffer->commit())
+ fatal(EC, "failed to write the output file");
}
static StringRef getOutputSection(StringRef Name) {
@@ -447,15 +455,15 @@ void Writer::createSymbolAndStringTable() {
OutputSection *LastSection = OutputSections.back();
// We position the symbol table to be adjacent to the end of the last section.
- uint64_t FileOff =
- LastSection->getFileOff() + align(LastSection->getRawSize(), SectorSize);
+ uint64_t FileOff = LastSection->getFileOff() +
+ alignTo(LastSection->getRawSize(), SectorSize);
if (!OutputSymtab.empty()) {
PointerToSymbolTable = FileOff;
FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
}
if (!Strtab.empty())
FileOff += Strtab.size() + 4;
- FileSize = align(FileOff, SectorSize);
+ FileSize = alignTo(FileOff, SectorSize);
}
// Visits all sections to assign incremental, non-overlapping RVAs and
@@ -466,7 +474,7 @@ void Writer::assignAddresses() {
sizeof(coff_section) * OutputSections.size();
SizeOfHeaders +=
Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
- SizeOfHeaders = align(SizeOfHeaders, SectorSize);
+ SizeOfHeaders = alignTo(SizeOfHeaders, SectorSize);
uint64_t RVA = 0x1000; // The first page is kept unmapped.
FileSize = SizeOfHeaders;
// Move DISCARDABLE (or non-memory-mapped) sections to the end of file because
@@ -480,10 +488,10 @@ void Writer::assignAddresses() {
addBaserels(Sec);
Sec->setRVA(RVA);
Sec->setFileOffset(FileSize);
- RVA += align(Sec->getVirtualSize(), PageSize);
- FileSize += align(Sec->getRawSize(), SectorSize);
+ RVA += alignTo(Sec->getVirtualSize(), PageSize);
+ FileSize += alignTo(Sec->getRawSize(), SectorSize);
}
- SizeOfImage = SizeOfHeaders + align(RVA - 0x1000, PageSize);
+ SizeOfImage = SizeOfHeaders + alignTo(RVA - 0x1000, PageSize);
}
template <typename PEHeaderTy> void Writer::writeHeader() {
@@ -596,13 +604,26 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) {
if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA();
- Dir[TLS_TABLE].Size = 40;
+ Dir[TLS_TABLE].Size = Config->is64()
+ ? sizeof(object::coff_tls_directory64)
+ : sizeof(object::coff_tls_directory32);
}
}
if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) {
- if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
+ if (auto *B = dyn_cast<DefinedRegular>(Sym->Body)) {
+ SectionChunk *SC = B->getChunk();
+ assert(B->getRVA() >= SC->getRVA());
+ uint64_t OffsetInChunk = B->getRVA() - SC->getRVA();
+ if (!SC->hasData() || OffsetInChunk + 4 > SC->getSize())
+ fatal("_load_config_used is malformed");
+
+ ArrayRef<uint8_t> SecContents = SC->getContents();
+ uint32_t LoadConfigSize =
+ *reinterpret_cast<const ulittle32_t *>(&SecContents[OffsetInChunk]);
+ if (OffsetInChunk + LoadConfigSize > SC->getSize())
+ fatal("_load_config_used is too large");
Dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = B->getRVA();
- Dir[LOAD_CONFIG_TABLE].Size = Config->is64() ? 112 : 64;
+ Dir[LOAD_CONFIG_TABLE].Size = LoadConfigSize;
}
}
@@ -626,14 +647,14 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
// The first 4 bytes is length including itself.
Buf = reinterpret_cast<uint8_t *>(&SymbolTable[NumberOfSymbols]);
write32le(Buf, Strtab.size() + 4);
- memcpy(Buf + 4, Strtab.data(), Strtab.size());
+ if (!Strtab.empty())
+ memcpy(Buf + 4, Strtab.data(), Strtab.size());
}
void Writer::openFile(StringRef Path) {
- ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
- FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable);
- error(BufferOrErr, Twine("failed to open ") + Path);
- Buffer = std::move(*BufferOrErr);
+ Buffer = check(
+ FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable),
+ "failed to open " + Path);
}
void Writer::fixSafeSEHSymbols() {
@@ -643,6 +664,17 @@ void Writer::fixSafeSEHSymbols() {
Config->SEHCount->setVA(SEHTable->getSize() / 4);
}
+// Handles /section options to allow users to overwrite
+// section attributes.
+void Writer::setSectionPermissions() {
+ for (auto &P : Config->Section) {
+ StringRef Name = P.first;
+ uint32_t Perm = P.second;
+ if (auto *Sec = findSection(Name))
+ Sec->setPermissions(Perm);
+ }
+}
+
// Write section contents to a mmap'ed file.
void Writer::writeSections() {
uint8_t *Buf = Buffer->getBufferStart();
diff --git a/ELF/CMakeLists.txt b/ELF/CMakeLists.txt
index 3dcb65ff8957..a1b65adc7400 100644
--- a/ELF/CMakeLists.txt
+++ b/ELF/CMakeLists.txt
@@ -2,25 +2,49 @@ set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(ELFOptionsTableGen)
-add_lld_library(lldELF2
+add_lld_library(lldELF
Driver.cpp
DriverUtils.cpp
+ EhFrame.cpp
Error.cpp
+ ICF.cpp
InputFiles.cpp
InputSection.cpp
+ LTO.cpp
LinkerScript.cpp
MarkLive.cpp
OutputSections.cpp
+ Relocations.cpp
+ ScriptParser.cpp
+ Strings.cpp
+ SymbolListFile.cpp
SymbolTable.cpp
Symbols.cpp
Target.cpp
+ Thunks.cpp
Writer.cpp
LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Analysis
+ BitReader
+ BitWriter
+ Codegen
+ Core
+ IPO
+ Linker
+ LTO
Object
Option
+ Passes
MC
Support
+ Target
+ TransformUtils
+
+ LINK_LIBS
+ lldConfig
+ ${PTHREAD_LIB}
)
-add_dependencies(lldELF2 ELFOptionsTableGen)
+add_dependencies(lldELF intrinsics_gen ELFOptionsTableGen)
diff --git a/ELF/Config.h b/ELF/Config.h
index c279b99b43c1..2ccd95e88775 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -17,10 +17,10 @@
#include <vector>
namespace lld {
-namespace elf2 {
+namespace elf {
class InputFile;
-class SymbolBody;
+struct Symbol;
enum ELFKind {
ELFNoneKind,
@@ -30,60 +30,105 @@ enum ELFKind {
ELF64BEKind
};
+enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring };
+
+enum class UnresolvedPolicy { NoUndef, Error, Warn, Ignore };
+
+struct SymbolVersion {
+ llvm::StringRef Name;
+ bool IsExternCpp;
+};
+
+// This struct contains symbols version definition that
+// can be found in version script if it is used for link.
+struct VersionDefinition {
+ VersionDefinition(llvm::StringRef Name, size_t Id) : Name(Name), Id(Id) {}
+ llvm::StringRef Name;
+ size_t Id;
+ std::vector<SymbolVersion> Globals;
+ size_t NameOff; // Offset in string table.
+};
+
// This struct contains the global configuration for the linker.
// Most fields are direct mapping from the command line options
// and such fields have the same name as the corresponding options.
// Most fields are initialized by the driver.
struct Configuration {
- SymbolBody *EntrySym = nullptr;
- SymbolBody *MipsGpDisp = nullptr;
+ Symbol *EntrySym = nullptr;
InputFile *FirstElf = nullptr;
llvm::StringRef DynamicLinker;
llvm::StringRef Entry;
llvm::StringRef Emulation;
llvm::StringRef Fini;
llvm::StringRef Init;
+ llvm::StringRef LtoAAPipeline;
+ llvm::StringRef LtoNewPmPasses;
llvm::StringRef OutputFile;
llvm::StringRef SoName;
llvm::StringRef Sysroot;
std::string RPath;
- llvm::MapVector<llvm::StringRef, std::vector<llvm::StringRef>> OutputSections;
+ std::vector<VersionDefinition> VersionDefinitions;
+ std::vector<llvm::StringRef> DynamicList;
std::vector<llvm::StringRef> SearchPaths;
std::vector<llvm::StringRef> Undefined;
+ std::vector<SymbolVersion> VersionScriptGlobals;
+ std::vector<uint8_t> BuildIdVector;
bool AllowMultipleDefinition;
bool AsNeeded = false;
bool Bsymbolic;
+ bool BsymbolicFunctions;
+ bool Demangle = true;
+ bool DisableVerify;
bool DiscardAll;
bool DiscardLocals;
bool DiscardNone;
+ bool EhFrameHdr;
bool EnableNewDtags;
bool ExportDynamic;
+ bool FatalWarnings;
bool GcSections;
bool GnuHash = false;
+ bool ICF;
bool Mips64EL = false;
- bool NoInhibitExec;
- bool NoUndefined;
+ bool NoGnuUnique;
+ bool NoUndefinedVersion;
+ bool Pic;
+ bool Pie;
bool PrintGcSections;
+ bool Rela;
+ bool Relocatable;
+ bool SaveTemps;
bool Shared;
bool Static = false;
bool StripAll;
+ bool StripDebug;
bool SysvHash = true;
+ bool Threads;
+ bool Trace;
bool Verbose;
+ bool WarnCommon;
+ bool ZCombreloc;
bool ZExecStack;
bool ZNodelete;
bool ZNow;
bool ZOrigin;
bool ZRelro;
+ UnresolvedPolicy UnresolvedSymbols;
+ BuildIdKind BuildId = BuildIdKind::None;
ELFKind EKind = ELFNoneKind;
+ uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
uint16_t EMachine = llvm::ELF::EM_NONE;
uint64_t EntryAddr = -1;
- unsigned Optimize = 0;
+ uint64_t ImageBase;
+ unsigned LtoJobs;
+ unsigned LtoO;
+ unsigned Optimize;
};
// The only instance of Configuration struct.
extern Configuration *Config;
-} // namespace elf2
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index f00d97851e4a..c6ca2639236f 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -10,119 +10,218 @@
#include "Driver.h"
#include "Config.h"
#include "Error.h"
+#include "ICF.h"
#include "InputFiles.h"
+#include "InputSection.h"
+#include "LinkerScript.h"
+#include "Strings.h"
+#include "SymbolListFile.h"
#include "SymbolTable.h"
#include "Target.h"
#include "Writer.h"
-#include "llvm/ADT/STLExtras.h"
+#include "lld/Driver/Driver.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
#include <utility>
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
+using namespace llvm::sys;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
-Configuration *elf2::Config;
-LinkerDriver *elf2::Driver;
+Configuration *elf::Config;
+LinkerDriver *elf::Driver;
+
+bool elf::link(ArrayRef<const char *> Args, raw_ostream &Error) {
+ HasError = false;
+ ErrorOS = &Error;
-void elf2::link(ArrayRef<const char *> Args) {
Configuration C;
LinkerDriver D;
+ ScriptConfiguration SC;
Config = &C;
Driver = &D;
- Driver->main(Args.slice(1));
+ ScriptConfig = &SC;
+
+ Driver->main(Args);
+ return !HasError;
}
+// Parses a linker -m option.
static std::pair<ELFKind, uint16_t> parseEmulation(StringRef S) {
- if (S == "elf32btsmip")
- return {ELF32BEKind, EM_MIPS};
- if (S == "elf32ltsmip")
- return {ELF32LEKind, EM_MIPS};
- if (S == "elf32ppc" || S == "elf32ppc_fbsd")
- return {ELF32BEKind, EM_PPC};
- if (S == "elf64ppc" || S == "elf64ppc_fbsd")
- return {ELF64BEKind, EM_PPC64};
- if (S == "elf_i386")
- return {ELF32LEKind, EM_386};
- if (S == "elf_x86_64")
- return {ELF64LEKind, EM_X86_64};
- if (S == "aarch64linux")
- return {ELF64LEKind, EM_AARCH64};
- if (S == "i386pe" || S == "i386pep" || S == "thumb2pe")
- error("Windows targets are not supported on the ELF frontend: " + S);
- error("Unknown emulation: " + S);
+ if (S.endswith("_fbsd"))
+ S = S.drop_back(5);
+
+ std::pair<ELFKind, uint16_t> Ret =
+ StringSwitch<std::pair<ELFKind, uint16_t>>(S)
+ .Case("aarch64linux", {ELF64LEKind, EM_AARCH64})
+ .Case("armelf_linux_eabi", {ELF32LEKind, EM_ARM})
+ .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64})
+ .Case("elf32btsmip", {ELF32BEKind, EM_MIPS})
+ .Case("elf32ltsmip", {ELF32LEKind, EM_MIPS})
+ .Case("elf32ppc", {ELF32BEKind, EM_PPC})
+ .Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
+ .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
+ .Case("elf64ppc", {ELF64BEKind, EM_PPC64})
+ .Case("elf_i386", {ELF32LEKind, EM_386})
+ .Case("elf_x86_64", {ELF64LEKind, EM_X86_64})
+ .Default({ELFNoneKind, EM_NONE});
+
+ if (Ret.first == ELFNoneKind) {
+ if (S == "i386pe" || S == "i386pep" || S == "thumb2pe")
+ error("Windows targets are not supported on the ELF frontend: " + S);
+ else
+ error("unknown emulation: " + S);
+ }
+ return Ret;
}
// Returns slices of MB by parsing MB as an archive file.
// Each slice consists of a member file in the archive.
-static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB) {
- ErrorOr<std::unique_ptr<Archive>> FileOrErr = Archive::create(MB);
- error(FileOrErr, "Failed to parse archive");
- std::unique_ptr<Archive> File = std::move(*FileOrErr);
+std::vector<MemoryBufferRef>
+LinkerDriver::getArchiveMembers(MemoryBufferRef MB) {
+ std::unique_ptr<Archive> File =
+ check(Archive::create(MB), "failed to parse archive");
std::vector<MemoryBufferRef> V;
- for (const ErrorOr<Archive::Child> &C : File->children()) {
- error(C, "Could not get the child of the archive " + File->getFileName());
- ErrorOr<MemoryBufferRef> MbOrErr = C->getMemoryBufferRef();
- error(MbOrErr, "Could not get the buffer for a child of the archive " +
- File->getFileName());
- V.push_back(*MbOrErr);
+ Error Err;
+ for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {
+ Archive::Child C = check(COrErr, "could not get the child of the archive " +
+ File->getFileName());
+ MemoryBufferRef MBRef =
+ check(C.getMemoryBufferRef(),
+ "could not get the buffer for a child of the archive " +
+ File->getFileName());
+ V.push_back(MBRef);
}
+ if (Err)
+ Error(Err);
+
+ // Take ownership of memory buffers created for members of thin archives.
+ for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers())
+ OwningMBs.push_back(std::move(MB));
+
return V;
}
// Opens and parses a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
void LinkerDriver::addFile(StringRef Path) {
- using namespace llvm::sys::fs;
+ using namespace sys::fs;
if (Config->Verbose)
- llvm::outs() << Path << "\n";
- auto MBOrErr = MemoryBuffer::getFile(Path);
- error(MBOrErr, "cannot open " + Path);
- std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
- MemoryBufferRef MBRef = MB->getMemBufferRef();
- OwningMBs.push_back(std::move(MB)); // take MB ownership
+ outs() << Path << "\n";
+
+ Optional<MemoryBufferRef> Buffer = readFile(Path);
+ if (!Buffer.hasValue())
+ return;
+ MemoryBufferRef MBRef = *Buffer;
switch (identify_magic(MBRef.getBuffer())) {
case file_magic::unknown:
- readLinkerScript(&Alloc, MBRef);
+ readLinkerScript(MBRef);
return;
case file_magic::archive:
if (WholeArchive) {
for (MemoryBufferRef MB : getArchiveMembers(MBRef))
- Files.push_back(createObjectFile(MB));
+ Files.push_back(createObjectFile(MB, Path));
return;
}
Files.push_back(make_unique<ArchiveFile>(MBRef));
return;
case file_magic::elf_shared_object:
+ if (Config->Relocatable) {
+ error("attempted static link of dynamic object " + Path);
+ return;
+ }
Files.push_back(createSharedFile(MBRef));
return;
default:
- Files.push_back(createObjectFile(MBRef));
+ if (InLib)
+ Files.push_back(make_unique<LazyObjectFile>(MBRef));
+ else
+ Files.push_back(createObjectFile(MBRef));
+ }
+}
+
+Optional<MemoryBufferRef> LinkerDriver::readFile(StringRef Path) {
+ auto MBOrErr = MemoryBuffer::getFile(Path);
+ if (auto EC = MBOrErr.getError()) {
+ error(EC, "cannot open " + Path);
+ return None;
}
+ std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
+ MemoryBufferRef MBRef = MB->getMemBufferRef();
+ OwningMBs.push_back(std::move(MB)); // take MB ownership
+
+ if (Cpio)
+ Cpio->append(relativeToRoot(Path), MBRef.getBuffer());
+
+ return MBRef;
+}
+
+// Add a given library by searching it from input search paths.
+void LinkerDriver::addLibrary(StringRef Name) {
+ std::string Path = searchLibrary(Name);
+ if (Path.empty())
+ error("unable to find library -l" + Name);
+ else
+ addFile(Path);
+}
+
+// This function is called on startup. We need this for LTO since
+// LTO calls LLVM functions to compile bitcode files to native code.
+// Technically this can be delayed until we read bitcode files, but
+// we don't bother to do lazily because the initialization is fast.
+static void initLLVM(opt::InputArgList &Args) {
+ InitializeAllTargets();
+ InitializeAllTargetMCs();
+ InitializeAllAsmPrinters();
+ InitializeAllAsmParsers();
+
+ // This is a flag to discard all but GlobalValue names.
+ // We want to enable it by default because it saves memory.
+ // Disable it only when a developer option (-save-temps) is given.
+ Driver->Context.setDiscardValueNames(!Config->SaveTemps);
+ Driver->Context.enableDebugTypeODRUniquing();
+
+ // Parse and evaluate -mllvm options.
+ std::vector<const char *> V;
+ V.push_back("lld (LLVM option parsing)");
+ for (auto *Arg : Args.filtered(OPT_mllvm))
+ V.push_back(Arg->getValue());
+ cl::ParseCommandLineOptions(V.size(), V.data());
}
// Some command line options or some combinations of them are not allowed.
// This function checks for such errors.
static void checkOptions(opt::InputArgList &Args) {
- // Traditional linkers can generate re-linkable object files instead
- // of executables or DSOs. We don't support that since the feature
- // does not seem to provide more value than the static archiver.
- if (Args.hasArg(OPT_relocatable))
- error("-r option is not supported. Use 'ar' command instead.");
-
// The MIPS ABI as of 2016 does not support the GNU-style symbol lookup
// table which is a relatively new feature.
if (Config->EMachine == EM_MIPS && Config->GnuHash)
- error("The .gnu.hash section is not compatible with the MIPS target.");
+ error("the .gnu.hash section is not compatible with the MIPS target.");
if (Config->EMachine == EM_AMDGPU && !Config->Entry.empty())
error("-e option is not valid for AMDGPU.");
+
+ if (Config->Pie && Config->Shared)
+ error("-shared and -pie may not be used together");
+
+ if (Config->Relocatable) {
+ if (Config->Shared)
+ error("-r and -shared may not be used together");
+ if (Config->GcSections)
+ error("-r and --gc-sections may not be used together");
+ if (Config->ICF)
+ error("-r and --icf may not be used together");
+ if (Config->Pie)
+ error("-r and -pie may not be used together");
+ }
}
static StringRef
@@ -132,6 +231,22 @@ getString(opt::InputArgList &Args, unsigned Key, StringRef Default = "") {
return Default;
}
+static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) {
+ int V = Default;
+ if (auto *Arg = Args.getLastArg(Key)) {
+ StringRef S = Arg->getValue();
+ if (S.getAsInteger(10, V))
+ error(Arg->getSpelling() + ": number expected, but got " + S);
+ }
+ return V;
+}
+
+static const char *getReproduceOption(opt::InputArgList &Args) {
+ if (auto *Arg = Args.getLastArg(OPT_reproduce))
+ return Arg->getValue();
+ return getenv("LLD_REPRODUCE");
+}
+
static bool hasZOption(opt::InputArgList &Args, StringRef Key) {
for (auto *Arg : Args.filtered(OPT_z))
if (Key == Arg->getValue())
@@ -140,12 +255,33 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) {
}
void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
- initSymbols();
+ ELFOptTable Parser;
+ opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
+ if (Args.hasArg(OPT_help)) {
+ printHelp(ArgsArr[0]);
+ return;
+ }
+ if (Args.hasArg(OPT_version)) {
+ outs() << getVersionString();
+ return;
+ }
+
+ if (const char *Path = getReproduceOption(Args)) {
+ // Note that --reproduce is a debug option so you can ignore it
+ // if you are trying to understand the whole picture of the code.
+ Cpio.reset(CpioFile::create(Path));
+ if (Cpio) {
+ Cpio->append("response.txt", createResponseFile(Args));
+ Cpio->append("version.txt", getVersionString());
+ }
+ }
- opt::InputArgList Args = parseArgs(&Alloc, ArgsArr);
readConfigs(Args);
+ initLLVM(Args);
createFiles(Args);
checkOptions(Args);
+ if (HasError)
+ return;
switch (Config->EKind) {
case ELF32LEKind:
@@ -165,6 +301,25 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
}
}
+static UnresolvedPolicy getUnresolvedSymbolOption(opt::InputArgList &Args) {
+ if (Args.hasArg(OPT_noinhibit_exec))
+ return UnresolvedPolicy::Warn;
+ if (Args.hasArg(OPT_no_undefined) || hasZOption(Args, "defs"))
+ return UnresolvedPolicy::NoUndef;
+ if (Config->Relocatable)
+ return UnresolvedPolicy::Ignore;
+
+ if (auto *Arg = Args.getLastArg(OPT_unresolved_symbols)) {
+ StringRef S = Arg->getValue();
+ if (S == "ignore-all" || S == "ignore-in-object-files")
+ return UnresolvedPolicy::Ignore;
+ if (S == "ignore-in-shared-libs" || S == "report-all")
+ return UnresolvedPolicy::Error;
+ error("unknown --unresolved-symbols value: " + S);
+ }
+ return UnresolvedPolicy::Error;
+}
+
// Initializes Config members by the command line options.
void LinkerDriver::readConfigs(opt::InputArgList &Args) {
for (auto *Arg : Args.filtered(OPT_L))
@@ -185,38 +340,66 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
+ Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
+ Config->Demangle = !Args.hasArg(OPT_no_demangle);
+ Config->DisableVerify = Args.hasArg(OPT_disable_verify);
Config->DiscardAll = Args.hasArg(OPT_discard_all);
Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
Config->DiscardNone = Args.hasArg(OPT_discard_none);
+ Config->EhFrameHdr = Args.hasArg(OPT_eh_frame_hdr);
Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags);
Config->ExportDynamic = Args.hasArg(OPT_export_dynamic);
+ Config->FatalWarnings = Args.hasArg(OPT_fatal_warnings);
Config->GcSections = Args.hasArg(OPT_gc_sections);
- Config->NoInhibitExec = Args.hasArg(OPT_noinhibit_exec);
- Config->NoUndefined = Args.hasArg(OPT_no_undefined);
+ Config->ICF = Args.hasArg(OPT_icf);
+ Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique);
+ Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version);
+ Config->Pie = Args.hasArg(OPT_pie);
Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections);
+ Config->Relocatable = Args.hasArg(OPT_relocatable);
+ Config->SaveTemps = Args.hasArg(OPT_save_temps);
Config->Shared = Args.hasArg(OPT_shared);
Config->StripAll = Args.hasArg(OPT_strip_all);
+ Config->StripDebug = Args.hasArg(OPT_strip_debug);
+ Config->Threads = Args.hasArg(OPT_threads);
+ Config->Trace = Args.hasArg(OPT_trace);
Config->Verbose = Args.hasArg(OPT_verbose);
+ Config->WarnCommon = Args.hasArg(OPT_warn_common);
Config->DynamicLinker = getString(Args, OPT_dynamic_linker);
Config->Entry = getString(Args, OPT_entry);
Config->Fini = getString(Args, OPT_fini, "_fini");
Config->Init = getString(Args, OPT_init, "_init");
+ Config->LtoAAPipeline = getString(Args, OPT_lto_aa_pipeline);
+ Config->LtoNewPmPasses = getString(Args, OPT_lto_newpm_passes);
Config->OutputFile = getString(Args, OPT_o);
Config->SoName = getString(Args, OPT_soname);
Config->Sysroot = getString(Args, OPT_sysroot);
+ Config->Optimize = getInteger(Args, OPT_O, 1);
+ Config->LtoO = getInteger(Args, OPT_lto_O, 2);
+ if (Config->LtoO > 3)
+ error("invalid optimization level for LTO: " + getString(Args, OPT_lto_O));
+ Config->LtoJobs = getInteger(Args, OPT_lto_jobs, 1);
+ if (Config->LtoJobs == 0)
+ error("number of threads must be > 0");
+
+ Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
Config->ZExecStack = hasZOption(Args, "execstack");
Config->ZNodelete = hasZOption(Args, "nodelete");
Config->ZNow = hasZOption(Args, "now");
Config->ZOrigin = hasZOption(Args, "origin");
Config->ZRelro = !hasZOption(Args, "norelro");
- if (auto *Arg = Args.getLastArg(OPT_O)) {
- StringRef Val = Arg->getValue();
- if (Val.getAsInteger(10, Config->Optimize))
- error("Invalid optimization level");
- }
+ if (Config->Relocatable)
+ Config->StripAll = false;
+
+ // --strip-all implies --strip-debug.
+ if (Config->StripAll)
+ Config->StripDebug = true;
+
+ // Config->Pic is true if we are generating position-independent code.
+ Config->Pic = Config->Pie || Config->Shared;
if (auto *Arg = Args.getLastArg(OPT_hash_style)) {
StringRef S = Arg->getValue();
@@ -226,19 +409,52 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
} else if (S == "both") {
Config->GnuHash = true;
} else if (S != "sysv")
- error("Unknown hash style: " + S);
+ error("unknown hash style: " + S);
+ }
+
+ // Parse --build-id or --build-id=<style>.
+ if (Args.hasArg(OPT_build_id))
+ Config->BuildId = BuildIdKind::Fnv1;
+ if (auto *Arg = Args.getLastArg(OPT_build_id_eq)) {
+ StringRef S = Arg->getValue();
+ if (S == "md5") {
+ Config->BuildId = BuildIdKind::Md5;
+ } else if (S == "sha1") {
+ Config->BuildId = BuildIdKind::Sha1;
+ } else if (S == "none") {
+ Config->BuildId = BuildIdKind::None;
+ } else if (S.startswith("0x")) {
+ Config->BuildId = BuildIdKind::Hexstring;
+ Config->BuildIdVector = parseHex(S.substr(2));
+ } else {
+ error("unknown --build-id style: " + S);
+ }
}
for (auto *Arg : Args.filtered(OPT_undefined))
Config->Undefined.push_back(Arg->getValue());
+
+ Config->UnresolvedSymbols = getUnresolvedSymbolOption(Args);
+
+ if (auto *Arg = Args.getLastArg(OPT_dynamic_list))
+ if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
+ parseDynamicList(*Buffer);
+
+ for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))
+ Config->DynamicList.push_back(Arg->getValue());
+
+ if (auto *Arg = Args.getLastArg(OPT_version_script))
+ if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
+ parseVersionScript(*Buffer);
}
void LinkerDriver::createFiles(opt::InputArgList &Args) {
for (auto *Arg : Args) {
switch (Arg->getOption().getID()) {
case OPT_l:
- addFile(searchLibrary(Arg->getValue()));
+ addLibrary(Arg->getValue());
break;
+ case OPT_alias_script_T:
case OPT_INPUT:
case OPT_script:
addFile(Arg->getValue());
@@ -261,75 +477,112 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
case OPT_no_whole_archive:
WholeArchive = false;
break;
+ case OPT_start_lib:
+ InLib = true;
+ break;
+ case OPT_end_lib:
+ InLib = false;
+ break;
}
}
- if (Files.empty())
+ if (Files.empty() && !HasError)
error("no input files.");
+
+ // If -m <machine_type> was not given, infer it from object files.
+ if (Config->EKind == ELFNoneKind) {
+ for (std::unique_ptr<InputFile> &F : Files) {
+ if (F->EKind == ELFNoneKind)
+ continue;
+ Config->EKind = F->EKind;
+ Config->EMachine = F->EMachine;
+ break;
+ }
+ }
}
+// Do actual linking. Note that when this function is called,
+// all linker scripts have already been parsed.
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
SymbolTable<ELFT> Symtab;
- Target.reset(createTarget());
-
- if (!Config->Shared) {
- // Add entry symbol.
- //
- // There is no entry symbol for AMDGPU binaries, so skip adding one to avoid
- // having and undefined symbol.
- if (Config->Entry.empty() && Config->EMachine != EM_AMDGPU)
- Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
-
- // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
- // is magical and is used to produce a R_386_GOTPC relocation.
- // The R_386_GOTPC relocation value doesn't actually depend on the
- // symbol value, so it could use an index of STN_UNDEF which, according
- // to the spec, means the symbol value is 0.
- // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in
- // the object file.
- // The situation is even stranger on x86_64 where the assembly doesn't
- // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as
- // an undefined symbol in the .o files.
- // Given that the symbol is effectively unused, we just create a dummy
- // hidden one to avoid the undefined symbol error.
- Symtab.addIgnored("_GLOBAL_OFFSET_TABLE_");
- }
+ elf::Symtab<ELFT>::X = &Symtab;
+
+ std::unique_ptr<TargetInfo> TI(createTarget());
+ Target = TI.get();
+ LinkerScript<ELFT> LS;
+ Script<ELFT>::X = &LS;
+
+ Config->Rela = ELFT::Is64Bits || Config->EMachine == EM_X86_64;
+ Config->Mips64EL =
+ (Config->EMachine == EM_MIPS && Config->EKind == ELF64LEKind);
+
+ // Add entry symbol. Note that AMDGPU binaries have no entry points.
+ if (Config->Entry.empty() && !Config->Shared && !Config->Relocatable &&
+ Config->EMachine != EM_AMDGPU)
+ Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
+
+ // Default output filename is "a.out" by the Unix tradition.
+ if (Config->OutputFile.empty())
+ Config->OutputFile = "a.out";
+
+ // Handle --trace-symbol.
+ for (auto *Arg : Args.filtered(OPT_trace_symbol))
+ Symtab.trace(Arg->getValue());
+ // Set either EntryAddr (if S is a number) or EntrySym (otherwise).
if (!Config->Entry.empty()) {
- // Set either EntryAddr (if S is a number) or EntrySym (otherwise).
StringRef S = Config->Entry;
if (S.getAsInteger(0, Config->EntryAddr))
Config->EntrySym = Symtab.addUndefined(S);
}
- if (Config->EMachine == EM_MIPS) {
- // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
- // start of function and gp pointer into GOT. Use 'strong' variant of
- // the addIgnored to prevent '_gp_disp' substitution.
- Config->MipsGpDisp = Symtab.addIgnoredStrong("_gp_disp");
-
- // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
- // so that it points to an absolute address which is relative to GOT.
- // See "Global Data Symbols" in Chapter 6 in the following document:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- Symtab.addAbsolute("_gp", ElfSym<ELFT>::MipsGp);
+ // Initialize Config->ImageBase.
+ if (auto *Arg = Args.getLastArg(OPT_image_base)) {
+ StringRef S = Arg->getValue();
+ if (S.getAsInteger(0, Config->ImageBase))
+ error(Arg->getSpelling() + ": number expected, but got " + S);
+ else if ((Config->ImageBase % Target->PageSize) != 0)
+ warning(Arg->getSpelling() + ": address isn't multiple of page size");
+ } else {
+ Config->ImageBase = Config->Pic ? 0 : Target->DefaultImageBase;
}
for (std::unique_ptr<InputFile> &F : Files)
Symtab.addFile(std::move(F));
+ if (HasError)
+ return; // There were duplicate symbols or incompatible files
- for (StringRef S : Config->Undefined)
- Symtab.addUndefinedOpt(S);
+ Symtab.scanUndefinedFlags();
+ Symtab.scanShlibUndefined();
+ Symtab.scanDynamicList();
+ Symtab.scanVersionScript();
+ Symtab.scanSymbolVersions();
+
+ Symtab.addCombinedLtoObject();
+ if (HasError)
+ return;
for (auto *Arg : Args.filtered(OPT_wrap))
Symtab.wrap(Arg->getValue());
- if (Config->OutputFile.empty())
- Config->OutputFile = "a.out";
-
// Write the result to the file.
- Symtab.scanShlibUndefined();
if (Config->GcSections)
- markLive<ELFT>(&Symtab);
+ markLive<ELFT>();
+ if (Config->ICF)
+ doIcf<ELFT>();
+
+ // MergeInputSection::splitIntoPieces needs to be called before
+ // any call of MergeInputSection::getOffset. Do that.
+ for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
+ Symtab.getObjectFiles())
+ for (InputSectionBase<ELFT> *S : F->getSections()) {
+ if (!S || S == &InputSection<ELFT>::Discarded || !S->Live)
+ continue;
+ if (S->Compressed)
+ S->uncompress();
+ if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S))
+ MS->splitIntoPieces();
+ }
+
writeResult<ELFT>(&Symtab);
}
diff --git a/ELF/Driver.h b/ELF/Driver.h
index 720ef46dc710..6b9b9bb208e5 100644
--- a/ELF/Driver.h
+++ b/ELF/Driver.h
@@ -12,36 +12,54 @@
#include "SymbolTable.h"
#include "lld/Core/LLVM.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/raw_ostream.h"
namespace lld {
-namespace elf2 {
+namespace elf {
extern class LinkerDriver *Driver;
-// Entry point of the ELF linker.
-void link(ArrayRef<const char *> Args);
+class CpioFile;
class LinkerDriver {
public:
void main(ArrayRef<const char *> Args);
void addFile(StringRef Path);
+ void addLibrary(StringRef Name);
+ llvm::LLVMContext Context; // to parse bitcode ifles
+ std::unique_ptr<CpioFile> Cpio; // for reproduce
private:
+ std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
+ llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
void readConfigs(llvm::opt::InputArgList &Args);
void createFiles(llvm::opt::InputArgList &Args);
template <class ELFT> void link(llvm::opt::InputArgList &Args);
- llvm::BumpPtrAllocator Alloc;
+ // True if we are in --whole-archive and --no-whole-archive.
bool WholeArchive = false;
+
+ // True if we are in --start-lib and --end-lib.
+ bool InLib = false;
+
+ llvm::BumpPtrAllocator Alloc;
std::vector<std::unique_ptr<InputFile>> Files;
std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
};
// Parses command line options.
-llvm::opt::InputArgList parseArgs(llvm::BumpPtrAllocator *A,
- ArrayRef<const char *> Args);
+class ELFOptTable : public llvm::opt::OptTable {
+public:
+ ELFOptTable();
+ llvm::opt::InputArgList parse(ArrayRef<const char *> Argv);
+
+private:
+ llvm::BumpPtrAllocator Alloc;
+};
// Create enum with OPT_xxx values for each option in Options.td
enum {
@@ -51,14 +69,43 @@ enum {
#undef OPTION
};
-// Parses a linker script. Calling this function updates the Symtab and Config.
-void readLinkerScript(llvm::BumpPtrAllocator *A, MemoryBufferRef MB);
+// This is the class to create a .cpio file for --reproduce.
+//
+// If "--reproduce foo" is given, we create a file "foo.cpio" and
+// copy all input files to the archive, along with a response file
+// to re-run the same command with the same inputs.
+// It is useful for reporting issues to LLD developers.
+//
+// Cpio as a file format is a deliberate choice. It's standardized in
+// POSIX and very easy to create. cpio command is available virtually
+// on all Unix systems. See
+// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_07
+// for the format details.
+class CpioFile {
+public:
+ static CpioFile *create(StringRef OutputPath);
+ void append(StringRef Path, StringRef Data);
+
+private:
+ CpioFile(std::unique_ptr<llvm::raw_fd_ostream> OS, StringRef Basename);
+
+ std::unique_ptr<llvm::raw_fd_ostream> OS;
+ llvm::StringSet<> Seen;
+ std::string Basename;
+};
+
+void printHelp(const char *Argv0);
+std::string getVersionString();
+std::vector<uint8_t> parseHexstring(StringRef S);
+
+std::string createResponseFile(const llvm::opt::InputArgList &Args);
+std::string relativeToRoot(StringRef Path);
std::string findFromSearchPaths(StringRef Path);
std::string searchLibrary(StringRef Path);
std::string buildSysrootedPath(llvm::StringRef Dir, llvm::StringRef File);
-} // namespace elf2
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/DriverUtils.cpp b/ELF/DriverUtils.cpp
index 965ed4f00a61..3f18259b4ae7 100644
--- a/ELF/DriverUtils.cpp
+++ b/ELF/DriverUtils.cpp
@@ -15,16 +15,20 @@
#include "Driver.h"
#include "Error.h"
+#include "lld/Config/Version.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
using namespace llvm;
+using namespace llvm::sys;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
// Create OptTable
@@ -34,55 +38,208 @@ using namespace lld::elf2;
#undef PREFIX
// Create table mapping all options defined in Options.td
-static const opt::OptTable::Info infoTable[] = {
+static const opt::OptTable::Info OptInfo[] = {
#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
{ \
X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, X8, X7, OPT_##GROUP, \
OPT_##ALIAS, X6 \
- } \
- ,
+ },
#include "Options.inc"
#undef OPTION
};
-class ELFOptTable : public opt::OptTable {
-public:
- ELFOptTable() : OptTable(infoTable) {}
-};
+ELFOptTable::ELFOptTable() : OptTable(OptInfo) {}
+
+static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
+ if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) {
+ StringRef S = Arg->getValue();
+ if (S != "windows" && S != "posix")
+ error("invalid response file quoting: " + S);
+ if (S == "windows")
+ return cl::TokenizeWindowsCommandLine;
+ return cl::TokenizeGNUCommandLine;
+ }
+ if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32)
+ return cl::TokenizeWindowsCommandLine;
+ return cl::TokenizeGNUCommandLine;
+}
// Parses a given list of options.
-opt::InputArgList elf2::parseArgs(llvm::BumpPtrAllocator *A,
- ArrayRef<const char *> Argv) {
+opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {
// Make InputArgList from string vectors.
- ELFOptTable Table;
unsigned MissingIndex;
unsigned MissingCount;
+ SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
+
+ // We need to get the quoting style for response files before parsing all
+ // options so we parse here before and ignore all the options but
+ // --rsp-quoting.
+ opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
// Expand response files. '@<filename>' is replaced by the file's contents.
- SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
- StringSaver Saver(*A);
- llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, Vec);
+ StringSaver Saver(Alloc);
+ cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
// Parse options and then do error checking.
- opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
+ Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
if (MissingCount)
error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
"\", expected " + Twine(MissingCount) +
(MissingCount == 1 ? " argument.\n" : " arguments"));
- iterator_range<opt::arg_iterator> Unknowns = Args.filtered(OPT_UNKNOWN);
- for (auto *Arg : Unknowns)
- warning("warning: unknown argument: " + Arg->getSpelling());
- if (Unknowns.begin() != Unknowns.end())
- error("unknown argument(s) found");
-
+ for (auto *Arg : Args.filtered(OPT_UNKNOWN))
+ error("unknown argument: " + Arg->getSpelling());
return Args;
}
-std::string elf2::findFromSearchPaths(StringRef Path) {
+void elf::printHelp(const char *Argv0) {
+ ELFOptTable Table;
+ Table.PrintHelp(outs(), Argv0, "lld", false);
+}
+
+std::string elf::getVersionString() {
+ std::string Version = getLLDVersion();
+ std::string Repo = getLLDRepositoryVersion();
+ if (Repo.empty())
+ return "LLD " + Version + "\n";
+ return "LLD " + Version + " " + Repo + "\n";
+}
+
+// Makes a given pathname an absolute path first, and then remove
+// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
+// assuming that the current directory is "/home/john/bar".
+std::string elf::relativeToRoot(StringRef Path) {
+ SmallString<128> Abs = Path;
+ if (std::error_code EC = fs::make_absolute(Abs))
+ fatal("make_absolute failed: " + EC.message());
+ path::remove_dots(Abs, /*remove_dot_dot=*/true);
+
+ // This is Windows specific. root_name() returns a drive letter
+ // (e.g. "c:") or a UNC name (//net). We want to keep it as part
+ // of the result.
+ SmallString<128> Res;
+ StringRef Root = path::root_name(Abs);
+ if (Root.endswith(":"))
+ Res = Root.drop_back();
+ else if (Root.startswith("//"))
+ Res = Root.substr(2);
+
+ path::append(Res, path::relative_path(Abs));
+ return Res.str();
+}
+
+CpioFile::CpioFile(std::unique_ptr<raw_fd_ostream> OS, StringRef S)
+ : OS(std::move(OS)), Basename(S) {}
+
+CpioFile *CpioFile::create(StringRef OutputPath) {
+ std::string Path = (OutputPath + ".cpio").str();
+ std::error_code EC;
+ auto OS = llvm::make_unique<raw_fd_ostream>(Path, EC, fs::F_None);
+ if (EC) {
+ error(EC, "--reproduce: failed to open " + Path);
+ return nullptr;
+ }
+ return new CpioFile(std::move(OS), path::filename(OutputPath));
+}
+
+static void writeMember(raw_fd_ostream &OS, StringRef Path, StringRef Data) {
+ // The c_dev/c_ino pair should be unique according to the spec,
+ // but no one seems to care.
+ OS << "070707"; // c_magic
+ OS << "000000"; // c_dev
+ OS << "000000"; // c_ino
+ OS << "100664"; // c_mode: C_ISREG | rw-rw-r--
+ OS << "000000"; // c_uid
+ OS << "000000"; // c_gid
+ OS << "000001"; // c_nlink
+ OS << "000000"; // c_rdev
+ OS << "00000000000"; // c_mtime
+ OS << format("%06o", Path.size() + 1); // c_namesize
+ OS << format("%011o", Data.size()); // c_filesize
+ OS << Path << '\0'; // c_name
+ OS << Data; // c_filedata
+}
+
+void CpioFile::append(StringRef Path, StringRef Data) {
+ if (!Seen.insert(Path).second)
+ return;
+
+ // Construct an in-archive filename so that /home/foo/bar is stored
+ // as baz/home/foo/bar where baz is the basename of the output file.
+ // (i.e. in that case we are creating baz.cpio.)
+ SmallString<128> Fullpath;
+ path::append(Fullpath, Basename, Path);
+
+ // Use unix path separators so the cpio can be extracted on both unix and
+ // windows.
+ std::replace(Fullpath.begin(), Fullpath.end(), '\\', '/');
+
+ writeMember(*OS, Fullpath, Data);
+
+ // Print the trailer and seek back.
+ // This way we have a valid archive if we crash.
+ uint64_t Pos = OS->tell();
+ writeMember(*OS, "TRAILER!!!", "");
+ OS->seek(Pos);
+}
+
+// Quote a given string if it contains a space character.
+static std::string quote(StringRef S) {
+ if (S.find(' ') == StringRef::npos)
+ return S;
+ return ("\"" + S + "\"").str();
+}
+
+static std::string rewritePath(StringRef S) {
+ if (fs::exists(S))
+ return relativeToRoot(S);
+ return S;
+}
+
+static std::string stringize(opt::Arg *Arg) {
+ std::string K = Arg->getSpelling();
+ if (Arg->getNumValues() == 0)
+ return K;
+ std::string V = quote(Arg->getValue());
+ if (Arg->getOption().getRenderStyle() == opt::Option::RenderJoinedStyle)
+ return K + V;
+ return K + " " + V;
+}
+
+// Reconstructs command line arguments so that so that you can re-run
+// the same command with the same inputs. This is for --reproduce.
+std::string elf::createResponseFile(const opt::InputArgList &Args) {
+ SmallString<0> Data;
+ raw_svector_ostream OS(Data);
+
+ // Copy the command line to the output while rewriting paths.
+ for (auto *Arg : Args) {
+ switch (Arg->getOption().getID()) {
+ case OPT_reproduce:
+ break;
+ case OPT_INPUT:
+ OS << quote(rewritePath(Arg->getValue())) << "\n";
+ break;
+ case OPT_L:
+ case OPT_dynamic_list:
+ case OPT_rpath:
+ case OPT_alias_script_T:
+ case OPT_script:
+ case OPT_version_script:
+ OS << Arg->getSpelling() << " "
+ << quote(rewritePath(Arg->getValue())) << "\n";
+ break;
+ default:
+ OS << stringize(Arg) << "\n";
+ }
+ }
+ return Data.str();
+}
+
+std::string elf::findFromSearchPaths(StringRef Path) {
for (StringRef Dir : Config->SearchPaths) {
std::string FullPath = buildSysrootedPath(Dir, Path);
- if (sys::fs::exists(FullPath))
+ if (fs::exists(FullPath))
return FullPath;
}
return "";
@@ -90,31 +247,30 @@ std::string elf2::findFromSearchPaths(StringRef Path) {
// Searches a given library from input search paths, which are filled
// from -L command line switches. Returns a path to an existent library file.
-std::string elf2::searchLibrary(StringRef Path) {
- std::vector<std::string> Names;
- if (Path[0] == ':') {
- Names.push_back(Path.drop_front());
- } else {
- if (!Config->Static)
- Names.push_back(("lib" + Path + ".so").str());
- Names.push_back(("lib" + Path + ".a").str());
- }
- for (const std::string &Name : Names) {
- std::string S = findFromSearchPaths(Name);
- if (!S.empty())
+std::string elf::searchLibrary(StringRef Path) {
+ if (Path.startswith(":"))
+ return findFromSearchPaths(Path.substr(1));
+ for (StringRef Dir : Config->SearchPaths) {
+ if (!Config->Static) {
+ std::string S = buildSysrootedPath(Dir, ("lib" + Path + ".so").str());
+ if (fs::exists(S))
+ return S;
+ }
+ std::string S = buildSysrootedPath(Dir, ("lib" + Path + ".a").str());
+ if (fs::exists(S))
return S;
}
- error("Unable to find library -l" + Path);
+ return "";
}
// Makes a path by concatenating Dir and File.
// If Dir starts with '=' the result will be preceded by Sysroot,
// which can be set with --sysroot command line switch.
-std::string elf2::buildSysrootedPath(StringRef Dir, StringRef File) {
+std::string elf::buildSysrootedPath(StringRef Dir, StringRef File) {
SmallString<128> Path;
if (Dir.startswith("="))
- sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
+ path::append(Path, Config->Sysroot, Dir.substr(1), File);
else
- sys::path::append(Path, Dir, File);
+ path::append(Path, Dir, File);
return Path.str();
}
diff --git a/ELF/EhFrame.cpp b/ELF/EhFrame.cpp
new file mode 100644
index 000000000000..b130ac1ca22d
--- /dev/null
+++ b/ELF/EhFrame.cpp
@@ -0,0 +1,167 @@
+//===- EhFrame.cpp -------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// .eh_frame section contains information on how to unwind the stack when
+// an exception is thrown. The section consists of sequence of CIE and FDE
+// records. The linker needs to merge CIEs and associate FDEs to CIEs.
+// That means the linker has to understand the format of the section.
+//
+// This file contains a few utility functions to read .eh_frame contents.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EhFrame.h"
+#include "Error.h"
+
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::dwarf;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+
+namespace lld {
+namespace elf {
+
+// .eh_frame section is a sequence of records. Each record starts with
+// a 4 byte length field. This function reads the length.
+template <class ELFT> size_t readEhRecordSize(ArrayRef<uint8_t> D) {
+ const endianness E = ELFT::TargetEndianness;
+ if (D.size() < 4)
+ fatal("CIE/FDE too small");
+
+ // First 4 bytes of CIE/FDE is the size of the record.
+ // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,
+ // but we do not support that format yet.
+ uint64_t V = read32<E>(D.data());
+ if (V == UINT32_MAX)
+ fatal("CIE/FDE too large");
+ uint64_t Size = V + 4;
+ if (Size > D.size())
+ fatal("CIE/FIE ends past the end of the section");
+ return Size;
+}
+
+// Read a byte and advance D by one byte.
+static uint8_t readByte(ArrayRef<uint8_t> &D) {
+ if (D.empty())
+ fatal("corrupted or unsupported CIE information");
+ uint8_t B = D.front();
+ D = D.slice(1);
+ return B;
+}
+
+// Skip an integer encoded in the LEB128 format.
+// Actual number is not of interest because only the runtime needs it.
+// But we need to be at least able to skip it so that we can read
+// the field that follows a LEB128 number.
+static void skipLeb128(ArrayRef<uint8_t> &D) {
+ while (!D.empty()) {
+ uint8_t Val = D.front();
+ D = D.slice(1);
+ if ((Val & 0x80) == 0)
+ return;
+ }
+ fatal("corrupted or unsupported CIE information");
+}
+
+template <class ELFT> static size_t getAugPSize(unsigned Enc) {
+ switch (Enc & 0x0f) {
+ case DW_EH_PE_absptr:
+ case DW_EH_PE_signed:
+ return ELFT::Is64Bits ? 8 : 4;
+ case DW_EH_PE_udata2:
+ case DW_EH_PE_sdata2:
+ return 2;
+ case DW_EH_PE_udata4:
+ case DW_EH_PE_sdata4:
+ return 4;
+ case DW_EH_PE_udata8:
+ case DW_EH_PE_sdata8:
+ return 8;
+ }
+ fatal("unknown FDE encoding");
+}
+
+template <class ELFT> static void skipAugP(ArrayRef<uint8_t> &D) {
+ uint8_t Enc = readByte(D);
+ if ((Enc & 0xf0) == DW_EH_PE_aligned)
+ fatal("DW_EH_PE_aligned encoding is not supported");
+ size_t Size = getAugPSize<ELFT>(Enc);
+ if (Size >= D.size())
+ fatal("corrupted CIE");
+ D = D.slice(Size);
+}
+
+template <class ELFT> uint8_t getFdeEncoding(ArrayRef<uint8_t> D) {
+ if (D.size() < 8)
+ fatal("CIE too small");
+ D = D.slice(8);
+
+ uint8_t Version = readByte(D);
+ if (Version != 1 && Version != 3)
+ fatal("FDE version 1 or 3 expected, but got " + Twine((unsigned)Version));
+
+ const unsigned char *AugEnd = std::find(D.begin(), D.end(), '\0');
+ if (AugEnd == D.end())
+ fatal("corrupted CIE");
+ StringRef Aug(reinterpret_cast<const char *>(D.begin()), AugEnd - D.begin());
+ D = D.slice(Aug.size() + 1);
+
+ // Code alignment factor should always be 1 for .eh_frame.
+ if (readByte(D) != 1)
+ fatal("CIE code alignment must be 1");
+
+ // Skip data alignment factor.
+ skipLeb128(D);
+
+ // Skip the return address register. In CIE version 1 this is a single
+ // byte. In CIE version 3 this is an unsigned LEB128.
+ if (Version == 1)
+ readByte(D);
+ else
+ skipLeb128(D);
+
+ // We only care about an 'R' value, but other records may precede an 'R'
+ // record. Unfortunately records are not in TLV (type-length-value) format,
+ // so we need to teach the linker how to skip records for each type.
+ for (char C : Aug) {
+ if (C == 'R')
+ return readByte(D);
+ if (C == 'z') {
+ skipLeb128(D);
+ continue;
+ }
+ if (C == 'P') {
+ skipAugP<ELFT>(D);
+ continue;
+ }
+ if (C == 'L') {
+ readByte(D);
+ continue;
+ }
+ fatal("unknown .eh_frame augmentation string: " + Aug);
+ }
+ return DW_EH_PE_absptr;
+}
+
+template size_t readEhRecordSize<ELF32LE>(ArrayRef<uint8_t>);
+template size_t readEhRecordSize<ELF32BE>(ArrayRef<uint8_t>);
+template size_t readEhRecordSize<ELF64LE>(ArrayRef<uint8_t>);
+template size_t readEhRecordSize<ELF64BE>(ArrayRef<uint8_t>);
+
+template uint8_t getFdeEncoding<ELF32LE>(ArrayRef<uint8_t>);
+template uint8_t getFdeEncoding<ELF32BE>(ArrayRef<uint8_t>);
+template uint8_t getFdeEncoding<ELF64LE>(ArrayRef<uint8_t>);
+template uint8_t getFdeEncoding<ELF64BE>(ArrayRef<uint8_t>);
+}
+}
diff --git a/ELF/EhFrame.h b/ELF/EhFrame.h
new file mode 100644
index 000000000000..0d5a2ff2f417
--- /dev/null
+++ b/ELF/EhFrame.h
@@ -0,0 +1,22 @@
+//===- EhFrame.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_EHFRAME_H
+#define LLD_ELF_EHFRAME_H
+
+#include "lld/Core/LLVM.h"
+
+namespace lld {
+namespace elf {
+template <class ELFT> size_t readEhRecordSize(ArrayRef<uint8_t> Data);
+template <class ELFT> uint8_t getFdeEncoding(ArrayRef<uint8_t> Data);
+}
+}
+
+#endif
diff --git a/ELF/Error.cpp b/ELF/Error.cpp
index e0701f7f4cc6..59a49c17b97c 100644
--- a/ELF/Error.cpp
+++ b/ELF/Error.cpp
@@ -8,31 +8,58 @@
//===----------------------------------------------------------------------===//
#include "Error.h"
+#include "Config.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
namespace lld {
-namespace elf2 {
+namespace elf {
+
+bool HasError;
+raw_ostream *ErrorOS;
-void warning(const Twine &Msg) { llvm::errs() << Msg << "\n"; }
+void log(const Twine &Msg) {
+ if (Config->Verbose)
+ outs() << Msg << "\n";
+}
+
+void warning(const Twine &Msg) {
+ if (Config->FatalWarnings)
+ error(Msg);
+ else
+ *ErrorOS << Msg << "\n";
+}
void error(const Twine &Msg) {
- llvm::errs() << Msg << "\n";
- exit(1);
+ *ErrorOS << Msg << "\n";
+ HasError = true;
}
void error(std::error_code EC, const Twine &Prefix) {
- if (!EC)
- return;
error(Prefix + ": " + EC.message());
}
-void error(std::error_code EC) {
- if (!EC)
- return;
- error(EC.message());
+void fatal(const Twine &Msg) {
+ *ErrorOS << Msg << "\n";
+ exit(1);
+}
+
+void fatal(const Twine &Msg, const Twine &Prefix) {
+ fatal(Prefix + ": " + Msg);
+}
+
+void check(std::error_code EC) {
+ if (EC)
+ fatal(EC.message());
+}
+
+void check(Error Err) {
+ check(errorToErrorCode(std::move(Err)));
}
-} // namespace elf2
+} // namespace elf
} // namespace lld
diff --git a/ELF/Error.h b/ELF/Error.h
index b1d2e7a8fc5b..552f50498464 100644
--- a/ELF/Error.h
+++ b/ELF/Error.h
@@ -13,20 +13,49 @@
#include "lld/Core/LLVM.h"
namespace lld {
-namespace elf2 {
+namespace elf {
+extern bool HasError;
+extern llvm::raw_ostream *ErrorOS;
+
+void log(const Twine &Msg);
void warning(const Twine &Msg);
-LLVM_ATTRIBUTE_NORETURN void error(const Twine &Msg);
+void error(const Twine &Msg);
void error(std::error_code EC, const Twine &Prefix);
-void error(std::error_code EC);
template <typename T> void error(const ErrorOr<T> &V, const Twine &Prefix) {
error(V.getError(), Prefix);
}
-template <typename T> void error(const ErrorOr<T> &V) { error(V.getError()); }
-} // namespace elf2
+LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg, const Twine &Prefix);
+
+template <class T> T check(ErrorOr<T> E) {
+ if (auto EC = E.getError())
+ fatal(EC.message());
+ return std::move(*E);
+}
+
+template <class T> T check(Expected<T> E) {
+ if (!E)
+ fatal(errorToErrorCode(E.takeError()).message());
+ return std::move(*E);
+}
+
+template <class T> T check(ErrorOr<T> E, const Twine &Prefix) {
+ if (auto EC = E.getError())
+ fatal(EC.message(), Prefix);
+ return std::move(*E);
+}
+
+template <class T> T check(Expected<T> E, const Twine &Prefix) {
+ if (!E)
+ fatal(errorToErrorCode(E.takeError()).message(), Prefix);
+ return std::move(*E);
+}
+
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp
new file mode 100644
index 000000000000..10a2603b3b3e
--- /dev/null
+++ b/ELF/ICF.cpp
@@ -0,0 +1,345 @@
+//===- ICF.cpp ------------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Identical Code Folding is a feature to merge sections not by name (which
+// is regular comdat handling) but by contents. If two non-writable sections
+// have the same data, relocations, attributes, etc., then the two
+// are considered identical and merged by the linker. This optimization
+// makes outputs smaller.
+//
+// ICF is theoretically a problem of reducing graphs by merging as many
+// identical subgraphs as possible if we consider sections as vertices and
+// relocations as edges. It may sound simple, but it is a bit more
+// complicated than you might think. The order of processing sections
+// matters because merging two sections can make other sections, whose
+// relocations now point to the same section, mergeable. Graphs may contain
+// cycles. We need a sophisticated algorithm to do this properly and
+// efficiently.
+//
+// What we do in this file is this. We split sections into groups. Sections
+// in the same group are considered identical.
+//
+// We begin by optimistically putting all sections into a single equivalence
+// class. Then we apply a series of checks that split this initial
+// equivalence class into more and more refined equivalence classes based on
+// the properties by which a section can be distinguished.
+//
+// We begin by checking that the section contents and flags are the
+// same. This only needs to be done once since these properties don't depend
+// on the current equivalence class assignment.
+//
+// Then we split the equivalence classes based on checking that their
+// relocations are the same, where relocation targets are compared by their
+// equivalence class, not the concrete section. This may need to be done
+// multiple times because as the equivalence classes are refined, two
+// sections that had a relocation target in the same equivalence class may
+// now target different equivalence classes, and hence these two sections
+// must be put in different equivalence classes (whereas in the previous
+// iteration they were not since the relocation target was the same.)
+//
+// Our algorithm is smart enough to merge the following mutually-recursive
+// functions.
+//
+// void foo() { bar(); }
+// void bar() { foo(); }
+//
+// This algorithm is so-called "optimistic" algorithm described in
+// http://research.google.com/pubs/pub36912.html. (Note that what GNU
+// gold implemented is different from the optimistic algorithm.)
+//
+//===----------------------------------------------------------------------===//
+
+#include "ICF.h"
+#include "Config.h"
+#include "OutputSections.h"
+#include "SymbolTable.h"
+
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lld;
+using namespace lld::elf;
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::object;
+
+namespace lld {
+namespace elf {
+template <class ELFT> class ICF {
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::uint uintX_t;
+ typedef Elf_Rel_Impl<ELFT, false> Elf_Rel;
+
+ using Comparator = std::function<bool(const InputSection<ELFT> *,
+ const InputSection<ELFT> *)>;
+
+public:
+ void run();
+
+private:
+ uint64_t NextId = 1;
+
+ static void setLive(SymbolTable<ELFT> *S);
+ static uint64_t relSize(InputSection<ELFT> *S);
+ static uint64_t getHash(InputSection<ELFT> *S);
+ static bool isEligible(InputSectionBase<ELFT> *Sec);
+ static std::vector<InputSection<ELFT> *> getSections();
+
+ void segregate(InputSection<ELFT> **Begin, InputSection<ELFT> **End,
+ Comparator Eq);
+
+ void forEachGroup(std::vector<InputSection<ELFT> *> &V, Comparator Eq);
+
+ template <class RelTy>
+ static bool relocationEq(ArrayRef<RelTy> RA, ArrayRef<RelTy> RB);
+
+ template <class RelTy>
+ static bool variableEq(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B, ArrayRef<RelTy> RA,
+ ArrayRef<RelTy> RB);
+
+ static bool equalsConstant(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B);
+
+ static bool equalsVariable(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B);
+};
+}
+}
+
+// Returns a hash value for S. Note that the information about
+// relocation targets is not included in the hash value.
+template <class ELFT> uint64_t ICF<ELFT>::getHash(InputSection<ELFT> *S) {
+ uint64_t Flags = S->getSectionHdr()->sh_flags;
+ uint64_t H = hash_combine(Flags, S->getSize());
+ for (const Elf_Shdr *Rel : S->RelocSections)
+ H = hash_combine(H, (uint64_t)Rel->sh_size);
+ return H;
+}
+
+// Returns true if Sec is subject of ICF.
+template <class ELFT> bool ICF<ELFT>::isEligible(InputSectionBase<ELFT> *Sec) {
+ if (!Sec || Sec == &InputSection<ELFT>::Discarded || !Sec->Live)
+ return false;
+ auto *S = dyn_cast<InputSection<ELFT>>(Sec);
+ if (!S)
+ return false;
+
+ // .init and .fini contains instructions that must be executed to
+ // initialize and finalize the process. They cannot and should not
+ // be merged.
+ StringRef Name = S->getSectionName();
+ if (Name == ".init" || Name == ".fini")
+ return false;
+
+ const Elf_Shdr &H = *S->getSectionHdr();
+ return (H.sh_flags & SHF_ALLOC) && (~H.sh_flags & SHF_WRITE);
+}
+
+template <class ELFT>
+std::vector<InputSection<ELFT> *> ICF<ELFT>::getSections() {
+ std::vector<InputSection<ELFT> *> V;
+ for (const std::unique_ptr<ObjectFile<ELFT>> &F :
+ Symtab<ELFT>::X->getObjectFiles())
+ for (InputSectionBase<ELFT> *S : F->getSections())
+ if (isEligible(S))
+ V.push_back(cast<InputSection<ELFT>>(S));
+ return V;
+}
+
+// All sections between Begin and End must have the same group ID before
+// you call this function. This function compare sections between Begin
+// and End using Eq and assign new group IDs for new groups.
+template <class ELFT>
+void ICF<ELFT>::segregate(InputSection<ELFT> **Begin, InputSection<ELFT> **End,
+ Comparator Eq) {
+ // This loop rearranges [Begin, End) so that all sections that are
+ // equal in terms of Eq are contiguous. The algorithm is quadratic in
+ // the worst case, but that is not an issue in practice because the
+ // number of distinct sections in [Begin, End) is usually very small.
+ InputSection<ELFT> **I = Begin;
+ for (;;) {
+ InputSection<ELFT> *Head = *I;
+ auto Bound = std::stable_partition(
+ I + 1, End, [&](InputSection<ELFT> *S) { return Eq(Head, S); });
+ if (Bound == End)
+ return;
+ uint64_t Id = NextId++;
+ for (; I != Bound; ++I)
+ (*I)->GroupId = Id;
+ }
+}
+
+template <class ELFT>
+void ICF<ELFT>::forEachGroup(std::vector<InputSection<ELFT> *> &V,
+ Comparator Eq) {
+ for (InputSection<ELFT> **I = V.data(), **E = I + V.size(); I != E;) {
+ InputSection<ELFT> *Head = *I;
+ auto Bound = std::find_if(I + 1, E, [&](InputSection<ELFT> *S) {
+ return S->GroupId != Head->GroupId;
+ });
+ segregate(I, Bound, Eq);
+ I = Bound;
+ }
+}
+
+// Compare two lists of relocations.
+template <class ELFT>
+template <class RelTy>
+bool ICF<ELFT>::relocationEq(ArrayRef<RelTy> RelsA, ArrayRef<RelTy> RelsB) {
+ const RelTy *IA = RelsA.begin();
+ const RelTy *EA = RelsA.end();
+ const RelTy *IB = RelsB.begin();
+ const RelTy *EB = RelsB.end();
+ if (EA - IA != EB - IB)
+ return false;
+ for (; IA != EA; ++IA, ++IB)
+ if (IA->r_offset != IB->r_offset ||
+ IA->getType(Config->Mips64EL) != IB->getType(Config->Mips64EL) ||
+ getAddend<ELFT>(*IA) != getAddend<ELFT>(*IB))
+ return false;
+ return true;
+}
+
+// Compare "non-moving" part of two InputSections, namely everything
+// except relocation targets.
+template <class ELFT>
+bool ICF<ELFT>::equalsConstant(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B) {
+ if (A->RelocSections.size() != B->RelocSections.size())
+ return false;
+
+ for (size_t I = 0, E = A->RelocSections.size(); I != E; ++I) {
+ const Elf_Shdr *RA = A->RelocSections[I];
+ const Elf_Shdr *RB = B->RelocSections[I];
+ ELFFile<ELFT> &FileA = A->File->getObj();
+ ELFFile<ELFT> &FileB = B->File->getObj();
+ if (RA->sh_type == SHT_RELA) {
+ if (!relocationEq(FileA.relas(RA), FileB.relas(RB)))
+ return false;
+ } else {
+ if (!relocationEq(FileA.rels(RA), FileB.rels(RB)))
+ return false;
+ }
+ }
+
+ return A->getSectionHdr()->sh_flags == B->getSectionHdr()->sh_flags &&
+ A->getSize() == B->getSize() &&
+ A->getSectionData() == B->getSectionData();
+}
+
+template <class ELFT>
+template <class RelTy>
+bool ICF<ELFT>::variableEq(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B, ArrayRef<RelTy> RelsA,
+ ArrayRef<RelTy> RelsB) {
+ const RelTy *IA = RelsA.begin();
+ const RelTy *EA = RelsA.end();
+ const RelTy *IB = RelsB.begin();
+ for (; IA != EA; ++IA, ++IB) {
+ SymbolBody &SA = A->File->getRelocTargetSym(*IA);
+ SymbolBody &SB = B->File->getRelocTargetSym(*IB);
+ if (&SA == &SB)
+ continue;
+
+ // Or, the symbols should be pointing to the same section
+ // in terms of the group ID.
+ auto *DA = dyn_cast<DefinedRegular<ELFT>>(&SA);
+ auto *DB = dyn_cast<DefinedRegular<ELFT>>(&SB);
+ if (!DA || !DB)
+ return false;
+ if (DA->Value != DB->Value)
+ return false;
+ InputSection<ELFT> *X = dyn_cast<InputSection<ELFT>>(DA->Section);
+ InputSection<ELFT> *Y = dyn_cast<InputSection<ELFT>>(DB->Section);
+ if (X && Y && X->GroupId && X->GroupId == Y->GroupId)
+ continue;
+ return false;
+ }
+ return true;
+}
+
+// Compare "moving" part of two InputSections, namely relocation targets.
+template <class ELFT>
+bool ICF<ELFT>::equalsVariable(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B) {
+ for (size_t I = 0, E = A->RelocSections.size(); I != E; ++I) {
+ const Elf_Shdr *RA = A->RelocSections[I];
+ const Elf_Shdr *RB = B->RelocSections[I];
+ ELFFile<ELFT> &FileA = A->File->getObj();
+ ELFFile<ELFT> &FileB = B->File->getObj();
+ if (RA->sh_type == SHT_RELA) {
+ if (!variableEq(A, B, FileA.relas(RA), FileB.relas(RB)))
+ return false;
+ } else {
+ if (!variableEq(A, B, FileA.rels(RA), FileB.rels(RB)))
+ return false;
+ }
+ }
+ return true;
+}
+
+// The main function of ICF.
+template <class ELFT> void ICF<ELFT>::run() {
+ // Initially, we use hash values as section group IDs. Therefore,
+ // if two sections have the same ID, they are likely (but not
+ // guaranteed) to have the same static contents in terms of ICF.
+ std::vector<InputSection<ELFT> *> V = getSections();
+ for (InputSection<ELFT> *S : V)
+ // Set MSB on to avoid collisions with serial group IDs
+ S->GroupId = getHash(S) | (uint64_t(1) << 63);
+
+ // From now on, sections in V are ordered so that sections in
+ // the same group are consecutive in the vector.
+ std::stable_sort(V.begin(), V.end(),
+ [](InputSection<ELFT> *A, InputSection<ELFT> *B) {
+ return A->GroupId < B->GroupId;
+ });
+
+ // Compare static contents and assign unique IDs for each static content.
+ forEachGroup(V, equalsConstant);
+
+ // Split groups by comparing relocations until we get a convergence.
+ int Cnt = 1;
+ for (;;) {
+ ++Cnt;
+ uint64_t Id = NextId;
+ forEachGroup(V, equalsVariable);
+ if (Id == NextId)
+ break;
+ }
+ log("ICF needed " + Twine(Cnt) + " iterations.");
+
+ // Merge sections in the same group.
+ for (auto I = V.begin(), E = V.end(); I != E;) {
+ InputSection<ELFT> *Head = *I++;
+ auto Bound = std::find_if(I, E, [&](InputSection<ELFT> *S) {
+ return Head->GroupId != S->GroupId;
+ });
+ if (I == Bound)
+ continue;
+ log("selected " + Head->getSectionName());
+ while (I != Bound) {
+ InputSection<ELFT> *S = *I++;
+ log(" removed " + S->getSectionName());
+ Head->replace(S);
+ }
+ }
+}
+
+// ICF entry point function.
+template <class ELFT> void elf::doIcf() { ICF<ELFT>().run(); }
+
+template void elf::doIcf<ELF32LE>();
+template void elf::doIcf<ELF32BE>();
+template void elf::doIcf<ELF64LE>();
+template void elf::doIcf<ELF64BE>();
diff --git a/ELF/ICF.h b/ELF/ICF.h
new file mode 100644
index 000000000000..502e128c8109
--- /dev/null
+++ b/ELF/ICF.h
@@ -0,0 +1,19 @@
+//===- ICF.h --------------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_ICF_H
+#define LLD_ELF_ICF_H
+
+namespace lld {
+namespace elf {
+template <class ELFT> void doIcf();
+}
+}
+
+#endif
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index 6a908d450f60..57e556395937 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -8,10 +8,17 @@
//===----------------------------------------------------------------------===//
#include "InputFiles.h"
-#include "InputSection.h"
+#include "Driver.h"
#include "Error.h"
+#include "InputSection.h"
+#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/Analysis.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::ELF;
@@ -19,43 +26,52 @@ using namespace llvm::object;
using namespace llvm::sys::fs;
using namespace lld;
-using namespace lld::elf2;
-
-namespace {
-class ECRAII {
- std::error_code EC;
-
-public:
- std::error_code &getEC() { return EC; }
- ~ECRAII() { error(EC); }
-};
+using namespace lld::elf;
+
+// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
+std::string elf::getFilename(const InputFile *F) {
+ if (!F)
+ return "(internal)";
+ if (!F->ArchiveName.empty())
+ return (F->ArchiveName + "(" + F->getName() + ")").str();
+ return F->getName();
}
template <class ELFT>
-ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef M)
- : InputFile(K, M), ELFObj(MB.getBuffer(), ECRAII().getEC()) {}
+static ELFFile<ELFT> createELFObj(MemoryBufferRef MB) {
+ std::error_code EC;
+ ELFFile<ELFT> F(MB.getBuffer(), EC);
+ if (EC)
+ error(EC, "failed to read " + MB.getBufferIdentifier());
+ return F;
+}
-template <class ELFT>
-ELFKind ELFFileBase<ELFT>::getELFKind() {
+template <class ELFT> static ELFKind getELFKind() {
if (ELFT::TargetEndianness == support::little)
return ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind;
return ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind;
}
template <class ELFT>
-typename ELFFileBase<ELFT>::Elf_Sym_Range
-ELFFileBase<ELFT>::getSymbolsHelper(bool Local) {
+ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB)
+ : InputFile(K, MB), ELFObj(createELFObj<ELFT>(MB)) {
+ EKind = getELFKind<ELFT>();
+ EMachine = ELFObj.getHeader()->e_machine;
+}
+
+template <class ELFT>
+typename ELFT::SymRange ELFFileBase<ELFT>::getElfSymbols(bool OnlyGlobals) {
if (!Symtab)
return Elf_Sym_Range(nullptr, nullptr);
Elf_Sym_Range Syms = ELFObj.symbols(Symtab);
uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
uint32_t FirstNonLocal = Symtab->sh_info;
if (FirstNonLocal > NumSymbols)
- error("Invalid sh_info in symbol table");
- if (!Local)
- return make_range(Syms.begin() + FirstNonLocal, Syms.end());
- // +1 to skip over dummy symbol.
- return make_range(Syms.begin() + 1, Syms.begin() + FirstNonLocal);
+ fatal(getFilename(this) + ": invalid sh_info in symbol table");
+
+ if (OnlyGlobals)
+ return makeArrayRef(Syms.begin() + FirstNonLocal, Syms.end());
+ return makeArrayRef(Syms.begin(), Syms.end());
}
template <class ELFT>
@@ -63,7 +79,7 @@ uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {
uint32_t I = Sym.st_shndx;
if (I == ELF::SHN_XINDEX)
return ELFObj.getExtendedSymbolTableIndex(&Sym, Symtab, SymtabSHNDX);
- if (I >= ELF::SHN_LORESERVE || I == ELF::SHN_ABS)
+ if (I >= ELF::SHN_LORESERVE)
return 0;
return I;
}
@@ -71,44 +87,46 @@ uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {
template <class ELFT> void ELFFileBase<ELFT>::initStringTable() {
if (!Symtab)
return;
- ErrorOr<StringRef> StringTableOrErr = ELFObj.getStringTableForSymtab(*Symtab);
- error(StringTableOrErr);
- StringTable = *StringTableOrErr;
+ StringTable = check(ELFObj.getStringTableForSymtab(*Symtab));
}
template <class ELFT>
-typename ELFFileBase<ELFT>::Elf_Sym_Range
-ELFFileBase<ELFT>::getNonLocalSymbols() {
- return getSymbolsHelper(false);
+elf::ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
+ : ELFFileBase<ELFT>(Base::ObjectKind, M) {}
+
+template <class ELFT>
+ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getNonLocalSymbols() {
+ if (!this->Symtab)
+ return this->SymbolBodies;
+ uint32_t FirstNonLocal = this->Symtab->sh_info;
+ return makeArrayRef(this->SymbolBodies).slice(FirstNonLocal);
}
template <class ELFT>
-ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
- : ELFFileBase<ELFT>(Base::ObjectKind, M) {}
+ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getLocalSymbols() {
+ if (!this->Symtab)
+ return this->SymbolBodies;
+ uint32_t FirstNonLocal = this->Symtab->sh_info;
+ return makeArrayRef(this->SymbolBodies).slice(1, FirstNonLocal - 1);
+}
template <class ELFT>
-typename ObjectFile<ELFT>::Elf_Sym_Range ObjectFile<ELFT>::getLocalSymbols() {
- return this->getSymbolsHelper(true);
+ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getSymbols() {
+ if (!this->Symtab)
+ return this->SymbolBodies;
+ return makeArrayRef(this->SymbolBodies).slice(1);
}
-template <class ELFT> uint32_t ObjectFile<ELFT>::getMipsGp0() const {
- if (MipsReginfo)
+template <class ELFT> uint32_t elf::ObjectFile<ELFT>::getMipsGp0() const {
+ if (ELFT::Is64Bits && MipsOptions && MipsOptions->Reginfo)
+ return MipsOptions->Reginfo->ri_gp_value;
+ if (!ELFT::Is64Bits && MipsReginfo && MipsReginfo->Reginfo)
return MipsReginfo->Reginfo->ri_gp_value;
return 0;
}
template <class ELFT>
-const typename ObjectFile<ELFT>::Elf_Sym *
-ObjectFile<ELFT>::getLocalSymbol(uintX_t SymIndex) {
- uint32_t FirstNonLocal = this->Symtab->sh_info;
- if (SymIndex >= FirstNonLocal)
- return nullptr;
- Elf_Sym_Range Syms = this->ELFObj.symbols(this->Symtab);
- return Syms.begin() + SymIndex;
-}
-
-template <class ELFT>
-void ObjectFile<ELFT>::parse(DenseSet<StringRef> &ComdatGroups) {
+void elf::ObjectFile<ELFT>::parse(DenseSet<StringRef> &ComdatGroups) {
// Read section and symbol tables.
initializeSections(ComdatGroups);
initializeSymbols();
@@ -118,63 +136,57 @@ void ObjectFile<ELFT>::parse(DenseSet<StringRef> &ComdatGroups) {
// They are identified and deduplicated by group name. This function
// returns a group name.
template <class ELFT>
-StringRef ObjectFile<ELFT>::getShtGroupSignature(const Elf_Shdr &Sec) {
+StringRef elf::ObjectFile<ELFT>::getShtGroupSignature(const Elf_Shdr &Sec) {
const ELFFile<ELFT> &Obj = this->ELFObj;
- uint32_t SymtabdSectionIndex = Sec.sh_link;
- ErrorOr<const Elf_Shdr *> SecOrErr = Obj.getSection(SymtabdSectionIndex);
- error(SecOrErr);
- const Elf_Shdr *SymtabSec = *SecOrErr;
- uint32_t SymIndex = Sec.sh_info;
- const Elf_Sym *Sym = Obj.getSymbol(SymtabSec, SymIndex);
- ErrorOr<StringRef> StringTableOrErr = Obj.getStringTableForSymtab(*SymtabSec);
- error(StringTableOrErr);
- ErrorOr<StringRef> SignatureOrErr = Sym->getName(*StringTableOrErr);
- error(SignatureOrErr);
- return *SignatureOrErr;
+ const Elf_Shdr *Symtab = check(Obj.getSection(Sec.sh_link));
+ const Elf_Sym *Sym = Obj.getSymbol(Symtab, Sec.sh_info);
+ StringRef Strtab = check(Obj.getStringTableForSymtab(*Symtab));
+ return check(Sym->getName(Strtab));
}
template <class ELFT>
-ArrayRef<typename ObjectFile<ELFT>::uint32_X>
-ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
+ArrayRef<typename elf::ObjectFile<ELFT>::Elf_Word>
+elf::ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
const ELFFile<ELFT> &Obj = this->ELFObj;
- ErrorOr<ArrayRef<uint32_X>> EntriesOrErr =
- Obj.template getSectionContentsAsArray<uint32_X>(&Sec);
- error(EntriesOrErr);
- ArrayRef<uint32_X> Entries = *EntriesOrErr;
+ ArrayRef<Elf_Word> Entries =
+ check(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec));
if (Entries.empty() || Entries[0] != GRP_COMDAT)
- error("Unsupported SHT_GROUP format");
+ fatal(getFilename(this) + ": unsupported SHT_GROUP format");
return Entries.slice(1);
}
template <class ELFT>
-static bool shouldMerge(const typename ELFFile<ELFT>::Elf_Shdr &Sec) {
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+bool elf::ObjectFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
+ // We don't merge sections if -O0 (default is -O1). This makes sometimes
+ // the linker significantly faster, although the output will be bigger.
+ if (Config->Optimize == 0)
+ return false;
+
uintX_t Flags = Sec.sh_flags;
if (!(Flags & SHF_MERGE))
return false;
if (Flags & SHF_WRITE)
- error("Writable SHF_MERGE sections are not supported");
+ fatal(getFilename(this) + ": writable SHF_MERGE section is not supported");
uintX_t EntSize = Sec.sh_entsize;
if (!EntSize || Sec.sh_size % EntSize)
- error("SHF_MERGE section size must be a multiple of sh_entsize");
+ fatal(getFilename(this) +
+ ": SHF_MERGE section size must be a multiple of sh_entsize");
- // Don't try to merge if the aligment is larger than the sh_entsize.
+ // Don't try to merge if the alignment is larger than the sh_entsize and this
+ // is not SHF_STRINGS.
//
- // If this is not a SHF_STRINGS, we would need to pad after every entity. It
- // would be equivalent for the producer of the .o to just set a larger
+ // Since this is not a SHF_STRINGS, we would need to pad after every entity.
+ // It would be equivalent for the producer of the .o to just set a larger
// sh_entsize.
- //
- // If this is a SHF_STRINGS, the larger alignment makes sense. Unfortunately
- // it would complicate tail merging. This doesn't seem that common to
- // justify the effort.
- if (Sec.sh_addralign > EntSize)
- return false;
+ if (Flags & SHF_STRINGS)
+ return true;
- return true;
+ return Sec.sh_addralign <= EntSize;
}
template <class ELFT>
-void ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &ComdatGroups) {
+void elf::ObjectFile<ELFT>::initializeSections(
+ DenseSet<StringRef> &ComdatGroups) {
uint64_t Size = this->ELFObj.getNumSections();
Sections.resize(Size);
unsigned I = -1;
@@ -191,53 +203,85 @@ void ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &ComdatGroups) {
continue;
for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
if (SecIndex >= Size)
- error("Invalid section index in group");
+ fatal(getFilename(this) + ": invalid section index in group: " +
+ Twine(SecIndex));
Sections[SecIndex] = &InputSection<ELFT>::Discarded;
}
break;
case SHT_SYMTAB:
this->Symtab = &Sec;
break;
- case SHT_SYMTAB_SHNDX: {
- ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = Obj.getSHNDXTable(Sec);
- error(ErrorOrTable);
- this->SymtabSHNDX = *ErrorOrTable;
+ case SHT_SYMTAB_SHNDX:
+ this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec));
break;
- }
case SHT_STRTAB:
case SHT_NULL:
break;
case SHT_RELA:
case SHT_REL: {
- uint32_t RelocatedSectionIndex = Sec.sh_info;
- if (RelocatedSectionIndex >= Size)
- error("Invalid relocated section index");
- InputSectionBase<ELFT> *RelocatedSection =
- Sections[RelocatedSectionIndex];
- if (!RelocatedSection)
- error("Unsupported relocation reference");
- if (auto *S = dyn_cast<InputSection<ELFT>>(RelocatedSection)) {
+ // This section contains relocation information.
+ // If -r is given, we do not interpret or apply relocation
+ // but just copy relocation sections to output.
+ if (Config->Relocatable) {
+ Sections[I] = new (IAlloc.Allocate()) InputSection<ELFT>(this, &Sec);
+ break;
+ }
+
+ // Find the relocation target section and associate this
+ // section with it.
+ InputSectionBase<ELFT> *Target = getRelocTarget(Sec);
+ if (!Target)
+ break;
+ if (auto *S = dyn_cast<InputSection<ELFT>>(Target)) {
S->RelocSections.push_back(&Sec);
- } else if (auto *S = dyn_cast<EHInputSection<ELFT>>(RelocatedSection)) {
+ break;
+ }
+ if (auto *S = dyn_cast<EhInputSection<ELFT>>(Target)) {
if (S->RelocSection)
- error("Multiple relocation sections to .eh_frame are not supported");
+ fatal(
+ getFilename(this) +
+ ": multiple relocation sections to .eh_frame are not supported");
S->RelocSection = &Sec;
- } else {
- error("Relocations pointing to SHF_MERGE are not supported");
+ break;
}
- break;
+ fatal(getFilename(this) +
+ ": relocations pointing to SHF_MERGE are not supported");
}
+ case SHT_ARM_ATTRIBUTES:
+ // FIXME: ARM meta-data section. At present attributes are ignored,
+ // they can be used to reason about object compatibility.
+ Sections[I] = &InputSection<ELFT>::Discarded;
+ break;
default:
Sections[I] = createInputSection(Sec);
}
}
}
-template <class ELFT> InputSectionBase<ELFT> *
-ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
- ErrorOr<StringRef> NameOrErr = this->ELFObj.getSectionName(&Sec);
- error(NameOrErr);
- StringRef Name = *NameOrErr;
+template <class ELFT>
+InputSectionBase<ELFT> *
+elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
+ uint32_t Idx = Sec.sh_info;
+ if (Idx >= Sections.size())
+ fatal(getFilename(this) + ": invalid relocated section index: " +
+ Twine(Idx));
+ InputSectionBase<ELFT> *Target = Sections[Idx];
+
+ // Strictly speaking, a relocation section must be included in the
+ // group of the section it relocates. However, LLVM 3.3 and earlier
+ // would fail to do so, so we gracefully handle that case.
+ if (Target == &InputSection<ELFT>::Discarded)
+ return nullptr;
+
+ if (!Target)
+ fatal(getFilename(this) + ": unsupported relocation reference");
+ return Target;
+}
+
+template <class ELFT>
+InputSectionBase<ELFT> *
+elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
+ StringRef Name = check(this->ELFObj.getSectionName(&Sec));
// .note.GNU-stack is a marker section to control the presence of
// PT_GNU_STACK segment in outputs. Since the presence of the segment
@@ -246,98 +290,129 @@ ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
if (Name == ".note.GNU-stack")
return &InputSection<ELFT>::Discarded;
- // A MIPS object file has a special section that contains register
- // usage info, which needs to be handled by the linker specially.
- if (Config->EMachine == EM_MIPS && Name == ".reginfo") {
- MipsReginfo = new (Alloc) MipsReginfoInputSection<ELFT>(this, &Sec);
- return MipsReginfo;
+ if (Name == ".note.GNU-split-stack") {
+ error("objects using splitstacks are not supported");
+ return &InputSection<ELFT>::Discarded;
}
- if (Name == ".eh_frame")
- return new (EHAlloc.Allocate()) EHInputSection<ELFT>(this, &Sec);
- if (shouldMerge<ELFT>(Sec))
+ if (Config->StripDebug && Name.startswith(".debug"))
+ return &InputSection<ELFT>::Discarded;
+
+ // A MIPS object file has a special sections that contain register
+ // usage info, which need to be handled by the linker specially.
+ if (Config->EMachine == EM_MIPS) {
+ if (Name == ".reginfo") {
+ MipsReginfo.reset(new MipsReginfoInputSection<ELFT>(this, &Sec));
+ return MipsReginfo.get();
+ }
+ if (Name == ".MIPS.options") {
+ MipsOptions.reset(new MipsOptionsInputSection<ELFT>(this, &Sec));
+ return MipsOptions.get();
+ }
+ }
+
+ // The linker merges EH (exception handling) frames and creates a
+ // .eh_frame_hdr section for runtime. So we handle them with a special
+ // class. For relocatable outputs, they are just passed through.
+ if (Name == ".eh_frame" && !Config->Relocatable)
+ return new (EHAlloc.Allocate()) EhInputSection<ELFT>(this, &Sec);
+
+ if (shouldMerge(Sec))
return new (MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec);
- return new (Alloc) InputSection<ELFT>(this, &Sec);
+ return new (IAlloc.Allocate()) InputSection<ELFT>(this, &Sec);
}
-template <class ELFT> void ObjectFile<ELFT>::initializeSymbols() {
+template <class ELFT> void elf::ObjectFile<ELFT>::initializeSymbols() {
this->initStringTable();
- Elf_Sym_Range Syms = this->getNonLocalSymbols();
+ Elf_Sym_Range Syms = this->getElfSymbols(false);
uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
SymbolBodies.reserve(NumSymbols);
for (const Elf_Sym &Sym : Syms)
- SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym));
+ SymbolBodies.push_back(createSymbolBody(&Sym));
}
template <class ELFT>
InputSectionBase<ELFT> *
-ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
+elf::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
uint32_t Index = this->getSectionIndex(Sym);
if (Index == 0)
return nullptr;
if (Index >= Sections.size() || !Sections[Index])
- error("Invalid section index");
- return Sections[Index];
+ fatal(getFilename(this) + ": invalid section index: " + Twine(Index));
+ InputSectionBase<ELFT> *S = Sections[Index];
+ if (S == &InputSectionBase<ELFT>::Discarded)
+ return S;
+ return S->Repl;
}
template <class ELFT>
-SymbolBody *ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
- const Elf_Sym *Sym) {
- ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
- error(NameOrErr);
- StringRef Name = *NameOrErr;
+SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
+ int Binding = Sym->getBinding();
+ InputSectionBase<ELFT> *Sec = getSection(*Sym);
+ if (Binding == STB_LOCAL) {
+ if (Sym->st_shndx == SHN_UNDEF)
+ return new (this->Alloc)
+ Undefined(Sym->st_name, Sym->st_other, Sym->getType(), this);
+ return new (this->Alloc) DefinedRegular<ELFT>(*Sym, Sec);
+ }
+
+ StringRef Name = check(Sym->getName(this->StringTable));
switch (Sym->st_shndx) {
case SHN_UNDEF:
- return new (Alloc) UndefinedElf<ELFT>(Name, *Sym);
+ return elf::Symtab<ELFT>::X
+ ->addUndefined(Name, Binding, Sym->st_other, Sym->getType(),
+ /*CanOmitFromDynSym*/ false, this)
+ ->body();
case SHN_COMMON:
- return new (Alloc) DefinedCommon(Name, Sym->st_size, Sym->st_value,
- Sym->getBinding() == llvm::ELF::STB_WEAK,
- Sym->getVisibility());
+ return elf::Symtab<ELFT>::X
+ ->addCommon(Name, Sym->st_size, Sym->st_value, Binding, Sym->st_other,
+ Sym->getType(), this)
+ ->body();
}
- switch (Sym->getBinding()) {
+ switch (Binding) {
default:
- error("unexpected binding");
+ fatal(getFilename(this) + ": unexpected binding: " + Twine(Binding));
case STB_GLOBAL:
case STB_WEAK:
- case STB_GNU_UNIQUE: {
- InputSectionBase<ELFT> *Sec = getSection(*Sym);
+ case STB_GNU_UNIQUE:
if (Sec == &InputSection<ELFT>::Discarded)
- return new (Alloc) UndefinedElf<ELFT>(Name, *Sym);
- return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, Sec);
- }
+ return elf::Symtab<ELFT>::X
+ ->addUndefined(Name, Binding, Sym->st_other, Sym->getType(),
+ /*CanOmitFromDynSym*/ false, this)
+ ->body();
+ return elf::Symtab<ELFT>::X->addRegular(Name, *Sym, Sec)->body();
}
}
-void ArchiveFile::parse() {
- ErrorOr<std::unique_ptr<Archive>> FileOrErr = Archive::create(MB);
- error(FileOrErr, "Failed to parse archive");
- File = std::move(*FileOrErr);
-
- // Allocate a buffer for Lazy objects.
- size_t NumSyms = File->getNumberOfSymbols();
- LazySymbols.reserve(NumSyms);
+template <class ELFT> void ArchiveFile::parse() {
+ File = check(Archive::create(MB), "failed to parse archive");
// Read the symbol table to construct Lazy objects.
for (const Archive::Symbol &Sym : File->symbols())
- LazySymbols.emplace_back(this, Sym);
+ Symtab<ELFT>::X->addLazyArchive(this, Sym);
}
// Returns a buffer pointing to a member file containing a given symbol.
MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
- ErrorOr<Archive::Child> COrErr = Sym->getMember();
- error(COrErr, "Could not get the member for symbol " + Sym->getName());
- const Archive::Child &C = *COrErr;
+ Archive::Child C =
+ check(Sym->getMember(),
+ "could not get the member for symbol " + Sym->getName());
if (!Seen.insert(C.getChildOffset()).second)
return MemoryBufferRef();
- ErrorOr<MemoryBufferRef> RefOrErr = C.getMemoryBufferRef();
- if (!RefOrErr)
- error(RefOrErr, "Could not get the buffer for the member defining symbol " +
- Sym->getName());
- return *RefOrErr;
+ MemoryBufferRef Ret =
+ check(C.getMemoryBufferRef(),
+ "could not get the buffer for the member defining symbol " +
+ Sym->getName());
+
+ if (C.getParent()->isThin() && Driver->Cpio)
+ Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
+ Ret.getBuffer());
+
+ return Ret;
}
template <class ELFT>
@@ -345,21 +420,19 @@ SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
: ELFFileBase<ELFT>(Base::SharedKind, M), AsNeeded(Config->AsNeeded) {}
template <class ELFT>
-const typename ELFFile<ELFT>::Elf_Shdr *
+const typename ELFT::Shdr *
SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const {
uint32_t Index = this->getSectionIndex(Sym);
if (Index == 0)
return nullptr;
- ErrorOr<const Elf_Shdr *> Ret = this->ELFObj.getSection(Index);
- error(Ret);
- return *Ret;
+ return check(this->ELFObj.getSection(Index));
}
// Partially parse the shared object file so that we can call
// getSoName on this object.
template <class ELFT> void SharedFile<ELFT>::parseSoName() {
- typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Dyn Elf_Dyn;
+ typedef typename ELFT::uint uintX_t;
const Elf_Shdr *DynamicSec = nullptr;
const ELFFile<ELFT> Obj = this->ELFObj;
@@ -373,12 +446,15 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
case SHT_DYNAMIC:
DynamicSec = &Sec;
break;
- case SHT_SYMTAB_SHNDX: {
- ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = Obj.getSHNDXTable(Sec);
- error(ErrorOrTable);
- this->SymtabSHNDX = *ErrorOrTable;
+ case SHT_SYMTAB_SHNDX:
+ this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec));
+ break;
+ case SHT_GNU_versym:
+ this->VersymSec = &Sec;
+ break;
+ case SHT_GNU_verdef:
+ this->VerdefSec = &Sec;
break;
- }
}
}
@@ -395,83 +471,358 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
if (Dyn.d_tag == DT_SONAME) {
uintX_t Val = Dyn.getVal();
if (Val >= this->StringTable.size())
- error("Invalid DT_SONAME entry");
+ fatal(getFilename(this) + ": invalid DT_SONAME entry");
SoName = StringRef(this->StringTable.data() + Val);
return;
}
}
}
+// Parse the version definitions in the object file if present. Returns a vector
+// whose nth element contains a pointer to the Elf_Verdef for version identifier
+// n. Version identifiers that are not definitions map to nullptr. The array
+// always has at least length 1.
+template <class ELFT>
+std::vector<const typename ELFT::Verdef *>
+SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) {
+ std::vector<const Elf_Verdef *> Verdefs(1);
+ // We only need to process symbol versions for this DSO if it has both a
+ // versym and a verdef section, which indicates that the DSO contains symbol
+ // version definitions.
+ if (!VersymSec || !VerdefSec)
+ return Verdefs;
+
+ // The location of the first global versym entry.
+ Versym = reinterpret_cast<const Elf_Versym *>(this->ELFObj.base() +
+ VersymSec->sh_offset) +
+ this->Symtab->sh_info;
+
+ // We cannot determine the largest verdef identifier without inspecting
+ // every Elf_Verdef, but both bfd and gold assign verdef identifiers
+ // sequentially starting from 1, so we predict that the largest identifier
+ // will be VerdefCount.
+ unsigned VerdefCount = VerdefSec->sh_info;
+ Verdefs.resize(VerdefCount + 1);
+
+ // Build the Verdefs array by following the chain of Elf_Verdef objects
+ // from the start of the .gnu.version_d section.
+ const uint8_t *Verdef = this->ELFObj.base() + VerdefSec->sh_offset;
+ for (unsigned I = 0; I != VerdefCount; ++I) {
+ auto *CurVerdef = reinterpret_cast<const Elf_Verdef *>(Verdef);
+ Verdef += CurVerdef->vd_next;
+ unsigned VerdefIndex = CurVerdef->vd_ndx;
+ if (Verdefs.size() <= VerdefIndex)
+ Verdefs.resize(VerdefIndex + 1);
+ Verdefs[VerdefIndex] = CurVerdef;
+ }
+
+ return Verdefs;
+}
+
// Fully parse the shared object file. This must be called after parseSoName().
template <class ELFT> void SharedFile<ELFT>::parseRest() {
- Elf_Sym_Range Syms = this->getNonLocalSymbols();
- uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
- SymbolBodies.reserve(NumSymbols);
+ // Create mapping from version identifiers to Elf_Verdef entries.
+ const Elf_Versym *Versym = nullptr;
+ std::vector<const Elf_Verdef *> Verdefs = parseVerdefs(Versym);
+
+ Elf_Sym_Range Syms = this->getElfSymbols(true);
for (const Elf_Sym &Sym : Syms) {
- ErrorOr<StringRef> NameOrErr = Sym.getName(this->StringTable);
- error(NameOrErr.getError());
- StringRef Name = *NameOrErr;
+ unsigned VersymIndex = 0;
+ if (Versym) {
+ VersymIndex = Versym->vs_index;
+ ++Versym;
+ }
- if (Sym.isUndefined())
+ StringRef Name = check(Sym.getName(this->StringTable));
+ if (Sym.isUndefined()) {
Undefs.push_back(Name);
- else
- SymbolBodies.emplace_back(this, Name, Sym);
+ continue;
+ }
+
+ if (Versym) {
+ // Ignore local symbols and non-default versions.
+ if (VersymIndex == VER_NDX_LOCAL || (VersymIndex & VERSYM_HIDDEN))
+ continue;
+ }
+
+ const Elf_Verdef *V =
+ VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex];
+ elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V);
}
}
-template <typename T>
-static std::unique_ptr<InputFile> createELFFileAux(MemoryBufferRef MB) {
- std::unique_ptr<T> Ret = llvm::make_unique<T>(MB);
+static ELFKind getELFKind(MemoryBufferRef MB) {
+ std::string TripleStr = getBitcodeTargetTriple(MB, Driver->Context);
+ Triple TheTriple(TripleStr);
+ bool Is64Bits = TheTriple.isArch64Bit();
+ if (TheTriple.isLittleEndian())
+ return Is64Bits ? ELF64LEKind : ELF32LEKind;
+ return Is64Bits ? ELF64BEKind : ELF32BEKind;
+}
- if (!Config->FirstElf)
- Config->FirstElf = Ret.get();
+static uint8_t getMachineKind(MemoryBufferRef MB) {
+ std::string TripleStr = getBitcodeTargetTriple(MB, Driver->Context);
+ switch (Triple(TripleStr).getArch()) {
+ case Triple::aarch64:
+ return EM_AARCH64;
+ case Triple::arm:
+ return EM_ARM;
+ case Triple::mips:
+ case Triple::mipsel:
+ case Triple::mips64:
+ case Triple::mips64el:
+ return EM_MIPS;
+ case Triple::ppc:
+ return EM_PPC;
+ case Triple::ppc64:
+ return EM_PPC64;
+ case Triple::x86:
+ return EM_386;
+ case Triple::x86_64:
+ return EM_X86_64;
+ default:
+ fatal(MB.getBufferIdentifier() +
+ ": could not infer e_machine from bitcode target triple " +
+ TripleStr);
+ }
+}
+
+BitcodeFile::BitcodeFile(MemoryBufferRef MB) : InputFile(BitcodeKind, MB) {
+ EKind = getELFKind(MB);
+ EMachine = getMachineKind(MB);
+}
- if (Config->EKind == ELFNoneKind) {
- Config->EKind = Ret->getELFKind();
- Config->EMachine = Ret->getEMachine();
+static uint8_t getGvVisibility(const GlobalValue *GV) {
+ switch (GV->getVisibility()) {
+ case GlobalValue::DefaultVisibility:
+ return STV_DEFAULT;
+ case GlobalValue::HiddenVisibility:
+ return STV_HIDDEN;
+ case GlobalValue::ProtectedVisibility:
+ return STV_PROTECTED;
}
+ llvm_unreachable("unknown visibility");
+}
+
+template <class ELFT>
+Symbol *BitcodeFile::createSymbol(const DenseSet<const Comdat *> &KeptComdats,
+ const IRObjectFile &Obj,
+ const BasicSymbolRef &Sym) {
+ const GlobalValue *GV = Obj.getSymbolGV(Sym.getRawDataRefImpl());
+
+ SmallString<64> Name;
+ raw_svector_ostream OS(Name);
+ Sym.printName(OS);
+ StringRef NameRef = Saver.save(StringRef(Name));
+
+ uint32_t Flags = Sym.getFlags();
+ bool IsWeak = Flags & BasicSymbolRef::SF_Weak;
+ uint32_t Binding = IsWeak ? STB_WEAK : STB_GLOBAL;
+
+ uint8_t Type = STT_NOTYPE;
+ bool CanOmitFromDynSym = false;
+ // FIXME: Expose a thread-local flag for module asm symbols.
+ if (GV) {
+ if (GV->isThreadLocal())
+ Type = STT_TLS;
+ CanOmitFromDynSym = canBeOmittedFromSymbolTable(GV);
+ }
+
+ uint8_t Visibility;
+ if (GV)
+ Visibility = getGvVisibility(GV);
+ else
+ // FIXME: Set SF_Hidden flag correctly for module asm symbols, and expose
+ // protected visibility.
+ Visibility = STV_DEFAULT;
+
+ if (GV)
+ if (const Comdat *C = GV->getComdat())
+ if (!KeptComdats.count(C))
+ return Symtab<ELFT>::X->addUndefined(NameRef, Binding, Visibility, Type,
+ CanOmitFromDynSym, this);
+
+ const Module &M = Obj.getModule();
+ if (Flags & BasicSymbolRef::SF_Undefined)
+ return Symtab<ELFT>::X->addUndefined(NameRef, Binding, Visibility, Type,
+ CanOmitFromDynSym, this);
+ if (Flags & BasicSymbolRef::SF_Common) {
+ // FIXME: Set SF_Common flag correctly for module asm symbols, and expose
+ // size and alignment.
+ assert(GV);
+ const DataLayout &DL = M.getDataLayout();
+ uint64_t Size = DL.getTypeAllocSize(GV->getValueType());
+ return Symtab<ELFT>::X->addCommon(NameRef, Size, GV->getAlignment(),
+ Binding, Visibility, STT_OBJECT, this);
+ }
+ return Symtab<ELFT>::X->addBitcode(NameRef, IsWeak, Visibility, Type,
+ CanOmitFromDynSym, this);
+}
- return std::move(Ret);
+bool BitcodeFile::shouldSkip(uint32_t Flags) {
+ return !(Flags & BasicSymbolRef::SF_Global) ||
+ (Flags & BasicSymbolRef::SF_FormatSpecific);
+}
+
+template <class ELFT>
+void BitcodeFile::parse(DenseSet<StringRef> &ComdatGroups) {
+ Obj = check(IRObjectFile::create(MB, Driver->Context));
+ const Module &M = Obj->getModule();
+
+ DenseSet<const Comdat *> KeptComdats;
+ for (const auto &P : M.getComdatSymbolTable()) {
+ StringRef N = Saver.save(P.first());
+ if (ComdatGroups.insert(N).second)
+ KeptComdats.insert(&P.second);
+ }
+
+ for (const BasicSymbolRef &Sym : Obj->symbols())
+ if (!shouldSkip(Sym.getFlags()))
+ Symbols.push_back(createSymbol<ELFT>(KeptComdats, *Obj, Sym));
}
template <template <class> class T>
static std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB) {
- std::pair<unsigned char, unsigned char> Type = getElfArchType(MB.getBuffer());
- if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
- error("Invalid data encoding: " + MB.getBufferIdentifier());
-
- if (Type.first == ELF::ELFCLASS32) {
- if (Type.second == ELF::ELFDATA2LSB)
- return createELFFileAux<T<ELF32LE>>(MB);
- return createELFFileAux<T<ELF32BE>>(MB);
- }
- if (Type.first == ELF::ELFCLASS64) {
- if (Type.second == ELF::ELFDATA2LSB)
- return createELFFileAux<T<ELF64LE>>(MB);
- return createELFFileAux<T<ELF64BE>>(MB);
- }
- error("Invalid file class: " + MB.getBufferIdentifier());
+ unsigned char Size;
+ unsigned char Endian;
+ std::tie(Size, Endian) = getElfArchType(MB.getBuffer());
+ if (Endian != ELFDATA2LSB && Endian != ELFDATA2MSB)
+ fatal("invalid data encoding: " + MB.getBufferIdentifier());
+
+ std::unique_ptr<InputFile> Obj;
+ if (Size == ELFCLASS32 && Endian == ELFDATA2LSB)
+ Obj.reset(new T<ELF32LE>(MB));
+ else if (Size == ELFCLASS32 && Endian == ELFDATA2MSB)
+ Obj.reset(new T<ELF32BE>(MB));
+ else if (Size == ELFCLASS64 && Endian == ELFDATA2LSB)
+ Obj.reset(new T<ELF64LE>(MB));
+ else if (Size == ELFCLASS64 && Endian == ELFDATA2MSB)
+ Obj.reset(new T<ELF64BE>(MB));
+ else
+ fatal("invalid file class: " + MB.getBufferIdentifier());
+
+ if (!Config->FirstElf)
+ Config->FirstElf = Obj.get();
+ return Obj;
+}
+
+static bool isBitcode(MemoryBufferRef MB) {
+ using namespace sys::fs;
+ return identify_magic(MB.getBuffer()) == file_magic::bitcode;
}
-std::unique_ptr<InputFile> elf2::createObjectFile(MemoryBufferRef MB) {
- return createELFFile<ObjectFile>(MB);
+std::unique_ptr<InputFile> elf::createObjectFile(MemoryBufferRef MB,
+ StringRef ArchiveName) {
+ std::unique_ptr<InputFile> F;
+ if (isBitcode(MB))
+ F.reset(new BitcodeFile(MB));
+ else
+ F = createELFFile<ObjectFile>(MB);
+ F->ArchiveName = ArchiveName;
+ return F;
}
-std::unique_ptr<InputFile> elf2::createSharedFile(MemoryBufferRef MB) {
+std::unique_ptr<InputFile> elf::createSharedFile(MemoryBufferRef MB) {
return createELFFile<SharedFile>(MB);
}
-template class elf2::ELFFileBase<ELF32LE>;
-template class elf2::ELFFileBase<ELF32BE>;
-template class elf2::ELFFileBase<ELF64LE>;
-template class elf2::ELFFileBase<ELF64BE>;
+MemoryBufferRef LazyObjectFile::getBuffer() {
+ if (Seen)
+ return MemoryBufferRef();
+ Seen = true;
+ return MB;
+}
-template class elf2::ObjectFile<ELF32LE>;
-template class elf2::ObjectFile<ELF32BE>;
-template class elf2::ObjectFile<ELF64LE>;
-template class elf2::ObjectFile<ELF64BE>;
+template <class ELFT>
+void LazyObjectFile::parse() {
+ for (StringRef Sym : getSymbols())
+ Symtab<ELFT>::X->addLazyObject(Sym, *this);
+}
+
+template <class ELFT> std::vector<StringRef> LazyObjectFile::getElfSymbols() {
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::SymRange Elf_Sym_Range;
+
+ const ELFFile<ELFT> Obj = createELFObj<ELFT>(this->MB);
+ for (const Elf_Shdr &Sec : Obj.sections()) {
+ if (Sec.sh_type != SHT_SYMTAB)
+ continue;
+ Elf_Sym_Range Syms = Obj.symbols(&Sec);
+ uint32_t FirstNonLocal = Sec.sh_info;
+ StringRef StringTable = check(Obj.getStringTableForSymtab(Sec));
+ std::vector<StringRef> V;
+ for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal))
+ if (Sym.st_shndx != SHN_UNDEF)
+ V.push_back(check(Sym.getName(StringTable)));
+ return V;
+ }
+ return {};
+}
+
+std::vector<StringRef> LazyObjectFile::getBitcodeSymbols() {
+ LLVMContext Context;
+ std::unique_ptr<IRObjectFile> Obj =
+ check(IRObjectFile::create(this->MB, Context));
+ std::vector<StringRef> V;
+ for (const BasicSymbolRef &Sym : Obj->symbols()) {
+ uint32_t Flags = Sym.getFlags();
+ if (BitcodeFile::shouldSkip(Flags))
+ continue;
+ if (Flags & BasicSymbolRef::SF_Undefined)
+ continue;
+ SmallString<64> Name;
+ raw_svector_ostream OS(Name);
+ Sym.printName(OS);
+ V.push_back(Saver.save(StringRef(Name)));
+ }
+ return V;
+}
+
+// Returns a vector of globally-visible defined symbol names.
+std::vector<StringRef> LazyObjectFile::getSymbols() {
+ if (isBitcode(this->MB))
+ return getBitcodeSymbols();
+
+ unsigned char Size;
+ unsigned char Endian;
+ std::tie(Size, Endian) = getElfArchType(this->MB.getBuffer());
+ if (Size == ELFCLASS32) {
+ if (Endian == ELFDATA2LSB)
+ return getElfSymbols<ELF32LE>();
+ return getElfSymbols<ELF32BE>();
+ }
+ if (Endian == ELFDATA2LSB)
+ return getElfSymbols<ELF64LE>();
+ return getElfSymbols<ELF64BE>();
+}
-template class elf2::SharedFile<ELF32LE>;
-template class elf2::SharedFile<ELF32BE>;
-template class elf2::SharedFile<ELF64LE>;
-template class elf2::SharedFile<ELF64BE>;
+template void ArchiveFile::parse<ELF32LE>();
+template void ArchiveFile::parse<ELF32BE>();
+template void ArchiveFile::parse<ELF64LE>();
+template void ArchiveFile::parse<ELF64BE>();
+
+template void BitcodeFile::parse<ELF32LE>(DenseSet<StringRef> &);
+template void BitcodeFile::parse<ELF32BE>(DenseSet<StringRef> &);
+template void BitcodeFile::parse<ELF64LE>(DenseSet<StringRef> &);
+template void BitcodeFile::parse<ELF64BE>(DenseSet<StringRef> &);
+
+template void LazyObjectFile::parse<ELF32LE>();
+template void LazyObjectFile::parse<ELF32BE>();
+template void LazyObjectFile::parse<ELF64LE>();
+template void LazyObjectFile::parse<ELF64BE>();
+
+template class elf::ELFFileBase<ELF32LE>;
+template class elf::ELFFileBase<ELF32BE>;
+template class elf::ELFFileBase<ELF64LE>;
+template class elf::ELFFileBase<ELF64BE>;
+
+template class elf::ObjectFile<ELF32LE>;
+template class elf::ObjectFile<ELF32BE>;
+template class elf::ObjectFile<ELF64LE>;
+template class elf::ObjectFile<ELF64BE>;
+
+template class elf::SharedFile<ELF32LE>;
+template class elf::SharedFile<ELF32BE>;
+template class elf::SharedFile<ELF64LE>;
+template class elf::SharedFile<ELF64BE>;
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 45d403c0125c..79cb751494b3 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -18,11 +18,16 @@
#include "lld/Core/LLVM.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/Comdat.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
+#include "llvm/Object/IRObjectFile.h"
+#include "llvm/Support/StringSaver.h"
+
+#include <map>
namespace lld {
-namespace elf2 {
+namespace elf {
using llvm::object::Archive;
@@ -33,25 +38,45 @@ class SymbolBody;
// The root class of input files.
class InputFile {
public:
- enum Kind { ObjectKind, SharedKind, ArchiveKind };
+ enum Kind {
+ ObjectKind,
+ SharedKind,
+ LazyObjectKind,
+ ArchiveKind,
+ BitcodeKind,
+ };
+
Kind kind() const { return FileKind; }
StringRef getName() const { return MB.getBufferIdentifier(); }
+ MemoryBufferRef MB;
+
+ // Filename of .a which contained this file. If this file was
+ // not in an archive file, it is the empty string. We use this
+ // string for creating error messages.
+ StringRef ArchiveName;
+
+ // If this is an architecture-specific file, the following members
+ // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
+ ELFKind EKind = ELFNoneKind;
+ uint16_t EMachine = llvm::ELF::EM_NONE;
protected:
InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
- MemoryBufferRef MB;
private:
const Kind FileKind;
};
+// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
+std::string getFilename(const InputFile *F);
+
template <typename ELFT> class ELFFileBase : public InputFile {
public:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::Word Elf_Word;
+ typedef typename ELFT::SymRange Elf_Sym_Range;
ELFFileBase(Kind K, MemoryBufferRef M);
static bool classof(const InputFile *F) {
@@ -59,11 +84,9 @@ public:
return K == ObjectKind || K == SharedKind;
}
- static ELFKind getELFKind();
const llvm::object::ELFFile<ELFT> &getObj() const { return ELFObj; }
llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; }
- uint16_t getEMachine() const { return getObj().getHeader()->e_machine; }
uint8_t getOSABI() const {
return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];
}
@@ -72,39 +95,36 @@ public:
uint32_t getSectionIndex(const Elf_Sym &Sym) const;
+ Elf_Sym_Range getElfSymbols(bool OnlyGlobals);
+
protected:
llvm::object::ELFFile<ELFT> ELFObj;
const Elf_Shdr *Symtab = nullptr;
ArrayRef<Elf_Word> SymtabSHNDX;
StringRef StringTable;
void initStringTable();
- Elf_Sym_Range getNonLocalSymbols();
- Elf_Sym_Range getSymbolsHelper(bool);
};
// .o file.
template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
typedef ELFFileBase<ELFT> Base;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
-
- // uint32 in ELFT's byte order
- typedef llvm::support::detail::packed_endian_specific_integral<
- uint32_t, ELFT::TargetEndianness, 2>
- uint32_X;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::SymRange Elf_Sym_Range;
+ typedef typename ELFT::Word Elf_Word;
+ typedef typename ELFT::uint uintX_t;
StringRef getShtGroupSignature(const Elf_Shdr &Sec);
- ArrayRef<uint32_X> getShtGroupEntries(const Elf_Shdr &Sec);
+ ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec);
public:
static bool classof(const InputFile *F) {
return F->kind() == Base::ObjectKind;
}
- ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; }
+ ArrayRef<SymbolBody *> getSymbols();
+ ArrayRef<SymbolBody *> getLocalSymbols();
+ ArrayRef<SymbolBody *> getNonLocalSymbols();
explicit ObjectFile(MemoryBufferRef M);
void parse(llvm::DenseSet<StringRef> &ComdatGroups);
@@ -112,15 +132,14 @@ public:
ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; }
InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const;
- SymbolBody *getSymbolBody(uint32_t SymbolIndex) const {
- uint32_t FirstNonLocal = this->Symtab->sh_info;
- if (SymbolIndex < FirstNonLocal)
- return nullptr;
- return SymbolBodies[SymbolIndex - FirstNonLocal];
+ SymbolBody &getSymbolBody(uint32_t SymbolIndex) const {
+ return *SymbolBodies[SymbolIndex];
}
- Elf_Sym_Range getLocalSymbols();
- const Elf_Sym *getLocalSymbol(uintX_t SymIndex);
+ template <typename RelT> SymbolBody &getRelocTargetSym(const RelT &Rel) const {
+ uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
+ return getSymbolBody(SymIndex);
+ }
const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
@@ -129,12 +148,22 @@ public:
// R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
uint32_t getMipsGp0() const;
+ // The number is the offset in the string table. It will be used as the
+ // st_name of the symbol.
+ std::vector<std::pair<const DefinedRegular<ELFT> *, unsigned>> KeptLocalSyms;
+
+ // SymbolBodies and Thunks for sections in this file are allocated
+ // using this buffer.
+ llvm::BumpPtrAllocator Alloc;
+
private:
void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups);
void initializeSymbols();
+ InputSectionBase<ELFT> *getRelocTarget(const Elf_Shdr &Sec);
InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec);
- SymbolBody *createSymbolBody(StringRef StringTable, const Elf_Sym *Sym);
+ bool shouldMerge(const Elf_Shdr &Sec);
+ SymbolBody *createSymbolBody(const Elf_Sym *Sym);
// List of all sections defined by this file.
std::vector<InputSectionBase<ELFT> *> Sections;
@@ -143,49 +172,97 @@ private:
std::vector<SymbolBody *> SymbolBodies;
// MIPS .reginfo section defined by this file.
- MipsReginfoInputSection<ELFT> *MipsReginfo = nullptr;
+ std::unique_ptr<MipsReginfoInputSection<ELFT>> MipsReginfo;
+ // MIPS .MIPS.options section defined by this file.
+ std::unique_ptr<MipsOptionsInputSection<ELFT>> MipsOptions;
- llvm::BumpPtrAllocator Alloc;
+ llvm::SpecificBumpPtrAllocator<InputSection<ELFT>> IAlloc;
llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc;
- llvm::SpecificBumpPtrAllocator<EHInputSection<ELFT>> EHAlloc;
+ llvm::SpecificBumpPtrAllocator<EhInputSection<ELFT>> EHAlloc;
+};
+
+// LazyObjectFile is analogous to ArchiveFile in the sense that
+// the file contains lazy symbols. The difference is that
+// LazyObjectFile wraps a single file instead of multiple files.
+//
+// This class is used for --start-lib and --end-lib options which
+// instruct the linker to link object files between them with the
+// archive file semantics.
+class LazyObjectFile : public InputFile {
+public:
+ explicit LazyObjectFile(MemoryBufferRef M) : InputFile(LazyObjectKind, M) {}
+
+ static bool classof(const InputFile *F) {
+ return F->kind() == LazyObjectKind;
+ }
+
+ template <class ELFT> void parse();
+ MemoryBufferRef getBuffer();
+
+private:
+ std::vector<StringRef> getSymbols();
+ template <class ELFT> std::vector<StringRef> getElfSymbols();
+ std::vector<StringRef> getBitcodeSymbols();
+
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver Saver{Alloc};
+ bool Seen = false;
};
+// An ArchiveFile object represents a .a file.
class ArchiveFile : public InputFile {
public:
explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
- void parse();
+ template <class ELFT> void parse();
// Returns a memory buffer for a given symbol. An empty memory buffer
// is returned if we have already returned the same memory buffer.
// (So that we don't instantiate same members more than once.)
MemoryBufferRef getMember(const Archive::Symbol *Sym);
- llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
-
private:
std::unique_ptr<Archive> File;
- std::vector<Lazy> LazySymbols;
llvm::DenseSet<uint64_t> Seen;
};
+class BitcodeFile : public InputFile {
+public:
+ explicit BitcodeFile(MemoryBufferRef M);
+ static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
+ template <class ELFT>
+ void parse(llvm::DenseSet<StringRef> &ComdatGroups);
+ ArrayRef<Symbol *> getSymbols() { return Symbols; }
+ static bool shouldSkip(uint32_t Flags);
+ std::unique_ptr<llvm::object::IRObjectFile> Obj;
+
+private:
+ std::vector<Symbol *> Symbols;
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver Saver{Alloc};
+ template <class ELFT>
+ Symbol *createSymbol(const llvm::DenseSet<const llvm::Comdat *> &KeptComdats,
+ const llvm::object::IRObjectFile &Obj,
+ const llvm::object::BasicSymbolRef &Sym);
+};
+
// .so file.
template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
typedef ELFFileBase<ELFT> Base;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::Word Elf_Word;
+ typedef typename ELFT::SymRange Elf_Sym_Range;
+ typedef typename ELFT::Versym Elf_Versym;
+ typedef typename ELFT::Verdef Elf_Verdef;
- std::vector<SharedSymbol<ELFT>> SymbolBodies;
std::vector<StringRef> Undefs;
StringRef SoName;
+ const Elf_Shdr *VersymSec = nullptr;
+ const Elf_Shdr *VerdefSec = nullptr;
public:
StringRef getSoName() const { return SoName; }
- llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() {
- return SymbolBodies;
- }
const Elf_Shdr *getSection(const Elf_Sym &Sym) const;
llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
@@ -197,6 +274,19 @@ public:
void parseSoName();
void parseRest();
+ std::vector<const Elf_Verdef *> parseVerdefs(const Elf_Versym *&Versym);
+
+ struct NeededVer {
+ // The string table offset of the version name in the output file.
+ size_t StrTab;
+
+ // The version identifier for this version name.
+ uint16_t Index;
+ };
+
+ // Mapping from Elf_Verdef data structures to information about Elf_Vernaux
+ // data structures in the output file.
+ std::map<const Elf_Verdef *, NeededVer> VerdefMap;
// Used for --as-needed
bool AsNeeded = false;
@@ -204,10 +294,11 @@ public:
bool isNeeded() const { return !AsNeeded || IsUsed; }
};
-std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB);
+std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB,
+ StringRef ArchiveName = "");
std::unique_ptr<InputFile> createSharedFile(MemoryBufferRef MB);
-} // namespace elf2
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index f6aa51b47b98..6564e7995a89 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -9,86 +9,118 @@
#include "InputSection.h"
#include "Config.h"
+#include "EhFrame.h"
#include "Error.h"
#include "InputFiles.h"
+#include "LinkerScript.h"
#include "OutputSections.h"
#include "Target.h"
+#include "Thunks.h"
+
+#include "llvm/Support/Compression.h"
+#include "llvm/Support/Endian.h"
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
+using namespace llvm::support::endian;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
+
+template <class ELFT> bool elf::isDiscarded(InputSectionBase<ELFT> *S) {
+ return !S || S == &InputSection<ELFT>::Discarded || !S->Live ||
+ Script<ELFT>::X->isDiscarded(S);
+}
template <class ELFT>
-InputSectionBase<ELFT>::InputSectionBase(ObjectFile<ELFT> *File,
+InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
const Elf_Shdr *Header,
Kind SectionKind)
- : Header(Header), File(File), SectionKind(SectionKind) {}
+ : Header(Header), File(File), SectionKind(SectionKind), Repl(this),
+ Compressed(Header->sh_flags & SHF_COMPRESSED) {
+ // The garbage collector sets sections' Live bits.
+ // If GC is disabled, all sections are considered live by default.
+ Live = !Config->GcSections;
+
+ // The ELF spec states that a value of 0 means the section has
+ // no alignment constraits.
+ Alignment = std::max<uintX_t>(Header->sh_addralign, 1);
+}
+
+template <class ELFT> size_t InputSectionBase<ELFT>::getSize() const {
+ if (auto *D = dyn_cast<InputSection<ELFT>>(this))
+ if (D->getThunksSize() > 0)
+ return D->getThunkOff() + D->getThunksSize();
+ return Header->sh_size;
+}
template <class ELFT> StringRef InputSectionBase<ELFT>::getSectionName() const {
- ErrorOr<StringRef> Name = File->getObj().getSectionName(this->Header);
- error(Name);
- return *Name;
+ return check(File->getObj().getSectionName(this->Header));
}
template <class ELFT>
ArrayRef<uint8_t> InputSectionBase<ELFT>::getSectionData() const {
- ErrorOr<ArrayRef<uint8_t>> Ret =
- this->File->getObj().getSectionContents(this->Header);
- error(Ret);
- return *Ret;
+ if (Compressed)
+ return ArrayRef<uint8_t>((const uint8_t *)Uncompressed.data(),
+ Uncompressed.size());
+ return check(this->File->getObj().getSectionContents(this->Header));
}
template <class ELFT>
-typename ELFFile<ELFT>::uintX_t
-InputSectionBase<ELFT>::getOffset(uintX_t Offset) {
+typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
switch (SectionKind) {
case Regular:
return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
case EHFrame:
- return cast<EHInputSection<ELFT>>(this)->getOffset(Offset);
+ return cast<EhInputSection<ELFT>>(this)->getOffset(Offset);
case Merge:
return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
case MipsReginfo:
- // MIPS .reginfo sections are consumed by the linker,
- // so it should never be copied to output.
- llvm_unreachable("MIPS .reginfo reached writeTo().");
+ case MipsOptions:
+ // MIPS .reginfo and .MIPS.options sections are consumed by the linker,
+ // and the linker produces a single output section. It is possible that
+ // input files contain section symbol points to the corresponding input
+ // section. Redirect it to the produced output section.
+ if (Offset != 0)
+ fatal("Unsupported reference to the middle of '" + getSectionName() +
+ "' section");
+ return this->OutSec->getVA();
}
- llvm_unreachable("Invalid section kind");
+ llvm_unreachable("invalid section kind");
}
-template <class ELFT>
-typename ELFFile<ELFT>::uintX_t
-InputSectionBase<ELFT>::getOffset(const Elf_Sym &Sym) {
- return getOffset(Sym.st_value);
-}
+template <class ELFT> void InputSectionBase<ELFT>::uncompress() {
+ if (!zlib::isAvailable())
+ fatal("build lld with zlib to enable compressed sections support");
-// Returns a section that Rel relocation is pointing to.
-template <class ELFT>
-InputSectionBase<ELFT> *
-InputSectionBase<ELFT>::getRelocTarget(const Elf_Rel &Rel) {
- // Global symbol
- uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
- if (SymbolBody *B = File->getSymbolBody(SymIndex))
- if (auto *D = dyn_cast<DefinedRegular<ELFT>>(B->repl()))
- return D->Section;
- // Local symbol
- if (const Elf_Sym *Sym = File->getLocalSymbol(SymIndex))
- if (InputSectionBase<ELFT> *Sec = File->getSection(*Sym))
- return Sec;
- return nullptr;
+ // A compressed section consists of a header of Elf_Chdr type
+ // followed by compressed data.
+ ArrayRef<uint8_t> Data =
+ check(this->File->getObj().getSectionContents(this->Header));
+ if (Data.size() < sizeof(Elf_Chdr))
+ fatal("corrupt compressed section");
+
+ auto *Hdr = reinterpret_cast<const Elf_Chdr *>(Data.data());
+ Data = Data.slice(sizeof(Elf_Chdr));
+
+ if (Hdr->ch_type != ELFCOMPRESS_ZLIB)
+ fatal("unsupported compression type");
+
+ StringRef Buf((const char *)Data.data(), Data.size());
+ if (zlib::uncompress(Buf, Uncompressed, Hdr->ch_size) != zlib::StatusOK)
+ fatal("error uncompressing section");
}
template <class ELFT>
-InputSectionBase<ELFT> *
-InputSectionBase<ELFT>::getRelocTarget(const Elf_Rela &Rel) {
- return getRelocTarget(reinterpret_cast<const Elf_Rel &>(Rel));
+typename ELFT::uint
+InputSectionBase<ELFT>::getOffset(const DefinedRegular<ELFT> &Sym) const {
+ return getOffset(Sym.Value);
}
template <class ELFT>
-InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header)
+InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F,
+ const Elf_Shdr *Header)
: InputSectionBase<ELFT>(F, Header, Base::Regular) {}
template <class ELFT>
@@ -97,267 +129,494 @@ bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
}
template <class ELFT>
-template <bool isRela>
-uint8_t *
-InputSectionBase<ELFT>::findMipsPairedReloc(uint8_t *Buf, uint32_t SymIndex,
- uint32_t Type,
- RelIteratorRange<isRela> Rels) {
- // Some MIPS relocations use addend calculated from addend of the relocation
- // itself and addend of paired relocation. ABI requires to compute such
- // combined addend in case of REL relocation record format only.
- // See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- if (isRela || Config->EMachine != EM_MIPS)
- return nullptr;
- if (Type == R_MIPS_HI16)
- Type = R_MIPS_LO16;
- else if (Type == R_MIPS_PCHI16)
- Type = R_MIPS_PCLO16;
- else if (Type == R_MICROMIPS_HI16)
- Type = R_MICROMIPS_LO16;
- else
- return nullptr;
- for (const auto &RI : Rels) {
- if (RI.getType(Config->Mips64EL) != Type)
- continue;
- if (RI.getSymbol(Config->Mips64EL) != SymIndex)
- continue;
- uintX_t Offset = getOffset(RI.r_offset);
- if (Offset == (uintX_t)-1)
- return nullptr;
- return Buf + Offset;
- }
- return nullptr;
+InputSectionBase<ELFT> *InputSection<ELFT>::getRelocatedSection() {
+ assert(this->Header->sh_type == SHT_RELA || this->Header->sh_type == SHT_REL);
+ ArrayRef<InputSectionBase<ELFT> *> Sections = this->File->getSections();
+ return Sections[this->Header->sh_info];
}
template <class ELFT>
-static typename llvm::object::ELFFile<ELFT>::uintX_t
-getSymSize(SymbolBody &Body) {
- if (auto *SS = dyn_cast<DefinedElf<ELFT>>(&Body))
- return SS->Sym.st_size;
- return 0;
+void InputSection<ELFT>::addThunk(const Thunk<ELFT> *T) {
+ Thunks.push_back(T);
+}
+
+template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const {
+ return this->Header->sh_size;
}
+template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const {
+ uint64_t Total = 0;
+ for (const Thunk<ELFT> *T : Thunks)
+ Total += T->size();
+ return Total;
+}
+
+// This is used for -r. We can't use memcpy to copy relocations because we need
+// to update symbol table offset and section index for each relocation. So we
+// copy relocations one by one.
template <class ELFT>
-template <bool isRela>
-void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
- RelIteratorRange<isRela> Rels) {
- typedef Elf_Rel_Impl<ELFT, isRela> RelType;
- size_t Num = Rels.end() - Rels.begin();
- for (size_t I = 0; I < Num; ++I) {
- const RelType &RI = *(Rels.begin() + I);
- uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
- uint32_t Type = RI.getType(Config->Mips64EL);
- uintX_t Offset = getOffset(RI.r_offset);
- if (Offset == (uintX_t)-1)
- continue;
+template <class RelTy>
+void InputSection<ELFT>::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
+ InputSectionBase<ELFT> *RelocatedSection = getRelocatedSection();
- uint8_t *BufLoc = Buf + Offset;
- uintX_t AddrLoc = OutSec->getVA() + Offset;
- auto NextRelocs = llvm::make_range(&RI, Rels.end());
+ for (const RelTy &Rel : Rels) {
+ uint32_t Type = Rel.getType(Config->Mips64EL);
+ SymbolBody &Body = this->File->getRelocTargetSym(Rel);
- if (Target->isTlsLocalDynamicReloc(Type) &&
- !Target->isTlsOptimized(Type, nullptr)) {
- Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
- Out<ELFT>::Got->getLocalTlsIndexVA() +
- getAddend<ELFT>(RI));
- continue;
- }
+ RelTy *P = reinterpret_cast<RelTy *>(Buf);
+ Buf += sizeof(RelTy);
- const Elf_Shdr *SymTab = File->getSymbolTable();
- SymbolBody *Body = nullptr;
- if (SymIndex >= SymTab->sh_info)
- Body = File->getSymbolBody(SymIndex)->repl();
-
- if (Target->isTlsOptimized(Type, Body)) {
- uintX_t SymVA;
- if (!Body)
- SymVA = getLocalRelTarget(*File, RI, 0);
- else if (Target->relocNeedsGot(Type, *Body))
- SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
- else
- SymVA = getSymVA<ELFT>(*Body);
- // By optimizing TLS relocations, it is sometimes needed to skip
- // relocations that immediately follow TLS relocations. This function
- // knows how many slots we need to skip.
- I += Target->relocateTlsOptimize(BufLoc, BufEnd, Type, AddrLoc, SymVA,
- *Body);
- continue;
+ P->r_offset = RelocatedSection->getOffset(Rel.r_offset);
+ P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL);
+ }
+}
+
+// Page(Expr) is the page address of the expression Expr, defined
+// as (Expr & ~0xFFF). (This applies even if the machine page size
+// supported by the platform has a different value.)
+static uint64_t getAArch64Page(uint64_t Expr) {
+ return Expr & (~static_cast<uint64_t>(0xFFF));
+}
+
+template <class ELFT>
+static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
+ typename ELFT::uint P,
+ const SymbolBody &Body, RelExpr Expr) {
+ typedef typename ELFT::uint uintX_t;
+
+ switch (Expr) {
+ case R_HINT:
+ llvm_unreachable("cannot relocate hint relocs");
+ case R_TLSLD:
+ return Out<ELFT>::Got->getTlsIndexOff() + A -
+ Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
+ case R_TLSLD_PC:
+ return Out<ELFT>::Got->getTlsIndexVA() + A - P;
+ case R_THUNK_ABS:
+ return Body.getThunkVA<ELFT>() + A;
+ case R_THUNK_PC:
+ case R_THUNK_PLT_PC:
+ return Body.getThunkVA<ELFT>() + A - P;
+ case R_PPC_TOC:
+ return getPPC64TocBase() + A;
+ case R_TLSGD:
+ return Out<ELFT>::Got->getGlobalDynOffset(Body) + A -
+ Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
+ case R_TLSGD_PC:
+ return Out<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
+ case R_TLSDESC:
+ return Out<ELFT>::Got->getGlobalDynAddr(Body) + A;
+ case R_TLSDESC_PAGE:
+ return getAArch64Page(Out<ELFT>::Got->getGlobalDynAddr(Body) + A) -
+ getAArch64Page(P);
+ case R_PLT:
+ return Body.getPltVA<ELFT>() + A;
+ case R_PLT_PC:
+ case R_PPC_PLT_OPD:
+ return Body.getPltVA<ELFT>() + A - P;
+ case R_SIZE:
+ return Body.getSize<ELFT>() + A;
+ case R_GOTREL:
+ return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA();
+ case R_RELAX_TLS_GD_TO_IE_END:
+ case R_GOT_FROM_END:
+ return Body.getGotOffset<ELFT>() + A -
+ Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
+ case R_RELAX_TLS_GD_TO_IE_ABS:
+ case R_GOT:
+ return Body.getGotVA<ELFT>() + A;
+ case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
+ case R_GOT_PAGE_PC:
+ return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P);
+ case R_RELAX_TLS_GD_TO_IE:
+ case R_GOT_PC:
+ return Body.getGotVA<ELFT>() + A - P;
+ case R_GOTONLY_PC:
+ return Out<ELFT>::Got->getVA() + A - P;
+ case R_RELAX_TLS_LD_TO_LE:
+ case R_RELAX_TLS_IE_TO_LE:
+ case R_RELAX_TLS_GD_TO_LE:
+ case R_TLS:
+ if (Target->TcbSize)
+ return Body.getVA<ELFT>(A) +
+ alignTo(Target->TcbSize, Out<ELFT>::TlsPhdr->p_align);
+ return Body.getVA<ELFT>(A) - Out<ELFT>::TlsPhdr->p_memsz;
+ case R_RELAX_TLS_GD_TO_LE_NEG:
+ case R_NEG_TLS:
+ return Out<ELF32LE>::TlsPhdr->p_memsz - Body.getVA<ELFT>(A);
+ case R_ABS:
+ case R_RELAX_GOT_PC_NOPIC:
+ return Body.getVA<ELFT>(A);
+ case R_GOT_OFF:
+ return Body.getGotOffset<ELFT>() + A;
+ case R_MIPS_GOT_LOCAL_PAGE:
+ // If relocation against MIPS local symbol requires GOT entry, this entry
+ // should be initialized by 'page address'. This address is high 16-bits
+ // of sum the symbol's value and the addend.
+ return Out<ELFT>::Got->getMipsLocalPageOffset(Body.getVA<ELFT>(A));
+ case R_MIPS_GOT_OFF:
+ // In case of MIPS if a GOT relocation has non-zero addend this addend
+ // should be applied to the GOT entry content not to the GOT entry offset.
+ // That is why we use separate expression type.
+ return Out<ELFT>::Got->getMipsGotOffset(Body, A);
+ case R_MIPS_TLSGD:
+ return Out<ELFT>::Got->getGlobalDynOffset(Body) +
+ Out<ELFT>::Got->getMipsTlsOffset() - MipsGPOffset;
+ case R_MIPS_TLSLD:
+ return Out<ELFT>::Got->getTlsIndexOff() +
+ Out<ELFT>::Got->getMipsTlsOffset() - MipsGPOffset;
+ case R_PPC_OPD: {
+ uint64_t SymVA = Body.getVA<ELFT>(A);
+ // If we have an undefined weak symbol, we might get here with a symbol
+ // address of zero. That could overflow, but the code must be unreachable,
+ // so don't bother doing anything at all.
+ if (!SymVA)
+ return 0;
+ if (Out<ELF64BE>::Opd) {
+ // If this is a local call, and we currently have the address of a
+ // function-descriptor, get the underlying code address instead.
+ uint64_t OpdStart = Out<ELF64BE>::Opd->getVA();
+ uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->getSize();
+ bool InOpd = OpdStart <= SymVA && SymVA < OpdEnd;
+ if (InOpd)
+ SymVA = read64be(&Out<ELF64BE>::OpdBuf[SymVA - OpdStart]);
}
+ return SymVA - P;
+ }
+ case R_PC:
+ case R_RELAX_GOT_PC:
+ return Body.getVA<ELFT>(A) - P;
+ case R_PLT_PAGE_PC:
+ case R_PAGE_PC:
+ return getAArch64Page(Body.getVA<ELFT>(A)) - getAArch64Page(P);
+ }
+ llvm_unreachable("Invalid expression");
+}
- // Handle relocations for local symbols -- they never get
- // resolved so we don't allocate a SymbolBody.
- uintX_t A = getAddend<ELFT>(RI);
- if (!Body) {
- uintX_t SymVA = getLocalRelTarget(*File, RI, A);
- // We need to adjust SymVA value in case of R_MIPS_GPREL16/32 relocations
- // because they use the following expression to calculate the relocation's
- // result for local symbol: S + A + GP0 - G.
- if (Config->EMachine == EM_MIPS &&
- (Type == R_MIPS_GPREL16 || Type == R_MIPS_GPREL32))
- SymVA += File->getMipsGp0();
- Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0,
- findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs));
- continue;
+// This function applies relocations to sections without SHF_ALLOC bit.
+// Such sections are never mapped to memory at runtime. Debug sections are
+// an example. Relocations in non-alloc sections are much easier to
+// handle than in allocated sections because it will never need complex
+// treatement such as GOT or PLT (because at runtime no one refers them).
+// So, we handle relocations for non-alloc sections directly in this
+// function as a performance optimization.
+template <class ELFT>
+template <class RelTy>
+void InputSection<ELFT>::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
+ const unsigned Bits = sizeof(uintX_t) * 8;
+ for (const RelTy &Rel : Rels) {
+ uint32_t Type = Rel.getType(Config->Mips64EL);
+ uintX_t Offset = this->getOffset(Rel.r_offset);
+ uint8_t *BufLoc = Buf + Offset;
+ uintX_t Addend = getAddend<ELFT>(Rel);
+ if (!RelTy::IsRela)
+ Addend += Target->getImplicitAddend(BufLoc, Type);
+
+ SymbolBody &Sym = this->File->getRelocTargetSym(Rel);
+ if (Target->getRelExpr(Type, Sym) != R_ABS) {
+ error(this->getSectionName() + " has non-ABS reloc");
+ return;
}
- if (Target->isTlsGlobalDynamicReloc(Type) &&
- !Target->isTlsOptimized(Type, Body)) {
- Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
- Out<ELFT>::Got->getGlobalDynAddr(*Body) +
- getAddend<ELFT>(RI));
- continue;
+ uintX_t AddrLoc = this->OutSec->getVA() + Offset;
+ uint64_t SymVA =
+ SignExtend64<Bits>(getSymVA<ELFT>(Type, Addend, AddrLoc, Sym, R_ABS));
+ Target->relocateOne(BufLoc, Type, SymVA);
+ }
+}
+
+template <class ELFT>
+void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) {
+ // scanReloc function in Writer.cpp constructs Relocations
+ // vector only for SHF_ALLOC'ed sections. For other sections,
+ // we handle relocations directly here.
+ auto *IS = dyn_cast<InputSection<ELFT>>(this);
+ if (IS && !(IS->Header->sh_flags & SHF_ALLOC)) {
+ for (const Elf_Shdr *RelSec : IS->RelocSections) {
+ if (RelSec->sh_type == SHT_RELA)
+ IS->relocateNonAlloc(Buf, IS->File->getObj().relas(RelSec));
+ else
+ IS->relocateNonAlloc(Buf, IS->File->getObj().rels(RelSec));
}
+ return;
+ }
- uintX_t SymVA = getSymVA<ELFT>(*Body);
- if (Target->relocNeedsPlt(Type, *Body)) {
- SymVA = Out<ELFT>::Plt->getEntryAddr(*Body);
- } else if (Target->relocNeedsGot(Type, *Body)) {
- SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
- if (Body->isTls())
- Type = Target->getTlsGotReloc(Type);
- } else if (!Target->needsCopyRel(Type, *Body) &&
- isa<SharedSymbol<ELFT>>(*Body)) {
- continue;
- } else if (Target->isTlsDynReloc(Type, *Body)) {
- continue;
- } else if (Target->isSizeReloc(Type) && canBePreempted(Body, false)) {
- // A SIZE relocation is supposed to set a symbol size, but if a symbol
- // can be preempted, the size at runtime may be different than link time.
- // If that's the case, we leave the field alone rather than filling it
- // with a possibly incorrect value.
- continue;
- } else if (Config->EMachine == EM_MIPS) {
- if (Type == R_MIPS_HI16 && Body == Config->MipsGpDisp)
- SymVA = getMipsGpAddr<ELFT>() - AddrLoc;
- else if (Type == R_MIPS_LO16 && Body == Config->MipsGpDisp)
- SymVA = getMipsGpAddr<ELFT>() - AddrLoc + 4;
+ const unsigned Bits = sizeof(uintX_t) * 8;
+ for (const Relocation<ELFT> &Rel : Relocations) {
+ uintX_t Offset = Rel.InputSec->getOffset(Rel.Offset);
+ uint8_t *BufLoc = Buf + Offset;
+ uint32_t Type = Rel.Type;
+ uintX_t A = Rel.Addend;
+
+ uintX_t AddrLoc = OutSec->getVA() + Offset;
+ RelExpr Expr = Rel.Expr;
+ uint64_t SymVA =
+ SignExtend64<Bits>(getSymVA<ELFT>(Type, A, AddrLoc, *Rel.Sym, Expr));
+
+ switch (Expr) {
+ case R_RELAX_GOT_PC:
+ case R_RELAX_GOT_PC_NOPIC:
+ Target->relaxGot(BufLoc, SymVA);
+ break;
+ case R_RELAX_TLS_IE_TO_LE:
+ Target->relaxTlsIeToLe(BufLoc, Type, SymVA);
+ break;
+ case R_RELAX_TLS_LD_TO_LE:
+ Target->relaxTlsLdToLe(BufLoc, Type, SymVA);
+ break;
+ case R_RELAX_TLS_GD_TO_LE:
+ case R_RELAX_TLS_GD_TO_LE_NEG:
+ Target->relaxTlsGdToLe(BufLoc, Type, SymVA);
+ break;
+ case R_RELAX_TLS_GD_TO_IE:
+ case R_RELAX_TLS_GD_TO_IE_ABS:
+ case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
+ case R_RELAX_TLS_GD_TO_IE_END:
+ Target->relaxTlsGdToIe(BufLoc, Type, SymVA);
+ break;
+ case R_PPC_PLT_OPD:
+ // Patch a nop (0x60000000) to a ld.
+ if (BufLoc + 8 <= BufEnd && read32be(BufLoc + 4) == 0x60000000)
+ write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1)
+ // fallthrough
+ default:
+ Target->relocateOne(BufLoc, Type, SymVA);
+ break;
}
- uintX_t Size = getSymSize<ELFT>(*Body);
- Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A,
- findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs));
}
}
template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) {
if (this->Header->sh_type == SHT_NOBITS)
return;
+ ELFFile<ELFT> &EObj = this->File->getObj();
+
+ // If -r is given, then an InputSection may be a relocation section.
+ if (this->Header->sh_type == SHT_RELA) {
+ copyRelocations(Buf + OutSecOff, EObj.relas(this->Header));
+ return;
+ }
+ if (this->Header->sh_type == SHT_REL) {
+ copyRelocations(Buf + OutSecOff, EObj.rels(this->Header));
+ return;
+ }
+
// Copy section contents from source object file to output file.
ArrayRef<uint8_t> Data = this->getSectionData();
memcpy(Buf + OutSecOff, Data.data(), Data.size());
- ELFFile<ELFT> &EObj = this->File->getObj();
- uint8_t *BufEnd = Buf + OutSecOff + Data.size();
// Iterate over all relocation sections that apply to this section.
- for (const Elf_Shdr *RelSec : this->RelocSections) {
- if (RelSec->sh_type == SHT_RELA)
- this->relocate(Buf, BufEnd, EObj.relas(RelSec));
- else
- this->relocate(Buf, BufEnd, EObj.rels(RelSec));
+ uint8_t *BufEnd = Buf + OutSecOff + Data.size();
+ this->relocate(Buf, BufEnd);
+
+ // The section might have a data/code generated by the linker and need
+ // to be written after the section. Usually these are thunks - small piece
+ // of code used to jump between "incompatible" functions like PIC and non-PIC
+ // or if the jump target too far and its address does not fit to the short
+ // jump istruction.
+ if (!Thunks.empty()) {
+ Buf += OutSecOff + getThunkOff();
+ for (const Thunk<ELFT> *T : Thunks) {
+ T->writeTo(Buf);
+ Buf += T->size();
+ }
}
}
template <class ELFT>
+void InputSection<ELFT>::replace(InputSection<ELFT> *Other) {
+ this->Alignment = std::max(this->Alignment, Other->Alignment);
+ Other->Repl = this->Repl;
+ Other->Live = false;
+}
+
+template <class ELFT>
SplitInputSection<ELFT>::SplitInputSection(
- ObjectFile<ELFT> *File, const Elf_Shdr *Header,
+ elf::ObjectFile<ELFT> *File, const Elf_Shdr *Header,
typename InputSectionBase<ELFT>::Kind SectionKind)
: InputSectionBase<ELFT>(File, Header, SectionKind) {}
template <class ELFT>
-EHInputSection<ELFT>::EHInputSection(ObjectFile<ELFT> *F,
+EhInputSection<ELFT>::EhInputSection(elf::ObjectFile<ELFT> *F,
const Elf_Shdr *Header)
: SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::EHFrame) {
// Mark .eh_frame sections as live by default because there are
// usually no relocations that point to .eh_frames. Otherwise,
- // the garbage collector would drop all .eh_frame sections.
+ // the garbage collector would drop all .eh_frame sections.
this->Live = true;
}
template <class ELFT>
-bool EHInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
+bool EhInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
return S->SectionKind == InputSectionBase<ELFT>::EHFrame;
}
+// .eh_frame is a sequence of CIE or FDE records.
+// This function splits an input section into records and returns them.
+template <class ELFT>
+void EhInputSection<ELFT>::split() {
+ ArrayRef<uint8_t> Data = this->getSectionData();
+ for (size_t Off = 0, End = Data.size(); Off != End;) {
+ size_t Size = readEhRecordSize<ELFT>(Data.slice(Off));
+ this->Pieces.emplace_back(Off, Data.slice(Off, Size));
+ // The empty record is the end marker.
+ if (Size == 4)
+ break;
+ Off += Size;
+ }
+}
+
template <class ELFT>
-typename EHInputSection<ELFT>::uintX_t
-EHInputSection<ELFT>::getOffset(uintX_t Offset) {
+typename ELFT::uint EhInputSection<ELFT>::getOffset(uintX_t Offset) const {
// The file crtbeginT.o has relocations pointing to the start of an empty
// .eh_frame that is known to be the first in the link. It does that to
// identify the start of the output .eh_frame. Handle this special case.
if (this->getSectionHdr()->sh_size == 0)
return Offset;
- std::pair<uintX_t, uintX_t> *I = this->getRangeAndSize(Offset).first;
- uintX_t Base = I->second;
- if (Base == uintX_t(-1))
+ const SectionPiece *Piece = this->getSectionPiece(Offset);
+ if (Piece->OutputOff == size_t(-1))
return -1; // Not in the output
- uintX_t Addend = Offset - I->first;
- return Base + Addend;
+ uintX_t Addend = Offset - Piece->InputOff;
+ return Piece->OutputOff + Addend;
+}
+
+static size_t findNull(ArrayRef<uint8_t> A, size_t EntSize) {
+ // Optimize the common case.
+ StringRef S((const char *)A.data(), A.size());
+ if (EntSize == 1)
+ return S.find(0);
+
+ for (unsigned I = 0, N = S.size(); I != N; I += EntSize) {
+ const char *B = S.begin() + I;
+ if (std::all_of(B, B + EntSize, [](char C) { return C == 0; }))
+ return I;
+ }
+ return StringRef::npos;
+}
+
+// Split SHF_STRINGS section. Such section is a sequence of
+// null-terminated strings.
+static std::vector<SectionPiece> splitStrings(ArrayRef<uint8_t> Data,
+ size_t EntSize) {
+ std::vector<SectionPiece> V;
+ size_t Off = 0;
+ while (!Data.empty()) {
+ size_t End = findNull(Data, EntSize);
+ if (End == StringRef::npos)
+ fatal("string is not null terminated");
+ size_t Size = End + EntSize;
+ V.emplace_back(Off, Data.slice(0, Size));
+ Data = Data.slice(Size);
+ Off += Size;
+ }
+ return V;
+}
+
+// Split non-SHF_STRINGS section. Such section is a sequence of
+// fixed size records.
+static std::vector<SectionPiece> splitNonStrings(ArrayRef<uint8_t> Data,
+ size_t EntSize) {
+ std::vector<SectionPiece> V;
+ size_t Size = Data.size();
+ assert((Size % EntSize) == 0);
+ for (unsigned I = 0, N = Size; I != N; I += EntSize)
+ V.emplace_back(I, Data.slice(I, EntSize));
+ return V;
}
template <class ELFT>
-MergeInputSection<ELFT>::MergeInputSection(ObjectFile<ELFT> *F,
+MergeInputSection<ELFT>::MergeInputSection(elf::ObjectFile<ELFT> *F,
const Elf_Shdr *Header)
: SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::Merge) {}
+template <class ELFT> void MergeInputSection<ELFT>::splitIntoPieces() {
+ ArrayRef<uint8_t> Data = this->getSectionData();
+ uintX_t EntSize = this->Header->sh_entsize;
+ if (this->Header->sh_flags & SHF_STRINGS)
+ this->Pieces = splitStrings(Data, EntSize);
+ else
+ this->Pieces = splitNonStrings(Data, EntSize);
+
+ if (Config->GcSections)
+ for (uintX_t Off : LiveOffsets)
+ this->getSectionPiece(Off)->Live = true;
+}
+
template <class ELFT>
bool MergeInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
return S->SectionKind == InputSectionBase<ELFT>::Merge;
}
+// Do binary search to get a section piece at a given input offset.
template <class ELFT>
-std::pair<std::pair<typename ELFFile<ELFT>::uintX_t,
- typename ELFFile<ELFT>::uintX_t> *,
- typename ELFFile<ELFT>::uintX_t>
-SplitInputSection<ELFT>::getRangeAndSize(uintX_t Offset) {
+SectionPiece *SplitInputSection<ELFT>::getSectionPiece(uintX_t Offset) {
+ auto *This = static_cast<const SplitInputSection<ELFT> *>(this);
+ return const_cast<SectionPiece *>(This->getSectionPiece(Offset));
+}
+
+template <class ELFT>
+const SectionPiece *
+SplitInputSection<ELFT>::getSectionPiece(uintX_t Offset) const {
ArrayRef<uint8_t> D = this->getSectionData();
StringRef Data((const char *)D.data(), D.size());
uintX_t Size = Data.size();
if (Offset >= Size)
- error("Entry is past the end of the section");
+ fatal("entry is past the end of the section");
// Find the element this offset points to.
auto I = std::upper_bound(
- Offsets.begin(), Offsets.end(), Offset,
- [](const uintX_t &A, const std::pair<uintX_t, uintX_t> &B) {
- return A < B.first;
- });
- uintX_t End = I == Offsets.end() ? Data.size() : I->first;
+ Pieces.begin(), Pieces.end(), Offset,
+ [](const uintX_t &A, const SectionPiece &B) { return A < B.InputOff; });
--I;
- return std::make_pair(&*I, End);
+ return &*I;
}
+// Returns the offset in an output section for a given input offset.
+// Because contents of a mergeable section is not contiguous in output,
+// it is not just an addition to a base output offset.
template <class ELFT>
-typename MergeInputSection<ELFT>::uintX_t
-MergeInputSection<ELFT>::getOffset(uintX_t Offset) {
- std::pair<std::pair<uintX_t, uintX_t> *, uintX_t> T =
- this->getRangeAndSize(Offset);
- std::pair<uintX_t, uintX_t> *I = T.first;
- uintX_t End = T.second;
- uintX_t Start = I->first;
-
- // Compute the Addend and if the Base is cached, return.
- uintX_t Addend = Offset - Start;
- uintX_t &Base = I->second;
- if (Base != uintX_t(-1))
- return Base + Addend;
-
- // Map the base to the offset in the output section and cache it.
- ArrayRef<uint8_t> D = this->getSectionData();
- StringRef Data((const char *)D.data(), D.size());
- StringRef Entry = Data.substr(Start, End - Start);
- Base =
- static_cast<MergeOutputSection<ELFT> *>(this->OutSec)->getOffset(Entry);
- return Base + Addend;
+typename ELFT::uint MergeInputSection<ELFT>::getOffset(uintX_t Offset) const {
+ auto It = OffsetMap.find(Offset);
+ if (It != OffsetMap.end())
+ return It->second;
+
+ // If Offset is not at beginning of a section piece, it is not in the map.
+ // In that case we need to search from the original section piece vector.
+ const SectionPiece &Piece = *this->getSectionPiece(Offset);
+ assert(Piece.Live);
+ uintX_t Addend = Offset - Piece.InputOff;
+ return Piece.OutputOff + Addend;
+}
+
+// Create a map from input offsets to output offsets for all section pieces.
+// It is called after finalize().
+template <class ELFT> void MergeInputSection<ELFT>::finalizePieces() {
+ OffsetMap.grow(this->Pieces.size());
+ for (SectionPiece &Piece : this->Pieces) {
+ if (!Piece.Live)
+ continue;
+ if (Piece.OutputOff == size_t(-1)) {
+ // Offsets of tail-merged strings are computed lazily.
+ auto *OutSec = static_cast<MergeOutputSection<ELFT> *>(this->OutSec);
+ ArrayRef<uint8_t> D = Piece.data();
+ StringRef S((const char *)D.data(), D.size());
+ Piece.OutputOff = OutSec->getOffset(S);
+ }
+ OffsetMap[Piece.InputOff] = Piece.OutputOff;
+ }
}
template <class ELFT>
-MipsReginfoInputSection<ELFT>::MipsReginfoInputSection(ObjectFile<ELFT> *F,
+MipsReginfoInputSection<ELFT>::MipsReginfoInputSection(elf::ObjectFile<ELFT> *F,
const Elf_Shdr *Hdr)
: InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsReginfo) {
// Initialize this->Reginfo.
ArrayRef<uint8_t> D = this->getSectionData();
- if (D.size() != sizeof(Elf_Mips_RegInfo<ELFT>))
- error("Invalid size of .reginfo section");
+ if (D.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) {
+ error("invalid size of .reginfo section");
+ return;
+ }
Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(D.data());
}
@@ -366,31 +625,67 @@ bool MipsReginfoInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
return S->SectionKind == InputSectionBase<ELFT>::MipsReginfo;
}
-namespace lld {
-namespace elf2 {
-template class InputSectionBase<object::ELF32LE>;
-template class InputSectionBase<object::ELF32BE>;
-template class InputSectionBase<object::ELF64LE>;
-template class InputSectionBase<object::ELF64BE>;
-
-template class InputSection<object::ELF32LE>;
-template class InputSection<object::ELF32BE>;
-template class InputSection<object::ELF64LE>;
-template class InputSection<object::ELF64BE>;
-
-template class EHInputSection<object::ELF32LE>;
-template class EHInputSection<object::ELF32BE>;
-template class EHInputSection<object::ELF64LE>;
-template class EHInputSection<object::ELF64BE>;
-
-template class MergeInputSection<object::ELF32LE>;
-template class MergeInputSection<object::ELF32BE>;
-template class MergeInputSection<object::ELF64LE>;
-template class MergeInputSection<object::ELF64BE>;
-
-template class MipsReginfoInputSection<object::ELF32LE>;
-template class MipsReginfoInputSection<object::ELF32BE>;
-template class MipsReginfoInputSection<object::ELF64LE>;
-template class MipsReginfoInputSection<object::ELF64BE>;
+template <class ELFT>
+MipsOptionsInputSection<ELFT>::MipsOptionsInputSection(elf::ObjectFile<ELFT> *F,
+ const Elf_Shdr *Hdr)
+ : InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsOptions) {
+ // Find ODK_REGINFO option in the section's content.
+ ArrayRef<uint8_t> D = this->getSectionData();
+ while (!D.empty()) {
+ if (D.size() < sizeof(Elf_Mips_Options<ELFT>)) {
+ error("invalid size of .MIPS.options section");
+ break;
+ }
+ auto *O = reinterpret_cast<const Elf_Mips_Options<ELFT> *>(D.data());
+ if (O->kind == ODK_REGINFO) {
+ Reginfo = &O->getRegInfo();
+ break;
+ }
+ D = D.slice(O->size);
+ }
}
+
+template <class ELFT>
+bool MipsOptionsInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
+ return S->SectionKind == InputSectionBase<ELFT>::MipsOptions;
}
+
+template bool elf::isDiscarded<ELF32LE>(InputSectionBase<ELF32LE> *);
+template bool elf::isDiscarded<ELF32BE>(InputSectionBase<ELF32BE> *);
+template bool elf::isDiscarded<ELF64LE>(InputSectionBase<ELF64LE> *);
+template bool elf::isDiscarded<ELF64BE>(InputSectionBase<ELF64BE> *);
+
+template class elf::InputSectionBase<ELF32LE>;
+template class elf::InputSectionBase<ELF32BE>;
+template class elf::InputSectionBase<ELF64LE>;
+template class elf::InputSectionBase<ELF64BE>;
+
+template class elf::InputSection<ELF32LE>;
+template class elf::InputSection<ELF32BE>;
+template class elf::InputSection<ELF64LE>;
+template class elf::InputSection<ELF64BE>;
+
+template class elf::SplitInputSection<ELF32LE>;
+template class elf::SplitInputSection<ELF32BE>;
+template class elf::SplitInputSection<ELF64LE>;
+template class elf::SplitInputSection<ELF64BE>;
+
+template class elf::EhInputSection<ELF32LE>;
+template class elf::EhInputSection<ELF32BE>;
+template class elf::EhInputSection<ELF64LE>;
+template class elf::EhInputSection<ELF64BE>;
+
+template class elf::MergeInputSection<ELF32LE>;
+template class elf::MergeInputSection<ELF32BE>;
+template class elf::MergeInputSection<ELF64LE>;
+template class elf::MergeInputSection<ELF64BE>;
+
+template class elf::MipsReginfoInputSection<ELF32LE>;
+template class elf::MipsReginfoInputSection<ELF32BE>;
+template class elf::MipsReginfoInputSection<ELF64LE>;
+template class elf::MipsReginfoInputSection<ELF64BE>;
+
+template class elf::MipsOptionsInputSection<ELF32LE>;
+template class elf::MipsOptionsInputSection<ELF32BE>;
+template class elf::MipsOptionsInputSection<ELF64LE>;
+template class elf::MipsOptionsInputSection<ELF64BE>;
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
index 26956c72a960..61a89c540c5d 100644
--- a/ELF/InputSection.h
+++ b/ELF/InputSection.h
@@ -11,12 +11,22 @@
#define LLD_ELF_INPUT_SECTION_H
#include "Config.h"
+#include "Relocations.h"
+#include "Thunks.h"
#include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Object/ELF.h"
namespace lld {
-namespace elf2 {
+namespace elf {
+template <class ELFT> bool isDiscarded(InputSectionBase<ELFT> *S);
+
+class SymbolBody;
+
+template <class ELFT> class ICF;
+template <class ELFT> class DefinedRegular;
template <class ELFT> class ObjectFile;
template <class ELFT> class OutputSection;
template <class ELFT> class OutputSectionBase;
@@ -24,120 +34,148 @@ template <class ELFT> class OutputSectionBase;
// This corresponds to a section of an input file.
template <class ELFT> class InputSectionBase {
protected:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Chdr Elf_Chdr;
+ typedef typename ELFT::Rel Elf_Rel;
+ typedef typename ELFT::Rela Elf_Rela;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::uint uintX_t;
const Elf_Shdr *Header;
// The file this section is from.
ObjectFile<ELFT> *File;
+ // If a section is compressed, this vector has uncompressed section data.
+ SmallVector<char, 0> Uncompressed;
+
public:
- enum Kind { Regular, EHFrame, Merge, MipsReginfo };
+ enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions };
Kind SectionKind;
+ InputSectionBase() : Repl(this) {}
+
InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
Kind SectionKind);
OutputSectionBase<ELFT> *OutSec = nullptr;
+ uint32_t Alignment;
// Used for garbage collection.
- // Live bit makes sense only when Config->GcSections is true.
- bool isLive() const { return !Config->GcSections || Live; }
- bool Live = false;
+ bool Live;
+
+ // This pointer points to the "real" instance of this instance.
+ // Usually Repl == this. However, if ICF merges two sections,
+ // Repl pointer of one section points to another section. So,
+ // if you need to get a pointer to this instance, do not use
+ // this but instead this->Repl.
+ InputSectionBase<ELFT> *Repl;
// Returns the size of this section (even if this is a common or BSS.)
- size_t getSize() const { return Header->sh_size; }
+ size_t getSize() const;
static InputSectionBase<ELFT> Discarded;
StringRef getSectionName() const;
const Elf_Shdr *getSectionHdr() const { return Header; }
ObjectFile<ELFT> *getFile() const { return File; }
-
- // The writer sets and uses the addresses.
- uintX_t getAlign() {
- // The ELF spec states that a value of 0 means the section has no alignment
- // constraits.
- return std::max<uintX_t>(Header->sh_addralign, 1);
- }
-
- uintX_t getOffset(const Elf_Sym &Sym);
+ uintX_t getOffset(const DefinedRegular<ELFT> &Sym) const;
// Translate an offset in the input section to an offset in the output
// section.
- uintX_t getOffset(uintX_t Offset);
+ uintX_t getOffset(uintX_t Offset) const;
ArrayRef<uint8_t> getSectionData() const;
- // Returns a section that Rel is pointing to. Used by the garbage collector.
- InputSectionBase<ELFT> *getRelocTarget(const Elf_Rel &Rel);
- InputSectionBase<ELFT> *getRelocTarget(const Elf_Rela &Rel);
+ void uncompress();
+
+ void relocate(uint8_t *Buf, uint8_t *BufEnd);
+ std::vector<Relocation<ELFT>> Relocations;
+
+ bool Compressed;
+};
+
+template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded;
+
+// SectionPiece represents a piece of splittable section contents.
+struct SectionPiece {
+ SectionPiece(size_t Off, ArrayRef<uint8_t> Data)
+ : InputOff(Off), Data((const uint8_t *)Data.data()), Size(Data.size()),
+ Live(!Config->GcSections) {}
- template <bool isRela>
- using RelIteratorRange =
- llvm::iterator_range<const llvm::object::Elf_Rel_Impl<ELFT, isRela> *>;
+ ArrayRef<uint8_t> data() { return {Data, Size}; }
+ size_t size() const { return Size; }
- template <bool isRela>
- void relocate(uint8_t *Buf, uint8_t *BufEnd, RelIteratorRange<isRela> Rels);
+ size_t InputOff;
+ size_t OutputOff = -1;
private:
- template <bool isRela>
- uint8_t *findMipsPairedReloc(uint8_t *Buf, uint32_t SymIndex, uint32_t Type,
- RelIteratorRange<isRela> Rels);
-};
+ // We use bitfields because SplitInputSection is accessed by
+ // std::upper_bound very often.
+ // We want to save bits to make it cache friendly.
+ const uint8_t *Data;
+ uint32_t Size : 31;
-template <class ELFT>
-InputSectionBase<ELFT>
- InputSectionBase<ELFT>::Discarded(nullptr, nullptr,
- InputSectionBase<ELFT>::Regular);
+public:
+ uint32_t Live : 1;
+};
// Usually sections are copied to the output as atomic chunks of data,
// but some special types of sections are split into small pieces of data
// and each piece is copied to a different place in the output.
// This class represents such special sections.
template <class ELFT> class SplitInputSection : public InputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::uint uintX_t;
public:
SplitInputSection(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
typename InputSectionBase<ELFT>::Kind SectionKind);
- // For each piece of data, we maintain the offsets in the input section and
- // in the output section. The latter may be -1 if it is not assigned yet.
- std::vector<std::pair<uintX_t, uintX_t>> Offsets;
+ // Splittable sections are handled as a sequence of data
+ // rather than a single large blob of data.
+ std::vector<SectionPiece> Pieces;
- std::pair<std::pair<uintX_t, uintX_t> *, uintX_t>
- getRangeAndSize(uintX_t Offset);
+ // Returns the SectionPiece at a given input section offset.
+ SectionPiece *getSectionPiece(uintX_t Offset);
+ const SectionPiece *getSectionPiece(uintX_t Offset) const;
};
// This corresponds to a SHF_MERGE section of an input file.
template <class ELFT> class MergeInputSection : public SplitInputSection<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::Shdr Elf_Shdr;
public:
MergeInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
static bool classof(const InputSectionBase<ELFT> *S);
- // Translate an offset in the input section to an offset in the output
- // section.
- uintX_t getOffset(uintX_t Offset);
+ void splitIntoPieces();
+
+ // Mark the piece at a given offset live. Used by GC.
+ void markLiveAt(uintX_t Offset) { LiveOffsets.insert(Offset); }
+
+ // Translate an offset in the input section to an offset
+ // in the output section.
+ uintX_t getOffset(uintX_t Offset) const;
+
+ void finalizePieces();
+
+private:
+ llvm::DenseMap<uintX_t, uintX_t> OffsetMap;
+ llvm::DenseSet<uintX_t> LiveOffsets;
};
// This corresponds to a .eh_frame section of an input file.
-template <class ELFT> class EHInputSection : public SplitInputSection<ELFT> {
+template <class ELFT> class EhInputSection : public SplitInputSection<ELFT> {
public:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- EHInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::uint uintX_t;
+ EhInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
static bool classof(const InputSectionBase<ELFT> *S);
+ void split();
// Translate an offset in the input section to an offset in the output
// section.
- uintX_t getOffset(uintX_t Offset);
+ uintX_t getOffset(uintX_t Offset) const;
// Relocation section that refer to this one.
const Elf_Shdr *RelocSection = nullptr;
@@ -145,12 +183,13 @@ public:
// This corresponds to a non SHF_MERGE section of an input file.
template <class ELFT> class InputSection : public InputSectionBase<ELFT> {
+ friend ICF<ELFT>;
typedef InputSectionBase<ELFT> Base;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Rela Elf_Rela;
+ typedef typename ELFT::Rel Elf_Rel;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::uint uintX_t;
public:
InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
@@ -160,13 +199,41 @@ public:
void writeTo(uint8_t *Buf);
// Relocation sections that refer to this one.
- SmallVector<const Elf_Shdr *, 1> RelocSections;
+ llvm::TinyPtrVector<const Elf_Shdr *> RelocSections;
// The offset from beginning of the output sections this section was assigned
// to. The writer sets a value.
uint64_t OutSecOff = 0;
static bool classof(const InputSectionBase<ELFT> *S);
+
+ InputSectionBase<ELFT> *getRelocatedSection();
+
+ // Register thunk related to the symbol. When the section is written
+ // to a mmap'ed file, target is requested to write an actual thunk code.
+ // Now thunks is supported for MIPS and ARM target only.
+ void addThunk(const Thunk<ELFT> *T);
+
+ // The offset of synthetic thunk code from beginning of this section.
+ uint64_t getThunkOff() const;
+
+ // Size of chunk with thunks code.
+ uint64_t getThunksSize() const;
+
+ template <class RelTy>
+ void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
+
+private:
+ template <class RelTy>
+ void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
+
+ // Called by ICF to merge two input sections.
+ void replace(InputSection<ELFT> *Other);
+
+ // Used by ICF.
+ uint64_t GroupId = 0;
+
+ llvm::TinyPtrVector<const Thunk<ELFT> *> Thunks;
};
// MIPS .reginfo section provides information on the registers used by the code
@@ -177,16 +244,27 @@ public:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
template <class ELFT>
class MipsReginfoInputSection : public InputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename ELFT::Shdr Elf_Shdr;
public:
MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
static bool classof(const InputSectionBase<ELFT> *S);
- const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo;
+ const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo = nullptr;
+};
+
+template <class ELFT>
+class MipsOptionsInputSection : public InputSectionBase<ELFT> {
+ typedef typename ELFT::Shdr Elf_Shdr;
+
+public:
+ MipsOptionsInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
+ static bool classof(const InputSectionBase<ELFT> *S);
+
+ const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo = nullptr;
};
-} // namespace elf2
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/LTO.cpp b/ELF/LTO.cpp
new file mode 100644
index 000000000000..0e8006a3b32a
--- /dev/null
+++ b/ELF/LTO.cpp
@@ -0,0 +1,325 @@
+//===- LTO.cpp ------------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LTO.h"
+#include "Config.h"
+#include "Driver.h"
+#include "Error.h"
+#include "InputFiles.h"
+#include "Symbols.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/Analysis/LoopPassManager.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/CodeGen/ParallelCG.h"
+#include "llvm/IR/AutoUpgrade.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/LTO/legacy/UpdateCompilerUsed.h"
+#include "llvm/Linker/IRMover.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::ELF;
+
+using namespace lld;
+using namespace lld::elf;
+
+// This is for use when debugging LTO.
+static void saveBuffer(StringRef Buffer, const Twine &Path) {
+ std::error_code EC;
+ raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
+ if (EC)
+ error(EC, "cannot create " + Path);
+ OS << Buffer;
+}
+
+// This is for use when debugging LTO.
+static void saveBCFile(Module &M, const Twine &Path) {
+ std::error_code EC;
+ raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
+ if (EC)
+ error(EC, "cannot create " + Path);
+ WriteBitcodeToFile(&M, OS, /* ShouldPreserveUseListOrder */ true);
+}
+
+static void runNewCustomLtoPasses(Module &M, TargetMachine &TM) {
+ PassBuilder PB(&TM);
+
+ AAManager AA;
+
+ // Parse a custom AA pipeline if asked to.
+ if (!PB.parseAAPipeline(AA, Config->LtoAAPipeline)) {
+ error("Unable to parse AA pipeline description: " + Config->LtoAAPipeline);
+ return;
+ }
+
+ LoopAnalysisManager LAM;
+ FunctionAnalysisManager FAM;
+ CGSCCAnalysisManager CGAM;
+ ModuleAnalysisManager MAM;
+
+ // Register the AA manager first so that our version is the one used.
+ FAM.registerPass([&] { return std::move(AA); });
+
+ // Register all the basic analyses with the managers.
+ PB.registerModuleAnalyses(MAM);
+ PB.registerCGSCCAnalyses(CGAM);
+ PB.registerFunctionAnalyses(FAM);
+ PB.registerLoopAnalyses(LAM);
+ PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+ ModulePassManager MPM;
+ if (!Config->DisableVerify)
+ MPM.addPass(VerifierPass());
+
+ // Now, add all the passes we've been requested to.
+ if (!PB.parsePassPipeline(MPM, Config->LtoNewPmPasses)) {
+ error("unable to parse pass pipeline description: " +
+ Config->LtoNewPmPasses);
+ return;
+ }
+
+ if (!Config->DisableVerify)
+ MPM.addPass(VerifierPass());
+ MPM.run(M, MAM);
+}
+
+static void runOldLtoPasses(Module &M, TargetMachine &TM) {
+ // Note that the gold plugin has a similar piece of code, so
+ // it is probably better to move this code to a common place.
+ legacy::PassManager LtoPasses;
+ LtoPasses.add(createTargetTransformInfoWrapperPass(TM.getTargetIRAnalysis()));
+ PassManagerBuilder PMB;
+ PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM.getTargetTriple()));
+ PMB.Inliner = createFunctionInliningPass();
+ PMB.VerifyInput = PMB.VerifyOutput = !Config->DisableVerify;
+ PMB.LoopVectorize = true;
+ PMB.SLPVectorize = true;
+ PMB.OptLevel = Config->LtoO;
+ PMB.populateLTOPassManager(LtoPasses);
+ LtoPasses.run(M);
+}
+
+static void runLTOPasses(Module &M, TargetMachine &TM) {
+ if (!Config->LtoNewPmPasses.empty()) {
+ // The user explicitly asked for a set of passes to be run.
+ // This needs the new PM to work as there's no clean way to
+ // pass a set of passes to run in the legacy PM.
+ runNewCustomLtoPasses(M, TM);
+ if (HasError)
+ return;
+ } else {
+ // Run the 'default' set of LTO passes. This code still uses
+ // the legacy PM as the new one is not the default.
+ runOldLtoPasses(M, TM);
+ }
+
+ if (Config->SaveTemps)
+ saveBCFile(M, Config->OutputFile + ".lto.opt.bc");
+}
+
+static bool shouldInternalize(const SmallPtrSet<GlobalValue *, 8> &Used,
+ Symbol *S, GlobalValue *GV) {
+ if (S->IsUsedInRegularObj || Used.count(GV))
+ return false;
+ return !S->includeInDynsym();
+}
+
+BitcodeCompiler::BitcodeCompiler()
+ : Combined(new Module("ld-temp.o", Driver->Context)) {}
+
+static void undefine(Symbol *S) {
+ replaceBody<Undefined>(S, S->body()->getName(), STV_DEFAULT, S->body()->Type,
+ nullptr);
+}
+
+static void handleUndefinedAsmRefs(const BasicSymbolRef &Sym, GlobalValue *GV,
+ StringSet<> &AsmUndefinedRefs) {
+ // GV associated => not an assembly symbol, bail out.
+ if (GV)
+ return;
+
+ // This is an undefined reference to a symbol in asm. We put that in
+ // compiler.used, so that we can preserve it from being dropped from
+ // the output, without necessarily preventing its internalization.
+ SmallString<64> Name;
+ raw_svector_ostream OS(Name);
+ Sym.printName(OS);
+ AsmUndefinedRefs.insert(Name.str());
+}
+
+void BitcodeCompiler::add(BitcodeFile &F) {
+ std::unique_ptr<IRObjectFile> Obj = std::move(F.Obj);
+ std::vector<GlobalValue *> Keep;
+ unsigned BodyIndex = 0;
+ ArrayRef<Symbol *> Syms = F.getSymbols();
+
+ Module &M = Obj->getModule();
+ if (M.getDataLayoutStr().empty())
+ fatal("invalid bitcode file: " + F.getName() + " has no datalayout");
+
+ // Discard non-compatible debug infos if necessary.
+ M.materializeMetadata();
+ UpgradeDebugInfo(M);
+
+ // If a symbol appears in @llvm.used, the linker is required
+ // to treat the symbol as there is a reference to the symbol
+ // that it cannot see. Therefore, we can't internalize.
+ SmallPtrSet<GlobalValue *, 8> Used;
+ collectUsedGlobalVariables(M, Used, /* CompilerUsed */ false);
+
+ for (const BasicSymbolRef &Sym : Obj->symbols()) {
+ uint32_t Flags = Sym.getFlags();
+ GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl());
+ if (GV && GV->hasAppendingLinkage())
+ Keep.push_back(GV);
+ if (BitcodeFile::shouldSkip(Flags))
+ continue;
+ Symbol *S = Syms[BodyIndex++];
+ if (Flags & BasicSymbolRef::SF_Undefined) {
+ handleUndefinedAsmRefs(Sym, GV, AsmUndefinedRefs);
+ continue;
+ }
+ auto *B = dyn_cast<DefinedBitcode>(S->body());
+ if (!B || B->file() != &F)
+ continue;
+
+ // We collect the set of symbols we want to internalize here
+ // and change the linkage after the IRMover executed, i.e. after
+ // we imported the symbols and satisfied undefined references
+ // to it. We can't just change linkage here because otherwise
+ // the IRMover will just rename the symbol.
+ if (GV && shouldInternalize(Used, S, GV))
+ InternalizedSyms.insert(GV->getName());
+
+ // At this point we know that either the combined LTO object will provide a
+ // definition of a symbol, or we will internalize it. In either case, we
+ // need to undefine the symbol. In the former case, the real definition
+ // needs to be able to replace the original definition without conflicting.
+ // In the latter case, we need to allow the combined LTO object to provide a
+ // definition with the same name, for example when doing parallel codegen.
+ undefine(S);
+
+ if (!GV)
+ // Module asm symbol.
+ continue;
+
+ switch (GV->getLinkage()) {
+ default:
+ break;
+ case GlobalValue::LinkOnceAnyLinkage:
+ GV->setLinkage(GlobalValue::WeakAnyLinkage);
+ break;
+ case GlobalValue::LinkOnceODRLinkage:
+ GV->setLinkage(GlobalValue::WeakODRLinkage);
+ break;
+ }
+
+ Keep.push_back(GV);
+ }
+
+ IRMover Mover(*Combined);
+ if (Error E = Mover.move(Obj->takeModule(), Keep,
+ [](GlobalValue &, IRMover::ValueAdder) {})) {
+ handleAllErrors(std::move(E), [&](const ErrorInfoBase &EIB) {
+ fatal("failed to link module " + F.getName() + ": " + EIB.message());
+ });
+ }
+}
+
+static void internalize(GlobalValue &GV) {
+ assert(!GV.hasLocalLinkage() &&
+ "Trying to internalize a symbol with local linkage!");
+ GV.setLinkage(GlobalValue::InternalLinkage);
+}
+
+std::vector<std::unique_ptr<InputFile>> BitcodeCompiler::runSplitCodegen(
+ const std::function<std::unique_ptr<TargetMachine>()> &TMFactory) {
+ unsigned NumThreads = Config->LtoJobs;
+ OwningData.resize(NumThreads);
+
+ std::list<raw_svector_ostream> OSs;
+ std::vector<raw_pwrite_stream *> OSPtrs;
+ for (SmallString<0> &Obj : OwningData) {
+ OSs.emplace_back(Obj);
+ OSPtrs.push_back(&OSs.back());
+ }
+
+ splitCodeGen(std::move(Combined), OSPtrs, {}, TMFactory);
+
+ std::vector<std::unique_ptr<InputFile>> ObjFiles;
+ for (SmallString<0> &Obj : OwningData)
+ ObjFiles.push_back(createObjectFile(
+ MemoryBufferRef(Obj, "LLD-INTERNAL-combined-lto-object")));
+
+ // If -save-temps is given, we need to save temporary objects to files.
+ // This is for debugging.
+ if (Config->SaveTemps) {
+ if (NumThreads == 1) {
+ saveBuffer(OwningData[0], Config->OutputFile + ".lto.o");
+ } else {
+ for (unsigned I = 0; I < NumThreads; ++I)
+ saveBuffer(OwningData[I], Config->OutputFile + Twine(I) + ".lto.o");
+ }
+ }
+
+ return ObjFiles;
+}
+
+// Merge all the bitcode files we have seen, codegen the result
+// and return the resulting ObjectFile.
+std::vector<std::unique_ptr<InputFile>> BitcodeCompiler::compile() {
+ for (const auto &Name : InternalizedSyms) {
+ GlobalValue *GV = Combined->getNamedValue(Name.first());
+ assert(GV);
+ internalize(*GV);
+ }
+
+ std::string TheTriple = Combined->getTargetTriple();
+ std::string Msg;
+ const Target *T = TargetRegistry::lookupTarget(TheTriple, Msg);
+ if (!T)
+ fatal("target not found: " + Msg);
+
+ // LLD supports the new relocations.
+ TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+ Options.RelaxELFRelocations = true;
+
+ auto CreateTargetMachine = [&]() {
+ return std::unique_ptr<TargetMachine>(T->createTargetMachine(
+ TheTriple, "", "", Options, Config->Pic ? Reloc::PIC_ : Reloc::Static));
+ };
+
+ std::unique_ptr<TargetMachine> TM = CreateTargetMachine();
+
+ // Update llvm.compiler.used so that optimizations won't strip
+ // off AsmUndefinedReferences.
+ updateCompilerUsed(*Combined, *TM, AsmUndefinedRefs);
+
+ if (Config->SaveTemps)
+ saveBCFile(*Combined, Config->OutputFile + ".lto.bc");
+
+ runLTOPasses(*Combined, *TM);
+ if (HasError)
+ return {};
+
+ return runSplitCodegen(CreateTargetMachine);
+}
diff --git a/ELF/LTO.h b/ELF/LTO.h
new file mode 100644
index 000000000000..81dffb6004b2
--- /dev/null
+++ b/ELF/LTO.h
@@ -0,0 +1,54 @@
+//===- LTO.h ----------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a way to combine bitcode files into one ELF
+// file by compiling them using LLVM.
+//
+// If LTO is in use, your input files are not in regular ELF files
+// but instead LLVM bitcode files. In that case, the linker has to
+// convert bitcode files into the native format so that we can create
+// an ELF file that contains native code. This file provides that
+// functionality.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_LTO_H
+#define LLD_ELF_LTO_H
+
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Linker/IRMover.h"
+
+namespace lld {
+namespace elf {
+
+class BitcodeFile;
+class InputFile;
+
+class BitcodeCompiler {
+public:
+ BitcodeCompiler();
+ void add(BitcodeFile &F);
+ std::vector<std::unique_ptr<InputFile>> compile();
+
+private:
+ std::vector<std::unique_ptr<InputFile>> runSplitCodegen(
+ const std::function<std::unique_ptr<llvm::TargetMachine>()> &TMFactory);
+
+ std::unique_ptr<llvm::Module> Combined;
+ std::vector<SmallString<0>> OwningData;
+ llvm::StringSet<> InternalizedSyms;
+ llvm::StringSet<> AsmUndefinedRefs;
+};
+}
+}
+
+#endif
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index a6df9ed48cdc..61abdc185e11 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -13,154 +13,366 @@
//
//===----------------------------------------------------------------------===//
+#include "LinkerScript.h"
#include "Config.h"
#include "Driver.h"
+#include "InputSection.h"
+#include "OutputSections.h"
+#include "ScriptParser.h"
+#include "Strings.h"
+#include "Symbols.h"
#include "SymbolTable.h"
+#include "Target.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ELF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::object;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
+ScriptConfiguration *elf::ScriptConfig;
+
+// This is an operator-precedence parser to parse and evaluate
+// a linker script expression. For each linker script arithmetic
+// expression (e.g. ". = . + 0x1000"), a new instance of ExprParser
+// is created and ran.
namespace {
-class LinkerScript {
+class ExprParser : public ScriptParserBase {
public:
- LinkerScript(BumpPtrAllocator *A, StringRef S, bool B)
- : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {}
- void run();
+ ExprParser(std::vector<StringRef> &Tokens, uint64_t Dot)
+ : ScriptParserBase(Tokens), Dot(Dot) {}
+
+ uint64_t run();
private:
- static std::vector<StringRef> tokenize(StringRef S);
- static StringRef skipSpace(StringRef S);
- StringRef next();
- bool skip(StringRef Tok);
- bool atEOF() { return Tokens.size() == Pos; }
- void expect(StringRef Expect);
+ uint64_t parsePrimary();
+ uint64_t parseTernary(uint64_t Cond);
+ uint64_t apply(StringRef Op, uint64_t L, uint64_t R);
+ uint64_t parseExpr1(uint64_t Lhs, int MinPrec);
+ uint64_t parseExpr();
- void addFile(StringRef Path);
+ uint64_t Dot;
+};
+}
- void readAsNeeded();
- void readEntry();
- void readExtern();
- void readGroup();
- void readInclude();
- void readOutput();
- void readOutputArch();
- void readOutputFormat();
- void readSearchDir();
- void readSections();
+static int precedence(StringRef Op) {
+ return StringSwitch<int>(Op)
+ .Case("*", 4)
+ .Case("/", 4)
+ .Case("+", 3)
+ .Case("-", 3)
+ .Case("<", 2)
+ .Case(">", 2)
+ .Case(">=", 2)
+ .Case("<=", 2)
+ .Case("==", 2)
+ .Case("!=", 2)
+ .Case("&", 1)
+ .Default(-1);
+}
- void readOutputSectionDescription();
+static uint64_t evalExpr(std::vector<StringRef> &Tokens, uint64_t Dot) {
+ return ExprParser(Tokens, Dot).run();
+}
- StringSaver Saver;
- std::vector<StringRef> Tokens;
- size_t Pos = 0;
- bool IsUnderSysroot;
-};
+uint64_t ExprParser::run() {
+ uint64_t V = parseExpr();
+ if (!atEOF() && !Error)
+ setError("stray token: " + peek());
+ return V;
}
-void LinkerScript::run() {
- while (!atEOF()) {
- StringRef Tok = next();
- if (Tok == ";")
- continue;
- if (Tok == "ENTRY") {
- readEntry();
- } else if (Tok == "EXTERN") {
- readExtern();
- } else if (Tok == "GROUP" || Tok == "INPUT") {
- readGroup();
- } else if (Tok == "INCLUDE") {
- readInclude();
- } else if (Tok == "OUTPUT") {
- readOutput();
- } else if (Tok == "OUTPUT_ARCH") {
- readOutputArch();
- } else if (Tok == "OUTPUT_FORMAT") {
- readOutputFormat();
- } else if (Tok == "SEARCH_DIR") {
- readSearchDir();
- } else if (Tok == "SECTIONS") {
- readSections();
- } else {
- error("unknown directive: " + Tok);
+// This is a part of the operator-precedence parser to evaluate
+// arithmetic expressions in SECTIONS command. This function evaluates an
+// integer literal, a parenthesized expression, the ALIGN function,
+// or the special variable ".".
+uint64_t ExprParser::parsePrimary() {
+ StringRef Tok = next();
+ if (Tok == ".")
+ return Dot;
+ if (Tok == "(") {
+ uint64_t V = parseExpr();
+ expect(")");
+ return V;
+ }
+ if (Tok == "ALIGN") {
+ expect("(");
+ uint64_t V = parseExpr();
+ expect(")");
+ return alignTo(Dot, V);
+ }
+ uint64_t V = 0;
+ if (Tok.getAsInteger(0, V))
+ setError("malformed number: " + Tok);
+ return V;
+}
+
+uint64_t ExprParser::parseTernary(uint64_t Cond) {
+ next();
+ uint64_t V = parseExpr();
+ expect(":");
+ uint64_t W = parseExpr();
+ return Cond ? V : W;
+}
+
+uint64_t ExprParser::apply(StringRef Op, uint64_t L, uint64_t R) {
+ if (Op == "*")
+ return L * R;
+ if (Op == "/") {
+ if (R == 0) {
+ error("division by zero");
+ return 0;
}
+ return L / R;
}
+ if (Op == "+")
+ return L + R;
+ if (Op == "-")
+ return L - R;
+ if (Op == "<")
+ return L < R;
+ if (Op == ">")
+ return L > R;
+ if (Op == ">=")
+ return L >= R;
+ if (Op == "<=")
+ return L <= R;
+ if (Op == "==")
+ return L == R;
+ if (Op == "!=")
+ return L != R;
+ if (Op == "&")
+ return L & R;
+ llvm_unreachable("invalid operator");
}
-// Split S into linker script tokens.
-std::vector<StringRef> LinkerScript::tokenize(StringRef S) {
- std::vector<StringRef> Ret;
- for (;;) {
- S = skipSpace(S);
- if (S.empty())
- return Ret;
-
- // Quoted token
- if (S.startswith("\"")) {
- size_t E = S.find("\"", 1);
- if (E == StringRef::npos)
- error("unclosed quote");
- Ret.push_back(S.substr(1, E));
- S = S.substr(E + 1);
- continue;
+// This is a part of the operator-precedence parser.
+// This function assumes that the remaining token stream starts
+// with an operator.
+uint64_t ExprParser::parseExpr1(uint64_t Lhs, int MinPrec) {
+ while (!atEOF()) {
+ // Read an operator and an expression.
+ StringRef Op1 = peek();
+ if (Op1 == "?")
+ return parseTernary(Lhs);
+ if (precedence(Op1) < MinPrec)
+ return Lhs;
+ next();
+ uint64_t Rhs = parsePrimary();
+
+ // Evaluate the remaining part of the expression first if the
+ // next operator has greater precedence than the previous one.
+ // For example, if we have read "+" and "3", and if the next
+ // operator is "*", then we'll evaluate 3 * ... part first.
+ while (!atEOF()) {
+ StringRef Op2 = peek();
+ if (precedence(Op2) <= precedence(Op1))
+ break;
+ Rhs = parseExpr1(Rhs, precedence(Op2));
}
- // Unquoted token
- size_t Pos = S.find_first_not_of(
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789_.$/\\~=+[]*?-:");
- // A character that cannot start a word (which is usually a
- // punctuation) forms a single character token.
- if (Pos == 0)
- Pos = 1;
- Ret.push_back(S.substr(0, Pos));
- S = S.substr(Pos);
+ Lhs = apply(Op1, Lhs, Rhs);
}
+ return Lhs;
+}
+
+// Reads and evaluates an arithmetic expression.
+uint64_t ExprParser::parseExpr() { return parseExpr1(parsePrimary(), 0); }
+
+template <class ELFT>
+StringRef LinkerScript<ELFT>::getOutputSection(InputSectionBase<ELFT> *S) {
+ for (SectionRule &R : Opt.Sections)
+ if (globMatch(R.SectionPattern, S->getSectionName()))
+ return R.Dest;
+ return "";
+}
+
+template <class ELFT>
+bool LinkerScript<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) {
+ return getOutputSection(S) == "/DISCARD/";
}
-// Skip leading whitespace characters or /**/-style comments.
-StringRef LinkerScript::skipSpace(StringRef S) {
- for (;;) {
- if (S.startswith("/*")) {
- size_t E = S.find("*/", 2);
- if (E == StringRef::npos)
- error("unclosed comment in a linker script");
- S = S.substr(E + 2);
+template <class ELFT>
+bool LinkerScript<ELFT>::shouldKeep(InputSectionBase<ELFT> *S) {
+ for (StringRef Pat : Opt.KeptSections)
+ if (globMatch(Pat, S->getSectionName()))
+ return true;
+ return false;
+}
+
+template <class ELFT>
+void LinkerScript<ELFT>::assignAddresses(
+ ArrayRef<OutputSectionBase<ELFT> *> Sections) {
+ // Orphan sections are sections present in the input files which
+ // are not explicitly placed into the output file by the linker script.
+ // We place orphan sections at end of file.
+ // Other linkers places them using some heuristics as described in
+ // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections.
+ for (OutputSectionBase<ELFT> *Sec : Sections) {
+ StringRef Name = Sec->getName();
+ if (getSectionIndex(Name) == INT_MAX)
+ Opt.Commands.push_back({SectionKind, {}, Name});
+ }
+
+ // Assign addresses as instructed by linker script SECTIONS sub-commands.
+ Dot = Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
+ uintX_t MinVA = std::numeric_limits<uintX_t>::max();
+ uintX_t ThreadBssOffset = 0;
+
+ for (SectionsCommand &Cmd : Opt.Commands) {
+ if (Cmd.Kind == AssignmentKind) {
+ uint64_t Val = evalExpr(Cmd.Expr, Dot);
+
+ if (Cmd.Name == ".") {
+ Dot = Val;
+ } else {
+ auto *D = cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd.Name));
+ D->Value = Val;
+ }
continue;
}
- size_t Size = S.size();
- S = S.ltrim();
- if (S.size() == Size)
- return S;
+
+ // Find all the sections with required name. There can be more than
+ // ont section with such name, if the alignment, flags or type
+ // attribute differs.
+ assert(Cmd.Kind == SectionKind);
+ for (OutputSectionBase<ELFT> *Sec : Sections) {
+ if (Sec->getName() != Cmd.Name)
+ continue;
+
+ if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
+ uintX_t TVA = Dot + ThreadBssOffset;
+ TVA = alignTo(TVA, Sec->getAlignment());
+ Sec->setVA(TVA);
+ ThreadBssOffset = TVA - Dot + Sec->getSize();
+ continue;
+ }
+
+ if (Sec->getFlags() & SHF_ALLOC) {
+ Dot = alignTo(Dot, Sec->getAlignment());
+ Sec->setVA(Dot);
+ MinVA = std::min(MinVA, Dot);
+ Dot += Sec->getSize();
+ continue;
+ }
+ }
}
+
+ // ELF and Program headers need to be right before the first section in
+ // memory.
+ // Set their addresses accordingly.
+ MinVA = alignDown(MinVA - Out<ELFT>::ElfHeader->getSize() -
+ Out<ELFT>::ProgramHeaders->getSize(),
+ Target->PageSize);
+ Out<ELFT>::ElfHeader->setVA(MinVA);
+ Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA);
}
-StringRef LinkerScript::next() {
- if (atEOF())
- error("unexpected EOF");
- return Tokens[Pos++];
+template <class ELFT>
+ArrayRef<uint8_t> LinkerScript<ELFT>::getFiller(StringRef Name) {
+ auto I = Opt.Filler.find(Name);
+ if (I == Opt.Filler.end())
+ return {};
+ return I->second;
}
-bool LinkerScript::skip(StringRef Tok) {
- if (atEOF())
- error("unexpected EOF");
- if (Tok != Tokens[Pos])
- return false;
- ++Pos;
- return true;
+// Returns the index of the given section name in linker script
+// SECTIONS commands. Sections are laid out as the same order as they
+// were in the script. If a given name did not appear in the script,
+// it returns INT_MAX, so that it will be laid out at end of file.
+template <class ELFT>
+int LinkerScript<ELFT>::getSectionIndex(StringRef Name) {
+ auto Begin = Opt.Commands.begin();
+ auto End = Opt.Commands.end();
+ auto I = std::find_if(Begin, End, [&](SectionsCommand &N) {
+ return N.Kind == SectionKind && N.Name == Name;
+ });
+ return I == End ? INT_MAX : (I - Begin);
}
-void LinkerScript::expect(StringRef Expect) {
- StringRef Tok = next();
- if (Tok != Expect)
- error(Expect + " expected, but got " + Tok);
+// A compartor to sort output sections. Returns -1 or 1 if
+// A or B are mentioned in linker script. Otherwise, returns 0.
+template <class ELFT>
+int LinkerScript<ELFT>::compareSections(StringRef A, StringRef B) {
+ int I = getSectionIndex(A);
+ int J = getSectionIndex(B);
+ if (I == INT_MAX && J == INT_MAX)
+ return 0;
+ return I < J ? -1 : 1;
+}
+
+template <class ELFT>
+void LinkerScript<ELFT>::addScriptedSymbols() {
+ for (SectionsCommand &Cmd : Opt.Commands)
+ if (Cmd.Kind == AssignmentKind)
+ if (Cmd.Name != "." && Symtab<ELFT>::X->find(Cmd.Name) == nullptr)
+ Symtab<ELFT>::X->addAbsolute(Cmd.Name, STV_DEFAULT);
}
-void LinkerScript::addFile(StringRef S) {
+class elf::ScriptParser : public ScriptParserBase {
+ typedef void (ScriptParser::*Handler)();
+
+public:
+ ScriptParser(StringRef S, bool B) : ScriptParserBase(S), IsUnderSysroot(B) {}
+
+ void run();
+
+private:
+ void addFile(StringRef Path);
+
+ void readAsNeeded();
+ void readEntry();
+ void readExtern();
+ void readGroup();
+ void readInclude();
+ void readNothing() {}
+ void readOutput();
+ void readOutputArch();
+ void readOutputFormat();
+ void readSearchDir();
+ void readSections();
+
+ void readLocationCounterValue();
+ void readOutputSectionDescription(StringRef OutSec);
+ void readSymbolAssignment(StringRef Name);
+ std::vector<StringRef> readSectionsCommandExpr();
+
+ const static StringMap<Handler> Cmd;
+ ScriptConfiguration &Opt = *ScriptConfig;
+ StringSaver Saver = {ScriptConfig->Alloc};
+ bool IsUnderSysroot;
+};
+
+const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = {
+ {"ENTRY", &ScriptParser::readEntry},
+ {"EXTERN", &ScriptParser::readExtern},
+ {"GROUP", &ScriptParser::readGroup},
+ {"INCLUDE", &ScriptParser::readInclude},
+ {"INPUT", &ScriptParser::readGroup},
+ {"OUTPUT", &ScriptParser::readOutput},
+ {"OUTPUT_ARCH", &ScriptParser::readOutputArch},
+ {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
+ {"SEARCH_DIR", &ScriptParser::readSearchDir},
+ {"SECTIONS", &ScriptParser::readSections},
+ {";", &ScriptParser::readNothing}};
+
+void ScriptParser::run() {
+ while (!atEOF()) {
+ StringRef Tok = next();
+ if (Handler Fn = Cmd.lookup(Tok))
+ (this->*Fn)();
+ else
+ setError("unknown directive: " + Tok);
+ }
+}
+
+void ScriptParser::addFile(StringRef S) {
if (IsUnderSysroot && S.startswith("/")) {
SmallString<128> Path;
(Config->Sysroot + S).toStringRef(Path);
@@ -178,22 +390,23 @@ void LinkerScript::addFile(StringRef S) {
else
Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
} else if (S.startswith("-l")) {
- Driver->addFile(searchLibrary(S.substr(2)));
+ Driver->addLibrary(S.substr(2));
} else if (sys::fs::exists(S)) {
Driver->addFile(S);
} else {
std::string Path = findFromSearchPaths(S);
if (Path.empty())
- error("Unable to find " + S);
- Driver->addFile(Saver.save(Path));
+ setError("unable to find " + S);
+ else
+ Driver->addFile(Saver.save(Path));
}
}
-void LinkerScript::readAsNeeded() {
+void ScriptParser::readAsNeeded() {
expect("(");
bool Orig = Config->AsNeeded;
Config->AsNeeded = true;
- for (;;) {
+ while (!Error) {
StringRef Tok = next();
if (Tok == ")")
break;
@@ -202,7 +415,7 @@ void LinkerScript::readAsNeeded() {
Config->AsNeeded = Orig;
}
-void LinkerScript::readEntry() {
+void ScriptParser::readEntry() {
// -e <symbol> takes predecence over ENTRY(<symbol>).
expect("(");
StringRef Tok = next();
@@ -211,9 +424,9 @@ void LinkerScript::readEntry() {
expect(")");
}
-void LinkerScript::readExtern() {
+void ScriptParser::readExtern() {
expect("(");
- for (;;) {
+ while (!Error) {
StringRef Tok = next();
if (Tok == ")")
return;
@@ -221,9 +434,9 @@ void LinkerScript::readExtern() {
}
}
-void LinkerScript::readGroup() {
+void ScriptParser::readGroup() {
expect("(");
- for (;;) {
+ while (!Error) {
StringRef Tok = next();
if (Tok == ")")
return;
@@ -235,17 +448,20 @@ void LinkerScript::readGroup() {
}
}
-void LinkerScript::readInclude() {
+void ScriptParser::readInclude() {
StringRef Tok = next();
auto MBOrErr = MemoryBuffer::getFile(Tok);
- error(MBOrErr, "cannot open " + Tok);
+ if (!MBOrErr) {
+ setError("cannot open " + Tok);
+ return;
+ }
std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
std::vector<StringRef> V = tokenize(S);
Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
}
-void LinkerScript::readOutput() {
+void ScriptParser::readOutput() {
// -o <file> takes predecence over OUTPUT(<file>).
expect("(");
StringRef Tok = next();
@@ -254,54 +470,121 @@ void LinkerScript::readOutput() {
expect(")");
}
-void LinkerScript::readOutputArch() {
+void ScriptParser::readOutputArch() {
// Error checking only for now.
expect("(");
next();
expect(")");
}
-void LinkerScript::readOutputFormat() {
+void ScriptParser::readOutputFormat() {
// Error checking only for now.
expect("(");
next();
StringRef Tok = next();
if (Tok == ")")
return;
- if (Tok != ",")
- error("unexpected token: " + Tok);
+ if (Tok != ",") {
+ setError("unexpected token: " + Tok);
+ return;
+ }
next();
expect(",");
next();
expect(")");
}
-void LinkerScript::readSearchDir() {
+void ScriptParser::readSearchDir() {
expect("(");
Config->SearchPaths.push_back(next());
expect(")");
}
-void LinkerScript::readSections() {
+void ScriptParser::readSections() {
+ Opt.DoLayout = true;
expect("{");
- while (!skip("}"))
- readOutputSectionDescription();
+ while (!Error && !skip("}")) {
+ StringRef Tok = peek();
+ if (Tok == ".") {
+ readLocationCounterValue();
+ continue;
+ }
+ next();
+ if (peek() == "=")
+ readSymbolAssignment(Tok);
+ else
+ readOutputSectionDescription(Tok);
+ }
}
-void LinkerScript::readOutputSectionDescription() {
- StringRef Name = next();
- std::vector<StringRef> &InputSections = Config->OutputSections[Name];
+void ScriptParser::readLocationCounterValue() {
+ expect(".");
+ expect("=");
+ std::vector<StringRef> Expr = readSectionsCommandExpr();
+ if (Expr.empty())
+ error("error in location counter expression");
+ else
+ Opt.Commands.push_back({AssignmentKind, std::move(Expr), "."});
+}
+void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
+ Opt.Commands.push_back({SectionKind, {}, OutSec});
expect(":");
expect("{");
- while (!skip("}")) {
- next(); // Skip input file name.
- expect("(");
- while (!skip(")"))
- InputSections.push_back(next());
+
+ while (!Error && !skip("}")) {
+ StringRef Tok = next();
+ if (Tok == "*") {
+ expect("(");
+ while (!Error && !skip(")"))
+ Opt.Sections.emplace_back(OutSec, next());
+ } else if (Tok == "KEEP") {
+ expect("(");
+ expect("*");
+ expect("(");
+ while (!Error && !skip(")")) {
+ StringRef Sec = next();
+ Opt.Sections.emplace_back(OutSec, Sec);
+ Opt.KeptSections.push_back(Sec);
+ }
+ expect(")");
+ } else {
+ setError("unknown command " + Tok);
+ }
+ }
+
+ StringRef Tok = peek();
+ if (Tok.startswith("=")) {
+ if (!Tok.startswith("=0x")) {
+ setError("filler should be a hexadecimal value");
+ return;
+ }
+ Tok = Tok.substr(3);
+ Opt.Filler[OutSec] = parseHex(Tok);
+ next();
}
}
+void ScriptParser::readSymbolAssignment(StringRef Name) {
+ expect("=");
+ std::vector<StringRef> Expr = readSectionsCommandExpr();
+ if (Expr.empty())
+ error("error in symbol assignment expression");
+ else
+ Opt.Commands.push_back({AssignmentKind, std::move(Expr), Name});
+}
+
+std::vector<StringRef> ScriptParser::readSectionsCommandExpr() {
+ std::vector<StringRef> Expr;
+ while (!Error) {
+ StringRef Tok = next();
+ if (Tok == ";")
+ break;
+ Expr.push_back(Tok);
+ }
+ return Expr;
+}
+
static bool isUnderSysroot(StringRef Path) {
if (Config->Sysroot == "")
return false;
@@ -311,8 +594,13 @@ static bool isUnderSysroot(StringRef Path) {
return false;
}
-// Entry point. The other functions or classes are private to this file.
-void elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
+// Entry point.
+void elf::readLinkerScript(MemoryBufferRef MB) {
StringRef Path = MB.getBufferIdentifier();
- LinkerScript(A, MB.getBuffer(), isUnderSysroot(Path)).run();
+ ScriptParser(MB.getBuffer(), isUnderSysroot(Path)).run();
}
+
+template class elf::LinkerScript<ELF32LE>;
+template class elf::LinkerScript<ELF32BE>;
+template class elf::LinkerScript<ELF64LE>;
+template class elf::LinkerScript<ELF64BE>;
diff --git a/ELF/LinkerScript.h b/ELF/LinkerScript.h
new file mode 100644
index 000000000000..768f78a66468
--- /dev/null
+++ b/ELF/LinkerScript.h
@@ -0,0 +1,103 @@
+//===- LinkerScript.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_LINKER_SCRIPT_H
+#define LLD_ELF_LINKER_SCRIPT_H
+
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace lld {
+namespace elf {
+
+// Parses a linker script. Calling this function updates
+// Config and ScriptConfig.
+void readLinkerScript(MemoryBufferRef MB);
+
+class ScriptParser;
+template <class ELFT> class InputSectionBase;
+template <class ELFT> class OutputSectionBase;
+
+// This class represents each rule in SECTIONS command.
+struct SectionRule {
+ SectionRule(StringRef D, StringRef S)
+ : Dest(D), SectionPattern(S) {}
+
+ StringRef Dest;
+
+ StringRef SectionPattern;
+};
+
+// This enum represents what we can observe in SECTIONS tag of script:
+// ExprKind is a location counter change, like ". = . + 0x1000"
+// SectionKind is a description of output section, like ".data :..."
+enum SectionsCommandKind { SectionKind, AssignmentKind };
+
+struct SectionsCommand {
+ SectionsCommandKind Kind;
+ std::vector<StringRef> Expr;
+ StringRef Name;
+};
+
+// ScriptConfiguration holds linker script parse results.
+struct ScriptConfiguration {
+ // SECTIONS commands.
+ std::vector<SectionRule> Sections;
+
+ // Section fill attribute for each section.
+ llvm::StringMap<std::vector<uint8_t>> Filler;
+
+ // Used to assign addresses to sections.
+ std::vector<SectionsCommand> Commands;
+
+ bool DoLayout = false;
+
+ llvm::BumpPtrAllocator Alloc;
+
+ // List of section patterns specified with KEEP commands. They will
+ // be kept even if they are unused and --gc-sections is specified.
+ std::vector<StringRef> KeptSections;
+};
+
+extern ScriptConfiguration *ScriptConfig;
+
+// This is a runner of the linker script.
+template <class ELFT> class LinkerScript {
+ typedef typename ELFT::uint uintX_t;
+
+public:
+ StringRef getOutputSection(InputSectionBase<ELFT> *S);
+ ArrayRef<uint8_t> getFiller(StringRef Name);
+ bool isDiscarded(InputSectionBase<ELFT> *S);
+ bool shouldKeep(InputSectionBase<ELFT> *S);
+ void assignAddresses(ArrayRef<OutputSectionBase<ELFT> *> S);
+ int compareSections(StringRef A, StringRef B);
+ void addScriptedSymbols();
+
+private:
+ // "ScriptConfig" is a bit too long, so define a short name for it.
+ ScriptConfiguration &Opt = *ScriptConfig;
+
+ int getSectionIndex(StringRef Name);
+
+ uintX_t Dot;
+};
+
+// Variable template is a C++14 feature, so we can't template
+// a global variable. Use a struct to workaround.
+template <class ELFT> struct Script { static LinkerScript<ELFT> *X; };
+template <class ELFT> LinkerScript<ELFT> *Script<ELFT>::X;
+
+} // namespace elf
+} // namespace lld
+
+#endif
diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp
index f682f3b8b473..41e30ce599d2 100644
--- a/ELF/MarkLive.cpp
+++ b/ELF/MarkLive.cpp
@@ -21,9 +21,12 @@
//===----------------------------------------------------------------------===//
#include "InputSection.h"
+#include "LinkerScript.h"
#include "OutputSections.h"
+#include "Strings.h"
#include "SymbolTable.h"
#include "Symbols.h"
+#include "Target.h"
#include "Writer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELF.h"
@@ -35,30 +38,78 @@ using namespace llvm::ELF;
using namespace llvm::object;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
+
+// A resolved relocation. The Sec and Offset fields are set if the relocation
+// was resolved to an offset within a section.
+template <class ELFT>
+struct ResolvedReloc {
+ InputSectionBase<ELFT> *Sec;
+ typename ELFT::uint Offset;
+};
-// Calls Fn for each section that Sec refers to via relocations.
template <class ELFT>
-static void forEachSuccessor(InputSection<ELFT> *Sec,
- std::function<void(InputSectionBase<ELFT> *)> Fn) {
- typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
-
- ELFFile<ELFT> &Obj = Sec->getFile()->getObj();
- for (const Elf_Shdr *RelSec : Sec->RelocSections) {
- if (RelSec->sh_type == SHT_RELA) {
- for (const Elf_Rela &RI : Obj.relas(RelSec))
- if (InputSectionBase<ELFT> *Succ = Sec->getRelocTarget(RI))
- Fn(Succ);
- } else {
- for (const Elf_Rel &RI : Obj.rels(RelSec))
- if (InputSectionBase<ELFT> *Succ = Sec->getRelocTarget(RI))
- Fn(Succ);
- }
+static typename ELFT::uint getAddend(InputSectionBase<ELFT> &Sec,
+ const typename ELFT::Rel &Rel) {
+ return Target->getImplicitAddend(Sec.getSectionData().begin(),
+ Rel.getType(Config->Mips64EL));
+}
+
+template <class ELFT>
+static typename ELFT::uint getAddend(InputSectionBase<ELFT> &Sec,
+ const typename ELFT::Rela &Rel) {
+ return Rel.r_addend;
+}
+
+template <class ELFT, class RelT>
+static ResolvedReloc<ELFT> resolveReloc(InputSectionBase<ELFT> &Sec,
+ RelT &Rel) {
+ SymbolBody &B = Sec.getFile()->getRelocTargetSym(Rel);
+ auto *D = dyn_cast<DefinedRegular<ELFT>>(&B);
+ if (!D || !D->Section)
+ return {nullptr, 0};
+ typename ELFT::uint Offset = D->Value;
+ if (D->isSection())
+ Offset += getAddend(Sec, Rel);
+ return {D->Section->Repl, Offset};
+}
+
+template <class ELFT, class Elf_Shdr>
+static void run(ELFFile<ELFT> &Obj, InputSectionBase<ELFT> &Sec,
+ Elf_Shdr *RelSec, std::function<void(ResolvedReloc<ELFT>)> Fn) {
+ if (RelSec->sh_type == SHT_RELA) {
+ for (const typename ELFT::Rela &RI : Obj.relas(RelSec))
+ Fn(resolveReloc(Sec, RI));
+ } else {
+ for (const typename ELFT::Rel &RI : Obj.rels(RelSec))
+ Fn(resolveReloc(Sec, RI));
}
}
+// Calls Fn for each section that Sec refers to via relocations.
+template <class ELFT>
+static void forEachSuccessor(InputSection<ELFT> &Sec,
+ std::function<void(ResolvedReloc<ELFT>)> Fn) {
+ ELFFile<ELFT> &Obj = Sec.getFile()->getObj();
+ for (const typename ELFT::Shdr *RelSec : Sec.RelocSections)
+ run(Obj, Sec, RelSec, Fn);
+}
+
+template <class ELFT>
+static void scanEhFrameSection(EhInputSection<ELFT> &EH,
+ std::function<void(ResolvedReloc<ELFT>)> Fn) {
+ if (!EH.RelocSection)
+ return;
+ ELFFile<ELFT> &EObj = EH.getFile()->getObj();
+ run<ELFT>(EObj, EH, EH.RelocSection, [&](ResolvedReloc<ELFT> R) {
+ if (!R.Sec || R.Sec == &InputSection<ELFT>::Discarded)
+ return;
+ if (R.Sec->getSectionHdr()->sh_flags & SHF_EXECINSTR)
+ return;
+ Fn({R.Sec, 0});
+ });
+}
+
// Sections listed below are special because they are used by the loader
// just by being in an ELF file. They should not be garbage-collected.
template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) {
@@ -70,6 +121,12 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) {
return true;
default:
StringRef S = Sec->getSectionName();
+
+ // We do not want to reclaim sections if they can be referred
+ // by __start_* and __stop_* symbols.
+ if (isValidCIdentifier(S))
+ return true;
+
return S.startswith(".ctors") || S.startswith(".dtors") ||
S.startswith(".init") || S.startswith(".fini") ||
S.startswith(".jcr");
@@ -79,52 +136,66 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) {
// This is the main function of the garbage collector.
// Starting from GC-root sections, this function visits all reachable
// sections to set their "Live" bits.
-template <class ELFT> void elf2::markLive(SymbolTable<ELFT> *Symtab) {
+template <class ELFT> void elf::markLive() {
SmallVector<InputSection<ELFT> *, 256> Q;
- auto Enqueue = [&](InputSectionBase<ELFT> *Sec) {
- if (!Sec || Sec->Live)
+ auto Enqueue = [&](ResolvedReloc<ELFT> R) {
+ if (!R.Sec)
+ return;
+
+ // Usually, a whole section is marked as live or dead, but in mergeable
+ // (splittable) sections, each piece of data has independent liveness bit.
+ // So we explicitly tell it which offset is in use.
+ if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(R.Sec))
+ MS->markLiveAt(R.Offset);
+
+ if (R.Sec->Live)
return;
- Sec->Live = true;
- if (InputSection<ELFT> *S = dyn_cast<InputSection<ELFT>>(Sec))
+ R.Sec->Live = true;
+ if (InputSection<ELFT> *S = dyn_cast<InputSection<ELFT>>(R.Sec))
Q.push_back(S);
};
- auto MarkSymbol = [&](SymbolBody *Sym) {
- if (Sym)
- if (auto *D = dyn_cast<DefinedRegular<ELFT>>(Sym->repl()))
- Enqueue(D->Section);
+ auto MarkSymbol = [&](const SymbolBody *Sym) {
+ if (auto *D = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym))
+ Enqueue({D->Section, D->Value});
};
// Add GC root symbols.
- MarkSymbol(Config->EntrySym);
- MarkSymbol(Symtab->find(Config->Init));
- MarkSymbol(Symtab->find(Config->Fini));
+ if (Config->EntrySym)
+ MarkSymbol(Config->EntrySym->body());
+ MarkSymbol(Symtab<ELFT>::X->find(Config->Init));
+ MarkSymbol(Symtab<ELFT>::X->find(Config->Fini));
for (StringRef S : Config->Undefined)
- MarkSymbol(Symtab->find(S));
+ MarkSymbol(Symtab<ELFT>::X->find(S));
// Preserve externally-visible symbols if the symbols defined by this
// file can interrupt other ELF file's symbols at runtime.
- if (Config->Shared || Config->ExportDynamic) {
- for (const std::pair<StringRef, Symbol *> &P : Symtab->getSymbols()) {
- SymbolBody *B = P.second->Body;
- if (B->getVisibility() == STV_DEFAULT)
- MarkSymbol(B);
- }
- }
+ for (const Symbol *S : Symtab<ELFT>::X->getSymbols())
+ if (S->includeInDynsym())
+ MarkSymbol(S->body());
- // Preserve special sections.
- for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles())
+ // Preserve special sections and those which are specified in linker
+ // script KEEP command.
+ for (const std::unique_ptr<ObjectFile<ELFT>> &F :
+ Symtab<ELFT>::X->getObjectFiles())
for (InputSectionBase<ELFT> *Sec : F->getSections())
- if (Sec && Sec != &InputSection<ELFT>::Discarded && isReserved(Sec))
- Enqueue(Sec);
+ if (Sec && Sec != &InputSection<ELFT>::Discarded) {
+ // .eh_frame is always marked as live now, but also it can reference to
+ // sections that contain personality. We preserve all non-text sections
+ // referred by .eh_frame here.
+ if (auto *EH = dyn_cast_or_null<EhInputSection<ELFT>>(Sec))
+ scanEhFrameSection<ELFT>(*EH, Enqueue);
+ if (isReserved(Sec) || Script<ELFT>::X->shouldKeep(Sec))
+ Enqueue({Sec, 0});
+ }
// Mark all reachable sections.
while (!Q.empty())
- forEachSuccessor<ELFT>(Q.pop_back_val(), Enqueue);
+ forEachSuccessor<ELFT>(*Q.pop_back_val(), Enqueue);
}
-template void elf2::markLive<ELF32LE>(SymbolTable<ELF32LE> *);
-template void elf2::markLive<ELF32BE>(SymbolTable<ELF32BE> *);
-template void elf2::markLive<ELF64LE>(SymbolTable<ELF64LE> *);
-template void elf2::markLive<ELF64BE>(SymbolTable<ELF64BE> *);
+template void elf::markLive<ELF32LE>();
+template void elf::markLive<ELF32BE>();
+template void elf::markLive<ELF64LE>();
+template void elf::markLive<ELF64BE>();
diff --git a/ELF/Options.td b/ELF/Options.td
index 1b02c5c8b795..010f37687f03 100644
--- a/ELF/Options.td
+++ b/ELF/Options.td
@@ -1,165 +1,276 @@
include "llvm/Option/OptParser.td"
-def Bsymbolic: Flag<["-"], "Bsymbolic">,
- HelpText<"Bind defined symbols locally">;
+// For options whose names are multiple letters, either one dash or
+// two can precede the option name except those that start with 'o'.
+class F<string name>: Flag<["--", "-"], name>;
+class J<string name>: Joined<["--", "-"], name>;
+class S<string name>: Separate<["--", "-"], name>;
+class JS<string name>: JoinedOrSeparate<["--", "-"], name>;
-def Bdynamic: Flag<["-"], "Bdynamic">,
- HelpText<"Link against shared libraries">;
+def Bsymbolic: F<"Bsymbolic">, HelpText<"Bind defined symbols locally">;
-def Bstatic: Flag<["-"], "Bstatic">,
- HelpText<"Do not link against shared libraries">;
+def Bsymbolic_functions: F<"Bsymbolic-functions">,
+ HelpText<"Bind defined function symbols locally">;
-def L : JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
- HelpText<"Directory to search for libraries">;
+def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">;
-def O : Joined<["-"], "O">, HelpText<"Optimize">;
+def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
-def allow_multiple_definition: Flag<["--"], "allow-multiple-definition">,
- HelpText<"Allow multiple definitions">;
+def build_id: F<"build-id">, HelpText<"Generate build ID note">;
+
+def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">;
+
+def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
+ HelpText<"Add a directory to the library search path">;
+
+def O: Joined<["-"], "O">, HelpText<"Optimize output file size">;
-def allow_shlib_undefined : Flag<["--", "-"], "allow-shlib-undefined">;
+def allow_multiple_definition: F<"allow-multiple-definition">,
+ HelpText<"Allow multiple definitions">;
-def as_needed : Flag<["--"], "as-needed">;
+def as_needed: F<"as-needed">,
+ HelpText<"Only set DT_NEEDED for shared libraries if used">;
-def disable_new_dtags : Flag<["--"], "disable-new-dtags">,
+def disable_new_dtags: F<"disable-new-dtags">,
HelpText<"Disable new dynamic tags">;
-def discard_all : Flag<["-"], "discard-all">,
- HelpText<"Delete all local symbols">;
+def discard_all: F<"discard-all">, HelpText<"Delete all local symbols">;
-def discard_locals : Flag<["-"], "discard-locals">,
+def discard_locals: F<"discard-locals">,
HelpText<"Delete temporary local symbols">;
-def discard_none : Flag<["-"], "discard-none">,
+def discard_none: F<"discard-none">,
HelpText<"Keep all symbols in the symbol table">;
-def dynamic_linker : Separate<["--", "-"], "dynamic-linker">,
+def dynamic_linker: S<"dynamic-linker">,
HelpText<"Which dynamic linker to use">;
-def enable_new_dtags : Flag<["--"], "enable-new-dtags">,
+def dynamic_list: S<"dynamic-list">,
+ HelpText<"Read a list of dynamic symbols">;
+
+def eh_frame_hdr: F<"eh-frame-hdr">,
+ HelpText<"Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header">;
+
+def enable_new_dtags: F<"enable-new-dtags">,
HelpText<"Enable new dynamic tags">;
-def entry : Separate<["--", "-"], "entry">, MetaVarName<"<entry>">,
+def end_lib: F<"end-lib">,
+ HelpText<"End a grouping of objects that should be treated as if they were together in an archive">;
+
+def entry: S<"entry">, MetaVarName<"<entry>">,
HelpText<"Name of entry point symbol">;
-def export_dynamic : Flag<["--", "-"], "export-dynamic">,
+def export_dynamic: F<"export-dynamic">,
HelpText<"Put symbols in the dynamic symbol table">;
-def fini : Separate<["-"], "fini">, MetaVarName<"<symbol>">,
+def export_dynamic_symbol: S<"export-dynamic-symbol">,
+ HelpText<"Put a symbol in the dynamic symbol table">;
+
+def fatal_warnings: F<"fatal-warnings">,
+ HelpText<"Treat warnings as errors">;
+
+def fini: S<"fini">, MetaVarName<"<symbol>">,
HelpText<"Specify a finalizer function">;
-def hash_style : Separate<["--", "-"], "hash-style">,
+def hash_style: S<"hash-style">,
HelpText<"Specify hash style (sysv, gnu or both)">;
-def gc_sections : Flag<["--"], "gc-sections">,
+def help: F<"help">, HelpText<"Print option help">;
+
+def icf: F<"icf=all">, HelpText<"Enable identical code folding">;
+
+def image_base : J<"image-base=">, HelpText<"Set the base address">;
+
+def gc_sections: F<"gc-sections">,
HelpText<"Enable garbage collection of unused sections">;
-def init : Separate<["-"], "init">, MetaVarName<"<symbol>">,
+def init: S<"init">, MetaVarName<"<symbol>">,
HelpText<"Specify an initializer function">;
-def l : JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
+def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
HelpText<"Root name of library to use">;
-def m : JoinedOrSeparate<["-"], "m">,
- HelpText<"Set target emulation">;
+def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">,
+ HelpText<"Optimization level for LTO">;
+
+def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
+
+def no_as_needed: F<"no-as-needed">,
+ HelpText<"Always DT_NEEDED for shared libraries">;
-def no_allow_shlib_undefined : Flag<["--"], "no-allow-shlib-undefined">;
+def no_demangle: F<"no-demangle">,
+ HelpText<"Do not demangle symbol names">;
-def no_as_needed : Flag<["--"], "no-as-needed">;
+def no_gnu_unique: F<"no-gnu-unique">,
+ HelpText<"Disable STB_GNU_UNIQUE symbol binding">;
-def no_whole_archive : Flag<["--", "-"], "no-whole-archive">,
+def no_whole_archive: F<"no-whole-archive">,
HelpText<"Restores the default behavior of loading archive members">;
-def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
+def noinhibit_exec: F<"noinhibit-exec">,
HelpText<"Retain the executable output file whenever it is still usable">;
-def no_undefined : Flag<["--"], "no-undefined">,
+def no_undefined: F<"no-undefined">,
HelpText<"Report unresolved symbols even if the linker is creating a shared library">;
-def o : Separate<["-"], "o">, MetaVarName<"<path>">,
+def no_undefined_version: F<"no-undefined-version">,
+ HelpText<"Report version scripts that refer undefined symbols">;
+
+def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
HelpText<"Path to file to write output">;
-def print_gc_sections: Flag<["--"], "print-gc-sections">,
+def pie: F<"pie">, HelpText<"Create a position independent executable">;
+
+def print_gc_sections: F<"print-gc-sections">,
HelpText<"List removed unused sections">;
-def rpath : Separate<["-"], "rpath">,
- HelpText<"Add a DT_RUNPATH to the output">;
+def reproduce: S<"reproduce">,
+ HelpText<"Dump linker invocation and input files for debugging">;
+
+def rpath: S<"rpath">, HelpText<"Add a DT_RUNPATH to the output">;
+
+def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">;
+
+def script: S<"script">, HelpText<"Read linker script">;
+
+def shared: F<"shared">, HelpText<"Build a shared object">;
+
+def soname: J<"soname=">, HelpText<"Set DT_SONAME">;
-def relocatable : Flag<["--"], "relocatable">;
+def start_lib: F<"start-lib">,
+ HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">;
-def script : Separate<["--"], "script">, HelpText<"Read linker script">;
+def strip_all: F<"strip-all">, HelpText<"Strip all symbols">;
-def shared : Flag<["-"], "shared">,
- HelpText<"Build a shared object">;
+def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;
-def soname : Joined<["-"], "soname=">,
- HelpText<"Set DT_SONAME">;
+def sysroot: J<"sysroot=">, HelpText<"Set the system root">;
-def strip_all : Flag<["--"], "strip-all">,
- HelpText<"Strip all symbols">;
+def threads: F<"threads">, HelpText<"Enable use of threads">;
-def sysroot : Joined<["--"], "sysroot=">,
- HelpText<"Set the system root">;
+def trace: F<"trace">, HelpText<"Print the names of the input files">;
-def undefined : Joined<["--"], "undefined=">,
+def trace_symbol : J<"trace-symbol=">, HelpText<"Trace references to symbols">;
+
+def undefined: J<"undefined=">,
HelpText<"Force undefined symbol during linking">;
-def verbose : Flag<["--"], "verbose">;
+def unresolved_symbols: J<"unresolved-symbols=">,
+ HelpText<"Determine how to handle unresolved symbols">;
+
+def rsp_quoting: J<"rsp-quoting=">,
+ HelpText<"Quoting style for response files. Values supported: windows|posix">;
+
+def verbose: F<"verbose">, HelpText<"Verbose mode">;
+
+def version: F<"version">, HelpText<"Display the version number">;
-def whole_archive : Flag<["--", "-"], "whole-archive">,
+def version_script: S<"version-script">,
+ HelpText<"Read a version script">;
+
+def warn_common: F<"warn-common">,
+ HelpText<"Warn about duplicate common symbols">;
+
+def whole_archive: F<"whole-archive">,
HelpText<"Force load of all members in a static library">;
-def wrap : Separate<["--", "-"], "wrap">, MetaVarName<"<symbol>">,
+def wrap: S<"wrap">, MetaVarName<"<symbol>">,
HelpText<"Use wrapper functions for symbol">;
-def z : JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
+def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
HelpText<"Linker option extensions">;
// Aliases
-def alias_Bdynamic_call_shared: Flag<["-"], "call_shared">, Alias<Bdynamic>;
-def alias_Bdynamic_dy: Flag<["-"], "dy">, Alias<Bdynamic>;
-def alias_Bstatic_dn: Flag<["-"], "dn">, Alias<Bstatic>;
-def alias_Bstatic_non_shared: Flag<["-"], "non_shared">, Alias<Bstatic>;
-def alias_Bstatic_static: Flag<["-"], "static">, Alias<Bstatic>;
-def alias_L__library_path : Joined<["--"], "library-path=">, Alias<L>;
+def alias_Bdynamic_call_shared: F<"call_shared">, Alias<Bdynamic>;
+def alias_Bdynamic_dy: F<"dy">, Alias<Bdynamic>;
+def alias_Bstatic_dn: F<"dn">, Alias<Bstatic>;
+def alias_Bstatic_non_shared: F<"non_shared">, Alias<Bstatic>;
+def alias_Bstatic_static: F<"static">, Alias<Bstatic>;
+def alias_L__library_path: J<"library-path=">, Alias<L>;
def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
-def alias_entry_e : Separate<["-"], "e">, Alias<entry>;
+def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>;
+def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>;
+def alias_entry_entry: J<"entry=">, Alias<entry>;
def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>;
-def alias_fini_fini : Joined<["-"], "fini=">, Alias<fini>;
-def alias_hash_style_hash_style : Joined<["--", "-"], "hash-style=">, Alias<hash_style>;
-def alias_init_init : Joined<["-"], "init=">, Alias<init>;
-def alias_l__library : Joined<["--"], "library=">, Alias<l>;
-def alias_o_output : Joined<["--"], "output=">, Alias<o>;
-def alias_rpath_rpath : Joined<["-"], "rpath=">, Alias<rpath>;
-def alias_relocatable_r : Flag<["-"], "r">, Alias<relocatable>;
-def alias_shared_Bshareable : Flag<["-"], "Bshareable">, Alias<shared>;
-def alias_soname_h : Separate<["-"], "h">, Alias<soname>;
-def alias_soname_soname : Separate<["-"], "soname">, Alias<soname>;
-def alias_script_T : Separate<["-"], "T">, Alias<script>;
+def alias_export_dynamic_symbol: J<"export-dynamic-symbol=">,
+ Alias<export_dynamic_symbol>;
+def alias_fini_fini: J<"fini=">, Alias<fini>;
+def alias_hash_style_hash_style: J<"hash-style=">, Alias<hash_style>;
+def alias_init_init: J<"init=">, Alias<init>;
+def alias_l__library: J<"library=">, Alias<l>;
+def alias_o_output: Joined<["--"], "output=">, Alias<o>;
+def alias_pie_pic_executable: F<"pic-executable">, Alias<pie>;
+def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>;
+def alias_rpath_R: Joined<["-"], "R">, Alias<rpath>;
+def alias_rpath_rpath: J<"rpath=">, Alias<rpath>;
+def alias_script_T: JoinedOrSeparate<["-"], "T">, Alias<script>;
+def alias_shared_Bshareable: F<"Bshareable">, Alias<shared>;
+def alias_soname_h: JoinedOrSeparate<["-"], "h">, Alias<soname>;
+def alias_soname_soname: S<"soname">, Alias<soname>;
def alias_strip_all: Flag<["-"], "s">, Alias<strip_all>;
-def alias_undefined_u : Separate<["-"], "u">, Alias<undefined>;
-def alias_wrap_wrap : Joined<["--", "-"], "wrap=">, Alias<wrap>;
+def alias_strip_debug_S: Flag<["-"], "S">, Alias<strip_debug>;
+def alias_trace: Flag<["-"], "t">, Alias<trace>;
+def alias_trace_symbol_y : JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>;
+def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>;
+def alias_version_V: Flag<["-"], "V">, Alias<version>;
+def alias_version_v: Flag<["-"], "v">, Alias<version>;
+def alias_wrap_wrap: J<"wrap=">, Alias<wrap>;
// Our symbol resolution algorithm handles symbols in archive files differently
// than traditional linkers, so we don't need --start-group and --end-group.
// These options are recongized for compatibility but ignored.
-def end_group : Flag<["--"], "end-group">;
+def end_group: F<"end-group">;
def end_group_paren: Flag<["-"], ")">;
-def start_group : Flag<["--"], "start-group">;
+def start_group: F<"start-group">;
def start_group_paren: Flag<["-"], "(">;
+// Ignore LTO plugin-related options.
+// clang -flto passes -plugin and -plugin-opt to the linker. This is required
+// for ld.gold and ld.bfd to get LTO working. But it's not for lld which doesn't
+// rely on a plugin. Instead of detecting which linker is used on clang side we
+// just ignore the option on lld side as it's easier. In fact, the linker could
+// be called 'ld' and understanding which linker is used would require parsing of
+// --version output.
+def plugin: S<"plugin">;
+def plugin_eq: J<"plugin=">;
+def plugin_opt: S<"plugin-opt">;
+def plugin_opt_eq: J<"plugin-opt=">;
+
// Options listed below are silently ignored for now for compatibility.
-def build_id : Flag<["--"], "build-id">;
-def eh_frame_hdr : Flag<["--"], "eh-frame-hdr">;
-def fatal_warnings : Flag<["--"], "fatal-warnings">;
-def no_add_needed : Flag<["--"], "no-add-needed">;
-def no_fatal_warnings : Flag<["--"], "no-fatal-warnings">;
-def no_warn_mismatch : Flag<["--"], "no-warn-mismatch">;
-def version_script : Separate<["--"], "version-script">;
-def warn_common : Flag<["--"], "warn-common">;
-def warn_shared_textrel : Flag<["--"], "warn-shared-textrel">;
-def G : Separate<["-"], "G">;
+def allow_shlib_undefined: F<"allow-shlib-undefined">;
+def define_common: F<"define-common">;
+def demangle: F<"demangle">;
+def detect_odr_violations: F<"detect-odr-violations">;
+def no_add_needed: F<"no-add-needed">;
+def no_allow_shlib_undefined: F<"no-allow-shlib-undefined">;
+def no_copy_dt_needed_entries: F<"no-copy-dt-needed-entries">,
+ Alias<no_add_needed>;
+def no_dynamic_linker: F<"no-dynamic-linker">;
+def no_fatal_warnings: F<"no-fatal-warnings">;
+def no_mmap_output_file: F<"no-mmap-output-file">;
+def no_warn_common: F<"no-warn-common">;
+def no_warn_mismatch: F<"no-warn-mismatch">;
+def rpath_link: S<"rpath-link">;
+def rpath_link_eq: J<"rpath-link=">;
+def sort_common: F<"sort-common">;
+def warn_execstack: F<"warn-execstack">;
+def warn_shared_textrel: F<"warn-shared-textrel">;
+def G: Separate<["-"], "G">;
// Aliases for ignored options
-def alias_version_script_version_script : Joined<["--"], "version-script=">, Alias<version_script>;
+def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>;
+def alias_define_common_dc: F<"dc">, Alias<define_common>;
+def alias_define_common_dp: F<"dp">, Alias<define_common>;
+def alias_version_script_version_script: J<"version-script=">,
+ Alias<version_script>;
+
+// LTO-related options.
+def lto_jobs: J<"lto-jobs=">, HelpText<"Number of threads to run codegen">;
+def lto_aa_pipeline: J<"lto-aa-pipeline=">,
+ HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">;
+def lto_newpm_passes: J<"lto-newpm-passes=">,
+ HelpText<"Passes to run during LTO">;
+def disable_verify: F<"disable-verify">;
+def mllvm: S<"mllvm">;
+def save_temps: F<"save-temps">;
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index 2aa814524d6b..50b94015f229 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -9,19 +9,26 @@
#include "OutputSections.h"
#include "Config.h"
+#include "EhFrame.h"
+#include "LinkerScript.h"
+#include "Strings.h"
#include "SymbolTable.h"
#include "Target.h"
+#include "lld/Core/Parallel.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/SHA1.h"
+#include <map>
using namespace llvm;
+using namespace llvm::dwarf;
using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::ELF;
using namespace lld;
-using namespace lld::elf2;
-
-bool elf2::HasGotOffRel = false;
+using namespace lld::elf;
template <class ELFT>
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
@@ -30,39 +37,39 @@ OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
memset(&Header, 0, sizeof(Elf_Shdr));
Header.sh_type = Type;
Header.sh_flags = Flags;
+ Header.sh_addralign = 1;
+}
+
+template <class ELFT>
+void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *Shdr) {
+ *Shdr = Header;
}
template <class ELFT>
GotPltSection<ELFT>::GotPltSection()
: OutputSectionBase<ELFT>(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
- this->Header.sh_addralign = sizeof(uintX_t);
+ this->Header.sh_addralign = Target->GotPltEntrySize;
}
-template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody *Sym) {
- Sym->GotPltIndex = Target->getGotPltHeaderEntriesNum() + Entries.size();
- Entries.push_back(Sym);
+template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody &Sym) {
+ Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size();
+ Entries.push_back(&Sym);
}
template <class ELFT> bool GotPltSection<ELFT>::empty() const {
return Entries.empty();
}
-template <class ELFT>
-typename GotPltSection<ELFT>::uintX_t
-GotPltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
- return this->getVA() + B.GotPltIndex * sizeof(uintX_t);
-}
-
template <class ELFT> void GotPltSection<ELFT>::finalize() {
- this->Header.sh_size =
- (Target->getGotPltHeaderEntriesNum() + Entries.size()) * sizeof(uintX_t);
+ this->Header.sh_size = (Target->GotPltHeaderEntriesNum + Entries.size()) *
+ Target->GotPltEntrySize;
}
template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
- Target->writeGotPltHeaderEntries(Buf);
- Buf += Target->getGotPltHeaderEntriesNum() * sizeof(uintX_t);
+ Target->writeGotPltHeader(Buf);
+ Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize;
for (const SymbolBody *B : Entries) {
- Target->writeGotPltEntry(Buf, Out<ELFT>::Plt->getEntryAddr(*B));
+ Target->writeGotPlt(Buf, *B);
Buf += sizeof(uintX_t);
}
}
@@ -72,37 +79,135 @@ GotSection<ELFT>::GotSection()
: OutputSectionBase<ELFT>(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
if (Config->EMachine == EM_MIPS)
this->Header.sh_flags |= SHF_MIPS_GPREL;
- this->Header.sh_addralign = sizeof(uintX_t);
+ this->Header.sh_addralign = Target->GotEntrySize;
}
-template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) {
- Sym->GotIndex = Target->getGotHeaderEntriesNum() + Entries.size();
- Entries.push_back(Sym);
+template <class ELFT>
+void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
+ Sym.GotIndex = Entries.size();
+ Entries.push_back(&Sym);
}
-template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody *Sym) {
- if (Sym->hasGlobalDynIndex())
+template <class ELFT>
+void GotSection<ELFT>::addMipsEntry(SymbolBody &Sym, uintX_t Addend,
+ RelExpr Expr) {
+ // For "true" local symbols which can be referenced from the same module
+ // only compiler creates two instructions for address loading:
+ //
+ // lw $8, 0($gp) # R_MIPS_GOT16
+ // addi $8, $8, 0 # R_MIPS_LO16
+ //
+ // The first instruction loads high 16 bits of the symbol address while
+ // the second adds an offset. That allows to reduce number of required
+ // GOT entries because only one global offset table entry is necessary
+ // for every 64 KBytes of local data. So for local symbols we need to
+ // allocate number of GOT entries to hold all required "page" addresses.
+ //
+ // All global symbols (hidden and regular) considered by compiler uniformly.
+ // It always generates a single `lw` instruction and R_MIPS_GOT16 relocation
+ // to load address of the symbol. So for each such symbol we need to
+ // allocate dedicated GOT entry to store its address.
+ //
+ // If a symbol is preemptible we need help of dynamic linker to get its
+ // final address. The corresponding GOT entries are allocated in the
+ // "global" part of GOT. Entries for non preemptible global symbol allocated
+ // in the "local" part of GOT.
+ //
+ // See "Global Offset Table" in Chapter 5:
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ if (Expr == R_MIPS_GOT_LOCAL_PAGE) {
+ // At this point we do not know final symbol value so to reduce number
+ // of allocated GOT entries do the following trick. Save all output
+ // sections referenced by GOT relocations. Then later in the `finalize`
+ // method calculate number of "pages" required to cover all saved output
+ // section and allocate appropriate number of GOT entries.
+ auto *OutSec = cast<DefinedRegular<ELFT>>(&Sym)->Section->OutSec;
+ MipsOutSections.insert(OutSec);
+ return;
+ }
+ if (Sym.isTls()) {
+ // GOT entries created for MIPS TLS relocations behave like
+ // almost GOT entries from other ABIs. They go to the end
+ // of the global offset table.
+ Sym.GotIndex = Entries.size();
+ Entries.push_back(&Sym);
+ return;
+ }
+ auto AddEntry = [&](SymbolBody &S, uintX_t A, MipsGotEntries &Items) {
+ if (S.isInGot() && !A)
+ return;
+ size_t NewIndex = Items.size();
+ if (!MipsGotMap.insert({{&S, A}, NewIndex}).second)
+ return;
+ Items.emplace_back(&S, A);
+ if (!A)
+ S.GotIndex = NewIndex;
+ };
+ if (Sym.isPreemptible()) {
+ // Ignore addends for preemptible symbols. They got single GOT entry anyway.
+ AddEntry(Sym, 0, MipsGlobal);
+ Sym.IsInGlobalMipsGot = true;
+ } else
+ AddEntry(Sym, Addend, MipsLocal);
+}
+
+template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
+ if (Sym.GlobalDynIndex != -1U)
return false;
- Sym->GlobalDynIndex = Target->getGotHeaderEntriesNum() + Entries.size();
+ Sym.GlobalDynIndex = Entries.size();
// Global Dynamic TLS entries take two GOT slots.
- Entries.push_back(Sym);
Entries.push_back(nullptr);
+ Entries.push_back(&Sym);
return true;
}
-template <class ELFT> bool GotSection<ELFT>::addCurrentModuleTlsIndex() {
- if (LocalTlsIndexOff != uint32_t(-1))
+// Reserves TLS entries for a TLS module ID and a TLS block offset.
+// In total it takes two GOT slots.
+template <class ELFT> bool GotSection<ELFT>::addTlsIndex() {
+ if (TlsIndexOff != uint32_t(-1))
return false;
+ TlsIndexOff = Entries.size() * sizeof(uintX_t);
Entries.push_back(nullptr);
Entries.push_back(nullptr);
- LocalTlsIndexOff = (Entries.size() - 2) * sizeof(uintX_t);
return true;
}
template <class ELFT>
typename GotSection<ELFT>::uintX_t
-GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
- return this->getVA() + B.GotIndex * sizeof(uintX_t);
+GotSection<ELFT>::getMipsLocalPageOffset(uintX_t EntryValue) {
+ // Initialize the entry by the %hi(EntryValue) expression
+ // but without right-shifting.
+ EntryValue = (EntryValue + 0x8000) & ~0xffff;
+ // Take into account MIPS GOT header.
+ // See comment in the GotSection::writeTo.
+ size_t NewIndex = MipsLocalGotPos.size() + 2;
+ auto P = MipsLocalGotPos.insert(std::make_pair(EntryValue, NewIndex));
+ assert(!P.second || MipsLocalGotPos.size() <= MipsPageEntries);
+ return (uintX_t)P.first->second * sizeof(uintX_t) - MipsGPOffset;
+}
+
+template <class ELFT>
+typename GotSection<ELFT>::uintX_t
+GotSection<ELFT>::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const {
+ uintX_t Off = MipsPageEntries;
+ if (B.isTls())
+ Off += MipsLocal.size() + MipsGlobal.size() + B.GotIndex;
+ else if (B.IsInGlobalMipsGot)
+ Off += MipsLocal.size() + B.GotIndex;
+ else if (B.isInGot())
+ Off += B.GotIndex;
+ else {
+ auto It = MipsGotMap.find({&B, Addend});
+ assert(It != MipsGotMap.end());
+ Off += It->second;
+ }
+ return Off * sizeof(uintX_t) - MipsGPOffset;
+}
+
+template <class ELFT>
+typename GotSection<ELFT>::uintX_t GotSection<ELFT>::getMipsTlsOffset() {
+ return (MipsPageEntries + MipsLocal.size() + MipsGlobal.size()) *
+ sizeof(uintX_t);
}
template <class ELFT>
@@ -112,37 +217,85 @@ GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
}
template <class ELFT>
+typename GotSection<ELFT>::uintX_t
+GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const {
+ return B.GlobalDynIndex * sizeof(uintX_t);
+}
+
+template <class ELFT>
const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const {
- return Entries.empty() ? nullptr : Entries.front();
+ return MipsGlobal.empty() ? nullptr : MipsGlobal.front().first;
}
template <class ELFT>
unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const {
- // TODO: Update when the support of GOT entries for local symbols is added.
- return Target->getGotHeaderEntriesNum();
+ return MipsPageEntries + MipsLocal.size();
}
template <class ELFT> void GotSection<ELFT>::finalize() {
- this->Header.sh_size =
- (Target->getGotHeaderEntriesNum() + Entries.size()) * sizeof(uintX_t);
+ size_t EntriesNum = Entries.size();
+ if (Config->EMachine == EM_MIPS) {
+ // Take into account MIPS GOT header.
+ // See comment in the GotSection::writeTo.
+ MipsPageEntries += 2;
+ for (const OutputSectionBase<ELFT> *OutSec : MipsOutSections) {
+ // Calculate an upper bound of MIPS GOT entries required to store page
+ // addresses of local symbols. We assume the worst case - each 64kb
+ // page of the output section has at least one GOT relocation against it.
+ // Add 0x8000 to the section's size because the page address stored
+ // in the GOT entry is calculated as (value + 0x8000) & ~0xffff.
+ MipsPageEntries += (OutSec->getSize() + 0x8000 + 0xfffe) / 0xffff;
+ }
+ EntriesNum += MipsPageEntries + MipsLocal.size() + MipsGlobal.size();
+ }
+ this->Header.sh_size = EntriesNum * sizeof(uintX_t);
+}
+
+template <class ELFT> void GotSection<ELFT>::writeMipsGot(uint8_t *&Buf) {
+ // Set the MSB of the second GOT slot. This is not required by any
+ // MIPS ABI documentation, though.
+ //
+ // There is a comment in glibc saying that "The MSB of got[1] of a
+ // gnu object is set to identify gnu objects," and in GNU gold it
+ // says "the second entry will be used by some runtime loaders".
+ // But how this field is being used is unclear.
+ //
+ // We are not really willing to mimic other linkers behaviors
+ // without understanding why they do that, but because all files
+ // generated by GNU tools have this special GOT value, and because
+ // we've been doing this for years, it is probably a safe bet to
+ // keep doing this for now. We really need to revisit this to see
+ // if we had to do this.
+ auto *P = reinterpret_cast<typename ELFT::Off *>(Buf);
+ P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31);
+ // Write 'page address' entries to the local part of the GOT.
+ for (std::pair<uintX_t, size_t> &L : MipsLocalGotPos) {
+ uint8_t *Entry = Buf + L.second * sizeof(uintX_t);
+ write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, L.first);
+ }
+ Buf += MipsPageEntries * sizeof(uintX_t);
+ auto AddEntry = [&](const MipsGotEntry &SA) {
+ uint8_t *Entry = Buf;
+ Buf += sizeof(uintX_t);
+ const SymbolBody* Body = SA.first;
+ uintX_t VA = Body->template getVA<ELFT>(SA.second);
+ write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
+ };
+ std::for_each(std::begin(MipsLocal), std::end(MipsLocal), AddEntry);
+ std::for_each(std::begin(MipsGlobal), std::end(MipsGlobal), AddEntry);
}
template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
- Target->writeGotHeaderEntries(Buf);
- Buf += Target->getGotHeaderEntriesNum() * sizeof(uintX_t);
+ if (Config->EMachine == EM_MIPS)
+ writeMipsGot(Buf);
for (const SymbolBody *B : Entries) {
uint8_t *Entry = Buf;
Buf += sizeof(uintX_t);
if (!B)
continue;
- // MIPS has special rules to fill up GOT entries.
- // See "Global Offset Table" in Chapter 5 in the following document
- // for detailed description:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- // As the first approach, we can just store addresses for all symbols.
- if (Config->EMachine != EM_MIPS && canBePreempted(B, false))
+ if (B->isPreemptible())
continue; // The dynamic linker will take care of it.
- uintX_t VA = getSymVA<ELFT>(*B);
+ uintX_t VA = B->getVA<ELFT>();
write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
}
}
@@ -154,165 +307,81 @@ PltSection<ELFT>::PltSection()
}
template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
- size_t Off = 0;
- bool LazyReloc = Target->supportsLazyRelocations();
- if (LazyReloc) {
- // First write PLT[0] entry which is special.
- Target->writePltZeroEntry(Buf, Out<ELFT>::GotPlt->getVA(), this->getVA());
- Off += Target->getPltZeroEntrySize();
- }
+ // At beginning of PLT, we have code to call the dynamic linker
+ // to resolve dynsyms at runtime. Write such code.
+ Target->writePltHeader(Buf);
+ size_t Off = Target->PltHeaderSize;
+
for (auto &I : Entries) {
- const SymbolBody *E = I.first;
+ const SymbolBody *B = I.first;
unsigned RelOff = I.second;
- uint64_t GotVA =
- LazyReloc ? Out<ELFT>::GotPlt->getVA() : Out<ELFT>::Got->getVA();
- uint64_t GotE = LazyReloc ? Out<ELFT>::GotPlt->getEntryAddr(*E)
- : Out<ELFT>::Got->getEntryAddr(*E);
+ uint64_t Got = B->getGotPltVA<ELFT>();
uint64_t Plt = this->getVA() + Off;
- Target->writePltEntry(Buf + Off, GotVA, GotE, Plt, E->PltIndex, RelOff);
- Off += Target->getPltEntrySize();
+ Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff);
+ Off += Target->PltEntrySize;
}
}
-template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody *Sym) {
- Sym->PltIndex = Entries.size();
- unsigned RelOff = Target->supportsLazyRelocations()
- ? Out<ELFT>::RelaPlt->getRelocOffset()
- : Out<ELFT>::RelaDyn->getRelocOffset();
- Entries.push_back(std::make_pair(Sym, RelOff));
-}
-
-template <class ELFT>
-typename PltSection<ELFT>::uintX_t
-PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
- return this->getVA() + Target->getPltZeroEntrySize() +
- B.PltIndex * Target->getPltEntrySize();
+template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody &Sym) {
+ Sym.PltIndex = Entries.size();
+ unsigned RelOff = Out<ELFT>::RelaPlt->getRelocOffset();
+ Entries.push_back(std::make_pair(&Sym, RelOff));
}
template <class ELFT> void PltSection<ELFT>::finalize() {
- this->Header.sh_size = Target->getPltZeroEntrySize() +
- Entries.size() * Target->getPltEntrySize();
+ this->Header.sh_size =
+ Target->PltHeaderSize + Entries.size() * Target->PltEntrySize;
}
template <class ELFT>
-RelocationSection<ELFT>::RelocationSection(StringRef Name, bool IsRela)
- : OutputSectionBase<ELFT>(Name, IsRela ? SHT_RELA : SHT_REL, SHF_ALLOC),
- IsRela(IsRela) {
- this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
- this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort)
+ : OutputSectionBase<ELFT>(Name, Config->Rela ? SHT_RELA : SHT_REL,
+ SHF_ALLOC),
+ Sort(Sort) {
+ this->Header.sh_entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+ this->Header.sh_addralign = sizeof(uintX_t);
}
-// Applies corresponding symbol and type for dynamic tls relocation.
-// Returns true if relocation was handled.
template <class ELFT>
-bool RelocationSection<ELFT>::applyTlsDynamicReloc(SymbolBody *Body,
- uint32_t Type, Elf_Rel *P,
- Elf_Rel *N) {
- if (Target->isTlsLocalDynamicReloc(Type)) {
- P->setSymbolAndType(0, Target->getTlsModuleIndexReloc(), Config->Mips64EL);
- P->r_offset = Out<ELFT>::Got->getLocalTlsIndexVA();
- return true;
- }
-
- if (!Body || !Target->isTlsGlobalDynamicReloc(Type))
- return false;
-
- if (Target->isTlsOptimized(Type, Body)) {
- P->setSymbolAndType(Body->DynamicSymbolTableIndex,
- Target->getTlsGotReloc(), Config->Mips64EL);
- P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
- return true;
- }
+void RelocationSection<ELFT>::addReloc(const DynamicReloc<ELFT> &Reloc) {
+ Relocs.push_back(Reloc);
+}
- P->setSymbolAndType(Body->DynamicSymbolTableIndex,
- Target->getTlsModuleIndexReloc(), Config->Mips64EL);
- P->r_offset = Out<ELFT>::Got->getGlobalDynAddr(*Body);
- N->setSymbolAndType(Body->DynamicSymbolTableIndex,
- Target->getTlsOffsetReloc(), Config->Mips64EL);
- N->r_offset = Out<ELFT>::Got->getGlobalDynAddr(*Body) + sizeof(uintX_t);
- return true;
+template <class ELFT, class RelTy>
+static bool compRelocations(const RelTy &A, const RelTy &B) {
+ return A.getSymbol(Config->Mips64EL) < B.getSymbol(Config->Mips64EL);
}
template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
+ uint8_t *BufBegin = Buf;
for (const DynamicReloc<ELFT> &Rel : Relocs) {
- auto *P = reinterpret_cast<Elf_Rel *>(Buf);
- Buf += IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
-
- // Skip placeholder for global dynamic TLS relocation pair. It was already
- // handled by the previous relocation.
- if (!Rel.C)
- continue;
-
- InputSectionBase<ELFT> &C = *Rel.C;
- const Elf_Rel &RI = *Rel.RI;
- uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
- const ObjectFile<ELFT> &File = *C.getFile();
- SymbolBody *Body = File.getSymbolBody(SymIndex);
- if (Body)
- Body = Body->repl();
+ auto *P = reinterpret_cast<Elf_Rela *>(Buf);
+ Buf += Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+
+ if (Config->Rela)
+ P->r_addend = Rel.getAddend();
+ P->r_offset = Rel.getOffset();
+ if (Config->EMachine == EM_MIPS && Rel.getOutputSec() == Out<ELFT>::Got)
+ // Dynamic relocation against MIPS GOT section make deal TLS entries
+ // allocated in the end of the GOT. We need to adjust the offset to take
+ // in account 'local' and 'global' GOT entries.
+ P->r_offset += Out<ELFT>::Got->getMipsTlsOffset();
+ P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->Mips64EL);
+ }
- uint32_t Type = RI.getType(Config->Mips64EL);
- if (applyTlsDynamicReloc(Body, Type, P, reinterpret_cast<Elf_Rel *>(Buf)))
- continue;
- bool NeedsCopy = Body && Target->needsCopyRel(Type, *Body);
- bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body);
- bool CBP = canBePreempted(Body, NeedsGot);
- bool LazyReloc = Body && Target->supportsLazyRelocations() &&
- Target->relocNeedsPlt(Type, *Body);
- bool IsDynRelative = Type == Target->getRelativeReloc();
-
- unsigned Sym = CBP ? Body->DynamicSymbolTableIndex : 0;
- unsigned Reloc;
- if (!CBP && Body && isGnuIFunc<ELFT>(*Body))
- Reloc = Target->getIRelativeReloc();
- else if (!CBP || IsDynRelative)
- Reloc = Target->getRelativeReloc();
- else if (LazyReloc)
- Reloc = Target->getPltReloc();
- else if (NeedsGot)
- Reloc = Body->isTls() ? Target->getTlsGotReloc() : Target->getGotReloc();
- else if (NeedsCopy)
- Reloc = Target->getCopyReloc();
- else
- Reloc = Target->getDynReloc(Type);
- P->setSymbolAndType(Sym, Reloc, Config->Mips64EL);
-
- if (LazyReloc)
- P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
- else if (NeedsGot)
- P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
- else if (NeedsCopy)
- P->r_offset = Out<ELFT>::Bss->getVA() +
- cast<SharedSymbol<ELFT>>(Body)->OffsetInBss;
- else
- P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA();
-
- uintX_t OrigAddend = 0;
- if (IsRela && !NeedsGot)
- OrigAddend = static_cast<const Elf_Rela &>(RI).r_addend;
-
- uintX_t Addend;
- if (NeedsCopy)
- Addend = 0;
- else if (CBP || IsDynRelative)
- Addend = OrigAddend;
- else if (Body)
- Addend = getSymVA<ELFT>(*Body) + OrigAddend;
- else if (IsRela)
- Addend =
- getLocalRelTarget(File, static_cast<const Elf_Rela &>(RI),
- getAddend<ELFT>(static_cast<const Elf_Rela &>(RI)));
+ if (Sort) {
+ if (Config->Rela)
+ std::stable_sort((Elf_Rela *)BufBegin,
+ (Elf_Rela *)BufBegin + Relocs.size(),
+ compRelocations<ELFT, Elf_Rela>);
else
- Addend = getLocalRelTarget(File, RI, 0);
-
- if (IsRela)
- static_cast<Elf_Rela *>(P)->r_addend = Addend;
+ std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(),
+ compRelocations<ELFT, Elf_Rel>);
}
}
template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
- const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
- return EntrySize * Relocs.size();
+ return this->Header.sh_entsize * Relocs.size();
}
template <class ELFT> void RelocationSection<ELFT>::finalize() {
@@ -325,17 +394,11 @@ template <class ELFT>
InterpSection<ELFT>::InterpSection()
: OutputSectionBase<ELFT>(".interp", SHT_PROGBITS, SHF_ALLOC) {
this->Header.sh_size = Config->DynamicLinker.size() + 1;
- this->Header.sh_addralign = 1;
-}
-
-template <class ELFT>
-void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *SHdr) {
- Header.sh_name = Out<ELFT>::ShStrTab->addString(Name);
- *SHdr = Header;
}
template <class ELFT> void InterpSection<ELFT>::writeTo(uint8_t *Buf) {
- memcpy(Buf, Config->DynamicLinker.data(), Config->DynamicLinker.size());
+ StringRef S = Config->DynamicLinker;
+ memcpy(Buf, S.data(), S.size());
}
template <class ELFT>
@@ -360,7 +423,7 @@ static uint32_t hashSysv(StringRef Name) {
template <class ELFT> void HashTableSection<ELFT>::finalize() {
this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
- unsigned NumEntries = 2; // nbucket and nchain.
+ unsigned NumEntries = 2; // nbucket and nchain.
NumEntries += Out<ELFT>::DynSymTab->getNumSymbols(); // The chain entries.
// Create as many buckets as there are symbols.
@@ -379,9 +442,11 @@ template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
Elf_Word *Buckets = P;
Elf_Word *Chains = P + NumSymbols;
- for (SymbolBody *Body : Out<ELFT>::DynSymTab->getSymbols()) {
+ for (const std::pair<SymbolBody *, unsigned> &P :
+ Out<ELFT>::DynSymTab->getSymbols()) {
+ SymbolBody *Body = P.first;
StringRef Name = Body->getName();
- unsigned I = Body->DynamicSymbolTableIndex;
+ unsigned I = Body->DynsymIndex;
uint32_t Hash = hashSysv(Name) % NumSymbols;
Chains[I] = Buckets[Hash];
Buckets[Hash] = I;
@@ -399,7 +464,7 @@ template <class ELFT>
GnuHashTableSection<ELFT>::GnuHashTableSection()
: OutputSectionBase<ELFT>(".gnu.hash", SHT_GNU_HASH, SHF_ALLOC) {
this->Header.sh_entsize = ELFT::Is64Bits ? 0 : 4;
- this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+ this->Header.sh_addralign = sizeof(uintX_t);
}
template <class ELFT>
@@ -437,7 +502,7 @@ unsigned GnuHashTableSection<ELFT>::calcMaskWords(unsigned NumHashed) {
}
template <class ELFT> void GnuHashTableSection<ELFT>::finalize() {
- unsigned NumHashed = HashedSymbols.size();
+ unsigned NumHashed = Symbols.size();
NBuckets = calcNBuckets(NumHashed);
MaskWords = calcMaskWords(NumHashed);
// Second hash shift estimation: just predefined values.
@@ -452,7 +517,7 @@ template <class ELFT> void GnuHashTableSection<ELFT>::finalize() {
template <class ELFT> void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) {
writeHeader(Buf);
- if (HashedSymbols.empty())
+ if (Symbols.empty())
return;
writeBloomFilter(Buf);
writeHashTable(Buf);
@@ -462,7 +527,7 @@ template <class ELFT>
void GnuHashTableSection<ELFT>::writeHeader(uint8_t *&Buf) {
auto *P = reinterpret_cast<Elf_Word *>(Buf);
*P++ = NBuckets;
- *P++ = Out<ELFT>::DynSymTab->getNumSymbols() - HashedSymbols.size();
+ *P++ = Out<ELFT>::DynSymTab->getNumSymbols() - Symbols.size();
*P++ = MaskWords;
*P++ = Shift2;
Buf = reinterpret_cast<uint8_t *>(P);
@@ -473,10 +538,10 @@ void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *&Buf) {
unsigned C = sizeof(Elf_Off) * 8;
auto *Masks = reinterpret_cast<Elf_Off *>(Buf);
- for (const HashedSymbolData &Item : HashedSymbols) {
- size_t Pos = (Item.Hash / C) & (MaskWords - 1);
- uintX_t V = (uintX_t(1) << (Item.Hash % C)) |
- (uintX_t(1) << ((Item.Hash >> Shift2) % C));
+ for (const SymbolData &Sym : Symbols) {
+ size_t Pos = (Sym.Hash / C) & (MaskWords - 1);
+ uintX_t V = (uintX_t(1) << (Sym.Hash % C)) |
+ (uintX_t(1) << ((Sym.Hash >> Shift2) % C));
Masks[Pos] |= V;
}
Buf += sizeof(Elf_Off) * MaskWords;
@@ -489,58 +554,64 @@ void GnuHashTableSection<ELFT>::writeHashTable(uint8_t *Buf) {
int PrevBucket = -1;
int I = 0;
- for (const HashedSymbolData &Item : HashedSymbols) {
- int Bucket = Item.Hash % NBuckets;
+ for (const SymbolData &Sym : Symbols) {
+ int Bucket = Sym.Hash % NBuckets;
assert(PrevBucket <= Bucket);
if (Bucket != PrevBucket) {
- Buckets[Bucket] = Item.Body->DynamicSymbolTableIndex;
+ Buckets[Bucket] = Sym.Body->DynsymIndex;
PrevBucket = Bucket;
if (I > 0)
Values[I - 1] |= 1;
}
- Values[I] = Item.Hash & ~1;
+ Values[I] = Sym.Hash & ~1;
++I;
}
if (I > 0)
Values[I - 1] |= 1;
}
-static bool includeInGnuHashTable(SymbolBody *B) {
- // Assume that includeInDynamicSymtab() is already checked.
- return !B->isUndefined();
-}
-
+// Add symbols to this symbol hash table. Note that this function
+// destructively sort a given vector -- which is needed because
+// GNU-style hash table places some sorting requirements.
template <class ELFT>
-void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolBody *> &Symbols) {
- std::vector<SymbolBody *> NotHashed;
- NotHashed.reserve(Symbols.size());
- HashedSymbols.reserve(Symbols.size());
- for (SymbolBody *B : Symbols) {
- if (includeInGnuHashTable(B))
- HashedSymbols.push_back(HashedSymbolData{B, hashGnu(B->getName())});
- else
- NotHashed.push_back(B);
- }
- if (HashedSymbols.empty())
+void GnuHashTableSection<ELFT>::addSymbols(
+ std::vector<std::pair<SymbolBody *, size_t>> &V) {
+ // Ideally this will just be 'auto' but GCC 6.1 is not able
+ // to deduce it correctly.
+ std::vector<std::pair<SymbolBody *, size_t>>::iterator Mid =
+ std::stable_partition(V.begin(), V.end(),
+ [](std::pair<SymbolBody *, size_t> &P) {
+ return P.first->isUndefined();
+ });
+ if (Mid == V.end())
return;
+ for (auto I = Mid, E = V.end(); I != E; ++I) {
+ SymbolBody *B = I->first;
+ size_t StrOff = I->second;
+ Symbols.push_back({B, StrOff, hashGnu(B->getName())});
+ }
- unsigned NBuckets = calcNBuckets(HashedSymbols.size());
- std::stable_sort(HashedSymbols.begin(), HashedSymbols.end(),
- [&](const HashedSymbolData &L, const HashedSymbolData &R) {
+ unsigned NBuckets = calcNBuckets(Symbols.size());
+ std::stable_sort(Symbols.begin(), Symbols.end(),
+ [&](const SymbolData &L, const SymbolData &R) {
return L.Hash % NBuckets < R.Hash % NBuckets;
});
- Symbols = std::move(NotHashed);
- for (const HashedSymbolData &Item : HashedSymbols)
- Symbols.push_back(Item.Body);
+ V.erase(Mid, V.end());
+ for (const SymbolData &Sym : Symbols)
+ V.push_back({Sym.Body, Sym.STName});
}
+// Returns the number of version definition entries. Because the first entry
+// is for the version definition itself, it is the number of versioned symbols
+// plus one. Note that we don't support multiple versions yet.
+static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; }
+
template <class ELFT>
-DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab)
- : OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE),
- SymTab(SymTab) {
+DynamicSection<ELFT>::DynamicSection()
+ : OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE) {
Elf_Shdr &Header = this->Header;
- Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+ Header.sh_addralign = sizeof(uintX_t);
Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
// .dynamic section is not writable on MIPS.
@@ -557,61 +628,66 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
Elf_Shdr &Header = this->Header;
Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
- unsigned NumEntries = 0;
+ auto Add = [=](Entry E) { Entries.push_back(E); };
+
+ // Add strings. We know that these are the last strings to be added to
+ // DynStrTab and doing this here allows this function to set DT_STRSZ.
+ if (!Config->RPath.empty())
+ Add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
+ Out<ELFT>::DynStrTab->addString(Config->RPath)});
+ for (const std::unique_ptr<SharedFile<ELFT>> &F :
+ Symtab<ELFT>::X->getSharedFiles())
+ if (F->isNeeded())
+ Add({DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName())});
+ if (!Config->SoName.empty())
+ Add({DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName)});
+
+ Out<ELFT>::DynStrTab->finalize();
+
if (Out<ELFT>::RelaDyn->hasRelocs()) {
- ++NumEntries; // DT_RELA / DT_REL
- ++NumEntries; // DT_RELASZ / DT_RELSZ
- ++NumEntries; // DT_RELAENT / DT_RELENT
+ bool IsRela = Config->Rela;
+ Add({IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn});
+ Add({IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->getSize()});
+ Add({IsRela ? DT_RELAENT : DT_RELENT,
+ uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))});
}
if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
- ++NumEntries; // DT_JMPREL
- ++NumEntries; // DT_PLTRELSZ
- ++NumEntries; // DT_PLTGOT / DT_MIPS_PLTGOT
- ++NumEntries; // DT_PLTREL
+ Add({DT_JMPREL, Out<ELFT>::RelaPlt});
+ Add({DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize()});
+ Add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
+ Out<ELFT>::GotPlt});
+ Add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)});
}
- ++NumEntries; // DT_SYMTAB
- ++NumEntries; // DT_SYMENT
- ++NumEntries; // DT_STRTAB
- ++NumEntries; // DT_STRSZ
+ Add({DT_SYMTAB, Out<ELFT>::DynSymTab});
+ Add({DT_SYMENT, sizeof(Elf_Sym)});
+ Add({DT_STRTAB, Out<ELFT>::DynStrTab});
+ Add({DT_STRSZ, Out<ELFT>::DynStrTab->getSize()});
if (Out<ELFT>::GnuHashTab)
- ++NumEntries; // DT_GNU_HASH
+ Add({DT_GNU_HASH, Out<ELFT>::GnuHashTab});
if (Out<ELFT>::HashTab)
- ++NumEntries; // DT_HASH
+ Add({DT_HASH, Out<ELFT>::HashTab});
- if (!Config->RPath.empty()) {
- ++NumEntries; // DT_RUNPATH / DT_RPATH
- Out<ELFT>::DynStrTab->reserve(Config->RPath);
+ if (PreInitArraySec) {
+ Add({DT_PREINIT_ARRAY, PreInitArraySec});
+ Add({DT_PREINIT_ARRAYSZ, PreInitArraySec->getSize()});
}
-
- if (!Config->SoName.empty()) {
- ++NumEntries; // DT_SONAME
- Out<ELFT>::DynStrTab->reserve(Config->SoName);
+ if (InitArraySec) {
+ Add({DT_INIT_ARRAY, InitArraySec});
+ Add({DT_INIT_ARRAYSZ, (uintX_t)InitArraySec->getSize()});
}
-
- if (PreInitArraySec)
- NumEntries += 2;
- if (InitArraySec)
- NumEntries += 2;
- if (FiniArraySec)
- NumEntries += 2;
-
- for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) {
- if (!F->isNeeded())
- continue;
- Out<ELFT>::DynStrTab->reserve(F->getSoName());
- ++NumEntries;
+ if (FiniArraySec) {
+ Add({DT_FINI_ARRAY, FiniArraySec});
+ Add({DT_FINI_ARRAYSZ, (uintX_t)FiniArraySec->getSize()});
}
- if (Symbol *S = SymTab.getSymbols().lookup(Config->Init))
- InitSym = S->Body;
- if (Symbol *S = SymTab.getSymbols().lookup(Config->Fini))
- FiniSym = S->Body;
- if (InitSym)
- ++NumEntries; // DT_INIT
- if (FiniSym)
- ++NumEntries; // DT_FINI
+ if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Init))
+ Add({DT_INIT, B});
+ if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Fini))
+ Add({DT_FINI, B});
+ uint32_t DtFlags = 0;
+ uint32_t DtFlags1 = 0;
if (Config->Bsymbolic)
DtFlags |= DF_SYMBOLIC;
if (Config->ZNodelete)
@@ -626,462 +702,490 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
}
if (DtFlags)
- ++NumEntries; // DT_FLAGS
+ Add({DT_FLAGS, DtFlags});
if (DtFlags1)
- ++NumEntries; // DT_FLAGS_1
+ Add({DT_FLAGS_1, DtFlags1});
if (!Config->Entry.empty())
- ++NumEntries; // DT_DEBUG
+ Add({DT_DEBUG, (uint64_t)0});
+
+ bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
+ if (HasVerNeed || Out<ELFT>::VerDef)
+ Add({DT_VERSYM, Out<ELFT>::VerSym});
+ if (Out<ELFT>::VerDef) {
+ Add({DT_VERDEF, Out<ELFT>::VerDef});
+ Add({DT_VERDEFNUM, getVerDefNum()});
+ }
+ if (HasVerNeed) {
+ Add({DT_VERNEED, Out<ELFT>::VerNeed});
+ Add({DT_VERNEEDNUM, Out<ELFT>::VerNeed->getNeedNum()});
+ }
if (Config->EMachine == EM_MIPS) {
- ++NumEntries; // DT_MIPS_RLD_VERSION
- ++NumEntries; // DT_MIPS_FLAGS
- ++NumEntries; // DT_MIPS_BASE_ADDRESS
- ++NumEntries; // DT_MIPS_SYMTABNO
- ++NumEntries; // DT_MIPS_LOCAL_GOTNO
- ++NumEntries; // DT_MIPS_GOTSYM;
- ++NumEntries; // DT_PLTGOT
+ Add({DT_MIPS_RLD_VERSION, 1});
+ Add({DT_MIPS_FLAGS, RHF_NOTPOT});
+ Add({DT_MIPS_BASE_ADDRESS, Config->ImageBase});
+ Add({DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols()});
+ Add({DT_MIPS_LOCAL_GOTNO, Out<ELFT>::Got->getMipsLocalEntriesNum()});
+ if (const SymbolBody *B = Out<ELFT>::Got->getMipsFirstGlobalEntry())
+ Add({DT_MIPS_GOTSYM, B->DynsymIndex});
+ else
+ Add({DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols()});
+ Add({DT_PLTGOT, Out<ELFT>::Got});
if (Out<ELFT>::MipsRldMap)
- ++NumEntries; // DT_MIPS_RLD_MAP
+ Add({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap});
}
- ++NumEntries; // DT_NULL
-
- Header.sh_size = NumEntries * Header.sh_entsize;
+ // +1 for DT_NULL
+ Header.sh_size = (Entries.size() + 1) * Header.sh_entsize;
}
template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
auto *P = reinterpret_cast<Elf_Dyn *>(Buf);
- auto WritePtr = [&](int32_t Tag, uint64_t Val) {
- P->d_tag = Tag;
- P->d_un.d_ptr = Val;
- ++P;
- };
-
- auto WriteVal = [&](int32_t Tag, uint32_t Val) {
- P->d_tag = Tag;
- P->d_un.d_val = Val;
+ for (const Entry &E : Entries) {
+ P->d_tag = E.Tag;
+ switch (E.Kind) {
+ case Entry::SecAddr:
+ P->d_un.d_ptr = E.OutSec->getVA();
+ break;
+ case Entry::SymAddr:
+ P->d_un.d_ptr = E.Sym->template getVA<ELFT>();
+ break;
+ case Entry::PlainInt:
+ P->d_un.d_val = E.Val;
+ break;
+ }
++P;
- };
-
- if (Out<ELFT>::RelaDyn->hasRelocs()) {
- bool IsRela = Out<ELFT>::RelaDyn->isRela();
- WritePtr(IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn->getVA());
- WriteVal(IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->getSize());
- WriteVal(IsRela ? DT_RELAENT : DT_RELENT,
- IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));
}
- if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
- WritePtr(DT_JMPREL, Out<ELFT>::RelaPlt->getVA());
- WriteVal(DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize());
- // On MIPS, the address of the .got.plt section is stored in
- // the DT_MIPS_PLTGOT entry because the DT_PLTGOT entry points to
- // the .got section. See "Dynamic Section" in the following document:
- // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
- WritePtr((Config->EMachine == EM_MIPS) ? DT_MIPS_PLTGOT : DT_PLTGOT,
- Out<ELFT>::GotPlt->getVA());
- WriteVal(DT_PLTREL, Out<ELFT>::RelaPlt->isRela() ? DT_RELA : DT_REL);
- }
-
- WritePtr(DT_SYMTAB, Out<ELFT>::DynSymTab->getVA());
- WritePtr(DT_SYMENT, sizeof(Elf_Sym));
- WritePtr(DT_STRTAB, Out<ELFT>::DynStrTab->getVA());
- WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->getSize());
- if (Out<ELFT>::GnuHashTab)
- WritePtr(DT_GNU_HASH, Out<ELFT>::GnuHashTab->getVA());
- if (Out<ELFT>::HashTab)
- WritePtr(DT_HASH, Out<ELFT>::HashTab->getVA());
-
- // If --enable-new-dtags is set, lld emits DT_RUNPATH
- // instead of DT_RPATH. The two tags are functionally
- // equivalent except for the following:
- // - DT_RUNPATH is searched after LD_LIBRARY_PATH, while
- // DT_RPATH is searched before.
- // - DT_RUNPATH is used only to search for direct
- // dependencies of the object it's contained in, while
- // DT_RPATH is used for indirect dependencies as well.
- if (!Config->RPath.empty())
- WriteVal(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
- Out<ELFT>::DynStrTab->addString(Config->RPath));
-
- if (!Config->SoName.empty())
- WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName));
-
- auto WriteArray = [&](int32_t T1, int32_t T2,
- const OutputSectionBase<ELFT> *Sec) {
- if (!Sec)
- return;
- WritePtr(T1, Sec->getVA());
- WriteVal(T2, Sec->getSize());
- };
- WriteArray(DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ, PreInitArraySec);
- WriteArray(DT_INIT_ARRAY, DT_INIT_ARRAYSZ, InitArraySec);
- WriteArray(DT_FINI_ARRAY, DT_FINI_ARRAYSZ, FiniArraySec);
-
- for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
- if (F->isNeeded())
- WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName()));
+}
- if (InitSym)
- WritePtr(DT_INIT, getSymVA<ELFT>(*InitSym));
- if (FiniSym)
- WritePtr(DT_FINI, getSymVA<ELFT>(*FiniSym));
- if (DtFlags)
- WriteVal(DT_FLAGS, DtFlags);
- if (DtFlags1)
- WriteVal(DT_FLAGS_1, DtFlags1);
- if (!Config->Entry.empty())
- WriteVal(DT_DEBUG, 0);
+template <class ELFT>
+EhFrameHeader<ELFT>::EhFrameHeader()
+ : OutputSectionBase<ELFT>(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC) {}
+
+// .eh_frame_hdr contains a binary search table of pointers to FDEs.
+// Each entry of the search table consists of two values,
+// the starting PC from where FDEs covers, and the FDE's address.
+// It is sorted by PC.
+template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) {
+ const endianness E = ELFT::TargetEndianness;
- // See "Dynamic Section" in Chapter 5 in the following document
- // for detailed description:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- if (Config->EMachine == EM_MIPS) {
- WriteVal(DT_MIPS_RLD_VERSION, 1);
- WriteVal(DT_MIPS_FLAGS, RHF_NOTPOT);
- WritePtr(DT_MIPS_BASE_ADDRESS, Target->getVAStart());
- WriteVal(DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols());
- WriteVal(DT_MIPS_LOCAL_GOTNO, Out<ELFT>::Got->getMipsLocalEntriesNum());
- if (const SymbolBody *B = Out<ELFT>::Got->getMipsFirstGlobalEntry())
- WriteVal(DT_MIPS_GOTSYM, B->DynamicSymbolTableIndex);
- else
- WriteVal(DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols());
- WritePtr(DT_PLTGOT, Out<ELFT>::Got->getVA());
- if (Out<ELFT>::MipsRldMap)
- WritePtr(DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap->getVA());
+ // Sort the FDE list by their PC and uniqueify. Usually there is only
+ // one FDE for a PC (i.e. function), but if ICF merges two functions
+ // into one, there can be more than one FDEs pointing to the address.
+ auto Less = [](const FdeData &A, const FdeData &B) { return A.Pc < B.Pc; };
+ std::stable_sort(Fdes.begin(), Fdes.end(), Less);
+ auto Eq = [](const FdeData &A, const FdeData &B) { return A.Pc == B.Pc; };
+ Fdes.erase(std::unique(Fdes.begin(), Fdes.end(), Eq), Fdes.end());
+
+ Buf[0] = 1;
+ Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
+ Buf[2] = DW_EH_PE_udata4;
+ Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
+ write32<E>(Buf + 4, Out<ELFT>::EhFrame->getVA() - this->getVA() - 4);
+ write32<E>(Buf + 8, Fdes.size());
+ Buf += 12;
+
+ uintX_t VA = this->getVA();
+ for (FdeData &Fde : Fdes) {
+ write32<E>(Buf, Fde.Pc - VA);
+ write32<E>(Buf + 4, Fde.FdeVA - VA);
+ Buf += 8;
}
+}
+
+template <class ELFT> void EhFrameHeader<ELFT>::finalize() {
+ // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
+ this->Header.sh_size = 12 + Out<ELFT>::EhFrame->NumFdes * 8;
+}
- WriteVal(DT_NULL, 0);
+template <class ELFT>
+void EhFrameHeader<ELFT>::addFde(uint32_t Pc, uint32_t FdeVA) {
+ Fdes.push_back({Pc, FdeVA});
}
template <class ELFT>
-OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type,
- uintX_t Flags)
- : OutputSectionBase<ELFT>(Name, Type, Flags) {}
+OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags)
+ : OutputSectionBase<ELFT>(Name, Type, Flags) {
+ if (Type == SHT_RELA)
+ this->Header.sh_entsize = sizeof(Elf_Rela);
+ else if (Type == SHT_REL)
+ this->Header.sh_entsize = sizeof(Elf_Rel);
+}
+
+template <class ELFT> void OutputSection<ELFT>::finalize() {
+ uint32_t Type = this->Header.sh_type;
+ if (Type != SHT_RELA && Type != SHT_REL)
+ return;
+ this->Header.sh_link = Out<ELFT>::SymTab->SectionIndex;
+ // sh_info for SHT_REL[A] sections should contain the section header index of
+ // the section to which the relocation applies.
+ InputSectionBase<ELFT> *S = Sections[0]->getRelocatedSection();
+ this->Header.sh_info = S->OutSec->SectionIndex;
+}
template <class ELFT>
void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
+ assert(C->Live);
auto *S = cast<InputSection<ELFT>>(C);
Sections.push_back(S);
S->OutSec = this;
- uint32_t Align = S->getAlign();
- if (Align > this->Header.sh_addralign)
- this->Header.sh_addralign = Align;
+ this->updateAlignment(S->Alignment);
+}
- uintX_t Off = this->Header.sh_size;
- Off = align(Off, Align);
- S->OutSecOff = Off;
- Off += S->getSize();
- this->Header.sh_size = Off;
+// If an input string is in the form of "foo.N" where N is a number,
+// return N. Otherwise, returns 65536, which is one greater than the
+// lowest priority.
+static int getPriority(StringRef S) {
+ size_t Pos = S.rfind('.');
+ if (Pos == StringRef::npos)
+ return 65536;
+ int V;
+ if (S.substr(Pos + 1).getAsInteger(10, V))
+ return 65536;
+ return V;
}
-template <class ELFT>
-typename ELFFile<ELFT>::uintX_t elf2::getSymVA(const SymbolBody &S) {
- switch (S.kind()) {
- case SymbolBody::DefinedSyntheticKind: {
- auto &D = cast<DefinedSynthetic<ELFT>>(S);
- return D.Section.getVA() + D.Value;
- }
- case SymbolBody::DefinedRegularKind: {
- const auto &DR = cast<DefinedRegular<ELFT>>(S);
- InputSectionBase<ELFT> *SC = DR.Section;
- if (!SC)
- return DR.Sym.st_value;
-
- // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol
- // from the beginning of the section.
- if (Config->EMachine == EM_AMDGPU)
- return SC->getOffset(DR.Sym);
- if (DR.Sym.getType() == STT_TLS)
- return SC->OutSec->getVA() + SC->getOffset(DR.Sym) -
- Out<ELFT>::TlsPhdr->p_vaddr;
- return SC->OutSec->getVA() + SC->getOffset(DR.Sym);
- }
- case SymbolBody::DefinedCommonKind:
- return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBss;
- case SymbolBody::SharedKind: {
- auto &SS = cast<SharedSymbol<ELFT>>(S);
- if (SS.NeedsCopy)
- return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;
- return 0;
- }
- case SymbolBody::UndefinedElfKind:
- case SymbolBody::UndefinedKind:
- return 0;
- case SymbolBody::LazyKind:
- assert(S.isUsedInRegularObj() && "Lazy symbol reached writer");
- return 0;
- }
- llvm_unreachable("Invalid symbol kind");
-}
-
-// Returns a VA which a relocatin RI refers to. Used only for local symbols.
-// For non-local symbols, use getSymVA instead.
-template <class ELFT, bool IsRela>
-typename ELFFile<ELFT>::uintX_t
-elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
- const Elf_Rel_Impl<ELFT, IsRela> &RI,
- typename ELFFile<ELFT>::uintX_t Addend) {
- typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
-
- // PPC64 has a special relocation representing the TOC base pointer
- // that does not have a corresponding symbol.
- if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC)
- return getPPC64TocBase() + Addend;
-
- const Elf_Sym *Sym =
- File.getObj().getRelocationSymbol(&RI, File.getSymbolTable());
-
- if (!Sym)
- error("Unsupported relocation without symbol");
-
- InputSectionBase<ELFT> *Section = File.getSection(*Sym);
-
- if (Sym->getType() == STT_TLS)
- return (Section->OutSec->getVA() + Section->getOffset(*Sym) + Addend) -
- Out<ELFT>::TlsPhdr->p_vaddr;
-
- // According to the ELF spec reference to a local symbol from outside
- // the group are not allowed. Unfortunately .eh_frame breaks that rule
- // and must be treated specially. For now we just replace the symbol with
- // 0.
- if (Section == &InputSection<ELFT>::Discarded || !Section->isLive())
- return Addend;
-
- uintX_t VA = Section->OutSec->getVA();
- if (isa<InputSection<ELFT>>(Section))
- return VA + Section->getOffset(*Sym) + Addend;
-
- uintX_t Offset = Sym->st_value;
- if (Sym->getType() == STT_SECTION) {
- Offset += Addend;
- Addend = 0;
+// This function is called after we sort input sections
+// and scan relocations to setup sections' offsets.
+template <class ELFT> void OutputSection<ELFT>::assignOffsets() {
+ uintX_t Off = this->Header.sh_size;
+ for (InputSection<ELFT> *S : Sections) {
+ Off = alignTo(Off, S->Alignment);
+ S->OutSecOff = Off;
+ Off += S->getSize();
}
- return VA + Section->getOffset(Offset) + Addend;
+ this->Header.sh_size = Off;
}
-// Returns true if a symbol can be replaced at load-time by a symbol
-// with the same name defined in other ELF executable or DSO.
-bool elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) {
- if (!Body)
- return false; // Body is a local symbol.
- if (Body->isShared())
+// Sorts input sections by section name suffixes, so that .foo.N comes
+// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
+// We want to keep the original order if the priorities are the same
+// because the compiler keeps the original initialization order in a
+// translation unit and we need to respect that.
+// For more detail, read the section of the GCC's manual about init_priority.
+template <class ELFT> void OutputSection<ELFT>::sortInitFini() {
+ // Sort sections by priority.
+ typedef std::pair<int, InputSection<ELFT> *> Pair;
+ auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
+
+ std::vector<Pair> V;
+ for (InputSection<ELFT> *S : Sections)
+ V.push_back({getPriority(S->getSectionName()), S});
+ std::stable_sort(V.begin(), V.end(), Comp);
+ Sections.clear();
+ for (Pair &P : V)
+ Sections.push_back(P.second);
+}
+
+// Returns true if S matches /Filename.?\.o$/.
+static bool isCrtBeginEnd(StringRef S, StringRef Filename) {
+ if (!S.endswith(".o"))
+ return false;
+ S = S.drop_back(2);
+ if (S.endswith(Filename))
return true;
+ return !S.empty() && S.drop_back().endswith(Filename);
+}
- if (Body->isUndefined()) {
- if (!Body->isWeak())
- return true;
-
- // This is an horrible corner case. Ideally we would like to say that any
- // undefined symbol can be preempted so that the dynamic linker has a
- // chance of finding it at runtime.
- //
- // The problem is that the code sequence used to test for weak undef
- // functions looks like
- // if (func) func()
- // If the code is -fPIC the first reference is a load from the got and
- // everything works.
- // If the code is not -fPIC there is no reasonable way to solve it:
- // * A relocation writing to the text segment will fail (it is ro).
- // * A copy relocation doesn't work for functions.
- // * The trick of using a plt entry as the address would fail here since
- // the plt entry would have a non zero address.
- // Since we cannot do anything better, we just resolve the symbol to 0 and
- // don't produce a dynamic relocation.
- //
- // As an extra hack, assume that if we are producing a shared library the
- // user knows what he or she is doing and can handle a dynamic relocation.
- return Config->Shared || NeedsGot;
- }
- if (!Config->Shared)
+static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); }
+static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }
+
+// .ctors and .dtors are sorted by this priority from highest to lowest.
+//
+// 1. The section was contained in crtbegin (crtbegin contains
+// some sentinel value in its .ctors and .dtors so that the runtime
+// can find the beginning of the sections.)
+//
+// 2. The section has an optional priority value in the form of ".ctors.N"
+// or ".dtors.N" where N is a number. Unlike .{init,fini}_array,
+// they are compared as string rather than number.
+//
+// 3. The section is just ".ctors" or ".dtors".
+//
+// 4. The section was contained in crtend, which contains an end marker.
+//
+// In an ideal world, we don't need this function because .init_array and
+// .ctors are duplicate features (and .init_array is newer.) However, there
+// are too many real-world use cases of .ctors, so we had no choice to
+// support that with this rather ad-hoc semantics.
+template <class ELFT>
+static bool compCtors(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B) {
+ bool BeginA = isCrtbegin(A->getFile()->getName());
+ bool BeginB = isCrtbegin(B->getFile()->getName());
+ if (BeginA != BeginB)
+ return BeginA;
+ bool EndA = isCrtend(A->getFile()->getName());
+ bool EndB = isCrtend(B->getFile()->getName());
+ if (EndA != EndB)
+ return EndB;
+ StringRef X = A->getSectionName();
+ StringRef Y = B->getSectionName();
+ assert(X.startswith(".ctors") || X.startswith(".dtors"));
+ assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
+ X = X.substr(6);
+ Y = Y.substr(6);
+ if (X.empty() && Y.empty())
return false;
- return Body->getVisibility() == STV_DEFAULT;
+ return X < Y;
}
-template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
- for (InputSection<ELFT> *C : Sections)
- C->writeTo(Buf);
+// Sorts input sections by the special rules for .ctors and .dtors.
+// Unfortunately, the rules are different from the one for .{init,fini}_array.
+// Read the comment above.
+template <class ELFT> void OutputSection<ELFT>::sortCtorsDtors() {
+ std::stable_sort(Sections.begin(), Sections.end(), compCtors<ELFT>);
}
-template <class ELFT>
-EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t Type,
- uintX_t Flags)
- : OutputSectionBase<ELFT>(Name, Type, Flags) {}
-
-template <class ELFT>
-EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index)
- : S(S), Index(Index) {}
+static void fill(uint8_t *Buf, size_t Size, ArrayRef<uint8_t> A) {
+ size_t I = 0;
+ for (; I + A.size() < Size; I += A.size())
+ memcpy(Buf + I, A.data(), A.size());
+ memcpy(Buf + I, A.data(), Size - I);
+}
-template <class ELFT> StringRef EHRegion<ELFT>::data() const {
- ArrayRef<uint8_t> SecData = S->getSectionData();
- ArrayRef<std::pair<uintX_t, uintX_t>> Offsets = S->Offsets;
- size_t Start = Offsets[Index].first;
- size_t End =
- Index == Offsets.size() - 1 ? SecData.size() : Offsets[Index + 1].first;
- return StringRef((const char *)SecData.data() + Start, End - Start);
+template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
+ ArrayRef<uint8_t> Filler = Script<ELFT>::X->getFiller(this->Name);
+ if (!Filler.empty())
+ fill(Buf, this->getSize(), Filler);
+ if (Config->Threads) {
+ parallel_for_each(Sections.begin(), Sections.end(),
+ [=](InputSection<ELFT> *C) { C->writeTo(Buf); });
+ } else {
+ for (InputSection<ELFT> *C : Sections)
+ C->writeTo(Buf);
+ }
}
template <class ELFT>
-Cie<ELFT>::Cie(EHInputSection<ELFT> *S, unsigned Index)
- : EHRegion<ELFT>(S, Index) {}
+EhOutputSection<ELFT>::EhOutputSection()
+ : OutputSectionBase<ELFT>(".eh_frame", SHT_PROGBITS, SHF_ALLOC) {}
+
+// Returns the first relocation that points to a region
+// between Begin and Begin+Size.
+template <class IntTy, class RelTy>
+static const RelTy *getReloc(IntTy Begin, IntTy Size, ArrayRef<RelTy> &Rels) {
+ for (auto I = Rels.begin(), E = Rels.end(); I != E; ++I) {
+ if (I->r_offset < Begin)
+ continue;
+
+ // Truncate Rels for fast access. That means we expect that the
+ // relocations are sorted and we are looking up symbols in
+ // sequential order. It is naturally satisfied for .eh_frame.
+ Rels = Rels.slice(I - Rels.begin());
+ if (I->r_offset < Begin + Size)
+ return I;
+ return nullptr;
+ }
+ Rels = ArrayRef<RelTy>();
+ return nullptr;
+}
+// Search for an existing CIE record or create a new one.
+// CIE records from input object files are uniquified by their contents
+// and where their relocations point to.
template <class ELFT>
-template <bool IsRela>
-void EHOutputSection<ELFT>::addSectionAux(
- EHInputSection<ELFT> *S,
- iterator_range<const Elf_Rel_Impl<ELFT, IsRela> *> Rels) {
+template <class RelTy>
+CieRecord *EhOutputSection<ELFT>::addCie(SectionPiece &Piece,
+ EhInputSection<ELFT> *Sec,
+ ArrayRef<RelTy> &Rels) {
const endianness E = ELFT::TargetEndianness;
+ if (read32<E>(Piece.data().data() + 4) != 0)
+ fatal("CIE expected at beginning of .eh_frame: " + Sec->getSectionName());
- S->OutSec = this;
- uint32_t Align = S->getAlign();
- if (Align > this->Header.sh_addralign)
- this->Header.sh_addralign = Align;
+ SymbolBody *Personality = nullptr;
+ if (const RelTy *Rel = getReloc(Piece.InputOff, Piece.size(), Rels))
+ Personality = &Sec->getFile()->getRelocTargetSym(*Rel);
- Sections.push_back(S);
+ // Search for an existing CIE by CIE contents/relocation target pair.
+ CieRecord *Cie = &CieMap[{Piece.data(), Personality}];
- ArrayRef<uint8_t> SecData = S->getSectionData();
- ArrayRef<uint8_t> D = SecData;
- uintX_t Offset = 0;
- auto RelI = Rels.begin();
- auto RelE = Rels.end();
+ // If not found, create a new one.
+ if (Cie->Piece == nullptr) {
+ Cie->Piece = &Piece;
+ Cies.push_back(Cie);
+ }
+ return Cie;
+}
- DenseMap<unsigned, unsigned> OffsetToIndex;
- while (!D.empty()) {
- unsigned Index = S->Offsets.size();
- S->Offsets.push_back(std::make_pair(Offset, -1));
+// There is one FDE per function. Returns true if a given FDE
+// points to a live function.
+template <class ELFT>
+template <class RelTy>
+bool EhOutputSection<ELFT>::isFdeLive(SectionPiece &Piece,
+ EhInputSection<ELFT> *Sec,
+ ArrayRef<RelTy> &Rels) {
+ const RelTy *Rel = getReloc(Piece.InputOff, Piece.size(), Rels);
+ if (!Rel)
+ fatal("FDE doesn't reference another section");
+ SymbolBody &B = Sec->getFile()->getRelocTargetSym(*Rel);
+ auto *D = dyn_cast<DefinedRegular<ELFT>>(&B);
+ if (!D || !D->Section)
+ return false;
+ InputSectionBase<ELFT> *Target = D->Section->Repl;
+ return Target && Target->Live;
+}
- uintX_t Length = readEntryLength(D);
- StringRef Entry((const char *)D.data(), Length);
+// .eh_frame is a sequence of CIE or FDE records. In general, there
+// is one CIE record per input object file which is followed by
+// a list of FDEs. This function searches an existing CIE or create a new
+// one and associates FDEs to the CIE.
+template <class ELFT>
+template <class RelTy>
+void EhOutputSection<ELFT>::addSectionAux(EhInputSection<ELFT> *Sec,
+ ArrayRef<RelTy> Rels) {
+ const endianness E = ELFT::TargetEndianness;
- while (RelI != RelE && RelI->r_offset < Offset)
- ++RelI;
- uintX_t NextOffset = Offset + Length;
- bool HasReloc = RelI != RelE && RelI->r_offset < NextOffset;
+ DenseMap<size_t, CieRecord *> OffsetToCie;
+ for (SectionPiece &Piece : Sec->Pieces) {
+ // The empty record is the end marker.
+ if (Piece.size() == 4)
+ return;
- uint32_t ID = read32<E>(D.data() + 4);
+ size_t Offset = Piece.InputOff;
+ uint32_t ID = read32<E>(Piece.data().data() + 4);
if (ID == 0) {
- // CIE
- Cie<ELFT> C(S, Index);
-
- StringRef Personality;
- if (HasReloc) {
- uint32_t SymIndex = RelI->getSymbol(Config->Mips64EL);
- SymbolBody &Body = *S->getFile()->getSymbolBody(SymIndex)->repl();
- Personality = Body.getName();
- }
-
- std::pair<StringRef, StringRef> CieInfo(Entry, Personality);
- auto P = CieMap.insert(std::make_pair(CieInfo, Cies.size()));
- if (P.second) {
- Cies.push_back(C);
- this->Header.sh_size += align(Length, sizeof(uintX_t));
- }
- OffsetToIndex[Offset] = P.first->second;
- } else {
- if (!HasReloc)
- error("FDE doesn't reference another section");
- InputSectionBase<ELFT> *Target = S->getRelocTarget(*RelI);
- if (Target != &InputSection<ELFT>::Discarded && Target->isLive()) {
- uint32_t CieOffset = Offset + 4 - ID;
- auto I = OffsetToIndex.find(CieOffset);
- if (I == OffsetToIndex.end())
- error("Invalid CIE reference");
- Cies[I->second].Fdes.push_back(EHRegion<ELFT>(S, Index));
- this->Header.sh_size += align(Length, sizeof(uintX_t));
- }
+ OffsetToCie[Offset] = addCie(Piece, Sec, Rels);
+ continue;
}
- Offset = NextOffset;
- D = D.slice(Length);
+ uint32_t CieOffset = Offset + 4 - ID;
+ CieRecord *Cie = OffsetToCie[CieOffset];
+ if (!Cie)
+ fatal("invalid CIE reference");
+
+ if (!isFdeLive(Piece, Sec, Rels))
+ continue;
+ Cie->FdePieces.push_back(&Piece);
+ NumFdes++;
}
}
template <class ELFT>
-typename EHOutputSection<ELFT>::uintX_t
-EHOutputSection<ELFT>::readEntryLength(ArrayRef<uint8_t> D) {
- const endianness E = ELFT::TargetEndianness;
+void EhOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
+ auto *Sec = cast<EhInputSection<ELFT>>(C);
+ Sec->OutSec = this;
+ this->updateAlignment(Sec->Alignment);
+ Sections.push_back(Sec);
+
+ // .eh_frame is a sequence of CIE or FDE records. This function
+ // splits it into pieces so that we can call
+ // SplitInputSection::getSectionPiece on the section.
+ Sec->split();
+ if (Sec->Pieces.empty())
+ return;
- if (D.size() < 4)
- error("Truncated CIE/FDE length");
- uint64_t Len = read32<E>(D.data());
- if (Len < UINT32_MAX) {
- if (Len > (UINT32_MAX - 4))
- error("CIE/FIE size is too large");
- if (Len + 4 > D.size())
- error("CIE/FIE ends past the end of the section");
- return Len + 4;
+ if (const Elf_Shdr *RelSec = Sec->RelocSection) {
+ ELFFile<ELFT> &Obj = Sec->getFile()->getObj();
+ if (RelSec->sh_type == SHT_RELA)
+ addSectionAux(Sec, Obj.relas(RelSec));
+ else
+ addSectionAux(Sec, Obj.rels(RelSec));
+ return;
}
-
- if (D.size() < 12)
- error("Truncated CIE/FDE length");
- Len = read64<E>(D.data() + 4);
- if (Len > (UINT64_MAX - 12))
- error("CIE/FIE size is too large");
- if (Len + 12 > D.size())
- error("CIE/FIE ends past the end of the section");
- return Len + 12;
+ addSectionAux(Sec, makeArrayRef<Elf_Rela>(nullptr, nullptr));
}
template <class ELFT>
-void EHOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
- auto *S = cast<EHInputSection<ELFT>>(C);
- const Elf_Shdr *RelSec = S->RelocSection;
- if (!RelSec)
- return addSectionAux(
- S, make_range((const Elf_Rela *)nullptr, (const Elf_Rela *)nullptr));
- ELFFile<ELFT> &Obj = S->getFile()->getObj();
- if (RelSec->sh_type == SHT_RELA)
- return addSectionAux(S, Obj.relas(RelSec));
- return addSectionAux(S, Obj.rels(RelSec));
+static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {
+ memcpy(Buf, D.data(), D.size());
+
+ // Fix the size field. -4 since size does not include the size field itself.
+ const endianness E = ELFT::TargetEndianness;
+ write32<E>(Buf, alignTo(D.size(), sizeof(typename ELFT::uint)) - 4);
}
-template <class ELFT>
-static typename ELFFile<ELFT>::uintX_t writeAlignedCieOrFde(StringRef Data,
- uint8_t *Buf) {
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+template <class ELFT> void EhOutputSection<ELFT>::finalize() {
+ if (this->Header.sh_size)
+ return; // Already finalized.
+
+ size_t Off = 0;
+ for (CieRecord *Cie : Cies) {
+ Cie->Piece->OutputOff = Off;
+ Off += alignTo(Cie->Piece->size(), sizeof(uintX_t));
+
+ for (SectionPiece *Fde : Cie->FdePieces) {
+ Fde->OutputOff = Off;
+ Off += alignTo(Fde->size(), sizeof(uintX_t));
+ }
+ }
+ this->Header.sh_size = Off;
+}
+
+template <class ELFT> static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
const endianness E = ELFT::TargetEndianness;
- uint64_t Len = align(Data.size(), sizeof(uintX_t));
- write32<E>(Buf, Len - 4);
- memcpy(Buf + 4, Data.data() + 4, Data.size() - 4);
- return Len;
+ switch (Size) {
+ case DW_EH_PE_udata2:
+ return read16<E>(Buf);
+ case DW_EH_PE_udata4:
+ return read32<E>(Buf);
+ case DW_EH_PE_udata8:
+ return read64<E>(Buf);
+ case DW_EH_PE_absptr:
+ if (ELFT::Is64Bits)
+ return read64<E>(Buf);
+ return read32<E>(Buf);
+ }
+ fatal("unknown FDE size encoding");
}
-template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) {
+// Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to.
+// We need it to create .eh_frame_hdr section.
+template <class ELFT>
+typename ELFT::uint EhOutputSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff,
+ uint8_t Enc) {
+ // The starting address to which this FDE applies is
+ // stored at FDE + 8 byte.
+ size_t Off = FdeOff + 8;
+ uint64_t Addr = readFdeAddr<ELFT>(Buf + Off, Enc & 0x7);
+ if ((Enc & 0x70) == DW_EH_PE_absptr)
+ return Addr;
+ if ((Enc & 0x70) == DW_EH_PE_pcrel)
+ return Addr + this->getVA() + Off;
+ fatal("unknown FDE size relative encoding");
+}
+
+template <class ELFT> void EhOutputSection<ELFT>::writeTo(uint8_t *Buf) {
const endianness E = ELFT::TargetEndianness;
- size_t Offset = 0;
- for (const Cie<ELFT> &C : Cies) {
- size_t CieOffset = Offset;
-
- uintX_t CIELen = writeAlignedCieOrFde<ELFT>(C.data(), Buf + Offset);
- C.S->Offsets[C.Index].second = Offset;
- Offset += CIELen;
-
- for (const EHRegion<ELFT> &F : C.Fdes) {
- uintX_t Len = writeAlignedCieOrFde<ELFT>(F.data(), Buf + Offset);
- write32<E>(Buf + Offset + 4, Offset + 4 - CieOffset); // Pointer
- F.S->Offsets[F.Index].second = Offset;
- Offset += Len;
+ for (CieRecord *Cie : Cies) {
+ size_t CieOffset = Cie->Piece->OutputOff;
+ writeCieFde<ELFT>(Buf + CieOffset, Cie->Piece->data());
+
+ for (SectionPiece *Fde : Cie->FdePieces) {
+ size_t Off = Fde->OutputOff;
+ writeCieFde<ELFT>(Buf + Off, Fde->data());
+
+ // FDE's second word should have the offset to an associated CIE.
+ // Write it.
+ write32<E>(Buf + Off + 4, Off + 4 - CieOffset);
}
}
- for (EHInputSection<ELFT> *S : Sections) {
- const Elf_Shdr *RelSec = S->RelocSection;
- if (!RelSec)
- continue;
- ELFFile<ELFT> &EObj = S->getFile()->getObj();
- if (RelSec->sh_type == SHT_RELA)
- S->relocate(Buf, nullptr, EObj.relas(RelSec));
- else
- S->relocate(Buf, nullptr, EObj.rels(RelSec));
+ for (EhInputSection<ELFT> *S : Sections)
+ S->relocate(Buf, nullptr);
+
+ // Construct .eh_frame_hdr. .eh_frame_hdr is a binary search table
+ // to get a FDE from an address to which FDE is applied. So here
+ // we obtain two addresses and pass them to EhFrameHdr object.
+ if (Out<ELFT>::EhFrameHdr) {
+ for (CieRecord *Cie : Cies) {
+ uint8_t Enc = getFdeEncoding<ELFT>(Cie->Piece->data());
+ for (SectionPiece *Fde : Cie->FdePieces) {
+ uintX_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
+ uintX_t FdeVA = this->getVA() + Fde->OutputOff;
+ Out<ELFT>::EhFrameHdr->addFde(Pc, FdeVA);
+ }
+ }
}
}
template <class ELFT>
MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t Type,
- uintX_t Flags)
- : OutputSectionBase<ELFT>(Name, Type, Flags) {}
+ uintX_t Flags, uintX_t Alignment)
+ : OutputSectionBase<ELFT>(Name, Type, Flags),
+ Builder(StringTableBuilder::RAW, Alignment) {}
template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) {
if (shouldTailMerge()) {
@@ -1089,58 +1193,32 @@ template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) {
memcpy(Buf, Data.data(), Data.size());
return;
}
- for (const std::pair<StringRef, size_t> &P : Builder.getMap()) {
- StringRef Data = P.first;
+ for (const std::pair<CachedHash<StringRef>, size_t> &P : Builder.getMap()) {
+ StringRef Data = P.first.Val;
memcpy(Buf + P.second, Data.data(), Data.size());
}
}
-static size_t findNull(StringRef S, size_t EntSize) {
- // Optimize the common case.
- if (EntSize == 1)
- return S.find(0);
-
- for (unsigned I = 0, N = S.size(); I != N; I += EntSize) {
- const char *B = S.begin() + I;
- if (std::all_of(B, B + EntSize, [](char C) { return C == 0; }))
- return I;
- }
- return StringRef::npos;
+static StringRef toStringRef(ArrayRef<uint8_t> A) {
+ return {(const char *)A.data(), A.size()};
}
template <class ELFT>
void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
- auto *S = cast<MergeInputSection<ELFT>>(C);
- S->OutSec = this;
- uint32_t Align = S->getAlign();
- if (Align > this->Header.sh_addralign)
- this->Header.sh_addralign = Align;
-
- ArrayRef<uint8_t> D = S->getSectionData();
- StringRef Data((const char *)D.data(), D.size());
- uintX_t EntSize = S->getSectionHdr()->sh_entsize;
-
- if (this->Header.sh_flags & SHF_STRINGS) {
- uintX_t Offset = 0;
- while (!Data.empty()) {
- size_t End = findNull(Data, EntSize);
- if (End == StringRef::npos)
- error("String is not null terminated");
- StringRef Entry = Data.substr(0, End + EntSize);
- uintX_t OutputOffset = Builder.add(Entry);
- if (shouldTailMerge())
- OutputOffset = -1;
- S->Offsets.push_back(std::make_pair(Offset, OutputOffset));
- uintX_t Size = End + EntSize;
- Data = Data.substr(Size);
- Offset += Size;
- }
- } else {
- for (unsigned I = 0, N = Data.size(); I != N; I += EntSize) {
- StringRef Entry = Data.substr(I, EntSize);
- size_t OutputOffset = Builder.add(Entry);
- S->Offsets.push_back(std::make_pair(I, OutputOffset));
- }
+ auto *Sec = cast<MergeInputSection<ELFT>>(C);
+ Sec->OutSec = this;
+ this->updateAlignment(Sec->Alignment);
+ this->Header.sh_entsize = Sec->getSectionHdr()->sh_entsize;
+ Sections.push_back(Sec);
+
+ bool IsString = this->Header.sh_flags & SHF_STRINGS;
+
+ for (SectionPiece &Piece : Sec->Pieces) {
+ if (!Piece.Live)
+ continue;
+ uintX_t OutputOffset = Builder.add(toStringRef(Piece.data()));
+ if (!IsString || !shouldTailMerge())
+ Piece.OutputOff = OutputOffset;
}
}
@@ -1159,38 +1237,32 @@ template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
this->Header.sh_size = Builder.getSize();
}
+template <class ELFT> void MergeOutputSection<ELFT>::finalizePieces() {
+ for (MergeInputSection<ELFT> *Sec : Sections)
+ Sec->finalizePieces();
+}
+
template <class ELFT>
StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
: OutputSectionBase<ELFT>(Name, SHT_STRTAB,
Dynamic ? (uintX_t)SHF_ALLOC : 0),
- Dynamic(Dynamic) {
- this->Header.sh_addralign = 1;
-}
+ Dynamic(Dynamic) {}
-// String tables are created in two phases. First you call reserve()
-// to reserve room in the string table, and then call addString() to actually
-// add that string.
-//
-// Why two phases? We want to know the size of the string table as early as
-// possible to fix file layout. So we have separated finalize(), which
-// determines the size of the section, from writeTo(), which writes the section
-// contents to the output buffer. If we merge reserve() with addString(),
-// we need a plumbing work for finalize() and writeTo() so that offsets
-// we obtained in the former function can be written in the latter.
-// This design eliminated that need.
-template <class ELFT> void StringTableSection<ELFT>::reserve(StringRef S) {
- Reserved += S.size() + 1; // +1 for NUL
-}
-
-// Adds a string to the string table. You must call reserve() with the
-// same string before calling addString().
-template <class ELFT> size_t StringTableSection<ELFT>::addString(StringRef S) {
- size_t Pos = Used;
+// Adds a string to the string table. If HashIt is true we hash and check for
+// duplicates. It is optional because the name of global symbols are already
+// uniqued and hashing them again has a big cost for a small value: uniquing
+// them with some other string that happens to be the same.
+template <class ELFT>
+unsigned StringTableSection<ELFT>::addString(StringRef S, bool HashIt) {
+ if (HashIt) {
+ auto R = StringMap.insert(std::make_pair(S, Size));
+ if (!R.second)
+ return R.first->second;
+ }
+ unsigned Ret = Size;
+ Size += S.size() + 1;
Strings.push_back(S);
- Used += S.size() + 1;
- Reserved -= S.size() + 1;
- assert((int64_t)Reserved >= 0);
- return Pos;
+ return Ret;
}
template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) {
@@ -1203,42 +1275,34 @@ template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) {
}
template <class ELFT>
-bool elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File, StringRef SymName,
- const typename ELFFile<ELFT>::Elf_Sym &Sym) {
- if (Sym.getType() == STT_SECTION)
- return false;
-
- InputSectionBase<ELFT> *Sec = File.getSection(Sym);
- // If sym references a section in a discarded group, don't keep it.
- if (Sec == &InputSection<ELFT>::Discarded)
- return false;
-
- if (Config->DiscardNone)
- return true;
-
- // In ELF assembly .L symbols are normally discarded by the assembler.
- // If the assembler fails to do so, the linker discards them if
- // * --discard-locals is used.
- // * The symbol is in a SHF_MERGE section, which is normally the reason for
- // the assembler keeping the .L symbol.
- if (!SymName.startswith(".L") && !SymName.empty())
- return true;
+typename ELFT::uint DynamicReloc<ELFT>::getOffset() const {
+ if (OutputSec)
+ return OutputSec->getVA() + OffsetInSec;
+ return InputSec->OutSec->getVA() + InputSec->getOffset(OffsetInSec);
+}
- if (Config->DiscardLocals)
- return false;
+template <class ELFT>
+typename ELFT::uint DynamicReloc<ELFT>::getAddend() const {
+ if (UseSymVA)
+ return Sym->getVA<ELFT>(Addend);
+ return Addend;
+}
- return !(Sec->getSectionHdr()->sh_flags & SHF_MERGE);
+template <class ELFT> uint32_t DynamicReloc<ELFT>::getSymIndex() const {
+ if (Sym && !UseSymVA)
+ return Sym->DynsymIndex;
+ return 0;
}
template <class ELFT>
SymbolTableSection<ELFT>::SymbolTableSection(
- SymbolTable<ELFT> &Table, StringTableSection<ELFT> &StrTabSec)
+ StringTableSection<ELFT> &StrTabSec)
: OutputSectionBase<ELFT>(StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
- Table(Table), StrTabSec(StrTabSec) {
+ StrTabSec(StrTabSec) {
this->Header.sh_entsize = sizeof(Elf_Sym);
- this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+ this->Header.sh_addralign = sizeof(uintX_t);
}
// Orders symbols according to their positions in the GOT,
@@ -1246,10 +1310,25 @@ SymbolTableSection<ELFT>::SymbolTableSection(
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed description:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-static bool sortMipsSymbols(SymbolBody *L, SymbolBody *R) {
- if (!L->isInGot() || !R->isInGot())
- return R->isInGot();
- return L->GotIndex < R->GotIndex;
+static bool sortMipsSymbols(const std::pair<SymbolBody *, unsigned> &L,
+ const std::pair<SymbolBody *, unsigned> &R) {
+ // Sort entries related to non-local preemptible symbols by GOT indexes.
+ // All other entries go to the first part of GOT in arbitrary order.
+ bool LIsInLocalGot = !L.first->IsInGlobalMipsGot;
+ bool RIsInLocalGot = !R.first->IsInGlobalMipsGot;
+ if (LIsInLocalGot || RIsInLocalGot)
+ return !RIsInLocalGot;
+ return L.first->GotIndex < R.first->GotIndex;
+}
+
+static uint8_t getSymbolBinding(SymbolBody *Body) {
+ Symbol *S = Body->symbol();
+ uint8_t Visibility = S->Visibility;
+ if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
+ return STB_LOCAL;
+ if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE)
+ return STB_GLOBAL;
+ return S->Binding;
}
template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
@@ -1260,11 +1339,19 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
this->Header.sh_link = StrTabSec.SectionIndex;
this->Header.sh_info = NumLocals + 1;
+ if (Config->Relocatable) {
+ size_t I = NumLocals;
+ for (const std::pair<SymbolBody *, size_t> &P : Symbols)
+ P.first->DynsymIndex = ++I;
+ return;
+ }
+
if (!StrTabSec.isDynamic()) {
std::stable_sort(Symbols.begin(), Symbols.end(),
- [](SymbolBody *L, SymbolBody *R) {
- return getSymbolBinding(L) == STB_LOCAL &&
- getSymbolBinding(R) != STB_LOCAL;
+ [](const std::pair<SymbolBody *, unsigned> &L,
+ const std::pair<SymbolBody *, unsigned> &R) {
+ return getSymbolBinding(L.first) == STB_LOCAL &&
+ getSymbolBinding(R.first) != STB_LOCAL;
});
return;
}
@@ -1274,22 +1361,13 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
else if (Config->EMachine == EM_MIPS)
std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);
size_t I = 0;
- for (SymbolBody *B : Symbols)
- B->DynamicSymbolTableIndex = ++I;
+ for (const std::pair<SymbolBody *, size_t> &P : Symbols)
+ P.first->DynsymIndex = ++I;
}
template <class ELFT>
-void SymbolTableSection<ELFT>::addLocalSymbol(StringRef Name) {
- StrTabSec.reserve(Name);
- ++NumVisible;
- ++NumLocals;
-}
-
-template <class ELFT>
-void SymbolTableSection<ELFT>::addSymbol(SymbolBody *Body) {
- StrTabSec.reserve(Body->getName());
- Symbols.push_back(Body);
- ++NumVisible;
+void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
+ Symbols.push_back({B, StrTabSec.addString(B->getName(), false)});
}
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
@@ -1307,123 +1385,311 @@ template <class ELFT>
void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
// Iterate over all input object files to copy their local symbols
// to the output symbol table pointed by Buf.
- for (const std::unique_ptr<ObjectFile<ELFT>> &File : Table.getObjectFiles()) {
- Elf_Sym_Range Syms = File->getLocalSymbols();
- for (const Elf_Sym &Sym : Syms) {
- ErrorOr<StringRef> SymNameOrErr = Sym.getName(File->getStringTable());
- error(SymNameOrErr);
- StringRef SymName = *SymNameOrErr;
- if (!shouldKeepInSymtab<ELFT>(*File, SymName, Sym))
- continue;
-
+ for (const std::unique_ptr<ObjectFile<ELFT>> &File :
+ Symtab<ELFT>::X->getObjectFiles()) {
+ for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :
+ File->KeptLocalSyms) {
+ const DefinedRegular<ELFT> &Body = *P.first;
+ InputSectionBase<ELFT> *Section = Body.Section;
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
- uintX_t VA = 0;
- if (Sym.st_shndx == SHN_ABS) {
+
+ if (!Section) {
ESym->st_shndx = SHN_ABS;
- VA = Sym.st_value;
+ ESym->st_value = Body.Value;
} else {
- InputSectionBase<ELFT> *Section = File->getSection(Sym);
- if (!Section->isLive())
- continue;
const OutputSectionBase<ELFT> *OutSec = Section->OutSec;
ESym->st_shndx = OutSec->SectionIndex;
- VA = Section->getOffset(Sym);
- // Symbol offsets for AMDGPU need to be the offset in bytes of the
- // symbol from the beginning of the section.
- if (Config->EMachine != EM_AMDGPU)
- VA += OutSec->getVA();
+ ESym->st_value = OutSec->getVA() + Section->getOffset(Body);
}
- ESym->st_name = StrTabSec.addString(SymName);
- ESym->st_size = Sym.st_size;
- ESym->setBindingAndType(Sym.getBinding(), Sym.getType());
- ESym->st_value = VA;
+ ESym->st_name = P.second;
+ ESym->st_size = Body.template getSize<ELFT>();
+ ESym->setBindingAndType(STB_LOCAL, Body.Type);
Buf += sizeof(*ESym);
}
}
}
template <class ELFT>
-static const typename llvm::object::ELFFile<ELFT>::Elf_Sym *
-getElfSym(SymbolBody &Body) {
- if (auto *EBody = dyn_cast<DefinedElf<ELFT>>(&Body))
- return &EBody->Sym;
- if (auto *EBody = dyn_cast<UndefinedElf<ELFT>>(&Body))
- return &EBody->Sym;
- return nullptr;
-}
-
-template <class ELFT>
void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
// Write the internal symbol table contents to the output symbol table
// pointed by Buf.
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
- for (SymbolBody *Body : Symbols) {
- const OutputSectionBase<ELFT> *OutSec = nullptr;
+ for (const std::pair<SymbolBody *, size_t> &P : Symbols) {
+ SymbolBody *Body = P.first;
+ size_t StrOff = P.second;
- switch (Body->kind()) {
- case SymbolBody::DefinedSyntheticKind:
- OutSec = &cast<DefinedSynthetic<ELFT>>(Body)->Section;
- break;
- case SymbolBody::DefinedRegularKind: {
- auto *Sym = cast<DefinedRegular<ELFT>>(Body->repl());
- if (InputSectionBase<ELFT> *Sec = Sym->Section) {
- if (!Sec->isLive())
- continue;
- OutSec = Sec->OutSec;
- }
- break;
- }
- case SymbolBody::DefinedCommonKind:
- OutSec = Out<ELFT>::Bss;
- break;
- case SymbolBody::SharedKind: {
- if (cast<SharedSymbol<ELFT>>(Body)->NeedsCopy)
- OutSec = Out<ELFT>::Bss;
- break;
- }
- case SymbolBody::UndefinedElfKind:
- case SymbolBody::UndefinedKind:
- case SymbolBody::LazyKind:
- break;
- }
-
- StringRef Name = Body->getName();
- ESym->st_name = StrTabSec.addString(Name);
-
- unsigned char Type = STT_NOTYPE;
- uintX_t Size = 0;
- if (const Elf_Sym *InputSym = getElfSym<ELFT>(*Body)) {
- Type = InputSym->getType();
- Size = InputSym->st_size;
- } else if (auto *C = dyn_cast<DefinedCommon>(Body)) {
- Type = STT_OBJECT;
- Size = C->Size;
- }
+ uint8_t Type = Body->Type;
+ uintX_t Size = Body->getSize<ELFT>();
ESym->setBindingAndType(getSymbolBinding(Body), Type);
ESym->st_size = Size;
- ESym->setVisibility(Body->getVisibility());
- ESym->st_value = getSymVA<ELFT>(*Body);
+ ESym->st_name = StrOff;
+ ESym->setVisibility(Body->symbol()->Visibility);
+ ESym->st_value = Body->getVA<ELFT>();
- if (OutSec)
+ if (const OutputSectionBase<ELFT> *OutSec = getOutputSection(Body))
ESym->st_shndx = OutSec->SectionIndex;
else if (isa<DefinedRegular<ELFT>>(Body))
ESym->st_shndx = SHN_ABS;
+ // On MIPS we need to mark symbol which has a PLT entry and requires pointer
+ // equality by STO_MIPS_PLT flag. That is necessary to help dynamic linker
+ // distinguish such symbols and MIPS lazy-binding stubs.
+ // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
+ if (Config->EMachine == EM_MIPS && Body->isInPlt() &&
+ Body->NeedsCopyOrPltAddr)
+ ESym->st_other |= STO_MIPS_PLT;
++ESym;
}
}
template <class ELFT>
-uint8_t SymbolTableSection<ELFT>::getSymbolBinding(SymbolBody *Body) {
- uint8_t Visibility = Body->getVisibility();
- if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
- return STB_LOCAL;
- if (const Elf_Sym *ESym = getElfSym<ELFT>(*Body))
- return ESym->getBinding();
- if (isa<DefinedSynthetic<ELFT>>(Body))
- return STB_LOCAL;
- return Body->isWeak() ? STB_WEAK : STB_GLOBAL;
+const OutputSectionBase<ELFT> *
+SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
+ switch (Sym->kind()) {
+ case SymbolBody::DefinedSyntheticKind:
+ return cast<DefinedSynthetic<ELFT>>(Sym)->Section;
+ case SymbolBody::DefinedRegularKind: {
+ auto &D = cast<DefinedRegular<ELFT>>(*Sym);
+ if (D.Section)
+ return D.Section->OutSec;
+ break;
+ }
+ case SymbolBody::DefinedCommonKind:
+ return Out<ELFT>::Bss;
+ case SymbolBody::SharedKind:
+ if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy())
+ return Out<ELFT>::Bss;
+ break;
+ case SymbolBody::UndefinedKind:
+ case SymbolBody::LazyArchiveKind:
+ case SymbolBody::LazyObjectKind:
+ break;
+ case SymbolBody::DefinedBitcodeKind:
+ llvm_unreachable("should have been replaced");
+ }
+ return nullptr;
+}
+
+template <class ELFT>
+VersionDefinitionSection<ELFT>::VersionDefinitionSection()
+ : OutputSectionBase<ELFT>(".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC) {
+ this->Header.sh_addralign = sizeof(uint32_t);
+}
+
+static StringRef getFileDefName() {
+ if (!Config->SoName.empty())
+ return Config->SoName;
+ return Config->OutputFile;
+}
+
+template <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
+ FileDefNameOff = Out<ELFT>::DynStrTab->addString(getFileDefName());
+ for (VersionDefinition &V : Config->VersionDefinitions)
+ V.NameOff = Out<ELFT>::DynStrTab->addString(V.Name);
+
+ this->Header.sh_size =
+ (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
+ this->Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
+
+ // sh_info should be set to the number of definitions. This fact is missed in
+ // documentation, but confirmed by binutils community:
+ // https://sourceware.org/ml/binutils/2014-11/msg00355.html
+ this->Header.sh_info = getVerDefNum();
+}
+
+template <class ELFT>
+void VersionDefinitionSection<ELFT>::writeOne(uint8_t *Buf, uint32_t Index,
+ StringRef Name, size_t NameOff) {
+ auto *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
+ Verdef->vd_version = 1;
+ Verdef->vd_cnt = 1;
+ Verdef->vd_aux = sizeof(Elf_Verdef);
+ Verdef->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
+ Verdef->vd_flags = (Index == 1 ? VER_FLG_BASE : 0);
+ Verdef->vd_ndx = Index;
+ Verdef->vd_hash = hashSysv(Name);
+
+ auto *Verdaux = reinterpret_cast<Elf_Verdaux *>(Buf + sizeof(Elf_Verdef));
+ Verdaux->vda_name = NameOff;
+ Verdaux->vda_next = 0;
+}
+
+template <class ELFT>
+void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) {
+ writeOne(Buf, 1, getFileDefName(), FileDefNameOff);
+
+ for (VersionDefinition &V : Config->VersionDefinitions) {
+ Buf += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
+ writeOne(Buf, V.Id, V.Name, V.NameOff);
+ }
+
+ // Need to terminate the last version definition.
+ Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
+ Verdef->vd_next = 0;
+}
+
+template <class ELFT>
+VersionTableSection<ELFT>::VersionTableSection()
+ : OutputSectionBase<ELFT>(".gnu.version", SHT_GNU_versym, SHF_ALLOC) {
+ this->Header.sh_addralign = sizeof(uint16_t);
+}
+
+template <class ELFT> void VersionTableSection<ELFT>::finalize() {
+ this->Header.sh_size =
+ sizeof(Elf_Versym) * (Out<ELFT>::DynSymTab->getSymbols().size() + 1);
+ this->Header.sh_entsize = sizeof(Elf_Versym);
+ // At the moment of june 2016 GNU docs does not mention that sh_link field
+ // should be set, but Sun docs do. Also readelf relies on this field.
+ this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
+}
+
+template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
+ auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
+ for (const std::pair<SymbolBody *, size_t> &P :
+ Out<ELFT>::DynSymTab->getSymbols()) {
+ OutVersym->vs_index = P.first->symbol()->VersionId;
+ ++OutVersym;
+ }
+}
+
+template <class ELFT>
+VersionNeedSection<ELFT>::VersionNeedSection()
+ : OutputSectionBase<ELFT>(".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC) {
+ this->Header.sh_addralign = sizeof(uint32_t);
+
+ // Identifiers in verneed section start at 2 because 0 and 1 are reserved
+ // for VER_NDX_LOCAL and VER_NDX_GLOBAL.
+ // First identifiers are reserved by verdef section if it exist.
+ NextIndex = getVerDefNum() + 1;
+}
+
+template <class ELFT>
+void VersionNeedSection<ELFT>::addSymbol(SharedSymbol<ELFT> *SS) {
+ if (!SS->Verdef) {
+ SS->symbol()->VersionId = VER_NDX_GLOBAL;
+ return;
+ }
+ SharedFile<ELFT> *F = SS->file();
+ // If we don't already know that we need an Elf_Verneed for this DSO, prepare
+ // to create one by adding it to our needed list and creating a dynstr entry
+ // for the soname.
+ if (F->VerdefMap.empty())
+ Needed.push_back({F, Out<ELFT>::DynStrTab->addString(F->getSoName())});
+ typename SharedFile<ELFT>::NeededVer &NV = F->VerdefMap[SS->Verdef];
+ // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef,
+ // prepare to create one by allocating a version identifier and creating a
+ // dynstr entry for the version name.
+ if (NV.Index == 0) {
+ NV.StrTab = Out<ELFT>::DynStrTab->addString(
+ SS->file()->getStringTable().data() + SS->Verdef->getAux()->vda_name);
+ NV.Index = NextIndex++;
+ }
+ SS->symbol()->VersionId = NV.Index;
+}
+
+template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
+ // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs.
+ auto *Verneed = reinterpret_cast<Elf_Verneed *>(Buf);
+ auto *Vernaux = reinterpret_cast<Elf_Vernaux *>(Verneed + Needed.size());
+
+ for (std::pair<SharedFile<ELFT> *, size_t> &P : Needed) {
+ // Create an Elf_Verneed for this DSO.
+ Verneed->vn_version = 1;
+ Verneed->vn_cnt = P.first->VerdefMap.size();
+ Verneed->vn_file = P.second;
+ Verneed->vn_aux =
+ reinterpret_cast<char *>(Vernaux) - reinterpret_cast<char *>(Verneed);
+ Verneed->vn_next = sizeof(Elf_Verneed);
+ ++Verneed;
+
+ // Create the Elf_Vernauxs for this Elf_Verneed. The loop iterates over
+ // VerdefMap, which will only contain references to needed version
+ // definitions. Each Elf_Vernaux is based on the information contained in
+ // the Elf_Verdef in the source DSO. This loop iterates over a std::map of
+ // pointers, but is deterministic because the pointers refer to Elf_Verdef
+ // data structures within a single input file.
+ for (auto &NV : P.first->VerdefMap) {
+ Vernaux->vna_hash = NV.first->vd_hash;
+ Vernaux->vna_flags = 0;
+ Vernaux->vna_other = NV.second.Index;
+ Vernaux->vna_name = NV.second.StrTab;
+ Vernaux->vna_next = sizeof(Elf_Vernaux);
+ ++Vernaux;
+ }
+
+ Vernaux[-1].vna_next = 0;
+ }
+ Verneed[-1].vn_next = 0;
+}
+
+template <class ELFT> void VersionNeedSection<ELFT>::finalize() {
+ this->Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
+ this->Header.sh_info = Needed.size();
+ unsigned Size = Needed.size() * sizeof(Elf_Verneed);
+ for (std::pair<SharedFile<ELFT> *, size_t> &P : Needed)
+ Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux);
+ this->Header.sh_size = Size;
+}
+
+template <class ELFT>
+BuildIdSection<ELFT>::BuildIdSection(size_t HashSize)
+ : OutputSectionBase<ELFT>(".note.gnu.build-id", SHT_NOTE, SHF_ALLOC),
+ HashSize(HashSize) {
+ // 16 bytes for the note section header.
+ this->Header.sh_size = 16 + HashSize;
+}
+
+template <class ELFT> void BuildIdSection<ELFT>::writeTo(uint8_t *Buf) {
+ const endianness E = ELFT::TargetEndianness;
+ write32<E>(Buf, 4); // Name size
+ write32<E>(Buf + 4, HashSize); // Content size
+ write32<E>(Buf + 8, NT_GNU_BUILD_ID); // Type
+ memcpy(Buf + 12, "GNU", 4); // Name string
+ HashBuf = Buf + 16;
+}
+
+template <class ELFT>
+void BuildIdFnv1<ELFT>::writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) {
+ const endianness E = ELFT::TargetEndianness;
+
+ // 64-bit FNV-1 hash
+ uint64_t Hash = 0xcbf29ce484222325;
+ for (ArrayRef<uint8_t> Buf : Bufs) {
+ for (uint8_t B : Buf) {
+ Hash *= 0x100000001b3;
+ Hash ^= B;
+ }
+ }
+ write64<E>(this->HashBuf, Hash);
+}
+
+template <class ELFT>
+void BuildIdMd5<ELFT>::writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) {
+ MD5 Hash;
+ for (ArrayRef<uint8_t> Buf : Bufs)
+ Hash.update(Buf);
+ MD5::MD5Result Res;
+ Hash.final(Res);
+ memcpy(this->HashBuf, Res, 16);
+}
+
+template <class ELFT>
+void BuildIdSha1<ELFT>::writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) {
+ SHA1 Hash;
+ for (ArrayRef<uint8_t> Buf : Bufs)
+ Hash.update(Buf);
+ memcpy(this->HashBuf, Hash.final().data(), 20);
+}
+
+template <class ELFT>
+BuildIdHexstring<ELFT>::BuildIdHexstring()
+ : BuildIdSection<ELFT>(Config->BuildIdVector.size()) {}
+
+template <class ELFT>
+void BuildIdHexstring<ELFT>::writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) {
+ memcpy(this->HashBuf, Config->BuildIdVector.data(),
+ Config->BuildIdVector.size());
}
template <class ELFT>
@@ -1437,7 +1703,7 @@ MipsReginfoOutputSection<ELFT>::MipsReginfoOutputSection()
template <class ELFT>
void MipsReginfoOutputSection<ELFT>::writeTo(uint8_t *Buf) {
auto *R = reinterpret_cast<Elf_Mips_RegInfo *>(Buf);
- R->ri_gp_value = getMipsGpAddr<ELFT>();
+ R->ri_gp_value = Out<ELFT>::Got->getVA() + MipsGPOffset;
R->ri_gprmask = GprMask;
}
@@ -1446,15 +1712,136 @@ void MipsReginfoOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
// Copy input object file's .reginfo gprmask to output.
auto *S = cast<MipsReginfoInputSection<ELFT>>(C);
GprMask |= S->Reginfo->ri_gprmask;
+ S->OutSec = this;
+}
+
+template <class ELFT>
+MipsOptionsOutputSection<ELFT>::MipsOptionsOutputSection()
+ : OutputSectionBase<ELFT>(".MIPS.options", SHT_MIPS_OPTIONS,
+ SHF_ALLOC | SHF_MIPS_NOSTRIP) {
+ this->Header.sh_addralign = 8;
+ this->Header.sh_entsize = 1;
+ this->Header.sh_size = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
+}
+
+template <class ELFT>
+void MipsOptionsOutputSection<ELFT>::writeTo(uint8_t *Buf) {
+ auto *Opt = reinterpret_cast<Elf_Mips_Options *>(Buf);
+ Opt->kind = ODK_REGINFO;
+ Opt->size = this->Header.sh_size;
+ Opt->section = 0;
+ Opt->info = 0;
+ auto *Reg = reinterpret_cast<Elf_Mips_RegInfo *>(Buf + sizeof(*Opt));
+ Reg->ri_gp_value = Out<ELFT>::Got->getVA() + MipsGPOffset;
+ Reg->ri_gprmask = GprMask;
+}
+
+template <class ELFT>
+void MipsOptionsOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
+ auto *S = cast<MipsOptionsInputSection<ELFT>>(C);
+ if (S->Reginfo)
+ GprMask |= S->Reginfo->ri_gprmask;
+ S->OutSec = this;
+}
+
+template <class ELFT>
+std::pair<OutputSectionBase<ELFT> *, bool>
+OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
+ StringRef OutsecName) {
+ SectionKey<ELFT::Is64Bits> Key = createKey(C, OutsecName);
+ OutputSectionBase<ELFT> *&Sec = Map[Key];
+ if (Sec)
+ return {Sec, false};
+
+ switch (C->SectionKind) {
+ case InputSectionBase<ELFT>::Regular:
+ Sec = new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ break;
+ case InputSectionBase<ELFT>::EHFrame:
+ return {Out<ELFT>::EhFrame, false};
+ case InputSectionBase<ELFT>::Merge:
+ Sec = new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags,
+ Key.Alignment);
+ break;
+ case InputSectionBase<ELFT>::MipsReginfo:
+ Sec = new MipsReginfoOutputSection<ELFT>();
+ break;
+ case InputSectionBase<ELFT>::MipsOptions:
+ Sec = new MipsOptionsOutputSection<ELFT>();
+ break;
+ }
+ return {Sec, true};
+}
+
+template <class ELFT>
+OutputSectionBase<ELFT> *OutputSectionFactory<ELFT>::lookup(StringRef Name,
+ uint32_t Type,
+ uintX_t Flags) {
+ return Map.lookup({Name, Type, Flags, 0});
+}
+
+template <class ELFT>
+SectionKey<ELFT::Is64Bits>
+OutputSectionFactory<ELFT>::createKey(InputSectionBase<ELFT> *C,
+ StringRef OutsecName) {
+ const Elf_Shdr *H = C->getSectionHdr();
+ uintX_t Flags = H->sh_flags & ~SHF_GROUP & ~SHF_COMPRESSED;
+
+ // For SHF_MERGE we create different output sections for each alignment.
+ // This makes each output section simple and keeps a single level mapping from
+ // input to output.
+ uintX_t Alignment = 0;
+ if (isa<MergeInputSection<ELFT>>(C))
+ Alignment = std::max(H->sh_addralign, H->sh_entsize);
+
+ uint32_t Type = H->sh_type;
+ return SectionKey<ELFT::Is64Bits>{OutsecName, Type, Flags, Alignment};
+}
+
+template <bool Is64Bits>
+typename lld::elf::SectionKey<Is64Bits>
+DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getEmptyKey() {
+ return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0, 0};
+}
+
+template <bool Is64Bits>
+typename lld::elf::SectionKey<Is64Bits>
+DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getTombstoneKey() {
+ return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 0,
+ 0};
+}
+
+template <bool Is64Bits>
+unsigned
+DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getHashValue(const Key &Val) {
+ return hash_combine(Val.Name, Val.Type, Val.Flags, Val.Alignment);
+}
+
+template <bool Is64Bits>
+bool DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::isEqual(const Key &LHS,
+ const Key &RHS) {
+ return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
+ LHS.Type == RHS.Type && LHS.Flags == RHS.Flags &&
+ LHS.Alignment == RHS.Alignment;
+}
+
+namespace llvm {
+template struct DenseMapInfo<SectionKey<true>>;
+template struct DenseMapInfo<SectionKey<false>>;
}
namespace lld {
-namespace elf2 {
+namespace elf {
template class OutputSectionBase<ELF32LE>;
template class OutputSectionBase<ELF32BE>;
template class OutputSectionBase<ELF64LE>;
template class OutputSectionBase<ELF64BE>;
+template class EhFrameHeader<ELF32LE>;
+template class EhFrameHeader<ELF32BE>;
+template class EhFrameHeader<ELF64LE>;
+template class EhFrameHeader<ELF64BE>;
+
template class GotPltSection<ELF32LE>;
template class GotPltSection<ELF32BE>;
template class GotPltSection<ELF64LE>;
@@ -1500,16 +1887,21 @@ template class OutputSection<ELF32BE>;
template class OutputSection<ELF64LE>;
template class OutputSection<ELF64BE>;
-template class EHOutputSection<ELF32LE>;
-template class EHOutputSection<ELF32BE>;
-template class EHOutputSection<ELF64LE>;
-template class EHOutputSection<ELF64BE>;
+template class EhOutputSection<ELF32LE>;
+template class EhOutputSection<ELF32BE>;
+template class EhOutputSection<ELF64LE>;
+template class EhOutputSection<ELF64BE>;
template class MipsReginfoOutputSection<ELF32LE>;
template class MipsReginfoOutputSection<ELF32BE>;
template class MipsReginfoOutputSection<ELF64LE>;
template class MipsReginfoOutputSection<ELF64BE>;
+template class MipsOptionsOutputSection<ELF32LE>;
+template class MipsOptionsOutputSection<ELF32BE>;
+template class MipsOptionsOutputSection<ELF64LE>;
+template class MipsOptionsOutputSection<ELF64BE>;
+
template class MergeOutputSection<ELF32LE>;
template class MergeOutputSection<ELF32BE>;
template class MergeOutputSection<ELF64LE>;
@@ -1525,39 +1917,49 @@ template class SymbolTableSection<ELF32BE>;
template class SymbolTableSection<ELF64LE>;
template class SymbolTableSection<ELF64BE>;
-template ELFFile<ELF32LE>::uintX_t getSymVA<ELF32LE>(const SymbolBody &);
-template ELFFile<ELF32BE>::uintX_t getSymVA<ELF32BE>(const SymbolBody &);
-template ELFFile<ELF64LE>::uintX_t getSymVA<ELF64LE>(const SymbolBody &);
-template ELFFile<ELF64BE>::uintX_t getSymVA<ELF64BE>(const SymbolBody &);
-
-template ELFFile<ELF32LE>::uintX_t
-getLocalRelTarget(const ObjectFile<ELF32LE> &,
- const ELFFile<ELF32LE>::Elf_Rel &,
- ELFFile<ELF32LE>::uintX_t Addend);
-template ELFFile<ELF32BE>::uintX_t
-getLocalRelTarget(const ObjectFile<ELF32BE> &,
- const ELFFile<ELF32BE>::Elf_Rel &,
- ELFFile<ELF32BE>::uintX_t Addend);
-template ELFFile<ELF64LE>::uintX_t
-getLocalRelTarget(const ObjectFile<ELF64LE> &,
- const ELFFile<ELF64LE>::Elf_Rel &,
- ELFFile<ELF64LE>::uintX_t Addend);
-template ELFFile<ELF64BE>::uintX_t
-getLocalRelTarget(const ObjectFile<ELF64BE> &,
- const ELFFile<ELF64BE>::Elf_Rel &,
- ELFFile<ELF64BE>::uintX_t Addend);
-
-template bool shouldKeepInSymtab<ELF32LE>(const ObjectFile<ELF32LE> &,
- StringRef,
- const ELFFile<ELF32LE>::Elf_Sym &);
-template bool shouldKeepInSymtab<ELF32BE>(const ObjectFile<ELF32BE> &,
- StringRef,
- const ELFFile<ELF32BE>::Elf_Sym &);
-template bool shouldKeepInSymtab<ELF64LE>(const ObjectFile<ELF64LE> &,
- StringRef,
- const ELFFile<ELF64LE>::Elf_Sym &);
-template bool shouldKeepInSymtab<ELF64BE>(const ObjectFile<ELF64BE> &,
- StringRef,
- const ELFFile<ELF64BE>::Elf_Sym &);
+template class VersionTableSection<ELF32LE>;
+template class VersionTableSection<ELF32BE>;
+template class VersionTableSection<ELF64LE>;
+template class VersionTableSection<ELF64BE>;
+
+template class VersionNeedSection<ELF32LE>;
+template class VersionNeedSection<ELF32BE>;
+template class VersionNeedSection<ELF64LE>;
+template class VersionNeedSection<ELF64BE>;
+
+template class VersionDefinitionSection<ELF32LE>;
+template class VersionDefinitionSection<ELF32BE>;
+template class VersionDefinitionSection<ELF64LE>;
+template class VersionDefinitionSection<ELF64BE>;
+
+template class BuildIdSection<ELF32LE>;
+template class BuildIdSection<ELF32BE>;
+template class BuildIdSection<ELF64LE>;
+template class BuildIdSection<ELF64BE>;
+
+template class BuildIdFnv1<ELF32LE>;
+template class BuildIdFnv1<ELF32BE>;
+template class BuildIdFnv1<ELF64LE>;
+template class BuildIdFnv1<ELF64BE>;
+
+template class BuildIdMd5<ELF32LE>;
+template class BuildIdMd5<ELF32BE>;
+template class BuildIdMd5<ELF64LE>;
+template class BuildIdMd5<ELF64BE>;
+
+template class BuildIdSha1<ELF32LE>;
+template class BuildIdSha1<ELF32BE>;
+template class BuildIdSha1<ELF64LE>;
+template class BuildIdSha1<ELF64BE>;
+
+template class BuildIdHexstring<ELF32LE>;
+template class BuildIdHexstring<ELF32BE>;
+template class BuildIdHexstring<ELF64LE>;
+template class BuildIdHexstring<ELF64BE>;
+
+template class OutputSectionFactory<ELF32LE>;
+template class OutputSectionFactory<ELF32BE>;
+template class OutputSectionFactory<ELF64LE>;
+template class OutputSectionFactory<ELF64BE>;
}
}
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index d7109c580cdc..5fdf8de4cb46 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -10,64 +10,35 @@
#ifndef LLD_ELF_OUTPUT_SECTIONS_H
#define LLD_ELF_OUTPUT_SECTIONS_H
-#include "lld/Core/LLVM.h"
+#include "Config.h"
+#include "Relocations.h"
-#include "llvm/ADT/MapVector.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELF.h"
-
-#include "Config.h"
-
-#include <type_traits>
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/SHA1.h"
namespace lld {
-namespace elf2 {
+namespace elf {
class SymbolBody;
+struct SectionPiece;
template <class ELFT> class SymbolTable;
template <class ELFT> class SymbolTableSection;
template <class ELFT> class StringTableSection;
-template <class ELFT> class EHInputSection;
+template <class ELFT> class EhInputSection;
template <class ELFT> class InputSection;
template <class ELFT> class InputSectionBase;
template <class ELFT> class MergeInputSection;
template <class ELFT> class MipsReginfoInputSection;
template <class ELFT> class OutputSection;
template <class ELFT> class ObjectFile;
+template <class ELFT> class SharedFile;
+template <class ELFT> class SharedSymbol;
template <class ELFT> class DefinedRegular;
-// Flag to force GOT to be in output if we have relocations
-// that relies on its address.
-extern bool HasGotOffRel;
-
-template <class ELFT>
-static inline typename llvm::object::ELFFile<ELFT>::uintX_t
-getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rel &Rel) {
- return 0;
-}
-
-template <class ELFT>
-static inline typename llvm::object::ELFFile<ELFT>::uintX_t
-getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rela &Rel) {
- return Rel.r_addend;
-}
-
-template <class ELFT>
-typename llvm::object::ELFFile<ELFT>::uintX_t getSymVA(const SymbolBody &S);
-
-template <class ELFT, bool IsRela>
-typename llvm::object::ELFFile<ELFT>::uintX_t
-getLocalRelTarget(const ObjectFile<ELFT> &File,
- const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel,
- typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
-
-bool canBePreempted(const SymbolBody *Body, bool NeedsGot);
-
-template <class ELFT>
-bool shouldKeepInSymtab(
- const ObjectFile<ELFT> &File, StringRef Name,
- const typename llvm::object::ELFFile<ELFT>::Elf_Sym &Sym);
-
// This represents a section in an output file.
// Different sub classes represent different types of sections. Some contain
// input sections, others are created by the linker.
@@ -75,13 +46,14 @@ bool shouldKeepInSymtab(
// non-overlapping file offsets and VAs.
template <class ELFT> class OutputSectionBase {
public:
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Shdr Elf_Shdr;
- OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ OutputSectionBase(StringRef Name, uint32_t Type, uintX_t Flags);
void setVA(uintX_t VA) { Header.sh_addr = VA; }
uintX_t getVA() const { return Header.sh_addr; }
void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
+ void setSHName(unsigned Val) { Header.sh_name = Val; }
void writeHeaderTo(Elf_Shdr *SHdr);
StringRef getName() { return Name; }
@@ -92,21 +64,24 @@ public:
// Returns the size of the section in the output file.
uintX_t getSize() const { return Header.sh_size; }
void setSize(uintX_t Val) { Header.sh_size = Val; }
- uintX_t getFlags() { return Header.sh_flags; }
- uintX_t getFileOff() { return Header.sh_offset; }
- uintX_t getAlign() {
- // The ELF spec states that a value of 0 means the section has no alignment
- // constraits.
- return std::max<uintX_t>(Header.sh_addralign, 1);
- }
- uint32_t getType() { return Header.sh_type; }
- void updateAlign(uintX_t Align) {
- if (Align > Header.sh_addralign)
- Header.sh_addralign = Align;
+ uintX_t getFlags() const { return Header.sh_flags; }
+ uintX_t getFileOff() const { return Header.sh_offset; }
+ uintX_t getAlignment() const { return Header.sh_addralign; }
+ uint32_t getType() const { return Header.sh_type; }
+
+ void updateAlignment(uintX_t Alignment) {
+ if (Alignment > Header.sh_addralign)
+ Header.sh_addralign = Alignment;
}
+ // If true, this section will be page aligned on disk.
+ // Typically the first section of each PT_LOAD segment has this flag.
+ bool PageAlign = false;
+
virtual void finalize() {}
- virtual void writeTo(uint8_t *Buf) = 0;
+ virtual void finalizePieces() {}
+ virtual void assignOffsets() {}
+ virtual void writeTo(uint8_t *Buf) {}
virtual ~OutputSectionBase() = default;
protected:
@@ -116,18 +91,21 @@ protected:
template <class ELFT> class GotSection final : public OutputSectionBase<ELFT> {
typedef OutputSectionBase<ELFT> Base;
- typedef typename Base::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
public:
GotSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- void addEntry(SymbolBody *Sym);
- bool addDynTlsEntry(SymbolBody *Sym);
- bool addCurrentModuleTlsIndex();
- bool empty() const { return Entries.empty(); }
- uintX_t getEntryAddr(const SymbolBody &B) const;
+ void addEntry(SymbolBody &Sym);
+ void addMipsEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr);
+ bool addDynTlsEntry(SymbolBody &Sym);
+ bool addTlsIndex();
+ bool empty() const { return MipsPageEntries == 0 && Entries.empty(); }
+ uintX_t getMipsLocalPageOffset(uintX_t Addr);
+ uintX_t getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const;
uintX_t getGlobalDynAddr(const SymbolBody &B) const;
+ uintX_t getGlobalDynOffset(const SymbolBody &B) const;
uintX_t getNumEntries() const { return Entries.size(); }
// Returns the symbol which corresponds to the first entry of the global part
@@ -140,24 +118,52 @@ public:
// the number of reserved entries. This method is MIPS-specific.
unsigned getMipsLocalEntriesNum() const;
- uint32_t getLocalTlsIndexVA() { return Base::getVA() + LocalTlsIndexOff; }
+ // Returns offset of TLS part of the MIPS GOT table. This part goes
+ // after 'local' and 'global' entries.
+ uintX_t getMipsTlsOffset();
+
+ uintX_t getTlsIndexVA() { return Base::getVA() + TlsIndexOff; }
+ uint32_t getTlsIndexOff() { return TlsIndexOff; }
+
+ // Flag to force GOT to be in output if we have relocations
+ // that relies on its address.
+ bool HasGotOffRel = false;
private:
std::vector<const SymbolBody *> Entries;
- uint32_t LocalTlsIndexOff = -1;
+ uint32_t TlsIndexOff = -1;
+ uint32_t MipsPageEntries = 0;
+ // Output sections referenced by MIPS GOT relocations.
+ llvm::SmallPtrSet<const OutputSectionBase<ELFT> *, 10> MipsOutSections;
+ llvm::DenseMap<uintX_t, size_t> MipsLocalGotPos;
+
+ // MIPS ABI requires to create unique GOT entry for each Symbol/Addend
+ // pairs. The `MipsGotMap` maps (S,A) pair to the GOT index in the `MipsLocal`
+ // or `MipsGlobal` vectors. In general it does not have a sence to take in
+ // account addend for preemptible symbols because the corresponding
+ // GOT entries should have one-to-one mapping with dynamic symbols table.
+ // But we use the same container's types for both kind of GOT entries
+ // to handle them uniformly.
+ typedef std::pair<const SymbolBody*, uintX_t> MipsGotEntry;
+ typedef std::vector<MipsGotEntry> MipsGotEntries;
+ llvm::DenseMap<MipsGotEntry, size_t> MipsGotMap;
+ MipsGotEntries MipsLocal;
+ MipsGotEntries MipsGlobal;
+
+ // Write MIPS-specific parts of the GOT.
+ void writeMipsGot(uint8_t *&Buf);
};
template <class ELFT>
class GotPltSection final : public OutputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
public:
GotPltSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- void addEntry(SymbolBody *Sym);
+ void addEntry(SymbolBody &Sym);
bool empty() const;
- uintX_t getEntryAddr(const SymbolBody &B) const;
private:
std::vector<const SymbolBody *> Entries;
@@ -165,156 +171,248 @@ private:
template <class ELFT> class PltSection final : public OutputSectionBase<ELFT> {
typedef OutputSectionBase<ELFT> Base;
- typedef typename Base::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
public:
PltSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- void addEntry(SymbolBody *Sym);
+ void addEntry(SymbolBody &Sym);
bool empty() const { return Entries.empty(); }
- uintX_t getEntryAddr(const SymbolBody &B) const;
private:
std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
};
-template <class ELFT> struct DynamicReloc {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- InputSectionBase<ELFT> *C;
- const Elf_Rel *RI;
+template <class ELFT> class DynamicReloc {
+ typedef typename ELFT::uint uintX_t;
+
+public:
+ DynamicReloc(uint32_t Type, const InputSectionBase<ELFT> *InputSec,
+ uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym,
+ uintX_t Addend)
+ : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec),
+ UseSymVA(UseSymVA), Addend(Addend) {}
+
+ DynamicReloc(uint32_t Type, const OutputSectionBase<ELFT> *OutputSec,
+ uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym,
+ uintX_t Addend)
+ : Type(Type), Sym(Sym), OutputSec(OutputSec), OffsetInSec(OffsetInSec),
+ UseSymVA(UseSymVA), Addend(Addend) {}
+
+ uintX_t getOffset() const;
+ uintX_t getAddend() const;
+ uint32_t getSymIndex() const;
+ const OutputSectionBase<ELFT> *getOutputSec() const { return OutputSec; }
+
+ uint32_t Type;
+
+private:
+ SymbolBody *Sym;
+ const InputSectionBase<ELFT> *InputSec = nullptr;
+ const OutputSectionBase<ELFT> *OutputSec = nullptr;
+ uintX_t OffsetInSec;
+ bool UseSymVA;
+ uintX_t Addend;
};
template <class ELFT>
class SymbolTableSection final : public OutputSectionBase<ELFT> {
public:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- SymbolTableSection(SymbolTable<ELFT> &Table,
- StringTableSection<ELFT> &StrTabSec);
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::SymRange Elf_Sym_Range;
+ typedef typename ELFT::uint uintX_t;
+ SymbolTableSection(StringTableSection<ELFT> &StrTabSec);
void finalize() override;
void writeTo(uint8_t *Buf) override;
- void addLocalSymbol(StringRef Name);
void addSymbol(SymbolBody *Body);
StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
- unsigned getNumSymbols() const { return NumVisible + 1; }
+ unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
- ArrayRef<SymbolBody *> getSymbols() const { return Symbols; }
+ ArrayRef<std::pair<SymbolBody *, size_t>> getSymbols() const {
+ return Symbols;
+ }
+
+ unsigned NumLocals = 0;
+ StringTableSection<ELFT> &StrTabSec;
private:
void writeLocalSymbols(uint8_t *&Buf);
void writeGlobalSymbols(uint8_t *Buf);
- static uint8_t getSymbolBinding(SymbolBody *Body);
+ const OutputSectionBase<ELFT> *getOutputSection(SymbolBody *Sym);
- SymbolTable<ELFT> &Table;
- StringTableSection<ELFT> &StrTabSec;
- std::vector<SymbolBody *> Symbols;
- unsigned NumVisible = 0;
- unsigned NumLocals = 0;
+ // A vector of symbols and their string table offsets.
+ std::vector<std::pair<SymbolBody *, size_t>> Symbols;
+};
+
+// For more information about .gnu.version and .gnu.version_r see:
+// https://www.akkadia.org/drepper/symbol-versioning
+
+// The .gnu.version_d section which has a section type of SHT_GNU_verdef shall
+// contain symbol version definitions. The number of entries in this section
+// shall be contained in the DT_VERDEFNUM entry of the .dynamic section.
+// The section shall contain an array of Elf_Verdef structures, optionally
+// followed by an array of Elf_Verdaux structures.
+template <class ELFT>
+class VersionDefinitionSection final : public OutputSectionBase<ELFT> {
+ typedef typename ELFT::Verdef Elf_Verdef;
+ typedef typename ELFT::Verdaux Elf_Verdaux;
+
+public:
+ VersionDefinitionSection();
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+
+private:
+ void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff);
+
+ unsigned FileDefNameOff;
+};
+
+// The .gnu.version section specifies the required version of each symbol in the
+// dynamic symbol table. It contains one Elf_Versym for each dynamic symbol
+// table entry. An Elf_Versym is just a 16-bit integer that refers to a version
+// identifier defined in the either .gnu.version_r or .gnu.version_d section.
+// The values 0 and 1 are reserved. All other values are used for versions in
+// the own object or in any of the dependencies.
+template <class ELFT>
+class VersionTableSection final : public OutputSectionBase<ELFT> {
+ typedef typename ELFT::Versym Elf_Versym;
+
+public:
+ VersionTableSection();
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+};
+
+// The .gnu.version_r section defines the version identifiers used by
+// .gnu.version. It contains a linked list of Elf_Verneed data structures. Each
+// Elf_Verneed specifies the version requirements for a single DSO, and contains
+// a reference to a linked list of Elf_Vernaux data structures which define the
+// mapping from version identifiers to version names.
+template <class ELFT>
+class VersionNeedSection final : public OutputSectionBase<ELFT> {
+ typedef typename ELFT::Verneed Elf_Verneed;
+ typedef typename ELFT::Vernaux Elf_Vernaux;
+
+ // A vector of shared files that need Elf_Verneed data structures and the
+ // string table offsets of their sonames.
+ std::vector<std::pair<SharedFile<ELFT> *, size_t>> Needed;
+
+ // The next available version identifier.
+ unsigned NextIndex;
+
+public:
+ VersionNeedSection();
+ void addSymbol(SharedSymbol<ELFT> *SS);
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+ size_t getNeedNum() const { return Needed.size(); }
};
template <class ELFT>
class RelocationSection final : public OutputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Rel Elf_Rel;
+ typedef typename ELFT::Rela Elf_Rela;
+ typedef typename ELFT::uint uintX_t;
public:
- RelocationSection(StringRef Name, bool IsRela);
- void addReloc(const DynamicReloc<ELFT> &Reloc) { Relocs.push_back(Reloc); }
+ RelocationSection(StringRef Name, bool Sort);
+ void addReloc(const DynamicReloc<ELFT> &Reloc);
unsigned getRelocOffset();
void finalize() override;
void writeTo(uint8_t *Buf) override;
bool hasRelocs() const { return !Relocs.empty(); }
- bool isRela() const { return IsRela; }
bool Static = false;
private:
- bool applyTlsDynamicReloc(SymbolBody *Body, uint32_t Type, Elf_Rel *P,
- Elf_Rel *N);
-
+ bool Sort;
std::vector<DynamicReloc<ELFT>> Relocs;
- const bool IsRela;
};
template <class ELFT>
class OutputSection final : public OutputSectionBase<ELFT> {
public:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::Rel Elf_Rel;
+ typedef typename ELFT::Rela Elf_Rela;
+ typedef typename ELFT::uint uintX_t;
+ OutputSection(StringRef Name, uint32_t Type, uintX_t Flags);
void addSection(InputSectionBase<ELFT> *C) override;
+ void sortInitFini();
+ void sortCtorsDtors();
void writeTo(uint8_t *Buf) override;
-
-private:
+ void finalize() override;
+ void assignOffsets() override;
std::vector<InputSection<ELFT> *> Sections;
};
template <class ELFT>
class MergeOutputSection final : public OutputSectionBase<ELFT> {
- typedef typename OutputSectionBase<ELFT>::uintX_t uintX_t;
-
- bool shouldTailMerge() const;
+ typedef typename ELFT::uint uintX_t;
public:
- MergeOutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ MergeOutputSection(StringRef Name, uint32_t Type, uintX_t Flags,
+ uintX_t Alignment);
void addSection(InputSectionBase<ELFT> *S) override;
void writeTo(uint8_t *Buf) override;
unsigned getOffset(StringRef Val);
void finalize() override;
+ void finalizePieces() override;
+ bool shouldTailMerge() const;
private:
- llvm::StringTableBuilder Builder{llvm::StringTableBuilder::RAW};
+ llvm::StringTableBuilder Builder;
+ std::vector<MergeInputSection<ELFT> *> Sections;
};
-// FDE or CIE
-template <class ELFT> struct EHRegion {
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- EHRegion(EHInputSection<ELFT> *S, unsigned Index);
- StringRef data() const;
- EHInputSection<ELFT> *S;
- unsigned Index;
-};
-
-template <class ELFT> struct Cie : public EHRegion<ELFT> {
- Cie(EHInputSection<ELFT> *S, unsigned Index);
- std::vector<EHRegion<ELFT>> Fdes;
+struct CieRecord {
+ SectionPiece *Piece = nullptr;
+ std::vector<SectionPiece *> FdePieces;
};
+// Output section for .eh_frame.
template <class ELFT>
-class EHOutputSection final : public OutputSectionBase<ELFT> {
+class EhOutputSection final : public OutputSectionBase<ELFT> {
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Rel Elf_Rel;
+ typedef typename ELFT::Rela Elf_Rela;
+
public:
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- EHOutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ EhOutputSection();
void writeTo(uint8_t *Buf) override;
-
- template <bool IsRela>
- void addSectionAux(
- EHInputSection<ELFT> *S,
- llvm::iterator_range<const llvm::object::Elf_Rel_Impl<ELFT, IsRela> *>
- Rels);
+ void finalize() override;
+ bool empty() const { return Sections.empty(); }
void addSection(InputSectionBase<ELFT> *S) override;
+ size_t NumFdes = 0;
+
private:
- uintX_t readEntryLength(ArrayRef<uint8_t> D);
+ template <class RelTy>
+ void addSectionAux(EhInputSection<ELFT> *S, llvm::ArrayRef<RelTy> Rels);
+
+ template <class RelTy>
+ CieRecord *addCie(SectionPiece &Piece, EhInputSection<ELFT> *Sec,
+ ArrayRef<RelTy> &Rels);
+
+ template <class RelTy>
+ bool isFdeLive(SectionPiece &Piece, EhInputSection<ELFT> *Sec,
+ ArrayRef<RelTy> &Rels);
+
+ uintX_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc);
- std::vector<EHInputSection<ELFT> *> Sections;
- std::vector<Cie<ELFT>> Cies;
+ std::vector<EhInputSection<ELFT> *> Sections;
+ std::vector<CieRecord *> Cies;
- // Maps CIE content + personality to a index in Cies.
- llvm::DenseMap<std::pair<StringRef, StringRef>, unsigned> CieMap;
+ // CIE records are uniquified by their contents and personality functions.
+ llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap;
};
template <class ELFT>
@@ -327,25 +425,24 @@ public:
template <class ELFT>
class StringTableSection final : public OutputSectionBase<ELFT> {
public:
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
StringTableSection(StringRef Name, bool Dynamic);
- void reserve(StringRef S);
- size_t addString(StringRef S);
+ unsigned addString(StringRef S, bool HashIt = true);
void writeTo(uint8_t *Buf) override;
- size_t getSize() const { return Used + Reserved; }
+ unsigned getSize() const { return Size; }
void finalize() override { this->Header.sh_size = getSize(); }
bool isDynamic() const { return Dynamic; }
private:
const bool Dynamic;
+ llvm::DenseMap<StringRef, unsigned> StringMap;
std::vector<StringRef> Strings;
- size_t Used = 1; // ELF string tables start with a NUL byte, so 1.
- size_t Reserved = 0;
+ unsigned Size = 1; // ELF string tables start with a NUL byte, so 1.
};
template <class ELFT>
class HashTableSection final : public OutputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
+ typedef typename ELFT::Word Elf_Word;
public:
HashTableSection();
@@ -357,9 +454,9 @@ public:
// https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections
template <class ELFT>
class GnuHashTableSection final : public OutputSectionBase<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Off Elf_Off;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Off Elf_Off;
+ typedef typename ELFT::Word Elf_Word;
+ typedef typename ELFT::uint uintX_t;
public:
GnuHashTableSection();
@@ -368,7 +465,7 @@ public:
// Adds symbols to the hash table.
// Sorts the input to satisfy GNU hash section requirements.
- void addSymbols(std::vector<SymbolBody *> &Symbols);
+ void addSymbols(std::vector<std::pair<SymbolBody *, size_t>> &Symbols);
private:
static unsigned calcNBuckets(unsigned NumHashed);
@@ -378,12 +475,13 @@ private:
void writeBloomFilter(uint8_t *&Buf);
void writeHashTable(uint8_t *Buf);
- struct HashedSymbolData {
+ struct SymbolData {
SymbolBody *Body;
+ size_t STName;
uint32_t Hash;
};
- std::vector<HashedSymbolData> HashedSymbols;
+ std::vector<SymbolData> Symbols;
unsigned MaskWords;
unsigned NBuckets;
@@ -393,27 +491,45 @@ private:
template <class ELFT>
class DynamicSection final : public OutputSectionBase<ELFT> {
typedef OutputSectionBase<ELFT> Base;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+ typedef typename ELFT::Dyn Elf_Dyn;
+ typedef typename ELFT::Rel Elf_Rel;
+ typedef typename ELFT::Rela Elf_Rela;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::uint uintX_t;
+
+ // The .dynamic section contains information for the dynamic linker.
+ // The section consists of fixed size entries, which consist of
+ // type and value fields. Value are one of plain integers, symbol
+ // addresses, or section addresses. This struct represents the entry.
+ struct Entry {
+ int32_t Tag;
+ union {
+ OutputSectionBase<ELFT> *OutSec;
+ uint64_t Val;
+ const SymbolBody *Sym;
+ };
+ enum KindT { SecAddr, SymAddr, PlainInt } Kind;
+ Entry(int32_t Tag, OutputSectionBase<ELFT> *OutSec)
+ : Tag(Tag), OutSec(OutSec), Kind(SecAddr) {}
+ Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {}
+ Entry(int32_t Tag, const SymbolBody *Sym)
+ : Tag(Tag), Sym(Sym), Kind(SymAddr) {}
+ };
+
+ // finalize() fills this vector with the section contents. finalize()
+ // cannot directly create final section contents because when the
+ // function is called, symbol or section addresses are not fixed yet.
+ std::vector<Entry> Entries;
public:
- DynamicSection(SymbolTable<ELFT> &SymTab);
+ explicit DynamicSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
OutputSectionBase<ELFT> *PreInitArraySec = nullptr;
OutputSectionBase<ELFT> *InitArraySec = nullptr;
OutputSectionBase<ELFT> *FiniArraySec = nullptr;
-
-private:
- SymbolTable<ELFT> &SymTab;
- const SymbolBody *InitSym = nullptr;
- const SymbolBody *FiniSym = nullptr;
- uint32_t DtFlags = 0;
- uint32_t DtFlags1 = 0;
};
template <class ELFT>
@@ -429,17 +545,94 @@ private:
uint32_t GprMask = 0;
};
-inline uint64_t align(uint64_t Value, uint64_t Align) {
- return llvm::RoundUpToAlignment(Value, Align);
-}
+template <class ELFT>
+class MipsOptionsOutputSection final : public OutputSectionBase<ELFT> {
+ typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
+ typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+public:
+ MipsOptionsOutputSection();
+ void writeTo(uint8_t *Buf) override;
+ void addSection(InputSectionBase<ELFT> *S) override;
+
+private:
+ uint32_t GprMask = 0;
+};
+
+// --eh-frame-hdr option tells linker to construct a header for all the
+// .eh_frame sections. This header is placed to a section named .eh_frame_hdr
+// and also to a PT_GNU_EH_FRAME segment.
+// At runtime the unwinder then can find all the PT_GNU_EH_FRAME segments by
+// calling dl_iterate_phdr.
+// This section contains a lookup table for quick binary search of FDEs.
+// Detailed info about internals can be found in Ian Lance Taylor's blog:
+// http://www.airs.com/blog/archives/460 (".eh_frame")
+// http://www.airs.com/blog/archives/462 (".eh_frame_hdr")
+template <class ELFT>
+class EhFrameHeader final : public OutputSectionBase<ELFT> {
+ typedef typename ELFT::uint uintX_t;
+
+public:
+ EhFrameHeader();
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+ void addFde(uint32_t Pc, uint32_t FdeVA);
+
+private:
+ struct FdeData {
+ uint32_t Pc;
+ uint32_t FdeVA;
+ };
+
+ std::vector<FdeData> Fdes;
+};
+
+template <class ELFT> class BuildIdSection : public OutputSectionBase<ELFT> {
+public:
+ void writeTo(uint8_t *Buf) override;
+ virtual void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) = 0;
+
+protected:
+ BuildIdSection(size_t HashSize);
+ size_t HashSize;
+ uint8_t *HashBuf = nullptr;
+};
+
+template <class ELFT> class BuildIdFnv1 final : public BuildIdSection<ELFT> {
+public:
+ BuildIdFnv1() : BuildIdSection<ELFT>(8) {}
+ void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
+};
+
+template <class ELFT> class BuildIdMd5 final : public BuildIdSection<ELFT> {
+public:
+ BuildIdMd5() : BuildIdSection<ELFT>(16) {}
+ void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
+};
+
+template <class ELFT> class BuildIdSha1 final : public BuildIdSection<ELFT> {
+public:
+ BuildIdSha1() : BuildIdSection<ELFT>(20) {}
+ void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
+};
+
+template <class ELFT>
+class BuildIdHexstring final : public BuildIdSection<ELFT> {
+public:
+ BuildIdHexstring();
+ void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
+};
// All output sections that are hadnled by the linker specially are
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
template <class ELFT> struct Out {
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Phdr Elf_Phdr;
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Phdr Elf_Phdr;
+ static BuildIdSection<ELFT> *BuildId;
static DynamicSection<ELFT> *Dynamic;
+ static EhFrameHeader<ELFT> *EhFrameHdr;
+ static EhOutputSection<ELFT> *EhFrame;
static GnuHashTableSection<ELFT> *GnuHashTab;
static GotPltSection<ELFT> *GotPlt;
static GotSection<ELFT> *Got;
@@ -457,10 +650,47 @@ template <class ELFT> struct Out {
static StringTableSection<ELFT> *StrTab;
static SymbolTableSection<ELFT> *DynSymTab;
static SymbolTableSection<ELFT> *SymTab;
+ static VersionDefinitionSection<ELFT> *VerDef;
+ static VersionTableSection<ELFT> *VerSym;
+ static VersionNeedSection<ELFT> *VerNeed;
static Elf_Phdr *TlsPhdr;
+ static OutputSectionBase<ELFT> *ElfHeader;
+ static OutputSectionBase<ELFT> *ProgramHeaders;
};
+template <bool Is64Bits> struct SectionKey {
+ typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
+ StringRef Name;
+ uint32_t Type;
+ uintX_t Flags;
+ uintX_t Alignment;
+};
+
+// This class knows how to create an output section for a given
+// input section. Output section type is determined by various
+// factors, including input section's sh_flags, sh_type and
+// linker scripts.
+template <class ELFT> class OutputSectionFactory {
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::uint uintX_t;
+ typedef typename elf::SectionKey<ELFT::Is64Bits> Key;
+
+public:
+ std::pair<OutputSectionBase<ELFT> *, bool> create(InputSectionBase<ELFT> *C,
+ StringRef OutsecName);
+
+ OutputSectionBase<ELFT> *lookup(StringRef Name, uint32_t Type, uintX_t Flags);
+
+private:
+ Key createKey(InputSectionBase<ELFT> *C, StringRef OutsecName);
+
+ llvm::SmallDenseMap<Key, OutputSectionBase<ELFT> *> Map;
+};
+
+template <class ELFT> BuildIdSection<ELFT> *Out<ELFT>::BuildId;
template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic;
+template <class ELFT> EhFrameHeader<ELFT> *Out<ELFT>::EhFrameHdr;
+template <class ELFT> EhOutputSection<ELFT> *Out<ELFT>::EhFrame;
template <class ELFT> GnuHashTableSection<ELFT> *Out<ELFT>::GnuHashTab;
template <class ELFT> GotPltSection<ELFT> *Out<ELFT>::GotPlt;
template <class ELFT> GotSection<ELFT> *Out<ELFT>::Got;
@@ -478,9 +708,25 @@ template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::ShStrTab;
template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
-template <class ELFT> typename Out<ELFT>::Elf_Phdr *Out<ELFT>::TlsPhdr;
-
-} // namespace elf2
+template <class ELFT> VersionDefinitionSection<ELFT> *Out<ELFT>::VerDef;
+template <class ELFT> VersionTableSection<ELFT> *Out<ELFT>::VerSym;
+template <class ELFT> VersionNeedSection<ELFT> *Out<ELFT>::VerNeed;
+template <class ELFT> typename ELFT::Phdr *Out<ELFT>::TlsPhdr;
+template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::ElfHeader;
+template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::ProgramHeaders;
+
+} // namespace elf
} // namespace lld
-#endif // LLD_ELF_OUTPUT_SECTIONS_H
+namespace llvm {
+template <bool Is64Bits> struct DenseMapInfo<lld::elf::SectionKey<Is64Bits>> {
+ typedef typename lld::elf::SectionKey<Is64Bits> Key;
+
+ static Key getEmptyKey();
+ static Key getTombstoneKey();
+ static unsigned getHashValue(const Key &Val);
+ static bool isEqual(const Key &LHS, const Key &RHS);
+};
+}
+
+#endif
diff --git a/ELF/README.md b/ELF/README.md
index 49b8167bbfe0..f1bfc9c15263 100644
--- a/ELF/README.md
+++ b/ELF/README.md
@@ -1,21 +1 @@
-The New ELF Linker
-==================
-This directory contains a port of the new PE/COFF linker for ELF.
-
-Overall Design
---------------
-See COFF/README.md for details on the design. Note that unlike COFF, we do not
-distinguish chunks from input sections; they are merged together.
-
-Capabilities
-------------
-This linker can link LLVM and Clang on Linux/x86-64 or FreeBSD/x86-64
-"Hello world" can be linked on Linux/PPC64 and on Linux/AArch64 or
-FreeBSD/AArch64.
-
-Performance
------------
-Achieving good performance is one of our goals. It's too early to reach a
-conclusion, but we are optimistic about that as it currently seems to be faster
-than GNU gold. It will be interesting to compare when we are close to feature
-parity.
+See docs/NewLLD.rst
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
new file mode 100644
index 000000000000..c09cf6b2b1ef
--- /dev/null
+++ b/ELF/Relocations.cpp
@@ -0,0 +1,704 @@
+//===- Relocations.cpp ----------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains platform-independent functions to process relocations.
+// I'll describe the overview of this file here.
+//
+// Simple relocations are easy to handle for the linker. For example,
+// for R_X86_64_PC64 relocs, the linker just has to fix up locations
+// with the relative offsets to the target symbols. It would just be
+// reading records from relocation sections and applying them to output.
+//
+// But not all relocations are that easy to handle. For example, for
+// R_386_GOTOFF relocs, the linker has to create new GOT entries for
+// symbols if they don't exist, and fix up locations with GOT entry
+// offsets from the beginning of GOT section. So there is more than
+// fixing addresses in relocation processing.
+//
+// ELF defines a large number of complex relocations.
+//
+// The functions in this file analyze relocations and do whatever needs
+// to be done. It includes, but not limited to, the following.
+//
+// - create GOT/PLT entries
+// - create new relocations in .dynsym to let the dynamic linker resolve
+// them at runtime (since ELF supports dynamic linking, not all
+// relocations can be resolved at link-time)
+// - create COPY relocs and reserve space in .bss
+// - replace expensive relocs (in terms of runtime cost) with cheap ones
+// - error out infeasible combinations such as PIC and non-relative relocs
+//
+// Note that the functions in this file don't actually apply relocations
+// because it doesn't know about the output file nor the output file buffer.
+// It instead stores Relocation objects to InputSection's Relocations
+// vector to let it apply later in InputSection::writeTo.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Relocations.h"
+#include "Config.h"
+#include "OutputSections.h"
+#include "SymbolTable.h"
+#include "Target.h"
+#include "Thunks.h"
+
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+
+namespace lld {
+namespace elf {
+
+static bool refersToGotEntry(RelExpr Expr) {
+ return Expr == R_GOT || Expr == R_GOT_OFF || Expr == R_MIPS_GOT_LOCAL_PAGE ||
+ Expr == R_MIPS_GOT_OFF || Expr == R_MIPS_TLSGD ||
+ Expr == R_MIPS_TLSLD || Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC ||
+ Expr == R_GOT_FROM_END || Expr == R_TLSGD || Expr == R_TLSGD_PC ||
+ Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE;
+}
+
+static bool isPreemptible(const SymbolBody &Body, uint32_t Type) {
+ // In case of MIPS GP-relative relocations always resolve to a definition
+ // in a regular input file, ignoring the one-definition rule. So we,
+ // for example, should not attempt to create a dynamic relocation even
+ // if the target symbol is preemptible. There are two two MIPS GP-relative
+ // relocations R_MIPS_GPREL16 and R_MIPS_GPREL32. But only R_MIPS_GPREL16
+ // can be against a preemptible symbol.
+ // To get MIPS relocation type we apply 0xff mask. In case of O32 ABI all
+ // relocation types occupy eight bit. In case of N64 ABI we extract first
+ // relocation from 3-in-1 packet because only the first relocation can
+ // be against a real symbol.
+ if (Config->EMachine == EM_MIPS && (Type & 0xff) == R_MIPS_GPREL16)
+ return false;
+ return Body.isPreemptible();
+}
+
+// This function is similar to the `handleTlsRelocation`. MIPS does not support
+// any relaxations for TLS relocations so by factoring out MIPS handling into
+// the separate function we can simplify the code and does not pollute
+// `handleTlsRelocation` by MIPS `ifs` statements.
+template <class ELFT>
+static unsigned
+handleMipsTlsRelocation(uint32_t Type, SymbolBody &Body,
+ InputSectionBase<ELFT> &C, typename ELFT::uint Offset,
+ typename ELFT::uint Addend, RelExpr Expr) {
+ if (Expr == R_MIPS_TLSLD) {
+ if (Out<ELFT>::Got->addTlsIndex())
+ Out<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, Out<ELFT>::Got,
+ Out<ELFT>::Got->getTlsIndexOff(), false,
+ nullptr, 0});
+ C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body});
+ return 1;
+ }
+ if (Target->isTlsGlobalDynamicRel(Type)) {
+ if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
+ typedef typename ELFT::uint uintX_t;
+ uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body);
+ Out<ELFT>::RelaDyn->addReloc(
+ {Target->TlsModuleIndexRel, Out<ELFT>::Got, Off, false, &Body, 0});
+ Out<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, Out<ELFT>::Got,
+ Off + (uintX_t)sizeof(uintX_t), false,
+ &Body, 0});
+ }
+ C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body});
+ return 1;
+ }
+ return 0;
+}
+
+// Returns the number of relocations processed.
+template <class ELFT>
+static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
+ InputSectionBase<ELFT> &C,
+ typename ELFT::uint Offset,
+ typename ELFT::uint Addend, RelExpr Expr) {
+ if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
+ return 0;
+
+ if (!Body.isTls())
+ return 0;
+
+ typedef typename ELFT::uint uintX_t;
+
+ if (Config->EMachine == EM_MIPS)
+ return handleMipsTlsRelocation<ELFT>(Type, Body, C, Offset, Addend, Expr);
+
+ if ((Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE || Expr == R_HINT) &&
+ Config->Shared) {
+ if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
+ uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body);
+ Out<ELFT>::RelaDyn->addReloc(
+ {Target->TlsDescRel, Out<ELFT>::Got, Off, false, &Body, 0});
+ }
+ if (Expr != R_HINT)
+ C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body});
+ return 1;
+ }
+
+ if (Expr == R_TLSLD_PC || Expr == R_TLSLD) {
+ // Local-Dynamic relocs can be relaxed to Local-Exec.
+ if (!Config->Shared) {
+ C.Relocations.push_back(
+ {R_RELAX_TLS_LD_TO_LE, Type, &C, Offset, Addend, &Body});
+ return 2;
+ }
+ if (Out<ELFT>::Got->addTlsIndex())
+ Out<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, Out<ELFT>::Got,
+ Out<ELFT>::Got->getTlsIndexOff(), false,
+ nullptr, 0});
+ C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body});
+ return 1;
+ }
+
+ // Local-Dynamic relocs can be relaxed to Local-Exec.
+ if (Target->isTlsLocalDynamicRel(Type) && !Config->Shared) {
+ C.Relocations.push_back(
+ {R_RELAX_TLS_LD_TO_LE, Type, &C, Offset, Addend, &Body});
+ return 1;
+ }
+
+ if (Expr == R_TLSDESC_PAGE || Expr == R_TLSDESC || Expr == R_HINT ||
+ Target->isTlsGlobalDynamicRel(Type)) {
+ if (Config->Shared) {
+ if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
+ uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body);
+ Out<ELFT>::RelaDyn->addReloc(
+ {Target->TlsModuleIndexRel, Out<ELFT>::Got, Off, false, &Body, 0});
+
+ // If the symbol is preemptible we need the dynamic linker to write
+ // the offset too.
+ if (isPreemptible(Body, Type))
+ Out<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, Out<ELFT>::Got,
+ Off + (uintX_t)sizeof(uintX_t), false,
+ &Body, 0});
+ }
+ C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body});
+ return 1;
+ }
+
+ // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec
+ // depending on the symbol being locally defined or not.
+ if (isPreemptible(Body, Type)) {
+ C.Relocations.push_back(
+ {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_IE), Type,
+ &C, Offset, Addend, &Body});
+ if (!Body.isInGot()) {
+ Out<ELFT>::Got->addEntry(Body);
+ Out<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, Out<ELFT>::Got,
+ Body.getGotOffset<ELFT>(), false, &Body,
+ 0});
+ }
+ return Target->TlsGdRelaxSkip;
+ }
+ C.Relocations.push_back(
+ {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type, &C,
+ Offset, Addend, &Body});
+ return Target->TlsGdRelaxSkip;
+ }
+
+ // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
+ // defined.
+ if (Target->isTlsInitialExecRel(Type) && !Config->Shared &&
+ !isPreemptible(Body, Type)) {
+ C.Relocations.push_back(
+ {R_RELAX_TLS_IE_TO_LE, Type, &C, Offset, Addend, &Body});
+ return 1;
+ }
+ return 0;
+}
+
+template <endianness E> static int16_t readSignedLo16(const uint8_t *Loc) {
+ return read32<E>(Loc) & 0xffff;
+}
+
+template <class RelTy>
+static uint32_t getMipsPairType(const RelTy *Rel, const SymbolBody &Sym) {
+ switch (Rel->getType(Config->Mips64EL)) {
+ case R_MIPS_HI16:
+ return R_MIPS_LO16;
+ case R_MIPS_GOT16:
+ return Sym.isLocal() ? R_MIPS_LO16 : R_MIPS_NONE;
+ case R_MIPS_PCHI16:
+ return R_MIPS_PCLO16;
+ case R_MICROMIPS_HI16:
+ return R_MICROMIPS_LO16;
+ default:
+ return R_MIPS_NONE;
+ }
+}
+
+template <class ELFT, class RelTy>
+static int32_t findMipsPairedAddend(const uint8_t *Buf, const uint8_t *BufLoc,
+ SymbolBody &Sym, const RelTy *Rel,
+ const RelTy *End) {
+ uint32_t SymIndex = Rel->getSymbol(Config->Mips64EL);
+ uint32_t Type = getMipsPairType(Rel, Sym);
+
+ // Some MIPS relocations use addend calculated from addend of the relocation
+ // itself and addend of paired relocation. ABI requires to compute such
+ // combined addend in case of REL relocation record format only.
+ // See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ if (RelTy::IsRela || Type == R_MIPS_NONE)
+ return 0;
+
+ for (const RelTy *RI = Rel; RI != End; ++RI) {
+ if (RI->getType(Config->Mips64EL) != Type)
+ continue;
+ if (RI->getSymbol(Config->Mips64EL) != SymIndex)
+ continue;
+ const endianness E = ELFT::TargetEndianness;
+ return ((read32<E>(BufLoc) & 0xffff) << 16) +
+ readSignedLo16<E>(Buf + RI->r_offset);
+ }
+ warning("can't find matching " + getRelName(Type) + " relocation for " +
+ getRelName(Rel->getType(Config->Mips64EL)));
+ return 0;
+}
+
+// True if non-preemptable symbol always has the same value regardless of where
+// the DSO is loaded.
+template <class ELFT> static bool isAbsolute(const SymbolBody &Body) {
+ if (Body.isUndefined())
+ return !Body.isLocal() && Body.symbol()->isWeak();
+ if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(&Body))
+ return DR->Section == nullptr; // Absolute symbol.
+ return false;
+}
+
+static bool needsPlt(RelExpr Expr) {
+ return Expr == R_PLT_PC || Expr == R_PPC_PLT_OPD || Expr == R_PLT ||
+ Expr == R_PLT_PAGE_PC || Expr == R_THUNK_PLT_PC;
+}
+
+// True if this expression is of the form Sym - X, where X is a position in the
+// file (PC, or GOT for example).
+static bool isRelExpr(RelExpr Expr) {
+ return Expr == R_PC || Expr == R_GOTREL || Expr == R_PAGE_PC ||
+ Expr == R_RELAX_GOT_PC || Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC;
+}
+
+template <class ELFT>
+static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type,
+ const SymbolBody &Body) {
+ // These expressions always compute a constant
+ if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF ||
+ E == R_MIPS_GOT_LOCAL_PAGE || E == R_MIPS_GOT_OFF || E == R_MIPS_TLSGD ||
+ E == R_GOT_PAGE_PC || E == R_GOT_PC || E == R_PLT_PC || E == R_TLSGD_PC ||
+ E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE ||
+ E == R_HINT || E == R_THUNK_PC || E == R_THUNK_PLT_PC)
+ return true;
+
+ // These never do, except if the entire file is position dependent or if
+ // only the low bits are used.
+ if (E == R_GOT || E == R_PLT || E == R_TLSDESC)
+ return Target->usesOnlyLowPageBits(Type) || !Config->Pic;
+
+ if (isPreemptible(Body, Type))
+ return false;
+
+ if (!Config->Pic)
+ return true;
+
+ bool AbsVal = isAbsolute<ELFT>(Body) || Body.isTls();
+ bool RelE = isRelExpr(E);
+ if (AbsVal && !RelE)
+ return true;
+ if (!AbsVal && RelE)
+ return true;
+
+ // Relative relocation to an absolute value. This is normally unrepresentable,
+ // but if the relocation refers to a weak undefined symbol, we allow it to
+ // resolve to the image base. This is a little strange, but it allows us to
+ // link function calls to such symbols. Normally such a call will be guarded
+ // with a comparison, which will load a zero from the GOT.
+ if (AbsVal && RelE) {
+ if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
+ return true;
+ error("relocation " + getRelName(Type) +
+ " cannot refer to absolute symbol " + Body.getName());
+ return true;
+ }
+
+ return Target->usesOnlyLowPageBits(Type);
+}
+
+static RelExpr toPlt(RelExpr Expr) {
+ if (Expr == R_PPC_OPD)
+ return R_PPC_PLT_OPD;
+ if (Expr == R_PC)
+ return R_PLT_PC;
+ if (Expr == R_PAGE_PC)
+ return R_PLT_PAGE_PC;
+ if (Expr == R_ABS)
+ return R_PLT;
+ return Expr;
+}
+
+static RelExpr fromPlt(RelExpr Expr) {
+ // We decided not to use a plt. Optimize a reference to the plt to a
+ // reference to the symbol itself.
+ if (Expr == R_PLT_PC)
+ return R_PC;
+ if (Expr == R_PPC_PLT_OPD)
+ return R_PPC_OPD;
+ if (Expr == R_PLT)
+ return R_ABS;
+ return Expr;
+}
+
+template <class ELFT> static uint32_t getAlignment(SharedSymbol<ELFT> *SS) {
+ typedef typename ELFT::uint uintX_t;
+
+ uintX_t SecAlign = SS->file()->getSection(SS->Sym)->sh_addralign;
+ uintX_t SymValue = SS->Sym.st_value;
+ int TrailingZeros =
+ std::min(countTrailingZeros(SecAlign), countTrailingZeros(SymValue));
+ return 1 << TrailingZeros;
+}
+
+// Reserve space in .bss for copy relocation.
+template <class ELFT> static void addCopyRelSymbol(SharedSymbol<ELFT> *SS) {
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Sym Elf_Sym;
+
+ // Copy relocation against zero-sized symbol doesn't make sense.
+ uintX_t SymSize = SS->template getSize<ELFT>();
+ if (SymSize == 0)
+ fatal("cannot create a copy relocation for " + SS->getName());
+
+ uintX_t Alignment = getAlignment(SS);
+ uintX_t Off = alignTo(Out<ELFT>::Bss->getSize(), Alignment);
+ Out<ELFT>::Bss->setSize(Off + SymSize);
+ Out<ELFT>::Bss->updateAlignment(Alignment);
+ uintX_t Shndx = SS->Sym.st_shndx;
+ uintX_t Value = SS->Sym.st_value;
+ // Look through the DSO's dynamic symbol table for aliases and create a
+ // dynamic symbol for each one. This causes the copy relocation to correctly
+ // interpose any aliases.
+ for (const Elf_Sym &S : SS->file()->getElfSymbols(true)) {
+ if (S.st_shndx != Shndx || S.st_value != Value)
+ continue;
+ auto *Alias = dyn_cast_or_null<SharedSymbol<ELFT>>(
+ Symtab<ELFT>::X->find(check(S.getName(SS->file()->getStringTable()))));
+ if (!Alias)
+ continue;
+ Alias->OffsetInBss = Off;
+ Alias->NeedsCopyOrPltAddr = true;
+ Alias->symbol()->IsUsedInRegularObj = true;
+ }
+ Out<ELFT>::RelaDyn->addReloc(
+ {Target->CopyRel, Out<ELFT>::Bss, SS->OffsetInBss, false, SS, 0});
+}
+
+template <class ELFT>
+static RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody &Body,
+ bool IsWrite, RelExpr Expr, uint32_t Type,
+ const uint8_t *Data) {
+ bool Preemptible = isPreemptible(Body, Type);
+ if (Body.isGnuIFunc()) {
+ Expr = toPlt(Expr);
+ } else if (!Preemptible) {
+ if (needsPlt(Expr))
+ Expr = fromPlt(Expr);
+ if (Expr == R_GOT_PC)
+ Expr = Target->adjustRelaxExpr(Type, Data, Expr);
+ }
+ Expr = Target->getThunkExpr(Expr, Type, File, Body);
+
+ if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body))
+ return Expr;
+
+ // This relocation would require the dynamic linker to write a value to read
+ // only memory. We can hack around it if we are producing an executable and
+ // the refered symbol can be preemepted to refer to the executable.
+ if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) {
+ error("can't create dynamic relocation " + getRelName(Type) +
+ " against readonly segment");
+ return Expr;
+ }
+ if (Body.getVisibility() != STV_DEFAULT) {
+ error("cannot preempt symbol");
+ return Expr;
+ }
+ if (Body.isObject()) {
+ // Produce a copy relocation.
+ auto *B = cast<SharedSymbol<ELFT>>(&Body);
+ if (!B->needsCopy())
+ addCopyRelSymbol(B);
+ return Expr;
+ }
+ if (Body.isFunc()) {
+ // This handles a non PIC program call to function in a shared library. In
+ // an ideal world, we could just report an error saying the relocation can
+ // overflow at runtime. In the real world with glibc, crt1.o has a
+ // R_X86_64_PC32 pointing to libc.so.
+ //
+ // The general idea on how to handle such cases is to create a PLT entry and
+ // use that as the function value.
+ //
+ // For the static linking part, we just return a plt expr and everything
+ // else will use the the PLT entry as the address.
+ //
+ // The remaining problem is making sure pointer equality still works. We
+ // need the help of the dynamic linker for that. We let it know that we have
+ // a direct reference to a so symbol by creating an undefined symbol with a
+ // non zero st_value. Seeing that, the dynamic linker resolves the symbol to
+ // the value of the symbol we created. This is true even for got entries, so
+ // pointer equality is maintained. To avoid an infinite loop, the only entry
+ // that points to the real function is a dedicated got entry used by the
+ // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
+ // R_386_JMP_SLOT, etc).
+ Body.NeedsCopyOrPltAddr = true;
+ return toPlt(Expr);
+ }
+ error("symbol is missing type");
+
+ return Expr;
+}
+
+template <class ELFT, class RelTy>
+static typename ELFT::uint computeAddend(const elf::ObjectFile<ELFT> &File,
+ const uint8_t *SectionData,
+ const RelTy *End, const RelTy &RI,
+ RelExpr Expr, SymbolBody &Body) {
+ typedef typename ELFT::uint uintX_t;
+
+ uint32_t Type = RI.getType(Config->Mips64EL);
+ uintX_t Addend = getAddend<ELFT>(RI);
+ const uint8_t *BufLoc = SectionData + RI.r_offset;
+ if (!RelTy::IsRela)
+ Addend += Target->getImplicitAddend(BufLoc, Type);
+ if (Config->EMachine == EM_MIPS) {
+ Addend += findMipsPairedAddend<ELFT>(SectionData, BufLoc, Body, &RI, End);
+ if (Type == R_MIPS_LO16 && Expr == R_PC)
+ // R_MIPS_LO16 expression has R_PC type iif the target is _gp_disp
+ // symbol. In that case we should use the following formula for
+ // calculation "AHL + GP - P + 4". Let's add 4 right here.
+ // For details see p. 4-19 at
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ Addend += 4;
+ if (Expr == R_GOTREL) {
+ Addend -= MipsGPOffset;
+ if (Body.isLocal())
+ Addend += File.getMipsGp0();
+ }
+ }
+ if (Config->Pic && Config->EMachine == EM_PPC64 && Type == R_PPC64_TOC)
+ Addend += getPPC64TocBase();
+ return Addend;
+}
+
+// The reason we have to do this early scan is as follows
+// * To mmap the output file, we need to know the size
+// * For that, we need to know how many dynamic relocs we will have.
+// It might be possible to avoid this by outputting the file with write:
+// * Write the allocated output sections, computing addresses.
+// * Apply relocations, recording which ones require a dynamic reloc.
+// * Write the dynamic relocations.
+// * Write the rest of the file.
+// This would have some drawbacks. For example, we would only know if .rela.dyn
+// is needed after applying relocations. If it is, it will go after rw and rx
+// sections. Given that it is ro, we will need an extra PT_LOAD. This
+// complicates things for the dynamic linker and means we would have to reserve
+// space for the extra PT_LOAD even if we end up not using it.
+template <class ELFT, class RelTy>
+static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
+ typedef typename ELFT::uint uintX_t;
+
+ bool IsWrite = C.getSectionHdr()->sh_flags & SHF_WRITE;
+
+ auto AddDyn = [=](const DynamicReloc<ELFT> &Reloc) {
+ Out<ELFT>::RelaDyn->addReloc(Reloc);
+ };
+
+ const elf::ObjectFile<ELFT> &File = *C.getFile();
+ ArrayRef<uint8_t> SectionData = C.getSectionData();
+ const uint8_t *Buf = SectionData.begin();
+ for (auto I = Rels.begin(), E = Rels.end(); I != E; ++I) {
+ const RelTy &RI = *I;
+ SymbolBody &Body = File.getRelocTargetSym(RI);
+ uint32_t Type = RI.getType(Config->Mips64EL);
+
+ RelExpr Expr = Target->getRelExpr(Type, Body);
+ bool Preemptible = isPreemptible(Body, Type);
+ Expr = adjustExpr(File, Body, IsWrite, Expr, Type, Buf + RI.r_offset);
+ if (HasError)
+ continue;
+
+ // Skip a relocation that points to a dead piece
+ // in a mergeable section.
+ if (C.getOffset(RI.r_offset) == (uintX_t)-1)
+ continue;
+
+ // This relocation does not require got entry, but it is relative to got and
+ // needs it to be created. Here we request for that.
+ if (Expr == R_GOTONLY_PC || Expr == R_GOTREL || Expr == R_PPC_TOC)
+ Out<ELFT>::Got->HasGotOffRel = true;
+
+ uintX_t Addend = computeAddend(File, Buf, E, RI, Expr, Body);
+
+ if (unsigned Processed = handleTlsRelocation<ELFT>(
+ Type, Body, C, RI.r_offset, Addend, Expr)) {
+ I += (Processed - 1);
+ continue;
+ }
+
+ // Ignore "hint" relocation because it is for optional code optimization.
+ if (Expr == R_HINT)
+ continue;
+
+ if (needsPlt(Expr) || Expr == R_THUNK_ABS || Expr == R_THUNK_PC ||
+ Expr == R_THUNK_PLT_PC || refersToGotEntry(Expr) ||
+ !isPreemptible(Body, Type)) {
+ // If the relocation points to something in the file, we can process it.
+ bool Constant = isStaticLinkTimeConstant<ELFT>(Expr, Type, Body);
+
+ // If the output being produced is position independent, the final value
+ // is still not known. In that case we still need some help from the
+ // dynamic linker. We can however do better than just copying the incoming
+ // relocation. We can process some of it and and just ask the dynamic
+ // linker to add the load address.
+ if (!Constant)
+ AddDyn({Target->RelativeRel, &C, RI.r_offset, true, &Body, Addend});
+
+ // If the produced value is a constant, we just remember to write it
+ // when outputting this section. We also have to do it if the format
+ // uses Elf_Rel, since in that case the written value is the addend.
+ if (Constant || !RelTy::IsRela)
+ C.Relocations.push_back({Expr, Type, &C, RI.r_offset, Addend, &Body});
+ } else {
+ // We don't know anything about the finaly symbol. Just ask the dynamic
+ // linker to handle the relocation for us.
+ AddDyn({Target->getDynRel(Type), &C, RI.r_offset, false, &Body, Addend});
+ // MIPS ABI turns using of GOT and dynamic relocations inside out.
+ // While regular ABI uses dynamic relocations to fill up GOT entries
+ // MIPS ABI requires dynamic linker to fills up GOT entries using
+ // specially sorted dynamic symbol table. This affects even dynamic
+ // relocations against symbols which do not require GOT entries
+ // creation explicitly, i.e. do not have any GOT-relocations. So if
+ // a preemptible symbol has a dynamic relocation we anyway have
+ // to create a GOT entry for it.
+ // If a non-preemptible symbol has a dynamic relocation against it,
+ // dynamic linker takes it st_value, adds offset and writes down
+ // result of the dynamic relocation. In case of preemptible symbol
+ // dynamic linker performs symbol resolution, writes the symbol value
+ // to the GOT entry and reads the GOT entry when it needs to perform
+ // a dynamic relocation.
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19
+ if (Config->EMachine == EM_MIPS)
+ Out<ELFT>::Got->addMipsEntry(Body, Addend, Expr);
+ continue;
+ }
+
+ // Some targets might require creation of thunks for relocations.
+ // Now we support only MIPS which requires LA25 thunk to call PIC
+ // code from non-PIC one, and ARM which requires interworking.
+ if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC) {
+ auto *Sec = cast<InputSection<ELFT>>(&C);
+ addThunk<ELFT>(Type, Body, *Sec);
+ }
+
+ // At this point we are done with the relocated position. Some relocations
+ // also require us to create a got or plt entry.
+
+ // If a relocation needs PLT, we create a PLT and a GOT slot for the symbol.
+ if (needsPlt(Expr)) {
+ if (Body.isInPlt())
+ continue;
+ Out<ELFT>::Plt->addEntry(Body);
+
+ uint32_t Rel;
+ if (Body.isGnuIFunc() && !Preemptible)
+ Rel = Target->IRelativeRel;
+ else
+ Rel = Target->PltRel;
+
+ Out<ELFT>::GotPlt->addEntry(Body);
+ Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
+ Body.getGotPltOffset<ELFT>(), !Preemptible,
+ &Body, 0});
+ continue;
+ }
+
+ if (refersToGotEntry(Expr)) {
+ if (Config->EMachine == EM_MIPS) {
+ // MIPS ABI has special rules to process GOT entries
+ // and doesn't require relocation entries for them.
+ // See "Global Offset Table" in Chapter 5 in the following document
+ // for detailed description:
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ Out<ELFT>::Got->addMipsEntry(Body, Addend, Expr);
+ if (Body.isTls())
+ AddDyn({Target->TlsGotRel, Out<ELFT>::Got, Body.getGotOffset<ELFT>(),
+ !Preemptible, &Body, 0});
+ continue;
+ }
+
+ if (Body.isInGot())
+ continue;
+
+ Out<ELFT>::Got->addEntry(Body);
+ if (Preemptible || (Config->Pic && !isAbsolute<ELFT>(Body))) {
+ uint32_t DynType;
+ if (Body.isTls())
+ DynType = Target->TlsGotRel;
+ else if (Preemptible)
+ DynType = Target->GotRel;
+ else
+ DynType = Target->RelativeRel;
+ AddDyn({DynType, Out<ELFT>::Got, Body.getGotOffset<ELFT>(),
+ !Preemptible, &Body, 0});
+ }
+ continue;
+ }
+ }
+}
+
+template <class ELFT> void scanRelocations(InputSection<ELFT> &C) {
+ typedef typename ELFT::Shdr Elf_Shdr;
+
+ // Scan all relocations. Each relocation goes through a series
+ // of tests to determine if it needs special treatment, such as
+ // creating GOT, PLT, copy relocations, etc.
+ // Note that relocations for non-alloc sections are directly
+ // processed by InputSection::relocateNonAlloc.
+ if (C.getSectionHdr()->sh_flags & SHF_ALLOC)
+ for (const Elf_Shdr *RelSec : C.RelocSections)
+ scanRelocations(C, *RelSec);
+}
+
+template <class ELFT>
+void scanRelocations(InputSectionBase<ELFT> &S,
+ const typename ELFT::Shdr &RelSec) {
+ ELFFile<ELFT> &EObj = S.getFile()->getObj();
+ if (RelSec.sh_type == SHT_RELA)
+ scanRelocs(S, EObj.relas(&RelSec));
+ else
+ scanRelocs(S, EObj.rels(&RelSec));
+}
+
+template void scanRelocations<ELF32LE>(InputSection<ELF32LE> &);
+template void scanRelocations<ELF32BE>(InputSection<ELF32BE> &);
+template void scanRelocations<ELF64LE>(InputSection<ELF64LE> &);
+template void scanRelocations<ELF64BE>(InputSection<ELF64BE> &);
+
+template void scanRelocations<ELF32LE>(InputSectionBase<ELF32LE> &,
+ const ELF32LE::Shdr &);
+template void scanRelocations<ELF32BE>(InputSectionBase<ELF32BE> &,
+ const ELF32BE::Shdr &);
+template void scanRelocations<ELF64LE>(InputSectionBase<ELF64LE> &,
+ const ELF64LE::Shdr &);
+template void scanRelocations<ELF64BE>(InputSectionBase<ELF64BE> &,
+ const ELF64BE::Shdr &);
+}
+}
diff --git a/ELF/Relocations.h b/ELF/Relocations.h
new file mode 100644
index 000000000000..4c1c74efb0da
--- /dev/null
+++ b/ELF/Relocations.h
@@ -0,0 +1,93 @@
+//===- Relocations.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_RELOCATIONS_H
+#define LLD_ELF_RELOCATIONS_H
+
+#include "lld/Core/LLVM.h"
+
+namespace lld {
+namespace elf {
+class SymbolBody;
+template <class ELFT> class InputSection;
+template <class ELFT> class InputSectionBase;
+
+enum RelExpr {
+ R_ABS,
+ R_GOT,
+ R_GOTONLY_PC,
+ R_GOTREL,
+ R_GOT_FROM_END,
+ R_GOT_OFF,
+ R_GOT_PAGE_PC,
+ R_GOT_PC,
+ R_HINT,
+ R_MIPS_GOT_LOCAL_PAGE,
+ R_MIPS_GOT_OFF,
+ R_MIPS_TLSGD,
+ R_MIPS_TLSLD,
+ R_NEG_TLS,
+ R_PAGE_PC,
+ R_PC,
+ R_PLT,
+ R_PLT_PC,
+ R_PLT_PAGE_PC,
+ R_PPC_OPD,
+ R_PPC_PLT_OPD,
+ R_PPC_TOC,
+ R_RELAX_GOT_PC,
+ R_RELAX_GOT_PC_NOPIC,
+ R_RELAX_TLS_GD_TO_IE,
+ R_RELAX_TLS_GD_TO_IE_END,
+ R_RELAX_TLS_GD_TO_IE_ABS,
+ R_RELAX_TLS_GD_TO_IE_PAGE_PC,
+ R_RELAX_TLS_GD_TO_LE,
+ R_RELAX_TLS_GD_TO_LE_NEG,
+ R_RELAX_TLS_IE_TO_LE,
+ R_RELAX_TLS_LD_TO_LE,
+ R_SIZE,
+ R_THUNK_ABS,
+ R_THUNK_PC,
+ R_THUNK_PLT_PC,
+ R_TLS,
+ R_TLSDESC,
+ R_TLSDESC_PAGE,
+ R_TLSGD,
+ R_TLSGD_PC,
+ R_TLSLD,
+ R_TLSLD_PC
+};
+
+template <class ELFT> struct Relocation {
+ RelExpr Expr;
+ uint32_t Type;
+ InputSectionBase<ELFT> *InputSec;
+ uint64_t Offset;
+ uint64_t Addend;
+ SymbolBody *Sym;
+};
+
+template <class ELFT> void scanRelocations(InputSection<ELFT> &);
+
+template <class ELFT>
+void scanRelocations(InputSectionBase<ELFT> &, const typename ELFT::Shdr &);
+
+template <class ELFT>
+static inline typename ELFT::uint getAddend(const typename ELFT::Rel &Rel) {
+ return 0;
+}
+
+template <class ELFT>
+static inline typename ELFT::uint getAddend(const typename ELFT::Rela &Rel) {
+ return Rel.r_addend;
+}
+}
+}
+
+#endif
diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp
new file mode 100644
index 000000000000..559ec1be0e39
--- /dev/null
+++ b/ELF/ScriptParser.cpp
@@ -0,0 +1,163 @@
+//===- ScriptParser.cpp ---------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the base parser class for linker script and dynamic
+// list.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ScriptParser.h"
+#include "Error.h"
+#include "llvm/ADT/Twine.h"
+
+using namespace llvm;
+using namespace lld;
+using namespace lld::elf;
+
+// Returns the line that the character S[Pos] is in.
+static StringRef getLine(StringRef S, size_t Pos) {
+ size_t Begin = S.rfind('\n', Pos);
+ size_t End = S.find('\n', Pos);
+ Begin = (Begin == StringRef::npos) ? 0 : Begin + 1;
+ if (End == StringRef::npos)
+ End = S.size();
+ // rtrim for DOS-style newlines.
+ return S.substr(Begin, End - Begin).rtrim();
+}
+
+void ScriptParserBase::printErrorPos() {
+ StringRef Tok = Tokens[Pos == 0 ? 0 : Pos - 1];
+ StringRef Line = getLine(Input, Tok.data() - Input.data());
+ size_t Col = Tok.data() - Line.data();
+ error(Line);
+ error(std::string(Col, ' ') + "^");
+}
+
+// We don't want to record cascading errors. Keep only the first one.
+void ScriptParserBase::setError(const Twine &Msg) {
+ if (Error)
+ return;
+ if (Input.empty() || Tokens.empty()) {
+ error(Msg);
+ } else {
+ error("line " + Twine(getPos()) + ": " + Msg);
+ printErrorPos();
+ }
+ Error = true;
+}
+
+// Split S into linker script tokens.
+std::vector<StringRef> ScriptParserBase::tokenize(StringRef S) {
+ std::vector<StringRef> Ret;
+ for (;;) {
+ S = skipSpace(S);
+ if (S.empty())
+ return Ret;
+
+ // Quoted token
+ if (S.startswith("\"")) {
+ size_t E = S.find("\"", 1);
+ if (E == StringRef::npos) {
+ error("unclosed quote");
+ return {};
+ }
+ Ret.push_back(S.substr(1, E - 1));
+ S = S.substr(E + 1);
+ continue;
+ }
+
+ // Unquoted token
+ size_t Pos = S.find_first_not_of(
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789_.$/\\~=+[]*?-:!<>");
+ // A character that cannot start a word (which is usually a
+ // punctuation) forms a single character token.
+ if (Pos == 0)
+ Pos = 1;
+ Ret.push_back(S.substr(0, Pos));
+ S = S.substr(Pos);
+ }
+}
+
+// Skip leading whitespace characters or comments.
+StringRef ScriptParserBase::skipSpace(StringRef S) {
+ for (;;) {
+ if (S.startswith("/*")) {
+ size_t E = S.find("*/", 2);
+ if (E == StringRef::npos) {
+ error("unclosed comment in a linker script");
+ return "";
+ }
+ S = S.substr(E + 2);
+ continue;
+ }
+ if (S.startswith("#")) {
+ size_t E = S.find('\n', 1);
+ if (E == StringRef::npos)
+ E = S.size() - 1;
+ S = S.substr(E + 1);
+ continue;
+ }
+ size_t Size = S.size();
+ S = S.ltrim();
+ if (S.size() == Size)
+ return S;
+ }
+}
+
+// An erroneous token is handled as if it were the last token before EOF.
+bool ScriptParserBase::atEOF() { return Error || Tokens.size() == Pos; }
+
+StringRef ScriptParserBase::next() {
+ if (Error)
+ return "";
+ if (atEOF()) {
+ setError("unexpected EOF");
+ return "";
+ }
+ return Tokens[Pos++];
+}
+
+StringRef ScriptParserBase::peek() {
+ StringRef Tok = next();
+ if (Error)
+ return "";
+ --Pos;
+ return Tok;
+}
+
+bool ScriptParserBase::skip(StringRef Tok) {
+ if (Error)
+ return false;
+ if (atEOF()) {
+ setError("unexpected EOF");
+ return false;
+ }
+ if (Tokens[Pos] != Tok)
+ return false;
+ ++Pos;
+ return true;
+}
+
+void ScriptParserBase::expect(StringRef Expect) {
+ if (Error)
+ return;
+ StringRef Tok = next();
+ if (Tok != Expect)
+ setError(Expect + " expected, but got " + Tok);
+}
+
+// Returns the current line number.
+size_t ScriptParserBase::getPos() {
+ if (Pos == 0)
+ return 1;
+ const char *Begin = Input.data();
+ const char *Tok = Tokens[Pos - 1].data();
+ return StringRef(Begin, Tok - Begin).count('\n') + 1;
+}
diff --git a/ELF/ScriptParser.h b/ELF/ScriptParser.h
new file mode 100644
index 000000000000..20735f78da81
--- /dev/null
+++ b/ELF/ScriptParser.h
@@ -0,0 +1,49 @@
+//===- ScriptParser.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_SCRIPT_PARSER_H
+#define LLD_ELF_SCRIPT_PARSER_H
+
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include <utility>
+#include <vector>
+
+namespace lld {
+namespace elf {
+
+class ScriptParserBase {
+public:
+ explicit ScriptParserBase(StringRef S) : Input(S), Tokens(tokenize(S)) {}
+ explicit ScriptParserBase(std::vector<StringRef> Tokens)
+ : Input(""), Tokens(std::move(Tokens)) {}
+
+protected:
+ void setError(const Twine &Msg);
+ static std::vector<StringRef> tokenize(StringRef S);
+ static StringRef skipSpace(StringRef S);
+ bool atEOF();
+ StringRef next();
+ StringRef peek();
+ bool skip(StringRef Tok);
+ void expect(StringRef Expect);
+
+ size_t getPos();
+ void printErrorPos();
+
+ StringRef Input;
+ std::vector<StringRef> Tokens;
+ size_t Pos = 0;
+ bool Error = false;
+};
+
+} // namespace elf
+} // namespace lld
+
+#endif
diff --git a/ELF/Strings.cpp b/ELF/Strings.cpp
new file mode 100644
index 000000000000..0c21e8819d6c
--- /dev/null
+++ b/ELF/Strings.cpp
@@ -0,0 +1,98 @@
+//===- Strings.cpp -------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Strings.h"
+#include "Error.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/config.h"
+#include <algorithm>
+
+#ifdef HAVE_CXXABI_H
+#include <cxxabi.h>
+#endif
+
+using namespace llvm;
+using namespace lld;
+using namespace lld::elf;
+
+// Returns true if S matches T. S can contain glob meta-characters.
+// The asterisk ('*') matches zero or more characters, and the question
+// mark ('?') matches one character.
+bool elf::globMatch(StringRef S, StringRef T) {
+ for (;;) {
+ if (S.empty())
+ return T.empty();
+ if (S[0] == '*') {
+ S = S.substr(1);
+ if (S.empty())
+ // Fast path. If a pattern is '*', it matches anything.
+ return true;
+ for (size_t I = 0, E = T.size(); I < E; ++I)
+ if (globMatch(S, T.substr(I)))
+ return true;
+ return false;
+ }
+ if (T.empty() || (S[0] != T[0] && S[0] != '?'))
+ return false;
+ S = S.substr(1);
+ T = T.substr(1);
+ }
+}
+
+// Converts a hex string (e.g. "deadbeef") to a vector.
+std::vector<uint8_t> elf::parseHex(StringRef S) {
+ std::vector<uint8_t> Hex;
+ while (!S.empty()) {
+ StringRef B = S.substr(0, 2);
+ S = S.substr(2);
+ uint8_t H;
+ if (B.getAsInteger(16, H)) {
+ error("not a hexadecimal value: " + B);
+ return {};
+ }
+ Hex.push_back(H);
+ }
+ return Hex;
+}
+
+static bool isAlpha(char C) {
+ return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
+}
+
+static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
+
+// Returns true if S is valid as a C language identifier.
+bool elf::isValidCIdentifier(StringRef S) {
+ return !S.empty() && isAlpha(S[0]) &&
+ std::all_of(S.begin() + 1, S.end(), isAlnum);
+}
+
+// Returns the demangled C++ symbol name for Name.
+std::string elf::demangle(StringRef Name) {
+#if !defined(HAVE_CXXABI_H)
+ return Name;
+#else
+ // __cxa_demangle can be used to demangle strings other than symbol
+ // names which do not necessarily start with "_Z". Name can be
+ // either a C or C++ symbol. Don't call __cxa_demangle if the name
+ // does not look like a C++ symbol name to avoid getting unexpected
+ // result for a C symbol that happens to match a mangled type name.
+ if (!Name.startswith("_Z"))
+ return Name;
+
+ char *Buf =
+ abi::__cxa_demangle(Name.str().c_str(), nullptr, nullptr, nullptr);
+ if (!Buf)
+ return Name;
+ std::string S(Buf);
+ free(Buf);
+ return S;
+#endif
+}
diff --git a/ELF/Strings.h b/ELF/Strings.h
new file mode 100644
index 000000000000..4948e9dbd56b
--- /dev/null
+++ b/ELF/Strings.h
@@ -0,0 +1,29 @@
+//===- Strings.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COFF_STRINGS_H
+#define LLD_COFF_STRINGS_H
+
+#include "lld/Core/LLVM.h"
+#include <vector>
+
+namespace lld {
+namespace elf {
+bool globMatch(StringRef S, StringRef T);
+std::vector<uint8_t> parseHex(StringRef S);
+bool isValidCIdentifier(StringRef S);
+
+// Returns a demangled C++ symbol name. If Name is not a mangled
+// name or the system does not provide __cxa_demangle function,
+// it returns an unmodified string.
+std::string demangle(StringRef Name);
+}
+}
+
+#endif
diff --git a/ELF/SymbolListFile.cpp b/ELF/SymbolListFile.cpp
new file mode 100644
index 000000000000..9e088025c1b7
--- /dev/null
+++ b/ELF/SymbolListFile.cpp
@@ -0,0 +1,168 @@
+//===- SymbolListFile.cpp -------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the parser/evaluator of the linker script.
+// It does not construct an AST but consume linker script directives directly.
+// Results are written to Driver or Config object.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolListFile.h"
+#include "Config.h"
+#include "ScriptParser.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace llvm;
+using namespace llvm::ELF;
+
+using namespace lld;
+using namespace lld::elf;
+
+// Parse the --dynamic-list argument. A dynamic list is in the form
+//
+// { symbol1; symbol2; [...]; symbolN };
+//
+// Multiple groups can be defined in the same file, and they are merged
+// into a single group.
+
+class DynamicListParser final : public ScriptParserBase {
+public:
+ DynamicListParser(StringRef S) : ScriptParserBase(S) {}
+ void run();
+};
+
+void DynamicListParser::run() {
+ while (!atEOF()) {
+ expect("{");
+ while (!Error) {
+ Config->DynamicList.push_back(next());
+ expect(";");
+ if (skip("}"))
+ break;
+ }
+ expect(";");
+ }
+}
+
+void elf::parseDynamicList(MemoryBufferRef MB) {
+ DynamicListParser(MB.getBuffer()).run();
+}
+
+// Parse the --version-script argument. We currently only accept the following
+// version script syntax:
+//
+// { [ global: symbol1; symbol2; [...]; symbolN; ] local: *; };
+//
+// No wildcards are supported, other than for the local entry. Symbol versioning
+// is also not supported.
+
+class VersionScriptParser final : public ScriptParserBase {
+public:
+ VersionScriptParser(StringRef S) : ScriptParserBase(S) {}
+
+ void run();
+
+private:
+ void parseExtern(std::vector<SymbolVersion> *Globals);
+ void parseVersion(StringRef VerStr);
+ void parseGlobal(StringRef VerStr);
+ void parseLocal();
+};
+
+size_t elf::defineSymbolVersion(StringRef VerStr) {
+ // Identifiers start at 2 because 0 and 1 are reserved
+ // for VER_NDX_LOCAL and VER_NDX_GLOBAL constants.
+ size_t VersionId = Config->VersionDefinitions.size() + 2;
+ Config->VersionDefinitions.push_back({VerStr, VersionId});
+ return VersionId;
+}
+
+void VersionScriptParser::parseVersion(StringRef VerStr) {
+ defineSymbolVersion(VerStr);
+
+ if (skip("global:") || peek() != "local:")
+ parseGlobal(VerStr);
+ if (skip("local:"))
+ parseLocal();
+ expect("}");
+
+ // Each version may have a parent version. For example, "Ver2" defined as
+ // "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" as a parent. This
+ // version hierarchy is, probably against your instinct, purely for human; the
+ // runtime doesn't care about them at all. In LLD, we simply skip the token.
+ if (!VerStr.empty() && peek() != ";")
+ next();
+ expect(";");
+}
+
+void VersionScriptParser::parseLocal() {
+ Config->DefaultSymbolVersion = VER_NDX_LOCAL;
+ expect("*");
+ expect(";");
+}
+
+void VersionScriptParser::parseExtern(std::vector<SymbolVersion> *Globals) {
+ expect("C++");
+ expect("{");
+
+ for (;;) {
+ if (peek() == "}" || Error)
+ break;
+ Globals->push_back({next(), true});
+ expect(";");
+ }
+
+ expect("}");
+ expect(";");
+}
+
+void VersionScriptParser::parseGlobal(StringRef VerStr) {
+ std::vector<SymbolVersion> *Globals;
+ if (VerStr.empty())
+ Globals = &Config->VersionScriptGlobals;
+ else
+ Globals = &Config->VersionDefinitions.back().Globals;
+
+ for (;;) {
+ if (skip("extern"))
+ parseExtern(Globals);
+
+ StringRef Cur = peek();
+ if (Cur == "}" || Cur == "local:" || Error)
+ return;
+ next();
+ Globals->push_back({Cur, false});
+ expect(";");
+ }
+}
+
+void VersionScriptParser::run() {
+ StringRef Msg = "anonymous version definition is used in "
+ "combination with other version definitions";
+ if (skip("{")) {
+ parseVersion("");
+ if (!atEOF())
+ setError(Msg);
+ return;
+ }
+
+ while (!atEOF() && !Error) {
+ StringRef VerStr = next();
+ if (VerStr == "{") {
+ setError(Msg);
+ return;
+ }
+ expect("{");
+ parseVersion(VerStr);
+ }
+}
+
+void elf::parseVersionScript(MemoryBufferRef MB) {
+ VersionScriptParser(MB.getBuffer()).run();
+}
diff --git a/ELF/SymbolListFile.h b/ELF/SymbolListFile.h
new file mode 100644
index 000000000000..cf3c4c639ea4
--- /dev/null
+++ b/ELF/SymbolListFile.h
@@ -0,0 +1,27 @@
+//===- SymbolListFile.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_SYMBOL_LIST_FILE_H
+#define LLD_ELF_SYMBOL_LIST_FILE_H
+
+#include "lld/Core/LLVM.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace lld {
+namespace elf {
+
+size_t defineSymbolVersion(StringRef Version);
+
+void parseDynamicList(MemoryBufferRef MB);
+void parseVersionScript(MemoryBufferRef MB);
+
+} // namespace elf
+} // namespace lld
+
+#endif
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 65f5dff9d7a3..78c1298df427 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -17,7 +17,11 @@
#include "SymbolTable.h"
#include "Config.h"
#include "Error.h"
+#include "LinkerScript.h"
+#include "Strings.h"
+#include "SymbolListFile.h"
#include "Symbols.h"
+#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/StringSaver.h"
using namespace llvm;
@@ -25,40 +29,48 @@ using namespace llvm::object;
using namespace llvm::ELF;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
// All input object files must be for the same architecture
// (e.g. it does not make sense to link x86 object files with
// MIPS object files.) This function checks for that error.
-template <class ELFT>
-static void checkCompatibility(InputFile *FileP) {
- auto *F = dyn_cast<ELFFileBase<ELFT>>(FileP);
- if (!F)
- return;
- if (F->getELFKind() == Config->EKind && F->getEMachine() == Config->EMachine)
- return;
+template <class ELFT> static bool isCompatible(InputFile *F) {
+ if (!isa<ELFFileBase<ELFT>>(F) && !isa<BitcodeFile>(F))
+ return true;
+ if (F->EKind == Config->EKind && F->EMachine == Config->EMachine)
+ return true;
StringRef A = F->getName();
StringRef B = Config->Emulation;
if (B.empty())
B = Config->FirstElf->getName();
error(A + " is incompatible with " + B);
+ return false;
}
// Add symbols in File to the symbol table.
template <class ELFT>
void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
InputFile *FileP = File.get();
- checkCompatibility<ELFT>(FileP);
+ if (!isCompatible<ELFT>(FileP))
+ return;
// .a file
if (auto *F = dyn_cast<ArchiveFile>(FileP)) {
ArchiveFiles.emplace_back(cast<ArchiveFile>(File.release()));
- F->parse();
- for (Lazy &Sym : F->getLazySymbols())
- addLazy(&Sym);
+ F->parse<ELFT>();
return;
}
+ // Lazy object file
+ if (auto *F = dyn_cast<LazyObjectFile>(FileP)) {
+ LazyObjectFiles.emplace_back(cast<LazyObjectFile>(File.release()));
+ F->parse<ELFT>();
+ return;
+ }
+
+ if (Config->Trace)
+ outs() << getFilename(FileP) << "\n";
+
// .so file
if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
// DSOs are uniquified not by filename but by soname.
@@ -68,189 +80,443 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
F->parseRest();
- for (SharedSymbol<ELFT> &B : F->getSharedSymbols())
- resolve(&B);
return;
}
- // .o file
+ // LLVM bitcode file
+ if (auto *F = dyn_cast<BitcodeFile>(FileP)) {
+ BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release()));
+ F->parse<ELFT>(ComdatGroups);
+ return;
+ }
+
+ // Regular object file
auto *F = cast<ObjectFile<ELFT>>(FileP);
ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
F->parse(ComdatGroups);
- for (SymbolBody *B : F->getSymbols())
- resolve(B);
}
-// Add an undefined symbol.
-template <class ELFT>
-SymbolBody *SymbolTable<ELFT>::addUndefined(StringRef Name) {
- auto *Sym = new (Alloc) Undefined(Name, false, STV_DEFAULT, false);
- resolve(Sym);
- return Sym;
-}
+// This function is where all the optimizations of link-time
+// optimization happens. When LTO is in use, some input files are
+// not in native object file format but in the LLVM bitcode format.
+// This function compiles bitcode files into a few big native files
+// using LLVM functions and replaces bitcode symbols with the results.
+// Because all bitcode files that consist of a program are passed
+// to the compiler at once, it can do whole-program optimization.
+template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() {
+ if (BitcodeFiles.empty())
+ return;
-// Add an undefined symbol. Unlike addUndefined, that symbol
-// doesn't have to be resolved, thus "opt" (optional).
-template <class ELFT>
-SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) {
- auto *Sym = new (Alloc) Undefined(Name, false, STV_HIDDEN, true);
- resolve(Sym);
- return Sym;
-}
+ // Compile bitcode files.
+ Lto.reset(new BitcodeCompiler);
+ for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles)
+ Lto->add(*F);
+ std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile();
-template <class ELFT>
-SymbolBody *SymbolTable<ELFT>::addAbsolute(StringRef Name, Elf_Sym &ESym) {
- // Pass nullptr because absolute symbols have no corresponding input sections.
- auto *Sym = new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr);
- resolve(Sym);
- return Sym;
+ // Replace bitcode symbols.
+ for (auto &IF : IFs) {
+ ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release());
+
+ DenseSet<StringRef> DummyGroups;
+ Obj->parse(DummyGroups);
+ ObjectFiles.emplace_back(Obj);
+ }
}
template <class ELFT>
-SymbolBody *SymbolTable<ELFT>::addSynthetic(StringRef Name,
- OutputSectionBase<ELFT> &Section,
- uintX_t Value) {
- auto *Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, Value, Section);
- resolve(Sym);
- return Sym;
+DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name,
+ uint8_t Visibility) {
+ return cast<DefinedRegular<ELFT>>(
+ addRegular(Name, STB_GLOBAL, Visibility)->body());
}
// Add Name as an "ignored" symbol. An ignored symbol is a regular
-// linker-synthesized defined symbol, but it is not recorded to the output
-// file's symbol table. Such symbols are useful for some linker-defined symbols.
+// linker-synthesized defined symbol, but is only defined if needed.
template <class ELFT>
-SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) {
- return addAbsolute(Name, ElfSym<ELFT>::IgnoredWeak);
+DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,
+ uint8_t Visibility) {
+ if (!find(Name))
+ return nullptr;
+ return addAbsolute(Name, Visibility);
}
-// The 'strong' variant of the addIgnored. Adds symbol which has a global
-// binding and cannot be substituted.
-template <class ELFT>
-SymbolBody *SymbolTable<ELFT>::addIgnoredStrong(StringRef Name) {
- return addAbsolute(Name, ElfSym<ELFT>::Ignored);
+// Set a flag for --trace-symbol so that we can print out a log message
+// if a new symbol with the same name is inserted into the symbol table.
+template <class ELFT> void SymbolTable<ELFT>::trace(StringRef Name) {
+ Symtab.insert({Name, {-1, true}});
}
// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
// Used to implement --wrap.
template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
- if (Symtab.count(Name) == 0)
+ SymbolBody *B = find(Name);
+ if (!B)
return;
StringSaver Saver(Alloc);
- Symbol *Sym = addUndefined(Name)->getSymbol();
- Symbol *Real = addUndefined(Saver.save("__real_" + Name))->getSymbol();
- Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name))->getSymbol();
- Real->Body = Sym->Body;
- Sym->Body = Wrap->Body;
+ Symbol *Sym = B->symbol();
+ Symbol *Real = addUndefined(Saver.save("__real_" + Name));
+ Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name));
+ // We rename symbols by replacing the old symbol's SymbolBody with the new
+ // symbol's SymbolBody. This causes all SymbolBody pointers referring to the
+ // old symbol to instead refer to the new symbol.
+ memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body));
+ memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body));
+}
+
+static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
+ if (VA == STV_DEFAULT)
+ return VB;
+ if (VB == STV_DEFAULT)
+ return VA;
+ return std::min(VA, VB);
}
-// Returns a file from which symbol B was created.
-// If B does not belong to any file, returns a nullptr.
+// Find an existing symbol or create and insert a new one.
template <class ELFT>
-ELFFileBase<ELFT> *SymbolTable<ELFT>::findFile(SymbolBody *B) {
- for (const std::unique_ptr<ObjectFile<ELFT>> &F : ObjectFiles) {
- ArrayRef<SymbolBody *> Syms = F->getSymbols();
- if (std::find(Syms.begin(), Syms.end(), B) != Syms.end())
- return F.get();
+std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
+ auto P = Symtab.insert({Name, {(int)SymVector.size(), false}});
+ SymIndex &V = P.first->second;
+ bool IsNew = P.second;
+
+ if (V.Idx == -1) {
+ IsNew = true;
+ V = {(int)SymVector.size(), true};
+ }
+
+ Symbol *Sym;
+ if (IsNew) {
+ Sym = new (Alloc) Symbol;
+ Sym->Binding = STB_WEAK;
+ Sym->Visibility = STV_DEFAULT;
+ Sym->IsUsedInRegularObj = false;
+ Sym->ExportDynamic = false;
+ Sym->VersionId = Config->DefaultSymbolVersion;
+ Sym->Traced = V.Traced;
+ SymVector.push_back(Sym);
+ } else {
+ Sym = SymVector[V.Idx];
}
- return nullptr;
+ return {Sym, IsNew};
+}
+
+// Find an existing symbol or create and insert a new one, then apply the given
+// attributes.
+template <class ELFT>
+std::pair<Symbol *, bool>
+SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility,
+ bool CanOmitFromDynSym, bool IsUsedInRegularObj,
+ InputFile *File) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) = insert(Name);
+
+ // Merge in the new symbol's visibility.
+ S->Visibility = getMinVisibility(S->Visibility, Visibility);
+ if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic))
+ S->ExportDynamic = true;
+ if (IsUsedInRegularObj)
+ S->IsUsedInRegularObj = true;
+ if (!WasInserted && S->body()->Type != SymbolBody::UnknownType &&
+ ((Type == STT_TLS) != S->body()->isTls()))
+ error("TLS attribute mismatch for symbol: " +
+ conflictMsg(S->body(), File));
+
+ return {S, WasInserted};
}
// Construct a string in the form of "Sym in File1 and File2".
// Used to construct an error message.
-template <class ELFT>
-std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) {
- ELFFileBase<ELFT> *OldFile = findFile(Old);
- ELFFileBase<ELFT> *NewFile = findFile(New);
+template <typename ELFT>
+std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing,
+ InputFile *NewFile) {
+ std::string Sym = Existing->getName();
+ if (Config->Demangle)
+ Sym = demangle(Sym);
+ return Sym + " in " + getFilename(Existing->File) + " and " +
+ getFilename(NewFile);
+}
- StringRef Sym = Old->getName();
- StringRef F1 = OldFile ? OldFile->getName() : "(internal)";
- StringRef F2 = NewFile ? NewFile->getName() : "(internal)";
- return (Sym + " in " + F1 + " and " + F2).str();
+template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) {
+ return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0,
+ /*CanOmitFromDynSym*/ false, /*File*/ nullptr);
}
-// This function resolves conflicts if there's an existing symbol with
-// the same name. Decisions are made based on symbol type.
-template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
- Symbol *Sym = insert(New);
- if (Sym->Body == New)
- return;
+template <class ELFT>
+Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding,
+ uint8_t StOther, uint8_t Type,
+ bool CanOmitFromDynSym,
+ InputFile *File) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) =
+ insert(Name, Type, StOther & 3, CanOmitFromDynSym,
+ /*IsUsedInRegularObj*/ !File || !isa<BitcodeFile>(File), File);
+ if (WasInserted) {
+ S->Binding = Binding;
+ replaceBody<Undefined>(S, Name, StOther, Type, File);
+ return S;
+ }
+ if (Binding != STB_WEAK) {
+ if (S->body()->isShared() || S->body()->isLazy())
+ S->Binding = Binding;
+ if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body()))
+ SS->file()->IsUsed = true;
+ }
+ if (auto *L = dyn_cast<Lazy>(S->body())) {
+ // An undefined weak will not fetch archive members, but we have to remember
+ // its type. See also comment in addLazyArchive.
+ if (S->isWeak())
+ L->Type = Type;
+ else if (auto F = L->fetch())
+ addFile(std::move(F));
+ }
+ return S;
+}
- SymbolBody *Existing = Sym->Body;
+// We have a new defined symbol with the specified binding. Return 1 if the new
+// symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
+// strong defined symbols.
+static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
+ if (WasInserted)
+ return 1;
+ SymbolBody *Body = S->body();
+ if (Body->isLazy() || Body->isUndefined() || Body->isShared())
+ return 1;
+ if (Binding == STB_WEAK)
+ return -1;
+ if (S->isWeak())
+ return 1;
+ return 0;
+}
- if (Lazy *L = dyn_cast<Lazy>(Existing)) {
- if (auto *Undef = dyn_cast<Undefined>(New)) {
- addMemberFile(Undef, L);
- return;
+// We have a new non-common defined symbol with the specified binding. Return 1
+// if the new symbol should win, -1 if the new symbol should lose, or 0 if there
+// is a conflict. If the new symbol wins, also update the binding.
+static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding) {
+ if (int Cmp = compareDefined(S, WasInserted, Binding)) {
+ if (Cmp > 0)
+ S->Binding = Binding;
+ return Cmp;
+ }
+ if (isa<DefinedCommon>(S->body())) {
+ // Non-common symbols take precedence over common symbols.
+ if (Config->WarnCommon)
+ warning("common " + S->body()->getName() + " is overridden");
+ return 1;
+ }
+ return 0;
+}
+
+template <class ELFT>
+Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size,
+ uint64_t Alignment, uint8_t Binding,
+ uint8_t StOther, uint8_t Type,
+ InputFile *File) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) =
+ insert(N, Type, StOther & 3, /*CanOmitFromDynSym*/ false,
+ /*IsUsedInRegularObj*/ true, File);
+ int Cmp = compareDefined(S, WasInserted, Binding);
+ if (Cmp > 0) {
+ S->Binding = Binding;
+ replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
+ } else if (Cmp == 0) {
+ auto *C = dyn_cast<DefinedCommon>(S->body());
+ if (!C) {
+ // Non-common symbols take precedence over common symbols.
+ if (Config->WarnCommon)
+ warning("common " + S->body()->getName() + " is overridden");
+ return S;
}
- // Found a definition for something also in an archive.
- // Ignore the archive definition.
- Sym->Body = New;
- return;
+
+ if (Config->WarnCommon)
+ warning("multiple common of " + S->body()->getName());
+
+ C->Size = std::max(C->Size, Size);
+ C->Alignment = std::max(C->Alignment, Alignment);
}
+ return S;
+}
- if (New->isTls() != Existing->isTls())
- error("TLS attribute mismatch for symbol: " + conflictMsg(Existing, New));
-
- // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
- // equivalent (conflicting), or more preferable, respectively.
- int Comp = Existing->compare<ELFT>(New);
- if (Comp == 0) {
- std::string S = "duplicate symbol: " + conflictMsg(Existing, New);
- if (!Config->AllowMultipleDefinition)
- error(S);
- warning(S);
- return;
+template <class ELFT>
+void SymbolTable<ELFT>::reportDuplicate(SymbolBody *Existing,
+ InputFile *NewFile) {
+ std::string Msg = "duplicate symbol: " + conflictMsg(Existing, NewFile);
+ if (Config->AllowMultipleDefinition)
+ warning(Msg);
+ else
+ error(Msg);
+}
+
+template <typename ELFT>
+Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym,
+ InputSectionBase<ELFT> *Section) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) =
+ insert(Name, Sym.getType(), Sym.getVisibility(),
+ /*CanOmitFromDynSym*/ false, /*IsUsedInRegularObj*/ true,
+ Section ? Section->getFile() : nullptr);
+ int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding());
+ if (Cmp > 0)
+ replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section);
+ else if (Cmp == 0)
+ reportDuplicate(S->body(), Section->getFile());
+ return S;
+}
+
+template <typename ELFT>
+Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding,
+ uint8_t StOther) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) =
+ insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false,
+ /*IsUsedInRegularObj*/ true, nullptr);
+ int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
+ if (Cmp > 0)
+ replaceBody<DefinedRegular<ELFT>>(S, Name, StOther);
+ else if (Cmp == 0)
+ reportDuplicate(S->body(), nullptr);
+ return S;
+}
+
+template <typename ELFT>
+Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
+ OutputSectionBase<ELFT> *Section,
+ uintX_t Value) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) =
+ insert(N, STT_NOTYPE, STV_HIDDEN, /*CanOmitFromDynSym*/ false,
+ /*IsUsedInRegularObj*/ true, nullptr);
+ int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL);
+ if (Cmp > 0)
+ replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section);
+ else if (Cmp == 0)
+ reportDuplicate(S->body(), nullptr);
+ return S;
+}
+
+template <typename ELFT>
+void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
+ const Elf_Sym &Sym,
+ const typename ELFT::Verdef *Verdef) {
+ // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT
+ // as the visibility, which will leave the visibility in the symbol table
+ // unchanged.
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) =
+ insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true,
+ /*IsUsedInRegularObj*/ false, F);
+ // Make sure we preempt DSO symbols with default visibility.
+ if (Sym.getVisibility() == STV_DEFAULT)
+ S->ExportDynamic = true;
+ if (WasInserted || isa<Undefined>(S->body())) {
+ replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
+ if (!S->isWeak())
+ F->IsUsed = true;
}
- if (Comp < 0)
- Sym->Body = New;
}
-// Find an existing symbol or create and insert a new one.
-template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
- StringRef Name = New->getName();
- Symbol *&Sym = Symtab[Name];
- if (!Sym)
- Sym = new (Alloc) Symbol{New};
- New->setBackref(Sym);
- return Sym;
+template <class ELFT>
+Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, bool IsWeak,
+ uint8_t StOther, uint8_t Type,
+ bool CanOmitFromDynSym, BitcodeFile *F) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) = insert(Name, Type, StOther & 3, CanOmitFromDynSym,
+ /*IsUsedInRegularObj*/ false, F);
+ int Cmp =
+ compareDefinedNonCommon(S, WasInserted, IsWeak ? STB_WEAK : STB_GLOBAL);
+ if (Cmp > 0)
+ replaceBody<DefinedBitcode>(S, Name, StOther, Type, F);
+ else if (Cmp == 0)
+ reportDuplicate(S->body(), F);
+ return S;
}
template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
auto It = Symtab.find(Name);
if (It == Symtab.end())
return nullptr;
- return It->second->Body;
+ SymIndex V = It->second;
+ if (V.Idx == -1)
+ return nullptr;
+ return SymVector[V.Idx]->body();
+}
+
+// Returns a list of defined symbols that match with a given glob pattern.
+template <class ELFT>
+std::vector<SymbolBody *> SymbolTable<ELFT>::findAll(StringRef Pattern) {
+ std::vector<SymbolBody *> Res;
+ for (Symbol *Sym : SymVector) {
+ SymbolBody *B = Sym->body();
+ if (!B->isUndefined() && globMatch(Pattern, B->getName()))
+ Res.push_back(B);
+ }
+ return Res;
}
-template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *L) {
- Symbol *Sym = insert(L);
- if (Sym->Body == L)
+template <class ELFT>
+void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
+ const object::Archive::Symbol Sym) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) = insert(Sym.getName());
+ if (WasInserted) {
+ replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType);
+ return;
+ }
+ if (!S->body()->isUndefined())
+ return;
+
+ // Weak undefined symbols should not fetch members from archives. If we were
+ // to keep old symbol we would not know that an archive member was available
+ // if a strong undefined symbol shows up afterwards in the link. If a strong
+ // undefined symbol never shows up, this lazy symbol will get to the end of
+ // the link and must be treated as the weak undefined one. We already marked
+ // this symbol as used when we added it to the symbol table, but we also need
+ // to preserve its type. FIXME: Move the Type field to Symbol.
+ if (S->isWeak()) {
+ replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type);
return;
- if (auto *Undef = dyn_cast<Undefined>(Sym->Body)) {
- Sym->Body = L;
- addMemberFile(Undef, L);
}
+ MemoryBufferRef MBRef = F->getMember(&Sym);
+ if (!MBRef.getBuffer().empty())
+ addFile(createObjectFile(MBRef, F->getName()));
}
template <class ELFT>
-void SymbolTable<ELFT>::addMemberFile(Undefined *Undef, Lazy *L) {
- // Weak undefined symbols should not fetch members from archives.
- // If we were to keep old symbol we would not know that an archive member was
- // available if a strong undefined symbol shows up afterwards in the link.
- // If a strong undefined symbol never shows up, this lazy symbol will
- // get to the end of the link and must be treated as the weak undefined one.
- // We set UsedInRegularObj in a similar way to what is done with shared
- // symbols and mark it as weak to reduce how many special cases are needed.
- if (Undef->isWeak()) {
- L->setUsedInRegularObj();
- L->setWeak();
+void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) {
+ Symbol *S;
+ bool WasInserted;
+ std::tie(S, WasInserted) = insert(Name);
+ if (WasInserted) {
+ replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType);
return;
}
+ if (!S->body()->isUndefined())
+ return;
+
+ // See comment for addLazyArchive above.
+ if (S->isWeak()) {
+ replaceBody<LazyObject>(S, Name, Obj, S->body()->Type);
+ } else {
+ MemoryBufferRef MBRef = Obj.getBuffer();
+ if (!MBRef.getBuffer().empty())
+ addFile(createObjectFile(MBRef));
+ }
+}
- // Fetch a member file that has the definition for L.
- // getMember returns nullptr if the member was already read from the library.
- if (std::unique_ptr<InputFile> File = L->getMember())
- addFile(std::move(File));
+// Process undefined (-u) flags by loading lazy symbols named by those flags.
+template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() {
+ for (StringRef S : Config->Undefined)
+ if (auto *L = dyn_cast_or_null<Lazy>(find(S)))
+ if (std::unique_ptr<InputFile> File = L->fetch())
+ addFile(std::move(File));
}
// This function takes care of the case in which shared libraries depend on
@@ -265,10 +531,183 @@ template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
for (StringRef U : File->getUndefinedSymbols())
if (SymbolBody *Sym = find(U))
if (Sym->isDefined())
- Sym->setUsedInDynamicReloc();
+ Sym->symbol()->ExportDynamic = true;
+}
+
+// This function process the dynamic list option by marking all the symbols
+// to be exported in the dynamic table.
+template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
+ for (StringRef S : Config->DynamicList)
+ if (SymbolBody *B = find(S))
+ B->symbol()->ExportDynamic = true;
+}
+
+static bool hasWildcard(StringRef S) {
+ return S.find_first_of("?*") != StringRef::npos;
+}
+
+static void setVersionId(SymbolBody *Body, StringRef VersionName,
+ StringRef Name, uint16_t Version) {
+ if (!Body || Body->isUndefined()) {
+ if (Config->NoUndefinedVersion)
+ error("version script assignment of " + VersionName + " to symbol " +
+ Name + " failed: symbol not defined");
+ return;
+ }
+
+ Symbol *Sym = Body->symbol();
+ if (Sym->VersionId != Config->DefaultSymbolVersion)
+ warning("duplicate symbol " + Name + " in version script");
+ Sym->VersionId = Version;
+}
+
+template <class ELFT>
+std::map<std::string, SymbolBody *> SymbolTable<ELFT>::getDemangledSyms() {
+ std::map<std::string, SymbolBody *> Result;
+ for (Symbol *Sym : SymVector) {
+ SymbolBody *B = Sym->body();
+ Result[demangle(B->getName())] = B;
+ }
+ return Result;
+}
+
+static bool hasExternCpp() {
+ for (VersionDefinition &V : Config->VersionDefinitions)
+ for (SymbolVersion Sym : V.Globals)
+ if (Sym.IsExternCpp)
+ return true;
+ return false;
+}
+
+// This function processes the --version-script option by marking all global
+// symbols with the VersionScriptGlobal flag, which acts as a filter on the
+// dynamic symbol table.
+template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
+ // If version script does not contain versions declarations,
+ // we just should mark global symbols.
+ if (!Config->VersionScriptGlobals.empty()) {
+ for (SymbolVersion &Sym : Config->VersionScriptGlobals)
+ if (SymbolBody *B = find(Sym.Name))
+ B->symbol()->VersionId = VER_NDX_GLOBAL;
+ return;
+ }
+
+ if (Config->VersionDefinitions.empty())
+ return;
+
+ // If we have symbols version declarations, we should
+ // assign version references for each symbol.
+ // Current rules are:
+ // * If there is an exact match for the mangled name or we have extern C++
+ // exact match, then we use it.
+ // * Otherwise, we look through the wildcard patterns. We look through the
+ // version tags in reverse order. We use the first match we find (the last
+ // matching version tag in the file).
+ // Handle exact matches and build a map of demangled externs for
+ // quick search during next step.
+ std::map<std::string, SymbolBody *> Demangled;
+ if (hasExternCpp())
+ Demangled = getDemangledSyms();
+
+ for (VersionDefinition &V : Config->VersionDefinitions) {
+ for (SymbolVersion Sym : V.Globals) {
+ if (hasWildcard(Sym.Name))
+ continue;
+ SymbolBody *B = Sym.IsExternCpp ? Demangled[Sym.Name] : find(Sym.Name);
+ setVersionId(B, V.Name, Sym.Name, V.Id);
+ }
+ }
+
+ // Handle wildcards.
+ for (size_t I = Config->VersionDefinitions.size() - 1; I != (size_t)-1; --I) {
+ VersionDefinition &V = Config->VersionDefinitions[I];
+ for (SymbolVersion &Sym : V.Globals)
+ if (hasWildcard(Sym.Name))
+ for (SymbolBody *B : findAll(Sym.Name))
+ if (B->symbol()->VersionId == Config->DefaultSymbolVersion)
+ B->symbol()->VersionId = V.Id;
+ }
+}
+
+// Returns the size of the longest version name.
+static int getMaxVersionLen() {
+ size_t Len = 0;
+ for (VersionDefinition &V : Config->VersionDefinitions)
+ Len = std::max(Len, V.Name.size());
+ return Len;
+}
+
+// Parses a symbol name in the form of <name>@<version> or <name>@@<version>.
+static std::pair<StringRef, uint16_t>
+getSymbolVersion(SymbolBody *B, int MaxVersionLen) {
+ StringRef S = B->getName();
+
+ // MaxVersionLen was passed so that we don't need to scan
+ // all characters in a symbol name. It is effective because
+ // versions are usually short and symbol names can be very long.
+ size_t Pos = S.find('@', std::max(0, int(S.size()) - MaxVersionLen - 2));
+ if (Pos == 0 || Pos == StringRef::npos)
+ return {"", 0};
+
+ StringRef Name = S.substr(0, Pos);
+ StringRef Verstr = S.substr(Pos + 1);
+ if (Verstr.empty())
+ return {"", 0};
+
+ // '@@' in a symbol name means the default version.
+ // It is usually the most recent one.
+ bool IsDefault = (Verstr[0] == '@');
+ if (IsDefault)
+ Verstr = Verstr.substr(1);
+
+ for (VersionDefinition &V : Config->VersionDefinitions) {
+ if (V.Name == Verstr)
+ return {Name, IsDefault ? V.Id : (V.Id | VERSYM_HIDDEN)};
+ }
+
+ // It is an error if the specified version was not defined.
+ error("symbol " + S + " has undefined version " + Verstr);
+ return {"", 0};
+}
+
+// Versions are usually assigned to symbols using version scripts,
+// but there's another way to assign versions to symbols.
+// If a symbol name contains '@', the string after it is not
+// actually a part of the symbol name but specifies a version.
+// This function takes care of it.
+template <class ELFT> void SymbolTable<ELFT>::scanSymbolVersions() {
+ if (Config->VersionDefinitions.empty())
+ return;
+
+ int MaxVersionLen = getMaxVersionLen();
+
+ // Unfortunately there's no way other than iterating over all
+ // symbols to look for '@' characters in symbol names.
+ // So this is inherently slow. A good news is that we do this
+ // only when versions have been defined.
+ for (Symbol *Sym : SymVector) {
+ // Symbol versions for exported symbols are by nature
+ // only for defined global symbols.
+ SymbolBody *B = Sym->body();
+ if (!B->isDefined())
+ continue;
+ uint8_t Visibility = B->getVisibility();
+ if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
+ continue;
+
+ // Look for '@' in the symbol name.
+ StringRef Name;
+ uint16_t Version;
+ std::tie(Name, Version) = getSymbolVersion(B, MaxVersionLen);
+ if (Name.empty())
+ continue;
+
+ B->setName(Name);
+ Sym->VersionId = Version;
+ }
}
-template class elf2::SymbolTable<ELF32LE>;
-template class elf2::SymbolTable<ELF32BE>;
-template class elf2::SymbolTable<ELF64LE>;
-template class elf2::SymbolTable<ELF64BE>;
+template class elf::SymbolTable<ELF32LE>;
+template class elf::SymbolTable<ELF32BE>;
+template class elf::SymbolTable<ELF64LE>;
+template class elf::SymbolTable<ELF64BE>;
diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h
index 16ed821bf01a..40415b645a44 100644
--- a/ELF/SymbolTable.h
+++ b/ELF/SymbolTable.h
@@ -11,14 +11,16 @@
#define LLD_ELF_SYMBOL_TABLE_H
#include "InputFiles.h"
-#include "llvm/ADT/MapVector.h"
+#include "LTO.h"
+#include "llvm/ADT/DenseMap.h"
namespace lld {
-namespace elf2 {
+namespace elf {
class Lazy;
template <class ELFT> class OutputSectionBase;
struct Symbol;
-class Undefined;
+
+typedef llvm::CachedHash<StringRef> SymName;
// SymbolTable is a bucket of all known symbols, including defined,
// undefined, or lazy symbols (the last one is symbols in archive
@@ -29,17 +31,18 @@ class Undefined;
// conflicts. For example, obviously, a defined symbol is better than
// an undefined symbol. Or, if there's a conflict between a lazy and a
// undefined, it'll read an archive member to read a real definition
-// to replace the lazy symbol. The logic is implemented in resolve().
+// to replace the lazy symbol. The logic is implemented in the
+// add*() functions, which are called by input files as they are parsed. There
+// is one add* function per symbol type.
template <class ELFT> class SymbolTable {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::uint uintX_t;
public:
void addFile(std::unique_ptr<InputFile> File);
+ void addCombinedLtoObject();
- const llvm::MapVector<StringRef, Symbol *> &getSymbols() const {
- return Symtab;
- }
+ llvm::ArrayRef<Symbol *> getSymbols() const { return SymVector; }
const std::vector<std::unique_ptr<ObjectFile<ELFT>>> &getObjectFiles() const {
return ObjectFiles;
@@ -49,34 +52,69 @@ public:
return SharedFiles;
}
- SymbolBody *addUndefined(StringRef Name);
- SymbolBody *addUndefinedOpt(StringRef Name);
- SymbolBody *addAbsolute(StringRef Name, Elf_Sym &ESym);
- SymbolBody *addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section,
- uintX_t Value);
- SymbolBody *addIgnored(StringRef Name);
- SymbolBody *addIgnoredStrong(StringRef Name);
-
+ DefinedRegular<ELFT> *addAbsolute(StringRef Name,
+ uint8_t Visibility = llvm::ELF::STV_HIDDEN);
+ DefinedRegular<ELFT> *addIgnored(StringRef Name,
+ uint8_t Visibility = llvm::ELF::STV_HIDDEN);
+
+ Symbol *addUndefined(StringRef Name);
+ Symbol *addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther,
+ uint8_t Type, bool CanOmitFromDynSym, InputFile *File);
+
+ Symbol *addRegular(StringRef Name, const Elf_Sym &Sym,
+ InputSectionBase<ELFT> *Section);
+ Symbol *addRegular(StringRef Name, uint8_t Binding, uint8_t StOther);
+ Symbol *addSynthetic(StringRef N, OutputSectionBase<ELFT> *Section,
+ uintX_t Value);
+ void addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym,
+ const typename ELFT::Verdef *Verdef);
+
+ void addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S);
+ void addLazyObject(StringRef Name, LazyObjectFile &Obj);
+ Symbol *addBitcode(StringRef Name, bool IsWeak, uint8_t StOther, uint8_t Type,
+ bool CanOmitFromDynSym, BitcodeFile *File);
+
+ Symbol *addCommon(StringRef N, uint64_t Size, uint64_t Alignment,
+ uint8_t Binding, uint8_t StOther, uint8_t Type,
+ InputFile *File);
+
+ void scanUndefinedFlags();
void scanShlibUndefined();
+ void scanDynamicList();
+ void scanVersionScript();
+ void scanSymbolVersions();
+
SymbolBody *find(StringRef Name);
+
+ void trace(StringRef Name);
void wrap(StringRef Name);
- ELFFileBase<ELFT> *findFile(SymbolBody *B);
private:
- Symbol *insert(SymbolBody *New);
- void addLazy(Lazy *New);
- void addMemberFile(Undefined *Undef, Lazy *L);
- void resolve(SymbolBody *Body);
- std::string conflictMsg(SymbolBody *Old, SymbolBody *New);
+ std::vector<SymbolBody *> findAll(StringRef Pattern);
+ std::pair<Symbol *, bool> insert(StringRef Name);
+ std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type,
+ uint8_t Visibility, bool CanOmitFromDynSym,
+ bool IsUsedInRegularObj, InputFile *File);
+
+ std::string conflictMsg(SymbolBody *Existing, InputFile *NewFile);
+ void reportDuplicate(SymbolBody *Existing, InputFile *NewFile);
+
+ std::map<std::string, SymbolBody *> getDemangledSyms();
+
+ struct SymIndex {
+ int Idx : 31;
+ unsigned Traced : 1;
+ };
// The order the global symbols are in is not defined. We can use an arbitrary
// order, but it has to be reproducible. That is true even when cross linking.
// The default hashing of StringRef produces different results on 32 and 64
- // bit systems so we use a MapVector. That is arbitrary, deterministic but
- // a bit inefficient.
+ // bit systems so we use a map to a vector. That is arbitrary, deterministic
+ // but a bit inefficient.
// FIXME: Experiment with passing in a custom hashing or sorting the symbols
// once symbol resolution is finished.
- llvm::MapVector<StringRef, Symbol *> Symtab;
+ llvm::DenseMap<SymName, SymIndex> Symtab;
+ std::vector<Symbol *> SymVector;
llvm::BumpPtrAllocator Alloc;
// Comdat groups define "link once" sections. If two comdat groups have the
@@ -87,13 +125,20 @@ private:
// The symbol table owns all file objects.
std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
+ std::vector<std::unique_ptr<LazyObjectFile>> LazyObjectFiles;
std::vector<std::unique_ptr<SharedFile<ELFT>>> SharedFiles;
+ std::vector<std::unique_ptr<BitcodeFile>> BitcodeFiles;
// Set of .so files to not link the same shared object file more than once.
llvm::DenseSet<StringRef> SoNames;
+
+ std::unique_ptr<BitcodeCompiler> Lto;
};
-} // namespace elf2
+template <class ELFT> struct Symtab { static SymbolTable<ELFT> *X; };
+template <class ELFT> SymbolTable<ELFT> *Symtab<ELFT>::X;
+
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 3c864cbe2b67..d6a605d11183 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -8,9 +8,11 @@
//===----------------------------------------------------------------------===//
#include "Symbols.h"
-#include "InputSection.h"
#include "Error.h"
#include "InputFiles.h"
+#include "InputSection.h"
+#include "OutputSections.h"
+#include "Target.h"
#include "llvm/ADT/STLExtras.h"
@@ -19,131 +21,316 @@ using namespace llvm::object;
using namespace llvm::ELF;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
+
+template <class ELFT>
+static typename ELFT::uint getSymVA(const SymbolBody &Body,
+ typename ELFT::uint &Addend) {
+ typedef typename ELFT::uint uintX_t;
+
+ switch (Body.kind()) {
+ case SymbolBody::DefinedSyntheticKind: {
+ auto &D = cast<DefinedSynthetic<ELFT>>(Body);
+ const OutputSectionBase<ELFT> *Sec = D.Section;
+ if (!Sec)
+ return D.Value;
+ if (D.Value == DefinedSynthetic<ELFT>::SectionEnd)
+ return Sec->getVA() + Sec->getSize();
+ return Sec->getVA() + D.Value;
+ }
+ case SymbolBody::DefinedRegularKind: {
+ auto &D = cast<DefinedRegular<ELFT>>(Body);
+ InputSectionBase<ELFT> *SC = D.Section;
+
+ // According to the ELF spec reference to a local symbol from outside
+ // the group are not allowed. Unfortunately .eh_frame breaks that rule
+ // and must be treated specially. For now we just replace the symbol with
+ // 0.
+ if (SC == &InputSection<ELFT>::Discarded)
+ return 0;
-static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
- if (VA == STV_DEFAULT)
- return VB;
- if (VB == STV_DEFAULT)
+ // This is an absolute symbol.
+ if (!SC)
+ return D.Value;
+
+ uintX_t Offset = D.Value;
+ if (D.isSection()) {
+ Offset += Addend;
+ Addend = 0;
+ }
+ uintX_t VA = SC->OutSec->getVA() + SC->getOffset(Offset);
+ if (D.isTls())
+ return VA - Out<ELFT>::TlsPhdr->p_vaddr;
return VA;
- return std::min(VA, VB);
+ }
+ case SymbolBody::DefinedCommonKind:
+ return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(Body).OffsetInBss;
+ case SymbolBody::SharedKind: {
+ auto &SS = cast<SharedSymbol<ELFT>>(Body);
+ if (!SS.NeedsCopyOrPltAddr)
+ return 0;
+ if (SS.isFunc())
+ return Body.getPltVA<ELFT>();
+ return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;
+ }
+ case SymbolBody::UndefinedKind:
+ return 0;
+ case SymbolBody::LazyArchiveKind:
+ case SymbolBody::LazyObjectKind:
+ assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer");
+ return 0;
+ case SymbolBody::DefinedBitcodeKind:
+ llvm_unreachable("should have been replaced");
+ }
+ llvm_unreachable("invalid symbol kind");
}
-// Returns 1, 0 or -1 if this symbol should take precedence
-// over the Other, tie or lose, respectively.
-template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
- assert(!isLazy() && !Other->isLazy());
- std::pair<bool, bool> L(isDefined(), !isWeak());
- std::pair<bool, bool> R(Other->isDefined(), !Other->isWeak());
+SymbolBody::SymbolBody(Kind K, uint32_t NameOffset, uint8_t StOther,
+ uint8_t Type)
+ : SymbolKind(K), NeedsCopyOrPltAddr(false), IsLocal(true),
+ IsInGlobalMipsGot(false), Type(Type), StOther(StOther),
+ NameOffset(NameOffset) {}
+
+SymbolBody::SymbolBody(Kind K, StringRef Name, uint8_t StOther, uint8_t Type)
+ : SymbolKind(K), NeedsCopyOrPltAddr(false), IsLocal(false),
+ IsInGlobalMipsGot(false), Type(Type), StOther(StOther),
+ Name({Name.data(), Name.size()}) {}
- // Normalize
- if (L > R)
- return -Other->compare<ELFT>(this);
+StringRef SymbolBody::getName() const {
+ assert(!isLocal());
+ return StringRef(Name.S, Name.Len);
+}
- Visibility = Other->Visibility =
- getMinVisibility(Visibility, Other->Visibility);
+void SymbolBody::setName(StringRef S) {
+ Name.S = S.data();
+ Name.Len = S.size();
+}
- if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
- IsUsedInRegularObj = Other->IsUsedInRegularObj = true;
+// Returns true if a symbol can be replaced at load-time by a symbol
+// with the same name defined in other ELF executable or DSO.
+bool SymbolBody::isPreemptible() const {
+ if (isLocal())
+ return false;
- if (L != R)
- return -1;
- if (!L.first || !L.second)
- return 1;
+ // Shared symbols resolve to the definition in the DSO. The exceptions are
+ // symbols with copy relocations (which resolve to .bss) or preempt plt
+ // entries (which resolve to that plt entry).
if (isShared())
- return -1;
- if (Other->isShared())
- return 1;
- if (isCommon()) {
- if (!Other->isCommon())
- return -1;
- auto *ThisC = cast<DefinedCommon>(this);
- auto *OtherC = cast<DefinedCommon>(Other);
- uintX_t Align = std::max(ThisC->MaxAlignment, OtherC->MaxAlignment);
- if (ThisC->Size >= OtherC->Size) {
- ThisC->MaxAlignment = Align;
- return 1;
- }
- OtherC->MaxAlignment = Align;
- return -1;
- }
- if (Other->isCommon())
- return 1;
+ return !NeedsCopyOrPltAddr;
+
+ // That's all that can be preempted in a non-DSO.
+ if (!Config->Shared)
+ return false;
+
+ // Only symbols that appear in dynsym can be preempted.
+ if (!symbol()->includeInDynsym())
+ return false;
+
+ // Only default visibility symbols can be preempted.
+ if (symbol()->Visibility != STV_DEFAULT)
+ return false;
+
+ // -Bsymbolic means that definitions are not preempted.
+ if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc()))
+ return !isDefined();
+ return true;
+}
+
+template <class ELFT> bool SymbolBody::hasThunk() const {
+ if (auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
+ return DR->ThunkData != nullptr;
+ if (auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
+ return S->ThunkData != nullptr;
+ return false;
+}
+
+template <class ELFT>
+typename ELFT::uint SymbolBody::getVA(typename ELFT::uint Addend) const {
+ typename ELFT::uint OutVA = getSymVA<ELFT>(*this, Addend);
+ return OutVA + Addend;
+}
+
+template <class ELFT> typename ELFT::uint SymbolBody::getGotVA() const {
+ return Out<ELFT>::Got->getVA() + getGotOffset<ELFT>();
+}
+
+template <class ELFT> typename ELFT::uint SymbolBody::getGotOffset() const {
+ return GotIndex * Target->GotEntrySize;
+}
+
+template <class ELFT> typename ELFT::uint SymbolBody::getGotPltVA() const {
+ return Out<ELFT>::GotPlt->getVA() + getGotPltOffset<ELFT>();
+}
+
+template <class ELFT> typename ELFT::uint SymbolBody::getGotPltOffset() const {
+ return GotPltIndex * Target->GotPltEntrySize;
+}
+
+template <class ELFT> typename ELFT::uint SymbolBody::getPltVA() const {
+ return Out<ELFT>::Plt->getVA() + Target->PltHeaderSize +
+ PltIndex * Target->PltEntrySize;
+}
+
+template <class ELFT> typename ELFT::uint SymbolBody::getThunkVA() const {
+ if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
+ return DR->ThunkData->getVA();
+ if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
+ return S->ThunkData->getVA();
+ fatal("getThunkVA() not supported for Symbol class\n");
+}
+
+template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
+ if (const auto *C = dyn_cast<DefinedCommon>(this))
+ return C->Size;
+ if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
+ return DR->Size;
+ if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
+ return S->Sym.st_size;
return 0;
}
-Defined::Defined(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,
- bool IsTls)
- : SymbolBody(K, Name, IsWeak, Visibility, IsTls) {}
+Defined::Defined(Kind K, StringRef Name, uint8_t StOther, uint8_t Type)
+ : SymbolBody(K, Name, StOther, Type) {}
-Undefined::Undefined(SymbolBody::Kind K, StringRef N, bool IsWeak,
- uint8_t Visibility, bool IsTls)
- : SymbolBody(K, N, IsWeak, Visibility, IsTls), CanKeepUndefined(false) {}
+Defined::Defined(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type)
+ : SymbolBody(K, NameOffset, StOther, Type) {}
-Undefined::Undefined(StringRef N, bool IsWeak, uint8_t Visibility,
- bool CanKeepUndefined)
- : Undefined(SymbolBody::UndefinedKind, N, IsWeak, Visibility,
- /*IsTls*/ false) {
- this->CanKeepUndefined = CanKeepUndefined;
+DefinedBitcode::DefinedBitcode(StringRef Name, uint8_t StOther, uint8_t Type,
+ BitcodeFile *F)
+ : Defined(DefinedBitcodeKind, Name, StOther, Type) {
+ this->File = F;
}
-template <typename ELFT>
-UndefinedElf<ELFT>::UndefinedElf(StringRef N, const Elf_Sym &Sym)
- : Undefined(SymbolBody::UndefinedElfKind, N,
- Sym.getBinding() == llvm::ELF::STB_WEAK, Sym.getVisibility(),
- Sym.getType() == llvm::ELF::STT_TLS),
- Sym(Sym) {}
+bool DefinedBitcode::classof(const SymbolBody *S) {
+ return S->kind() == DefinedBitcodeKind;
+}
+
+Undefined::Undefined(StringRef Name, uint8_t StOther, uint8_t Type,
+ InputFile *File)
+ : SymbolBody(SymbolBody::UndefinedKind, Name, StOther, Type) {
+ this->File = File;
+}
+
+Undefined::Undefined(uint32_t NameOffset, uint8_t StOther, uint8_t Type,
+ InputFile *File)
+ : SymbolBody(SymbolBody::UndefinedKind, NameOffset, StOther, Type) {
+ this->File = File;
+}
template <typename ELFT>
DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,
- OutputSectionBase<ELFT> &Section)
- : Defined(SymbolBody::DefinedSyntheticKind, N, false, STV_DEFAULT, false),
+ OutputSectionBase<ELFT> *Section)
+ : Defined(SymbolBody::DefinedSyntheticKind, N, STV_HIDDEN, 0 /* Type */),
Value(Value), Section(Section) {}
DefinedCommon::DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment,
- bool IsWeak, uint8_t Visibility)
- : Defined(SymbolBody::DefinedCommonKind, N, IsWeak, Visibility, false) {
- MaxAlignment = Alignment;
- this->Size = Size;
+ uint8_t StOther, uint8_t Type, InputFile *File)
+ : Defined(SymbolBody::DefinedCommonKind, N, StOther, Type),
+ Alignment(Alignment), Size(Size) {
+ this->File = File;
+}
+
+std::unique_ptr<InputFile> Lazy::fetch() {
+ if (auto *S = dyn_cast<LazyArchive>(this))
+ return S->fetch();
+ return cast<LazyObject>(this)->fetch();
}
-std::unique_ptr<InputFile> Lazy::getMember() {
- MemoryBufferRef MBRef = File->getMember(&Sym);
+LazyArchive::LazyArchive(ArchiveFile &File,
+ const llvm::object::Archive::Symbol S, uint8_t Type)
+ : Lazy(LazyArchiveKind, S.getName(), Type), Sym(S) {
+ this->File = &File;
+}
+
+LazyObject::LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type)
+ : Lazy(LazyObjectKind, Name, Type) {
+ this->File = &File;
+}
+
+std::unique_ptr<InputFile> LazyArchive::fetch() {
+ MemoryBufferRef MBRef = file()->getMember(&Sym);
// getMember returns an empty buffer if the member was already
// read from the library.
if (MBRef.getBuffer().empty())
return std::unique_ptr<InputFile>(nullptr);
+ return createObjectFile(MBRef, file()->getName());
+}
+
+std::unique_ptr<InputFile> LazyObject::fetch() {
+ MemoryBufferRef MBRef = file()->getBuffer();
+ if (MBRef.getBuffer().empty())
+ return std::unique_ptr<InputFile>(nullptr);
return createObjectFile(MBRef);
}
-template <class ELFT> static void doInitSymbols() {
- ElfSym<ELFT>::End.setBinding(STB_GLOBAL);
- ElfSym<ELFT>::IgnoredWeak.setBinding(STB_WEAK);
- ElfSym<ELFT>::IgnoredWeak.setVisibility(STV_HIDDEN);
- ElfSym<ELFT>::Ignored.setBinding(STB_GLOBAL);
- ElfSym<ELFT>::Ignored.setVisibility(STV_HIDDEN);
+bool Symbol::includeInDynsym() const {
+ if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
+ return false;
+ return (ExportDynamic && VersionId != VER_NDX_LOCAL) || body()->isShared() ||
+ (body()->isUndefined() && Config->Shared);
}
-void elf2::initSymbols() {
- doInitSymbols<ELF32LE>();
- doInitSymbols<ELF32BE>();
- doInitSymbols<ELF64LE>();
- doInitSymbols<ELF64BE>();
+// Print out a log message for --trace-symbol.
+void elf::printTraceSymbol(Symbol *Sym) {
+ SymbolBody *B = Sym->body();
+ outs() << getFilename(B->File);
+
+ if (B->isUndefined())
+ outs() << ": reference to ";
+ else if (B->isCommon())
+ outs() << ": common definition of ";
+ else
+ outs() << ": definition of ";
+ outs() << B->getName() << "\n";
}
-template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
-template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
-template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
-template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
+template bool SymbolBody::hasThunk<ELF32LE>() const;
+template bool SymbolBody::hasThunk<ELF32BE>() const;
+template bool SymbolBody::hasThunk<ELF64LE>() const;
+template bool SymbolBody::hasThunk<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;
+template uint32_t SymbolBody::template getVA<ELF32BE>(uint32_t) const;
+template uint64_t SymbolBody::template getVA<ELF64LE>(uint64_t) const;
+template uint64_t SymbolBody::template getVA<ELF64BE>(uint64_t) const;
+
+template uint32_t SymbolBody::template getGotVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getGotVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getGotVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getGotVA<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getGotOffset<ELF32LE>() const;
+template uint32_t SymbolBody::template getGotOffset<ELF32BE>() const;
+template uint64_t SymbolBody::template getGotOffset<ELF64LE>() const;
+template uint64_t SymbolBody::template getGotOffset<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getGotPltVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getGotPltVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getGotPltVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getGotPltVA<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getThunkVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getThunkVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getThunkVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getThunkVA<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getGotPltOffset<ELF32LE>() const;
+template uint32_t SymbolBody::template getGotPltOffset<ELF32BE>() const;
+template uint64_t SymbolBody::template getGotPltOffset<ELF64LE>() const;
+template uint64_t SymbolBody::template getGotPltOffset<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getPltVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getPltVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getPltVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getPltVA<ELF64BE>() const;
-template class elf2::UndefinedElf<ELF32LE>;
-template class elf2::UndefinedElf<ELF32BE>;
-template class elf2::UndefinedElf<ELF64LE>;
-template class elf2::UndefinedElf<ELF64BE>;
+template uint32_t SymbolBody::template getSize<ELF32LE>() const;
+template uint32_t SymbolBody::template getSize<ELF32BE>() const;
+template uint64_t SymbolBody::template getSize<ELF64LE>() const;
+template uint64_t SymbolBody::template getSize<ELF64BE>() const;
-template class elf2::DefinedSynthetic<ELF32LE>;
-template class elf2::DefinedSynthetic<ELF32BE>;
-template class elf2::DefinedSynthetic<ELF64LE>;
-template class elf2::DefinedSynthetic<ELF64BE>;
+template class elf::DefinedSynthetic<ELF32LE>;
+template class elf::DefinedSynthetic<ELF32BE>;
+template class elf::DefinedSynthetic<ELF64LE>;
+template class elf::DefinedSynthetic<ELF64BE>;
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index 6f65ea1a72e4..aa9a87d3b4f7 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -10,14 +10,6 @@
// All symbols are handled as SymbolBodies regardless of their types.
// This file defines various types of SymbolBodies.
//
-// File-scope symbols in ELF objects are the only exception of SymbolBody
-// instantiation. We will never create SymbolBodies for them for performance
-// reason. They are often represented as nullptrs. This is fine for symbol
-// resolution because the symbol table naturally cares only about
-// externally-visible symbols. For relocations, you have to deal with both
-// local and non-local functions, and we have two different functions
-// where we need them.
-//
//===----------------------------------------------------------------------===//
#ifndef LLD_ELF_SYMBOLS_H
@@ -28,28 +20,22 @@
#include "lld/Core/LLVM.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
+#include "llvm/Support/AlignOf.h"
namespace lld {
-namespace elf2 {
+namespace elf {
class ArchiveFile;
+class BitcodeFile;
class InputFile;
+class LazyObjectFile;
class SymbolBody;
template <class ELFT> class ObjectFile;
template <class ELFT> class OutputSection;
template <class ELFT> class OutputSectionBase;
template <class ELFT> class SharedFile;
-// Initializes global objects defined in this file.
-// Called at the beginning of main().
-void initSymbols();
-
-// A real symbol object, SymbolBody, is usually accessed indirectly
-// through a Symbol. There's always one Symbol for each symbol name.
-// The resolver updates SymbolBody pointers as it resolves symbols.
-struct Symbol {
- SymbolBody *Body;
-};
+struct Symbol;
// The base class for real symbol classes.
class SymbolBody {
@@ -58,115 +44,134 @@ public:
DefinedFirst,
DefinedRegularKind = DefinedFirst,
SharedKind,
- DefinedElfLast = SharedKind,
DefinedCommonKind,
+ DefinedBitcodeKind,
DefinedSyntheticKind,
DefinedLast = DefinedSyntheticKind,
- UndefinedElfKind,
UndefinedKind,
- LazyKind
+ LazyArchiveKind,
+ LazyObjectKind,
};
- Kind kind() const { return static_cast<Kind>(SymbolKind); }
+ SymbolBody(Kind K) : SymbolKind(K) {}
- bool isWeak() const { return IsWeak; }
- bool isUndefined() const {
- return SymbolKind == UndefinedKind || SymbolKind == UndefinedElfKind;
+ Symbol *symbol();
+ const Symbol *symbol() const {
+ return const_cast<SymbolBody *>(this)->symbol();
}
+
+ Kind kind() const { return static_cast<Kind>(SymbolKind); }
+
+ bool isUndefined() const { return SymbolKind == UndefinedKind; }
bool isDefined() const { return SymbolKind <= DefinedLast; }
bool isCommon() const { return SymbolKind == DefinedCommonKind; }
- bool isLazy() const { return SymbolKind == LazyKind; }
+ bool isLazy() const {
+ return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind;
+ }
bool isShared() const { return SymbolKind == SharedKind; }
- bool isUsedInRegularObj() const { return IsUsedInRegularObj; }
- bool isUsedInDynamicReloc() const { return IsUsedInDynamicReloc; }
- void setUsedInDynamicReloc() { IsUsedInDynamicReloc = true; }
- bool isTls() const { return IsTls; }
+ bool isLocal() const { return IsLocal; }
+ bool isPreemptible() const;
- // Returns the symbol name.
- StringRef getName() const { return Name; }
+ StringRef getName() const;
+ void setName(StringRef S);
- uint8_t getVisibility() const { return Visibility; }
+ uint32_t getNameOffset() const {
+ assert(isLocal());
+ return NameOffset;
+ }
- unsigned DynamicSymbolTableIndex = 0;
- uint32_t GlobalDynIndex = -1;
+ uint8_t getVisibility() const { return StOther & 0x3; }
+
+ unsigned DynsymIndex = 0;
uint32_t GotIndex = -1;
uint32_t GotPltIndex = -1;
uint32_t PltIndex = -1;
- bool hasGlobalDynIndex() { return GlobalDynIndex != uint32_t(-1); }
+ uint32_t GlobalDynIndex = -1;
bool isInGot() const { return GotIndex != -1U; }
- bool isInGotPlt() const { return GotPltIndex != -1U; }
bool isInPlt() const { return PltIndex != -1U; }
+ template <class ELFT> bool hasThunk() const;
+
+ template <class ELFT>
+ typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const;
+
+ template <class ELFT> typename ELFT::uint getGotOffset() const;
+ template <class ELFT> typename ELFT::uint getGotVA() const;
+ template <class ELFT> typename ELFT::uint getGotPltOffset() const;
+ template <class ELFT> typename ELFT::uint getGotPltVA() const;
+ template <class ELFT> typename ELFT::uint getPltVA() const;
+ template <class ELFT> typename ELFT::uint getThunkVA() const;
+ template <class ELFT> typename ELFT::uint getSize() const;
- // A SymbolBody has a backreference to a Symbol. Originally they are
- // doubly-linked. A backreference will never change. But the pointer
- // in the Symbol may be mutated by the resolver. If you have a
- // pointer P to a SymbolBody and are not sure whether the resolver
- // has chosen the object among other objects having the same name,
- // you can access P->Backref->Body to get the resolver's result.
- void setBackref(Symbol *P) { Backref = P; }
- SymbolBody *repl() { return Backref ? Backref->Body : this; }
- Symbol *getSymbol() { return Backref; }
-
- // Decides which symbol should "win" in the symbol table, this or
- // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
- // they are duplicate (conflicting) symbols.
- template <class ELFT> int compare(SymbolBody *Other);
+ // The file from which this symbol was created.
+ InputFile *File = nullptr;
protected:
- SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,
- bool IsTls)
- : SymbolKind(K), IsWeak(IsWeak), Visibility(Visibility), IsTls(IsTls),
- Name(Name) {
- IsUsedInRegularObj = K != SharedKind && K != LazyKind;
- IsUsedInDynamicReloc = 0;
- }
+ SymbolBody(Kind K, StringRef Name, uint8_t StOther, uint8_t Type);
+
+ SymbolBody(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type);
const unsigned SymbolKind : 8;
- unsigned IsWeak : 1;
- unsigned Visibility : 2;
- // True if the symbol was used for linking and thus need to be
- // added to the output file's symbol table. It is usually true,
- // but if it is a shared symbol that were not referenced by anyone,
- // it can be false.
- unsigned IsUsedInRegularObj : 1;
+public:
+ // True if the linker has to generate a copy relocation for this shared
+ // symbol or if the symbol should point to its plt entry.
+ unsigned NeedsCopyOrPltAddr : 1;
+
+ // True if this is a local symbol.
+ unsigned IsLocal : 1;
+
+ // True if this symbol has an entry in the global part of MIPS GOT.
+ unsigned IsInGlobalMipsGot : 1;
- // If true, the symbol is added to .dynsym symbol table.
- unsigned IsUsedInDynamicReloc : 1;
+ // The following fields have the same meaning as the ELF symbol attributes.
+ uint8_t Type; // symbol type
+ uint8_t StOther; // st_other field value
- unsigned IsTls : 1;
- StringRef Name;
- Symbol *Backref = nullptr;
+ // The Type field may also have this value. It means that we have not yet seen
+ // a non-Lazy symbol with this name, so we don't know what its type is. The
+ // Type field is normally set to this value for Lazy symbols unless we saw a
+ // weak undefined symbol first, in which case we need to remember the original
+ // symbol's type in order to check for TLS mismatches.
+ enum { UnknownType = 255 };
+
+ bool isSection() const { return Type == llvm::ELF::STT_SECTION; }
+ bool isTls() const { return Type == llvm::ELF::STT_TLS; }
+ bool isFunc() const { return Type == llvm::ELF::STT_FUNC; }
+ bool isGnuIFunc() const { return Type == llvm::ELF::STT_GNU_IFUNC; }
+ bool isObject() const { return Type == llvm::ELF::STT_OBJECT; }
+ bool isFile() const { return Type == llvm::ELF::STT_FILE; }
+
+protected:
+ struct Str {
+ const char *S;
+ size_t Len;
+ };
+ union {
+ Str Name;
+ uint32_t NameOffset;
+ };
};
// The base class for any defined symbols.
class Defined : public SymbolBody {
public:
- Defined(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility, bool IsTls);
+ Defined(Kind K, StringRef Name, uint8_t StOther, uint8_t Type);
+ Defined(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type);
static bool classof(const SymbolBody *S) { return S->isDefined(); }
};
-// Any defined symbol from an ELF file.
-template <class ELFT> class DefinedElf : public Defined {
-protected:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
-
+// The defined symbol in LLVM bitcode files.
+class DefinedBitcode : public Defined {
public:
- DefinedElf(Kind K, StringRef N, const Elf_Sym &Sym)
- : Defined(K, N, Sym.getBinding() == llvm::ELF::STB_WEAK,
- Sym.getVisibility(), Sym.getType() == llvm::ELF::STT_TLS),
- Sym(Sym) {}
-
- const Elf_Sym &Sym;
- static bool classof(const SymbolBody *S) {
- return S->kind() <= DefinedElfLast;
- }
+ DefinedBitcode(StringRef Name, uint8_t StOther, uint8_t Type, BitcodeFile *F);
+ static bool classof(const SymbolBody *S);
+ BitcodeFile *file() { return (BitcodeFile *)this->File; }
};
class DefinedCommon : public Defined {
public:
- DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment, bool IsWeak,
- uint8_t Visibility);
+ DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment, uint8_t StOther,
+ uint8_t Type, InputFile *File);
static bool classof(const SymbolBody *S) {
return S->kind() == SymbolBody::DefinedCommonKind;
@@ -177,95 +182,137 @@ public:
uint64_t OffsetInBss;
// The maximum alignment we have seen for this symbol.
- uint64_t MaxAlignment;
+ uint64_t Alignment;
uint64_t Size;
};
// Regular defined symbols read from object file symbol tables.
-template <class ELFT> class DefinedRegular : public DefinedElf<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+template <class ELFT> class DefinedRegular : public Defined {
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::uint uintX_t;
public:
- DefinedRegular(StringRef N, const Elf_Sym &Sym,
+ DefinedRegular(StringRef Name, const Elf_Sym &Sym,
InputSectionBase<ELFT> *Section)
- : DefinedElf<ELFT>(SymbolBody::DefinedRegularKind, N, Sym),
- Section(Section) {}
+ : Defined(SymbolBody::DefinedRegularKind, Name, Sym.st_other,
+ Sym.getType()),
+ Value(Sym.st_value), Size(Sym.st_size),
+ Section(Section ? Section->Repl : NullInputSection) {
+ if (Section)
+ this->File = Section->getFile();
+ }
+
+ DefinedRegular(const Elf_Sym &Sym, InputSectionBase<ELFT> *Section)
+ : Defined(SymbolBody::DefinedRegularKind, Sym.st_name, Sym.st_other,
+ Sym.getType()),
+ Value(Sym.st_value), Size(Sym.st_size),
+ Section(Section ? Section->Repl : NullInputSection) {
+ assert(isLocal());
+ if (Section)
+ this->File = Section->getFile();
+ }
+
+ DefinedRegular(StringRef Name, uint8_t StOther)
+ : Defined(SymbolBody::DefinedRegularKind, Name, StOther,
+ llvm::ELF::STT_NOTYPE),
+ Value(0), Size(0), Section(NullInputSection) {}
static bool classof(const SymbolBody *S) {
return S->kind() == SymbolBody::DefinedRegularKind;
}
- // If this is null, the symbol is absolute.
- InputSectionBase<ELFT> *Section;
+ uintX_t Value;
+ uintX_t Size;
+
+ // The input section this symbol belongs to. Notice that this is
+ // a reference to a pointer. We are using two levels of indirections
+ // because of ICF. If ICF decides two sections need to be merged, it
+ // manipulates this Section pointers so that they point to the same
+ // section. This is a bit tricky, so be careful to not be confused.
+ // If this is null, the symbol is an absolute symbol.
+ InputSectionBase<ELFT> *&Section;
+
+ // If non-null the symbol has a Thunk that may be used as an alternative
+ // destination for callers of this Symbol.
+ Thunk<ELFT> *ThunkData = nullptr;
+
+private:
+ static InputSectionBase<ELFT> *NullInputSection;
};
+template <class ELFT>
+InputSectionBase<ELFT> *DefinedRegular<ELFT>::NullInputSection;
+
// DefinedSynthetic is a class to represent linker-generated ELF symbols.
// The difference from the regular symbol is that DefinedSynthetic symbols
// don't belong to any input files or sections. Thus, its constructor
// takes an output section to calculate output VA, etc.
+// If Section is null, this symbol is relative to the image base.
template <class ELFT> class DefinedSynthetic : public Defined {
public:
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ typedef typename ELFT::uint uintX_t;
DefinedSynthetic(StringRef N, uintX_t Value,
- OutputSectionBase<ELFT> &Section);
+ OutputSectionBase<ELFT> *Section);
static bool classof(const SymbolBody *S) {
return S->kind() == SymbolBody::DefinedSyntheticKind;
}
+ // Special value designates that the symbol 'points'
+ // to the end of the section.
+ static const uintX_t SectionEnd = uintX_t(-1);
+
uintX_t Value;
- const OutputSectionBase<ELFT> &Section;
+ const OutputSectionBase<ELFT> *Section;
};
-// Undefined symbol.
class Undefined : public SymbolBody {
- typedef SymbolBody::Kind Kind;
- bool CanKeepUndefined;
-
-protected:
- Undefined(Kind K, StringRef N, bool IsWeak, uint8_t Visibility, bool IsTls);
-
-public:
- Undefined(StringRef N, bool IsWeak, uint8_t Visibility,
- bool CanKeepUndefined);
-
- static bool classof(const SymbolBody *S) { return S->isUndefined(); }
-
- bool canKeepUndefined() const { return CanKeepUndefined; }
-};
-
-template <class ELFT> class UndefinedElf : public Undefined {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
-
public:
- UndefinedElf(StringRef N, const Elf_Sym &Sym);
- const Elf_Sym &Sym;
+ Undefined(StringRef Name, uint8_t StOther, uint8_t Type, InputFile *F);
+ Undefined(uint32_t NameOffset, uint8_t StOther, uint8_t Type, InputFile *F);
static bool classof(const SymbolBody *S) {
- return S->kind() == SymbolBody::UndefinedElfKind;
+ return S->kind() == UndefinedKind;
}
+
+ InputFile *file() { return this->File; }
};
-template <class ELFT> class SharedSymbol : public DefinedElf<ELFT> {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+template <class ELFT> class SharedSymbol : public Defined {
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::Verdef Elf_Verdef;
+ typedef typename ELFT::uint uintX_t;
public:
static bool classof(const SymbolBody *S) {
return S->kind() == SymbolBody::SharedKind;
}
- SharedSymbol(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym)
- : DefinedElf<ELFT>(SymbolBody::SharedKind, Name, Sym), File(F) {}
+ SharedSymbol(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym,
+ const Elf_Verdef *Verdef)
+ : Defined(SymbolBody::SharedKind, Name, Sym.st_other, Sym.getType()),
+ Sym(Sym), Verdef(Verdef) {
+ // IFuncs defined in DSOs are treated as functions by the static linker.
+ if (isGnuIFunc())
+ Type = llvm::ELF::STT_FUNC;
+ this->File = F;
+ }
- SharedFile<ELFT> *File;
+ SharedFile<ELFT> *file() { return (SharedFile<ELFT> *)this->File; }
- // True if the linker has to generate a copy relocation for this shared
- // symbol. OffsetInBss is significant only when NeedsCopy is true.
- bool NeedsCopy = false;
+ const Elf_Sym &Sym;
+
+ // This field is a pointer to the symbol's version definition.
+ const Elf_Verdef *Verdef;
+
+ // OffsetInBss is significant only when needsCopy() is true.
uintX_t OffsetInBss = 0;
+
+ // If non-null the symbol has a Thunk that may be used as an alternative
+ // destination for callers of this Symbol.
+ Thunk<ELFT> *ThunkData = nullptr;
+ bool needsCopy() const { return this->NeedsCopyOrPltAddr && !this->isFunc(); }
};
// This class represents a symbol defined in an archive file. It is
@@ -275,58 +322,153 @@ public:
// the same name, it will ask the Lazy to load a file.
class Lazy : public SymbolBody {
public:
- Lazy(ArchiveFile *F, const llvm::object::Archive::Symbol S)
- : SymbolBody(LazyKind, S.getName(), false, llvm::ELF::STV_DEFAULT, false),
- File(F), Sym(S) {}
-
- static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; }
+ static bool classof(const SymbolBody *S) { return S->isLazy(); }
// Returns an object file for this symbol, or a nullptr if the file
// was already returned.
- std::unique_ptr<InputFile> getMember();
+ std::unique_ptr<InputFile> fetch();
- void setWeak() { IsWeak = true; }
- void setUsedInRegularObj() { IsUsedInRegularObj = true; }
+protected:
+ Lazy(SymbolBody::Kind K, StringRef Name, uint8_t Type)
+ : SymbolBody(K, Name, llvm::ELF::STV_DEFAULT, Type) {}
+};
+
+// LazyArchive symbols represents symbols in archive files.
+class LazyArchive : public Lazy {
+public:
+ LazyArchive(ArchiveFile &File, const llvm::object::Archive::Symbol S,
+ uint8_t Type);
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == LazyArchiveKind;
+ }
+
+ ArchiveFile *file() { return (ArchiveFile *)this->File; }
+ std::unique_ptr<InputFile> fetch();
private:
- ArchiveFile *File;
const llvm::object::Archive::Symbol Sym;
};
+// LazyObject symbols represents symbols in object files between
+// --start-lib and --end-lib options.
+class LazyObject : public Lazy {
+public:
+ LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type);
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == LazyObjectKind;
+ }
+
+ LazyObjectFile *file() { return (LazyObjectFile *)this->File; }
+ std::unique_ptr<InputFile> fetch();
+};
+
// Some linker-generated symbols need to be created as
-// DefinedRegular symbols, so they need Elf_Sym symbols.
-// Here we allocate such Elf_Sym symbols statically.
+// DefinedRegular symbols.
template <class ELFT> struct ElfSym {
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+ // The content for _etext and etext symbols.
+ static DefinedRegular<ELFT> *Etext;
+ static DefinedRegular<ELFT> *Etext2;
- // Used to represent an undefined symbol which we don't want
- // to add to the output file's symbol table. The `IgnoredWeak`
- // has weak binding and can be substituted. The `Ignore` has
- // global binding and gets priority over symbols from shared libs.
- static Elf_Sym IgnoredWeak;
- static Elf_Sym Ignored;
+ // The content for _edata and edata symbols.
+ static DefinedRegular<ELFT> *Edata;
+ static DefinedRegular<ELFT> *Edata2;
// The content for _end and end symbols.
- static Elf_Sym End;
+ static DefinedRegular<ELFT> *End;
+ static DefinedRegular<ELFT> *End2;
- // The content for _gp symbol for MIPS target.
- static Elf_Sym MipsGp;
+ // The content for _gp_disp symbol for MIPS target.
+ static SymbolBody *MipsGpDisp;
+};
+
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Etext;
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Etext2;
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Edata;
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::Edata2;
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End;
+template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End2;
+template <class ELFT> SymbolBody *ElfSym<ELFT>::MipsGpDisp;
+
+// A real symbol object, SymbolBody, is usually stored within a Symbol. There's
+// always one Symbol for each symbol name. The resolver updates the SymbolBody
+// stored in the Body field of this object as it resolves symbols. Symbol also
+// holds computed properties of symbol names.
+struct Symbol {
+ // Symbol binding. This is on the Symbol to track changes during resolution.
+ // In particular:
+ // An undefined weak is still weak when it resolves to a shared library.
+ // An undefined weak will not fetch archive members, but we have to remember
+ // it is weak.
+ uint8_t Binding;
+
+ // Version definition index.
+ uint16_t VersionId;
+
+ // Symbol visibility. This is the computed minimum visibility of all
+ // observed non-DSO symbols.
+ unsigned Visibility : 2;
+
+ // True if the symbol was used for linking and thus need to be added to the
+ // output file's symbol table. This is true for all symbols except for
+ // unreferenced DSO symbols and bitcode symbols that are unreferenced except
+ // by other bitcode objects.
+ unsigned IsUsedInRegularObj : 1;
- // __rel_iplt_start/__rel_iplt_end for signaling
- // where R_[*]_IRELATIVE relocations do live.
- static Elf_Sym RelaIpltStart;
- static Elf_Sym RelaIpltEnd;
+ // If this flag is true and the symbol has protected or default visibility, it
+ // will appear in .dynsym. This flag is set by interposable DSO symbols in
+ // executables, by most symbols in DSOs and executables built with
+ // --export-dynamic, and by dynamic lists.
+ unsigned ExportDynamic : 1;
+
+ // True if this symbol is specified by --trace-symbol option.
+ unsigned Traced : 1;
+
+ bool includeInDynsym() const;
+ bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
+
+ // This field is used to store the Symbol's SymbolBody. This instantiation of
+ // AlignedCharArrayUnion gives us a struct with a char array field that is
+ // large and aligned enough to store any derived class of SymbolBody. We
+ // assume that the size and alignment of ELF64LE symbols is sufficient for any
+ // ELFT, and we verify this with the static_asserts in replaceBody.
+ llvm::AlignedCharArrayUnion<
+ DefinedBitcode, DefinedCommon, DefinedRegular<llvm::object::ELF64LE>,
+ DefinedSynthetic<llvm::object::ELF64LE>, Undefined,
+ SharedSymbol<llvm::object::ELF64LE>, LazyArchive, LazyObject>
+ Body;
+
+ SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); }
+ const SymbolBody *body() const { return const_cast<Symbol *>(this)->body(); }
};
-template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::IgnoredWeak;
-template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::Ignored;
-template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::End;
-template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::MipsGp;
-template <class ELFT>
-typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::RelaIpltStart;
-template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::RelaIpltEnd;
+void printTraceSymbol(Symbol *Sym);
+
+template <typename T, typename... ArgT>
+void replaceBody(Symbol *S, ArgT &&... Arg) {
+ static_assert(sizeof(T) <= sizeof(S->Body), "Body too small");
+ static_assert(llvm::AlignOf<T>::Alignment <=
+ llvm::AlignOf<decltype(S->Body)>::Alignment,
+ "Body not aligned enough");
+ assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr &&
+ "Not a SymbolBody");
+
+ new (S->Body.buffer) T(std::forward<ArgT>(Arg)...);
+
+ // Print out a log message if --trace-symbol was specified.
+ // This is for debugging.
+ if (S->Traced)
+ printTraceSymbol(S);
+}
+
+inline Symbol *SymbolBody::symbol() {
+ assert(!isLocal());
+ return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) -
+ offsetof(Symbol, Body));
+}
-} // namespace elf2
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index 6d42dbe86e54..466d1b47ce12 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -11,14 +11,25 @@
// GOT or PLT entries, etc., are handled in this file.
//
// Refer the ELF spec for the single letter varaibles, S, A or P, used
-// in this file. SA is S+A.
+// in this file.
+//
+// Some functions defined in this file has "relaxTls" as part of their names.
+// They do peephole optimization for TLS variables by rewriting instructions.
+// They are not part of the ABI but optional optimization, so you can skip
+// them if you are not interested in how TLS variables are optimized.
+// See the following paper for the details.
+//
+// Ulrich Drepper, ELF Handling For Thread-Local Storage
+// http://www.akkadia.org/drepper/tls.pdf
//
//===----------------------------------------------------------------------===//
#include "Target.h"
#include "Error.h"
+#include "InputFiles.h"
#include "OutputSections.h"
#include "Symbols.h"
+#include "Thunks.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/ELF.h"
@@ -31,215 +42,169 @@ using namespace llvm::support::endian;
using namespace llvm::ELF;
namespace lld {
-namespace elf2 {
+namespace elf {
-std::unique_ptr<TargetInfo> Target;
+TargetInfo *Target;
-template <endianness E> static void add32(void *P, int32_t V) {
- write32<E>(P, read32<E>(P) + V);
-}
-
-static void add32le(uint8_t *P, int32_t V) { add32<support::little>(P, V); }
static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
+StringRef getRelName(uint32_t Type) {
+ return getELFRelocationTypeName(Config->EMachine, Type);
+}
+
template <unsigned N> static void checkInt(int64_t V, uint32_t Type) {
- if (isInt<N>(V))
- return;
- StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
- error("Relocation " + S + " out of range");
+ if (!isInt<N>(V))
+ error("relocation " + getRelName(Type) + " out of range");
}
template <unsigned N> static void checkUInt(uint64_t V, uint32_t Type) {
- if (isUInt<N>(V))
- return;
- StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
- error("Relocation " + S + " out of range");
+ if (!isUInt<N>(V))
+ error("relocation " + getRelName(Type) + " out of range");
}
template <unsigned N> static void checkIntUInt(uint64_t V, uint32_t Type) {
- if (isInt<N>(V) || isUInt<N>(V))
- return;
- StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
- error("Relocation " + S + " out of range");
+ if (!isInt<N>(V) && !isUInt<N>(V))
+ error("relocation " + getRelName(Type) + " out of range");
}
template <unsigned N> static void checkAlignment(uint64_t V, uint32_t Type) {
- if ((V & (N - 1)) == 0)
- return;
- StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
- error("Improper alignment for relocation " + S);
+ if ((V & (N - 1)) != 0)
+ error("improper alignment for relocation " + getRelName(Type));
}
-template <class ELFT> bool isGnuIFunc(const SymbolBody &S) {
- if (auto *SS = dyn_cast<DefinedElf<ELFT>>(&S))
- return SS->Sym.getType() == STT_GNU_IFUNC;
- return false;
+static void errorDynRel(uint32_t Type) {
+ error("relocation " + getRelName(Type) +
+ " cannot be used against shared object; recompile with -fPIC.");
}
-template bool isGnuIFunc<ELF32LE>(const SymbolBody &S);
-template bool isGnuIFunc<ELF32BE>(const SymbolBody &S);
-template bool isGnuIFunc<ELF64LE>(const SymbolBody &S);
-template bool isGnuIFunc<ELF64BE>(const SymbolBody &S);
-
namespace {
class X86TargetInfo final : public TargetInfo {
public:
X86TargetInfo();
- void writeGotPltHeaderEntries(uint8_t *Buf) const override;
- unsigned getDynReloc(unsigned Type) const override;
- unsigned getTlsGotReloc(unsigned Type) const override;
- bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
- void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
- void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const override;
- void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const override;
- bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsDynRelative(unsigned Type) const override;
- bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
- void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
- uint64_t SA, uint64_t ZA = 0,
- uint8_t *PairedLoc = nullptr) const override;
- bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override;
- unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
- uint64_t P, uint64_t SA,
- const SymbolBody &S) const override;
- bool isGotRelative(uint32_t Type) const override;
-
-private:
- void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const;
- void relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const;
- void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const;
- void relocateTlsIeToLe(unsigned Type, uint8_t *Loc, uint8_t *BufEnd,
- uint64_t P, uint64_t SA) const;
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
+ uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override;
+ void writeGotPltHeader(uint8_t *Buf) const override;
+ uint32_t getDynRel(uint32_t Type) const override;
+ bool isTlsLocalDynamicRel(uint32_t Type) const override;
+ bool isTlsGlobalDynamicRel(uint32_t Type) const override;
+ bool isTlsInitialExecRel(uint32_t Type) const override;
+ void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
+ void writePltHeader(uint8_t *Buf) const override;
+ void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
+ int32_t Index, unsigned RelOff) const override;
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+
+ RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const override;
+ void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
};
-class X86_64TargetInfo final : public TargetInfo {
+template <class ELFT> class X86_64TargetInfo final : public TargetInfo {
public:
X86_64TargetInfo();
- bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
- void writeGotPltHeaderEntries(uint8_t *Buf) const override;
- void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
- void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const override;
- void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const override;
- bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
- void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
- uint64_t SA, uint64_t ZA = 0,
- uint8_t *PairedLoc = nullptr) const override;
- bool isRelRelative(uint32_t Type) const override;
- bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override;
- bool isSizeReloc(uint32_t Type) const override;
- unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
- uint64_t P, uint64_t SA,
- const SymbolBody &S) const override;
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
+ uint32_t getDynRel(uint32_t Type) const override;
+ bool isTlsLocalDynamicRel(uint32_t Type) const override;
+ bool isTlsGlobalDynamicRel(uint32_t Type) const override;
+ bool isTlsInitialExecRel(uint32_t Type) const override;
+ void writeGotPltHeader(uint8_t *Buf) const override;
+ void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
+ void writePltHeader(uint8_t *Buf) const override;
+ void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
+ int32_t Index, unsigned RelOff) const override;
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+
+ RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const override;
+ void relaxGot(uint8_t *Loc, uint64_t Val) const override;
+ void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
private:
- void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const;
- void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const;
- void relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const;
- void relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const;
+ void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
+ uint8_t ModRm) const;
};
class PPCTargetInfo final : public TargetInfo {
public:
PPCTargetInfo();
- void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
- void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const override;
- void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const override;
- bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
- void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
- uint64_t SA, uint64_t ZA = 0,
- uint8_t *PairedLoc = nullptr) const override;
- bool isRelRelative(uint32_t Type) const override;
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
};
class PPC64TargetInfo final : public TargetInfo {
public:
PPC64TargetInfo();
- void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
- void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const override;
- void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const override;
- bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
- void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
- uint64_t SA, uint64_t ZA = 0,
- uint8_t *PairedLoc = nullptr) const override;
- bool isRelRelative(uint32_t Type) const override;
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
+ void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
+ int32_t Index, unsigned RelOff) const override;
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
};
class AArch64TargetInfo final : public TargetInfo {
public:
AArch64TargetInfo();
- unsigned getDynReloc(unsigned Type) const override;
- void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
- void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const override;
- void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const override;
- unsigned getTlsGotReloc(unsigned Type = -1) const override;
- bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
- bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
- void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
- uint64_t SA, uint64_t ZA = 0,
- uint8_t *PairedLoc = nullptr) const override;
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
+ uint32_t getDynRel(uint32_t Type) const override;
+ bool isTlsInitialExecRel(uint32_t Type) const override;
+ void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
+ void writePltHeader(uint8_t *Buf) const override;
+ void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
+ int32_t Index, unsigned RelOff) const override;
+ bool usesOnlyLowPageBits(uint32_t Type) const override;
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const override;
+ void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
};
class AMDGPUTargetInfo final : public TargetInfo {
public:
AMDGPUTargetInfo();
- void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
- void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const override;
- void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const override;
- bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
- void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
- uint64_t SA, uint64_t ZA = 0,
- uint8_t *PairedLoc = nullptr) const override;
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
+};
+
+class ARMTargetInfo final : public TargetInfo {
+public:
+ ARMTargetInfo();
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
+ uint32_t getDynRel(uint32_t Type) const override;
+ uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override;
+ void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
+ void writePltHeader(uint8_t *Buf) const override;
+ void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
+ int32_t Index, unsigned RelOff) const override;
+ RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType,
+ const InputFile &File,
+ const SymbolBody &S) const override;
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
};
template <class ELFT> class MipsTargetInfo final : public TargetInfo {
public:
MipsTargetInfo();
- void writeGotHeaderEntries(uint8_t *Buf) const override;
- void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
- void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const override;
- void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const override;
- bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
- bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
- void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
- uint64_t SA, uint64_t ZA = 0,
- uint8_t *PairedLoc = nullptr) const override;
- bool isRelRelative(uint32_t Type) const override;
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
+ uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override;
+ uint32_t getDynRel(uint32_t Type) const override;
+ bool isTlsLocalDynamicRel(uint32_t Type) const override;
+ bool isTlsGlobalDynamicRel(uint32_t Type) const override;
+ void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
+ void writePltHeader(uint8_t *Buf) const override;
+ void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
+ int32_t Index, unsigned RelOff) const override;
+ RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType,
+ const InputFile &File,
+ const SymbolBody &S) const override;
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ bool usesOnlyLowPageBits(uint32_t Type) const override;
};
} // anonymous namespace
@@ -251,80 +216,153 @@ TargetInfo *createTarget() {
return new AArch64TargetInfo();
case EM_AMDGPU:
return new AMDGPUTargetInfo();
+ case EM_ARM:
+ return new ARMTargetInfo();
case EM_MIPS:
switch (Config->EKind) {
case ELF32LEKind:
return new MipsTargetInfo<ELF32LE>();
case ELF32BEKind:
return new MipsTargetInfo<ELF32BE>();
+ case ELF64LEKind:
+ return new MipsTargetInfo<ELF64LE>();
+ case ELF64BEKind:
+ return new MipsTargetInfo<ELF64BE>();
default:
- error("Unsupported MIPS target");
+ fatal("unsupported MIPS target");
}
case EM_PPC:
return new PPCTargetInfo();
case EM_PPC64:
return new PPC64TargetInfo();
case EM_X86_64:
- return new X86_64TargetInfo();
+ if (Config->EKind == ELF32LEKind)
+ return new X86_64TargetInfo<ELF32LE>();
+ return new X86_64TargetInfo<ELF64LE>();
}
- error("Unknown target machine");
+ fatal("unknown target machine");
}
TargetInfo::~TargetInfo() {}
-bool TargetInfo::isTlsOptimized(unsigned Type, const SymbolBody *S) const {
- return false;
+uint64_t TargetInfo::getImplicitAddend(const uint8_t *Buf,
+ uint32_t Type) const {
+ return 0;
}
-uint64_t TargetInfo::getVAStart() const { return Config->Shared ? 0 : VAStart; }
+bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; }
-bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
+RelExpr TargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
+ const InputFile &File,
+ const SymbolBody &S) const {
+ return Expr;
+}
+
+bool TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return false; }
+
+bool TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const { return false; }
+
+bool TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const {
return false;
}
-bool TargetInfo::isGotRelative(uint32_t Type) const { return false; }
+RelExpr TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const {
+ return Expr;
+}
-bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
+void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {
+ llvm_unreachable("Should not have claimed to be relaxable");
+}
-bool TargetInfo::isSizeReloc(uint32_t Type) const { return false; }
+void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ llvm_unreachable("Should not have claimed to be relaxable");
+}
-unsigned TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
- uint32_t Type, uint64_t P, uint64_t SA,
- const SymbolBody &S) const {
- return 0;
+void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ llvm_unreachable("Should not have claimed to be relaxable");
}
-void TargetInfo::writeGotHeaderEntries(uint8_t *Buf) const {}
+void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ llvm_unreachable("Should not have claimed to be relaxable");
+}
-void TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {}
+void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ llvm_unreachable("Should not have claimed to be relaxable");
+}
X86TargetInfo::X86TargetInfo() {
- CopyReloc = R_386_COPY;
- PCRelReloc = R_386_PC32;
- GotReloc = R_386_GLOB_DAT;
- PltReloc = R_386_JUMP_SLOT;
- IRelativeReloc = R_386_IRELATIVE;
- RelativeReloc = R_386_RELATIVE;
- TlsGotReloc = R_386_TLS_TPOFF;
- TlsGlobalDynamicReloc = R_386_TLS_GD;
- TlsLocalDynamicReloc = R_386_TLS_LDM;
- TlsModuleIndexReloc = R_386_TLS_DTPMOD32;
- TlsOffsetReloc = R_386_TLS_DTPOFF32;
- LazyRelocations = true;
+ CopyRel = R_386_COPY;
+ GotRel = R_386_GLOB_DAT;
+ PltRel = R_386_JUMP_SLOT;
+ IRelativeRel = R_386_IRELATIVE;
+ RelativeRel = R_386_RELATIVE;
+ TlsGotRel = R_386_TLS_TPOFF;
+ TlsModuleIndexRel = R_386_TLS_DTPMOD32;
+ TlsOffsetRel = R_386_TLS_DTPOFF32;
+ GotEntrySize = 4;
+ GotPltEntrySize = 4;
PltEntrySize = 16;
- PltZeroEntrySize = 16;
+ PltHeaderSize = 16;
+ TlsGdRelaxSkip = 2;
}
-void X86TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {
+RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
+ switch (Type) {
+ default:
+ return R_ABS;
+ case R_386_TLS_GD:
+ return R_TLSGD;
+ case R_386_TLS_LDM:
+ return R_TLSLD;
+ case R_386_PLT32:
+ return R_PLT_PC;
+ case R_386_PC32:
+ return R_PC;
+ case R_386_GOTPC:
+ return R_GOTONLY_PC;
+ case R_386_TLS_IE:
+ return R_GOT;
+ case R_386_GOT32:
+ case R_386_GOT32X:
+ case R_386_TLS_GOTIE:
+ return R_GOT_FROM_END;
+ case R_386_GOTOFF:
+ return R_GOTREL;
+ case R_386_TLS_LE:
+ return R_TLS;
+ case R_386_TLS_LE_32:
+ return R_NEG_TLS;
+ }
+}
+
+RelExpr X86TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const {
+ switch (Expr) {
+ default:
+ return Expr;
+ case R_RELAX_TLS_GD_TO_IE:
+ return R_RELAX_TLS_GD_TO_IE_END;
+ case R_RELAX_TLS_GD_TO_LE:
+ return R_RELAX_TLS_GD_TO_LE_NEG;
+ }
+}
+
+void X86TargetInfo::writeGotPltHeader(uint8_t *Buf) const {
write32le(Buf, Out<ELF32LE>::Dynamic->getVA());
}
-void X86TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
- // Skip 6 bytes of "pushl (GOT+4)"
- write32le(Buf, Plt + 6);
+void X86TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {
+ // Entries in .got.plt initially points back to the corresponding
+ // PLT entries with a fixed offset to skip the first instruction.
+ write32le(Buf, S.getPltVA<ELF32LE>() + 6);
}
-unsigned X86TargetInfo::getDynReloc(unsigned Type) const {
+uint32_t X86TargetInfo::getDynRel(uint32_t Type) const {
if (Type == R_386_TLS_LE)
return R_386_TLS_TPOFF;
if (Type == R_386_TLS_LE_32)
@@ -332,30 +370,26 @@ unsigned X86TargetInfo::getDynReloc(unsigned Type) const {
return Type;
}
-unsigned X86TargetInfo::getTlsGotReloc(unsigned Type) const {
- if (Type == R_386_TLS_IE)
- return Type;
- return TlsGotReloc;
+bool X86TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const {
+ return Type == R_386_TLS_GD;
}
-bool X86TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
- if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 ||
- Type == R_386_TLS_GOTIE)
- return Config->Shared;
- if (Type == R_386_TLS_IE)
- return canBePreempted(&S, true);
- return Type == R_386_TLS_GD;
+bool X86TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const {
+ return Type == R_386_TLS_LDO_32 || Type == R_386_TLS_LDM;
}
-void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const {
+bool X86TargetInfo::isTlsInitialExecRel(uint32_t Type) const {
+ return Type == R_386_TLS_IE || Type == R_386_TLS_GOTIE;
+}
+
+void X86TargetInfo::writePltHeader(uint8_t *Buf) const {
// Executable files and shared object files have
// separate procedure linkage tables.
- if (Config->Shared) {
+ if (Config->Pic) {
const uint8_t V[] = {
0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx)
- 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx)
- 0x90, 0x90, 0x90, 0x90 // nop;nop;nop;nop
+ 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx)
+ 0x90, 0x90, 0x90, 0x90 // nop; nop; nop; nop
};
memcpy(Buf, V, sizeof(V));
return;
@@ -363,283 +397,229 @@ void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
const uint8_t PltData[] = {
0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushl (GOT+4)
- 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *(GOT+8)
- 0x90, 0x90, 0x90, 0x90 // nop;nop;nop;nop
+ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *(GOT+8)
+ 0x90, 0x90, 0x90, 0x90 // nop; nop; nop; nop
};
memcpy(Buf, PltData, sizeof(PltData));
- write32le(Buf + 2, GotEntryAddr + 4); // GOT+4
- write32le(Buf + 8, GotEntryAddr + 8); // GOT+8
+ uint32_t Got = Out<ELF32LE>::GotPlt->getVA();
+ write32le(Buf + 2, Got + 4);
+ write32le(Buf + 8, Got + 8);
}
-void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
- uint64_t GotEntryAddr, uint64_t PltEntryAddr,
- int32_t Index, unsigned RelOff) const {
+void X86TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {
const uint8_t Inst[] = {
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // jmp *foo_in_GOT|*foo@GOT(%ebx)
0x68, 0x00, 0x00, 0x00, 0x00, // pushl $reloc_offset
0xe9, 0x00, 0x00, 0x00, 0x00 // jmp .PLT0@PC
};
memcpy(Buf, Inst, sizeof(Inst));
+
// jmp *foo@GOT(%ebx) or jmp *foo_in_GOT
- Buf[1] = Config->Shared ? 0xa3 : 0x25;
- write32le(Buf + 2, Config->Shared ? (GotEntryAddr - GotAddr) : GotEntryAddr);
+ Buf[1] = Config->Pic ? 0xa3 : 0x25;
+ uint32_t Got = Out<ELF32LE>::GotPlt->getVA();
+ write32le(Buf + 2, Config->Shared ? GotEntryAddr - Got : GotEntryAddr);
write32le(Buf + 7, RelOff);
- write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16);
+ write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
}
-bool X86TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
- if (Type == R_386_32 || Type == R_386_16 || Type == R_386_8)
- if (auto *SS = dyn_cast<SharedSymbol<ELF32LE>>(&S))
- return SS->Sym.getType() == STT_OBJECT;
- return false;
-}
-
-bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
- if (S.isTls() && Type == R_386_TLS_GD)
- return Target->isTlsOptimized(Type, &S) && canBePreempted(&S, true);
- if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
- return !isTlsOptimized(Type, &S);
- return Type == R_386_GOT32 || relocNeedsPlt(Type, S);
-}
-
-bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
- return isGnuIFunc<ELF32LE>(S) ||
- (Type == R_386_PLT32 && canBePreempted(&S, true)) ||
- (Type == R_386_PC32 && S.isShared());
-}
-
-bool X86TargetInfo::isGotRelative(uint32_t Type) const {
- // This relocation does not require got entry,
- // but it is relative to got and needs it to be created.
- // Here we request for that.
- return Type == R_386_GOTOFF;
-}
-
-void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
- uint64_t P, uint64_t SA, uint64_t ZA,
- uint8_t *PairedLoc) const {
+uint64_t X86TargetInfo::getImplicitAddend(const uint8_t *Buf,
+ uint32_t Type) const {
switch (Type) {
+ default:
+ return 0;
case R_386_32:
- add32le(Loc, SA);
- break;
case R_386_GOT32:
+ case R_386_GOT32X:
case R_386_GOTOFF:
- add32le(Loc, SA - Out<ELF32LE>::Got->getVA());
- break;
case R_386_GOTPC:
- add32le(Loc, SA + Out<ELF32LE>::Got->getVA() - P);
- break;
case R_386_PC32:
case R_386_PLT32:
- add32le(Loc, SA - P);
- break;
- case R_386_TLS_GD:
- case R_386_TLS_LDM:
- case R_386_TLS_TPOFF: {
- uint64_t V = SA - Out<ELF32LE>::Got->getVA() -
- Out<ELF32LE>::Got->getNumEntries() * 4;
- checkInt<32>(V, Type);
- write32le(Loc, V);
- break;
+ return read32le(Buf);
}
- case R_386_TLS_IE:
- case R_386_TLS_LDO_32:
- write32le(Loc, SA);
- break;
- case R_386_TLS_LE:
- write32le(Loc, SA - Out<ELF32LE>::TlsPhdr->p_memsz);
- break;
- case R_386_TLS_LE_32:
- write32le(Loc, Out<ELF32LE>::TlsPhdr->p_memsz - SA);
- break;
- default:
- error("unrecognized reloc " + Twine(Type));
- }
-}
-
-bool X86TargetInfo::isTlsOptimized(unsigned Type, const SymbolBody *S) const {
- if (Config->Shared || (S && !S->isTls()))
- return false;
- return Type == R_386_TLS_LDO_32 || Type == R_386_TLS_LDM ||
- Type == R_386_TLS_GD ||
- (Type == R_386_TLS_IE && !canBePreempted(S, true)) ||
- (Type == R_386_TLS_GOTIE && !canBePreempted(S, true));
}
-bool X86TargetInfo::relocNeedsDynRelative(unsigned Type) const {
- return Config->Shared && Type == R_386_TLS_IE;
+void X86TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ checkInt<32>(Val, Type);
+ write32le(Loc, Val);
}
-unsigned X86TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
- uint32_t Type, uint64_t P,
- uint64_t SA,
- const SymbolBody &S) const {
- switch (Type) {
- case R_386_TLS_GD:
- if (canBePreempted(&S, true))
- relocateTlsGdToIe(Loc, BufEnd, P, SA);
- else
- relocateTlsGdToLe(Loc, BufEnd, P, SA);
- // The next relocation should be against __tls_get_addr, so skip it
- return 1;
- case R_386_TLS_GOTIE:
- case R_386_TLS_IE:
- relocateTlsIeToLe(Type, Loc, BufEnd, P, SA);
- return 0;
- case R_386_TLS_LDM:
- relocateTlsLdToLe(Loc, BufEnd, P, SA);
- // The next relocation should be against __tls_get_addr, so skip it
- return 1;
- case R_386_TLS_LDO_32:
- relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
- return 0;
- }
- llvm_unreachable("Unknown TLS optimization");
-}
-
-// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.1
-// IA-32 Linker Optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
-// how GD can be optimized to IE:
-// leal x@tlsgd(, %ebx, 1),
-// call __tls_get_addr@plt
-// Is converted to:
-// movl %gs:0, %eax
-// addl x@gotntpoff(%ebx), %eax
-void X86TargetInfo::relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const {
+void X86TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ // Convert
+ // leal x@tlsgd(, %ebx, 1),
+ // call __tls_get_addr@plt
+ // to
+ // movl %gs:0,%eax
+ // subl $x@ntpoff,%eax
const uint8_t Inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
- 0x03, 0x83, 0x00, 0x00, 0x00, 0x00 // addl 0(%ebx), %eax
+ 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
- relocateOne(Loc + 5, BufEnd, R_386_32, P,
- SA - Out<ELF32LE>::Got->getVA() -
- Out<ELF32LE>::Got->getNumEntries() * 4);
-}
-
-// GD can be optimized to LE:
-// leal x@tlsgd(, %ebx, 1),
-// call __tls_get_addr@plt
-// Can be converted to:
-// movl %gs:0,%eax
-// addl $x@ntpoff,%eax
-// But gold emits subl $foo@tpoff,%eax instead of addl.
-// These instructions are completely equal in behavior.
-// This method generates subl to be consistent with gold.
-void X86TargetInfo::relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const {
+ relocateOne(Loc + 5, R_386_32, Val);
+}
+
+void X86TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ // Convert
+ // leal x@tlsgd(, %ebx, 1),
+ // call __tls_get_addr@plt
+ // to
+ // movl %gs:0, %eax
+ // addl x@gotntpoff(%ebx), %eax
const uint8_t Inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
- 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax
+ 0x03, 0x83, 0x00, 0x00, 0x00, 0x00 // addl 0(%ebx), %eax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
- relocateOne(Loc + 5, BufEnd, R_386_32, P,
- Out<ELF32LE>::TlsPhdr->p_memsz - SA);
-}
-
-// LD can be optimized to LE:
-// leal foo(%reg),%eax
-// call ___tls_get_addr
-// Is converted to:
-// movl %gs:0,%eax
-// nop
-// leal 0(%esi,1),%esi
-void X86TargetInfo::relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const {
- const uint8_t Inst[] = {
- 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
- 0x90, // nop
- 0x8d, 0x74, 0x26, 0x00 // leal 0(%esi,1),%esi
- };
- memcpy(Loc - 2, Inst, sizeof(Inst));
+ relocateOne(Loc + 5, R_386_32, Val);
}
// In some conditions, relocations can be optimized to avoid using GOT.
// This function does that for Initial Exec to Local Exec case.
-// Read "ELF Handling For Thread-Local Storage, 5.1
-// IA-32 Linker Optimizations" (http://www.akkadia.org/drepper/tls.pdf)
-// by Ulrich Drepper for details.
-void X86TargetInfo::relocateTlsIeToLe(unsigned Type, uint8_t *Loc,
- uint8_t *BufEnd, uint64_t P,
- uint64_t SA) const {
+void X86TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
// Ulrich's document section 6.2 says that @gotntpoff can
// be used with MOVL or ADDL instructions.
// @indntpoff is similar to @gotntpoff, but for use in
// position dependent code.
- uint8_t *Inst = Loc - 2;
- uint8_t *Op = Loc - 1;
uint8_t Reg = (Loc[-1] >> 3) & 7;
- bool IsMov = *Inst == 0x8b;
+
if (Type == R_386_TLS_IE) {
- // For R_386_TLS_IE relocation we perform the next transformations:
- // MOVL foo@INDNTPOFF,%EAX is transformed to MOVL $foo,%EAX
- // MOVL foo@INDNTPOFF,%REG is transformed to MOVL $foo,%REG
- // ADDL foo@INDNTPOFF,%REG is transformed to ADDL $foo,%REG
- // First one is special because when EAX is used the sequence is 5 bytes
- // long, otherwise it is 6 bytes.
- if (*Op == 0xa1) {
- *Op = 0xb8;
+ if (Loc[-1] == 0xa1) {
+ // "movl foo@indntpoff,%eax" -> "movl $foo,%eax"
+ // This case is different from the generic case below because
+ // this is a 5 byte instruction while below is 6 bytes.
+ Loc[-1] = 0xb8;
+ } else if (Loc[-2] == 0x8b) {
+ // "movl foo@indntpoff,%reg" -> "movl $foo,%reg"
+ Loc[-2] = 0xc7;
+ Loc[-1] = 0xc0 | Reg;
} else {
- *Inst = IsMov ? 0xc7 : 0x81;
- *Op = 0xc0 | ((*Op >> 3) & 7);
+ // "addl foo@indntpoff,%reg" -> "addl $foo,%reg"
+ Loc[-2] = 0x81;
+ Loc[-1] = 0xc0 | Reg;
}
} else {
- // R_386_TLS_GOTIE relocation can be optimized to
- // R_386_TLS_LE so that it does not use GOT.
- // "MOVL foo@GOTTPOFF(%RIP), %REG" is transformed to "MOVL $foo, %REG".
- // "ADDL foo@GOTNTPOFF(%RIP), %REG" is transformed to "LEAL foo(%REG), %REG"
- // Note: gold converts to ADDL instead of LEAL.
- *Inst = IsMov ? 0xc7 : 0x8d;
- if (IsMov)
- *Op = 0xc0 | ((*Op >> 3) & 7);
- else
- *Op = 0x80 | Reg | (Reg << 3);
+ assert(Type == R_386_TLS_GOTIE);
+ if (Loc[-2] == 0x8b) {
+ // "movl foo@gottpoff(%rip),%reg" -> "movl $foo,%reg"
+ Loc[-2] = 0xc7;
+ Loc[-1] = 0xc0 | Reg;
+ } else {
+ // "addl foo@gotntpoff(%rip),%reg" -> "leal foo(%reg),%reg"
+ Loc[-2] = 0x8d;
+ Loc[-1] = 0x80 | (Reg << 3) | Reg;
+ }
+ }
+ relocateOne(Loc, R_386_TLS_LE, Val);
+}
+
+void X86TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ if (Type == R_386_TLS_LDO_32) {
+ relocateOne(Loc, R_386_TLS_LE, Val);
+ return;
}
- relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
-}
-
-X86_64TargetInfo::X86_64TargetInfo() {
- CopyReloc = R_X86_64_COPY;
- PCRelReloc = R_X86_64_PC32;
- GotReloc = R_X86_64_GLOB_DAT;
- PltReloc = R_X86_64_JUMP_SLOT;
- RelativeReloc = R_X86_64_RELATIVE;
- IRelativeReloc = R_X86_64_IRELATIVE;
- TlsGotReloc = R_X86_64_TPOFF64;
- TlsLocalDynamicReloc = R_X86_64_TLSLD;
- TlsGlobalDynamicReloc = R_X86_64_TLSGD;
- TlsModuleIndexReloc = R_X86_64_DTPMOD64;
- TlsOffsetReloc = R_X86_64_DTPOFF64;
- LazyRelocations = true;
+
+ // Convert
+ // leal foo(%reg),%eax
+ // call ___tls_get_addr
+ // to
+ // movl %gs:0,%eax
+ // nop
+ // leal 0(%esi,1),%esi
+ const uint8_t Inst[] = {
+ 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
+ 0x90, // nop
+ 0x8d, 0x74, 0x26, 0x00 // leal 0(%esi,1),%esi
+ };
+ memcpy(Loc - 2, Inst, sizeof(Inst));
+}
+
+template <class ELFT> X86_64TargetInfo<ELFT>::X86_64TargetInfo() {
+ CopyRel = R_X86_64_COPY;
+ GotRel = R_X86_64_GLOB_DAT;
+ PltRel = R_X86_64_JUMP_SLOT;
+ RelativeRel = R_X86_64_RELATIVE;
+ IRelativeRel = R_X86_64_IRELATIVE;
+ TlsGotRel = R_X86_64_TPOFF64;
+ TlsModuleIndexRel = R_X86_64_DTPMOD64;
+ TlsOffsetRel = R_X86_64_DTPOFF64;
+ GotEntrySize = 8;
+ GotPltEntrySize = 8;
PltEntrySize = 16;
- PltZeroEntrySize = 16;
+ PltHeaderSize = 16;
+ TlsGdRelaxSkip = 2;
}
-void X86_64TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {
- write64le(Buf, Out<ELF64LE>::Dynamic->getVA());
+template <class ELFT>
+RelExpr X86_64TargetInfo<ELFT>::getRelExpr(uint32_t Type,
+ const SymbolBody &S) const {
+ switch (Type) {
+ default:
+ return R_ABS;
+ case R_X86_64_TPOFF32:
+ return R_TLS;
+ case R_X86_64_TLSLD:
+ return R_TLSLD_PC;
+ case R_X86_64_TLSGD:
+ return R_TLSGD_PC;
+ case R_X86_64_SIZE32:
+ case R_X86_64_SIZE64:
+ return R_SIZE;
+ case R_X86_64_PLT32:
+ return R_PLT_PC;
+ case R_X86_64_PC32:
+ case R_X86_64_PC64:
+ return R_PC;
+ case R_X86_64_GOT32:
+ return R_GOT_FROM_END;
+ case R_X86_64_GOTPCREL:
+ case R_X86_64_GOTPCRELX:
+ case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_GOTTPOFF:
+ return R_GOT_PC;
+ }
}
-void X86_64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
- // Skip 6 bytes of "jmpq *got(%rip)"
- write32le(Buf, Plt + 6);
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
+ // The first entry holds the value of _DYNAMIC. It is not clear why that is
+ // required, but it is documented in the psabi and the glibc dynamic linker
+ // seems to use it (note that this is relevant for linking ld.so, not any
+ // other program).
+ write64le(Buf, Out<ELFT>::Dynamic->getVA());
}
-void X86_64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const {
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::writeGotPlt(uint8_t *Buf,
+ const SymbolBody &S) const {
+ // See comments in X86TargetInfo::writeGotPlt.
+ write32le(Buf, S.getPltVA<ELFT>() + 6);
+}
+
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::writePltHeader(uint8_t *Buf) const {
const uint8_t PltData[] = {
0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip)
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip)
0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax)
};
memcpy(Buf, PltData, sizeof(PltData));
- write32le(Buf + 2, GotEntryAddr - PltEntryAddr + 2); // GOT+8
- write32le(Buf + 8, GotEntryAddr - PltEntryAddr + 4); // GOT+16
+ uint64_t Got = Out<ELFT>::GotPlt->getVA();
+ uint64_t Plt = Out<ELFT>::Plt->getVA();
+ write32le(Buf + 2, Got - Plt + 2); // GOT+8
+ write32le(Buf + 8, Got - Plt + 4); // GOT+16
}
-void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
- uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const {
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {
const uint8_t Inst[] = {
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
@@ -649,277 +629,318 @@ void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
write32le(Buf + 2, GotEntryAddr - PltEntryAddr - 6);
write32le(Buf + 7, Index);
- write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16);
-}
-
-bool X86_64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
- if (Type == R_X86_64_32S || Type == R_X86_64_32 || Type == R_X86_64_PC32 ||
- Type == R_X86_64_64)
- if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S))
- return SS->Sym.getType() == STT_OBJECT;
- return false;
-}
-
-bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
- if (Type == R_X86_64_TLSGD)
- return Target->isTlsOptimized(Type, &S) && canBePreempted(&S, true);
- if (Type == R_X86_64_GOTTPOFF)
- return !isTlsOptimized(Type, &S);
- return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S);
-}
-
-bool X86_64TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
- return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
+ write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
}
-bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
- if (needsCopyRel(Type, S))
- return false;
- if (isGnuIFunc<ELF64LE>(S))
- return true;
-
- switch (Type) {
- default:
- return false;
- case R_X86_64_32:
- case R_X86_64_64:
- case R_X86_64_PC32:
- // This relocation is defined to have a value of (S + A - P).
- // The problems start when a non PIC program calls a function in a shared
- // library.
- // In an ideal world, we could just report an error saying the relocation
- // can overflow at runtime.
- // In the real world with glibc, crt1.o has a R_X86_64_PC32 pointing to
- // libc.so.
- //
- // The general idea on how to handle such cases is to create a PLT entry
- // and use that as the function value.
- //
- // For the static linking part, we just return true and everything else
- // will use the the PLT entry as the address.
- //
- // The remaining (unimplemented) problem is making sure pointer equality
- // still works. We need the help of the dynamic linker for that. We
- // let it know that we have a direct reference to a so symbol by creating
- // an undefined symbol with a non zero st_value. Seeing that, the
- // dynamic linker resolves the symbol to the value of the symbol we created.
- // This is true even for got entries, so pointer equality is maintained.
- // To avoid an infinite loop, the only entry that points to the
- // real function is a dedicated got entry used by the plt. That is
- // identified by special relocation types (R_X86_64_JUMP_SLOT,
- // R_386_JMP_SLOT, etc).
- return S.isShared();
- case R_X86_64_PLT32:
- return canBePreempted(&S, true);
- }
+template <class ELFT>
+uint32_t X86_64TargetInfo<ELFT>::getDynRel(uint32_t Type) const {
+ if (Type == R_X86_64_PC32 || Type == R_X86_64_32)
+ errorDynRel(Type);
+ return Type;
}
-bool X86_64TargetInfo::isRelRelative(uint32_t Type) const {
- switch (Type) {
- default:
- return false;
- case R_X86_64_DTPOFF32:
- case R_X86_64_DTPOFF64:
- case R_X86_64_PC8:
- case R_X86_64_PC16:
- case R_X86_64_PC32:
- case R_X86_64_PC64:
- case R_X86_64_PLT32:
- return true;
- }
+template <class ELFT>
+bool X86_64TargetInfo<ELFT>::isTlsInitialExecRel(uint32_t Type) const {
+ return Type == R_X86_64_GOTTPOFF;
}
-bool X86_64TargetInfo::isSizeReloc(uint32_t Type) const {
- return Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64;
+template <class ELFT>
+bool X86_64TargetInfo<ELFT>::isTlsGlobalDynamicRel(uint32_t Type) const {
+ return Type == R_X86_64_TLSGD;
}
-bool X86_64TargetInfo::isTlsOptimized(unsigned Type,
- const SymbolBody *S) const {
- if (Config->Shared || (S && !S->isTls()))
- return false;
- return Type == R_X86_64_TLSGD || Type == R_X86_64_TLSLD ||
- Type == R_X86_64_DTPOFF32 ||
- (Type == R_X86_64_GOTTPOFF && !canBePreempted(S, true));
-}
-
-// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
-// x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
-// how LD can be optimized to LE:
-// leaq bar@tlsld(%rip), %rdi
-// callq __tls_get_addr@PLT
-// leaq bar@dtpoff(%rax), %rcx
-// Is converted to:
-// .word 0x6666
-// .byte 0x66
-// mov %fs:0,%rax
-// leaq bar@tpoff(%rax), %rcx
-void X86_64TargetInfo::relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd,
- uint64_t P, uint64_t SA) const {
- const uint8_t Inst[] = {
- 0x66, 0x66, //.word 0x6666
- 0x66, //.byte 0x66
- 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax
- };
- memcpy(Loc - 3, Inst, sizeof(Inst));
+template <class ELFT>
+bool X86_64TargetInfo<ELFT>::isTlsLocalDynamicRel(uint32_t Type) const {
+ return Type == R_X86_64_DTPOFF32 || Type == R_X86_64_DTPOFF64 ||
+ Type == R_X86_64_TLSLD;
}
-// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
-// x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
-// how GD can be optimized to LE:
-// .byte 0x66
-// leaq x@tlsgd(%rip), %rdi
-// .word 0x6666
-// rex64
-// call __tls_get_addr@plt
-// Is converted to:
-// mov %fs:0x0,%rax
-// lea x@tpoff,%rax
-void X86_64TargetInfo::relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd,
- uint64_t P, uint64_t SA) const {
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ // Convert
+ // .byte 0x66
+ // leaq x@tlsgd(%rip), %rdi
+ // .word 0x6666
+ // rex64
+ // call __tls_get_addr@plt
+ // to
+ // mov %fs:0x0,%rax
+ // lea x@tpoff,%rax
const uint8_t Inst[] = {
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff,%rax
};
memcpy(Loc - 4, Inst, sizeof(Inst));
- relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF32, P, SA);
-}
-
-// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
-// x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
-// how GD can be optimized to IE:
-// .byte 0x66
-// leaq x@tlsgd(%rip), %rdi
-// .word 0x6666
-// rex64
-// call __tls_get_addr@plt
-// Is converted to:
-// mov %fs:0x0,%rax
-// addq x@tpoff,%rax
-void X86_64TargetInfo::relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd,
- uint64_t P, uint64_t SA) const {
+ // The original code used a pc relative relocation and so we have to
+ // compensate for the -4 in had in the addend.
+ relocateOne(Loc + 8, R_X86_64_TPOFF32, Val + 4);
+}
+
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ // Convert
+ // .byte 0x66
+ // leaq x@tlsgd(%rip), %rdi
+ // .word 0x6666
+ // rex64
+ // call __tls_get_addr@plt
+ // to
+ // mov %fs:0x0,%rax
+ // addq x@tpoff,%rax
const uint8_t Inst[] = {
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax
};
memcpy(Loc - 4, Inst, sizeof(Inst));
- relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF64, P + 12, SA);
+ // Both code sequences are PC relatives, but since we are moving the constant
+ // forward by 8 bytes we have to subtract the value by 8.
+ relocateOne(Loc + 8, R_X86_64_PC32, Val - 8);
}
// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
// R_X86_64_TPOFF32 so that it does not use GOT.
-// This function does that. Read "ELF Handling For Thread-Local Storage,
-// 5.5 x86-x64 linker optimizations" (http://www.akkadia.org/drepper/tls.pdf)
-// by Ulrich Drepper for details.
-void X86_64TargetInfo::relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd,
- uint64_t P, uint64_t SA) const {
- // Ulrich's document section 6.5 says that @gottpoff(%rip) must be
- // used in MOVQ or ADDQ instructions only.
- // "MOVQ foo@GOTTPOFF(%RIP), %REG" is transformed to "MOVQ $foo, %REG".
- // "ADDQ foo@GOTTPOFF(%RIP), %REG" is transformed to "LEAQ foo(%REG), %REG"
- // (if the register is not RSP/R12) or "ADDQ $foo, %RSP".
- // Opcodes info can be found at http://ref.x86asm.net/coder64.html#x48.
- uint8_t *Prefix = Loc - 3;
- uint8_t *Inst = Loc - 2;
- uint8_t *RegSlot = Loc - 1;
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ uint8_t *Inst = Loc - 3;
uint8_t Reg = Loc[-1] >> 3;
- bool IsMov = *Inst == 0x8b;
- bool RspAdd = !IsMov && Reg == 4;
- // r12 and rsp registers requires special handling.
- // Problem is that for other registers, for example leaq 0xXXXXXXXX(%r11),%r11
- // result out is 7 bytes: 4d 8d 9b XX XX XX XX,
- // but leaq 0xXXXXXXXX(%r12),%r12 is 8 bytes: 4d 8d a4 24 XX XX XX XX.
- // The same true for rsp. So we convert to addq for them, saving 1 byte that
- // we dont have.
- if (RspAdd)
- *Inst = 0x81;
- else
- *Inst = IsMov ? 0xc7 : 0x8d;
- if (*Prefix == 0x4c)
- *Prefix = (IsMov || RspAdd) ? 0x49 : 0x4d;
- *RegSlot = (IsMov || RspAdd) ? (0xc0 | Reg) : (0x80 | Reg | (Reg << 3));
- relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA);
-}
-
-// This function applies a TLS relocation with an optimization as described
-// in the Ulrich's document. As a result of rewriting instructions at the
-// relocation target, relocations immediately follow the TLS relocation (which
-// would be applied to rewritten instructions) may have to be skipped.
-// This function returns a number of relocations that need to be skipped.
-unsigned X86_64TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
- uint32_t Type, uint64_t P,
- uint64_t SA,
- const SymbolBody &S) const {
- switch (Type) {
- case R_X86_64_DTPOFF32:
- relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA);
- return 0;
- case R_X86_64_GOTTPOFF:
- relocateTlsIeToLe(Loc, BufEnd, P, SA);
- return 0;
- case R_X86_64_TLSGD: {
- if (canBePreempted(&S, true))
- relocateTlsGdToIe(Loc, BufEnd, P, SA);
- else
- relocateTlsGdToLe(Loc, BufEnd, P, SA);
- // The next relocation should be against __tls_get_addr, so skip it
- return 1;
+ uint8_t *RegSlot = Loc - 1;
+
+ // Note that ADD with RSP or R12 is converted to ADD instead of LEA
+ // because LEA with these registers needs 4 bytes to encode and thus
+ // wouldn't fit the space.
+
+ if (memcmp(Inst, "\x48\x03\x25", 3) == 0) {
+ // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp"
+ memcpy(Inst, "\x48\x81\xc4", 3);
+ } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) {
+ // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12"
+ memcpy(Inst, "\x49\x81\xc4", 3);
+ } else if (memcmp(Inst, "\x4c\x03", 2) == 0) {
+ // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]"
+ memcpy(Inst, "\x4d\x8d", 2);
+ *RegSlot = 0x80 | (Reg << 3) | Reg;
+ } else if (memcmp(Inst, "\x48\x03", 2) == 0) {
+ // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg"
+ memcpy(Inst, "\x48\x8d", 2);
+ *RegSlot = 0x80 | (Reg << 3) | Reg;
+ } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) {
+ // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]"
+ memcpy(Inst, "\x49\xc7", 2);
+ *RegSlot = 0xc0 | Reg;
+ } else if (memcmp(Inst, "\x48\x8b", 2) == 0) {
+ // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg"
+ memcpy(Inst, "\x48\xc7", 2);
+ *RegSlot = 0xc0 | Reg;
+ } else {
+ fatal("R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only");
}
- case R_X86_64_TLSLD:
- relocateTlsLdToLe(Loc, BufEnd, P, SA);
- // The next relocation should be against __tls_get_addr, so skip it
- return 1;
+
+ // The original code used a PC relative relocation.
+ // Need to compensate for the -4 it had in the addend.
+ relocateOne(Loc, R_X86_64_TPOFF32, Val + 4);
+}
+
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ // Convert
+ // leaq bar@tlsld(%rip), %rdi
+ // callq __tls_get_addr@PLT
+ // leaq bar@dtpoff(%rax), %rcx
+ // to
+ // .word 0x6666
+ // .byte 0x66
+ // mov %fs:0,%rax
+ // leaq bar@tpoff(%rax), %rcx
+ if (Type == R_X86_64_DTPOFF64) {
+ write64le(Loc, Val);
+ return;
}
- llvm_unreachable("Unknown TLS optimization");
+ if (Type == R_X86_64_DTPOFF32) {
+ relocateOne(Loc, R_X86_64_TPOFF32, Val);
+ return;
+ }
+
+ const uint8_t Inst[] = {
+ 0x66, 0x66, // .word 0x6666
+ 0x66, // .byte 0x66
+ 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax
+ };
+ memcpy(Loc - 3, Inst, sizeof(Inst));
}
-void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
- uint64_t P, uint64_t SA, uint64_t ZA,
- uint8_t *PairedLoc) const {
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
switch (Type) {
case R_X86_64_32:
- checkUInt<32>(SA, Type);
- write32le(Loc, SA);
+ checkUInt<32>(Val, Type);
+ write32le(Loc, Val);
break;
case R_X86_64_32S:
- checkInt<32>(SA, Type);
- write32le(Loc, SA);
- break;
- case R_X86_64_64:
- write64le(Loc, SA);
- break;
- case R_X86_64_DTPOFF32:
- write32le(Loc, SA);
- break;
- case R_X86_64_DTPOFF64:
- write64le(Loc, SA);
- break;
+ case R_X86_64_TPOFF32:
+ case R_X86_64_GOT32:
case R_X86_64_GOTPCREL:
+ case R_X86_64_GOTPCRELX:
+ case R_X86_64_REX_GOTPCRELX:
case R_X86_64_PC32:
+ case R_X86_64_GOTTPOFF:
case R_X86_64_PLT32:
case R_X86_64_TLSGD:
case R_X86_64_TLSLD:
- write32le(Loc, SA - P);
- break;
+ case R_X86_64_DTPOFF32:
case R_X86_64_SIZE32:
- write32le(Loc, ZA);
- break;
- case R_X86_64_SIZE64:
- write64le(Loc, ZA);
- break;
- case R_X86_64_TPOFF32: {
- uint64_t Val = SA - Out<ELF64LE>::TlsPhdr->p_memsz;
checkInt<32>(Val, Type);
write32le(Loc, Val);
break;
- }
- case R_X86_64_TPOFF64:
- write32le(Loc, SA - P);
+ case R_X86_64_64:
+ case R_X86_64_DTPOFF64:
+ case R_X86_64_SIZE64:
+ case R_X86_64_PC64:
+ write64le(Loc, Val);
break;
default:
- error("unrecognized reloc " + Twine(Type));
+ fatal("unrecognized reloc " + Twine(Type));
}
}
+template <class ELFT>
+RelExpr X86_64TargetInfo<ELFT>::adjustRelaxExpr(uint32_t Type,
+ const uint8_t *Data,
+ RelExpr RelExpr) const {
+ if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX)
+ return RelExpr;
+ const uint8_t Op = Data[-2];
+ const uint8_t ModRm = Data[-1];
+ // FIXME: When PIC is disabled and foo is defined locally in the
+ // lower 32 bit address space, memory operand in mov can be converted into
+ // immediate operand. Otherwise, mov must be changed to lea. We support only
+ // latter relaxation at this moment.
+ if (Op == 0x8b)
+ return R_RELAX_GOT_PC;
+ // Relax call and jmp.
+ if (Op == 0xff && (ModRm == 0x15 || ModRm == 0x25))
+ return R_RELAX_GOT_PC;
+
+ // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
+ // If PIC then no relaxation is available.
+ // We also don't relax test/binop instructions without REX byte,
+ // they are 32bit operations and not common to have.
+ assert(Type == R_X86_64_REX_GOTPCRELX);
+ return Config->Pic ? RelExpr : R_RELAX_GOT_PC_NOPIC;
+}
+
+// A subset of relaxations can only be applied for no-PIC. This method
+// handles such relaxations. Instructions encoding information was taken from:
+// "Intel 64 and IA-32 Architectures Software Developer's Manual V2"
+// (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/
+// 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf)
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val,
+ uint8_t Op, uint8_t ModRm) const {
+ const uint8_t Rex = Loc[-3];
+ // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg".
+ if (Op == 0x85) {
+ // See "TEST-Logical Compare" (4-428 Vol. 2B),
+ // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension).
+
+ // ModR/M byte has form XX YYY ZZZ, where
+ // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1).
+ // XX has different meanings:
+ // 00: The operand's memory address is in reg1.
+ // 01: The operand's memory address is reg1 + a byte-sized displacement.
+ // 10: The operand's memory address is reg1 + a word-sized displacement.
+ // 11: The operand is reg1 itself.
+ // If an instruction requires only one operand, the unused reg2 field
+ // holds extra opcode bits rather than a register code
+ // 0xC0 == 11 000 000 binary.
+ // 0x38 == 00 111 000 binary.
+ // We transfer reg2 to reg1 here as operand.
+ // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3).
+ Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte.
+
+ // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32
+ // See "TEST-Logical Compare" (4-428 Vol. 2B).
+ Loc[-2] = 0xf7;
+
+ // Move R bit to the B bit in REX byte.
+ // REX byte is encoded as 0100WRXB, where
+ // 0100 is 4bit fixed pattern.
+ // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the
+ // default operand size is used (which is 32-bit for most but not all
+ // instructions).
+ // REX.R This 1-bit value is an extension to the MODRM.reg field.
+ // REX.X This 1-bit value is an extension to the SIB.index field.
+ // REX.B This 1-bit value is an extension to the MODRM.rm field or the
+ // SIB.base field.
+ // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).
+ Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;
+ relocateOne(Loc, R_X86_64_PC32, Val);
+ return;
+ }
+
+ // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub
+ // or xor operations.
+
+ // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg".
+ // Logic is close to one for test instruction above, but we also
+ // write opcode extension here, see below for details.
+ Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte.
+
+ // Primary opcode is 0x81, opcode extension is one of:
+ // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB,
+ // 100b is AND, 101b is SUB, 110b is XOR, 111b is CMP.
+ // This value was wrote to MODRM.reg in a line above.
+ // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15),
+ // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for
+ // descriptions about each operation.
+ Loc[-2] = 0x81;
+ Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;
+ relocateOne(Loc, R_X86_64_PC32, Val);
+}
+
+template <class ELFT>
+void X86_64TargetInfo<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const {
+ const uint8_t Op = Loc[-2];
+ const uint8_t ModRm = Loc[-1];
+
+ // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg".
+ if (Op == 0x8b) {
+ Loc[-2] = 0x8d;
+ relocateOne(Loc, R_X86_64_PC32, Val);
+ return;
+ }
+
+ if (Op != 0xff) {
+ // We are relaxing a rip relative to an absolute, so compensate
+ // for the old -4 addend.
+ assert(!Config->Pic);
+ relaxGotNoPic(Loc, Val + 4, Op, ModRm);
+ return;
+ }
+
+ // Convert call/jmp instructions.
+ if (ModRm == 0x15) {
+ // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo".
+ // Instead we convert to "addr32 call foo" where addr32 is an instruction
+ // prefix. That makes result expression to be a single instruction.
+ Loc[-2] = 0x67; // addr32 prefix
+ Loc[-1] = 0xe8; // call
+ relocateOne(Loc, R_X86_64_PC32, Val);
+ return;
+ }
+
+ // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop".
+ // jmp doesn't return, so it is fine to use nop here, it is just a stub.
+ assert(ModRm == 0x25);
+ Loc[-2] = 0xe9; // jmp
+ Loc[3] = 0x90; // nop
+ relocateOne(Loc - 1, R_X86_64_PC32, Val + 1);
+}
+
// Relocation masks following the #lo(value), #hi(value), #ha(value),
// #higher(value), #highera(value), #highest(value), and #highesta(value)
// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
@@ -933,41 +954,32 @@ static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
PPCTargetInfo::PPCTargetInfo() {}
-void PPCTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
-void PPCTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const {}
-void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
- uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const {}
-bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
- return false;
-}
-bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
- return false;
-}
-bool PPCTargetInfo::isRelRelative(uint32_t Type) const { return false; }
-void PPCTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
- uint64_t P, uint64_t SA, uint64_t ZA,
- uint8_t *PairedLoc) const {
+void PPCTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
switch (Type) {
case R_PPC_ADDR16_HA:
- write16be(Loc, applyPPCHa(SA));
+ write16be(Loc, applyPPCHa(Val));
break;
case R_PPC_ADDR16_LO:
- write16be(Loc, applyPPCLo(SA));
+ write16be(Loc, applyPPCLo(Val));
break;
default:
- error("unrecognized reloc " + Twine(Type));
+ fatal("unrecognized reloc " + Twine(Type));
}
}
+RelExpr PPCTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
+ return R_ABS;
+}
+
PPC64TargetInfo::PPC64TargetInfo() {
- PCRelReloc = R_PPC64_REL24;
- GotReloc = R_PPC64_GLOB_DAT;
- RelativeReloc = R_PPC64_RELATIVE;
+ PltRel = GotRel = R_PPC64_GLOB_DAT;
+ RelativeRel = R_PPC64_RELATIVE;
+ GotEntrySize = 8;
+ GotPltEntrySize = 8;
PltEntrySize = 32;
+ PltHeaderSize = 0;
// We need 64K pages (at least under glibc/Linux, the loader won't
// set different permissions on a finer granularity than that).
@@ -981,33 +993,46 @@ PPC64TargetInfo::PPC64TargetInfo() {
//
// And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers
// use 0x10000000 as the starting address.
- VAStart = 0x10000000;
+ DefaultImageBase = 0x10000000;
}
-uint64_t getPPC64TocBase() {
- // The TOC consists of sections .got, .toc, .tocbss, .plt in that
- // order. The TOC starts where the first of these sections starts.
+static uint64_t PPC64TocOffset = 0x8000;
- // FIXME: This obviously does not do the right thing when there is no .got
- // section, but there is a .toc or .tocbss section.
+uint64_t getPPC64TocBase() {
+ // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The
+ // TOC starts where the first of these sections starts. We always create a
+ // .got when we see a relocation that uses it, so for us the start is always
+ // the .got.
uint64_t TocVA = Out<ELF64BE>::Got->getVA();
- if (!TocVA)
- TocVA = Out<ELF64BE>::Plt->getVA();
// Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
// thus permitting a full 64 Kbytes segment. Note that the glibc startup
// code (crt1.o) assumes that you can get from the TOC base to the
// start of the .toc section with only a single (signed) 16-bit relocation.
- return TocVA + 0x8000;
+ return TocVA + PPC64TocOffset;
}
-void PPC64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
-void PPC64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const {}
-void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
- uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const {
+RelExpr PPC64TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
+ switch (Type) {
+ default:
+ return R_ABS;
+ case R_PPC64_TOC16:
+ case R_PPC64_TOC16_DS:
+ case R_PPC64_TOC16_HA:
+ case R_PPC64_TOC16_HI:
+ case R_PPC64_TOC16_LO:
+ case R_PPC64_TOC16_LO_DS:
+ return R_GOTREL;
+ case R_PPC64_TOC:
+ return R_PPC_TOC;
+ case R_PPC64_REL24:
+ return R_PPC_PLT_OPD;
+ }
+}
+
+void PPC64TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {
uint64_t Off = GotEntryAddr - getPPC64TocBase();
// FIXME: What we should do, in theory, is get the offset of the function
@@ -1026,181 +1051,193 @@ void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
write32be(Buf + 28, 0x4e800420); // bctr
}
-bool PPC64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
- if (relocNeedsPlt(Type, S))
- return true;
-
+static std::pair<uint32_t, uint64_t> toAddr16Rel(uint32_t Type, uint64_t Val) {
+ uint64_t V = Val - PPC64TocOffset;
switch (Type) {
- default: return false;
- case R_PPC64_GOT16:
- case R_PPC64_GOT16_DS:
- case R_PPC64_GOT16_HA:
- case R_PPC64_GOT16_HI:
- case R_PPC64_GOT16_LO:
- case R_PPC64_GOT16_LO_DS:
- return true;
+ case R_PPC64_TOC16: return {R_PPC64_ADDR16, V};
+ case R_PPC64_TOC16_DS: return {R_PPC64_ADDR16_DS, V};
+ case R_PPC64_TOC16_HA: return {R_PPC64_ADDR16_HA, V};
+ case R_PPC64_TOC16_HI: return {R_PPC64_ADDR16_HI, V};
+ case R_PPC64_TOC16_LO: return {R_PPC64_ADDR16_LO, V};
+ case R_PPC64_TOC16_LO_DS: return {R_PPC64_ADDR16_LO_DS, V};
+ default: return {Type, Val};
}
}
-bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
- // These are function calls that need to be redirected through a PLT stub.
- return Type == R_PPC64_REL24 && canBePreempted(&S, false);
-}
-
-bool PPC64TargetInfo::isRelRelative(uint32_t Type) const {
- switch (Type) {
- default:
- return true;
- case R_PPC64_ADDR64:
- case R_PPC64_TOC:
- return false;
- }
-}
-
-void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
- uint64_t P, uint64_t SA, uint64_t ZA,
- uint8_t *PairedLoc) const {
- uint64_t TB = getPPC64TocBase();
-
- // For a TOC-relative relocation, adjust the addend and proceed in terms of
- // the corresponding ADDR16 relocation type.
- switch (Type) {
- case R_PPC64_TOC16: Type = R_PPC64_ADDR16; SA -= TB; break;
- case R_PPC64_TOC16_DS: Type = R_PPC64_ADDR16_DS; SA -= TB; break;
- case R_PPC64_TOC16_HA: Type = R_PPC64_ADDR16_HA; SA -= TB; break;
- case R_PPC64_TOC16_HI: Type = R_PPC64_ADDR16_HI; SA -= TB; break;
- case R_PPC64_TOC16_LO: Type = R_PPC64_ADDR16_LO; SA -= TB; break;
- case R_PPC64_TOC16_LO_DS: Type = R_PPC64_ADDR16_LO_DS; SA -= TB; break;
- default: break;
- }
+void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ // For a TOC-relative relocation, proceed in terms of the corresponding
+ // ADDR16 relocation type.
+ std::tie(Type, Val) = toAddr16Rel(Type, Val);
switch (Type) {
case R_PPC64_ADDR14: {
- checkAlignment<4>(SA, Type);
+ checkAlignment<4>(Val, Type);
// Preserve the AA/LK bits in the branch instruction
uint8_t AALK = Loc[3];
- write16be(Loc + 2, (AALK & 3) | (SA & 0xfffc));
+ write16be(Loc + 2, (AALK & 3) | (Val & 0xfffc));
break;
}
case R_PPC64_ADDR16:
- checkInt<16>(SA, Type);
- write16be(Loc, SA);
+ checkInt<16>(Val, Type);
+ write16be(Loc, Val);
break;
case R_PPC64_ADDR16_DS:
- checkInt<16>(SA, Type);
- write16be(Loc, (read16be(Loc) & 3) | (SA & ~3));
+ checkInt<16>(Val, Type);
+ write16be(Loc, (read16be(Loc) & 3) | (Val & ~3));
break;
case R_PPC64_ADDR16_HA:
- write16be(Loc, applyPPCHa(SA));
+ case R_PPC64_REL16_HA:
+ write16be(Loc, applyPPCHa(Val));
break;
case R_PPC64_ADDR16_HI:
- write16be(Loc, applyPPCHi(SA));
+ case R_PPC64_REL16_HI:
+ write16be(Loc, applyPPCHi(Val));
break;
case R_PPC64_ADDR16_HIGHER:
- write16be(Loc, applyPPCHigher(SA));
+ write16be(Loc, applyPPCHigher(Val));
break;
case R_PPC64_ADDR16_HIGHERA:
- write16be(Loc, applyPPCHighera(SA));
+ write16be(Loc, applyPPCHighera(Val));
break;
case R_PPC64_ADDR16_HIGHEST:
- write16be(Loc, applyPPCHighest(SA));
+ write16be(Loc, applyPPCHighest(Val));
break;
case R_PPC64_ADDR16_HIGHESTA:
- write16be(Loc, applyPPCHighesta(SA));
+ write16be(Loc, applyPPCHighesta(Val));
break;
case R_PPC64_ADDR16_LO:
- write16be(Loc, applyPPCLo(SA));
+ write16be(Loc, applyPPCLo(Val));
break;
case R_PPC64_ADDR16_LO_DS:
- write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(SA) & ~3));
+ case R_PPC64_REL16_LO:
+ write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(Val) & ~3));
break;
case R_PPC64_ADDR32:
- checkInt<32>(SA, Type);
- write32be(Loc, SA);
+ case R_PPC64_REL32:
+ checkInt<32>(Val, Type);
+ write32be(Loc, Val);
break;
case R_PPC64_ADDR64:
- write64be(Loc, SA);
- break;
- case R_PPC64_REL16_HA:
- write16be(Loc, applyPPCHa(SA - P));
- break;
- case R_PPC64_REL16_HI:
- write16be(Loc, applyPPCHi(SA - P));
- break;
- case R_PPC64_REL16_LO:
- write16be(Loc, applyPPCLo(SA - P));
+ case R_PPC64_REL64:
+ case R_PPC64_TOC:
+ write64be(Loc, Val);
break;
case R_PPC64_REL24: {
- // If we have an undefined weak symbol, we might get here with a symbol
- // address of zero. That could overflow, but the code must be unreachable,
- // so don't bother doing anything at all.
- if (!SA)
- break;
-
- uint64_t PltStart = Out<ELF64BE>::Plt->getVA();
- uint64_t PltEnd = PltStart + Out<ELF64BE>::Plt->getSize();
- bool InPlt = PltStart <= SA && SA < PltEnd;
-
- if (!InPlt && Out<ELF64BE>::Opd) {
- // If this is a local call, and we currently have the address of a
- // function-descriptor, get the underlying code address instead.
- uint64_t OpdStart = Out<ELF64BE>::Opd->getVA();
- uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->getSize();
- bool InOpd = OpdStart <= SA && SA < OpdEnd;
-
- if (InOpd)
- SA = read64be(&Out<ELF64BE>::OpdBuf[SA - OpdStart]);
- }
-
uint32_t Mask = 0x03FFFFFC;
- checkInt<24>(SA - P, Type);
- write32be(Loc, (read32be(Loc) & ~Mask) | ((SA - P) & Mask));
-
- uint32_t Nop = 0x60000000;
- if (InPlt && Loc + 8 <= BufEnd && read32be(Loc + 4) == Nop)
- write32be(Loc + 4, 0xe8410028); // ld %r2, 40(%r1)
+ checkInt<24>(Val, Type);
+ write32be(Loc, (read32be(Loc) & ~Mask) | (Val & Mask));
break;
}
- case R_PPC64_REL32:
- checkInt<32>(SA - P, Type);
- write32be(Loc, SA - P);
- break;
- case R_PPC64_REL64:
- write64be(Loc, SA - P);
- break;
- case R_PPC64_TOC:
- write64be(Loc, SA);
- break;
default:
- error("unrecognized reloc " + Twine(Type));
+ fatal("unrecognized reloc " + Twine(Type));
}
}
AArch64TargetInfo::AArch64TargetInfo() {
- CopyReloc = R_AARCH64_COPY;
- IRelativeReloc = R_AARCH64_IRELATIVE;
- GotReloc = R_AARCH64_GLOB_DAT;
- PltReloc = R_AARCH64_JUMP_SLOT;
- TlsGotReloc = R_AARCH64_TLS_TPREL64;
- LazyRelocations = true;
+ CopyRel = R_AARCH64_COPY;
+ RelativeRel = R_AARCH64_RELATIVE;
+ IRelativeRel = R_AARCH64_IRELATIVE;
+ GotRel = R_AARCH64_GLOB_DAT;
+ PltRel = R_AARCH64_JUMP_SLOT;
+ TlsDescRel = R_AARCH64_TLSDESC;
+ TlsGotRel = R_AARCH64_TLS_TPREL64;
+ GotEntrySize = 8;
+ GotPltEntrySize = 8;
PltEntrySize = 16;
- PltZeroEntrySize = 32;
+ PltHeaderSize = 32;
+
+ // It doesn't seem to be documented anywhere, but tls on aarch64 uses variant
+ // 1 of the tls structures and the tcb size is 16.
+ TcbSize = 16;
+}
+
+RelExpr AArch64TargetInfo::getRelExpr(uint32_t Type,
+ const SymbolBody &S) const {
+ switch (Type) {
+ default:
+ return R_ABS;
+ case R_AARCH64_TLSDESC_ADR_PAGE21:
+ return R_TLSDESC_PAGE;
+ case R_AARCH64_TLSDESC_LD64_LO12_NC:
+ case R_AARCH64_TLSDESC_ADD_LO12_NC:
+ return R_TLSDESC;
+ case R_AARCH64_TLSDESC_CALL:
+ return R_HINT;
+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+ case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ return R_TLS;
+ case R_AARCH64_CALL26:
+ case R_AARCH64_CONDBR19:
+ case R_AARCH64_JUMP26:
+ case R_AARCH64_TSTBR14:
+ return R_PLT_PC;
+ case R_AARCH64_PREL16:
+ case R_AARCH64_PREL32:
+ case R_AARCH64_PREL64:
+ case R_AARCH64_ADR_PREL_LO21:
+ return R_PC;
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ return R_PAGE_PC;
+ case R_AARCH64_LD64_GOT_LO12_NC:
+ case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+ return R_GOT;
+ case R_AARCH64_ADR_GOT_PAGE:
+ case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+ return R_GOT_PAGE_PC;
+ }
}
-unsigned AArch64TargetInfo::getDynReloc(unsigned Type) const {
+RelExpr AArch64TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const {
+ if (Expr == R_RELAX_TLS_GD_TO_IE) {
+ if (Type == R_AARCH64_TLSDESC_ADR_PAGE21)
+ return R_RELAX_TLS_GD_TO_IE_PAGE_PC;
+ return R_RELAX_TLS_GD_TO_IE_ABS;
+ }
+ return Expr;
+}
+
+bool AArch64TargetInfo::usesOnlyLowPageBits(uint32_t Type) const {
+ switch (Type) {
+ default:
+ return false;
+ case R_AARCH64_ADD_ABS_LO12_NC:
+ case R_AARCH64_LD64_GOT_LO12_NC:
+ case R_AARCH64_LDST128_ABS_LO12_NC:
+ case R_AARCH64_LDST16_ABS_LO12_NC:
+ case R_AARCH64_LDST32_ABS_LO12_NC:
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ case R_AARCH64_TLSDESC_ADD_LO12_NC:
+ case R_AARCH64_TLSDESC_LD64_LO12_NC:
+ case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+ return true;
+ }
+}
+
+bool AArch64TargetInfo::isTlsInitialExecRel(uint32_t Type) const {
+ return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
+ Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
+}
+
+uint32_t AArch64TargetInfo::getDynRel(uint32_t Type) const {
if (Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64)
return Type;
- StringRef S = getELFRelocationTypeName(EM_AARCH64, Type);
- error("Relocation " + S + " cannot be used when making a shared object; "
- "recompile with -fPIC.");
+ // Keep it going with a dummy value so that we can find more reloc errors.
+ errorDynRel(Type);
+ return R_AARCH64_ABS32;
}
-void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
+void AArch64TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
write64le(Buf, Out<ELF64LE>::Plt->getVA());
}
-void AArch64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const {
+static uint64_t getAArch64Page(uint64_t Expr) {
+ return Expr & (~static_cast<uint64_t>(0xFFF));
+}
+
+void AArch64TargetInfo::writePltHeader(uint8_t *Buf) const {
const uint8_t PltData[] = {
0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]!
0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2]))
@@ -1213,18 +1250,17 @@ void AArch64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
};
memcpy(Buf, PltData, sizeof(PltData));
- relocateOne(Buf + 4, Buf + 8, R_AARCH64_ADR_PREL_PG_HI21, PltEntryAddr + 4,
- GotEntryAddr + 16);
- relocateOne(Buf + 8, Buf + 12, R_AARCH64_LDST64_ABS_LO12_NC, PltEntryAddr + 8,
- GotEntryAddr + 16);
- relocateOne(Buf + 12, Buf + 16, R_AARCH64_ADD_ABS_LO12_NC, PltEntryAddr + 12,
- GotEntryAddr + 16);
+ uint64_t Got = Out<ELF64LE>::GotPlt->getVA();
+ uint64_t Plt = Out<ELF64LE>::Plt->getVA();
+ relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
+ getAArch64Page(Got + 16) - getAArch64Page(Plt + 4));
+ relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16);
+ relocateOne(Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, Got + 16);
}
-void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
- uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const {
+void AArch64TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {
const uint8_t Inst[] = {
0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n]))
0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))]
@@ -1233,377 +1269,851 @@ void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
};
memcpy(Buf, Inst, sizeof(Inst));
- relocateOne(Buf, Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, PltEntryAddr,
- GotEntryAddr);
- relocateOne(Buf + 4, Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, PltEntryAddr + 4,
- GotEntryAddr);
- relocateOne(Buf + 8, Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, PltEntryAddr + 8,
- GotEntryAddr);
+ relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21,
+ getAArch64Page(GotEntryAddr) - getAArch64Page(PltEntryAddr));
+ relocateOne(Buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, GotEntryAddr);
+ relocateOne(Buf + 8, R_AARCH64_ADD_ABS_LO12_NC, GotEntryAddr);
}
-unsigned AArch64TargetInfo::getTlsGotReloc(unsigned Type) const {
- if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
- Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
- return Type;
- return TlsGotReloc;
-}
-
-bool AArch64TargetInfo::isTlsDynReloc(unsigned Type,
- const SymbolBody &S) const {
- return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
- Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
-}
-
-bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
- if (Config->Shared)
- return false;
- switch (Type) {
- default:
- return false;
- case R_AARCH64_ABS16:
- case R_AARCH64_ABS32:
- case R_AARCH64_ABS64:
- case R_AARCH64_ADD_ABS_LO12_NC:
- case R_AARCH64_ADR_PREL_LO21:
- case R_AARCH64_ADR_PREL_PG_HI21:
- case R_AARCH64_LDST8_ABS_LO12_NC:
- case R_AARCH64_LDST32_ABS_LO12_NC:
- case R_AARCH64_LDST64_ABS_LO12_NC:
- if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S))
- return SS->Sym.getType() == STT_OBJECT;
- return false;
- }
-}
-
-bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
- const SymbolBody &S) const {
- switch (Type) {
- case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
- case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
- case R_AARCH64_ADR_GOT_PAGE:
- case R_AARCH64_LD64_GOT_LO12_NC:
- return true;
- default:
- return relocNeedsPlt(Type, S);
- }
-}
-
-bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
- const SymbolBody &S) const {
- if (isGnuIFunc<ELF64LE>(S))
- return true;
- switch (Type) {
- default:
- return false;
- case R_AARCH64_CALL26:
- case R_AARCH64_CONDBR19:
- case R_AARCH64_JUMP26:
- case R_AARCH64_TSTBR14:
- return canBePreempted(&S, true);
- }
-}
-
-static void updateAArch64Adr(uint8_t *L, uint64_t Imm) {
+static void updateAArch64Addr(uint8_t *L, uint64_t Imm) {
uint32_t ImmLo = (Imm & 0x3) << 29;
- uint32_t ImmHi = ((Imm & 0x1FFFFC) >> 2) << 5;
- uint64_t Mask = (0x3 << 29) | (0x7FFFF << 5);
+ uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;
+ uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);
write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi);
}
-// Page(Expr) is the page address of the expression Expr, defined
-// as (Expr & ~0xFFF). (This applies even if the machine page size
-// supported by the platform has a different value.)
-static uint64_t getAArch64Page(uint64_t Expr) {
- return Expr & (~static_cast<uint64_t>(0xFFF));
+static inline void updateAArch64Add(uint8_t *L, uint64_t Imm) {
+ or32le(L, (Imm & 0xFFF) << 10);
}
-void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
- uint32_t Type, uint64_t P, uint64_t SA,
- uint64_t ZA, uint8_t *PairedLoc) const {
+void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
switch (Type) {
case R_AARCH64_ABS16:
- checkIntUInt<16>(SA, Type);
- write16le(Loc, SA);
+ case R_AARCH64_PREL16:
+ checkIntUInt<16>(Val, Type);
+ write16le(Loc, Val);
break;
case R_AARCH64_ABS32:
- checkIntUInt<32>(SA, Type);
- write32le(Loc, SA);
+ case R_AARCH64_PREL32:
+ checkIntUInt<32>(Val, Type);
+ write32le(Loc, Val);
break;
case R_AARCH64_ABS64:
- write64le(Loc, SA);
+ case R_AARCH64_PREL64:
+ write64le(Loc, Val);
break;
case R_AARCH64_ADD_ABS_LO12_NC:
// This relocation stores 12 bits and there's no instruction
// to do it. Instead, we do a 32 bits store of the value
// of r_addend bitwise-or'ed Loc. This assumes that the addend
// bits in Loc are zero.
- or32le(Loc, (SA & 0xFFF) << 10);
- break;
- case R_AARCH64_ADR_GOT_PAGE: {
- uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
- checkInt<33>(X, Type);
- updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
- break;
- }
- case R_AARCH64_ADR_PREL_LO21: {
- uint64_t X = SA - P;
- checkInt<21>(X, Type);
- updateAArch64Adr(Loc, X & 0x1FFFFF);
+ or32le(Loc, (Val & 0xFFF) << 10);
break;
- }
+ case R_AARCH64_ADR_GOT_PAGE:
case R_AARCH64_ADR_PREL_PG_HI21:
- case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: {
- uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
- checkInt<33>(X, Type);
- updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
+ case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+ case R_AARCH64_TLSDESC_ADR_PAGE21:
+ checkInt<33>(Val, Type);
+ updateAArch64Addr(Loc, Val >> 12);
+ break;
+ case R_AARCH64_ADR_PREL_LO21:
+ checkInt<21>(Val, Type);
+ updateAArch64Addr(Loc, Val);
break;
- }
case R_AARCH64_CALL26:
- case R_AARCH64_JUMP26: {
- uint64_t X = SA - P;
- checkInt<28>(X, Type);
- or32le(Loc, (X & 0x0FFFFFFC) >> 2);
+ case R_AARCH64_JUMP26:
+ checkInt<28>(Val, Type);
+ or32le(Loc, (Val & 0x0FFFFFFC) >> 2);
break;
- }
- case R_AARCH64_CONDBR19: {
- uint64_t X = SA - P;
- checkInt<21>(X, Type);
- or32le(Loc, (X & 0x1FFFFC) << 3);
+ case R_AARCH64_CONDBR19:
+ checkInt<21>(Val, Type);
+ or32le(Loc, (Val & 0x1FFFFC) << 3);
break;
- }
case R_AARCH64_LD64_GOT_LO12_NC:
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
- checkAlignment<8>(SA, Type);
- or32le(Loc, (SA & 0xFF8) << 7);
+ case R_AARCH64_TLSDESC_LD64_LO12_NC:
+ checkAlignment<8>(Val, Type);
+ or32le(Loc, (Val & 0xFF8) << 7);
+ break;
+ case R_AARCH64_LDST128_ABS_LO12_NC:
+ or32le(Loc, (Val & 0x0FF8) << 6);
+ break;
+ case R_AARCH64_LDST16_ABS_LO12_NC:
+ or32le(Loc, (Val & 0x0FFC) << 9);
break;
case R_AARCH64_LDST8_ABS_LO12_NC:
- or32le(Loc, (SA & 0xFFF) << 10);
+ or32le(Loc, (Val & 0xFFF) << 10);
break;
case R_AARCH64_LDST32_ABS_LO12_NC:
- or32le(Loc, (SA & 0xFFC) << 8);
+ or32le(Loc, (Val & 0xFFC) << 8);
break;
case R_AARCH64_LDST64_ABS_LO12_NC:
- or32le(Loc, (SA & 0xFF8) << 7);
+ or32le(Loc, (Val & 0xFF8) << 7);
break;
- case R_AARCH64_PREL16:
- checkIntUInt<16>(SA - P, Type);
- write16le(Loc, SA - P);
+ case R_AARCH64_TSTBR14:
+ checkInt<16>(Val, Type);
+ or32le(Loc, (Val & 0xFFFC) << 3);
break;
- case R_AARCH64_PREL32:
- checkIntUInt<32>(SA - P, Type);
- write32le(Loc, SA - P);
+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+ checkInt<24>(Val, Type);
+ updateAArch64Add(Loc, Val >> 12);
break;
- case R_AARCH64_PREL64:
- write64le(Loc, SA - P);
+ case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ case R_AARCH64_TLSDESC_ADD_LO12_NC:
+ updateAArch64Add(Loc, Val);
break;
- case R_AARCH64_TSTBR14: {
- uint64_t X = SA - P;
- checkInt<16>(X, Type);
- or32le(Loc, (X & 0xFFFC) << 3);
+ default:
+ fatal("unrecognized reloc " + Twine(Type));
+ }
+}
+
+void AArch64TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ // TLSDESC Global-Dynamic relocation are in the form:
+ // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]
+ // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12_NC]
+ // add x0, x0, :tlsdesc_los:v [_AARCH64_TLSDESC_ADD_LO12_NC]
+ // .tlsdesccall [R_AARCH64_TLSDESC_CALL]
+ // blr x1
+ // And it can optimized to:
+ // movz x0, #0x0, lsl #16
+ // movk x0, #0x10
+ // nop
+ // nop
+ checkUInt<32>(Val, Type);
+
+ switch (Type) {
+ case R_AARCH64_TLSDESC_ADD_LO12_NC:
+ case R_AARCH64_TLSDESC_CALL:
+ write32le(Loc, 0xd503201f); // nop
+ return;
+ case R_AARCH64_TLSDESC_ADR_PAGE21:
+ write32le(Loc, 0xd2a00000 | (((Val >> 16) & 0xffff) << 5)); // movz
+ return;
+ case R_AARCH64_TLSDESC_LD64_LO12_NC:
+ write32le(Loc, 0xf2800000 | ((Val & 0xffff) << 5)); // movk
+ return;
+ default:
+ llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
+ }
+}
+
+void AArch64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ // TLSDESC Global-Dynamic relocation are in the form:
+ // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]
+ // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12_NC]
+ // add x0, x0, :tlsdesc_los:v [_AARCH64_TLSDESC_ADD_LO12_NC]
+ // .tlsdesccall [R_AARCH64_TLSDESC_CALL]
+ // blr x1
+ // And it can optimized to:
+ // adrp x0, :gottprel:v
+ // ldr x0, [x0, :gottprel_lo12:v]
+ // nop
+ // nop
+
+ switch (Type) {
+ case R_AARCH64_TLSDESC_ADD_LO12_NC:
+ case R_AARCH64_TLSDESC_CALL:
+ write32le(Loc, 0xd503201f); // nop
+ break;
+ case R_AARCH64_TLSDESC_ADR_PAGE21:
+ write32le(Loc, 0x90000000); // adrp
+ relocateOne(Loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, Val);
+ break;
+ case R_AARCH64_TLSDESC_LD64_LO12_NC:
+ write32le(Loc, 0xf9400000); // ldr
+ relocateOne(Loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, Val);
+ break;
+ default:
+ llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
+ }
+}
+
+void AArch64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ checkUInt<32>(Val, Type);
+
+ if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
+ // Generate MOVZ.
+ uint32_t RegNo = read32le(Loc) & 0x1f;
+ write32le(Loc, (0xd2a00000 | RegNo) | (((Val >> 16) & 0xffff) << 5));
+ return;
+ }
+ if (Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) {
+ // Generate MOVK.
+ uint32_t RegNo = read32le(Loc) & 0x1f;
+ write32le(Loc, (0xf2800000 | RegNo) | ((Val & 0xffff) << 5));
+ return;
+ }
+ llvm_unreachable("invalid relocation for TLS IE to LE relaxation");
+}
+
+AMDGPUTargetInfo::AMDGPUTargetInfo() {
+ GotRel = R_AMDGPU_ABS64;
+ GotEntrySize = 8;
+}
+
+void AMDGPUTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ switch (Type) {
+ case R_AMDGPU_GOTPCREL:
+ case R_AMDGPU_REL32:
+ write32le(Loc, Val);
break;
+ default:
+ fatal("unrecognized reloc " + Twine(Type));
}
+}
+
+RelExpr AMDGPUTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
+ switch (Type) {
+ case R_AMDGPU_REL32:
+ return R_PC;
+ case R_AMDGPU_GOTPCREL:
+ return R_GOT_PC;
default:
- error("unrecognized reloc " + Twine(Type));
+ fatal("do not know how to handle relocation " + Twine(Type));
}
}
-AMDGPUTargetInfo::AMDGPUTargetInfo() {}
+ARMTargetInfo::ARMTargetInfo() {
+ CopyRel = R_ARM_COPY;
+ RelativeRel = R_ARM_RELATIVE;
+ IRelativeRel = R_ARM_IRELATIVE;
+ GotRel = R_ARM_GLOB_DAT;
+ PltRel = R_ARM_JUMP_SLOT;
+ TlsGotRel = R_ARM_TLS_TPOFF32;
+ TlsModuleIndexRel = R_ARM_TLS_DTPMOD32;
+ TlsOffsetRel = R_ARM_TLS_DTPOFF32;
+ GotEntrySize = 4;
+ GotPltEntrySize = 4;
+ PltEntrySize = 16;
+ PltHeaderSize = 20;
+}
-void AMDGPUTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
- llvm_unreachable("not implemented");
+RelExpr ARMTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
+ switch (Type) {
+ default:
+ return R_ABS;
+ case R_ARM_THM_JUMP11:
+ return R_PC;
+ case R_ARM_CALL:
+ case R_ARM_JUMP24:
+ case R_ARM_PC24:
+ case R_ARM_PLT32:
+ case R_ARM_THM_JUMP19:
+ case R_ARM_THM_JUMP24:
+ case R_ARM_THM_CALL:
+ return R_PLT_PC;
+ case R_ARM_GOTOFF32:
+ // (S + A) - GOT_ORG
+ return R_GOTREL;
+ case R_ARM_GOT_BREL:
+ // GOT(S) + A - GOT_ORG
+ return R_GOT_OFF;
+ case R_ARM_GOT_PREL:
+ // GOT(S) + - GOT_ORG
+ return R_GOT_PC;
+ case R_ARM_BASE_PREL:
+ // B(S) + A - P
+ // FIXME: currently B(S) assumed to be .got, this may not hold for all
+ // platforms.
+ return R_GOTONLY_PC;
+ case R_ARM_MOVW_PREL_NC:
+ case R_ARM_MOVT_PREL:
+ case R_ARM_PREL31:
+ case R_ARM_REL32:
+ case R_ARM_THM_MOVW_PREL_NC:
+ case R_ARM_THM_MOVT_PREL:
+ return R_PC;
+ }
}
-void AMDGPUTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const {
- llvm_unreachable("not implemented");
+uint32_t ARMTargetInfo::getDynRel(uint32_t Type) const {
+ if (Type == R_ARM_ABS32)
+ return Type;
+ // Keep it going with a dummy value so that we can find more reloc errors.
+ errorDynRel(Type);
+ return R_ARM_ABS32;
}
-void AMDGPUTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
- uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const {
- llvm_unreachable("not implemented");
+void ARMTargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
+ write32le(Buf, Out<ELF32LE>::Plt->getVA());
}
-bool AMDGPUTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
- return false;
+void ARMTargetInfo::writePltHeader(uint8_t *Buf) const {
+ const uint8_t PltData[] = {
+ 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]!
+ 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2
+ 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr
+ 0x08, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #8]
+ 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8
+ };
+ memcpy(Buf, PltData, sizeof(PltData));
+ uint64_t GotPlt = Out<ELF32LE>::GotPlt->getVA();
+ uint64_t L1 = Out<ELF32LE>::Plt->getVA() + 8;
+ write32le(Buf + 16, GotPlt - L1 - 8);
}
-bool AMDGPUTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
- return false;
+void ARMTargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {
+ // FIXME: Using simple code sequence with simple relocations.
+ // There is a more optimal sequence but it requires support for the group
+ // relocations. See ELF for the ARM Architecture Appendix A.3
+ const uint8_t PltData[] = {
+ 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2
+ 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
+ 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip]
+ 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.plt.got) - L1 - 8
+ };
+ memcpy(Buf, PltData, sizeof(PltData));
+ uint64_t L1 = PltEntryAddr + 4;
+ write32le(Buf + 12, GotEntryAddr - L1 - 8);
+}
+
+RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
+ const InputFile &File,
+ const SymbolBody &S) const {
+ // A state change from ARM to Thumb and vice versa must go through an
+ // interworking thunk if the relocation type is not R_ARM_CALL or
+ // R_ARM_THM_CALL.
+ switch (RelocType) {
+ case R_ARM_PC24:
+ case R_ARM_PLT32:
+ case R_ARM_JUMP24:
+ // Source is ARM, all PLT entries are ARM so no interworking required.
+ // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
+ if (Expr == R_PC && ((S.getVA<ELF32LE>() & 1) == 1))
+ return R_THUNK_PC;
+ break;
+ case R_ARM_THM_JUMP19:
+ case R_ARM_THM_JUMP24:
+ // Source is Thumb, all PLT entries are ARM so interworking is required.
+ // Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
+ if (Expr == R_PLT_PC)
+ return R_THUNK_PLT_PC;
+ if ((S.getVA<ELF32LE>() & 1) == 0)
+ return R_THUNK_PC;
+ break;
+ }
+ return Expr;
}
-// Implementing relocations for AMDGPU is low priority since most
-// programs don't use relocations now. Thus, this function is not
-// actually called (relocateOne is called for each relocation).
-// That's why the AMDGPU port works without implementing this function.
-void AMDGPUTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
- uint64_t P, uint64_t SA, uint64_t ZA,
- uint8_t *PairedLoc) const {
- llvm_unreachable("not implemented");
+void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ switch (Type) {
+ case R_ARM_NONE:
+ break;
+ case R_ARM_ABS32:
+ case R_ARM_BASE_PREL:
+ case R_ARM_GOTOFF32:
+ case R_ARM_GOT_BREL:
+ case R_ARM_GOT_PREL:
+ case R_ARM_REL32:
+ write32le(Loc, Val);
+ break;
+ case R_ARM_PREL31:
+ checkInt<31>(Val, Type);
+ write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000));
+ break;
+ case R_ARM_CALL:
+ // R_ARM_CALL is used for BL and BLX instructions, depending on the
+ // value of bit 0 of Val, we must select a BL or BLX instruction
+ if (Val & 1) {
+ // If bit 0 of Val is 1 the target is Thumb, we must select a BLX.
+ // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'
+ checkInt<26>(Val, Type);
+ write32le(Loc, 0xfa000000 | // opcode
+ ((Val & 2) << 23) | // H
+ ((Val >> 2) & 0x00ffffff)); // imm24
+ break;
+ }
+ if ((read32le(Loc) & 0xfe000000) == 0xfa000000)
+ // BLX (always unconditional) instruction to an ARM Target, select an
+ // unconditional BL.
+ write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff));
+ // fall through as BL encoding is shared with B
+ case R_ARM_JUMP24:
+ case R_ARM_PC24:
+ case R_ARM_PLT32:
+ checkInt<26>(Val, Type);
+ write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff));
+ break;
+ case R_ARM_THM_JUMP11:
+ checkInt<12>(Val, Type);
+ write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff));
+ break;
+ case R_ARM_THM_JUMP19:
+ // Encoding T3: Val = S:J2:J1:imm6:imm11:0
+ checkInt<21>(Val, Type);
+ write16le(Loc,
+ (read16le(Loc) & 0xfbc0) | // opcode cond
+ ((Val >> 10) & 0x0400) | // S
+ ((Val >> 12) & 0x003f)); // imm6
+ write16le(Loc + 2,
+ 0x8000 | // opcode
+ ((Val >> 8) & 0x0800) | // J2
+ ((Val >> 5) & 0x2000) | // J1
+ ((Val >> 1) & 0x07ff)); // imm11
+ break;
+ case R_ARM_THM_CALL:
+ // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the
+ // value of bit 0 of Val, we must select a BL or BLX instruction
+ if ((Val & 1) == 0) {
+ // Ensure BLX destination is 4-byte aligned. As BLX instruction may
+ // only be two byte aligned. This must be done before overflow check
+ Val = alignTo(Val, 4);
+ }
+ // Bit 12 is 0 for BLX, 1 for BL
+ write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12);
+ // Fall through as rest of encoding is the same as B.W
+ case R_ARM_THM_JUMP24:
+ // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
+ // FIXME: Use of I1 and I2 require v6T2ops
+ checkInt<25>(Val, Type);
+ write16le(Loc,
+ 0xf000 | // opcode
+ ((Val >> 14) & 0x0400) | // S
+ ((Val >> 12) & 0x03ff)); // imm10
+ write16le(Loc + 2,
+ (read16le(Loc + 2) & 0xd000) | // opcode
+ (((~(Val >> 10)) ^ (Val >> 11)) & 0x2000) | // J1
+ (((~(Val >> 11)) ^ (Val >> 13)) & 0x0800) | // J2
+ ((Val >> 1) & 0x07ff)); // imm11
+ break;
+ case R_ARM_MOVW_ABS_NC:
+ case R_ARM_MOVW_PREL_NC:
+ write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) |
+ (Val & 0x0fff));
+ break;
+ case R_ARM_MOVT_ABS:
+ case R_ARM_MOVT_PREL:
+ checkInt<32>(Val, Type);
+ write32le(Loc, (read32le(Loc) & ~0x000f0fff) |
+ (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff));
+ break;
+ case R_ARM_THM_MOVT_ABS:
+ case R_ARM_THM_MOVT_PREL:
+ // Encoding T1: A = imm4:i:imm3:imm8
+ checkInt<32>(Val, Type);
+ write16le(Loc,
+ 0xf2c0 | // opcode
+ ((Val >> 17) & 0x0400) | // i
+ ((Val >> 28) & 0x000f)); // imm4
+ write16le(Loc + 2,
+ (read16le(Loc + 2) & 0x8f00) | // opcode
+ ((Val >> 12) & 0x7000) | // imm3
+ ((Val >> 16) & 0x00ff)); // imm8
+ break;
+ case R_ARM_THM_MOVW_ABS_NC:
+ case R_ARM_THM_MOVW_PREL_NC:
+ // Encoding T3: A = imm4:i:imm3:imm8
+ write16le(Loc,
+ 0xf240 | // opcode
+ ((Val >> 1) & 0x0400) | // i
+ ((Val >> 12) & 0x000f)); // imm4
+ write16le(Loc + 2,
+ (read16le(Loc + 2) & 0x8f00) | // opcode
+ ((Val << 4) & 0x7000) | // imm3
+ (Val & 0x00ff)); // imm8
+ break;
+ default:
+ fatal("unrecognized reloc " + Twine(Type));
+ }
+}
+
+uint64_t ARMTargetInfo::getImplicitAddend(const uint8_t *Buf,
+ uint32_t Type) const {
+ switch (Type) {
+ default:
+ return 0;
+ case R_ARM_ABS32:
+ case R_ARM_BASE_PREL:
+ case R_ARM_GOTOFF32:
+ case R_ARM_GOT_BREL:
+ case R_ARM_GOT_PREL:
+ case R_ARM_REL32:
+ return SignExtend64<32>(read32le(Buf));
+ case R_ARM_PREL31:
+ return SignExtend64<31>(read32le(Buf));
+ case R_ARM_CALL:
+ case R_ARM_JUMP24:
+ case R_ARM_PC24:
+ case R_ARM_PLT32:
+ return SignExtend64<26>(read32le(Buf) << 2);
+ case R_ARM_THM_JUMP11:
+ return SignExtend64<12>(read16le(Buf) << 1);
+ case R_ARM_THM_JUMP19: {
+ // Encoding T3: A = S:J2:J1:imm10:imm6:0
+ uint16_t Hi = read16le(Buf);
+ uint16_t Lo = read16le(Buf + 2);
+ return SignExtend64<20>(((Hi & 0x0400) << 10) | // S
+ ((Lo & 0x0800) << 8) | // J2
+ ((Lo & 0x2000) << 5) | // J1
+ ((Hi & 0x003f) << 12) | // imm6
+ ((Lo & 0x07ff) << 1)); // imm11:0
+ }
+ case R_ARM_THM_CALL:
+ case R_ARM_THM_JUMP24: {
+ // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0
+ // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)
+ // FIXME: I1 and I2 require v6T2ops
+ uint16_t Hi = read16le(Buf);
+ uint16_t Lo = read16le(Buf + 2);
+ return SignExtend64<24>(((Hi & 0x0400) << 14) | // S
+ (~((Lo ^ (Hi << 3)) << 10) & 0x00800000) | // I1
+ (~((Lo ^ (Hi << 1)) << 11) & 0x00400000) | // I2
+ ((Hi & 0x003ff) << 12) | // imm0
+ ((Lo & 0x007ff) << 1)); // imm11:0
+ }
+ // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and
+ // MOVT is in the range -32768 <= A < 32768
+ case R_ARM_MOVW_ABS_NC:
+ case R_ARM_MOVT_ABS:
+ case R_ARM_MOVW_PREL_NC:
+ case R_ARM_MOVT_PREL: {
+ uint64_t Val = read32le(Buf) & 0x000f0fff;
+ return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff));
+ }
+ case R_ARM_THM_MOVW_ABS_NC:
+ case R_ARM_THM_MOVT_ABS:
+ case R_ARM_THM_MOVW_PREL_NC:
+ case R_ARM_THM_MOVT_PREL: {
+ // Encoding T3: A = imm4:i:imm3:imm8
+ uint16_t Hi = read16le(Buf);
+ uint16_t Lo = read16le(Buf + 2);
+ return SignExtend64<16>(((Hi & 0x000f) << 12) | // imm4
+ ((Hi & 0x0400) << 1) | // i
+ ((Lo & 0x7000) >> 4) | // imm3
+ (Lo & 0x00ff)); // imm8
+ }
+ }
}
template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
+ GotPltHeaderEntriesNum = 2;
PageSize = 65536;
- GotHeaderEntriesNum = 2;
+ GotEntrySize = sizeof(typename ELFT::uint);
+ GotPltEntrySize = sizeof(typename ELFT::uint);
+ PltEntrySize = 16;
+ PltHeaderSize = 32;
+ CopyRel = R_MIPS_COPY;
+ PltRel = R_MIPS_JUMP_SLOT;
+ if (ELFT::Is64Bits) {
+ RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32;
+ TlsGotRel = R_MIPS_TLS_TPREL64;
+ TlsModuleIndexRel = R_MIPS_TLS_DTPMOD64;
+ TlsOffsetRel = R_MIPS_TLS_DTPREL64;
+ } else {
+ RelativeRel = R_MIPS_REL32;
+ TlsGotRel = R_MIPS_TLS_TPREL32;
+ TlsModuleIndexRel = R_MIPS_TLS_DTPMOD32;
+ TlsOffsetRel = R_MIPS_TLS_DTPREL32;
+ }
}
template <class ELFT>
-void MipsTargetInfo<ELFT>::writeGotHeaderEntries(uint8_t *Buf) const {
- typedef typename ELFFile<ELFT>::Elf_Off Elf_Off;
- auto *P = reinterpret_cast<Elf_Off *>(Buf);
- // Module pointer
- P[1] = ELFT::Is64Bits ? 0x8000000000000000 : 0x80000000;
+RelExpr MipsTargetInfo<ELFT>::getRelExpr(uint32_t Type,
+ const SymbolBody &S) const {
+ if (ELFT::Is64Bits)
+ // See comment in the calculateMips64RelChain.
+ Type &= 0xff;
+ switch (Type) {
+ default:
+ return R_ABS;
+ case R_MIPS_JALR:
+ return R_HINT;
+ case R_MIPS_GPREL16:
+ case R_MIPS_GPREL32:
+ return R_GOTREL;
+ case R_MIPS_26:
+ return R_PLT;
+ case R_MIPS_HI16:
+ case R_MIPS_LO16:
+ case R_MIPS_GOT_OFST:
+ // MIPS _gp_disp designates offset between start of function and 'gp'
+ // pointer into GOT. __gnu_local_gp is equal to the current value of
+ // the 'gp'. Therefore any relocations against them do not require
+ // dynamic relocation.
+ if (&S == ElfSym<ELFT>::MipsGpDisp)
+ return R_PC;
+ return R_ABS;
+ case R_MIPS_PC32:
+ case R_MIPS_PC16:
+ case R_MIPS_PC19_S2:
+ case R_MIPS_PC21_S2:
+ case R_MIPS_PC26_S2:
+ case R_MIPS_PCHI16:
+ case R_MIPS_PCLO16:
+ return R_PC;
+ case R_MIPS_GOT16:
+ if (S.isLocal())
+ return R_MIPS_GOT_LOCAL_PAGE;
+ // fallthrough
+ case R_MIPS_CALL16:
+ case R_MIPS_GOT_DISP:
+ case R_MIPS_TLS_GOTTPREL:
+ return R_MIPS_GOT_OFF;
+ case R_MIPS_GOT_PAGE:
+ return R_MIPS_GOT_LOCAL_PAGE;
+ case R_MIPS_TLS_GD:
+ return R_MIPS_TLSGD;
+ case R_MIPS_TLS_LDM:
+ return R_MIPS_TLSLD;
+ }
}
template <class ELFT>
-void MipsTargetInfo<ELFT>::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
-template <class ELFT>
-void MipsTargetInfo<ELFT>::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const {}
+uint32_t MipsTargetInfo<ELFT>::getDynRel(uint32_t Type) const {
+ if (Type == R_MIPS_32 || Type == R_MIPS_64)
+ return RelativeRel;
+ // Keep it going with a dummy value so that we can find more reloc errors.
+ errorDynRel(Type);
+ return R_MIPS_32;
+}
+
template <class ELFT>
-void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
- uint64_t GotEntryAddr,
- uint64_t PltEntryAddr, int32_t Index,
- unsigned RelOff) const {}
+bool MipsTargetInfo<ELFT>::isTlsLocalDynamicRel(uint32_t Type) const {
+ return Type == R_MIPS_TLS_LDM;
+}
template <class ELFT>
-bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type,
- const SymbolBody &S) const {
- return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16;
+bool MipsTargetInfo<ELFT>::isTlsGlobalDynamicRel(uint32_t Type) const {
+ return Type == R_MIPS_TLS_GD;
}
template <class ELFT>
-bool MipsTargetInfo<ELFT>::relocNeedsPlt(uint32_t Type,
- const SymbolBody &S) const {
- return false;
+void MipsTargetInfo<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
+ write32<ELFT::TargetEndianness>(Buf, Out<ELFT>::Plt->getVA());
}
static uint16_t mipsHigh(uint64_t V) { return (V + 0x8000) >> 16; }
-template <endianness E, uint8_t BSIZE>
-static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t P,
- uint64_t SA) {
- uint32_t Mask = ~(0xffffffff << BSIZE);
+template <endianness E, uint8_t BSIZE, uint8_t SHIFT>
+static int64_t getPcRelocAddend(const uint8_t *Loc) {
+ uint32_t Instr = read32<E>(Loc);
+ uint32_t Mask = 0xffffffff >> (32 - BSIZE);
+ return SignExtend64<BSIZE + SHIFT>((Instr & Mask) << SHIFT);
+}
+
+template <endianness E, uint8_t BSIZE, uint8_t SHIFT>
+static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t V) {
+ uint32_t Mask = 0xffffffff >> (32 - BSIZE);
uint32_t Instr = read32<E>(Loc);
- int64_t A = SignExtend64<BSIZE + 2>((Instr & Mask) << 2);
- checkAlignment<4>(SA + A, Type);
- int64_t V = SA + A - P;
- checkInt<BSIZE + 2>(V, Type);
- write32<E>(Loc, (Instr & ~Mask) | ((V >> 2) & Mask));
+ if (SHIFT > 0)
+ checkAlignment<(1 << SHIFT)>(V, Type);
+ checkInt<BSIZE + SHIFT>(V, Type);
+ write32<E>(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask));
+}
+
+template <endianness E>
+static void writeMipsHi16(uint8_t *Loc, uint64_t V) {
+ uint32_t Instr = read32<E>(Loc);
+ write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(V));
+}
+
+template <endianness E>
+static void writeMipsLo16(uint8_t *Loc, uint64_t V) {
+ uint32_t Instr = read32<E>(Loc);
+ write32<E>(Loc, (Instr & 0xffff0000) | (V & 0xffff));
}
template <class ELFT>
-void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
- uint32_t Type, uint64_t P, uint64_t SA,
- uint64_t ZA, uint8_t *PairedLoc) const {
+void MipsTargetInfo<ELFT>::writePltHeader(uint8_t *Buf) const {
+ const endianness E = ELFT::TargetEndianness;
+ write32<E>(Buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0])
+ write32<E>(Buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28)
+ write32<E>(Buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0])
+ write32<E>(Buf + 12, 0x031cc023); // subu $24, $24, $28
+ write32<E>(Buf + 16, 0x03e07825); // move $15, $31
+ write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2
+ write32<E>(Buf + 24, 0x0320f809); // jalr $25
+ write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2
+ uint64_t Got = Out<ELFT>::GotPlt->getVA();
+ writeMipsHi16<E>(Buf, Got);
+ writeMipsLo16<E>(Buf + 4, Got);
+ writeMipsLo16<E>(Buf + 8, Got);
+}
+
+template <class ELFT>
+void MipsTargetInfo<ELFT>::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {
+ const endianness E = ELFT::TargetEndianness;
+ write32<E>(Buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry)
+ write32<E>(Buf + 4, 0x8df90000); // l[wd] $25, %lo(.got.plt entry)($15)
+ write32<E>(Buf + 8, 0x03200008); // jr $25
+ write32<E>(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry)
+ writeMipsHi16<E>(Buf, GotEntryAddr);
+ writeMipsLo16<E>(Buf + 4, GotEntryAddr);
+ writeMipsLo16<E>(Buf + 12, GotEntryAddr);
+}
+
+template <class ELFT>
+RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type,
+ const InputFile &File,
+ const SymbolBody &S) const {
+ // Any MIPS PIC code function is invoked with its address in register $t9.
+ // So if we have a branch instruction from non-PIC code to the PIC one
+ // we cannot make the jump directly and need to create a small stubs
+ // to save the target function address.
+ // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ if (Type != R_MIPS_26)
+ return Expr;
+ auto *F = dyn_cast<ELFFileBase<ELFT>>(&File);
+ if (!F)
+ return Expr;
+ // If current file has PIC code, LA25 stub is not required.
+ if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC)
+ return Expr;
+ auto *D = dyn_cast<DefinedRegular<ELFT>>(&S);
+ if (!D || !D->Section)
+ return Expr;
+ // LA25 is required if target file has PIC code
+ // or target symbol is a PIC symbol.
+ const ELFFile<ELFT> &DefFile = D->Section->getFile()->getObj();
+ bool PicFile = DefFile.getHeader()->e_flags & EF_MIPS_PIC;
+ bool PicSym = (D->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC;
+ return (PicFile || PicSym) ? R_THUNK_ABS : Expr;
+}
+
+template <class ELFT>
+uint64_t MipsTargetInfo<ELFT>::getImplicitAddend(const uint8_t *Buf,
+ uint32_t Type) const {
const endianness E = ELFT::TargetEndianness;
switch (Type) {
+ default:
+ return 0;
case R_MIPS_32:
- add32<E>(Loc, SA);
- break;
- case R_MIPS_CALL16:
- case R_MIPS_GOT16: {
- int64_t V = SA - getMipsGpAddr<ELFT>();
- if (Type == R_MIPS_GOT16)
- checkInt<16>(V, Type);
- write32<E>(Loc, (read32<E>(Loc) & 0xffff0000) | (V & 0xffff));
- break;
- }
- case R_MIPS_GPREL16: {
- uint32_t Instr = read32<E>(Loc);
- int64_t V = SA + SignExtend64<16>(Instr & 0xffff) - getMipsGpAddr<ELFT>();
- checkInt<16>(V, Type);
- write32<E>(Loc, (Instr & 0xffff0000) | (V & 0xffff));
- break;
+ case R_MIPS_GPREL32:
+ return read32<E>(Buf);
+ case R_MIPS_26:
+ // FIXME (simon): If the relocation target symbol is not a PLT entry
+ // we should use another expression for calculation:
+ // ((A << 2) | (P & 0xf0000000)) >> 2
+ return SignExtend64<28>(read32<E>(Buf) << 2);
+ case R_MIPS_GPREL16:
+ case R_MIPS_LO16:
+ case R_MIPS_PCLO16:
+ case R_MIPS_TLS_DTPREL_HI16:
+ case R_MIPS_TLS_DTPREL_LO16:
+ case R_MIPS_TLS_TPREL_HI16:
+ case R_MIPS_TLS_TPREL_LO16:
+ return SignExtend64<16>(read32<E>(Buf));
+ case R_MIPS_PC16:
+ return getPcRelocAddend<E, 16, 2>(Buf);
+ case R_MIPS_PC19_S2:
+ return getPcRelocAddend<E, 19, 2>(Buf);
+ case R_MIPS_PC21_S2:
+ return getPcRelocAddend<E, 21, 2>(Buf);
+ case R_MIPS_PC26_S2:
+ return getPcRelocAddend<E, 26, 2>(Buf);
+ case R_MIPS_PC32:
+ return getPcRelocAddend<E, 32, 0>(Buf);
}
+}
+
+static std::pair<uint32_t, uint64_t> calculateMips64RelChain(uint32_t Type,
+ uint64_t Val) {
+ // MIPS N64 ABI packs multiple relocations into the single relocation
+ // record. In general, all up to three relocations can have arbitrary
+ // types. In fact, Clang and GCC uses only a few combinations. For now,
+ // we support two of them. That is allow to pass at least all LLVM
+ // test suite cases.
+ // <any relocation> / R_MIPS_SUB / R_MIPS_HI16 | R_MIPS_LO16
+ // <any relocation> / R_MIPS_64 / R_MIPS_NONE
+ // The first relocation is a 'real' relocation which is calculated
+ // using the corresponding symbol's value. The second and the third
+ // relocations used to modify result of the first one: extend it to
+ // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation
+ // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf
+ uint32_t Type2 = (Type >> 8) & 0xff;
+ uint32_t Type3 = (Type >> 16) & 0xff;
+ if (Type2 == R_MIPS_NONE && Type3 == R_MIPS_NONE)
+ return std::make_pair(Type, Val);
+ if (Type2 == R_MIPS_64 && Type3 == R_MIPS_NONE)
+ return std::make_pair(Type2, Val);
+ if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16))
+ return std::make_pair(Type3, -Val);
+ error("unsupported relocations combination " + Twine(Type));
+ return std::make_pair(Type & 0xff, Val);
+}
+
+template <class ELFT>
+void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
+ uint64_t Val) const {
+ const endianness E = ELFT::TargetEndianness;
+ // Thread pointer and DRP offsets from the start of TLS data area.
+ // https://www.linux-mips.org/wiki/NPTL
+ if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16)
+ Val -= 0x8000;
+ else if (Type == R_MIPS_TLS_TPREL_HI16 || Type == R_MIPS_TLS_TPREL_LO16)
+ Val -= 0x7000;
+ if (ELFT::Is64Bits)
+ std::tie(Type, Val) = calculateMips64RelChain(Type, Val);
+ switch (Type) {
+ case R_MIPS_32:
case R_MIPS_GPREL32:
- write32<E>(Loc, SA + int32_t(read32<E>(Loc)) - getMipsGpAddr<ELFT>());
- break;
- case R_MIPS_HI16: {
- uint32_t Instr = read32<E>(Loc);
- if (PairedLoc) {
- uint64_t AHL = ((Instr & 0xffff) << 16) +
- SignExtend64<16>(read32<E>(PairedLoc) & 0xffff);
- write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA + AHL));
- } else {
- warning("Can't find matching R_MIPS_LO16 relocation for R_MIPS_HI16");
- write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA));
- }
+ write32<E>(Loc, Val);
+ break;
+ case R_MIPS_64:
+ write64<E>(Loc, Val);
+ break;
+ case R_MIPS_26:
+ write32<E>(Loc, (read32<E>(Loc) & ~0x3ffffff) | (Val >> 2));
+ break;
+ case R_MIPS_GOT_DISP:
+ case R_MIPS_GOT_PAGE:
+ case R_MIPS_GOT16:
+ case R_MIPS_GPREL16:
+ case R_MIPS_TLS_GD:
+ case R_MIPS_TLS_LDM:
+ checkInt<16>(Val, Type);
+ // fallthrough
+ case R_MIPS_CALL16:
+ case R_MIPS_GOT_OFST:
+ case R_MIPS_LO16:
+ case R_MIPS_PCLO16:
+ case R_MIPS_TLS_DTPREL_LO16:
+ case R_MIPS_TLS_GOTTPREL:
+ case R_MIPS_TLS_TPREL_LO16:
+ writeMipsLo16<E>(Loc, Val);
+ break;
+ case R_MIPS_HI16:
+ case R_MIPS_PCHI16:
+ case R_MIPS_TLS_DTPREL_HI16:
+ case R_MIPS_TLS_TPREL_HI16:
+ writeMipsHi16<E>(Loc, Val);
break;
- }
case R_MIPS_JALR:
// Ignore this optimization relocation for now
break;
- case R_MIPS_LO16: {
- uint32_t Instr = read32<E>(Loc);
- int64_t AHL = SignExtend64<16>(Instr & 0xffff);
- write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL) & 0xffff));
- break;
- }
case R_MIPS_PC16:
- applyMipsPcReloc<E, 16>(Loc, Type, P, SA);
+ applyMipsPcReloc<E, 16, 2>(Loc, Type, Val);
break;
case R_MIPS_PC19_S2:
- applyMipsPcReloc<E, 19>(Loc, Type, P, SA);
+ applyMipsPcReloc<E, 19, 2>(Loc, Type, Val);
break;
case R_MIPS_PC21_S2:
- applyMipsPcReloc<E, 21>(Loc, Type, P, SA);
+ applyMipsPcReloc<E, 21, 2>(Loc, Type, Val);
break;
case R_MIPS_PC26_S2:
- applyMipsPcReloc<E, 26>(Loc, Type, P, SA);
- break;
- case R_MIPS_PCHI16: {
- uint32_t Instr = read32<E>(Loc);
- if (PairedLoc) {
- uint64_t AHL = ((Instr & 0xffff) << 16) +
- SignExtend64<16>(read32<E>(PairedLoc) & 0xffff);
- write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA + AHL - P));
- } else {
- warning("Can't find matching R_MIPS_PCLO16 relocation for R_MIPS_PCHI16");
- write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA - P));
- }
+ applyMipsPcReloc<E, 26, 2>(Loc, Type, Val);
break;
- }
- case R_MIPS_PCLO16: {
- uint32_t Instr = read32<E>(Loc);
- int64_t AHL = SignExtend64<16>(Instr & 0xffff);
- write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL - P) & 0xffff));
+ case R_MIPS_PC32:
+ applyMipsPcReloc<E, 32, 0>(Loc, Type, Val);
break;
- }
default:
- error("unrecognized reloc " + Twine(Type));
+ fatal("unrecognized reloc " + Twine(Type));
}
}
template <class ELFT>
-bool MipsTargetInfo<ELFT>::isRelRelative(uint32_t Type) const {
- switch (Type) {
- default:
- return false;
- case R_MIPS_PC16:
- case R_MIPS_PC19_S2:
- case R_MIPS_PC21_S2:
- case R_MIPS_PC26_S2:
- case R_MIPS_PCHI16:
- case R_MIPS_PCLO16:
- return true;
- }
+bool MipsTargetInfo<ELFT>::usesOnlyLowPageBits(uint32_t Type) const {
+ return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST;
}
-
-// _gp is a MIPS-specific ABI-defined symbol which points to
-// a location that is relative to GOT. This function returns
-// the value for the symbol.
-template <class ELFT> typename ELFFile<ELFT>::uintX_t getMipsGpAddr() {
- unsigned GPOffset = 0x7ff0;
- if (uint64_t V = Out<ELFT>::Got->getVA())
- return V + GPOffset;
- return 0;
-}
-
-template uint32_t getMipsGpAddr<ELF32LE>();
-template uint32_t getMipsGpAddr<ELF32BE>();
-template uint64_t getMipsGpAddr<ELF64LE>();
-template uint64_t getMipsGpAddr<ELF64BE>();
}
}
diff --git a/ELF/Target.h b/ELF/Target.h
index e9c5f4b31ae4..d335c1e051b7 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -10,76 +10,57 @@
#ifndef LLD_ELF_TARGET_H
#define LLD_ELF_TARGET_H
+#include "InputSection.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/ELF.h"
#include <memory>
namespace lld {
-namespace elf2 {
+namespace elf {
+class InputFile;
class SymbolBody;
class TargetInfo {
public:
- unsigned getPageSize() const { return PageSize; }
- uint64_t getVAStart() const;
- unsigned getCopyReloc() const { return CopyReloc; }
- unsigned getGotReloc() const { return GotReloc; }
- unsigned getPltReloc() const { return PltReloc; }
- unsigned getRelativeReloc() const { return RelativeReloc; }
- unsigned getIRelativeReloc() const { return IRelativeReloc; }
- bool isTlsLocalDynamicReloc(unsigned Type) const {
- return Type == TlsLocalDynamicReloc;
- }
- bool isTlsGlobalDynamicReloc(unsigned Type) const {
- return Type == TlsGlobalDynamicReloc;
- }
- unsigned getTlsModuleIndexReloc() const { return TlsModuleIndexReloc; }
- unsigned getTlsOffsetReloc() const { return TlsOffsetReloc; }
- unsigned getPltZeroEntrySize() const { return PltZeroEntrySize; }
- unsigned getPltEntrySize() const { return PltEntrySize; }
- bool supportsLazyRelocations() const { return LazyRelocations; }
- unsigned getGotHeaderEntriesNum() const { return GotHeaderEntriesNum; }
- unsigned getGotPltHeaderEntriesNum() const { return GotPltHeaderEntriesNum; }
- virtual unsigned getDynReloc(unsigned Type) const { return Type; }
- virtual bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
- return false;
- }
- virtual unsigned getTlsGotReloc(unsigned Type = -1) const {
- return TlsGotReloc;
- }
- virtual void writeGotHeaderEntries(uint8_t *Buf) const;
- virtual void writeGotPltHeaderEntries(uint8_t *Buf) const;
- virtual void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const = 0;
- virtual void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
- uint64_t PltEntryAddr) const = 0;
- virtual void writePltEntry(uint8_t *Buf, uint64_t GotAddr,
- uint64_t GotEntryAddr, uint64_t PltEntryAddr,
- int32_t Index, unsigned RelOff) const = 0;
-
- // Returns true if a relocation is relative to the place being relocated,
- // such as relocations used for PC-relative instructions. Such relocations
- // need not be fixed up if an image is loaded to a different address than
- // the link-time address. So we don't have to emit a relocation for the
- // dynamic linker if isRelRelative returns true.
- virtual bool isRelRelative(uint32_t Type) const;
-
- virtual bool isSizeReloc(uint32_t Type) const;
- virtual bool relocNeedsDynRelative(unsigned Type) const { return false; }
- virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
- virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
- virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
- uint64_t P, uint64_t SA, uint64_t ZA = 0,
- uint8_t *PairedLoc = nullptr) const = 0;
- virtual bool isGotRelative(uint32_t Type) const;
- virtual bool isTlsOptimized(unsigned Type, const SymbolBody *S) const;
- virtual bool needsCopyRel(uint32_t Type, const SymbolBody &S) const;
- virtual unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
- uint32_t Type, uint64_t P, uint64_t SA,
- const SymbolBody &S) const;
+ virtual bool isTlsInitialExecRel(uint32_t Type) const;
+ virtual bool isTlsLocalDynamicRel(uint32_t Type) const;
+ virtual bool isTlsGlobalDynamicRel(uint32_t Type) const;
+ virtual uint32_t getDynRel(uint32_t Type) const { return Type; }
+ virtual void writeGotPltHeader(uint8_t *Buf) const {}
+ virtual void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {};
+ virtual uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const;
+
+ // If lazy binding is supported, the first entry of the PLT has code
+ // to call the dynamic linker to resolve PLT entries the first time
+ // they are called. This function writes that code.
+ virtual void writePltHeader(uint8_t *Buf) const {}
+
+ virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {}
+
+ // Returns true if a relocation only uses the low bits of a value such that
+ // all those bits are in in the same page. For example, if the relocation
+ // only uses the low 12 bits in a system with 4k pages. If this is true, the
+ // bits will always have the same value at runtime and we don't have to emit
+ // a dynamic relocation.
+ virtual bool usesOnlyLowPageBits(uint32_t Type) const;
+
+ // Decide whether a Thunk is needed for the relocation from File
+ // targeting S. Returns one of:
+ // Expr if there is no Thunk required
+ // R_THUNK_ABS if thunk is required and expression is absolute
+ // R_THUNK_PC if thunk is required and expression is pc rel
+ // R_THUNK_PLT_PC if thunk is required to PLT entry and expression is pc rel
+ virtual RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType,
+ const InputFile &File,
+ const SymbolBody &S) const;
+ virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const = 0;
+ virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0;
virtual ~TargetInfo();
-protected:
+ unsigned TlsGdRelaxSkip = 1;
unsigned PageSize = 4096;
// On freebsd x86_64 the first page cannot be mmaped.
@@ -88,34 +69,44 @@ protected:
// Given that, the smallest value that can be used in here is 0x10000.
// If using 2MB pages, the smallest page aligned address that works is
// 0x200000, but it looks like every OS uses 4k pages for executables.
- uint64_t VAStart = 0x10000;
-
- unsigned CopyReloc;
- unsigned PCRelReloc;
- unsigned GotReloc;
- unsigned PltReloc;
- unsigned RelativeReloc;
- unsigned IRelativeReloc;
- unsigned TlsGotReloc = 0;
- unsigned TlsLocalDynamicReloc = 0;
- unsigned TlsGlobalDynamicReloc = 0;
- unsigned TlsModuleIndexReloc;
- unsigned TlsOffsetReloc;
- unsigned PltEntrySize = 8;
- unsigned PltZeroEntrySize = 0;
- unsigned GotHeaderEntriesNum = 0;
+ uint64_t DefaultImageBase = 0x10000;
+
+ uint32_t CopyRel;
+ uint32_t GotRel;
+ uint32_t PltRel;
+ uint32_t RelativeRel;
+ uint32_t IRelativeRel;
+ uint32_t TlsDescRel;
+ uint32_t TlsGotRel;
+ uint32_t TlsModuleIndexRel;
+ uint32_t TlsOffsetRel;
+ unsigned GotEntrySize;
+ unsigned GotPltEntrySize;
+ unsigned PltEntrySize;
+ unsigned PltHeaderSize;
+
+ // At least on x86_64 positions 1 and 2 are used by the first plt entry
+ // to support lazy loading.
unsigned GotPltHeaderEntriesNum = 3;
- bool LazyRelocations = false;
+
+ // Set to 0 for variant 2
+ unsigned TcbSize = 0;
+
+ virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
+ RelExpr Expr) const;
+ virtual void relaxGot(uint8_t *Loc, uint64_t Val) const;
+ virtual void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
+ virtual void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
+ virtual void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
+ virtual void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
};
+StringRef getRelName(uint32_t Type);
uint64_t getPPC64TocBase();
-template <class ELFT>
-typename llvm::object::ELFFile<ELFT>::uintX_t getMipsGpAddr();
-
-template <class ELFT> bool isGnuIFunc(const SymbolBody &S);
+const unsigned MipsGPOffset = 0x7ff0;
-extern std::unique_ptr<TargetInfo> Target;
+extern TargetInfo *Target;
TargetInfo *createTarget();
}
}
diff --git a/ELF/Thunks.cpp b/ELF/Thunks.cpp
new file mode 100644
index 000000000000..1ebbb17f3032
--- /dev/null
+++ b/ELF/Thunks.cpp
@@ -0,0 +1,268 @@
+//===- Thunks.cpp --------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// This file contains Thunk subclasses.
+//
+// A thunk is a small piece of code written after an input section
+// which is used to jump between "incompatible" functions
+// such as MIPS PIC and non-PIC or ARM non-Thumb and Thumb functions.
+//
+// If a jump target is too far and its address doesn't fit to a
+// short jump instruction, we need to create a thunk too, but we
+// haven't supported it yet.
+//
+// i386 and x86-64 don't need thunks.
+//
+//===---------------------------------------------------------------------===//
+
+#include "Thunks.h"
+#include "Error.h"
+#include "InputFiles.h"
+#include "InputSection.h"
+#include "OutputSections.h"
+#include "Symbols.h"
+#include "Target.h"
+#include "llvm/Support/Allocator.h"
+
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+using namespace llvm::ELF;
+
+namespace lld {
+namespace elf {
+
+namespace {
+// Specific ARM Thunk implementations. The naming convention is:
+// Source State, TargetState, Target Requirement, ABS or PI, Range
+template <class ELFT>
+class ARMToThumbV7ABSLongThunk final : public Thunk<ELFT> {
+public:
+ ARMToThumbV7ABSLongThunk(const SymbolBody &Dest,
+ const InputSection<ELFT> &Owner)
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 12; }
+ void writeTo(uint8_t *Buf) const override;
+};
+
+template <class ELFT> class ARMToThumbV7PILongThunk final : public Thunk<ELFT> {
+public:
+ ARMToThumbV7PILongThunk(const SymbolBody &Dest,
+ const InputSection<ELFT> &Owner)
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 16; }
+ void writeTo(uint8_t *Buf) const override;
+};
+
+template <class ELFT>
+class ThumbToARMV7ABSLongThunk final : public Thunk<ELFT> {
+public:
+ ThumbToARMV7ABSLongThunk(const SymbolBody &Dest,
+ const InputSection<ELFT> &Owner)
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 10; }
+ void writeTo(uint8_t *Buf) const override;
+};
+
+template <class ELFT> class ThumbToARMV7PILongThunk final : public Thunk<ELFT> {
+public:
+ ThumbToARMV7PILongThunk(const SymbolBody &Dest,
+ const InputSection<ELFT> &Owner)
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 12; }
+ void writeTo(uint8_t *Buf) const override;
+};
+
+// MIPS LA25 thunk
+template <class ELFT> class MipsThunk final : public Thunk<ELFT> {
+public:
+ MipsThunk(const SymbolBody &Dest, const InputSection<ELFT> &Owner)
+ : Thunk<ELFT>(Dest, Owner) {}
+
+ uint32_t size() const override { return 16; }
+ void writeTo(uint8_t *Buf) const override;
+};
+} // anonymous namespace
+
+// ARM Target Thunks
+template <class ELFT> static uint64_t getARMThunkDestVA(const SymbolBody &S) {
+ return S.isInPlt() ? S.getPltVA<ELFT>() : S.getVA<ELFT>();
+}
+
+template <class ELFT>
+void ARMToThumbV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf) const {
+ const uint8_t Data[] = {
+ 0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S
+ 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S
+ 0x1c, 0xff, 0x2f, 0xe1, // bx ip
+ };
+ uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
+ memcpy(Buf, Data, sizeof(Data));
+ Target->relocateOne(Buf, R_ARM_MOVW_ABS_NC, S);
+ Target->relocateOne(Buf + 4, R_ARM_MOVT_ABS, S);
+}
+
+template <class ELFT>
+void ThumbToARMV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf) const {
+ const uint8_t Data[] = {
+ 0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
+ 0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S
+ 0x60, 0x47, // bx ip
+ };
+ uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
+ memcpy(Buf, Data, sizeof(Data));
+ Target->relocateOne(Buf, R_ARM_THM_MOVW_ABS_NC, S);
+ Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_ABS, S);
+}
+
+template <class ELFT>
+void ARMToThumbV7PILongThunk<ELFT>::writeTo(uint8_t *Buf) const {
+ const uint8_t Data[] = {
+ 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) +8)
+ 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P+4) +8)
+ 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
+ 0x1c, 0xff, 0x2f, 0xe1, // bx r12
+ };
+ uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
+ uint64_t P = this->getVA();
+ memcpy(Buf, Data, sizeof(Data));
+ Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, S - P - 16);
+ Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, S - P - 12);
+}
+
+template <class ELFT>
+void ThumbToARMV7PILongThunk<ELFT>::writeTo(uint8_t *Buf) const {
+ const uint8_t Data[] = {
+ 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
+ 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P+4) + 4)
+ 0xfc, 0x44, // L1: add r12, pc
+ 0x60, 0x47, // bx r12
+ };
+ uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
+ uint64_t P = this->getVA();
+ memcpy(Buf, Data, sizeof(Data));
+ Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, S - P - 12);
+ Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, S - P - 8);
+}
+
+// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
+template <class ELFT> void MipsThunk<ELFT>::writeTo(uint8_t *Buf) const {
+ const endianness E = ELFT::TargetEndianness;
+
+ uint64_t S = this->Destination.template getVA<ELFT>();
+ write32<E>(Buf, 0x3c190000); // lui $25, %hi(func)
+ write32<E>(Buf + 4, 0x08000000 | (S >> 2)); // j func
+ write32<E>(Buf + 8, 0x27390000); // addiu $25, $25, %lo(func)
+ write32<E>(Buf + 12, 0x00000000); // nop
+ Target->relocateOne(Buf, R_MIPS_HI16, S);
+ Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
+}
+
+template <class ELFT>
+Thunk<ELFT>::Thunk(const SymbolBody &D, const InputSection<ELFT> &O)
+ : Destination(D), Owner(O), Offset(O.getThunkOff() + O.getThunksSize()) {}
+
+template <class ELFT> typename ELFT::uint Thunk<ELFT>::getVA() const {
+ return Owner.OutSec->getVA() + Owner.OutSecOff + Offset;
+}
+
+template <class ELFT> Thunk<ELFT>::~Thunk() {}
+
+// Creates a thunk for Thumb-ARM interworking.
+template <class ELFT>
+static Thunk<ELFT> *createThunkArm(uint32_t Reloc, SymbolBody &S,
+ InputSection<ELFT> &IS) {
+ // ARM relocations need ARM to Thumb interworking Thunks.
+ // Thumb relocations need Thumb to ARM relocations.
+ // Use position independent Thunks if we require position independent code.
+ BumpPtrAllocator &Alloc = IS.getFile()->Alloc;
+ switch (Reloc) {
+ case R_ARM_PC24:
+ case R_ARM_PLT32:
+ case R_ARM_JUMP24:
+ if (Config->Pic)
+ return new (Alloc) ARMToThumbV7PILongThunk<ELFT>(S, IS);
+ return new (Alloc) ARMToThumbV7ABSLongThunk<ELFT>(S, IS);
+ case R_ARM_THM_JUMP19:
+ case R_ARM_THM_JUMP24:
+ if (Config->Pic)
+ return new (Alloc) ThumbToARMV7PILongThunk<ELFT>(S, IS);
+ return new (Alloc) ThumbToARMV7ABSLongThunk<ELFT>(S, IS);
+ }
+ fatal("unrecognized relocation type");
+}
+
+template <class ELFT>
+static void addThunkARM(uint32_t Reloc, SymbolBody &S, InputSection<ELFT> &IS) {
+ // Only one Thunk supported per symbol.
+ if (S.hasThunk<ELFT>())
+ return;
+
+ // ARM Thunks are added to the same InputSection as the relocation. This
+ // isn't strictly necessary but it makes it more likely that a limited range
+ // branch can reach the Thunk, and it makes Thunks to the PLT section easier
+ Thunk<ELFT> *T = createThunkArm(Reloc, S, IS);
+ IS.addThunk(T);
+ if (auto *Sym = dyn_cast<DefinedRegular<ELFT>>(&S))
+ Sym->ThunkData = T;
+ else if (auto *Sym = dyn_cast<SharedSymbol<ELFT>>(&S))
+ Sym->ThunkData = T;
+ else
+ fatal("symbol not DefinedRegular or Shared");
+}
+
+template <class ELFT>
+static void addThunkMips(uint32_t RelocType, SymbolBody &S,
+ InputSection<ELFT> &IS) {
+ // Only one Thunk supported per symbol.
+ if (S.hasThunk<ELFT>())
+ return;
+
+ // Mips Thunks are added to the InputSection defining S.
+ auto *R = cast<DefinedRegular<ELFT>>(&S);
+ auto *Sec = cast<InputSection<ELFT>>(R->Section);
+ auto *T = new (IS.getFile()->Alloc) MipsThunk<ELFT>(S, *Sec);
+ Sec->addThunk(T);
+ R->ThunkData = T;
+}
+
+template <class ELFT>
+void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT> &IS) {
+ if (Config->EMachine == EM_ARM)
+ addThunkARM<ELFT>(RelocType, S, IS);
+ else if (Config->EMachine == EM_MIPS)
+ addThunkMips<ELFT>(RelocType, S, IS);
+ else
+ llvm_unreachable("add Thunk only supported for ARM and Mips");
+}
+
+template void addThunk<ELF32LE>(uint32_t, SymbolBody &,
+ InputSection<ELF32LE> &);
+template void addThunk<ELF32BE>(uint32_t, SymbolBody &,
+ InputSection<ELF32BE> &);
+template void addThunk<ELF64LE>(uint32_t, SymbolBody &,
+ InputSection<ELF64LE> &);
+template void addThunk<ELF64BE>(uint32_t, SymbolBody &,
+ InputSection<ELF64BE> &);
+
+template class Thunk<ELF32LE>;
+template class Thunk<ELF32BE>;
+template class Thunk<ELF64LE>;
+template class Thunk<ELF64BE>;
+
+} // namespace elf
+} // namespace lld
diff --git a/ELF/Thunks.h b/ELF/Thunks.h
new file mode 100644
index 000000000000..b937d7918491
--- /dev/null
+++ b/ELF/Thunks.h
@@ -0,0 +1,56 @@
+//===- Thunks.h --------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_THUNKS_H
+#define LLD_ELF_THUNKS_H
+
+#include "Relocations.h"
+
+namespace lld {
+namespace elf {
+class SymbolBody;
+template <class ELFT> class InputSection;
+
+// Class to describe an instance of a Thunk.
+// A Thunk is a code-sequence inserted by the linker in between a caller and
+// the callee. The relocation to the callee is redirected to the Thunk, which
+// after executing transfers control to the callee. Typical uses of Thunks
+// include transferring control from non-pi to pi and changing state on
+// targets like ARM.
+//
+// Thunks can be created for DefinedRegular and Shared Symbols. The Thunk
+// is stored in a field of the Symbol Destination.
+// Thunks to be written to an InputSection are recorded by the InputSection.
+template <class ELFT> class Thunk {
+ typedef typename ELFT::uint uintX_t;
+
+public:
+ Thunk(const SymbolBody &Destination, const InputSection<ELFT> &Owner);
+ virtual ~Thunk();
+
+ virtual uint32_t size() const { return 0; }
+ virtual void writeTo(uint8_t *Buf) const {}
+ uintX_t getVA() const;
+
+protected:
+ const SymbolBody &Destination;
+ const InputSection<ELFT> &Owner;
+ uint64_t Offset;
+};
+
+// For a Relocation to symbol S from InputSection Src, create a Thunk and
+// update the fields of S and the InputSection that the Thunk body will be
+// written to. At present there are implementations for ARM and Mips Thunks.
+template <class ELFT>
+void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT> &Src);
+
+} // namespace elf
+} // namespace lld
+
+#endif
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index fbecfc601ac1..387bec3d8fb2 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -9,362 +9,353 @@
#include "Writer.h"
#include "Config.h"
+#include "LinkerScript.h"
#include "OutputSections.h"
+#include "Relocations.h"
+#include "Strings.h"
#include "SymbolTable.h"
#include "Target.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
namespace {
// The writer writes a SymbolTable result to a file.
template <class ELFT> class Writer {
public:
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
- typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
- typedef typename ELFFile<ELFT>::Elf_Phdr Elf_Phdr;
- typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
- typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
- typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Ehdr Elf_Ehdr;
+ typedef typename ELFT::Phdr Elf_Phdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::SymRange Elf_Sym_Range;
+ typedef typename ELFT::Rela Elf_Rela;
Writer(SymbolTable<ELFT> &S) : Symtab(S) {}
void run();
private:
+ // This describes a program header entry.
+ // Each contains type, access flags and range of output sections that will be
+ // placed in it.
+ struct Phdr {
+ Phdr(unsigned Type, unsigned Flags) {
+ H.p_type = Type;
+ H.p_flags = Flags;
+ }
+ Elf_Phdr H = {};
+ OutputSectionBase<ELFT> *First = nullptr;
+ OutputSectionBase<ELFT> *Last = nullptr;
+ };
+
void copyLocalSymbols();
void addReservedSymbols();
void createSections();
void addPredefinedSections();
+ bool needsGot();
- template <bool isRela>
- void scanRelocs(InputSectionBase<ELFT> &C,
- iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels);
-
- void scanRelocs(InputSection<ELFT> &C);
- void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
- void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr, uintX_t VA);
+ void createPhdrs();
void assignAddresses();
- void buildSectionMap();
+ void assignFileOffsets();
+ void setPhdrs();
+ void fixHeaders();
+ void fixSectionAlignments();
void fixAbsoluteSymbols();
- void openFile(StringRef OutputPath);
+ void openFile();
void writeHeader();
void writeSections();
- bool isDiscarded(InputSectionBase<ELFT> *IS) const;
- StringRef getOutputSectionName(StringRef S) const;
+ void writeBuildId();
bool needsInterpSection() const {
return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty();
}
bool isOutputDynamic() const {
- return !Symtab.getSharedFiles().empty() || Config->Shared;
+ return !Symtab.getSharedFiles().empty() || Config->Pic;
}
- int getPhdrsNum() const;
- OutputSection<ELFT> *getBss();
void addCommonSymbols(std::vector<DefinedCommon *> &Syms);
- void addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms);
- std::unique_ptr<llvm::FileOutputBuffer> Buffer;
+ std::unique_ptr<FileOutputBuffer> Buffer;
BumpPtrAllocator Alloc;
std::vector<OutputSectionBase<ELFT> *> OutputSections;
std::vector<std::unique_ptr<OutputSectionBase<ELFT>>> OwningSections;
- unsigned getNumSections() const { return OutputSections.size() + 1; }
void addRelIpltSymbols();
void addStartEndSymbols();
void addStartStopSymbols(OutputSectionBase<ELFT> *Sec);
- void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff,
- uintX_t VA, uintX_t Size, uintX_t Align);
- void copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From);
- bool HasRelro = false;
SymbolTable<ELFT> &Symtab;
- std::vector<Elf_Phdr> Phdrs;
+ std::vector<Phdr> Phdrs;
uintX_t FileSize;
uintX_t SectionHeaderOff;
-
- llvm::StringMap<llvm::StringRef> InputToOutputSection;
};
} // anonymous namespace
-template <class ELFT> static bool shouldUseRela() { return ELFT::Is64Bits; }
+template <class ELFT>
+StringRef elf::getOutputSectionName(InputSectionBase<ELFT> *S) {
+ StringRef Dest = Script<ELFT>::X->getOutputSection(S);
+ if (!Dest.empty())
+ return Dest;
+
+ StringRef Name = S->getSectionName();
+ for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.",
+ ".init_array.", ".fini_array.", ".ctors.", ".dtors.",
+ ".tbss.", ".gcc_except_table.", ".tdata."})
+ if (Name.startswith(V))
+ return V.drop_back();
+ return Name;
+}
-template <class ELFT> void elf2::writeResult(SymbolTable<ELFT> *Symtab) {
- // Initialize output sections that are handled by Writer specially.
- // Don't reorder because the order of initialization matters.
- InterpSection<ELFT> Interp;
- Out<ELFT>::Interp = &Interp;
- StringTableSection<ELFT> ShStrTab(".shstrtab", false);
- Out<ELFT>::ShStrTab = &ShStrTab;
- StringTableSection<ELFT> StrTab(".strtab", false);
- if (!Config->StripAll)
- Out<ELFT>::StrTab = &StrTab;
- StringTableSection<ELFT> DynStrTab(".dynstr", true);
- Out<ELFT>::DynStrTab = &DynStrTab;
+template <class ELFT>
+void elf::reportDiscarded(InputSectionBase<ELFT> *IS,
+ const std::unique_ptr<elf::ObjectFile<ELFT>> &File) {
+ if (!Config->PrintGcSections || !IS || IS->Live)
+ return;
+ errs() << "removing unused section from '" << IS->getSectionName()
+ << "' in file '" << File->getName() << "'\n";
+}
+
+template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
+ typedef typename ELFT::uint uintX_t;
+ typedef typename ELFT::Ehdr Elf_Ehdr;
+
+ // Create singleton output sections.
+ OutputSection<ELFT> Bss(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
+ DynamicSection<ELFT> Dynamic;
+ EhOutputSection<ELFT> EhFrame;
GotSection<ELFT> Got;
- Out<ELFT>::Got = &Got;
- GotPltSection<ELFT> GotPlt;
- if (Target->supportsLazyRelocations())
- Out<ELFT>::GotPlt = &GotPlt;
+ InterpSection<ELFT> Interp;
PltSection<ELFT> Plt;
- Out<ELFT>::Plt = &Plt;
- std::unique_ptr<SymbolTableSection<ELFT>> SymTab;
+ RelocationSection<ELFT> RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn",
+ Config->ZCombreloc);
+ StringTableSection<ELFT> DynStrTab(".dynstr", true);
+ StringTableSection<ELFT> ShStrTab(".shstrtab", false);
+ SymbolTableSection<ELFT> DynSymTab(DynStrTab);
+ VersionTableSection<ELFT> VerSym;
+ VersionNeedSection<ELFT> VerNeed;
+
+ OutputSectionBase<ELFT> ElfHeader("", 0, SHF_ALLOC);
+ ElfHeader.setSize(sizeof(Elf_Ehdr));
+ OutputSectionBase<ELFT> ProgramHeaders("", 0, SHF_ALLOC);
+ ProgramHeaders.updateAlignment(sizeof(uintX_t));
+
+ // Instantiate optional output sections if they are needed.
+ std::unique_ptr<BuildIdSection<ELFT>> BuildId;
+ std::unique_ptr<EhFrameHeader<ELFT>> EhFrameHdr;
+ std::unique_ptr<GnuHashTableSection<ELFT>> GnuHashTab;
+ std::unique_ptr<GotPltSection<ELFT>> GotPlt;
+ std::unique_ptr<HashTableSection<ELFT>> HashTab;
+ std::unique_ptr<RelocationSection<ELFT>> RelaPlt;
+ std::unique_ptr<StringTableSection<ELFT>> StrTab;
+ std::unique_ptr<SymbolTableSection<ELFT>> SymTabSec;
+ std::unique_ptr<OutputSection<ELFT>> MipsRldMap;
+ std::unique_ptr<VersionDefinitionSection<ELFT>> VerDef;
+
+ if (Config->BuildId == BuildIdKind::Fnv1)
+ BuildId.reset(new BuildIdFnv1<ELFT>);
+ else if (Config->BuildId == BuildIdKind::Md5)
+ BuildId.reset(new BuildIdMd5<ELFT>);
+ else if (Config->BuildId == BuildIdKind::Sha1)
+ BuildId.reset(new BuildIdSha1<ELFT>);
+ else if (Config->BuildId == BuildIdKind::Hexstring)
+ BuildId.reset(new BuildIdHexstring<ELFT>);
+
+ if (Config->EhFrameHdr)
+ EhFrameHdr.reset(new EhFrameHeader<ELFT>);
+
+ if (Config->GnuHash)
+ GnuHashTab.reset(new GnuHashTableSection<ELFT>);
+ if (Config->SysvHash)
+ HashTab.reset(new HashTableSection<ELFT>);
+ StringRef S = Config->Rela ? ".rela.plt" : ".rel.plt";
+ GotPlt.reset(new GotPltSection<ELFT>);
+ RelaPlt.reset(new RelocationSection<ELFT>(S, false /*Sort*/));
if (!Config->StripAll) {
- SymTab.reset(new SymbolTableSection<ELFT>(*Symtab, *Out<ELFT>::StrTab));
- Out<ELFT>::SymTab = SymTab.get();
+ StrTab.reset(new StringTableSection<ELFT>(".strtab", false));
+ SymTabSec.reset(new SymbolTableSection<ELFT>(*StrTab));
}
- SymbolTableSection<ELFT> DynSymTab(*Symtab, *Out<ELFT>::DynStrTab);
+ if (Config->EMachine == EM_MIPS && !Config->Shared) {
+ // This is a MIPS specific section to hold a space within the data segment
+ // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry.
+ // See "Dynamic section" in Chapter 5 in the following document:
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ MipsRldMap.reset(new OutputSection<ELFT>(".rld_map", SHT_PROGBITS,
+ SHF_ALLOC | SHF_WRITE));
+ MipsRldMap->setSize(sizeof(uintX_t));
+ MipsRldMap->updateAlignment(sizeof(uintX_t));
+ }
+ if (!Config->VersionDefinitions.empty())
+ VerDef.reset(new VersionDefinitionSection<ELFT>());
+
+ Out<ELFT>::Bss = &Bss;
+ Out<ELFT>::BuildId = BuildId.get();
+ Out<ELFT>::DynStrTab = &DynStrTab;
Out<ELFT>::DynSymTab = &DynSymTab;
- HashTableSection<ELFT> HashTab;
- if (Config->SysvHash)
- Out<ELFT>::HashTab = &HashTab;
- GnuHashTableSection<ELFT> GnuHashTab;
- if (Config->GnuHash)
- Out<ELFT>::GnuHashTab = &GnuHashTab;
- bool IsRela = shouldUseRela<ELFT>();
- RelocationSection<ELFT> RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela);
- Out<ELFT>::RelaDyn = &RelaDyn;
- RelocationSection<ELFT> RelaPlt(IsRela ? ".rela.plt" : ".rel.plt", IsRela);
- if (Target->supportsLazyRelocations())
- Out<ELFT>::RelaPlt = &RelaPlt;
- DynamicSection<ELFT> Dynamic(*Symtab);
Out<ELFT>::Dynamic = &Dynamic;
+ Out<ELFT>::EhFrame = &EhFrame;
+ Out<ELFT>::EhFrameHdr = EhFrameHdr.get();
+ Out<ELFT>::GnuHashTab = GnuHashTab.get();
+ Out<ELFT>::Got = &Got;
+ Out<ELFT>::GotPlt = GotPlt.get();
+ Out<ELFT>::HashTab = HashTab.get();
+ Out<ELFT>::Interp = &Interp;
+ Out<ELFT>::Plt = &Plt;
+ Out<ELFT>::RelaDyn = &RelaDyn;
+ Out<ELFT>::RelaPlt = RelaPlt.get();
+ Out<ELFT>::ShStrTab = &ShStrTab;
+ Out<ELFT>::StrTab = StrTab.get();
+ Out<ELFT>::SymTab = SymTabSec.get();
+ Out<ELFT>::VerDef = VerDef.get();
+ Out<ELFT>::VerSym = &VerSym;
+ Out<ELFT>::VerNeed = &VerNeed;
+ Out<ELFT>::MipsRldMap = MipsRldMap.get();
+ Out<ELFT>::Opd = nullptr;
+ Out<ELFT>::OpdBuf = nullptr;
+ Out<ELFT>::TlsPhdr = nullptr;
+ Out<ELFT>::ElfHeader = &ElfHeader;
+ Out<ELFT>::ProgramHeaders = &ProgramHeaders;
Writer<ELFT>(*Symtab).run();
}
// The main function of the writer.
template <class ELFT> void Writer<ELFT>::run() {
- buildSectionMap();
if (!Config->DiscardAll)
copyLocalSymbols();
addReservedSymbols();
createSections();
- assignAddresses();
- fixAbsoluteSymbols();
- openFile(Config->OutputFile);
- writeHeader();
- writeSections();
- error(Buffer->commit());
-}
+ if (HasError)
+ return;
-namespace {
-template <bool Is64Bits> struct SectionKey {
- typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
- StringRef Name;
- uint32_t Type;
- uintX_t Flags;
- uintX_t EntSize;
-};
-}
-namespace llvm {
-template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {
- static SectionKey<Is64Bits> getEmptyKey() {
- return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0,
- 0};
- }
- static SectionKey<Is64Bits> getTombstoneKey() {
- return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0,
- 0, 0};
- }
- static unsigned getHashValue(const SectionKey<Is64Bits> &Val) {
- return hash_combine(Val.Name, Val.Type, Val.Flags, Val.EntSize);
- }
- static bool isEqual(const SectionKey<Is64Bits> &LHS,
- const SectionKey<Is64Bits> &RHS) {
- return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
- LHS.Type == RHS.Type && LHS.Flags == RHS.Flags &&
- LHS.EntSize == RHS.EntSize;
+ if (Config->Relocatable) {
+ assignFileOffsets();
+ } else {
+ createPhdrs();
+ fixHeaders();
+ if (ScriptConfig->DoLayout) {
+ Script<ELFT>::X->assignAddresses(OutputSections);
+ } else {
+ fixSectionAlignments();
+ assignAddresses();
+ }
+ assignFileOffsets();
+ setPhdrs();
+ fixAbsoluteSymbols();
}
-};
+
+ openFile();
+ if (HasError)
+ return;
+ writeHeader();
+ writeSections();
+ writeBuildId();
+ if (HasError)
+ return;
+ if (auto EC = Buffer->commit())
+ error(EC, "failed to write to the output file");
}
-// The reason we have to do this early scan is as follows
-// * To mmap the output file, we need to know the size
-// * For that, we need to know how many dynamic relocs we will have.
-// It might be possible to avoid this by outputting the file with write:
-// * Write the allocated output sections, computing addresses.
-// * Apply relocations, recording which ones require a dynamic reloc.
-// * Write the dynamic relocations.
-// * Write the rest of the file.
template <class ELFT>
-template <bool isRela>
-void Writer<ELFT>::scanRelocs(
- InputSectionBase<ELFT> &C,
- iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
- typedef Elf_Rel_Impl<ELFT, isRela> RelType;
- const ObjectFile<ELFT> &File = *C.getFile();
- for (const RelType &RI : Rels) {
- uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
- SymbolBody *Body = File.getSymbolBody(SymIndex);
- uint32_t Type = RI.getType(Config->Mips64EL);
-
- if (Target->isGotRelative(Type))
- HasGotOffRel = true;
-
- if (Target->isTlsLocalDynamicReloc(Type)) {
- if (Target->isTlsOptimized(Type, nullptr))
- continue;
- if (Out<ELFT>::Got->addCurrentModuleTlsIndex())
- Out<ELFT>::RelaDyn->addReloc({&C, &RI});
- continue;
- }
-
- // Set "used" bit for --as-needed.
- if (Body && Body->isUndefined() && !Body->isWeak())
- if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl()))
- S->File->IsUsed = true;
-
- if (Body)
- Body = Body->repl();
-
- if (Body && Body->isTls() && Target->isTlsGlobalDynamicReloc(Type)) {
- bool Opt = Target->isTlsOptimized(Type, Body);
- if (!Opt && Out<ELFT>::Got->addDynTlsEntry(Body)) {
- Out<ELFT>::RelaDyn->addReloc({&C, &RI});
- Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr});
- Body->setUsedInDynamicReloc();
- continue;
- }
- if (!canBePreempted(Body, true))
- continue;
- }
-
- if (Body && Body->isTls() && !Target->isTlsDynReloc(Type, *Body))
- continue;
+static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {
+ if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore)
+ return;
- if (Target->relocNeedsDynRelative(Type)) {
- RelType *Rel = new (Alloc) RelType;
- Rel->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
- Rel->r_offset = RI.r_offset;
- Out<ELFT>::RelaDyn->addReloc({&C, Rel});
- }
+ if (Config->Shared && Sym->symbol()->Visibility == STV_DEFAULT &&
+ Config->UnresolvedSymbols != UnresolvedPolicy::NoUndef)
+ return;
- bool NeedsGot = false;
- bool NeedsPlt = false;
- if (Body) {
- if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
- if (E->NeedsCopy)
- continue;
- if (Target->needsCopyRel(Type, *Body))
- E->NeedsCopy = true;
- }
- NeedsPlt = Target->relocNeedsPlt(Type, *Body);
- if (NeedsPlt) {
- if (Body->isInPlt())
- continue;
- Out<ELFT>::Plt->addEntry(Body);
- }
- NeedsGot = Target->relocNeedsGot(Type, *Body);
- if (NeedsGot) {
- if (NeedsPlt && Target->supportsLazyRelocations()) {
- Out<ELFT>::GotPlt->addEntry(Body);
- } else {
- if (Body->isInGot())
- continue;
- Out<ELFT>::Got->addEntry(Body);
- }
- }
- }
+ std::string Msg = "undefined symbol: " + Sym->getName().str();
+ if (Sym->File)
+ Msg += " in " + getFilename(Sym->File);
+ if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn)
+ warning(Msg);
+ else
+ error(Msg);
+}
- // An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
- // to the symbol go through the PLT. This is true even for a local
- // symbol, although local symbols normally do not require PLT entries.
- if (Body && isGnuIFunc<ELFT>(*Body)) {
- Body->setUsedInDynamicReloc();
- Out<ELFT>::RelaPlt->addReloc({&C, &RI});
- continue;
- }
+template <class ELFT>
+static bool shouldKeepInSymtab(InputSectionBase<ELFT> *Sec, StringRef SymName,
+ const SymbolBody &B) {
+ if (B.isFile())
+ return false;
- if (Config->EMachine == EM_MIPS) {
- if (NeedsGot) {
- // MIPS ABI has special rules to process GOT entries
- // and doesn't require relocation entries for them.
- // See "Global Offset Table" in Chapter 5 in the following document
- // for detailed description:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- Body->setUsedInDynamicReloc();
- continue;
- }
- if (Body == Config->MipsGpDisp)
- // MIPS _gp_disp designates offset between start of function and gp
- // pointer into GOT therefore any relocations against it do not require
- // dynamic relocation.
- continue;
- }
+ // We keep sections in symtab for relocatable output.
+ if (B.isSection())
+ return Config->Relocatable;
- // Here we are creating a relocation for the dynamic linker based on
- // a relocation from an object file, but some relocations need no
- // load-time fixup. Skip such relocation.
- bool CBP = canBePreempted(Body, NeedsGot);
- bool NoDynrel = Target->isRelRelative(Type) || Target->isSizeReloc(Type);
- if (!CBP && (NoDynrel || !Config->Shared))
- continue;
+ // If sym references a section in a discarded group, don't keep it.
+ if (Sec == &InputSection<ELFT>::Discarded)
+ return false;
- if (CBP)
- Body->setUsedInDynamicReloc();
- if (NeedsPlt && Target->supportsLazyRelocations())
- Out<ELFT>::RelaPlt->addReloc({&C, &RI});
- else
- Out<ELFT>::RelaDyn->addReloc({&C, &RI});
- }
-}
+ if (Config->DiscardNone)
+ return true;
-template <class ELFT> void Writer<ELFT>::scanRelocs(InputSection<ELFT> &C) {
- if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
- return;
+ // In ELF assembly .L symbols are normally discarded by the assembler.
+ // If the assembler fails to do so, the linker discards them if
+ // * --discard-locals is used.
+ // * The symbol is in a SHF_MERGE section, which is normally the reason for
+ // the assembler keeping the .L symbol.
+ if (!SymName.startswith(".L") && !SymName.empty())
+ return true;
- for (const Elf_Shdr *RelSec : C.RelocSections)
- scanRelocs(C, *RelSec);
-}
+ if (Config->DiscardLocals)
+ return false;
-template <class ELFT>
-void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S,
- const Elf_Shdr &RelSec) {
- ELFFile<ELFT> &EObj = S.getFile()->getObj();
- if (RelSec.sh_type == SHT_RELA)
- scanRelocs(S, EObj.relas(&RelSec));
- else
- scanRelocs(S, EObj.rels(&RelSec));
+ return !(Sec->getSectionHdr()->sh_flags & SHF_MERGE);
}
-template <class ELFT>
-static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {
- if (Config->Shared && !Config->NoUndefined)
- return;
+template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
+ if (!B.isLocal() && !B.symbol()->IsUsedInRegularObj)
+ return false;
- std::string Msg = "undefined symbol: " + Sym->getName().str();
- if (ELFFileBase<ELFT> *File = Symtab.findFile(Sym))
- Msg += " in " + File->getName().str();
- if (Config->NoInhibitExec)
- warning(Msg);
- else
- error(Msg);
+ if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B)) {
+ // Always include absolute symbols.
+ if (!D->Section)
+ return true;
+ // Exclude symbols pointing to garbage-collected sections.
+ if (!D->Section->Live)
+ return false;
+ if (auto *S = dyn_cast<MergeInputSection<ELFT>>(D->Section))
+ if (!S->getSectionPiece(D->Value)->Live)
+ return false;
+ }
+ return true;
}
// Local symbols are not in the linker's symbol table. This function scans
// each object file's symbol table to copy local symbols to the output.
template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
- for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
- for (const Elf_Sym &Sym : F->getLocalSymbols()) {
- ErrorOr<StringRef> SymNameOrErr = Sym.getName(F->getStringTable());
- error(SymNameOrErr);
- StringRef SymName = *SymNameOrErr;
- if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))
+ if (!Out<ELFT>::SymTab)
+ return;
+ for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
+ Symtab.getObjectFiles()) {
+ const char *StrTab = F->getStringTable().data();
+ for (SymbolBody *B : F->getLocalSymbols()) {
+ auto *DR = dyn_cast<DefinedRegular<ELFT>>(B);
+ // No reason to keep local undefined symbol in symtab.
+ if (!DR)
continue;
- if (Out<ELFT>::SymTab)
- Out<ELFT>::SymTab->addLocalSymbol(SymName);
+ if (!includeInSymtab<ELFT>(*B))
+ continue;
+ StringRef SymName(StrTab + B->getNameOffset());
+ InputSectionBase<ELFT> *Sec = DR->Section;
+ if (!shouldKeepInSymtab<ELFT>(Sec, SymName, *B))
+ continue;
+ ++Out<ELFT>::SymTab->NumLocals;
+ if (Config->Relocatable)
+ B->DynsymIndex = Out<ELFT>::SymTab->NumLocals;
+ F->KeptLocalSyms.push_back(
+ std::make_pair(DR, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));
}
}
}
@@ -377,16 +368,18 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
// thus, within reach of the TOC base pointer).
static int getPPC64SectionRank(StringRef SectionName) {
return StringSwitch<int>(SectionName)
- .Case(".tocbss", 0)
- .Case(".branch_lt", 2)
- .Case(".toc", 3)
- .Case(".toc1", 4)
- .Case(".opd", 5)
- .Default(1);
+ .Case(".tocbss", 0)
+ .Case(".branch_lt", 2)
+ .Case(".toc", 3)
+ .Case(".toc1", 4)
+ .Case(".opd", 5)
+ .Default(1);
}
template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) {
- typename OutputSectionBase<ELFT>::uintX_t Flags = Sec->getFlags();
+ if (!Config->ZRelro)
+ return false;
+ typename ELFT::uint Flags = Sec->getFlags();
if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
return false;
if (Flags & SHF_TLS)
@@ -406,9 +399,13 @@ template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) {
// Output section ordering is determined by this function.
template <class ELFT>
-static bool compareOutputSections(OutputSectionBase<ELFT> *A,
- OutputSectionBase<ELFT> *B) {
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+static bool compareSections(OutputSectionBase<ELFT> *A,
+ OutputSectionBase<ELFT> *B) {
+ typedef typename ELFT::uint uintX_t;
+
+ int Comp = Script<ELFT>::X->compareSections(A->getName(), B->getName());
+ if (Comp != 0)
+ return Comp < 0;
uintX_t AFlags = A->getFlags();
uintX_t BFlags = B->getFlags();
@@ -475,16 +472,6 @@ static bool compareOutputSections(OutputSectionBase<ELFT> *A,
return false;
}
-template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBss() {
- if (!Out<ELFT>::Bss) {
- Out<ELFT>::Bss =
- new OutputSection<ELFT>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
- OwningSections.emplace_back(Out<ELFT>::Bss);
- OutputSections.push_back(Out<ELFT>::Bss);
- }
- return Out<ELFT>::Bss;
-}
-
// Until this function is called, common symbols do not belong to any section.
// This function adds them to end of BSS section.
template <class ELFT>
@@ -495,12 +482,13 @@ void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
// Sort the common symbols by alignment as an heuristic to pack them better.
std::stable_sort(Syms.begin(), Syms.end(),
[](const DefinedCommon *A, const DefinedCommon *B) {
- return A->MaxAlignment > B->MaxAlignment;
+ return A->Alignment > B->Alignment;
});
- uintX_t Off = getBss()->getSize();
+ uintX_t Off = Out<ELFT>::Bss->getSize();
for (DefinedCommon *C : Syms) {
- Off = align(Off, C->MaxAlignment);
+ Off = alignTo(Off, C->Alignment);
+ Out<ELFT>::Bss->updateAlignment(C->Alignment);
C->OffsetInBss = Off;
Off += C->Size;
}
@@ -508,75 +496,16 @@ void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
Out<ELFT>::Bss->setSize(Off);
}
-// Reserve space in .bss for copy relocations.
-template <class ELFT>
-void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) {
- if (Syms.empty())
- return;
- uintX_t Off = getBss()->getSize();
- for (SharedSymbol<ELFT> *C : Syms) {
- const Elf_Sym &Sym = C->Sym;
- const Elf_Shdr *Sec = C->File->getSection(Sym);
- uintX_t SecAlign = Sec->sh_addralign;
- unsigned TrailingZeros =
- std::min(countTrailingZeros(SecAlign),
- countTrailingZeros((uintX_t)Sym.st_value));
- uintX_t Align = 1 << TrailingZeros;
- Out<ELFT>::Bss->updateAlign(Align);
- Off = align(Off, Align);
- C->OffsetInBss = Off;
- Off += Sym.st_size;
- }
- Out<ELFT>::Bss->setSize(Off);
-}
-
-template <class ELFT>
-StringRef Writer<ELFT>::getOutputSectionName(StringRef S) const {
- auto It = InputToOutputSection.find(S);
- if (It != std::end(InputToOutputSection))
- return It->second;
-
- if (S.startswith(".text."))
- return ".text";
- if (S.startswith(".rodata."))
- return ".rodata";
- if (S.startswith(".data.rel.ro"))
- return ".data.rel.ro";
- if (S.startswith(".data."))
- return ".data";
- if (S.startswith(".bss."))
- return ".bss";
- return S;
-}
-
-template <class ELFT>
-void reportDiscarded(InputSectionBase<ELFT> *IS,
- const std::unique_ptr<ObjectFile<ELFT>> &File) {
- if (!Config->PrintGcSections || !IS || IS->isLive())
- return;
- llvm::errs() << "removing unused section from '" << IS->getSectionName()
- << "' in file '" << File->getName() << "'\n";
-}
-
template <class ELFT>
-bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *IS) const {
- if (!IS || !IS->isLive() || IS == &InputSection<ELFT>::Discarded)
- return true;
- return InputToOutputSection.lookup(IS->getSectionName()) == "/DISCARD/";
-}
-
-template <class ELFT>
-static bool compareSections(OutputSectionBase<ELFT> *A,
- OutputSectionBase<ELFT> *B) {
- auto ItA = Config->OutputSections.find(A->getName());
- auto ItEnd = std::end(Config->OutputSections);
- if (ItA == ItEnd)
- return compareOutputSections(A, B);
- auto ItB = Config->OutputSections.find(B->getName());
- if (ItB == ItEnd)
- return compareOutputSections(A, B);
-
- return std::distance(ItA, ItB) > 0;
+static Symbol *addOptionalSynthetic(SymbolTable<ELFT> &Table, StringRef Name,
+ OutputSectionBase<ELFT> *Sec,
+ typename ELFT::uint Val) {
+ SymbolBody *S = Table.find(Name);
+ if (!S)
+ return nullptr;
+ if (!S->isUndefined() && !S->isShared())
+ return S->symbol();
+ return Table.addSynthetic(Name, Sec, Val);
}
// The beginning and the ending of .rel[a].plt section are marked
@@ -585,125 +514,57 @@ static bool compareSections(OutputSectionBase<ELFT> *A,
// all IRELATIVE relocs on startup. For dynamic executables, we don't
// need these symbols, since IRELATIVE relocs are resolved through GOT
// and PLT. For details, see http://www.airs.com/blog/archives/403.
-template <class ELFT>
-void Writer<ELFT>::addRelIpltSymbols() {
+template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
if (isOutputDynamic() || !Out<ELFT>::RelaPlt)
return;
- bool IsRela = shouldUseRela<ELFT>();
-
- StringRef S = IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
- if (Symtab.find(S))
- Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltStart);
-
- S = IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
- if (Symtab.find(S))
- Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltEnd);
-}
-
-template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
- if (!B.isUsedInRegularObj())
- return false;
-
- // Don't include synthetic symbols like __init_array_start in every output.
- if (auto *U = dyn_cast<DefinedRegular<ELFT>>(&B))
- if (&U->Sym == &ElfSym<ELFT>::IgnoredWeak ||
- &U->Sym == &ElfSym<ELFT>::Ignored)
- return false;
+ StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
+ addOptionalSynthetic(Symtab, S, Out<ELFT>::RelaPlt, 0);
- return true;
-}
-
-static bool includeInDynamicSymtab(const SymbolBody &B) {
- uint8_t V = B.getVisibility();
- if (V != STV_DEFAULT && V != STV_PROTECTED)
- return false;
- if (Config->ExportDynamic || Config->Shared)
- return true;
- return B.isUsedInDynamicReloc();
-}
-
-// This class knows how to create an output section for a given
-// input section. Output section type is determined by various
-// factors, including input section's sh_flags, sh_type and
-// linker scripts.
-namespace {
-template <class ELFT> class OutputSectionFactory {
- typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename ELFFile<ELFT>::uintX_t uintX_t;
-
-public:
- std::pair<OutputSectionBase<ELFT> *, bool> create(InputSectionBase<ELFT> *C,
- StringRef OutsecName);
-
- OutputSectionBase<ELFT> *lookup(StringRef Name, uint32_t Type, uintX_t Flags);
-
-private:
- SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
- StringRef OutsecName);
-
- SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
-};
-}
-
-template <class ELFT>
-std::pair<OutputSectionBase<ELFT> *, bool>
-OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
- StringRef OutsecName) {
- SectionKey<ELFT::Is64Bits> Key = createKey(C, OutsecName);
- OutputSectionBase<ELFT> *&Sec = Map[Key];
- if (Sec)
- return {Sec, false};
-
- switch (C->SectionKind) {
- case InputSectionBase<ELFT>::Regular:
- Sec = new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
- break;
- case InputSectionBase<ELFT>::EHFrame:
- Sec = new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
- break;
- case InputSectionBase<ELFT>::Merge:
- Sec = new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
- break;
- case InputSectionBase<ELFT>::MipsReginfo:
- Sec = new MipsReginfoOutputSection<ELFT>();
- break;
- }
- return {Sec, true};
-}
-
-template <class ELFT>
-OutputSectionBase<ELFT> *OutputSectionFactory<ELFT>::lookup(StringRef Name,
- uint32_t Type,
- uintX_t Flags) {
- return Map.lookup({Name, Type, Flags, 0});
-}
-
-template <class ELFT>
-SectionKey<ELFT::Is64Bits>
-OutputSectionFactory<ELFT>::createKey(InputSectionBase<ELFT> *C,
- StringRef OutsecName) {
- const Elf_Shdr *H = C->getSectionHdr();
- uintX_t Flags = H->sh_flags & ~SHF_GROUP;
-
- // For SHF_MERGE we create different output sections for each sh_entsize.
- // This makes each output section simple and keeps a single level
- // mapping from input to output.
- uintX_t EntSize = isa<MergeInputSection<ELFT>>(C) ? H->sh_entsize : 0;
-
- // GNU as can give .eh_frame secion type SHT_PROGBITS or SHT_X86_64_UNWIND
- // depending on the construct. We want to canonicalize it so that
- // there is only one .eh_frame in the end.
- uint32_t Type = H->sh_type;
- if (Type == SHT_PROGBITS && Config->EMachine == EM_X86_64 &&
- isa<EHInputSection<ELFT>>(C))
- Type = SHT_X86_64_UNWIND;
-
- return SectionKey<ELFT::Is64Bits>{OutsecName, Type, Flags, EntSize};
+ S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end";
+ addOptionalSynthetic(Symtab, S, Out<ELFT>::RelaPlt,
+ DefinedSynthetic<ELFT>::SectionEnd);
}
// The linker is expected to define some symbols depending on
// the linking result. This function defines such symbols.
template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
+ if (Config->EMachine == EM_MIPS) {
+ // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
+ // so that it points to an absolute address which is relative to GOT.
+ // See "Global Data Symbols" in Chapter 6 in the following document:
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ Symtab.addSynthetic("_gp", Out<ELFT>::Got, MipsGPOffset);
+
+ // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
+ // start of function and 'gp' pointer into GOT.
+ Symbol *Sym =
+ addOptionalSynthetic(Symtab, "_gp_disp", Out<ELFT>::Got, MipsGPOffset);
+ if (Sym)
+ ElfSym<ELFT>::MipsGpDisp = Sym->body();
+
+ // The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
+ // pointer. This symbol is used in the code generated by .cpload pseudo-op
+ // in case of using -mno-shared option.
+ // https://sourceware.org/ml/binutils/2004-12/msg00094.html
+ addOptionalSynthetic(Symtab, "__gnu_local_gp", Out<ELFT>::Got,
+ MipsGPOffset);
+ }
+
+ // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
+ // is magical and is used to produce a R_386_GOTPC relocation.
+ // The R_386_GOTPC relocation value doesn't actually depend on the
+ // symbol value, so it could use an index of STN_UNDEF which, according
+ // to the spec, means the symbol value is 0.
+ // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in
+ // the object file.
+ // The situation is even stranger on x86_64 where the assembly doesn't
+ // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as
+ // an undefined symbol in the .o files.
+ // Given that the symbol is effectively unused, we just create a dummy
+ // hidden one to avoid the undefined symbol error.
+ if (!Config->Relocatable)
+ Symtab.addIgnored("_GLOBAL_OFFSET_TABLE_");
+
// __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For
// static linking the linker is required to optimize away any references to
// __tls_get_addr, so it's not defined anywhere. Create a hidden definition
@@ -711,35 +572,44 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
if (!isOutputDynamic())
Symtab.addIgnored("__tls_get_addr");
- // If the "_end" symbol is referenced, it is expected to point to the address
- // right after the data segment. Usually, this symbol points to the end
- // of .bss section or to the end of .data section if .bss section is absent.
- // The order of the sections can be affected by linker script,
- // so it is hard to predict which section will be the last one.
- // So, if this symbol is referenced, we just add the placeholder here
- // and update its value later.
- if (Symtab.find("_end"))
- Symtab.addAbsolute("_end", ElfSym<ELFT>::End);
-
- // If there is an undefined symbol "end", we should initialize it
- // with the same value as "_end". In any other case it should stay intact,
- // because it is an allowable name for a user symbol.
- if (SymbolBody *B = Symtab.find("end"))
- if (B->isUndefined())
- Symtab.addAbsolute("end", ElfSym<ELFT>::End);
+ auto Define = [this](StringRef S, DefinedRegular<ELFT> *&Sym1,
+ DefinedRegular<ELFT> *&Sym2) {
+ Sym1 = Symtab.addIgnored(S, STV_DEFAULT);
+
+ // The name without the underscore is not a reserved name,
+ // so it is defined only when there is a reference against it.
+ assert(S.startswith("_"));
+ S = S.substr(1);
+ if (SymbolBody *B = Symtab.find(S))
+ if (B->isUndefined())
+ Sym2 = Symtab.addAbsolute(S, STV_DEFAULT);
+ };
+
+ Define("_end", ElfSym<ELFT>::End, ElfSym<ELFT>::End2);
+ Define("_etext", ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2);
+ Define("_edata", ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2);
+}
+
+// Sort input sections by section name suffixes for
+// __attribute__((init_priority(N))).
+template <class ELFT> static void sortInitFini(OutputSectionBase<ELFT> *S) {
+ if (S)
+ reinterpret_cast<OutputSection<ELFT> *>(S)->sortInitFini();
+}
+
+// Sort input sections by the special rule for .ctors and .dtors.
+template <class ELFT> static void sortCtorsDtors(OutputSectionBase<ELFT> *S) {
+ if (S)
+ reinterpret_cast<OutputSection<ELFT> *>(S)->sortCtorsDtors();
}
// Create output section objects and add them to OutputSections.
template <class ELFT> void Writer<ELFT>::createSections() {
- // Add .interp first because some loaders want to see that section
- // on the first page of the executable file when loaded into memory.
- if (needsInterpSection())
- OutputSections.push_back(Out<ELFT>::Interp);
-
// Create output sections for input object file sections.
std::vector<OutputSectionBase<ELFT> *> RegularSections;
OutputSectionFactory<ELFT> Factory;
- for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
+ for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
+ Symtab.getObjectFiles()) {
for (InputSectionBase<ELFT> *C : F->getSections()) {
if (isDiscarded(C)) {
reportDiscarded(C, F);
@@ -747,8 +617,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
}
OutputSectionBase<ELFT> *Sec;
bool IsNew;
- std::tie(Sec, IsNew) =
- Factory.create(C, getOutputSectionName(C->getSectionName()));
+ std::tie(Sec, IsNew) = Factory.create(C, getOutputSectionName(C));
if (IsNew) {
OwningSections.emplace_back(Sec);
OutputSections.push_back(Sec);
@@ -758,9 +627,6 @@ template <class ELFT> void Writer<ELFT>::createSections() {
}
}
- Out<ELFT>::Bss = static_cast<OutputSection<ELFT> *>(
- Factory.lookup(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE));
-
// If we have a .opd section (used under PPC64 for function descriptors),
// store a pointer to it here so that we can use it later when processing
// relocations.
@@ -773,56 +639,92 @@ template <class ELFT> void Writer<ELFT>::createSections() {
Out<ELFT>::Dynamic->FiniArraySec =
Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC);
+ // Sort section contents for __attribute__((init_priority(N)).
+ sortInitFini(Out<ELFT>::Dynamic->InitArraySec);
+ sortInitFini(Out<ELFT>::Dynamic->FiniArraySec);
+ sortCtorsDtors(Factory.lookup(".ctors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC));
+ sortCtorsDtors(Factory.lookup(".dtors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC));
+
// The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
// symbols for sections, so that the runtime can get the start and end
// addresses of each section by section name. Add such symbols.
- addStartEndSymbols();
- for (OutputSectionBase<ELFT> *Sec : RegularSections)
- addStartStopSymbols(Sec);
+ if (!Config->Relocatable) {
+ addStartEndSymbols();
+ for (OutputSectionBase<ELFT> *Sec : RegularSections)
+ addStartStopSymbols(Sec);
+ }
+
+ // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
+ // It should be okay as no one seems to care about the type.
+ // Even the author of gold doesn't remember why gold behaves that way.
+ // https://sourceware.org/ml/binutils/2002-03/msg00360.html
+ if (isOutputDynamic())
+ Symtab.addSynthetic("_DYNAMIC", Out<ELFT>::Dynamic, 0);
+
+ // Define __rel[a]_iplt_{start,end} symbols if needed.
+ addRelIpltSymbols();
+
+ // Add scripted symbols with zero values now.
+ // Real values will be assigned later
+ Script<ELFT>::X->addScriptedSymbols();
+
+ if (!Out<ELFT>::EhFrame->empty()) {
+ OutputSections.push_back(Out<ELFT>::EhFrame);
+ Out<ELFT>::EhFrame->finalize();
+ }
// Scan relocations. This must be done after every symbol is declared so that
// we can correctly decide if a dynamic relocation is needed.
- for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
+ for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
+ Symtab.getObjectFiles()) {
for (InputSectionBase<ELFT> *C : F->getSections()) {
if (isDiscarded(C))
continue;
- if (auto *S = dyn_cast<InputSection<ELFT>>(C))
- scanRelocs(*S);
- else if (auto *S = dyn_cast<EHInputSection<ELFT>>(C))
+ if (auto *S = dyn_cast<InputSection<ELFT>>(C)) {
+ scanRelocations(*S);
+ continue;
+ }
+ if (auto *S = dyn_cast<EhInputSection<ELFT>>(C))
if (S->RelocSection)
- scanRelocs(*S, *S->RelocSection);
+ scanRelocations(*S, *S->RelocSection);
}
}
- // Define __rel[a]_iplt_{start,end} symbols if needed.
- addRelIpltSymbols();
+ for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ Sec->assignOffsets();
// Now that we have defined all possible symbols including linker-
// synthesized ones. Visit all symbols to give the finishing touches.
std::vector<DefinedCommon *> CommonSymbols;
- std::vector<SharedSymbol<ELFT> *> CopyRelSymbols;
- for (auto &P : Symtab.getSymbols()) {
- SymbolBody *Body = P.second->Body;
- if (auto *U = dyn_cast<Undefined>(Body))
- if (!U->isWeak() && !U->canKeepUndefined())
- reportUndefined<ELFT>(Symtab, Body);
+ for (Symbol *S : Symtab.getSymbols()) {
+ SymbolBody *Body = S->body();
+
+ // We only report undefined symbols in regular objects. This means that we
+ // will accept an undefined reference in bitcode if it can be optimized out.
+ if (S->IsUsedInRegularObj && Body->isUndefined() && !S->isWeak())
+ reportUndefined<ELFT>(Symtab, Body);
if (auto *C = dyn_cast<DefinedCommon>(Body))
CommonSymbols.push_back(C);
- if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
- if (SC->NeedsCopy)
- CopyRelSymbols.push_back(SC);
if (!includeInSymtab<ELFT>(*Body))
continue;
if (Out<ELFT>::SymTab)
Out<ELFT>::SymTab->addSymbol(Body);
- if (isOutputDynamic() && includeInDynamicSymtab(*Body))
+ if (isOutputDynamic() && S->includeInDynsym()) {
Out<ELFT>::DynSymTab->addSymbol(Body);
+ if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
+ if (SS->file()->isNeeded())
+ Out<ELFT>::VerNeed->addSymbol(SS);
+ }
}
+
+ // Do not proceed if there was an undefined symbol.
+ if (HasError)
+ return;
+
addCommonSymbols(CommonSymbols);
- addCopyRelSymbols(CopyRelSymbols);
// So far we have added sections from input object files.
// This function adds linker-created Out<ELFT>::* sections.
@@ -831,25 +733,47 @@ template <class ELFT> void Writer<ELFT>::createSections() {
std::stable_sort(OutputSections.begin(), OutputSections.end(),
compareSections<ELFT>);
- for (unsigned I = 0, N = OutputSections.size(); I < N; ++I) {
- OutputSections[I]->SectionIndex = I + 1;
- HasRelro |= (Config->ZRelro && isRelroSection(OutputSections[I]));
+ unsigned I = 1;
+ for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+ Sec->SectionIndex = I++;
+ Sec->setSHName(Out<ELFT>::ShStrTab->addString(Sec->getName()));
}
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
- Out<ELFT>::ShStrTab->reserve(Sec->getName());
-
// Finalizers fix each section's size.
- // .dynamic section's finalizer may add strings to .dynstr,
- // so finalize that early.
- // Likewise, .dynsym is finalized early since that may fill up .gnu.hash.
- Out<ELFT>::Dynamic->finalize();
+ // .dynsym is finalized early since that may fill up .gnu.hash.
if (isOutputDynamic())
Out<ELFT>::DynSymTab->finalize();
- // Fill other section headers.
+ // Fill other section headers. The dynamic table is finalized
+ // at the end because some tags like RELSZ depend on result
+ // of finalizing other sections. The dynamic string table is
+ // finalized once the .dynamic finalizer has added a few last
+ // strings. See DynamicSection::finalize()
+ for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ if (Sec != Out<ELFT>::DynStrTab && Sec != Out<ELFT>::Dynamic)
+ Sec->finalize();
+
+ if (isOutputDynamic())
+ Out<ELFT>::Dynamic->finalize();
+
+ // Now that all output offsets are fixed. Finalize mergeable sections
+ // to fix their maps from input offsets to output offsets.
for (OutputSectionBase<ELFT> *Sec : OutputSections)
- Sec->finalize();
+ Sec->finalizePieces();
+}
+
+template <class ELFT> bool Writer<ELFT>::needsGot() {
+ if (!Out<ELFT>::Got->empty())
+ return true;
+
+ // We add the .got section to the result for dynamic MIPS target because
+ // its address and properties are mentioned in the .dynamic section.
+ if (Config->EMachine == EM_MIPS)
+ return true;
+
+ // If we have a relocation that is relative to GOT (such as GOTOFFREL),
+ // we need to emit a GOT even if it's empty.
+ return Out<ELFT>::Got->HasGotOffRel;
}
// This function add Out<ELFT>::* sections to OutputSections.
@@ -859,6 +783,17 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
OutputSections.push_back(C);
};
+ // A core file does not usually contain unmodified segments except
+ // the first page of the executable. Add the build ID section to beginning of
+ // the file so that the section is included in the first page.
+ if (Out<ELFT>::BuildId)
+ OutputSections.insert(OutputSections.begin(), Out<ELFT>::BuildId);
+
+ // Add .interp at first because some loaders want to see that section
+ // on the first page of the executable file when loaded into memory.
+ if (needsInterpSection())
+ OutputSections.insert(OutputSections.begin(), Out<ELFT>::Interp);
+
// This order is not the same as the final output order
// because we sort the sections using their attributes below.
Add(Out<ELFT>::SymTab);
@@ -866,25 +801,21 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
Add(Out<ELFT>::StrTab);
if (isOutputDynamic()) {
Add(Out<ELFT>::DynSymTab);
+
+ bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
+ if (Out<ELFT>::VerDef || HasVerNeed)
+ Add(Out<ELFT>::VerSym);
+ Add(Out<ELFT>::VerDef);
+ if (HasVerNeed)
+ Add(Out<ELFT>::VerNeed);
+
Add(Out<ELFT>::GnuHashTab);
Add(Out<ELFT>::HashTab);
Add(Out<ELFT>::Dynamic);
Add(Out<ELFT>::DynStrTab);
if (Out<ELFT>::RelaDyn->hasRelocs())
Add(Out<ELFT>::RelaDyn);
-
- // This is a MIPS specific section to hold a space within the data segment
- // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry.
- // See "Dynamic section" in Chapter 5 in the following document:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- if (Config->EMachine == EM_MIPS && !Config->Shared) {
- Out<ELFT>::MipsRldMap = new OutputSection<ELFT>(".rld_map", SHT_PROGBITS,
- SHF_ALLOC | SHF_WRITE);
- Out<ELFT>::MipsRldMap->setSize(ELFT::Is64Bits ? 8 : 4);
- Out<ELFT>::MipsRldMap->updateAlign(ELFT::Is64Bits ? 8 : 4);
- OwningSections.emplace_back(Out<ELFT>::MipsRldMap);
- Add(Out<ELFT>::MipsRldMap);
- }
+ Add(Out<ELFT>::MipsRldMap);
}
// We always need to add rel[a].plt to output if it has entries.
@@ -894,22 +825,16 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
Out<ELFT>::RelaPlt->Static = !isOutputDynamic();
}
- bool needsGot = !Out<ELFT>::Got->empty();
- // We add the .got section to the result for dynamic MIPS target because
- // its address and properties are mentioned in the .dynamic section.
- if (Config->EMachine == EM_MIPS)
- needsGot |= isOutputDynamic();
- // If we have a relocation that is relative to GOT (such as GOTOFFREL),
- // we need to emit a GOT even if it's empty.
- if (HasGotOffRel)
- needsGot = true;
-
- if (needsGot)
+ if (needsGot())
Add(Out<ELFT>::Got);
if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
Add(Out<ELFT>::GotPlt);
if (!Out<ELFT>::Plt->empty())
Add(Out<ELFT>::Plt);
+ if (!Out<ELFT>::EhFrame->empty())
+ Add(Out<ELFT>::EhFrameHdr);
+ if (Out<ELFT>::Bss->getSize() > 0)
+ Add(Out<ELFT>::Bss);
}
// The linker is expected to define SECNAME_start and SECNAME_end
@@ -918,11 +843,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
auto Define = [&](StringRef Start, StringRef End,
OutputSectionBase<ELFT> *OS) {
if (OS) {
- Symtab.addSynthetic(Start, *OS, 0);
- Symtab.addSynthetic(End, *OS, OS->getSize());
+ this->Symtab.addSynthetic(Start, OS, 0);
+ this->Symtab.addSynthetic(End, OS, DefinedSynthetic<ELFT>::SectionEnd);
} else {
- Symtab.addIgnored(Start);
- Symtab.addIgnored(End);
+ addOptionalSynthetic(this->Symtab, Start,
+ (OutputSectionBase<ELFT> *)nullptr, 0);
+ addOptionalSynthetic(this->Symtab, End,
+ (OutputSectionBase<ELFT> *)nullptr, 0);
}
};
@@ -934,19 +861,6 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
Out<ELFT>::Dynamic->FiniArraySec);
}
-static bool isAlpha(char C) {
- return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
-}
-
-static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
-
-// Returns true if S is valid as a C language identifier.
-static bool isValidCIdentifier(StringRef S) {
- if (S.empty() || !isAlpha(S[0]))
- return false;
- return std::all_of(S.begin() + 1, S.end(), isAlnum);
-}
-
// If a section name is valid as a C identifier (which is rare because of
// the leading '.'), linkers are expected to define __start_<secname> and
// __stop_<secname> symbols. They are at beginning and end of the section,
@@ -962,14 +876,22 @@ void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) {
StringRef Stop = Saver.save("__stop_" + S);
if (SymbolBody *B = Symtab.find(Start))
if (B->isUndefined())
- Symtab.addSynthetic(Start, *Sec, 0);
+ Symtab.addSynthetic(Start, Sec, 0);
if (SymbolBody *B = Symtab.find(Stop))
if (B->isUndefined())
- Symtab.addSynthetic(Stop, *Sec, Sec->getSize());
+ Symtab.addSynthetic(Stop, Sec, DefinedSynthetic<ELFT>::SectionEnd);
}
-template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) {
- return Sec->getFlags() & SHF_ALLOC;
+template <class ELFT> static bool needsPtLoad(OutputSectionBase<ELFT> *Sec) {
+ if (!(Sec->getFlags() & SHF_ALLOC))
+ return false;
+
+ // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
+ // responsible for allocating space for them, not the PT_LOAD that
+ // contains the TLS initialization image.
+ if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS)
+ return false;
+ return true;
}
static uint32_t toPhdrFlags(uint64_t Flags) {
@@ -981,269 +903,341 @@ static uint32_t toPhdrFlags(uint64_t Flags) {
return Ret;
}
-/// For AMDGPU we need to use custom segment kinds in order to specify which
-/// address space data should be loaded into.
-template <class ELFT>
-static uint32_t getAmdgpuPhdr(OutputSectionBase<ELFT> *Sec) {
- uint32_t Flags = Sec->getFlags();
- if (Flags & SHF_AMDGPU_HSA_CODE)
- return PT_AMDGPU_HSA_LOAD_CODE_AGENT;
- if ((Flags & SHF_AMDGPU_HSA_GLOBAL) && !(Flags & SHF_AMDGPU_HSA_AGENT))
- return PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM;
- return PT_LOAD;
-}
-
-template <class ELFT>
-void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
- uintX_t VA) {
- if (!GnuRelroPhdr->p_type)
- setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr,
- VA - Cur->p_vaddr, 1 /*p_align*/);
- GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr;
- GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr;
-}
-
-// Visits all sections to create PHDRs and to assign incremental,
-// non-overlapping addresses to output sections.
-template <class ELFT> void Writer<ELFT>::assignAddresses() {
- uintX_t VA = Target->getVAStart() + sizeof(Elf_Ehdr);
- uintX_t FileOff = sizeof(Elf_Ehdr);
+// Decide which program headers to create and which sections to include in each
+// one.
+template <class ELFT> void Writer<ELFT>::createPhdrs() {
+ auto AddHdr = [this](unsigned Type, unsigned Flags) {
+ return &*Phdrs.emplace(Phdrs.end(), Type, Flags);
+ };
- // Calculate and reserve the space for the program header first so that
- // the first section can start right after the program header.
- Phdrs.resize(getPhdrsNum());
- size_t PhdrSize = sizeof(Elf_Phdr) * Phdrs.size();
+ auto AddSec = [](Phdr &Hdr, OutputSectionBase<ELFT> *Sec) {
+ Hdr.Last = Sec;
+ if (!Hdr.First)
+ Hdr.First = Sec;
+ Hdr.H.p_align = std::max<uintX_t>(Hdr.H.p_align, Sec->getAlignment());
+ };
// The first phdr entry is PT_PHDR which describes the program header itself.
- setPhdr(&Phdrs[0], PT_PHDR, PF_R, FileOff, VA, PhdrSize, /*Align=*/8);
- FileOff += PhdrSize;
- VA += PhdrSize;
+ Phdr &Hdr = *AddHdr(PT_PHDR, PF_R);
+ AddSec(Hdr, Out<ELFT>::ProgramHeaders);
// PT_INTERP must be the second entry if exists.
- int PhdrIdx = 0;
- Elf_Phdr *Interp = nullptr;
- if (needsInterpSection())
- Interp = &Phdrs[++PhdrIdx];
+ if (needsInterpSection()) {
+ Phdr &Hdr = *AddHdr(PT_INTERP, toPhdrFlags(Out<ELFT>::Interp->getFlags()));
+ AddSec(Hdr, Out<ELFT>::Interp);
+ }
// Add the first PT_LOAD segment for regular output sections.
- setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, Target->getVAStart(), FileOff,
- Target->getPageSize());
-
- Elf_Phdr GnuRelroPhdr = {};
- Elf_Phdr TlsPhdr{};
- bool RelroAligned = false;
- uintX_t ThreadBssOffset = 0;
- // Create phdrs as we assign VAs and file offsets to all output sections.
+ uintX_t Flags = PF_R;
+ Phdr *Load = AddHdr(PT_LOAD, Flags);
+ AddSec(*Load, Out<ELFT>::ElfHeader);
+ AddSec(*Load, Out<ELFT>::ProgramHeaders);
+
+ Phdr TlsHdr(PT_TLS, PF_R);
+ Phdr RelRo(PT_GNU_RELRO, PF_R);
+ Phdr Note(PT_NOTE, PF_R);
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
- Elf_Phdr *PH = &Phdrs[PhdrIdx];
- if (needsPhdr<ELFT>(Sec)) {
- uintX_t Flags = toPhdrFlags(Sec->getFlags());
- bool InRelRo = Config->ZRelro && (Flags & PF_W) && isRelroSection(Sec);
- bool FirstNonRelRo = GnuRelroPhdr.p_type && !InRelRo && !RelroAligned;
- if (FirstNonRelRo || PH->p_flags != Flags) {
- VA = align(VA, Target->getPageSize());
- FileOff = align(FileOff, Target->getPageSize());
- if (FirstNonRelRo)
- RelroAligned = true;
- }
+ if (!(Sec->getFlags() & SHF_ALLOC))
+ break;
- if (PH->p_flags != Flags) {
- // Flags changed. Create a new PT_LOAD.
- PH = &Phdrs[++PhdrIdx];
- uint32_t PTType = (Config->EMachine != EM_AMDGPU) ? (uint32_t)PT_LOAD
- : getAmdgpuPhdr(Sec);
- setPhdr(PH, PTType, Flags, FileOff, VA, 0, Target->getPageSize());
- }
+ // If we meet TLS section then we create TLS header
+ // and put all TLS sections inside for futher use when
+ // assign addresses.
+ if (Sec->getFlags() & SHF_TLS)
+ AddSec(TlsHdr, Sec);
- if (Sec->getFlags() & SHF_TLS) {
- if (!TlsPhdr.p_vaddr)
- setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
- if (Sec->getType() != SHT_NOBITS)
- VA = align(VA, Sec->getAlign());
- uintX_t TVA = align(VA + ThreadBssOffset, Sec->getAlign());
- Sec->setVA(TVA);
- TlsPhdr.p_memsz += Sec->getSize();
- if (Sec->getType() == SHT_NOBITS) {
- ThreadBssOffset = TVA - VA + Sec->getSize();
- } else {
- TlsPhdr.p_filesz += Sec->getSize();
- VA += Sec->getSize();
- }
- TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
- } else {
- VA = align(VA, Sec->getAlign());
- Sec->setVA(VA);
- VA += Sec->getSize();
- if (InRelRo)
- updateRelro(PH, &GnuRelroPhdr, VA);
- }
- }
+ if (!needsPtLoad<ELFT>(Sec))
+ continue;
- FileOff = align(FileOff, Sec->getAlign());
- Sec->setFileOffset(FileOff);
- if (Sec->getType() != SHT_NOBITS)
- FileOff += Sec->getSize();
- if (needsPhdr<ELFT>(Sec)) {
- PH->p_filesz = FileOff - PH->p_offset;
- PH->p_memsz = VA - PH->p_vaddr;
+ // If flags changed then we want new load segment.
+ uintX_t NewFlags = toPhdrFlags(Sec->getFlags());
+ if (Flags != NewFlags) {
+ Load = AddHdr(PT_LOAD, NewFlags);
+ Flags = NewFlags;
}
- }
- if (TlsPhdr.p_vaddr) {
- // The TLS pointer goes after PT_TLS. At least glibc will align it,
- // so round up the size to make sure the offsets are correct.
- TlsPhdr.p_memsz = align(TlsPhdr.p_memsz, TlsPhdr.p_align);
- Phdrs[++PhdrIdx] = TlsPhdr;
- Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
+ AddSec(*Load, Sec);
+
+ if (isRelroSection(Sec))
+ AddSec(RelRo, Sec);
+ if (Sec->getType() == SHT_NOTE)
+ AddSec(Note, Sec);
}
+ // Add the TLS segment unless it's empty.
+ if (TlsHdr.First)
+ Phdrs.push_back(std::move(TlsHdr));
+
// Add an entry for .dynamic.
if (isOutputDynamic()) {
- Elf_Phdr *PH = &Phdrs[++PhdrIdx];
- PH->p_type = PT_DYNAMIC;
- copyPhdr(PH, Out<ELFT>::Dynamic);
+ Phdr &H = *AddHdr(PT_DYNAMIC, toPhdrFlags(Out<ELFT>::Dynamic->getFlags()));
+ AddSec(H, Out<ELFT>::Dynamic);
}
- if (HasRelro) {
- Elf_Phdr *PH = &Phdrs[++PhdrIdx];
- *PH = GnuRelroPhdr;
+ // PT_GNU_RELRO includes all sections that should be marked as
+ // read-only by dynamic linker after proccessing relocations.
+ if (RelRo.First)
+ Phdrs.push_back(std::move(RelRo));
+
+ // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
+ if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr) {
+ Phdr &Hdr = *AddHdr(PT_GNU_EH_FRAME,
+ toPhdrFlags(Out<ELFT>::EhFrameHdr->getFlags()));
+ AddSec(Hdr, Out<ELFT>::EhFrameHdr);
}
// PT_GNU_STACK is a special section to tell the loader to make the
// pages for the stack non-executable.
- if (!Config->ZExecStack) {
- Elf_Phdr *PH = &Phdrs[++PhdrIdx];
- PH->p_type = PT_GNU_STACK;
- PH->p_flags = PF_R | PF_W;
+ if (!Config->ZExecStack)
+ AddHdr(PT_GNU_STACK, PF_R | PF_W);
+
+ if (Note.First)
+ Phdrs.push_back(std::move(Note));
+
+ Out<ELFT>::ProgramHeaders->setSize(sizeof(Elf_Phdr) * Phdrs.size());
+}
+
+// The first section of each PT_LOAD and the first section after PT_GNU_RELRO
+// have to be page aligned so that the dynamic linker can set the permissions.
+template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
+ for (const Phdr &P : Phdrs)
+ if (P.H.p_type == PT_LOAD)
+ P.First->PageAlign = true;
+
+ for (const Phdr &P : Phdrs) {
+ if (P.H.p_type != PT_GNU_RELRO)
+ continue;
+ // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
+ // have to align it to a page.
+ auto End = OutputSections.end();
+ auto I = std::find(OutputSections.begin(), End, P.Last);
+ if (I == End || (I + 1) == End)
+ continue;
+ OutputSectionBase<ELFT> *Sec = *(I + 1);
+ if (needsPtLoad(Sec))
+ Sec->PageAlign = true;
}
+}
- // Fix up PT_INTERP as we now know the address of .interp section.
- if (Interp) {
- Interp->p_type = PT_INTERP;
- copyPhdr(Interp, Out<ELFT>::Interp);
+// We should set file offsets and VAs for elf header and program headers
+// sections. These are special, we do not include them into output sections
+// list, but have them to simplify the code.
+template <class ELFT> void Writer<ELFT>::fixHeaders() {
+ uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Config->ImageBase;
+ Out<ELFT>::ElfHeader->setVA(BaseVA);
+ uintX_t Off = Out<ELFT>::ElfHeader->getSize();
+ Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);
+}
+
+// Assign VAs (addresses at run-time) to output sections.
+template <class ELFT> void Writer<ELFT>::assignAddresses() {
+ uintX_t VA = Config->ImageBase + Out<ELFT>::ElfHeader->getSize() +
+ Out<ELFT>::ProgramHeaders->getSize();
+
+ uintX_t ThreadBssOffset = 0;
+ for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+ uintX_t Alignment = Sec->getAlignment();
+ if (Sec->PageAlign)
+ Alignment = std::max<uintX_t>(Alignment, Target->PageSize);
+
+ // We only assign VAs to allocated sections.
+ if (needsPtLoad<ELFT>(Sec)) {
+ VA = alignTo(VA, Alignment);
+ Sec->setVA(VA);
+ VA += Sec->getSize();
+ } else if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS) {
+ uintX_t TVA = VA + ThreadBssOffset;
+ TVA = alignTo(TVA, Alignment);
+ Sec->setVA(TVA);
+ ThreadBssOffset = TVA - VA + Sec->getSize();
+ }
}
+}
+
+// Adjusts the file alignment for a given output section and returns
+// its new file offset. The file offset must be the same with its
+// virtual address (modulo the page size) so that the loader can load
+// executables without any address adjustment.
+template <class ELFT, class uintX_t>
+static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase<ELFT> *Sec) {
+ uintX_t Alignment = Sec->getAlignment();
+ if (Sec->PageAlign)
+ Alignment = std::max<uintX_t>(Alignment, Target->PageSize);
+ Off = alignTo(Off, Alignment);
+
+ // Relocatable output does not have program headers
+ // and does not need any other offset adjusting.
+ if (Config->Relocatable || !(Sec->getFlags() & SHF_ALLOC))
+ return Off;
+ return alignTo(Off, Target->PageSize, Sec->getVA());
+}
+
+// Assign file offsets to output sections.
+template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
+ uintX_t Off = 0;
- // Add space for section headers.
- SectionHeaderOff = align(FileOff, ELFT::Is64Bits ? 8 : 4);
- FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
+ auto Set = [&](OutputSectionBase<ELFT> *Sec) {
+ if (Sec->getType() == SHT_NOBITS) {
+ Sec->setFileOffset(Off);
+ return;
+ }
- // Update "_end" and "end" symbols so that they
- // point to the end of the data segment.
- ElfSym<ELFT>::End.st_value = VA;
+ Off = getFileAlignment<ELFT>(Off, Sec);
+ Sec->setFileOffset(Off);
+ Off += Sec->getSize();
+ };
+
+ Set(Out<ELFT>::ElfHeader);
+ Set(Out<ELFT>::ProgramHeaders);
+ for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ Set(Sec);
+
+ SectionHeaderOff = alignTo(Off, sizeof(uintX_t));
+ FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
}
-// Returns the number of PHDR entries.
-template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
- bool Tls = false;
- int I = 2; // 2 for PT_PHDR and first PT_LOAD
- if (needsInterpSection())
- ++I;
- if (isOutputDynamic())
- ++I;
- if (!Config->ZExecStack)
- ++I;
- uintX_t Last = PF_R;
- for (OutputSectionBase<ELFT> *Sec : OutputSections) {
- if (!needsPhdr<ELFT>(Sec))
- continue;
- if (Sec->getFlags() & SHF_TLS)
- Tls = true;
- uintX_t Flags = toPhdrFlags(Sec->getFlags());
- if (Last != Flags) {
- Last = Flags;
- ++I;
+// Finalize the program headers. We call this function after we assign
+// file offsets and VAs to all sections.
+template <class ELFT> void Writer<ELFT>::setPhdrs() {
+ for (Phdr &P : Phdrs) {
+ Elf_Phdr &H = P.H;
+ OutputSectionBase<ELFT> *First = P.First;
+ OutputSectionBase<ELFT> *Last = P.Last;
+ if (First) {
+ H.p_filesz = Last->getFileOff() - First->getFileOff();
+ if (Last->getType() != SHT_NOBITS)
+ H.p_filesz += Last->getSize();
+ H.p_memsz = Last->getVA() + Last->getSize() - First->getVA();
+ H.p_offset = First->getFileOff();
+ H.p_vaddr = First->getVA();
+ }
+ if (H.p_type == PT_LOAD)
+ H.p_align = Target->PageSize;
+ else if (H.p_type == PT_GNU_RELRO)
+ H.p_align = 1;
+ H.p_paddr = H.p_vaddr;
+
+ // The TLS pointer goes after PT_TLS. At least glibc will align it,
+ // so round up the size to make sure the offsets are correct.
+ if (H.p_type == PT_TLS) {
+ Out<ELFT>::TlsPhdr = &H;
+ H.p_memsz = alignTo(H.p_memsz, H.p_align);
}
}
- if (Tls)
- ++I;
- if (HasRelro)
- ++I;
- return I;
}
-static uint32_t getELFFlags() {
- if (Config->EMachine != EM_MIPS)
- return 0;
+static uint32_t getMipsEFlags(bool Is64Bits) {
// FIXME: In fact ELF flags depends on ELF flags of input object files
// and selected emulation. For now just use hard coded values.
- uint32_t V = EF_MIPS_ABI_O32 | EF_MIPS_CPIC | EF_MIPS_ARCH_32R2;
+ if (Is64Bits)
+ return EF_MIPS_CPIC | EF_MIPS_PIC | EF_MIPS_ARCH_64R2;
+
+ uint32_t V = EF_MIPS_CPIC | EF_MIPS_ABI_O32 | EF_MIPS_ARCH_32R2;
if (Config->Shared)
V |= EF_MIPS_PIC;
return V;
}
-template <class ELFT>
-static typename ELFFile<ELFT>::uintX_t getEntryAddr() {
- if (Config->EntrySym) {
- if (SymbolBody *E = Config->EntrySym->repl())
- return getSymVA<ELFT>(*E);
- return 0;
- }
+template <class ELFT> static typename ELFT::uint getEntryAddr() {
+ if (Symbol *S = Config->EntrySym)
+ return S->body()->getVA<ELFT>();
if (Config->EntryAddr != uint64_t(-1))
return Config->EntryAddr;
return 0;
}
+template <class ELFT> static uint8_t getELFEncoding() {
+ if (ELFT::TargetEndianness == llvm::support::little)
+ return ELFDATA2LSB;
+ return ELFDATA2MSB;
+}
+
+static uint16_t getELFType() {
+ if (Config->Pic)
+ return ET_DYN;
+ if (Config->Relocatable)
+ return ET_REL;
+ return ET_EXEC;
+}
+
// This function is called after we have assigned address and size
// to each section. This function fixes some predefined absolute
// symbol values that depend on section address and size.
template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
- // Update __rel[a]_iplt_{start,end} symbols so that they point
- // to beginning or ending of .rela.plt section, respectively.
- if (Out<ELFT>::RelaPlt) {
- uintX_t Start = Out<ELFT>::RelaPlt->getVA();
- ElfSym<ELFT>::RelaIpltStart.st_value = Start;
- ElfSym<ELFT>::RelaIpltEnd.st_value = Start + Out<ELFT>::RelaPlt->getSize();
- }
+ auto Set = [](DefinedRegular<ELFT> *S1, DefinedRegular<ELFT> *S2, uintX_t V) {
+ if (S1)
+ S1->Value = V;
+ if (S2)
+ S2->Value = V;
+ };
- // Update MIPS _gp absolute symbol so that it points to the static data.
- if (Config->EMachine == EM_MIPS)
- ElfSym<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();
+ // _etext is the first location after the last read-only loadable segment.
+ // _edata is the first location after the last read-write loadable segment.
+ // _end is the first location after the uninitialized data region.
+ for (Phdr &P : Phdrs) {
+ Elf_Phdr &H = P.H;
+ if (H.p_type != PT_LOAD)
+ continue;
+ Set(ElfSym<ELFT>::End, ElfSym<ELFT>::End2, H.p_vaddr + H.p_memsz);
+
+ uintX_t Val = H.p_vaddr + H.p_filesz;
+ if (H.p_flags & PF_W)
+ Set(ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2, Val);
+ else
+ Set(ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2, Val);
+ }
}
template <class ELFT> void Writer<ELFT>::writeHeader() {
uint8_t *Buf = Buffer->getBufferStart();
memcpy(Buf, "\177ELF", 4);
+ auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
+
// Write the ELF header.
auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
EHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
- EHdr->e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little
- ? ELFDATA2LSB
- : ELFDATA2MSB;
+ EHdr->e_ident[EI_DATA] = getELFEncoding<ELFT>();
EHdr->e_ident[EI_VERSION] = EV_CURRENT;
-
- auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();
-
- EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
- EHdr->e_machine = FirstObj.getEMachine();
+ EHdr->e_type = getELFType();
+ EHdr->e_machine = FirstObj.EMachine;
EHdr->e_version = EV_CURRENT;
EHdr->e_entry = getEntryAddr<ELFT>();
- EHdr->e_phoff = sizeof(Elf_Ehdr);
EHdr->e_shoff = SectionHeaderOff;
- EHdr->e_flags = getELFFlags();
EHdr->e_ehsize = sizeof(Elf_Ehdr);
- EHdr->e_phentsize = sizeof(Elf_Phdr);
EHdr->e_phnum = Phdrs.size();
EHdr->e_shentsize = sizeof(Elf_Shdr);
- EHdr->e_shnum = getNumSections();
+ EHdr->e_shnum = OutputSections.size() + 1;
EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;
+ if (Config->EMachine == EM_MIPS)
+ EHdr->e_flags = getMipsEFlags(ELFT::Is64Bits);
+
+ if (!Config->Relocatable) {
+ EHdr->e_phoff = sizeof(Elf_Ehdr);
+ EHdr->e_phentsize = sizeof(Elf_Phdr);
+ }
+
// Write the program header table.
- memcpy(Buf + EHdr->e_phoff, &Phdrs[0], Phdrs.size() * sizeof(Phdrs[0]));
+ auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
+ for (Phdr &P : Phdrs)
+ *HBuf++ = P.H;
// Write the section header table. Note that the first table entry is null.
- auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
+ auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
for (OutputSectionBase<ELFT> *Sec : OutputSections)
Sec->writeHeaderTo(++SHdrs);
}
-template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) {
+template <class ELFT> void Writer<ELFT>::openFile() {
ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
- FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable);
- error(BufferOrErr, "failed to open " + Path);
- Buffer = std::move(*BufferOrErr);
+ FileOutputBuffer::create(Config->OutputFile, FileSize,
+ FileOutputBuffer::F_executable);
+ if (auto EC = BufferOrErr.getError())
+ error(EC, "failed to open " + Config->OutputFile);
+ else
+ Buffer = std::move(*BufferOrErr);
}
// Write section contents to a mmap'ed file.
@@ -1257,53 +1251,33 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
Sec->writeTo(Buf + Sec->getFileOff());
}
- // Write all sections but string table sections. We know the sizes of the
- // string tables already, but they may not have actual strings yet (only
- // room may be reserved), because writeTo() is allowed to add actual
- // strings to the string tables.
for (OutputSectionBase<ELFT> *Sec : OutputSections)
- if (Sec != Out<ELFT>::Opd && Sec->getType() != SHT_STRTAB)
+ if (Sec != Out<ELFT>::Opd)
Sec->writeTo(Buf + Sec->getFileOff());
-
- // Write string table sections.
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
- if (Sec != Out<ELFT>::Opd && Sec->getType() == SHT_STRTAB)
- Sec->writeTo(Buf + Sec->getFileOff());
-}
-
-template <class ELFT>
-void Writer<ELFT>::setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags,
- uintX_t FileOff, uintX_t VA, uintX_t Size,
- uintX_t Align) {
- PH->p_type = Type;
- PH->p_flags = Flags;
- PH->p_offset = FileOff;
- PH->p_vaddr = VA;
- PH->p_paddr = VA;
- PH->p_filesz = Size;
- PH->p_memsz = Size;
- PH->p_align = Align;
}
-template <class ELFT>
-void Writer<ELFT>::copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From) {
- PH->p_flags = toPhdrFlags(From->getFlags());
- PH->p_offset = From->getFileOff();
- PH->p_vaddr = From->getVA();
- PH->p_paddr = From->getVA();
- PH->p_filesz = From->getSize();
- PH->p_memsz = From->getSize();
- PH->p_align = From->getAlign();
-}
+template <class ELFT> void Writer<ELFT>::writeBuildId() {
+ if (!Out<ELFT>::BuildId)
+ return;
-template <class ELFT> void Writer<ELFT>::buildSectionMap() {
- for (const std::pair<StringRef, std::vector<StringRef>> &OutSec :
- Config->OutputSections)
- for (StringRef Name : OutSec.second)
- InputToOutputSection[Name] = OutSec.first;
+ // Compute a hash of all sections except .debug_* sections.
+ // We skip debug sections because they tend to be very large
+ // and their contents are very likely to be the same as long as
+ // other sections are the same.
+ uint8_t *Start = Buffer->getBufferStart();
+ uint8_t *Last = Start;
+ std::vector<ArrayRef<uint8_t>> Regions;
+ for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+ uint8_t *End = Start + Sec->getFileOff();
+ if (!Sec->getName().startswith(".debug_"))
+ Regions.push_back({Last, End});
+ Last = End;
+ }
+ Regions.push_back({Last, Start + FileSize});
+ Out<ELFT>::BuildId->writeBuildId(Regions);
}
-template void elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
-template void elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
-template void elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
-template void elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
+template void elf::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
+template void elf::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
+template void elf::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
+template void elf::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
diff --git a/ELF/Writer.h b/ELF/Writer.h
index 40a1711e2bd2..df25d8e404c2 100644
--- a/ELF/Writer.h
+++ b/ELF/Writer.h
@@ -10,14 +10,28 @@
#ifndef LLD_ELF_WRITER_H
#define LLD_ELF_WRITER_H
-namespace lld {
-namespace elf2 {
+#include <memory>
+
+namespace llvm {
+ class StringRef;
+}
+namespace lld {
+namespace elf {
+template <class ELFT> class InputSectionBase;
+template <class ELFT> class ObjectFile;
template <class ELFT> class SymbolTable;
template <class ELFT> void writeResult(SymbolTable<ELFT> *Symtab);
-template <class ELFT> void markLive(SymbolTable<ELFT> *Symtab);
+template <class ELFT> void markLive();
+
+template <class ELFT>
+llvm::StringRef getOutputSectionName(InputSectionBase<ELFT> *S);
+
+template <class ELFT>
+void reportDiscarded(InputSectionBase<ELFT> *IS,
+ const std::unique_ptr<elf::ObjectFile<ELFT>> &File);
}
}
diff --git a/LICENSE.TXT b/LICENSE.TXT
index bcb83b211422..ec97986c86ba 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -4,7 +4,7 @@ lld License
University of Illinois/NCSA
Open Source License
-Copyright (c) 2011-2015 by the contributors listed in CREDITS.TXT
+Copyright (c) 2011-2016 by the contributors listed in CREDITS.TXT
All rights reserved.
Developed by:
diff --git a/docs/AtomLLD.rst b/docs/AtomLLD.rst
new file mode 100644
index 000000000000..4d36ac60a7db
--- /dev/null
+++ b/docs/AtomLLD.rst
@@ -0,0 +1,61 @@
+ATOM-based lld
+==============
+
+ATOM-based lld is a new set of modular code for creating linker tools.
+Currently it supports Mach-O.
+
+* End-User Features:
+
+ * Compatible with existing linker options
+ * Reads standard Object Files
+ * Writes standard Executable Files
+ * Remove clang's reliance on "the system linker"
+ * Uses the LLVM `"UIUC" BSD-Style license`__.
+
+* Applications:
+
+ * Modular design
+ * Support cross linking
+ * Easy to add new CPU support
+ * Can be built as static tool or library
+
+* Design and Implementation:
+
+ * Extensive unit tests
+ * Internal linker model can be dumped/read to textual format
+ * Additional linking features can be plugged in as "passes"
+ * OS specific and CPU specific code factored out
+
+Why a new linker?
+-----------------
+
+The fact that clang relies on whatever linker tool you happen to have installed
+means that clang has been very conservative adopting features which require a
+recent linker.
+
+In the same way that the MC layer of LLVM has removed clang's reliance on the
+system assembler tool, the lld project will remove clang's reliance on the
+system linker tool.
+
+
+Contents
+--------
+
+.. toctree::
+ :maxdepth: 2
+
+ design
+ getting_started
+ ReleaseNotes
+ development
+ windows_support
+ open_projects
+ sphinx_intro
+
+Indices and tables
+------------------
+
+* :ref:`genindex`
+* :ref:`search`
+
+__ http://llvm.org/docs/DeveloperPolicy.html#license
diff --git a/docs/NewLLD.rst b/docs/NewLLD.rst
new file mode 100644
index 000000000000..1f9bf87f10e3
--- /dev/null
+++ b/docs/NewLLD.rst
@@ -0,0 +1,350 @@
+The ELF and COFF Linkers
+========================
+
+We started rewriting the ELF (Unix) and COFF (Windows) linkers in May 2015.
+Since then, we have been making a steady progress towards providing
+drop-in replacements for the system linkers.
+
+Currently, the Windows support is mostly complete and is about 2x faster
+than the linker that comes as a part of Micrsoft Visual Studio toolchain.
+
+The ELF support is in progress and is able to link large programs
+such as Clang or LLD itself. Unless your program depends on linker scripts,
+you can expect it to be linkable with LLD.
+It is currently about 1.2x to 2x faster than GNU gold linker.
+We aim to make it a drop-in replacement for the GNU linker.
+
+We expect that FreeBSD is going to be the first large system
+to adopt LLD as the system linker.
+We are working on it in collaboration with the FreeBSD project.
+
+The linkers are notably small; as of June 2016,
+the COFF linker is under 7k lines and the ELF linker is about 13k lines,
+while gold is 146K lines.
+
+The linkers are designed to be as fast and simple as possible.
+Because it is simple, it is easy to extend to support new features.
+It already supports several advanced features such section garbage
+collection and identical code folding.
+
+The COFF linker supports i386, x86-64 and ARM. The ELF linker supports
+i386, x86-64, x32, MIPS32, MIPS64, PowerPC, AMDGPU, ARM and Aarch64,
+although the quality varies depending on platform. By default, LLD
+provides support for all targets because the amount of code we have for
+each target is so small. We do not even provide a way to disable
+targets at compile time.
+
+There are a few key design choices that we made to achieve these goals.
+We will describe them in this document.
+
+The ELF Linker as a Library
+---------------------------
+
+You can embed LLD to your program by linking against it and calling the linker's
+entry point function lld::elf::link.
+
+The current policy is that it is your reponsibility to give trustworthy object
+files. The function is guaranteed to return as long as you do not pass corrupted
+or malicious object files. A corrupted file could cause a fatal error or SEGV.
+That being said, you don't need to worry too much about it if you create object
+files in the usual way and give them to the linker. It is naturally expected to
+work, or otherwise it's a linker's bug.
+
+Design
+======
+
+We will describe the design of the linkers in the rest of the document.
+
+Key Concepts
+------------
+
+Linkers are fairly large pieces of software.
+There are many design choices you have to make to create a complete linker.
+
+This is a list of design choices we've made for ELF and COFF LLD.
+We believe that these high-level design choices achieved a right balance
+between speed, simplicity and extensibility.
+
+* Implement as native linkers
+
+ We implemented the linkers as native linkers for each file format.
+
+ The two linkers share the same design but do not share code.
+ Sharing code makes sense if the benefit is worth its cost.
+ In our case, ELF and COFF are different enough that we thought the layer to
+ abstract the differences wouldn't worth its complexity and run-time cost.
+ Elimination of the abstract layer has greatly simplified the implementation.
+
+* Speed by design
+
+ One of the most important things in archiving high performance is to
+ do less rather than do it efficiently.
+ Therefore, the high-level design matters more than local optimizations.
+ Since we are trying to create a high-performance linker,
+ it is very important to keep the design as efficient as possible.
+
+ Broadly speaking, we do not do anything until we have to do it.
+ For example, we do not read section contents or relocations
+ until we need them to continue linking.
+ When we need to do some costly operation (such as looking up
+ a hash table for each symbol), we do it only once.
+ We obtain a handler (which is typically just a pointer to actual data)
+ on the first operation and use it throughout the process.
+
+* Efficient archive file handling
+
+ LLD's handling of archive files (the files with ".a" file extension) is different
+ from the traditional Unix linkers and similar to Windows linkers.
+ We'll describe how the traditional Unix linker handles archive files,
+ what the problem is, and how LLD approached the problem.
+
+ The traditional Unix linker maintains a set of undefined symbols during linking.
+ The linker visits each file in the order as they appeared in the command line
+ until the set becomes empty. What the linker would do depends on file type.
+
+ - If the linker visits an object file, the linker links object files to the result,
+ and undefined symbols in the object file are added to the set.
+
+ - If the linker visits an archive file, it checks for the archive file's symbol table
+ and extracts all object files that have definitions for any symbols in the set.
+
+ This algorithm sometimes leads to a counter-intuitive behavior.
+ If you give archive files before object files, nothing will happen
+ because when the linker visits archives, there is no undefined symbols in the set.
+ As a result, no files are extracted from the first archive file,
+ and the link is done at that point because the set is empty after it visits one file.
+
+ You can fix the problem by reordering the files,
+ but that cannot fix the issue of mutually-dependent archive files.
+
+ Linking mutually-dependent archive files is tricky.
+ You may specify the same archive file multiple times to
+ let the linker visit it more than once.
+ Or, you may use the special command line options, `--start-group` and `--end-group`,
+ to let the linker loop over the files between the options until
+ no new symbols are added to the set.
+
+ Visiting the same archive files multiple makes the linker slower.
+
+ Here is how LLD approached the problem. Instead of memorizing only undefined symbols,
+ we program LLD so that it memorizes all symbols.
+ When it sees an undefined symbol that can be resolved by extracting an object file
+ from an archive file it previously visited, it immediately extracts the file and link it.
+ It is doable because LLD does not forget symbols it have seen in archive files.
+
+ We believe that the LLD's way is efficient and easy to justify.
+
+ The semantics of LLD's archive handling is different from the traditional Unix's.
+ You can observe it if you carefully craft archive files to exploit it.
+ However, in reality, we don't know any program that cannot link
+ with our algorithm so far, so it's not going to cause trouble.
+
+Numbers You Want to Know
+------------------------
+
+To give you intuition about what kinds of data the linker is mainly working on,
+I'll give you the list of objects and their numbers LLD has to read and process
+in order to link a very large executable. In order to link Chrome with debug info,
+which is roughly 2 GB in output size, LLD reads
+
+- 17,000 files,
+- 1,800,000 sections,
+- 6,300,000 symbols, and
+- 13,000,000 relocations.
+
+LLD produces the 2 GB executable in 15 seconds.
+
+These numbers vary depending on your program, but in general,
+you have a lot of relocations and symbols for each file.
+If your program is written in C++, symbol names are likely to be
+pretty long because of name mangling.
+
+It is important to not waste time on relocations and symbols.
+
+In the above case, the total amount of symbol strings is 450 MB,
+and inserting all of them to a hash table takes 1.5 seconds.
+Therefore, if you causally add a hash table lookup for each symbol,
+it would slow down the linker by 10%. So, don't do that.
+
+On the other hand, you don't have to pursue efficiency
+when handling files.
+
+Important Data Strcutures
+-------------------------
+
+We will describe the key data structures in LLD in this section.
+The linker can be understood as the interactions between them.
+Once you understand their functions, the code of the linker should look obvious to you.
+
+* SymbolBody
+
+ SymbolBody is a class to represent symbols.
+ They are created for symbols in object files or archive files.
+ The linker creates linker-defined symbols as well.
+
+ There are basically three types of SymbolBodies: Defined, Undefined, or Lazy.
+
+ - Defined symbols are for all symbols that are considered as "resolved",
+ including real defined symbols, COMDAT symbols, common symbols,
+ absolute symbols, linker-created symbols, etc.
+ - Undefined symbols represent undefined symbols, which need to be replaced by
+ Defined symbols by the resolver until the link is complete.
+ - Lazy symbols represent symbols we found in archive file headers
+ which can turn into Defined if we read archieve members.
+
+* Symbol
+
+ A Symbol is a container for a SymbolBody. There's only one Symbol for each
+ unique symbol name (this uniqueness is guaranteed by the symbol table).
+ Each global symbol has only one SymbolBody at any one time, which is
+ the SymbolBody stored within a memory region of the Symbol large enough
+ to store any SymbolBody.
+
+ As the resolver reads symbols from input files, it replaces the Symbol's
+ SymbolBody with the "best" SymbolBody for its symbol name by constructing
+ the new SymbolBody in place on top of the existing SymbolBody. For example,
+ if the resolver is given a defined symbol, and the SymbolBody with its name
+ is undefined, it will construct a Defined SymbolBody over the Undefined
+ SymbolBody.
+
+ This means that each SymbolBody pointer always points to the best SymbolBody,
+ and it is possible to get from a SymbolBody to a Symbol, or vice versa,
+ by adding or subtracting a fixed offset. This memory layout helps reduce
+ the cache miss rate through high locality and a small number of required
+ pointer indirections.
+
+* SymbolTable
+
+ SymbolTable is basically a hash table from strings to Symbols
+ with a logic to resolve symbol conflicts. It resolves conflicts by symbol type.
+
+ - If we add Defined and Undefined symbols, the symbol table will keep the former.
+ - If we add Defined and Lazy symbols, it will keep the former.
+ - If we add Lazy and Undefined, it will keep the former,
+ but it will also trigger the Lazy symbol to load the archive member
+ to actually resolve the symbol.
+
+* Chunk (COFF specific)
+
+ Chunk represents a chunk of data that will occupy space in an output.
+ Each regular section becomes a chunk.
+ Chunks created for common or BSS symbols are not backed by sections.
+ The linker may create chunks to append additional data to an output as well.
+
+ Chunks know about their size, how to copy their data to mmap'ed outputs,
+ and how to apply relocations to them.
+ Specifically, section-based chunks know how to read relocation tables
+ and how to apply them.
+
+* InputSection (ELF specific)
+
+ Since we have less synthesized data for ELF, we don't abstract slices of
+ input files as Chunks for ELF. Instead, we directly use the input section
+ as an internal data type.
+
+ InputSection knows about their size and how to copy themselves to
+ mmap'ed outputs, just like COFF Chunks.
+
+* OutputSection
+
+ OutputSection is a container of InputSections (ELF) or Chunks (COFF).
+ An InputSection or Chunk belongs to at most one OutputSection.
+
+There are mainly three actors in this linker.
+
+* InputFile
+
+ InputFile is a superclass of file readers.
+ We have a different subclass for each input file type,
+ such as regular object file, archive file, etc.
+ They are responsible for creating and owning SymbolBodies and
+ InputSections/Chunks.
+
+* Writer
+
+ The writer is responsible for writing file headers and InputSections/Chunks to a file.
+ It creates OutputSections, put all InputSections/Chunks into them,
+ assign unique, non-overlapping addresses and file offsets to them,
+ and then write them down to a file.
+
+* Driver
+
+ The linking process is driven by the driver. The driver
+
+ - processes command line options,
+ - creates a symbol table,
+ - creates an InputFile for each input file and put all symbols in it into the symbol table,
+ - checks if there's no remaining undefined symbols,
+ - creates a writer,
+ - and passes the symbol table to the writer to write the result to a file.
+
+Link-Time Optimization
+----------------------
+
+LTO is implemented by handling LLVM bitcode files as object files.
+The linker resolves symbols in bitcode files normally. If all symbols
+are successfully resolved, it then runs LLVM passes
+with all bitcode files to convert them to one big regular ELF/COFF file.
+Finally, the linker replaces bitcode symbols with ELF/COFF symbols,
+so that they are linked as if they were in the native format from the beginning.
+
+The details are described in this document.
+http://llvm.org/docs/LinkTimeOptimization.html
+
+Glossary
+--------
+
+* RVA (COFF)
+
+ Short for Relative Virtual Address.
+
+ Windows executables or DLLs are not position-independent; they are
+ linked against a fixed address called an image base. RVAs are
+ offsets from an image base.
+
+ Default image bases are 0x140000000 for executables and 0x18000000
+ for DLLs. For example, when we are creating an executable, we assume
+ that the executable will be loaded at address 0x140000000 by the
+ loader, so we apply relocations accordingly. Result texts and data
+ will contain raw absolute addresses.
+
+* VA
+
+ Short for Virtual Address. For COFF, it is equivalent to RVA + image base.
+
+* Base relocations (COFF)
+
+ Relocation information for the loader. If the loader decides to map
+ an executable or a DLL to a different address than their image
+ bases, it fixes up binaries using information contained in the base
+ relocation table. A base relocation table consists of a list of
+ locations containing addresses. The loader adds a difference between
+ RVA and actual load address to all locations listed there.
+
+ Note that this run-time relocation mechanism is much simpler than ELF.
+ There's no PLT or GOT. Images are relocated as a whole just
+ by shifting entire images in memory by some offsets. Although doing
+ this breaks text sharing, I think this mechanism is not actually bad
+ on today's computers.
+
+* ICF
+
+ Short for Identical COMDAT Folding (COFF) or Identical Code Folding (ELF).
+
+ ICF is an optimization to reduce output size by merging read-only sections
+ by not only their names but by their contents. If two read-only sections
+ happen to have the same metadata, actual contents and relocations,
+ they are merged by ICF. It is known as an effective technique,
+ and it usually reduces C++ program's size by a few percent or more.
+
+ Note that this is not entirely sound optimization. C/C++ require
+ different functions have different addresses. If a program depends on
+ that property, it would fail at runtime.
+
+ On Windows, that's not really an issue because MSVC link.exe enabled
+ the optimization by default. As long as your program works
+ with the linker's default settings, your program should be safe with ICF.
+
+ On Unix, your program is generally not guaranteed to be safe with ICF,
+ although large programs happen to work correctly.
+ LLD works fine with ICF for example.
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
new file mode 100644
index 000000000000..79b8c2f88d72
--- /dev/null
+++ b/docs/ReleaseNotes.rst
@@ -0,0 +1,35 @@
+======================
+LLD 3.9 Release Notes
+======================
+
+.. contents::
+ :local:
+
+.. warning::
+ These are in-progress notes for the upcoming LLVM 3.9 release.
+
+Introduction
+============
+
+This document contains the release notes for the LLD linker, release 3.9.
+Here we describe the status of LLD, including major improvements
+from the previous release. All LLD releases may be downloaded
+from the `LLVM releases web site <http://llvm.org/releases/>`_.
+
+Non-comprehensive list of changes in this release
+=================================================
+
+ELF Improvements
+----------------
+
+* Initial support for LTO.
+
+COFF Improvements
+-----------------
+
+* Item 1.
+
+MachO Improvements
+------------------
+
+* Item 1.
diff --git a/docs/conf.py b/docs/conf.py
index 99866e1bd1e1..88fcdd8afcae 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -11,6 +11,7 @@
# serve to show the default.
import sys, os
+from datetime import date
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@@ -40,7 +41,7 @@ master_doc = 'index'
# General information about the project.
project = u'lld'
-copyright = u'2011-2014, LLVM Project'
+copyright = u'2011-%d, LLVM Project' % date.today().year
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
diff --git a/docs/design.rst b/docs/design.rst
index 408b8acaf890..14d180936902 100644
--- a/docs/design.rst
+++ b/docs/design.rst
@@ -150,37 +150,6 @@ into an Atom graph. For instance, you may want the Reader to only accept
certain architectures. The options class can be instantiated from command
line options, or it can be subclassed and the ivars programmatically set.
-ELF Section Groups
-~~~~~~~~~~~~~~~~~~
-Reference : `ELF Section Groups <http://mentorembedded.github.io/cxx-abi/abi/prop-72-comdat.html>`_
-
-C++ has many situations where the compiler may need to emit code or data,
-but may not be able to identify a unique compilation unit where it should be
-emitted. The approach chosen by the C++ ABI group to deal with this problem, is
-to allow the compiler to emit the required information in multiple compilation
-units, in a form which allows the linker to remove all but one copy. This is
-essentially the feature called COMDAT in several existing implementations.
-
-The COMDAT sections in ELF are modeled by using '.group' sections in the input
-files. Each '.group' section is associated with a signature. The '.group'
-section has a list of members that are part of the the '.group' which the linker
-selects to appear in the input file(Whichever .group section appeared first
-in the link). References to any of the '.group' members can also appear from
-outside the '.group'.
-
-In lld the the '.group' sections with COMDAT are identified by contentType(
-typeGroupComdat). The '.group' members are identified by using
-**kindGroupChild** references.
-
-The point to be noted here is the 'group child' members would need to be emitted
-in the output file **iff** the group was selected by the resolver.
-
-This is modeled in lld by removing the 'group child' members from the
-definedAtom List.
-
-Any reference to the group-child from **outside the group** is referenced using
-a 'undefined' atom.
-
Resolving
~~~~~~~~~
diff --git a/docs/index.rst b/docs/index.rst
index 88c6f217531a..d019c4f9fd8c 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -4,55 +4,12 @@ lld - The LLVM Linker
=====================
lld contains two linkers whose architectures are different from each other.
-One is a linker that implements native features directly.
-They are in `COFF` or `ELF` directories. Other directories contains the other
-implementation that is designed to be a set of modular code for creating
-linker tools. This document covers mainly the latter.
-For the former, please read README.md in `COFF` directory.
-* End-User Features:
-
- * Compatible with existing linker options
- * Reads standard Object Files (e.g. ELF, Mach-O, PE/COFF)
- * Writes standard Executable Files (e.g. ELF, Mach-O, PE)
- * Remove clang's reliance on "the system linker"
- * Uses the LLVM `"UIUC" BSD-Style license`__.
-
-* Applications:
-
- * Modular design
- * Support cross linking
- * Easy to add new CPU support
- * Can be built as static tool or library
-
-* Design and Implementation:
-
- * Extensive unit tests
- * Internal linker model can be dumped/read to textual format
- * Additional linking features can be plugged in as "passes"
- * OS specific and CPU specific code factored out
-
-Why a new linker?
------------------
-
-The fact that clang relies on whatever linker tool you happen to have installed
-means that clang has been very conservative adopting features which require a
-recent linker.
-
-In the same way that the MC layer of LLVM has removed clang's reliance on the
-system assembler tool, the lld project will remove clang's reliance on the
-system linker tool.
-
-
-Current Status
---------------
-
-lld can self host on x86-64 FreeBSD and Linux and x86 Windows.
-
-All SingleSource tests in test-suite pass on x86-64 Linux.
+.. toctree::
+ :maxdepth: 1
-All SingleSource and MultiSource tests in the LLVM test-suite
-pass on MIPS 32-bit little-endian Linux.
+ NewLLD
+ AtomLLD
Source
------
@@ -66,24 +23,3 @@ lld is also available via the read-only git mirror::
git clone http://llvm.org/git/lld.git
Put it in llvm's tools/ directory, rerun cmake, then build target lld.
-
-Contents
---------
-
-.. toctree::
- :maxdepth: 2
-
- design
- getting_started
- development
- windows_support
- open_projects
- sphinx_intro
-
-Indices and tables
-------------------
-
-* :ref:`genindex`
-* :ref:`search`
-
-__ http://llvm.org/docs/DeveloperPolicy.html#license
diff --git a/docs/open_projects.rst b/docs/open_projects.rst
index 448e967b5536..eeb9f9f48f34 100644
--- a/docs/open_projects.rst
+++ b/docs/open_projects.rst
@@ -4,11 +4,6 @@ Open Projects
=============
.. include:: ../include/lld/Core/TODO.txt
-.. include:: ../lib/Driver/TODO.rst
-.. include:: ../lib/ReaderWriter/ELF/X86_64/TODO.rst
-.. include:: ../lib/ReaderWriter/ELF/AArch64/TODO.rst
-.. include:: ../lib/ReaderWriter/ELF/ARM/TODO.rst
-.. include:: ../tools/lld/TODO.txt
Documentation TODOs
~~~~~~~~~~~~~~~~~~~
diff --git a/include/lld/Core/Alias.h b/include/lld/Core/Alias.h
deleted file mode 100644
index fa999292fbd3..000000000000
--- a/include/lld/Core/Alias.h
+++ /dev/null
@@ -1,100 +0,0 @@
-//===- lld/Core/Alias.h - Alias atoms -------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provide alias atoms.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ALIAS_H
-#define LLD_CORE_ALIAS_H
-
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/Optional.h"
-#include <string>
-
-namespace lld {
-
-// An AliasAtom is a zero-size atom representing an alias for other atom. It has
-// a LayoutAfter reference to the target atom, so that this atom and the target
-// atom will be laid out at the same location in the final result. Initially
-// the target atom is an undefined atom. Resolver will replace it with a defined
-// one.
-//
-// It does not have attributes itself. Most member function calls are forwarded
-// to the target atom.
-class AliasAtom : public SimpleDefinedAtom {
-public:
- AliasAtom(const File &file, StringRef name)
- : SimpleDefinedAtom(file), _name(name) {}
-
- StringRef name() const override { return _name; }
- uint64_t size() const override { return 0; }
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-
- Scope scope() const override {
- getTarget();
- return _target ? _target->scope() : scopeLinkageUnit;
- }
-
- Merge merge() const override {
- if (_merge.hasValue())
- return _merge.getValue();
- getTarget();
- return _target ? _target->merge() : mergeNo;
- }
-
- void setMerge(Merge val) { _merge = val; }
-
- ContentType contentType() const override {
- getTarget();
- return _target ? _target->contentType() : typeUnknown;
- }
-
- Interposable interposable() const override {
- getTarget();
- return _target ? _target->interposable() : interposeNo;
- }
-
- SectionChoice sectionChoice() const override {
- getTarget();
- return _target ? _target->sectionChoice() : sectionBasedOnContent;
- }
-
- StringRef customSectionName() const override {
- getTarget();
- return _target ? _target->customSectionName() : StringRef("");
- }
-
- DeadStripKind deadStrip() const override { return _deadStrip; }
- void setDeadStrip(DeadStripKind val) { _deadStrip = val; }
-
-private:
- void getTarget() const {
- if (_target)
- return;
- for (const Reference *r : *this) {
- if (r->kindNamespace() == lld::Reference::KindNamespace::all &&
- r->kindValue() == lld::Reference::kindLayoutAfter) {
- _target = dyn_cast<DefinedAtom>(r->target());
- return;
- }
- }
- }
-
- std::string _name;
- mutable const DefinedAtom *_target = nullptr;
- llvm::Optional<Merge> _merge = DefinedAtom::mergeNo;
- DeadStripKind _deadStrip = DefinedAtom::deadStripNormal;
-};
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/Core/ArchiveLibraryFile.h b/include/lld/Core/ArchiveLibraryFile.h
index ff379d4f3ecf..2c736e7d6c61 100644
--- a/include/lld/Core/ArchiveLibraryFile.h
+++ b/include/lld/Core/ArchiveLibraryFile.h
@@ -11,7 +11,6 @@
#define LLD_CORE_ARCHIVE_LIBRARY_FILE_H
#include "lld/Core/File.h"
-#include "lld/Core/Parallel.h"
#include <set>
namespace lld {
@@ -33,23 +32,11 @@ public:
/// Check if any member of the archive contains an Atom with the
/// specified name and return the File object for that member, or nullptr.
- virtual File *find(StringRef name, bool dataSymbolOnly) = 0;
+ virtual File *find(StringRef name) = 0;
virtual std::error_code
parseAllMembers(std::vector<std::unique_ptr<File>> &result) = 0;
- // Parses a member file containing a given symbol, so that when you
- // need the file find() can return that immediately. Calling this function
- // has no side effect other than pre-instantiating a file. Calling this
- // function doesn't affect correctness.
- virtual void preload(TaskGroup &group, StringRef symbolName) {}
-
- /// Returns a set of all defined symbols in the archive, i.e. all
- /// resolvable symbol using this file.
- virtual std::set<StringRef> getDefinedSymbols() {
- return std::set<StringRef>();
- }
-
protected:
/// only subclasses of ArchiveLibraryFile can be instantiated
ArchiveLibraryFile(StringRef path) : File(path, kindArchiveLibrary) {}
diff --git a/include/lld/Core/Atom.h b/include/lld/Core/Atom.h
index 27fdde022ba7..42ca2bb8af8c 100644
--- a/include/lld/Core/Atom.h
+++ b/include/lld/Core/Atom.h
@@ -16,6 +16,9 @@ namespace lld {
class File;
+template<typename T>
+class OwningAtomPtr;
+
///
/// The linker has a Graph Theory model of linking. An object file is seen
/// as a set of Atoms with References to other Atoms. Each Atom is a node
@@ -24,6 +27,7 @@ class File;
/// undefined symbol (extern declaration).
///
class Atom {
+ template<typename T> friend class OwningAtomPtr;
public:
/// Whether this atom is defined or a proxy for an undefined symbol
enum Definition {
@@ -71,6 +75,55 @@ private:
Definition _definition;
};
+/// Class which owns an atom pointer and runs the atom destructor when the
+/// owning pointer goes out of scope.
+template<typename T>
+class OwningAtomPtr {
+private:
+ OwningAtomPtr(const OwningAtomPtr &) = delete;
+ void operator=(const OwningAtomPtr&) = delete;
+public:
+ OwningAtomPtr() : atom(nullptr) { }
+ OwningAtomPtr(T *atom) : atom(atom) { }
+
+ ~OwningAtomPtr() {
+ if (atom)
+ runDestructor(atom);
+ }
+
+ void runDestructor(Atom *atom) {
+ atom->~Atom();
+ }
+
+ OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) {
+ ptr.atom = nullptr;
+ }
+
+ void operator=(OwningAtomPtr&& ptr) {
+ if (atom)
+ runDestructor(atom);
+ atom = ptr.atom;
+ ptr.atom = nullptr;
+ }
+
+ T *const &get() const {
+ return atom;
+ }
+
+ T *&get() {
+ return atom;
+ }
+
+ T *release() {
+ auto *v = atom;
+ atom = nullptr;
+ return v;
+ }
+
+private:
+ T *atom;
+};
+
} // namespace lld
#endif // LLD_CORE_ATOM_H
diff --git a/include/lld/Core/DefinedAtom.h b/include/lld/Core/DefinedAtom.h
index e4d4488ccdca..e3193f8aaf2e 100644
--- a/include/lld/Core/DefinedAtom.h
+++ b/include/lld/Core/DefinedAtom.h
@@ -11,11 +11,12 @@
#define LLD_CORE_DEFINED_ATOM_H
#include "lld/Core/Atom.h"
+#include "lld/Core/Reference.h"
#include "lld/Core/LLVM.h"
+#include "llvm/Support/ErrorHandling.h"
namespace lld {
class File;
-class Reference;
/// \brief The fundamental unit of linking.
///
@@ -105,6 +106,7 @@ public:
enum ContentType {
typeUnknown, // for use with definitionUndefined
+ typeMachHeader, // atom representing mach_header [Darwin]
typeCode, // executable code
typeResolver, // function which returns address of target
typeBranchIsland, // linker created for large binaries
@@ -127,6 +129,7 @@ public:
typeObjC1Class, // ObjC1 class [Darwin]
typeLazyPointer, // pointer through which a stub jumps
typeLazyDylibPointer, // pointer through which a stub jumps [Darwin]
+ typeNonLazyPointer, // pointer to external symbol
typeCFString, // NS/CFString object [Darwin]
typeGOT, // pointer to external symbol
typeInitializerPtr, // pointer to initializer function
@@ -134,6 +137,8 @@ public:
typeCStringPtr, // pointer to UTF8 C string [Darwin]
typeObjCClassPtr, // pointer to ObjC class [Darwin]
typeObjC2CategoryList, // pointers to ObjC category [Darwin]
+ typeObjCImageInfo, // pointer to ObjC class [Darwin]
+ typeObjCMethodList, // pointer to ObjC method list [Darwin]
typeDTraceDOF, // runtime data for Dtrace [Darwin]
typeInterposingTuples, // tuples of interposing info for dyld [Darwin]
typeTempLTO, // temporary atom for bitcode reader
@@ -143,14 +148,7 @@ public:
typeTLVInitialData, // initial data for a TLV [Darwin]
typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
typeTLVInitializerPtr, // pointer to thread local initializer [Darwin]
- typeMachHeader, // atom representing mach_header [Darwin]
- typeThreadZeroFill, // Uninitialized thread local data(TBSS) [ELF]
- typeThreadData, // Initialized thread local data(TDATA) [ELF]
- typeRONote, // Identifies readonly note sections [ELF]
- typeRWNote, // Identifies readwrite note sections [ELF]
- typeNoAlloc, // Identifies non allocatable sections [ELF]
- typeGroupComdat, // Identifies a section group [ELF, COFF]
- typeGnuLinkOnce, // Identifies a gnu.linkonce section [ELF]
+ typeDSOHandle, // atom representing DSO handle [Darwin]
typeSectCreate, // Created via the -sectcreate option [Darwin]
};
@@ -218,11 +216,6 @@ public:
///
/// This is used by the linker to order the layout of Atoms so that the
/// resulting image is stable and reproducible.
- ///
- /// Note that this should not be confused with ordinals of exported symbols in
- /// Windows DLLs. In Windows terminology, ordinals are symbols' export table
- /// indices (small integers) which can be used instead of symbol names to
- /// refer items in a DLL.
virtual uint64_t ordinal() const = 0;
/// \brief the number of bytes of space this atom's content will occupy in the
@@ -307,8 +300,12 @@ public:
return _atom.derefIterator(_it);
}
+ bool operator==(const reference_iterator &other) const {
+ return _it == other._it;
+ }
+
bool operator!=(const reference_iterator &other) const {
- return _it != other._it;
+ return !(*this == other);
}
reference_iterator &operator++() {
@@ -326,6 +323,14 @@ public:
/// \brief Returns an iterator to the end of this Atom's References.
virtual reference_iterator end() const = 0;
+ /// Adds a reference to this atom.
+ virtual void addReference(Reference::KindNamespace ns,
+ Reference::KindArch arch,
+ Reference::KindValue kindValue, uint64_t off,
+ const Atom *target, Reference::Addend a) {
+ llvm_unreachable("Subclass does not permit adding references");
+ }
+
static bool classof(const Atom *a) {
return a->definition() == definitionRegular;
}
@@ -338,16 +343,15 @@ public:
ContentType atomContentType = contentType();
return !(atomContentType == DefinedAtom::typeZeroFill ||
atomContentType == DefinedAtom::typeZeroFillFast ||
- atomContentType == DefinedAtom::typeTLVInitialZeroFill ||
- atomContentType == DefinedAtom::typeThreadZeroFill);
+ atomContentType == DefinedAtom::typeTLVInitialZeroFill);
}
- /// Utility function to check if the atom belongs to a group section
- /// that represents section groups or .gnu.linkonce sections.
- bool isGroupParent() const {
+ /// Utility function to check if relocations in this atom to other defined
+ /// atoms can be implicitly generated, and so we don't need to explicitly
+ /// emit those relocations.
+ bool relocsToDefinedCanBeImplicit() const {
ContentType atomContentType = contentType();
- return (atomContentType == DefinedAtom::typeGroupComdat ||
- atomContentType == DefinedAtom::typeGnuLinkOnce);
+ return atomContentType == typeCFI;
}
// Returns true if lhs should be placed before rhs in the final output.
@@ -359,6 +363,8 @@ protected:
// constructor.
DefinedAtom() : Atom(definitionRegular) { }
+ ~DefinedAtom() override = default;
+
/// \brief Returns a pointer to the Reference object that the abstract
/// iterator "points" to.
virtual const Reference *derefIterator(const void *iter) const = 0;
diff --git a/include/lld/Core/Error.h b/include/lld/Core/Error.h
index a7e61f91d8e9..b0bf73b1cb7b 100644
--- a/include/lld/Core/Error.h
+++ b/include/lld/Core/Error.h
@@ -15,6 +15,8 @@
#define LLD_CORE_ERROR_H
#include "lld/Core/LLVM.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
#include <system_error>
namespace lld {
@@ -30,39 +32,37 @@ inline std::error_code make_error_code(YamlReaderError e) {
return std::error_code(static_cast<int>(e), YamlReaderCategory());
}
-const std::error_category &LinkerScriptReaderCategory();
-
-enum class LinkerScriptReaderError {
- success = 0,
- parse_error,
- unknown_symbol_in_expr,
- unrecognized_function_in_expr,
- unknown_phdr_ids,
- extra_program_phdr,
- misplaced_program_phdr,
- program_phdr_wrong_phdrs,
-};
-
-inline std::error_code make_error_code(LinkerScriptReaderError e) {
- return std::error_code(static_cast<int>(e), LinkerScriptReaderCategory());
-}
-
/// Creates an error_code object that has associated with it an arbitrary
/// error messsage. The value() of the error_code will always be non-zero
/// but its value is meaningless. The messsage() will be (a copy of) the
/// supplied error string.
/// Note: Once ErrorOr<> is updated to work with errors other than error_code,
/// this can be updated to return some other kind of error.
-std::error_code make_dynamic_error_code(const char *msg);
std::error_code make_dynamic_error_code(StringRef msg);
-std::error_code make_dynamic_error_code(const Twine &msg);
+
+/// Generic error.
+///
+/// For errors that don't require their own specific sub-error (most errors)
+/// this class can be used to describe the error via a string message.
+class GenericError : public llvm::ErrorInfo<GenericError> {
+public:
+ static char ID;
+ GenericError(Twine Msg);
+ const std::string &getMessage() const { return Msg; }
+ void log(llvm::raw_ostream &OS) const override;
+
+ std::error_code convertToErrorCode() const override {
+ return make_dynamic_error_code(getMessage());
+ }
+
+private:
+ std::string Msg;
+};
} // end namespace lld
namespace std {
template <> struct is_error_code_enum<lld::YamlReaderError> : std::true_type {};
-template <>
-struct is_error_code_enum<lld::LinkerScriptReaderError> : std::true_type {};
}
#endif
diff --git a/include/lld/Core/File.h b/include/lld/Core/File.h
index 494e50065340..20418688dfa0 100644
--- a/include/lld/Core/File.h
+++ b/include/lld/Core/File.h
@@ -14,8 +14,8 @@
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
-#include "lld/Core/range.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include <functional>
@@ -45,9 +45,18 @@ public:
/// \brief Kinds of files that are supported.
enum Kind {
- kindObject, ///< object file (.o)
- kindSharedLibrary, ///< shared library (.so)
- kindArchiveLibrary ///< archive (.a)
+ kindErrorObject, ///< a error object file (.o)
+ kindNormalizedObject, ///< a normalized file (.o)
+ kindMachObject, ///< a MachO object file (.o)
+ kindCEntryObject, ///< a file for CEntries
+ kindHeaderObject, ///< a file for file headers
+ kindEntryObject, ///< a file for the entry
+ kindUndefinedSymsObject, ///< a file for undefined symbols
+ kindStubHelperObject, ///< a file for stub helpers
+ kindResolverMergedObject, ///< the resolver merged file.
+ kindSectCreateObject, ///< a sect create object file (.o)
+ kindSharedLibrary, ///< shared library (.so)
+ kindArchiveLibrary ///< archive (.a)
};
/// \brief Returns file kind. Need for dyn_cast<> on File objects.
@@ -97,17 +106,69 @@ public:
}
/// The type of atom mutable container.
- template <typename T> using AtomVector = std::vector<const T *>;
+ template <typename T> using AtomVector = std::vector<OwningAtomPtr<T>>;
- /// The range type for the atoms. It's backed by a std::vector, but hides
- /// its member functions so that you can only call begin or end.
+ /// The range type for the atoms.
template <typename T> class AtomRange {
public:
- AtomRange(AtomVector<T> v) : _v(v) {}
- typename AtomVector<T>::const_iterator begin() const { return _v.begin(); }
- typename AtomVector<T>::const_iterator end() const { return _v.end(); }
- typename AtomVector<T>::iterator begin() { return _v.begin(); }
- typename AtomVector<T>::iterator end() { return _v.end(); }
+ AtomRange(AtomVector<T> &v) : _v(v) {}
+ AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
+
+ typedef std::pointer_to_unary_function<const OwningAtomPtr<T>&,
+ const T*> ConstDerefFn;
+
+ typedef std::pointer_to_unary_function<OwningAtomPtr<T>&, T*> DerefFn;
+
+ typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
+ ConstDerefFn> ConstItTy;
+ typedef llvm::mapped_iterator<typename AtomVector<T>::iterator,
+ DerefFn> ItTy;
+
+ static const T* DerefConst(const OwningAtomPtr<T> &p) {
+ return p.get();
+ }
+
+ static T* Deref(OwningAtomPtr<T> &p) {
+ return p.get();
+ }
+
+ ConstItTy begin() const {
+ return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
+ }
+ ConstItTy end() const {
+ return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
+ }
+
+ ItTy begin() {
+ return ItTy(_v.begin(), DerefFn(Deref));
+ }
+ ItTy end() {
+ return ItTy(_v.end(), DerefFn(Deref));
+ }
+
+ llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() {
+ return llvm::make_range(_v.begin(), _v.end());
+ }
+
+ llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
+ return llvm::make_range(_v.begin(), _v.end());
+ }
+
+ bool empty() const {
+ return _v.empty();
+ }
+
+ size_t size() const {
+ return _v.size();
+ }
+
+ const OwningAtomPtr<T> &operator[](size_t idx) const {
+ return _v[idx];
+ }
+
+ OwningAtomPtr<T> &operator[](size_t idx) {
+ return _v[idx];
+ }
private:
AtomVector<T> &_v;
@@ -115,19 +176,25 @@ public:
/// \brief Must be implemented to return the AtomVector object for
/// all DefinedAtoms in this File.
- virtual const AtomVector<DefinedAtom> &defined() const = 0;
+ virtual const AtomRange<DefinedAtom> defined() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all UndefinedAtomw in this File.
- virtual const AtomVector<UndefinedAtom> &undefined() const = 0;
+ virtual const AtomRange<UndefinedAtom> undefined() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all SharedLibraryAtoms in this File.
- virtual const AtomVector<SharedLibraryAtom> &sharedLibrary() const = 0;
+ virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all AbsoluteAtoms in this File.
- virtual const AtomVector<AbsoluteAtom> &absolute() const = 0;
+ virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
+
+ /// Drop all of the atoms owned by this file. This will result in all of
+ /// the atoms running their destructors.
+ /// This is required because atoms may be allocated on a BumpPtrAllocator
+ /// of a different file. We need to destruct all atoms before any files.
+ virtual void clearAtoms() = 0;
/// \brief If a file is parsed using a different method than doParse(),
/// one must use this method to set the last error status, so that
@@ -137,14 +204,6 @@ public:
std::error_code parse();
- // This function is called just before the core linker tries to use
- // a file. Currently the PECOFF reader uses this to trigger the
- // driver to parse .drectve section (which contains command line options).
- // If you want to do something having side effects, don't do that in
- // doParse() because a file could be pre-loaded speculatively.
- // Use this hook instead.
- virtual void beforeLink() {}
-
// Usually each file owns a std::unique_ptr<MemoryBuffer>.
// However, there's one special case. If a file is an archive file,
// the archive file and its children all shares the same memory buffer.
@@ -190,23 +249,26 @@ private:
class ErrorFile : public File {
public:
ErrorFile(StringRef path, std::error_code ec)
- : File(path, kindObject), _ec(ec) {}
+ : File(path, kindErrorObject), _ec(ec) {}
std::error_code doParse() override { return _ec; }
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
llvm_unreachable("internal error");
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
llvm_unreachable("internal error");
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
llvm_unreachable("internal error");
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
llvm_unreachable("internal error");
}
+ void clearAtoms() override {
+ }
+
private:
std::error_code _ec;
};
diff --git a/include/lld/Core/LLVM.h b/include/lld/Core/LLVM.h
index d532c17fbfdf..ccf08859f4ae 100644
--- a/include/lld/Core/LLVM.h
+++ b/include/lld/Core/LLVM.h
@@ -23,6 +23,7 @@
namespace llvm {
// ADT's.
+ class Error;
class StringRef;
class Twine;
class MemoryBuffer;
@@ -38,6 +39,9 @@ namespace llvm {
template<typename T>
class ErrorOr;
+ template<typename T>
+ class Expected;
+
class raw_ostream;
// TODO: DenseMap, ...
}
@@ -51,6 +55,7 @@ namespace lld {
using llvm::cast_or_null;
// ADT's.
+ using llvm::Error;
using llvm::StringRef;
using llvm::Twine;
using llvm::MemoryBuffer;
@@ -61,6 +66,7 @@ namespace lld {
using llvm::SmallVectorImpl;
using llvm::SaveAndRestore;
using llvm::ErrorOr;
+ using llvm::Expected;
using llvm::raw_ostream;
} // end namespace lld.
diff --git a/include/lld/Core/LinkingContext.h b/include/lld/Core/LinkingContext.h
index a723854b3c91..7e4edaf22cf3 100644
--- a/include/lld/Core/LinkingContext.h
+++ b/include/lld/Core/LinkingContext.h
@@ -13,9 +13,7 @@
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Node.h"
-#include "lld/Core/Parallel.h"
#include "lld/Core/Reference.h"
-#include "lld/Core/range.h"
#include "lld/Core/Reader.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/raw_ostream.h"
@@ -33,16 +31,9 @@ class SharedLibraryFile;
///
/// The base class LinkingContext contains the options needed by core linking.
/// Subclasses of LinkingContext have additional options needed by specific
-/// Writers. For example, ELFLinkingContext has methods that supplies
-/// options to the ELF Writer and ELF Passes.
+/// Writers.
class LinkingContext {
public:
- /// \brief The types of output file that the linker creates.
- enum class OutputFileType : uint8_t {
- Default, // The default output type for this target
- YAML, // The output type is set to YAML
- };
-
virtual ~LinkingContext();
/// \name Methods needed by core linking
@@ -78,28 +69,6 @@ public:
_deadStripRoots.push_back(symbolName);
}
- /// Archive files (aka static libraries) are normally lazily loaded. That is,
- /// object files within an archive are only loaded and linked in, if the
- /// object file contains a DefinedAtom which will replace an existing
- /// UndefinedAtom. If this method returns true, core linking will also look
- /// for archive members to replace existing tentative definitions in addition
- /// to replacing undefines. Note: a "tentative definition" (also called a
- /// "common" symbols) is a C (but not C++) concept. They are modeled in lld
- /// as a DefinedAtom with merge() of mergeAsTentative.
- bool searchArchivesToOverrideTentativeDefinitions() const {
- return _searchArchivesToOverrideTentativeDefinitions;
- }
-
- /// Normally core linking will turn a tentative definition into a real
- /// definition if not replaced by a real DefinedAtom from some object file.
- /// If this method returns true, core linking will search all supplied
- /// dynamic shared libraries for symbol names that match remaining tentative
- /// definitions. If any are found, the corresponding tentative definition
- /// atom is replaced with SharedLibraryAtom.
- bool searchSharedLibrariesToOverrideTentativeDefinitions() const {
- return _searchSharedLibrariesToOverrideTentativeDefinitions;
- }
-
/// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
/// SharedLibraryAtom for the link to be successful. This method controls
/// whether core linking prints out a list of remaining UndefinedAtoms.
@@ -114,35 +83,6 @@ public:
/// whether core linking considers remaining undefines to be an error.
bool allowRemainingUndefines() const { return _allowRemainingUndefines; }
- /// In the lld model, a SharedLibraryAtom is a proxy atom for something
- /// that will be found in a dynamic shared library when the program runs.
- /// A SharedLibraryAtom optionally contains the name of the shared library
- /// in which to find the symbol name at runtime. Core linking may merge
- /// two SharedLibraryAtom with the same name. If this method returns true,
- /// when merging core linking will also verify that they both have the same
- /// loadName() and if not print a warning.
- ///
- /// \todo This should be a method core linking calls so that drivers can
- /// format the warning as needed.
- bool warnIfCoalesableAtomsHaveDifferentLoadName() const {
- return _warnIfCoalesableAtomsHaveDifferentLoadName;
- }
-
- /// In C/C++ you can mark a function's prototype with
- /// __attribute__((weak_import)) or __attribute__((weak)) to say the function
- /// may not be available at runtime and/or build time and in which case its
- /// address will evaluate to NULL. In lld this is modeled using the
- /// UndefinedAtom::canBeNull() method. During core linking, UndefinedAtom
- /// with the same name are automatically merged. If this method returns
- /// true, core link also verfies that the canBeNull() value for merged
- /// UndefinedAtoms are the same and warns if not.
- ///
- /// \todo This should be a method core linking calls so that drivers can
- /// format the warning as needed.
- bool warnIfCoalesableAtomsHaveDifferentCanBeNull() const {
- return _warnIfCoalesableAtomsHaveDifferentCanBeNull;
- }
-
/// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
/// SharedLibraryAtom for the link to be successful. This method controls
/// whether core linking considers remaining undefines from the shared library
@@ -176,20 +116,7 @@ public:
}
void setDeadStripping(bool enable) { _deadStrip = enable; }
- void setAllowDuplicates(bool enable) { _allowDuplicates = enable; }
void setGlobalsAreDeadStripRoots(bool v) { _globalsAreDeadStripRoots = v; }
- void setSearchArchivesToOverrideTentativeDefinitions(bool search) {
- _searchArchivesToOverrideTentativeDefinitions = search;
- }
- void setSearchSharedLibrariesToOverrideTentativeDefinitions(bool search) {
- _searchSharedLibrariesToOverrideTentativeDefinitions = search;
- }
- void setWarnIfCoalesableAtomsHaveDifferentCanBeNull(bool warn) {
- _warnIfCoalesableAtomsHaveDifferentCanBeNull = warn;
- }
- void setWarnIfCoalesableAtomsHaveDifferentLoadName(bool warn) {
- _warnIfCoalesableAtomsHaveDifferentLoadName = warn;
- }
void setPrintRemainingUndefines(bool print) {
_printRemainingUndefines = print;
}
@@ -199,27 +126,11 @@ public:
void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; }
void setLogInputFiles(bool log) { _logInputFiles = log; }
- // Returns true if multiple definitions should not be treated as a
- // fatal error.
- bool getAllowDuplicates() const { return _allowDuplicates; }
-
void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); }
- void addAlias(StringRef from, StringRef to) { _aliasSymbols[from] = to; }
- const std::map<std::string, std::string> &getAliases() const {
- return _aliasSymbols;
- }
-
std::vector<std::unique_ptr<Node>> &getNodes() { return _nodes; }
const std::vector<std::unique_ptr<Node>> &getNodes() const { return _nodes; }
- /// Notify the LinkingContext when the symbol table found a name collision.
- /// The useNew parameter specifies which the symbol table plans to keep,
- /// but that can be changed by the LinkingContext. This is also an
- /// opportunity for flavor specific processing.
- virtual void notifySymbolTableCoalesce(const Atom *existingAtom,
- const Atom *newAtom, bool &useNew) {}
-
/// This method adds undefined symbols specified by the -u option to the to
/// the list of undefined symbols known to the linker. This option essentially
/// forces an undefined symbol to be created. You may also need to call
@@ -242,7 +153,7 @@ public:
/// Return the list of undefined symbols that are specified in the
/// linker command line, using the -u option.
- range<const StringRef *> initialUndefinedSymbols() const {
+ ArrayRef<StringRef> initialUndefinedSymbols() const {
return _initialUndefinedSymbols;
}
@@ -255,9 +166,7 @@ public:
bool validate(raw_ostream &diagnostics);
/// Formats symbol name for use in error messages.
- virtual std::string demangle(StringRef symbolName) const {
- return symbolName;
- }
+ virtual std::string demangle(StringRef symbolName) const = 0;
/// @}
/// \name Methods used by Driver::link()
@@ -269,19 +178,6 @@ public:
/// the linker to write to an in-memory buffer.
StringRef outputPath() const { return _outputPath; }
- /// Set the various output file types that the linker would
- /// create
- bool setOutputFileType(StringRef outputFileType) {
- if (outputFileType.equals_lower("yaml")) {
- _outputFileType = OutputFileType::YAML;
- return true;
- }
- return false;
- }
-
- /// Returns the output file type that that the linker needs to create.
- OutputFileType outputFileType() const { return _outputFileType; }
-
/// Accessor for Register object embedded in LinkingContext.
const Registry &registry() const { return _registry; }
Registry &registry() { return _registry; }
@@ -289,25 +185,30 @@ public:
/// This method is called by core linking to give the Writer a chance
/// to add file format specific "files" to set of files to be linked. This is
/// how file format specific atoms can be added to the link.
- virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &);
+ virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &) = 0;
/// This method is called by core linking to build the list of Passes to be
/// run on the merged/linked graph of all input files.
- virtual void addPasses(PassManager &pm);
+ virtual void addPasses(PassManager &pm) = 0;
/// Calls through to the writeFile() method on the specified Writer.
///
/// \param linkedFile This is the merged/linked graph of all input file Atoms.
- virtual std::error_code writeFile(const File &linkedFile) const;
+ virtual llvm::Error writeFile(const File &linkedFile) const;
/// Return the next ordinal and Increment it.
virtual uint64_t getNextOrdinalAndIncrement() const { return _nextOrdinal++; }
// This function is called just before the Resolver kicks in.
// Derived classes may use it to change the list of input files.
- virtual void finalizeInputFiles() {}
+ virtual void finalizeInputFiles() = 0;
- TaskGroup &getTaskGroup() { return _taskGroup; }
+ /// Callback invoked for each file the Resolver decides we are going to load.
+ /// This can be used to update context state based on the file, and emit
+ /// errors for any differences between the context state and a loaded file.
+ /// For example, we can error if we try to load a file which is a different
+ /// arch from that being linked.
+ virtual llvm::Error handleLoadedFile(File &file) = 0;
/// @}
protected:
@@ -324,36 +225,25 @@ protected:
virtual std::unique_ptr<File> createUndefinedSymbolFile() const;
std::unique_ptr<File> createUndefinedSymbolFile(StringRef filename) const;
- /// Method to create an internal file for alias symbols
- std::unique_ptr<File> createAliasSymbolFile() const;
-
StringRef _outputPath;
StringRef _entrySymbolName;
- bool _deadStrip;
- bool _allowDuplicates;
- bool _globalsAreDeadStripRoots;
- bool _searchArchivesToOverrideTentativeDefinitions;
- bool _searchSharedLibrariesToOverrideTentativeDefinitions;
- bool _warnIfCoalesableAtomsHaveDifferentCanBeNull;
- bool _warnIfCoalesableAtomsHaveDifferentLoadName;
- bool _printRemainingUndefines;
- bool _allowRemainingUndefines;
- bool _logInputFiles;
- bool _allowShlibUndefines;
- OutputFileType _outputFileType;
+ bool _deadStrip = false;
+ bool _globalsAreDeadStripRoots = false;
+ bool _printRemainingUndefines = true;
+ bool _allowRemainingUndefines = false;
+ bool _logInputFiles = false;
+ bool _allowShlibUndefines = false;
std::vector<StringRef> _deadStripRoots;
- std::map<std::string, std::string> _aliasSymbols;
std::vector<const char *> _llvmOptions;
StringRefVector _initialUndefinedSymbols;
std::vector<std::unique_ptr<Node>> _nodes;
mutable llvm::BumpPtrAllocator _allocator;
- mutable uint64_t _nextOrdinal;
+ mutable uint64_t _nextOrdinal = 0;
Registry _registry;
private:
/// Validate the subclass bits. Only called by validate.
virtual bool validateImpl(raw_ostream &diagnostics) = 0;
- TaskGroup _taskGroup;
};
} // end namespace lld
diff --git a/include/lld/Core/Node.h b/include/lld/Core/Node.h
index cd38fbd4a482..8de0ecdbba6a 100644
--- a/include/lld/Core/Node.h
+++ b/include/lld/Core/Node.h
@@ -57,7 +57,7 @@ private:
class FileNode : public Node {
public:
explicit FileNode(std::unique_ptr<File> f)
- : Node(Node::Kind::File), _file(std::move(f)), _asNeeded(false) {}
+ : Node(Node::Kind::File), _file(std::move(f)) {}
static bool classof(const Node *a) {
return a->kind() == Node::Kind::File;
@@ -65,12 +65,8 @@ public:
File *getFile() { return _file.get(); }
- void setAsNeeded(bool val) { _asNeeded = val; }
- bool asNeeded() const { return _asNeeded; }
-
protected:
std::unique_ptr<File> _file;
- bool _asNeeded;
};
} // namespace lld
diff --git a/include/lld/Core/Parallel.h b/include/lld/Core/Parallel.h
index e2c38308b768..2dde97d9e3f0 100644
--- a/include/lld/Core/Parallel.h
+++ b/include/lld/Core/Parallel.h
@@ -12,7 +12,6 @@
#include "lld/Core/Instrumentation.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/range.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/thread.h"
@@ -63,41 +62,6 @@ public:
}
};
-/// \brief An implementation of future. std::future and std::promise in
-/// old libstdc++ have a threading bug; there is a small chance that a
-/// call of future::get throws an exception in the normal use case.
-/// We want to use our own future implementation until we drop support
-/// of old versions of libstdc++.
-/// https://gcc.gnu.org/ml/gcc-patches/2014-05/msg01389.html
-template<typename T> class Future {
-public:
- Future() : _hasValue(false) {}
-
- void set(T &&val) {
- assert(!_hasValue);
- {
- std::unique_lock<std::mutex> lock(_mutex);
- _val = val;
- _hasValue = true;
- }
- _cond.notify_all();
- }
-
- T &get() {
- std::unique_lock<std::mutex> lock(_mutex);
- if (_hasValue)
- return _val;
- _cond.wait(lock, [&] { return _hasValue; });
- return _val;
- }
-
-private:
- T _val;
- bool _hasValue;
- std::mutex _mutex;
- std::condition_variable _cond;
-};
-
// Classes in this namespace are implementation details of this header.
namespace internal {
diff --git a/include/lld/Core/Pass.h b/include/lld/Core/Pass.h
index 2e49cd1b8eee..0527f02cd362 100644
--- a/include/lld/Core/Pass.h
+++ b/include/lld/Core/Pass.h
@@ -13,7 +13,7 @@
#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
-#include "lld/Core/range.h"
+#include "llvm/Support/Error.h"
#include <vector>
namespace lld {
@@ -34,7 +34,7 @@ public:
virtual ~Pass() { }
/// Do the actual work of the Pass.
- virtual std::error_code perform(SimpleFile &mergedFile) = 0;
+ virtual llvm::Error perform(SimpleFile &mergedFile) = 0;
protected:
// Only subclassess can be instantiated.
diff --git a/include/lld/Core/PassManager.h b/include/lld/Core/PassManager.h
index 62aa119f8f76..71a25cc7f3cd 100644
--- a/include/lld/Core/PassManager.h
+++ b/include/lld/Core/PassManager.h
@@ -12,6 +12,7 @@
#include "lld/Core/LLVM.h"
#include "lld/Core/Pass.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <vector>
@@ -31,11 +32,11 @@ public:
_passes.push_back(std::move(pass));
}
- std::error_code runOnFile(SimpleFile &file) {
+ llvm::Error runOnFile(SimpleFile &file) {
for (std::unique_ptr<Pass> &pass : _passes)
- if (std::error_code EC = pass->perform(file))
+ if (llvm::Error EC = pass->perform(file))
return EC;
- return std::error_code();
+ return llvm::Error();
}
private:
diff --git a/include/lld/Core/Reader.h b/include/lld/Core/Reader.h
index 9324da475e3d..66df4380dc76 100644
--- a/include/lld/Core/Reader.h
+++ b/include/lld/Core/Reader.h
@@ -27,17 +27,14 @@ class IO;
}
namespace lld {
-class ELFLinkingContext;
class File;
class LinkingContext;
-class PECOFFLinkingContext;
class MachOLinkingContext;
/// \brief An abstract class for reading object files, library files, and
/// executable files.
///
-/// Each file format (e.g. ELF, mach-o, PECOFF, etc) have a concrete
-/// subclass of Reader.
+/// Each file format (e.g. mach-o, etc) has a concrete subclass of Reader.
class Reader {
public:
virtual ~Reader() {}
@@ -114,11 +111,7 @@ public:
// as parameters to the addSupport*() method.
void addSupportArchives(bool logLoading);
void addSupportYamlFiles();
- void addSupportCOFFObjects(PECOFFLinkingContext &);
- void addSupportCOFFImportLibraries(PECOFFLinkingContext &);
void addSupportMachOObjects(MachOLinkingContext &);
- void addSupportELFObjects(ELFLinkingContext &);
- void addSupportELFDynamicSharedObjects(ELFLinkingContext &);
/// To convert between kind values and names, the registry walks the list
/// of registered kind tables. Each table is a zero terminated array of
diff --git a/include/lld/Core/Reference.h b/include/lld/Core/Reference.h
index 971721eb7d54..86de4f6a4236 100644
--- a/include/lld/Core/Reference.h
+++ b/include/lld/Core/Reference.h
@@ -25,15 +25,13 @@ class Atom;
/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40,
/// kind=callsite, target=malloc, addend=0.
///
-/// Besides supporting traditional "relocations", References are also used
-/// grouping atoms (group comdat), forcing layout (one atom must follow
-/// another), marking data-in-code (jump tables or ARM constants), etc.
+/// Besides supporting traditional "relocations", references are also used
+/// forcing layout (one atom must follow another), marking data-in-code
+/// (jump tables or ARM constants), etc.
///
/// The "kind" of a reference is a tuple of <namespace, arch, value>. This
/// enable us to re-use existing relocation types definded for various
-/// file formats and architectures. For instance, in ELF the relocation type 10
-/// means R_X86_64_32 for x86_64, and R_386_GOTPC for i386. For PE/COFF
-/// relocation 10 means IMAGE_REL_AMD64_SECTION.
+/// file formats and architectures.
///
/// References and atoms form a directed graph. The dead-stripping pass
/// traverses them starting from dead-strip root atoms to garbage collect
@@ -47,16 +45,14 @@ public:
enum class KindNamespace {
all = 0,
testing = 1,
- ELF = 2,
- COFF = 3,
- mach_o = 4,
+ mach_o = 2,
};
KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; }
void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; }
// Which architecture the kind value is for.
- enum class KindArch { all, AArch64, AMDGPU, ARM, Hexagon, Mips, x86, x86_64 };
+ enum class KindArch { all, AArch64, ARM, x86, x86_64};
KindArch kindArch() const { return (KindArch)_kindArch; }
void setKindArch(KindArch a) { _kindArch = (uint8_t)a; }
@@ -76,8 +72,6 @@ public:
// kindLayoutAfter is treated as a bidirected edge by the dead-stripping
// pass.
kindLayoutAfter = 1,
- // kindGroupChild is treated as a bidirected edge too.
- kindGroupChild,
kindAssociate,
};
diff --git a/include/lld/Core/Resolver.h b/include/lld/Core/Resolver.h
index 05af7d9573ea..fb62a779c0a5 100644
--- a/include/lld/Core/Resolver.h
+++ b/include/lld/Core/Resolver.h
@@ -17,6 +17,7 @@
#include "lld/Core/SymbolTable.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/ErrorOr.h"
#include <set>
#include <unordered_map>
#include <unordered_set>
@@ -31,25 +32,23 @@ class LinkingContext;
/// and producing a merged graph.
class Resolver {
public:
- Resolver(LinkingContext &ctx)
- : _ctx(ctx), _symbolTable(ctx), _result(new MergedFile()),
- _fileIndex(0) {}
+ Resolver(LinkingContext &ctx) : _ctx(ctx), _result(new MergedFile()) {}
// InputFiles::Handler methods
- void doDefinedAtom(const DefinedAtom&);
- bool doUndefinedAtom(const UndefinedAtom &);
- void doSharedLibraryAtom(const SharedLibraryAtom &);
- void doAbsoluteAtom(const AbsoluteAtom &);
+ void doDefinedAtom(OwningAtomPtr<DefinedAtom> atom);
+ bool doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom);
+ void doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom);
+ void doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom);
// Handle files, this adds atoms from the current file thats
// being processed by the resolver
- bool handleFile(File &);
+ llvm::Expected<bool> handleFile(File &);
// Handle an archive library file.
- bool handleArchiveFile(File &);
+ llvm::Expected<bool> handleArchiveFile(File &);
// Handle a shared library file.
- void handleSharedLibrary(File &);
+ llvm::Error handleSharedLibrary(File &);
/// @brief do work of merging and resolving and return list
bool resolve();
@@ -57,37 +56,30 @@ public:
std::unique_ptr<SimpleFile> resultFile() { return std::move(_result); }
private:
- typedef std::function<void(StringRef, bool)> UndefCallback;
+ typedef std::function<llvm::Expected<bool>(StringRef)> UndefCallback;
bool undefinesAdded(int begin, int end);
File *getFile(int &index);
- /// \brief Add section group/.gnu.linkonce if it does not exist previously.
- void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);
-
/// \brief The main function that iterates over the files to resolve
- void updatePreloadArchiveMap();
bool resolveUndefines();
void updateReferences();
void deadStripOptimize();
bool checkUndefines();
void removeCoalescedAwayAtoms();
- void checkDylibSymbolCollisions();
- void forEachUndefines(File &file, bool searchForOverrides, UndefCallback callback);
+ llvm::Expected<bool> forEachUndefines(File &file, UndefCallback callback);
void markLive(const Atom *atom);
- void addAtoms(const std::vector<const DefinedAtom *>&);
- void maybePreloadArchiveMember(StringRef sym);
class MergedFile : public SimpleFile {
public:
- MergedFile() : SimpleFile("<linker-internal>") {}
- void addAtoms(std::vector<const Atom*>& atoms);
+ MergedFile() : SimpleFile("<linker-internal>", kindResolverMergedObject) {}
+ void addAtoms(llvm::MutableArrayRef<OwningAtomPtr<Atom>> atoms);
};
LinkingContext &_ctx;
SymbolTable _symbolTable;
- std::vector<const Atom *> _atoms;
+ std::vector<OwningAtomPtr<Atom>> _atoms;
std::set<const Atom *> _deadStripRoots;
llvm::DenseSet<const Atom *> _liveAtoms;
llvm::DenseSet<const Atom *> _deadAtoms;
@@ -97,11 +89,6 @@ private:
// --start-group and --end-group
std::vector<File *> _files;
std::map<File *, bool> _newUndefinesAdded;
- size_t _fileIndex;
-
- // Preloading
- llvm::StringMap<ArchiveLibraryFile *> _archiveMap;
- llvm::DenseSet<ArchiveLibraryFile *> _archiveSeen;
// List of undefined symbols.
std::vector<StringRef> _undefines;
diff --git a/include/lld/Core/STDExtras.h b/include/lld/Core/STDExtras.h
deleted file mode 100644
index 4a6183891844..000000000000
--- a/include/lld/Core/STDExtras.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===- lld/Core/STDExtra.h - Helpers for the stdlib -----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_STD_EXTRA_H
-#define LLD_CORE_STD_EXTRA_H
-
-namespace lld {
-/// \brief Deleter for smart pointers that only calls the destructor. Memory is
-/// managed elsewhere. A common use of this is for things allocated with a
-/// BumpPtrAllocator.
-template <class T>
-struct destruct_delete {
- void operator ()(T *ptr) {
- ptr->~T();
- }
-};
-
-template <class T>
-using unique_bump_ptr = std::unique_ptr<T, destruct_delete<T>>;
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/Core/SharedLibraryAtom.h b/include/lld/Core/SharedLibraryAtom.h
index 1b0c37c41138..7fec7a3e3d29 100644
--- a/include/lld/Core/SharedLibraryAtom.h
+++ b/include/lld/Core/SharedLibraryAtom.h
@@ -25,9 +25,7 @@ public:
};
/// Returns shared library name used to load it at runtime.
- /// On linux that is the DT_NEEDED name.
/// On Darwin it is the LC_DYLIB_LOAD dylib name.
- /// On Windows it is the DLL name that to be referred from .idata section.
virtual StringRef loadName() const = 0;
/// Returns if shared library symbol can be missing at runtime and if
@@ -46,6 +44,8 @@ public:
protected:
SharedLibraryAtom() : Atom(definitionSharedLibrary) {}
+
+ ~SharedLibraryAtom() override = default;
};
} // namespace lld
diff --git a/include/lld/Core/SharedLibraryFile.h b/include/lld/Core/SharedLibraryFile.h
index a2907287862d..53bf967b0236 100644
--- a/include/lld/Core/SharedLibraryFile.h
+++ b/include/lld/Core/SharedLibraryFile.h
@@ -27,29 +27,34 @@ public:
/// Check if the shared library exports a symbol with the specified name.
/// If so, return a SharedLibraryAtom which represents that exported
/// symbol. Otherwise return nullptr.
- virtual const SharedLibraryAtom *exports(StringRef name,
- bool dataSymbolOnly) const = 0;
+ virtual OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const = 0;
- // Returns DSO name. It's the soname (ELF), the install name (MachO) or
- // the import name (Windows).
+ // Returns the install name.
virtual StringRef getDSOName() const = 0;
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _definedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _undefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _sharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _absoluteAtoms;
}
+ void clearAtoms() override {
+ _definedAtoms.clear();
+ _undefinedAtoms.clear();
+ _sharedLibraryAtoms.clear();
+ _absoluteAtoms.clear();
+ }
+
protected:
/// only subclasses of SharedLibraryFile can be instantiated
explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}
diff --git a/include/lld/Core/Simple.h b/include/lld/Core/Simple.h
index 3c204f8ba284..f75b40327db4 100644
--- a/include/lld/Core/Simple.h
+++ b/include/lld/Core/Simple.h
@@ -15,36 +15,60 @@
#ifndef LLD_CORE_SIMPLE_H
#define LLD_CORE_SIMPLE_H
+#include "lld/Core/AbsoluteAtom.h"
+#include "lld/Core/Atom.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/LinkingContext.h"
#include "lld/Core/Reference.h"
+#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
-#include <atomic>
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <functional>
namespace lld {
class SimpleFile : public File {
public:
- SimpleFile(StringRef path) : File(path, kindObject) {}
+ SimpleFile(StringRef path, File::Kind kind)
+ : File(path, kind) {}
+
+ ~SimpleFile() override {
+ _defined.clear();
+ _undefined.clear();
+ _shared.clear();
+ _absolute.clear();
+ }
- void addAtom(const DefinedAtom &a) { _defined.push_back(&a); }
- void addAtom(const UndefinedAtom &a) { _undefined.push_back(&a); }
- void addAtom(const SharedLibraryAtom &a) { _shared.push_back(&a); }
- void addAtom(const AbsoluteAtom &a) { _absolute.push_back(&a); }
+ void addAtom(DefinedAtom &a) {
+ _defined.push_back(OwningAtomPtr<DefinedAtom>(&a));
+ }
+ void addAtom(UndefinedAtom &a) {
+ _undefined.push_back(OwningAtomPtr<UndefinedAtom>(&a));
+ }
+ void addAtom(SharedLibraryAtom &a) {
+ _shared.push_back(OwningAtomPtr<SharedLibraryAtom>(&a));
+ }
+ void addAtom(AbsoluteAtom &a) {
+ _absolute.push_back(OwningAtomPtr<AbsoluteAtom>(&a));
+ }
void addAtom(const Atom &atom) {
if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
- _defined.push_back(p);
+ addAtom(const_cast<DefinedAtom &>(*p));
} else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
- _undefined.push_back(p);
+ addAtom(const_cast<UndefinedAtom &>(*p));
} else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
- _shared.push_back(p);
+ addAtom(const_cast<SharedLibraryAtom &>(*p));
} else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
- _absolute.push_back(p);
+ addAtom(const_cast<AbsoluteAtom &>(*p));
} else {
llvm_unreachable("atom has unknown definition kind");
}
@@ -52,26 +76,33 @@ public:
void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
auto &atoms = _defined;
- auto newEnd = std::remove_if(atoms.begin(), atoms.end(), pred);
+ auto newEnd = std::remove_if(atoms.begin(), atoms.end(),
+ [&pred](OwningAtomPtr<DefinedAtom> &p) {
+ return pred(p.get());
+ });
atoms.erase(newEnd, atoms.end());
}
- const AtomVector<DefinedAtom> &defined() const override { return _defined; }
+ const AtomRange<DefinedAtom> defined() const override { return _defined; }
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _undefined;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _shared;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _absolute;
}
- typedef range<std::vector<const DefinedAtom *>::iterator> DefinedAtomRange;
- DefinedAtomRange definedAtoms() { return make_range(_defined); }
+ void clearAtoms() override {
+ _defined.clear();
+ _undefined.clear();
+ _shared.clear();
+ _absolute.clear();
+ }
private:
AtomVector<DefinedAtom> _defined;
@@ -80,48 +111,6 @@ private:
AtomVector<AbsoluteAtom> _absolute;
};
-/// \brief Archive library file that may be used as a virtual container
-/// for symbols that should be added dynamically in response to
-/// call to find() method.
-class SimpleArchiveLibraryFile : public ArchiveLibraryFile {
-public:
- SimpleArchiveLibraryFile(StringRef filename)
- : ArchiveLibraryFile(filename) {}
-
- const AtomVector<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
-
- const AtomVector<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
- }
-
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
- }
-
- const AtomVector<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
- }
-
- File *find(StringRef sym, bool dataSymbolOnly) override {
- // For descendants:
- // do some checks here and return dynamically generated files with atoms.
- return nullptr;
- }
-
- std::error_code
- parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
- return std::error_code();
- }
-
-private:
- AtomVector<DefinedAtom> _definedAtoms;
- AtomVector<UndefinedAtom> _undefinedAtoms;
- AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
- AtomVector<AbsoluteAtom> _absoluteAtoms;
-};
-
class SimpleReference : public Reference {
public:
SimpleReference(Reference::KindNamespace ns, Reference::KindArch arch,
@@ -159,12 +148,13 @@ private:
SimpleReference *_prev;
};
-}
+} // end namespace lld
// ilist will lazily create a sentinal (so end() can return a node past the
// end of the list). We need this trait so that the sentinal is allocated
// via the BumpPtrAllocator.
namespace llvm {
+
template<>
struct ilist_sentinel_traits<lld::SimpleReference> {
@@ -200,7 +190,8 @@ struct ilist_sentinel_traits<lld::SimpleReference> {
private:
mutable llvm::BumpPtrAllocator *_allocator;
};
-}
+
+} // end namespace llvm
namespace lld {
@@ -211,6 +202,10 @@ public:
_references.setAllocator(&f.allocator());
}
+ ~SimpleDefinedAtom() override {
+ _references.clearAndLeakNodesUnsafely();
+ }
+
const File &file() const override { return _file; }
StringRef name() const override { return StringRef(); }
@@ -256,9 +251,10 @@ public:
it = reinterpret_cast<const void*>(next);
}
- void addReference(Reference::KindNamespace ns, Reference::KindArch arch,
+ void addReference(Reference::KindNamespace ns,
+ Reference::KindArch arch,
Reference::KindValue kindValue, uint64_t off,
- const Atom *target, Reference::Addend a) {
+ const Atom *target, Reference::Addend a) override {
assert(target && "trying to create reference to nothing");
auto node = new (_file.allocator())
SimpleReference(ns, arch, kindValue, off, target, a);
@@ -290,6 +286,7 @@ public:
_references.push_back(node);
}
}
+
void setOrdinal(uint64_t ord) { _ordinal = ord; }
private:
@@ -306,6 +303,8 @@ public:
assert(!name.empty() && "UndefinedAtoms must have a name");
}
+ ~SimpleUndefinedAtom() override = default;
+
/// file - returns the File that produced/owns this Atom
const File &file() const override { return _file; }
@@ -320,23 +319,6 @@ private:
StringRef _name;
};
-class SimpleAbsoluteAtom : public AbsoluteAtom {
-public:
- SimpleAbsoluteAtom(const File &f, StringRef name, Scope s, uint64_t value)
- : _file(f), _name(name), _scope(s), _value(value) {}
-
- const File &file() const override { return _file; }
- StringRef name() const override { return _name; }
- uint64_t value() const override { return _value; }
- Scope scope() const override { return _scope; }
-
-private:
- const File &_file;
- StringRef _name;
- Scope _scope;
- uint64_t _value;
-};
-
} // end namespace lld
-#endif
+#endif // LLD_CORE_SIMPLE_H
diff --git a/include/lld/Core/SymbolTable.h b/include/lld/Core/SymbolTable.h
index 2e4459236d18..db610ad14066 100644
--- a/include/lld/Core/SymbolTable.h
+++ b/include/lld/Core/SymbolTable.h
@@ -34,8 +34,6 @@ class UndefinedAtom;
/// if an atom has been coalesced away.
class SymbolTable {
public:
- explicit SymbolTable(LinkingContext &);
-
/// @brief add atom to symbol table
bool add(const DefinedAtom &);
@@ -70,13 +68,6 @@ public:
/// @brief if atom has been coalesced away, return true
bool isCoalescedAway(const Atom *);
- /// @brief Find a group atom.
- const Atom *findGroup(StringRef name);
-
- /// @brief Add a group atom and returns true/false depending on whether the
- /// previously existed.
- bool addGroup(const DefinedAtom &da);
-
private:
typedef llvm::DenseMap<const Atom *, const Atom *> AtomToAtom;
@@ -105,10 +96,8 @@ private:
bool addByName(const Atom &);
bool addByContent(const DefinedAtom &);
- LinkingContext &_ctx;
AtomToAtom _replacedAtoms;
NameToAtom _nameTable;
- NameToAtom _groupTable;
AtomContentSet _contentTable;
};
diff --git a/include/lld/Core/UndefinedAtom.h b/include/lld/Core/UndefinedAtom.h
index 7a835a4ebaa8..f45d6ecda6b0 100644
--- a/include/lld/Core/UndefinedAtom.h
+++ b/include/lld/Core/UndefinedAtom.h
@@ -57,16 +57,10 @@ public:
static bool classof(const UndefinedAtom *) { return true; }
- /// Returns an undefined atom if this undefined symbol has a synonym. This is
- /// mainly used in COFF. In COFF, an unresolved external symbol can have up to
- /// one optional name (sym2) in addition to its regular name (sym1). If a
- /// definition of sym1 exists, sym1 is resolved normally. Otherwise, all
- /// references to sym1 refer to sym2 instead. In that case sym2 must be
- /// resolved, or link will fail.
- virtual const UndefinedAtom *fallback() const { return nullptr; }
-
protected:
UndefinedAtom() : Atom(definitionUndefined) {}
+
+ ~UndefinedAtom() override = default;
};
} // namespace lld
diff --git a/include/lld/Core/Writer.h b/include/lld/Core/Writer.h
index 8214ed6203f2..216f934916bc 100644
--- a/include/lld/Core/Writer.h
+++ b/include/lld/Core/Writer.h
@@ -11,25 +11,24 @@
#define LLD_CORE_WRITER_H
#include "lld/Core/LLVM.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <vector>
namespace lld {
-class ELFLinkingContext;
class File;
class LinkingContext;
class MachOLinkingContext;
-class PECOFFLinkingContext;
/// \brief The Writer is an abstract class for writing object files, shared
-/// library files, and executable files. Each file format (e.g. ELF, mach-o,
-/// PECOFF, etc) have a concrete subclass of Writer.
+/// library files, and executable files. Each file format (e.g. mach-o, etc)
+/// has a concrete subclass of Writer.
class Writer {
public:
virtual ~Writer();
/// \brief Write a file from the supplied File object
- virtual std::error_code writeFile(const File &linkedFile, StringRef path) = 0;
+ virtual llvm::Error writeFile(const File &linkedFile, StringRef path) = 0;
/// \brief This method is called by Core Linking to give the Writer a chance
/// to add file format specific "files" to set of files to be linked. This is
@@ -41,9 +40,7 @@ protected:
Writer();
};
-std::unique_ptr<Writer> createWriterELF(const ELFLinkingContext &);
std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &);
-std::unique_ptr<Writer> createWriterPECOFF(const PECOFFLinkingContext &);
std::unique_ptr<Writer> createWriterYAML(const LinkingContext &);
} // end namespace lld
diff --git a/include/lld/Core/range.h b/include/lld/Core/range.h
deleted file mode 100644
index 614c9672955c..000000000000
--- a/include/lld/Core/range.h
+++ /dev/null
@@ -1,738 +0,0 @@
-//===-- lld/Core/range.h - Iterator ranges ----------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Iterator range type based on c++1y range proposal.
-///
-/// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_RANGE_H
-#define LLD_CORE_RANGE_H
-
-#include "llvm/Support/Compiler.h"
-#include <array>
-#include <cassert>
-#include <iterator>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-namespace lld {
-// Nothing in this namespace is part of the exported interface.
-namespace detail {
-using std::begin;
-using std::end;
-/// Used as the result type of undefined functions.
-struct undefined {};
-
-template <typename R> class begin_result {
- template <typename T> static auto check(T &&t) -> decltype(begin(t));
- static undefined check(...);
-public:
- typedef decltype(check(std::declval<R>())) type;
-};
-
-template <typename R> class end_result {
- template <typename T> static auto check(T &&t) -> decltype(end(t));
- static undefined check(...);
-public:
- typedef decltype(check(std::declval<R>())) type;
-};
-
-// Things that begin and end work on, in compatible ways, are
-// ranges. [stmt.ranged]
-template <typename R>
-struct is_range : std::is_same<typename detail::begin_result<R>::type,
- typename detail::end_result<R>::type> {};
-
-// This currently requires specialization and doesn't work for
-// detecting \c range<>s or iterators. We should add
-// \c contiguous_iterator_tag to fix that.
-template <typename R> struct is_contiguous_range : std::false_type {};
-template <typename R>
-struct is_contiguous_range<R &> : is_contiguous_range<R> {};
-template <typename R>
-struct is_contiguous_range <R &&> : is_contiguous_range<R> {};
-template <typename R>
-struct is_contiguous_range<const R> : is_contiguous_range<R> {};
-
-template <typename T, size_t N>
-struct is_contiguous_range<T[N]> : std::true_type {};
-template <typename T, size_t N>
-struct is_contiguous_range<const T[N]> : std::true_type {};
-template <typename T, size_t N>
-struct is_contiguous_range<std::array<T, N> > : std::true_type {};
-template <typename charT, typename traits, typename Allocator>
-struct is_contiguous_range<
- std::basic_string<charT, traits, Allocator> > : std::true_type {};
-template <typename T, typename Allocator>
-struct is_contiguous_range<std::vector<T, Allocator> > : std::true_type {};
-
-// Removes cv qualifiers from all levels of a multi-level pointer
-// type, not just the type level.
-template <typename T> struct remove_all_cv_ptr {
- typedef T type;
-};
-template <typename T> struct remove_all_cv_ptr<T *> {
- typedef typename remove_all_cv_ptr<T>::type *type;
-};
-template <typename T> struct remove_all_cv_ptr<const T> {
- typedef typename remove_all_cv_ptr<T>::type type;
-};
-template <typename T> struct remove_all_cv_ptr<volatile T> {
- typedef typename remove_all_cv_ptr<T>::type type;
-};
-template <typename T> struct remove_all_cv_ptr<const volatile T> {
- typedef typename remove_all_cv_ptr<T>::type type;
-};
-
-template <typename From, typename To>
-struct conversion_preserves_array_indexing : std::false_type {};
-
-template <typename FromVal, typename ToVal>
-struct conversion_preserves_array_indexing<FromVal *,
- ToVal *> : std::integral_constant<
- bool, std::is_convertible<FromVal *, ToVal *>::value &&
- std::is_same<typename remove_all_cv_ptr<FromVal>::type,
- typename remove_all_cv_ptr<ToVal>::type>::value> {};
-
-template <typename T>
-LLVM_CONSTEXPR auto adl_begin(T &&t) -> decltype(begin(t)) {
- return begin(std::forward<T>(t));
-}
-
-template <typename T> LLVM_CONSTEXPR auto adl_end(T &&t) -> decltype(end(t)) {
- return end(std::forward<T>(t));
-}
-} // end namespace detail
-
-/// A \c std::range<Iterator> represents a half-open iterator range
-/// built from two iterators, \c 'begin', and \c 'end'. If \c end is
-/// not reachable from \c begin, the behavior is undefined.
-///
-/// The mutability of elements of the range is controlled by the
-/// Iterator argument. Instantiate
-/// <code>range<<var>Foo</var>::iterator></code> or
-/// <code>range<<var>T</var>*></code>, or call
-/// <code>make_range(<var>non_const_container</var>)</code>, and you
-/// get a mutable range. Instantiate
-/// <code>range<<var>Foo</var>::const_iterator></code> or
-/// <code>range<const <var>T</var>*></code>, or call
-/// <code>make_range(<var>const_container</var>)</code>, and you get a
-/// constant range.
-///
-/// \todo Inherit from std::pair<Iterator, Iterator>?
-///
-/// \todo This interface contains some functions that could be
-/// provided as free algorithms rather than member functions, and all
-/// of the <code>pop_*()</code> functions could be replaced by \c
-/// slice() at the cost of some extra iterator copies. This makes
-/// them more awkward to use, but makes it easier for users to write
-/// their own types that follow the same interface. On the other hand,
-/// a \c range_facade could be provided to help users write new
-/// ranges, and it could provide the members. Such functions are
-/// marked with a note in their documentation. (Of course, all of
-/// these member functions could be provided as free functions using
-/// the iterator access methods, but one goal here is to allow people
-/// to program without touching iterators at all.)
-template <typename Iterator> class range {
- Iterator begin_, end_;
-public:
- /// \name types
- /// @{
-
- /// The iterator category of \c Iterator.
- /// \todo Consider defining range categories. If they don't add
- /// anything over the corresponding iterator categories, then
- /// they're probably not worth defining.
- typedef typename std::iterator_traits<
- Iterator>::iterator_category iterator_category;
- /// The type of elements of the range. Not cv-qualified.
- typedef typename std::iterator_traits<Iterator>::value_type value_type;
- /// The type of the size of the range and offsets within the range.
- typedef typename std::iterator_traits<
- Iterator>::difference_type difference_type;
- /// The return type of element access methods: \c front(), \c back(), etc.
- typedef typename std::iterator_traits<Iterator>::reference reference;
- typedef typename std::iterator_traits<Iterator>::pointer pointer;
- /// @}
-
- /// \name constructors
- /// @{
-
- /// Creates a range of default-constructed (<em>not</em>
- /// value-initialized) iterators. For most \c Iterator types, this
- /// will be an invalid range.
- range() : begin_(), end_() {}
-
- /// \pre \c end is reachable from \c begin.
- /// \post <code>this->begin() == begin && this->end() == end</code>
- LLVM_CONSTEXPR range(Iterator begin, Iterator end)
- : begin_(begin), end_(end) {}
-
- /// \par Participates in overload resolution if:
- /// - \c Iterator is not a pointer type,
- /// - \c begin(r) and \c end(r) return the same type, and
- /// - that type is convertible to \c Iterator.
- ///
- /// \todo std::begin and std::end are overloaded between T& and
- /// const T&, which means that if a container has only a non-const
- /// begin or end method, then it's ill-formed to pass an rvalue to
- /// the free function. To avoid that problem, we don't use
- /// std::forward<> here, so begin() and end() are always called with
- /// an lvalue. Another option would be to insist that rvalue
- /// arguments to range() must have const begin() and end() methods.
- template <typename R> LLVM_CONSTEXPR range(
- R &&r,
- typename std::enable_if<
- !std::is_pointer<Iterator>::value &&
- detail::is_range<R>::value &&
- std::is_convertible<typename detail::begin_result<R>::type,
- Iterator>::value>::type* = 0)
- : begin_(detail::adl_begin(r)), end_(detail::adl_end(r)) {}
-
- /// This constructor creates a \c range<T*> from any range with
- /// contiguous iterators. Because dereferencing a past-the-end
- /// iterator can be undefined behavior, empty ranges get initialized
- /// with \c nullptr rather than \c &*begin().
- ///
- /// \par Participates in overload resolution if:
- /// - \c Iterator is a pointer type \c T*,
- /// - \c begin(r) and \c end(r) return the same type,
- /// - elements \c i of that type satisfy the invariant
- /// <code>&*(i + N) == (&*i) + N</code>, and
- /// - The result of <code>&*begin()</code> is convertible to \c T*
- /// using only qualification conversions [conv.qual] (since
- /// pointer conversions stop the pointer from pointing to an
- /// array element).
- ///
- /// \todo The <code>&*(i + N) == (&*i) + N</code> invariant is
- /// currently impossible to check for user-defined types. We need a
- /// \c contiguous_iterator_tag to let users assert it.
- template <typename R> LLVM_CONSTEXPR range(
- R &&r,
- typename std::enable_if<
- std::is_pointer<Iterator>::value &&
- detail::is_contiguous_range<R>::value
- // MSVC returns false for this in this context, but not if we lift it out of the
- // constructor.
-#ifndef _MSC_VER
- && detail::conversion_preserves_array_indexing<
- decltype(&*detail::adl_begin(r)), Iterator>::value
-#endif
- >::type* = 0)
- : begin_((detail::adl_begin(r) == detail::adl_end(r) &&
- !std::is_pointer<decltype(detail::adl_begin(r))>::value)
- // For non-pointers, &*begin(r) is only defined behavior
- // if there's an element there. Otherwise, use nullptr
- // since the user can't dereference it anyway. This _is_
- // detectable.
- ? nullptr : &*detail::adl_begin(r)),
- end_(begin_ + (detail::adl_end(r) - detail::adl_begin(r))) {}
-
- /// @}
-
- /// \name iterator access
- /// @{
- LLVM_CONSTEXPR Iterator begin() const { return begin_; }
- LLVM_CONSTEXPR Iterator end() const { return end_; }
- /// @}
-
- /// \name element access
- /// @{
-
- /// \par Complexity:
- /// O(1)
- /// \pre \c !empty()
- /// \returns a reference to the element at the front of the range.
- LLVM_CONSTEXPR reference front() const { return *begin(); }
-
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to \c
- /// std::bidirectional_iterator_tag.
- ///
- /// \par Complexity:
- /// O(2) (Involves copying and decrementing an iterator, so not
- /// quite as cheap as \c front())
- ///
- /// \pre \c !empty()
- /// \returns a reference to the element at the front of the range.
- LLVM_CONSTEXPR reference back() const {
- static_assert(
- std::is_convertible<iterator_category,
- std::bidirectional_iterator_tag>::value,
- "Can only retrieve the last element of a bidirectional range.");
- using std::prev;
- return *prev(end());
- }
-
- /// This method is drawn from scripting language indexing. It
- /// indexes std::forward from the beginning of the range if the argument
- /// is positive, or backwards from the end of the array if the
- /// argument is negative.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1)
- ///
- /// \pre <code>abs(index) < size() || index == -size()</code>
- ///
- /// \returns if <code>index >= 0</code>, a reference to the
- /// <code>index</code>'th element in the range. Otherwise, a
- /// reference to the <code>size()+index</code>'th element.
- LLVM_CONSTEXPR reference operator[](difference_type index) const {
- static_assert(std::is_convertible<iterator_category,
- std::random_access_iterator_tag>::value,
- "Can only index into a random-access range.");
- // Less readable construction for constexpr support.
- return index < 0 ? end()[index]
- : begin()[index];
- }
- /// @}
-
- /// \name size
- /// @{
-
- /// \par Complexity:
- /// O(1)
- /// \returns \c true if the range contains no elements.
- LLVM_CONSTEXPR bool empty() const { return begin() == end(); }
-
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::forward_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag. O(<code>size()</code>)
- /// otherwise.
- ///
- /// \returns the number of times \c pop_front() can be called before
- /// \c empty() becomes true.
- LLVM_CONSTEXPR difference_type size() const {
- static_assert(std::is_convertible<iterator_category,
- std::forward_iterator_tag>::value,
- "Calling size on an input range would destroy the range.");
- return dispatch_size(iterator_category());
- }
- /// @}
-
- /// \name traversal from the beginning of the range
- /// @{
-
- /// Advances the beginning of the range by one element.
- /// \pre \c !empty()
- void pop_front() { ++begin_; }
-
- /// Advances the beginning of the range by \c n elements.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag, O(<code>n</code>) otherwise.
- ///
- /// \pre <code>n >= 0</code>, and there must be at least \c n
- /// elements in the range.
- void pop_front(difference_type n) { advance(begin_, n); }
-
- /// Advances the beginning of the range by at most \c n elements,
- /// stopping if the range becomes empty. A negative argument causes
- /// no change.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag, O(<code>min(n,
- /// <var>#-elements-in-range</var>)</code>) otherwise.
- ///
- /// \note Could be provided as a free function with little-to-no
- /// loss in efficiency.
- void pop_front_upto(difference_type n) {
- advance_upto(begin_, std::max<difference_type>(0, n), end_,
- iterator_category());
- }
-
- /// @}
-
- /// \name traversal from the end of the range
- /// @{
-
- /// Moves the end of the range earlier by one element.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::bidirectional_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1)
- ///
- /// \pre \c !empty()
- void pop_back() {
- static_assert(std::is_convertible<iterator_category,
- std::bidirectional_iterator_tag>::value,
- "Can only access the end of a bidirectional range.");
- --end_;
- }
-
- /// Moves the end of the range earlier by \c n elements.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::bidirectional_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag, O(<code>n</code>) otherwise.
- ///
- /// \pre <code>n >= 0</code>, and there must be at least \c n
- /// elements in the range.
- void pop_back(difference_type n) {
- static_assert(std::is_convertible<iterator_category,
- std::bidirectional_iterator_tag>::value,
- "Can only access the end of a bidirectional range.");
- advance(end_, -n);
- }
-
- /// Moves the end of the range earlier by <code>min(n,
- /// size())</code> elements. A negative argument causes no change.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::bidirectional_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag, O(<code>min(n,
- /// <var>#-elements-in-range</var>)</code>) otherwise.
- ///
- /// \note Could be provided as a free function with little-to-no
- /// loss in efficiency.
- void pop_back_upto(difference_type n) {
- static_assert(std::is_convertible<iterator_category,
- std::bidirectional_iterator_tag>::value,
- "Can only access the end of a bidirectional range.");
- advance_upto(end_, -std::max<difference_type>(0, n), begin_,
- iterator_category());
- }
-
- /// @}
-
- /// \name creating derived ranges
- /// @{
-
- /// Divides the range into two pieces at \c index, where a positive
- /// \c index represents an offset from the beginning of the range
- /// and a negative \c index represents an offset from the end.
- /// <code>range[index]</code> is the first element in the second
- /// piece. If <code>index >= size()</code>, the second piece
- /// will be empty. If <code>index < -size()</code>, the first
- /// piece will be empty.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::forward_iterator_tag.
- ///
- /// \par Complexity:
- /// - If \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag: O(1)
- /// - Otherwise, if \c iterator_category is convertible to \c
- /// std::bidirectional_iterator_tag, \c abs(index) iterator increments
- /// or decrements
- /// - Otherwise, if <code>index >= 0</code>, \c index iterator
- /// increments
- /// - Otherwise, <code>size() + (size() + index)</code>
- /// iterator increments.
- ///
- /// \returns a pair of adjacent ranges.
- ///
- /// \post
- /// - <code>result.first.size() == min(index, this->size())</code>
- /// - <code>result.first.end() == result.second.begin()</code>
- /// - <code>result.first.size() + result.second.size()</code> <code>==
- /// this->size()</code>
- ///
- /// \todo split() could take an arbitrary number of indices and
- /// return an <code>N+1</code>-element \c tuple<>. This is tricky to
- /// implement with negative indices in the optimal number of
- /// increments or decrements for a bidirectional iterator, but it
- /// should be possible. Do we want it?
- std::pair<range, range> split(difference_type index) const {
- static_assert(
- std::is_convertible<iterator_category,
- std::forward_iterator_tag>::value,
- "Calling split on a non-std::forward range would return a useless "
- "first result.");
- if (index >= 0) {
- range second = *this;
- second.pop_front_upto(index);
- return make_pair(range(begin(), second.begin()), second);
- } else {
- return dispatch_split_neg(index, iterator_category());
- }
- }
-
- /// \returns A sub-range from \c start to \c stop (not including \c
- /// stop, as usual). \c start and \c stop are interpreted as for
- /// <code>operator[]</code>, with negative values offsetting from
- /// the end of the range. Omitting the \c stop argument makes the
- /// sub-range continue to the end of the original range. Positive
- /// arguments saturate to the end of the range, and negative
- /// arguments saturate to the beginning. If \c stop is before \c
- /// start, returns an empty range beginning and ending at \c start.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::forward_iterator_tag.
- ///
- /// \par Complexity:
- /// - If \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag: O(1)
- /// - Otherwise, if \c iterator_category is convertible to \c
- /// std::bidirectional_iterator_tag, at most <code>min(abs(start),
- /// size()) + min(abs(stop), size())</code> iterator
- /// increments or decrements
- /// - Otherwise, if <code>start >= 0 && stop >= 0</code>,
- /// <code>max(start, stop)</code> iterator increments
- /// - Otherwise, <code>size() + max(start', stop')</code>
- /// iterator increments, where \c start' and \c stop' are the
- /// offsets of the elements \c start and \c stop refer to.
- ///
- /// \note \c slice(start) should be implemented with a different
- /// overload, rather than defaulting \c stop to
- /// <code>numeric_limits<difference_type>::max()</code>, because
- /// using a default would force non-random-access ranges to use an
- /// O(<code>size()</code>) algorithm to compute the end rather
- /// than the O(1) they're capable of.
- range slice(difference_type start, difference_type stop) const {
- static_assert(
- std::is_convertible<iterator_category,
- std::forward_iterator_tag>::value,
- "Calling slice on a non-std::forward range would destroy the original "
- "range.");
- return dispatch_slice(start, stop, iterator_category());
- }
-
- range slice(difference_type start) const {
- static_assert(
- std::is_convertible<iterator_category,
- std::forward_iterator_tag>::value,
- "Calling slice on a non-std::forward range would destroy the original "
- "range.");
- return split(start).second;
- }
-
- /// @}
-
-private:
- // advance_upto: should be added to <algorithm>, but I'll use it as
- // a helper function here.
- //
- // These return the number of increments that weren't applied
- // because we ran into 'limit' (or 0 if we didn't run into limit).
- static difference_type advance_upto(Iterator &it, difference_type n,
- Iterator limit, std::input_iterator_tag) {
- if (n < 0)
- return 0;
- while (it != limit && n > 0) {
- ++it;
- --n;
- }
- return n;
- }
-
- static difference_type advance_upto(Iterator &it, difference_type n,
- Iterator limit,
- std::bidirectional_iterator_tag) {
- if (n < 0) {
- while (it != limit && n < 0) {
- --it;
- ++n;
- }
- } else {
- while (it != limit && n > 0) {
- ++it;
- --n;
- }
- }
- return n;
- }
-
- static difference_type advance_upto(Iterator &it, difference_type n,
- Iterator limit,
- std::random_access_iterator_tag) {
- difference_type distance = limit - it;
- if (distance < 0)
- assert(n <= 0);
- else if (distance > 0)
- assert(n >= 0);
-
- if (abs(distance) > abs(n)) {
- it += n;
- return 0;
- } else {
- it = limit;
- return n - distance;
- }
- }
-
- // Dispatch functions.
- difference_type dispatch_size(std::forward_iterator_tag) const {
- return std::distance(begin(), end());
- }
-
- LLVM_CONSTEXPR difference_type dispatch_size(
- std::random_access_iterator_tag) const {
- return end() - begin();
- }
-
- std::pair<range, range> dispatch_split_neg(difference_type index,
- std::forward_iterator_tag) const {
- assert(index < 0);
- difference_type size = this->size();
- return split(std::max<difference_type>(0, size + index));
- }
-
- std::pair<range, range> dispatch_split_neg(
- difference_type index, std::bidirectional_iterator_tag) const {
- assert(index < 0);
- range first = *this;
- first.pop_back_upto(-index);
- return make_pair(first, range(first.end(), end()));
- }
-
- range dispatch_slice(difference_type start, difference_type stop,
- std::forward_iterator_tag) const {
- if (start < 0 || stop < 0) {
- difference_type size = this->size();
- if (start < 0)
- start = std::max<difference_type>(0, size + start);
- if (stop < 0)
- stop = size + stop; // Possibly negative; will be fixed in 2 lines.
- }
- stop = std::max<difference_type>(start, stop);
-
- Iterator first = begin();
- advance_upto(first, start, end(), iterator_category());
- Iterator last = first;
- advance_upto(last, stop - start, end(), iterator_category());
- return range(first, last);
- }
-
- range dispatch_slice(const difference_type start, const difference_type stop,
- std::bidirectional_iterator_tag) const {
- Iterator first;
- if (start < 0) {
- first = end();
- advance_upto(first, start, begin(), iterator_category());
- } else {
- first = begin();
- advance_upto(first, start, end(), iterator_category());
- }
- Iterator last;
- if (stop < 0) {
- last = end();
- advance_upto(last, stop, first, iterator_category());
- } else {
- if (start >= 0) {
- last = first;
- if (stop > start)
- advance_upto(last, stop - start, end(), iterator_category());
- } else {
- // Complicated: 'start' walked from the end of the sequence,
- // but 'stop' needs to walk from the beginning.
- Iterator dummy = begin();
- // Walk up to 'stop' increments from begin(), stopping when we
- // get to 'first', and capturing the remaining number of
- // increments.
- difference_type increments_past_start =
- advance_upto(dummy, stop, first, iterator_category());
- if (increments_past_start == 0) {
- // If this is 0, then stop was before start.
- last = first;
- } else {
- // Otherwise, count that many spaces beyond first.
- last = first;
- advance_upto(last, increments_past_start, end(), iterator_category());
- }
- }
- }
- return range(first, last);
- }
-
- range dispatch_slice(difference_type start, difference_type stop,
- std::random_access_iterator_tag) const {
- const difference_type size = this->size();
- if (start < 0)
- start = size + start;
- if (start < 0)
- start = 0;
- if (start > size)
- start = size;
-
- if (stop < 0)
- stop = size + stop;
- if (stop < start)
- stop = start;
- if (stop > size)
- stop = size;
-
- return range(begin() + start, begin() + stop);
- }
-};
-
-/// \name deducing constructor wrappers
-/// \relates std::range
-/// \xmlonly <nonmember/> \endxmlonly
-///
-/// These functions do the same thing as the constructor with the same
-/// signature. They just allow users to avoid writing the iterator
-/// type.
-/// @{
-
-/// \todo I'd like to define a \c make_range taking a single iterator
-/// argument representing the beginning of a range that ends with a
-/// default-constructed \c Iterator. This would help with using
-/// iterators like \c istream_iterator. However, using just \c
-/// make_range() could be confusing and lead to people writing
-/// incorrect ranges of more common iterators. Is there a better name?
-template <typename Iterator>
-LLVM_CONSTEXPR range<Iterator> make_range(Iterator begin, Iterator end) {
- return range<Iterator>(begin, end);
-}
-
-/// \par Participates in overload resolution if:
-/// \c begin(r) and \c end(r) return the same type.
-template <typename Range> LLVM_CONSTEXPR auto make_range(
- Range &&r,
- typename std::enable_if<detail::is_range<Range>::value>::type* = 0)
- -> range<decltype(detail::adl_begin(r))> {
- return range<decltype(detail::adl_begin(r))>(r);
-}
-
-/// \par Participates in overload resolution if:
-/// - \c begin(r) and \c end(r) return the same type,
-/// - that type satisfies the invariant that <code>&*(i + N) ==
-/// (&*i) + N</code>, and
-/// - \c &*begin(r) has a pointer type.
-template <typename Range> LLVM_CONSTEXPR auto make_ptr_range(
- Range &&r,
- typename std::enable_if<
- detail::is_contiguous_range<Range>::value &&
- std::is_pointer<decltype(&*detail::adl_begin(r))>::value>::type* = 0)
- -> range<decltype(&*detail::adl_begin(r))> {
- return range<decltype(&*detail::adl_begin(r))>(r);
-}
-/// @}
-} // end namespace lld
-
-#endif
diff --git a/include/lld/Driver/Driver.h b/include/lld/Driver/Driver.h
index 4bf0f43f8ce5..312f4f812b77 100644
--- a/include/lld/Driver/Driver.h
+++ b/include/lld/Driver/Driver.h
@@ -6,145 +6,27 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Interface for Drivers which convert command line arguments into
-/// LinkingContext objects, then perform the link.
-///
-//===----------------------------------------------------------------------===//
#ifndef LLD_DRIVER_DRIVER_H
#define LLD_DRIVER_DRIVER_H
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Node.h"
-#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/raw_ostream.h"
-#include <memory>
-#include <set>
-#include <vector>
namespace lld {
-class LinkingContext;
-class CoreLinkingContext;
-class MachOLinkingContext;
-class PECOFFLinkingContext;
-class ELFLinkingContext;
-
-typedef std::vector<std::unique_ptr<File>> FileVector;
-
-FileVector makeErrorFile(StringRef path, std::error_code ec);
-FileVector parseMemberFiles(std::unique_ptr<File> File);
-FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
-
-/// Base class for all Drivers.
-class Driver {
-protected:
-
- /// Performs link using specified options
- static bool link(LinkingContext &context,
- raw_ostream &diag = llvm::errs());
-
- /// Parses the LLVM options from the context.
- static void parseLLVMOptions(const LinkingContext &context);
-
-private:
- Driver() = delete;
-};
-
-/// Driver for "universal" lld tool which can mimic any linker command line
-/// parsing once it figures out which command line flavor to use.
-class UniversalDriver : public Driver {
-public:
- /// Determine flavor and pass control to Driver for that flavor.
- static bool link(llvm::MutableArrayRef<const char *> args,
- raw_ostream &diag = llvm::errs());
-
-private:
- UniversalDriver() = delete;
-};
-
-/// Driver for gnu/binutil 'ld' command line options.
-class GnuLdDriver : public Driver {
-public:
- /// Parses command line arguments same as gnu/binutils ld and performs link.
- /// Returns true iff an error occurred.
- static bool linkELF(llvm::ArrayRef<const char *> args,
- raw_ostream &diag = llvm::errs());
-
- /// Uses gnu/binutils style ld command line options to fill in options struct.
- /// Returns true iff there was an error.
- static bool parse(llvm::ArrayRef<const char *> args,
- std::unique_ptr<ELFLinkingContext> &context,
- raw_ostream &diag = llvm::errs());
-
- /// Parses a given memory buffer as a linker script and evaluate that.
- /// Public function for testing.
- static std::error_code evalLinkerScript(ELFLinkingContext &ctx,
- std::unique_ptr<MemoryBuffer> mb,
- raw_ostream &diag, bool nostdlib);
-
- /// A factory method to create an instance of ELFLinkingContext.
- static std::unique_ptr<ELFLinkingContext>
- createELFLinkingContext(llvm::Triple triple);
-
-private:
- static llvm::Triple getDefaultTarget(const char *progName);
- static bool applyEmulation(llvm::Triple &triple,
- llvm::opt::InputArgList &args,
- raw_ostream &diag);
- static void addPlatformSearchDirs(ELFLinkingContext &ctx,
- llvm::Triple &triple,
- llvm::Triple &baseTriple);
-
- GnuLdDriver() = delete;
-};
-
-/// Driver for darwin/ld64 'ld' command line options.
-class DarwinLdDriver : public Driver {
-public:
- /// Parses command line arguments same as darwin's ld and performs link.
- /// Returns true iff there was an error.
- static bool linkMachO(llvm::ArrayRef<const char *> args,
- raw_ostream &diag = llvm::errs());
-
- /// Uses darwin style ld command line options to update LinkingContext object.
- /// Returns true iff there was an error.
- static bool parse(llvm::ArrayRef<const char *> args,
- MachOLinkingContext &info,
- raw_ostream &diag = llvm::errs());
-
-private:
- DarwinLdDriver() = delete;
-};
-
-/// Driver for Windows 'link.exe' command line options
namespace coff {
-void link(llvm::ArrayRef<const char *> args);
+bool link(llvm::ArrayRef<const char *> Args);
}
-namespace elf2 {
-void link(llvm::ArrayRef<const char *> args);
+namespace elf {
+bool link(llvm::ArrayRef<const char *> Args,
+ llvm::raw_ostream &Diag = llvm::errs());
}
-/// Driver for lld unit tests
-class CoreDriver : public Driver {
-public:
- /// Parses command line arguments same as lld-core and performs link.
- /// Returns true iff there was an error.
- static bool link(llvm::ArrayRef<const char *> args,
- raw_ostream &diag = llvm::errs());
-
- /// Uses lld-core command line options to fill in options struct.
- /// Returns true iff there was an error.
- static bool parse(llvm::ArrayRef<const char *> args, CoreLinkingContext &info,
- raw_ostream &diag = llvm::errs());
-
-private:
- CoreDriver() = delete;
-};
-
-} // end namespace lld
+namespace mach_o {
+bool link(llvm::ArrayRef<const char *> Args,
+ llvm::raw_ostream &Diag = llvm::errs());
+}
+}
#endif
diff --git a/include/lld/ReaderWriter/AtomLayout.h b/include/lld/ReaderWriter/AtomLayout.h
deleted file mode 100644
index ad4cd0607b88..000000000000
--- a/include/lld/ReaderWriter/AtomLayout.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- include/lld/ReaderWriter/AtomLayout.h ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ATOM_LAYOUT_H
-#define LLD_READER_WRITER_ATOM_LAYOUT_H
-
-namespace lld {
-class Atom;
-
-/// AtomLayouts are used by a writer to manage physical positions of atoms.
-/// AtomLayout has two positions; one is file offset, and the other is the
-/// address when loaded into memory.
-///
-/// Construction of AtomLayouts is usually a multi-pass process. When an atom
-/// is appended to a section, we don't know the starting address of the
-/// section. Thus, we have no choice but to store the offset from the
-/// beginning of the section as AtomLayout values. After all sections starting
-/// address are fixed, AtomLayout is revisited to get the offsets updated by
-/// adding the starting addresses of the section.
-struct AtomLayout {
- AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr)
- : _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) {}
-
- AtomLayout() : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {}
-
- const Atom *_atom;
- uint64_t _fileOffset;
- uint64_t _virtualAddr;
-};
-
-}
-
-#endif
diff --git a/include/lld/ReaderWriter/CoreLinkingContext.h b/include/lld/ReaderWriter/CoreLinkingContext.h
deleted file mode 100644
index d597ca46ddc7..000000000000
--- a/include/lld/ReaderWriter/CoreLinkingContext.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- lld/ReaderWriter/CoreLinkingContext.h ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_CORE_LINKER_CONTEXT_H
-#define LLD_READER_WRITER_CORE_LINKER_CONTEXT_H
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/Support/ErrorHandling.h"
-
-namespace lld {
-
-class CoreLinkingContext : public LinkingContext {
-public:
- CoreLinkingContext();
-
- enum {
- TEST_RELOC_CALL32 = 1,
- TEST_RELOC_PCREL32 = 2,
- TEST_RELOC_GOT_LOAD32 = 3,
- TEST_RELOC_GOT_USE32 = 4,
- TEST_RELOC_LEA32_WAS_GOT = 5,
- };
-
- bool validateImpl(raw_ostream &diagnostics) override;
- void addPasses(PassManager &pm) override;
-
- void addPassNamed(StringRef name) { _passNames.push_back(name); }
-
-protected:
- Writer &writer() const override;
-
-private:
- std::unique_ptr<Writer> _writer;
- std::vector<StringRef> _passNames;
-};
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/ELFLinkingContext.h b/include/lld/ReaderWriter/ELFLinkingContext.h
deleted file mode 100644
index d1a5b28bb61f..000000000000
--- a/include/lld/ReaderWriter/ELFLinkingContext.h
+++ /dev/null
@@ -1,422 +0,0 @@
-//===- lld/ReaderWriter/ELFLinkingContext.h -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_LINKER_CONTEXT_H
-#define LLD_READER_WRITER_ELF_LINKER_CONTEXT_H
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/STDExtras.h"
-#include "lld/Core/range.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "lld/ReaderWriter/LinkerScript.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-#include <map>
-#include <memory>
-#include <set>
-
-namespace llvm {
-class FileOutputBuffer;
-}
-
-namespace lld {
-struct AtomLayout;
-class File;
-class Reference;
-
-namespace elf {
-using llvm::object::ELF32LE;
-using llvm::object::ELF32BE;
-using llvm::object::ELF64LE;
-using llvm::object::ELF64BE;
-
-class ELFWriter;
-
-std::unique_ptr<ELFLinkingContext> createAArch64LinkingContext(llvm::Triple);
-std::unique_ptr<ELFLinkingContext> createAMDGPULinkingContext(llvm::Triple);
-std::unique_ptr<ELFLinkingContext> createARMLinkingContext(llvm::Triple);
-std::unique_ptr<ELFLinkingContext> createExampleLinkingContext(llvm::Triple);
-std::unique_ptr<ELFLinkingContext> createHexagonLinkingContext(llvm::Triple);
-std::unique_ptr<ELFLinkingContext> createMipsLinkingContext(llvm::Triple);
-std::unique_ptr<ELFLinkingContext> createX86LinkingContext(llvm::Triple);
-std::unique_ptr<ELFLinkingContext> createX86_64LinkingContext(llvm::Triple);
-
-class TargetRelocationHandler {
-public:
- virtual ~TargetRelocationHandler() {}
-
- virtual std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const lld::AtomLayout &,
- const Reference &) const = 0;
-};
-
-} // namespace elf
-
-/// \brief TargetHandler contains all the information responsible to handle a
-/// a particular target on ELF. A target might wish to override implementation
-/// of creating atoms and how the atoms are written to the output file.
-class TargetHandler {
-public:
- virtual ~TargetHandler() {}
-
- /// Determines how relocations need to be applied.
- virtual const elf::TargetRelocationHandler &getRelocationHandler() const = 0;
-
- /// Returns a reader for object files.
- virtual std::unique_ptr<Reader> getObjReader() = 0;
-
- /// Returns a reader for .so files.
- virtual std::unique_ptr<Reader> getDSOReader() = 0;
-
- /// Returns a writer to write an ELF file.
- virtual std::unique_ptr<Writer> getWriter() = 0;
-};
-
-class ELFLinkingContext : public LinkingContext {
-public:
- /// \brief The type of ELF executable that the linker
- /// creates.
- enum class OutputMagic : uint8_t {
- // The default mode, no specific magic set
- DEFAULT,
- // Disallow shared libraries and don't align sections
- // PageAlign Data, Mark Text Segment/Data segment RW
- NMAGIC,
- // Disallow shared libraries and don't align sections,
- // Mark Text Segment/Data segment RW
- OMAGIC,
- };
-
- /// \brief ELF DT_FLAGS.
- enum DTFlag : uint32_t {
- DT_NOW = 1 << 1,
- DT_ORIGIN = 1 << 2,
- };
-
- llvm::Triple getTriple() const { return _triple; }
-
- uint64_t getPageSize() const { return _maxPageSize; }
- void setMaxPageSize(uint64_t v) { _maxPageSize = v; }
-
- OutputMagic getOutputMagic() const { return _outputMagic; }
- uint16_t getOutputELFType() const { return _outputELFType; }
- uint16_t getOutputMachine() const;
- bool mergeCommonStrings() const { return _mergeCommonStrings; }
- virtual int getMachineType() const = 0;
- virtual uint64_t getBaseAddress() const { return _baseAddress; }
- virtual void setBaseAddress(uint64_t address) { _baseAddress = address; }
-
- void notifySymbolTableCoalesce(const Atom *existingAtom, const Atom *newAtom,
- bool &useNew) override;
-
- /// This controls if undefined atoms need to be created for undefines that are
- /// present in a SharedLibrary. If this option is set, undefined atoms are
- /// created for every undefined symbol that are present in the dynamic table
- /// in the shared library
- bool useShlibUndefines() const { return _useShlibUndefines; }
-
- /// \brief Returns true if a given relocation should be added to the
- /// dynamic relocation table.
- ///
- /// This table is evaluated at loadtime by the dynamic loader and is
- /// referenced by the DT_RELA{,ENT,SZ} entries in the dynamic table.
- /// Relocations that return true will be added to the dynamic relocation
- /// table.
- virtual bool isDynamicRelocation(const Reference &) const { return false; }
-
- /// \brief Returns true if a given reference is a copy relocation.
- ///
- /// If this is a copy relocation, its target must be an ObjectAtom. We must
- /// include in DT_NEEDED the name of the library where this object came from.
- virtual bool isCopyRelocation(const Reference &) const { return false; }
-
- bool validateImpl(raw_ostream &diagnostics) override;
-
- /// \brief Returns true if the linker allows dynamic libraries to be
- /// linked with.
- ///
- /// This is true when the output mode of the executable is set to be
- /// having NMAGIC/OMAGIC
- bool allowLinkWithDynamicLibraries() const {
- if (_outputMagic == OutputMagic::NMAGIC ||
- _outputMagic == OutputMagic::OMAGIC || _noAllowDynamicLibraries)
- return false;
- return true;
- }
-
- /// \brief Use Elf_Rela format to output relocation tables.
- virtual bool isRelaOutputFormat() const { return true; }
-
- /// \brief Returns true if a given relocation should be added to PLT.
- ///
- /// This table holds all of the relocations used for delayed symbol binding.
- /// It will be evaluated at load time if LD_BIND_NOW is set. It is referenced
- /// by the DT_{JMPREL,PLTRELSZ} entries in the dynamic table.
- /// Relocations that return true will be added to the dynamic plt relocation
- /// table.
- virtual bool isPLTRelocation(const Reference &) const { return false; }
-
- /// \brief The path to the dynamic interpreter
- virtual StringRef getDefaultInterpreter() const {
- return "/lib64/ld-linux-x86-64.so.2";
- }
-
- /// \brief The dynamic linker path set by the --dynamic-linker option
- StringRef getInterpreter() const {
- if (_dynamicLinkerPath.hasValue())
- return _dynamicLinkerPath.getValue();
- return getDefaultInterpreter();
- }
-
- /// \brief Returns true if the output have dynamic sections.
- bool isDynamic() const;
-
- /// \brief Returns true if we are creating a shared library.
- bool isDynamicLibrary() const { return _outputELFType == llvm::ELF::ET_DYN; }
-
- /// \brief Returns true if a given relocation is a relative relocation.
- virtual bool isRelativeReloc(const Reference &r) const;
-
- TargetHandler &getTargetHandler() const {
- assert(_targetHandler && "Got null TargetHandler!");
- return *_targetHandler;
- }
-
- virtual void registerRelocationNames(Registry &) = 0;
-
- void addPasses(PassManager &pm) override;
-
- void setTriple(llvm::Triple trip) { _triple = trip; }
- void setNoInhibitExec(bool v) { _noInhibitExec = v; }
- void setExportDynamic(bool v) { _exportDynamic = v; }
- void setIsStaticExecutable(bool v) { _isStaticExecutable = v; }
- void setMergeCommonStrings(bool v) { _mergeCommonStrings = v; }
- void setUseShlibUndefines(bool use) { _useShlibUndefines = use; }
- void setOutputELFType(uint32_t type) { _outputELFType = type; }
-
- bool shouldExportDynamic() const { return _exportDynamic; }
-
- void createInternalFiles(std::vector<std::unique_ptr<File>> &) const override;
-
- void finalizeInputFiles() override;
-
- /// \brief Set the dynamic linker path
- void setInterpreter(StringRef s) { _dynamicLinkerPath = s; }
-
- /// \brief Set NMAGIC output kind when the linker specifies --nmagic
- /// or -n in the command line
- /// Set OMAGIC output kind when the linker specifies --omagic
- /// or -N in the command line
- void setOutputMagic(OutputMagic magic) { _outputMagic = magic; }
-
- /// \brief Disallow dynamic libraries during linking
- void setNoAllowDynamicLibraries() { _noAllowDynamicLibraries = true; }
-
- /// Searches directories for a match on the input File
- ErrorOr<StringRef> searchLibrary(StringRef libName) const;
-
- /// \brief Searches directories for a match on the input file.
- /// If \p fileName is an absolute path and \p isSysRooted is true, check
- /// the file under sysroot directory. If \p fileName is a relative path
- /// and is not in the current directory, search the file through library
- /// search directories.
- ErrorOr<StringRef> searchFile(StringRef fileName, bool isSysRooted) const;
-
- /// Get the entry symbol name
- StringRef entrySymbolName() const override;
-
- /// \brief Set new initializer function
- void setInitFunction(StringRef name) { _initFunction = name; }
-
- /// \brief Return an initializer function name.
- /// Either default "_init" or configured by the -init command line option.
- StringRef initFunction() const { return _initFunction; }
-
- /// \brief Set new finalizer function
- void setFiniFunction(StringRef name) { _finiFunction = name; }
-
- /// \brief Return a finalizer function name.
- /// Either default "_fini" or configured by the -fini command line option.
- StringRef finiFunction() const { return _finiFunction; }
-
- /// Add an absolute symbol. Used for --defsym.
- void addInitialAbsoluteSymbol(StringRef name, uint64_t addr) {
- _absoluteSymbols[name] = addr;
- }
-
- StringRef sharedObjectName() const { return _soname; }
- void setSharedObjectName(StringRef soname) { _soname = soname; }
-
- StringRef getSysroot() const { return _sysrootPath; }
- void setSysroot(StringRef path) { _sysrootPath = path; }
-
- void addRpath(StringRef path) { _rpathList.push_back(path); }
- range<const StringRef *> getRpathList() const { return _rpathList; }
-
- void addRpathLink(StringRef path) { _rpathLinkList.push_back(path); }
- range<const StringRef *> getRpathLinkList() const { return _rpathLinkList; }
-
- const std::map<std::string, uint64_t> &getAbsoluteSymbols() const {
- return _absoluteSymbols;
- }
-
- /// \brief Helper function to allocate strings.
- StringRef allocateString(StringRef ref) const {
- char *x = _allocator.Allocate<char>(ref.size() + 1);
- memcpy(x, ref.data(), ref.size());
- x[ref.size()] = '\0';
- return x;
- }
-
- // add search path to list.
- void addSearchPath(StringRef ref) { _inputSearchPaths.push_back(ref); }
-
- // Retrieve search path list.
- StringRefVector getSearchPaths() { return _inputSearchPaths; }
-
- // By default, the linker would merge sections that are read only with
- // segments that have read and execute permissions. When the user specifies a
- // flag --rosegment, a separate segment needs to be created.
- bool mergeRODataToTextSegment() const { return _mergeRODataToTextSegment; }
-
- void setCreateSeparateROSegment() { _mergeRODataToTextSegment = false; }
-
- bool isDynamicallyExportedSymbol(StringRef name) const {
- return _dynamicallyExportedSymbols.count(name) != 0;
- }
-
- /// \brief Demangle symbols.
- std::string demangle(StringRef symbolName) const override;
- bool demangleSymbols() const { return _demangle; }
- void setDemangleSymbols(bool d) { _demangle = d; }
-
- /// \brief Align segments.
- bool alignSegments() const { return _alignSegments; }
- void setAlignSegments(bool align) { _alignSegments = align; }
-
- /// \brief Enable new dtags.
- /// If this flag is set lld emits DT_RUNPATH instead of
- /// DT_RPATH. They are functionally equivalent except for
- /// the following two differences:
- /// - DT_RUNPATH is searched after LD_LIBRARY_PATH, while
- /// DT_RPATH is searched before.
- /// - DT_RUNPATH is used only to search for direct dependencies
- /// of the object it's contained in, while DT_RPATH is used
- /// for indirect dependencies as well.
- bool getEnableNewDtags() const { return _enableNewDtags; }
- void setEnableNewDtags(bool e) { _enableNewDtags = e; }
-
- /// \brief Discard local symbols.
- bool discardLocals() const { return _discardLocals; }
- void setDiscardLocals(bool d) { _discardLocals = d; }
-
- /// \brief Discard temprorary local symbols.
- bool discardTempLocals() const { return _discardTempLocals; }
- void setDiscardTempLocals(bool d) { _discardTempLocals = d; }
-
- /// \brief Strip symbols.
- bool stripSymbols() const { return _stripSymbols; }
- void setStripSymbols(bool strip) { _stripSymbols = strip; }
-
- /// \brief Collect statistics.
- bool collectStats() const { return _collectStats; }
- void setCollectStats(bool s) { _collectStats = s; }
-
- // --wrap option.
- void addWrapForSymbol(StringRef sym) { _wrapCalls.insert(sym); }
-
- // \brief Set DT_FLAGS flag.
- void setDTFlag(DTFlag f) { _dtFlags |= f; }
- bool getDTFlag(DTFlag f) { return (_dtFlags & f); }
-
- const llvm::StringSet<> &wrapCalls() const { return _wrapCalls; }
-
- void setUndefinesResolver(std::unique_ptr<File> resolver);
-
- script::Sema &linkerScriptSema() { return _linkerScriptSema; }
- const script::Sema &linkerScriptSema() const { return _linkerScriptSema; }
-
- /// Notify the ELFLinkingContext when the new ELF section is read.
- void notifyInputSectionName(StringRef name);
- /// Encountered C-ident input section names.
- const llvm::StringSet<> &cidentSectionNames() const {
- return _cidentSections;
- }
-
- // Set R_ARM_TARGET1 relocation behaviour
- bool armTarget1Rel() const { return _armTarget1Rel; }
- void setArmTarget1Rel(bool value) { _armTarget1Rel = value; }
-
- // Set R_MIPS_EH relocation behaviour.
- bool mipsPcRelEhRel() const { return _mipsPcRelEhRel; }
- void setMipsPcRelEhRel(bool value) { _mipsPcRelEhRel = value; }
-
-protected:
- ELFLinkingContext(llvm::Triple triple, std::unique_ptr<TargetHandler> handler)
- : _triple(triple), _targetHandler(std::move(handler)) {}
-
- Writer &writer() const override;
-
- /// Method to create a internal file for an undefined symbol
- std::unique_ptr<File> createUndefinedSymbolFile() const override;
-
- uint16_t _outputELFType = llvm::ELF::ET_EXEC;
- llvm::Triple _triple;
- std::unique_ptr<TargetHandler> _targetHandler;
- uint64_t _baseAddress = 0;
- bool _isStaticExecutable = false;
- bool _noInhibitExec = false;
- bool _exportDynamic = false;
- bool _mergeCommonStrings = false;
- bool _useShlibUndefines = true;
- bool _dynamicLinkerArg = false;
- bool _noAllowDynamicLibraries = false;
- bool _mergeRODataToTextSegment = true;
- bool _demangle = true;
- bool _discardTempLocals = false;
- bool _discardLocals = false;
- bool _stripSymbols = false;
- bool _alignSegments = true;
- bool _enableNewDtags = false;
- bool _collectStats = false;
- bool _armTarget1Rel = false;
- bool _mipsPcRelEhRel = false;
- uint64_t _maxPageSize = 0x1000;
- uint32_t _dtFlags = 0;
-
- OutputMagic _outputMagic = OutputMagic::DEFAULT;
- StringRefVector _inputSearchPaths;
- std::unique_ptr<Writer> _writer;
- llvm::Optional<StringRef> _dynamicLinkerPath;
- StringRef _initFunction = "_init";
- StringRef _finiFunction = "_fini";
- StringRef _sysrootPath = "";
- StringRef _soname;
- StringRefVector _rpathList;
- StringRefVector _rpathLinkList;
- llvm::StringSet<> _wrapCalls;
- std::map<std::string, uint64_t> _absoluteSymbols;
- llvm::StringSet<> _dynamicallyExportedSymbols;
- std::unique_ptr<File> _resolver;
- std::mutex _cidentMutex;
- llvm::StringSet<> _cidentSections;
-
- // The linker script semantic object, which owns all script ASTs, is stored
- // in the current linking context via _linkerScriptSema.
- script::Sema _linkerScriptSema;
-};
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/LinkerScript.h b/include/lld/ReaderWriter/LinkerScript.h
deleted file mode 100644
index 08ccb89ce8c1..000000000000
--- a/include/lld/ReaderWriter/LinkerScript.h
+++ /dev/null
@@ -1,1471 +0,0 @@
-//===- ReaderWriter/LinkerScript.h ----------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Linker script parser.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_LINKER_SCRIPT_H
-#define LLD_READER_WRITER_LINKER_SCRIPT_H
-
-#include "lld/Core/Error.h"
-#include "lld/Core/LLVM.h"
-#include "lld/Core/range.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-#include <system_error>
-#include <unordered_map>
-#include <vector>
-
-namespace lld {
-namespace script {
-class Token {
-public:
- enum Kind {
- unknown,
- eof,
- exclaim,
- exclaimequal,
- amp,
- ampequal,
- l_paren,
- r_paren,
- star,
- starequal,
- plus,
- plusequal,
- comma,
- minus,
- minusequal,
- slash,
- slashequal,
- number,
- colon,
- semicolon,
- less,
- lessequal,
- lessless,
- lesslessequal,
- equal,
- equalequal,
- greater,
- greaterequal,
- greatergreater,
- greatergreaterequal,
- question,
- identifier,
- libname,
- kw_align,
- kw_align_with_input,
- kw_as_needed,
- kw_at,
- kw_discard,
- kw_entry,
- kw_exclude_file,
- kw_extern,
- kw_filehdr,
- kw_fill,
- kw_flags,
- kw_group,
- kw_hidden,
- kw_input,
- kw_keep,
- kw_length,
- kw_memory,
- kw_origin,
- kw_phdrs,
- kw_provide,
- kw_provide_hidden,
- kw_only_if_ro,
- kw_only_if_rw,
- kw_output,
- kw_output_arch,
- kw_output_format,
- kw_overlay,
- kw_search_dir,
- kw_sections,
- kw_sort_by_alignment,
- kw_sort_by_init_priority,
- kw_sort_by_name,
- kw_sort_none,
- kw_subalign,
- l_brace,
- pipe,
- pipeequal,
- r_brace,
- tilde
- };
-
- Token() : _kind(unknown) {}
- Token(StringRef range, Kind kind) : _range(range), _kind(kind) {}
-
- void dump(raw_ostream &os) const;
-
- StringRef _range;
- Kind _kind;
-};
-
-class Lexer {
-public:
- explicit Lexer(std::unique_ptr<MemoryBuffer> mb) : _buffer(mb->getBuffer()) {
- _sourceManager.AddNewSourceBuffer(std::move(mb), llvm::SMLoc());
- }
-
- void lex(Token &tok);
-
- const llvm::SourceMgr &getSourceMgr() const { return _sourceManager; }
-
-private:
- bool canStartNumber(char c) const;
- bool canContinueNumber(char c) const;
- bool canStartName(char c) const;
- bool canContinueName(char c) const;
- void skipWhitespace();
-
- Token _current;
- /// \brief The current buffer state.
- StringRef _buffer;
- // Lexer owns the input files.
- llvm::SourceMgr _sourceManager;
-};
-
-/// All linker scripts commands derive from this class. High-level, sections and
-/// output section commands are all subclasses of this class.
-/// Examples:
-///
-/// OUTPUT_FORMAT("elf64-x86-64") /* A linker script command */
-/// OUTPUT_ARCH(i386:x86-64) /* Another command */
-/// ENTRY(_start) /* Another command */
-///
-/// SECTIONS /* Another command */
-/// {
-/// .interp : { /* A sections-command */
-/// *(.interp) /* An output-section-command */
-/// }
-/// }
-///
-class Command {
-public:
- enum class Kind {
- Entry,
- Extern,
- Fill,
- Group,
- Input,
- InputSectionsCmd,
- InputSectionName,
- Memory,
- Output,
- OutputArch,
- OutputFormat,
- OutputSectionDescription,
- Overlay,
- PHDRS,
- SearchDir,
- Sections,
- SortedGroup,
- SymbolAssignment,
- };
-
- Kind getKind() const { return _kind; }
- inline llvm::BumpPtrAllocator &getAllocator() const;
-
- virtual void dump(raw_ostream &os) const = 0;
-
- virtual ~Command() {}
-
-protected:
- Command(class Parser &ctx, Kind k) : _ctx(ctx), _kind(k) {}
-
-private:
- Parser &_ctx;
- Kind _kind;
-};
-
-template <class T>
-ArrayRef<T> save_array(llvm::BumpPtrAllocator &alloc, ArrayRef<T> array) {
- size_t num = array.size();
- T *start = alloc.Allocate<T>(num);
- std::uninitialized_copy(std::begin(array), std::end(array), start);
- return llvm::makeArrayRef(start, num);
-}
-
-class Output : public Command {
-public:
- Output(Parser &ctx, StringRef outputFileName)
- : Command(ctx, Kind::Output), _outputFileName(outputFileName) {}
-
- static bool classof(const Command *c) { return c->getKind() == Kind::Output; }
-
- void dump(raw_ostream &os) const override {
- os << "OUTPUT(" << _outputFileName << ")\n";
- }
-
- StringRef getOutputFileName() const { return _outputFileName; }
-
-private:
- StringRef _outputFileName;
-};
-
-class OutputFormat : public Command {
-public:
- OutputFormat(Parser &ctx, const SmallVectorImpl<StringRef> &formats)
- : Command(ctx, Kind::OutputFormat) {
- _formats = save_array<StringRef>(getAllocator(), formats);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::OutputFormat;
- }
-
- void dump(raw_ostream &os) const override {
- os << "OUTPUT_FORMAT(";
- bool first = true;
- for (StringRef format : _formats) {
- if (!first)
- os << ",";
- first = false;
- os << "\"" << format << "\"";
- }
- os << ")\n";
- }
-
- llvm::ArrayRef<StringRef> getFormats() { return _formats; }
-
-private:
- llvm::ArrayRef<StringRef> _formats;
-};
-
-class OutputArch : public Command {
-public:
- OutputArch(Parser &ctx, StringRef arch)
- : Command(ctx, Kind::OutputArch), _arch(arch) {}
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::OutputArch;
- }
-
- void dump(raw_ostream &os) const override {
- os << "OUTPUT_ARCH(" << getArch() << ")\n";
- }
-
- StringRef getArch() const { return _arch; }
-
-private:
- StringRef _arch;
-};
-
-struct Path {
- StringRef _path;
- bool _asNeeded;
- bool _isDashlPrefix;
-
- Path() : _asNeeded(false), _isDashlPrefix(false) {}
- Path(StringRef path, bool asNeeded = false, bool isLib = false)
- : _path(path), _asNeeded(asNeeded), _isDashlPrefix(isLib) {}
-};
-
-template<Command::Kind K>
-class PathList : public Command {
-public:
- PathList(Parser &ctx, StringRef name, const SmallVectorImpl<Path> &paths)
- : Command(ctx, K), _name(name) {
- _paths = save_array<Path>(getAllocator(), paths);
- }
-
- static bool classof(const Command *c) { return c->getKind() == K; }
-
- void dump(raw_ostream &os) const override {
- os << _name << "(";
- bool first = true;
- for (const Path &path : getPaths()) {
- if (!first)
- os << " ";
- first = false;
- if (path._asNeeded)
- os << "AS_NEEDED(";
- if (path._isDashlPrefix)
- os << "-l";
- os << path._path;
- if (path._asNeeded)
- os << ")";
- }
- os << ")\n";
- }
-
- llvm::ArrayRef<Path> getPaths() const { return _paths; }
-
-private:
- StringRef _name;
- llvm::ArrayRef<Path> _paths;
-};
-
-class Group : public PathList<Command::Kind::Group> {
-public:
- template <class RangeT>
- Group(Parser &ctx, RangeT range)
- : PathList(ctx, "GROUP", std::move(range)) {}
-};
-
-class Input : public PathList<Command::Kind::Input> {
-public:
- template <class RangeT>
- Input(Parser &ctx, RangeT range)
- : PathList(ctx, "INPUT", std::move(range)) {}
-};
-
-class Entry : public Command {
-public:
- Entry(Parser &ctx, StringRef entryName)
- : Command(ctx, Kind::Entry), _entryName(entryName) {}
-
- static bool classof(const Command *c) { return c->getKind() == Kind::Entry; }
-
- void dump(raw_ostream &os) const override {
- os << "ENTRY(" << _entryName << ")\n";
- }
-
- StringRef getEntryName() const { return _entryName; }
-
-private:
- StringRef _entryName;
-};
-
-class SearchDir : public Command {
-public:
- SearchDir(Parser &ctx, StringRef searchPath)
- : Command(ctx, Kind::SearchDir), _searchPath(searchPath) {}
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::SearchDir;
- }
-
- void dump(raw_ostream &os) const override {
- os << "SEARCH_DIR(\"" << _searchPath << "\")\n";
- }
-
- StringRef getSearchPath() const { return _searchPath; }
-
-private:
- StringRef _searchPath;
-};
-
-/// Superclass for expression nodes. Linker scripts accept C-like expressions in
-/// many places, such as when defining the value of a symbol or the address of
-/// an output section.
-/// Example:
-///
-/// SECTIONS {
-/// my_symbol = 1 + 1 * 2;
-/// | | ^~~~> Constant : Expression
-/// | | ^~~~> Constant : Expression
-/// | | ^~~~> BinOp : Expression
-/// ^~~~> Constant : Expression
-/// ^~~~> BinOp : Expression (the top-level Expression node)
-/// }
-///
-class Expression {
-public:
- // The symbol table does not need to own its string keys and the use of StringMap
- // here is an overkill.
- typedef llvm::StringMap<int64_t, llvm::BumpPtrAllocator> SymbolTableTy;
-
- enum class Kind { Constant, Symbol, FunctionCall, Unary, BinOp,
- TernaryConditional };
- Kind getKind() const { return _kind; }
- inline llvm::BumpPtrAllocator &getAllocator() const;
- virtual void dump(raw_ostream &os) const = 0;
- virtual ErrorOr<int64_t>
- evalExpr(const SymbolTableTy &symbolTable = SymbolTableTy()) const = 0;
- virtual ~Expression() {}
-
-protected:
- Expression(class Parser &ctx, Kind k) : _ctx(ctx), _kind(k) {}
-
-private:
- Parser &_ctx;
- Kind _kind;
-};
-
-/// A constant value is stored as unsigned because it represents absolute
-/// values. We represent negative numbers by composing the unary '-' operator
-/// with a constant.
-class Constant : public Expression {
-public:
- Constant(Parser &ctx, uint64_t num)
- : Expression(ctx, Kind::Constant), _num(num) {}
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::Constant;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- uint64_t _num;
-};
-
-class Symbol : public Expression {
-public:
- Symbol(Parser &ctx, StringRef name)
- : Expression(ctx, Kind::Symbol), _name(name) {}
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::Symbol;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- StringRef _name;
-};
-
-class FunctionCall : public Expression {
-public:
- FunctionCall(Parser &ctx, StringRef name,
- const SmallVectorImpl<const Expression *> &args)
- : Expression(ctx, Kind::FunctionCall), _name(name) {
- _args = save_array<const Expression *>(getAllocator(), args);
- }
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::FunctionCall;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- StringRef _name;
- llvm::ArrayRef<const Expression *> _args;
-};
-
-class Unary : public Expression {
-public:
- enum Operation {
- Minus,
- Not
- };
-
- Unary(Parser &ctx, Operation op, const Expression *child)
- : Expression(ctx, Kind::Unary), _op(op), _child(child) {}
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::Unary;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- Operation _op;
- const Expression *_child;
-};
-
-class BinOp : public Expression {
-public:
- enum Operation {
- And,
- CompareDifferent,
- CompareEqual,
- CompareGreater,
- CompareGreaterEqual,
- CompareLess,
- CompareLessEqual,
- Div,
- Mul,
- Or,
- Shl,
- Shr,
- Sub,
- Sum
- };
-
- BinOp(Parser &ctx, const Expression *lhs, Operation op, const Expression *rhs)
- : Expression(ctx, Kind::BinOp), _op(op), _lhs(lhs), _rhs(rhs) {}
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::BinOp;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- Operation _op;
- const Expression *_lhs;
- const Expression *_rhs;
-};
-
-/// Operands of the ternary operator can be any expression, similar to the other
-/// operations, including another ternary operator. To disambiguate the parse
-/// tree, note that ternary conditionals have precedence 13 and, different from
-/// other operators, associates right-to-left. For example:
-///
-/// i = i > 3 ? i < 5 ? 1 : 2 : 0;
-///
-/// will have the following parse tree:
-///
-/// i = ((i > 3) ? ((i < 5) ? 1 : 2) : 0);
-///
-/// The '>' binds tigher because it has precedence 6. When faced with two "?"
-/// ternary operators back-to-back, the parser prioritized the rightmost one.
-///
-class TernaryConditional : public Expression {
-public:
- TernaryConditional(Parser &ctx, const Expression *conditional,
- const Expression *trueExpr, const Expression *falseExpr)
- : Expression(ctx, Kind::TernaryConditional), _conditional(conditional),
- _trueExpr(trueExpr), _falseExpr(falseExpr) {}
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::TernaryConditional;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- const Expression *_conditional;
- const Expression *_trueExpr;
- const Expression *_falseExpr;
-};
-
-/// Symbol assignments of the form "symbolname = <expression>" may occur either
-/// as sections-commands or as output-section-commands.
-/// Example:
-///
-/// SECTIONS {
-/// mysymbol = . /* SymbolAssignment as a sections-command */
-/// .data : {
-/// othersymbol = . /* SymbolAssignment as an output-section-command */
-/// }
-///}
-///
-class SymbolAssignment : public Command {
-public:
- enum AssignmentKind { Simple, Sum, Sub, Mul, Div, Shl, Shr, And, Or };
- enum AssignmentVisibility { Default, Hidden, Provide, ProvideHidden };
-
- SymbolAssignment(Parser &ctx, StringRef name, const Expression *expr,
- AssignmentKind kind, AssignmentVisibility visibility)
- : Command(ctx, Kind::SymbolAssignment), _expression(expr), _symbol(name),
- _assignmentKind(Simple), _assignmentVisibility(visibility) {}
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::SymbolAssignment;
- }
-
- void dump(raw_ostream &os) const override;
- const Expression *expr() const { return _expression; }
- StringRef symbol() const { return _symbol; }
- AssignmentKind assignmentKind() const { return _assignmentKind; }
- AssignmentVisibility assignmentVisibility() const {
- return _assignmentVisibility;
- }
-
-private:
- const Expression *_expression;
- StringRef _symbol;
- AssignmentKind _assignmentKind;
- AssignmentVisibility _assignmentVisibility;
-};
-
-/// Encodes how to sort file names or section names that are expanded from
-/// wildcard operators. This typically occurs in constructs such as
-/// SECTIONS { .data : SORT_BY_NAME(*)(*) }}, where the order of the expanded
-/// names is important to determine which sections go first.
-enum class WildcardSortMode {
- NA,
- ByAlignment,
- ByAlignmentAndName,
- ByInitPriority,
- ByName,
- ByNameAndAlignment,
- None
-};
-
-/// Represents either a single input section name or a group of sorted input
-/// section names. They specify which sections to map to a given output section.
-/// Example:
-///
-/// SECTIONS {
-/// .x: { *(.text) }
-/// /* ^~~~^ InputSectionName : InputSection */
-/// .y: { *(SORT(.text*)) }
-/// /* ^~~~~~~~~~~^ InputSectionSortedGroup : InputSection */
-/// }
-class InputSection : public Command {
-public:
- static bool classof(const Command *c) {
- return c->getKind() == Kind::InputSectionName ||
- c->getKind() == Kind::SortedGroup;
- }
-
-protected:
- InputSection(Parser &ctx, Kind k) : Command(ctx, k) {}
-};
-
-class InputSectionName : public InputSection {
-public:
- InputSectionName(Parser &ctx, StringRef name, bool excludeFile)
- : InputSection(ctx, Kind::InputSectionName), _name(name),
- _excludeFile(excludeFile) {}
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::InputSectionName;
- }
- bool hasExcludeFile() const { return _excludeFile; }
- StringRef name() const { return _name; }
-
-private:
- StringRef _name;
- bool _excludeFile;
-};
-
-class InputSectionSortedGroup : public InputSection {
-public:
- typedef llvm::ArrayRef<const InputSection *>::const_iterator const_iterator;
-
- InputSectionSortedGroup(Parser &ctx, WildcardSortMode sort,
- const SmallVectorImpl<const InputSection *> &sections)
- : InputSection(ctx, Kind::SortedGroup), _sortMode(sort) {
- _sections = save_array<const InputSection *>(getAllocator(), sections);
- }
-
- void dump(raw_ostream &os) const override;
- WildcardSortMode sortMode() const { return _sortMode; }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::SortedGroup;
- }
-
- const_iterator begin() const { return _sections.begin(); }
- const_iterator end() const { return _sections.end(); }
-
-private:
- WildcardSortMode _sortMode;
- llvm::ArrayRef<const InputSection *> _sections;
-};
-
-/// An output-section-command that maps a series of sections inside a given
-/// file-archive pair to an output section.
-/// Example:
-///
-/// SECTIONS {
-/// .x: { *(.text) }
-/// /* ^~~~~~~^ InputSectionsCmd */
-/// .y: { w:z(SORT(.text*)) }
-/// /* ^~~~~~~~~~~~~~~~^ InputSectionsCmd */
-/// }
-class InputSectionsCmd : public Command {
-public:
- typedef llvm::ArrayRef<const InputSection *>::const_iterator const_iterator;
- typedef std::vector<const InputSection *> VectorTy;
-
- InputSectionsCmd(Parser &ctx, StringRef memberName, StringRef archiveName,
- bool keep, WildcardSortMode fileSortMode,
- WildcardSortMode archiveSortMode,
- const SmallVectorImpl<const InputSection *> &sections)
- : Command(ctx, Kind::InputSectionsCmd), _memberName(memberName),
- _archiveName(archiveName), _keep(keep), _fileSortMode(fileSortMode),
- _archiveSortMode(archiveSortMode) {
- _sections = save_array<const InputSection *>(getAllocator(), sections);
- }
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::InputSectionsCmd;
- }
-
- StringRef memberName() const { return _memberName; }
- StringRef archiveName() const { return _archiveName; }
- const_iterator begin() const { return _sections.begin(); }
- const_iterator end() const { return _sections.end(); }
- WildcardSortMode archiveSortMode() const { return _archiveSortMode; }
- WildcardSortMode fileSortMode() const { return _fileSortMode; }
-
-private:
- StringRef _memberName;
- StringRef _archiveName;
- bool _keep;
- WildcardSortMode _fileSortMode;
- WildcardSortMode _archiveSortMode;
- llvm::ArrayRef<const InputSection *> _sections;
-};
-
-class FillCmd : public Command {
-public:
- FillCmd(Parser &ctx, ArrayRef<uint8_t> bytes) : Command(ctx, Kind::Fill) {
- _bytes = save_array<uint8_t>(getAllocator(), bytes);
- }
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Fill;
- }
-
- ArrayRef<uint8_t> bytes() { return _bytes; }
-
-private:
- ArrayRef<uint8_t> _bytes;
-};
-
-/// A sections-command to specify which input sections and symbols compose a
-/// given output section.
-/// Example:
-///
-/// SECTIONS {
-/// .x: { *(.text) ; symbol = .; }
-/// /*^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ OutputSectionDescription */
-/// .y: { w:z(SORT(.text*)) }
-/// /*^~~~~~~~~~~~~~~~~~~~~~~~^ OutputSectionDescription */
-/// .a 0x10000 : ONLY_IF_RW { *(.data*) ; *:libc.a(SORT(*)); }
-/// /*^~~~~~~~~~~~~ OutputSectionDescription ~~~~~~~~~~~~~~~~~^ */
-/// }
-class OutputSectionDescription : public Command {
-public:
- enum Constraint { C_None, C_OnlyIfRO, C_OnlyIfRW };
-
- typedef llvm::ArrayRef<const Command *>::const_iterator const_iterator;
-
- OutputSectionDescription(
- Parser &ctx, StringRef sectionName, const Expression *address,
- const Expression *align, const Expression *subAlign, const Expression *at,
- const Expression *fillExpr, StringRef fillStream, bool alignWithInput,
- bool discard, Constraint constraint,
- const SmallVectorImpl<const Command *> &outputSectionCommands,
- ArrayRef<StringRef> phdrs)
- : Command(ctx, Kind::OutputSectionDescription), _sectionName(sectionName),
- _address(address), _align(align), _subAlign(subAlign), _at(at),
- _fillExpr(fillExpr), _fillStream(fillStream),
- _alignWithInput(alignWithInput), _discard(discard),
- _constraint(constraint) {
- _outputSectionCommands =
- save_array<const Command *>(getAllocator(), outputSectionCommands);
- _phdrs = save_array<StringRef>(getAllocator(), phdrs);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::OutputSectionDescription;
- }
-
- void dump(raw_ostream &os) const override;
-
- const_iterator begin() const { return _outputSectionCommands.begin(); }
- const_iterator end() const { return _outputSectionCommands.end(); }
- StringRef name() const { return _sectionName; }
- bool isDiscarded() const { return _discard; }
- ArrayRef<StringRef> PHDRs() const { return _phdrs; }
-
-private:
- StringRef _sectionName;
- const Expression *_address;
- const Expression *_align;
- const Expression *_subAlign;
- const Expression *_at;
- const Expression *_fillExpr;
- StringRef _fillStream;
- bool _alignWithInput;
- bool _discard;
- Constraint _constraint;
- llvm::ArrayRef<const Command *> _outputSectionCommands;
- ArrayRef<StringRef> _phdrs;
-};
-
-/// Represents an Overlay structure as documented in
-/// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
-class Overlay : public Command {
-public:
- Overlay(Parser &ctx) : Command(ctx, Kind::Overlay) {}
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Overlay;
- }
-
- void dump(raw_ostream &os) const override { os << "Overlay description\n"; }
-};
-
-class PHDR {
-public:
- PHDR(StringRef name, uint64_t type, bool includeFileHdr, bool includePHDRs,
- const Expression *at, uint64_t flags)
- : _name(name), _type(type), _includeFileHdr(includeFileHdr),
- _includePHDRs(includePHDRs), _at(at), _flags(flags) {}
-
- StringRef name() const { return _name; }
- uint64_t type() const { return _type; }
- bool hasFileHdr() const { return _includeFileHdr; }
- bool hasPHDRs() const { return _includePHDRs; }
- uint64_t flags() const { return _flags; }
- bool isNone() const;
-
- void dump(raw_ostream &os) const;
-
-private:
- StringRef _name;
- uint64_t _type;
- bool _includeFileHdr;
- bool _includePHDRs;
- const Expression *_at;
- uint64_t _flags;
-};
-
-class PHDRS : public Command {
-public:
- typedef ArrayRef<const PHDR *>::const_iterator const_iterator;
-
- PHDRS(Parser &ctx, const SmallVectorImpl<const PHDR *> &phdrs)
- : Command(ctx, Kind::PHDRS) {
- _phdrs = save_array<const PHDR *>(getAllocator(), phdrs);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::PHDRS;
- }
-
- void dump(raw_ostream &os) const override;
- const_iterator begin() const { return _phdrs.begin(); }
- const_iterator end() const { return _phdrs.end(); }
-
-private:
- ArrayRef<const PHDR *> _phdrs;
-};
-
-/// Represents all the contents of the SECTIONS {} construct.
-class Sections : public Command {
-public:
- typedef llvm::ArrayRef<const Command *>::const_iterator const_iterator;
-
- Sections(Parser &ctx,
- const SmallVectorImpl<const Command *> &sectionsCommands)
- : Command(ctx, Kind::Sections) {
- _sectionsCommands =
- save_array<const Command *>(getAllocator(), sectionsCommands);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Sections;
- }
-
- void dump(raw_ostream &os) const override;
- const_iterator begin() const { return _sectionsCommands.begin(); }
- const_iterator end() const { return _sectionsCommands.end(); }
-
-private:
- llvm::ArrayRef<const Command *> _sectionsCommands;
-};
-
-/// Represents a single memory block definition in a MEMORY {} command.
-class MemoryBlock {
-public:
- MemoryBlock(StringRef name, StringRef attr,
- const Expression *origin, const Expression *length)
- : _name(name), _attr(attr), _origin(origin), _length(length) {}
-
- void dump(raw_ostream &os) const;
-
-private:
- StringRef _name;
- StringRef _attr;
- const Expression *_origin;
- const Expression *_length;
-};
-
-/// Represents all the contents of the MEMORY {} command.
-class Memory : public Command {
-public:
- Memory(Parser &ctx,
- const SmallVectorImpl<const MemoryBlock *> &blocks)
- : Command(ctx, Kind::Memory) {
- _blocks = save_array<const MemoryBlock *>(getAllocator(), blocks);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Memory;
- }
-
- void dump(raw_ostream &os) const override;
-
-private:
- llvm::ArrayRef<const MemoryBlock *> _blocks;
-};
-
-/// Represents an extern command.
-class Extern : public Command {
-public:
- typedef llvm::ArrayRef<StringRef>::const_iterator const_iterator;
-
- Extern(Parser &ctx,
- const SmallVectorImpl<StringRef> &symbols)
- : Command(ctx, Kind::Extern) {
- _symbols = save_array<StringRef>(getAllocator(), symbols);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Extern;
- }
-
- void dump(raw_ostream &os) const override;
- const_iterator begin() const { return _symbols.begin(); }
- const_iterator end() const { return _symbols.end(); }
-
-private:
- llvm::ArrayRef<StringRef> _symbols;
-};
-
-/// Stores the parse tree of a linker script.
-class LinkerScript {
-public:
- void dump(raw_ostream &os) const {
- for (const Command *c : _commands) {
- c->dump(os);
- if (isa<SymbolAssignment>(c))
- os << "\n";
- }
- }
-
- std::vector<const Command *> _commands;
-};
-
-/// Recognizes syntactic constructs of a linker script using a predictive
-/// parser/recursive descent implementation.
-///
-/// Based on the linker script documentation available at
-/// https://sourceware.org/binutils/docs/ld/Scripts.html
-class Parser {
-public:
- explicit Parser(std::unique_ptr<MemoryBuffer> mb)
- : _lex(std::move(mb)), _peekAvailable(false) {}
-
- /// Let's not allow copying of Parser class because it would be expensive
- /// to update all the AST pointers to a new buffer.
- Parser(const Parser &instance) = delete;
-
- /// Lex and parse the current memory buffer to create a linker script AST.
- std::error_code parse();
-
- /// Returns a reference to the top level node of the linker script AST.
- LinkerScript *get() { return &_script; }
-
- /// Returns a reference to the underlying allocator.
- llvm::BumpPtrAllocator &getAllocator() { return _alloc; }
-
-private:
- /// Advances to the next token, either asking the Lexer to lex the next token
- /// or obtaining it from the look ahead buffer.
- void consumeToken() {
- // First check if the look ahead buffer cached the next token
- if (_peekAvailable) {
- _tok = _bufferedToken;
- _peekAvailable = false;
- return;
- }
- _lex.lex(_tok);
- }
-
- /// Returns the token that succeeds the current one without consuming the
- /// current token. This operation will lex an additional token and store it in
- /// a private buffer.
- const Token &peek() {
- if (_peekAvailable)
- return _bufferedToken;
-
- _lex.lex(_bufferedToken);
- _peekAvailable = true;
- return _bufferedToken;
- }
-
- void error(const Token &tok, Twine msg) {
- _lex.getSourceMgr().PrintMessage(
- llvm::SMLoc::getFromPointer(tok._range.data()),
- llvm::SourceMgr::DK_Error, msg);
- }
-
- bool expectAndConsume(Token::Kind kind, Twine msg) {
- if (_tok._kind != kind) {
- error(_tok, msg);
- return false;
- }
- consumeToken();
- return true;
- }
-
- bool isNextToken(Token::Kind kind) { return (_tok._kind == kind); }
-
- // Recursive descent parsing member functions
- // All of these functions consumes tokens and return an AST object,
- // represented by the Command superclass. However, note that not all AST
- // objects derive from Command. For nodes of C-like expressions, used in
- // linker scripts, the superclass is Expression. For nodes that represent
- // input sections that map to an output section, the superclass is
- // InputSection.
- //
- // Example mapping common constructs to AST nodes:
- //
- // SECTIONS { /* Parsed to Sections class */
- // my_symbol = 1 + 1; /* Parsed to SymbolAssignment class */
- // /* ^~~> Parsed to Expression class */
- // .data : { *(.data) } /* Parsed to OutputSectionDescription class */
- // /* ^~~> Parsed to InputSectionName class */
- // /* ^~~~~> Parsed to InputSectionsCmd class */
- // }
-
- // ==== Expression parsing member functions ====
-
- /// Parse "identifier(param [, param]...)"
- ///
- /// Example:
- ///
- /// SECTIONS {
- /// my_symbol = 0x1000 | ALIGN(other_symbol);
- /// /* ^~~~> parseFunctionCall()
- /// }
- const Expression *parseFunctionCall();
-
- /// Ensures that the current token is an expression operand. If it is not,
- /// issues an error to the user and returns false.
- bool expectExprOperand();
-
- /// Parse operands of an expression, such as function calls, identifiers,
- /// literal numbers or unary operators.
- ///
- /// Example:
- ///
- /// SECTIONS {
- /// my_symbol = 0x1000 | ALIGN(other_symbol);
- /// ^~~~> parseExprTerminal()
- /// }
- const Expression *parseExprOperand();
-
- // As a reference to the precedence of C operators, consult
- // http://en.cppreference.com/w/c/language/operator_precedence
-
- /// Parse either a single expression operand and returns or parse an entire
- /// expression if its top-level node has a lower or equal precedence than the
- /// indicated.
- const Expression *parseExpression(unsigned precedence = 13);
-
- /// Parse an operator and its rhs operand, assuming that the lhs was already
- /// consumed. Keep parsing subsequent operator-operand pairs that do not
- /// exceed highestPrecedence.
- /// * lhs points to the left-hand-side operand of this operator
- /// * maxPrecedence has the maximum operator precedence level that this parse
- /// function is allowed to consume.
- const Expression *parseOperatorOperandLoop(const Expression *lhs,
- unsigned maxPrecedence);
-
- /// Parse ternary conditionals such as "(condition)? true: false;". This
- /// operator has precedence level 13 and associates right-to-left.
- const Expression *parseTernaryCondOp(const Expression *lhs);
-
- // ==== High-level commands parsing ====
-
- /// Parse the OUTPUT linker script command.
- /// Example:
- /// OUTPUT(/path/to/file)
- /// ^~~~> parseOutput()
- ///
- Output *parseOutput();
-
- /// Parse the OUTPUT_FORMAT linker script command.
- /// Example:
- ///
- /// OUTPUT_FORMAT(elf64-x86-64,elf64-x86-64,elf64-x86-64)
- /// ^~~~> parseOutputFormat()
- ///
- OutputFormat *parseOutputFormat();
-
- /// Parse the OUTPUT_ARCH linker script command.
- /// Example:
- ///
- /// OUTPUT_ARCH(i386:x86-64)
- /// ^~~~> parseOutputArch()
- ///
- OutputArch *parseOutputArch();
-
- /// Parse the INPUT or GROUP linker script command.
- /// Example:
- ///
- /// GROUP ( /lib/x86_64-linux-gnu/libc.so.6
- /// /usr/lib/x86_64-linux-gnu/libc_nonshared.a
- /// AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 )
- /// -lm -l:libgcc.a )
- ///
- template<class T> T *parsePathList();
- bool parseAsNeeded(SmallVectorImpl<Path> &paths);
-
- /// Parse the ENTRY linker script command.
- /// Example:
- ///
- /// ENTRY(init)
- /// ^~~~> parseEntry()
- ///
- Entry *parseEntry();
-
- /// Parse the SEARCH_DIR linker script command.
- /// Example:
- ///
- /// SEARCH_DIR("/usr/x86_64-linux-gnu/lib64");
- /// ^~~~> parseSearchDir()
- ///
- SearchDir *parseSearchDir();
-
- /// Parse "symbol = expression" commands that live inside the
- /// SECTIONS directive.
- /// Example:
- ///
- /// SECTIONS {
- /// my_symbol = 1 + 1;
- /// ^~~~> parseExpression()
- /// ^~~~ parseSymbolAssignment()
- /// }
- ///
- const SymbolAssignment *parseSymbolAssignment();
-
- /// Parse "EXCLUDE_FILE" used inside the listing of input section names.
- /// Example:
- ///
- /// SECTIONS {
- /// .data : { *(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors) }
- /// ^~~~> parseExcludeFile()
- /// }
- ///
- ErrorOr<InputSectionsCmd::VectorTy> parseExcludeFile();
-
- /// Helper to parse SORT_BY_NAME(, SORT_BY_ALIGNMENT( and SORT_NONE(,
- /// possibly nested. Returns the number of Token::r_paren tokens that need
- /// to be consumed, while sortMode is updated with the parsed sort
- /// criteria.
- /// Example:
- ///
- /// SORT_BY_NAME(SORT_BY_ALIGNMENT(*))
- /// ^~~~ parseSortDirectives() ~~^
- /// Returns 2, finishes with sortMode = WildcardSortMode::ByNameAndAlignment
- ///
- int parseSortDirectives(WildcardSortMode &sortMode);
-
- /// Parse a group of input section names that are sorted via SORT* directives.
- /// Example:
- /// SORT_BY_NAME(SORT_BY_ALIGNMENT(*data *bss))
- const InputSection *parseSortedInputSections();
-
- /// Parse input section description statements.
- /// Example:
- ///
- /// SECTIONS {
- /// .mysection : crt.o(.data* .bss SORT_BY_NAME(name*))
- /// ^~~~ parseInputSectionsCmd()
- /// }
- const InputSectionsCmd *parseInputSectionsCmd();
-
- const FillCmd *parseFillCmd();
-
- /// Parse output section description statements.
- /// Example:
- ///
- /// SECTIONS {
- /// .data : { crt.o(.data* .bss SORT_BY_NAME(name*)) }
- /// ^~~~ parseOutputSectionDescription()
- /// }
- const OutputSectionDescription *parseOutputSectionDescription();
-
- /// Stub for parsing overlay commands. Currently unimplemented.
- const Overlay *parseOverlay();
-
- const PHDR *parsePHDR();
-
- PHDRS *parsePHDRS();
-
- /// Parse the SECTIONS linker script command.
- /// Example:
- ///
- /// SECTIONS {
- /// ^~~~ parseSections()
- /// . = 0x100000;
- /// .data : { *(.data) }
- /// }
- ///
- Sections *parseSections();
-
- /// Parse the MEMORY linker script command.
- /// Example:
- ///
- /// MEMORY {
- /// ^~~~ parseMemory()
- /// ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
- /// rom (rx) : ORIGIN = 0x0, LENGTH = 256K
- /// }
- ///
- Memory *parseMemory();
-
- /// Parse the EXTERN linker script command.
- /// Example:
- ///
- /// EXTERN(symbol symbol ...)
- /// ^~~~> parseExtern()
- ///
- Extern *parseExtern();
-
-private:
- // Owns the entire linker script AST nodes
- llvm::BumpPtrAllocator _alloc;
-
- // The top-level/entry-point linker script AST node
- LinkerScript _script;
-
- Lexer _lex;
-
- // Current token being analyzed
- Token _tok;
-
- // Annotate whether we buffered the next token to allow peeking
- bool _peekAvailable;
- Token _bufferedToken;
-};
-
-/// script::Sema traverses all parsed linker script structures and populate
-/// internal data structures to be able to answer the following questions:
-///
-/// * According to the linker script, which input section goes first in the
-/// output file layout, input section A or input section B?
-///
-/// * What is the name of the output section that input section A should be
-/// mapped to?
-///
-/// * Which linker script expressions should be calculated before emitting
-/// a given section?
-///
-/// * How to evaluate a given linker script expression?
-///
-class Sema {
-public:
- /// From the linker script point of view, this class represents the minimum
- /// set of information to uniquely identify an input section.
- struct SectionKey {
- StringRef archivePath;
- StringRef memberPath;
- StringRef sectionName;
- };
-
- Sema();
-
- /// We can parse several linker scripts via command line whose ASTs are stored
- /// here via addLinkerScript().
- void addLinkerScript(std::unique_ptr<Parser> script) {
- _scripts.push_back(std::move(script));
- }
-
- const std::vector<std::unique_ptr<Parser>> &getLinkerScripts() {
- return _scripts;
- }
-
- /// Prepare our data structures according to the linker scripts currently in
- /// our control (control given via addLinkerScript()). Called once all linker
- /// scripts have been parsed.
- std::error_code perform();
-
- /// Answer if we have layout commands (section mapping rules). If we don't,
- /// the output file writer can assume there is no linker script special rule
- /// to handle.
- bool hasLayoutCommands() const { return _layoutCommands.size() > 0; }
-
- /// Return true if this section has a mapping rule in the linker script
- bool hasMapping(const SectionKey &key) const {
- return getLayoutOrder(key, true) >= 0;
- }
-
- /// Order function - used to sort input sections in the output file according
- /// to linker script custom mappings. Return true if lhs should appear before
- /// rhs.
- bool less(const SectionKey &lhs, const SectionKey &rhs) const;
-
- /// Retrieve the name of the output section that this input section is mapped
- /// to, according to custom linker script mappings.
- StringRef getOutputSection(const SectionKey &key) const;
-
- /// Retrieve all the linker script expressions that need to be evaluated
- /// before the given section is emitted. This is *not* const because the
- /// first section to retrieve a given set of expression is the only one to
- /// receive it. This set is marked as "delivered" and no other sections can
- /// retrieve this set again. If we don't do this, multiple sections may map
- /// to the same set of expressions because of wildcards rules.
- std::vector<const SymbolAssignment *> getExprs(const SectionKey &key);
-
- /// Evaluate a single linker script expression according to our current
- /// context (symbol table). This function is *not* constant because it can
- /// update our symbol table with new symbols calculated in this expression.
- std::error_code evalExpr(const SymbolAssignment *assgn, uint64_t &curPos);
-
- /// Retrieve the set of symbols defined in linker script expressions.
- const llvm::StringSet<> &getScriptDefinedSymbols() const;
-
- /// Queries the linker script symbol table for the value of a given symbol.
- /// This function must be called after linker script expressions evaluation
- /// has been performed (by calling evalExpr() for all expressions).
- uint64_t getLinkerScriptExprValue(StringRef name) const;
-
- /// Check if there are custom headers available.
- bool hasPHDRs() const;
-
- /// Retrieve all the headers the given output section is assigned to.
- std::vector<const PHDR *> getPHDRsForOutputSection(StringRef name) const;
-
- /// Retrieve program header if available.
- const PHDR *getProgramPHDR() const;
-
- void dump() const;
-
-private:
- /// A custom hash operator to teach the STL how to handle our custom keys.
- /// This will be used in our hash table mapping Sections to a Layout Order
- /// number (caching results).
- struct SectionKeyHash {
- int64_t operator()(const SectionKey &k) const {
- return llvm::hash_combine(k.archivePath, k.memberPath, k.sectionName);
- }
- };
-
- /// Teach the STL when two section keys are the same. This will be used in
- /// our hash table mapping Sections to a Layout Order number (caching results)
- struct SectionKeyEq {
- bool operator()(const SectionKey &lhs, const SectionKey &rhs) const {
- return ((lhs.archivePath == rhs.archivePath) &&
- (lhs.memberPath == rhs.memberPath) &&
- (lhs.sectionName == rhs.sectionName));
- }
- };
-
- /// Given an order id, check if it matches the tuple
- /// <archivePath, memberPath, sectionName> and returns the
- /// internal id that matched, or -1 if no matches.
- int matchSectionName(int id, const SectionKey &key) const;
-
- /// Returns a number that will determine the order of this input section
- /// in the final layout. If coarse is true, we simply return the layour order
- /// of the higher-level node InputSectionsCmd, used to order input sections.
- /// If coarse is false, we return the layout index down to the internal
- /// InputSectionsCmd arrangement, used to get the set of preceding linker
- ///expressions.
- int getLayoutOrder(const SectionKey &key, bool coarse) const;
-
- /// Compare two sections that have the same mapping rule (i.e., are matched
- /// by the same InputSectionsCmd).
- /// Determine if lhs < rhs by analyzing the InputSectionsCmd structure.
- bool localCompare(int order, const SectionKey &lhs,
- const SectionKey &rhs) const;
-
- /// Convert the PHDRS command into map of names to headers.
- /// Determine program header during processing.
- std::error_code collectPHDRs(const PHDRS *ph,
- llvm::StringMap<const PHDR *> &phdrs);
-
- /// Build map that matches output section names to segments they should be
- /// put into.
- std::error_code buildSectionToPHDR(llvm::StringMap<const PHDR *> &phdrs);
-
- /// Our goal with all linearizeAST overloaded functions is to
- /// traverse the linker script AST while putting nodes in a vector and
- /// thus enforcing order among nodes (which comes first).
- ///
- /// The order among nodes is determined by their indexes in this vector
- /// (_layoutCommands). This index allows us to solve the problem of
- /// establishing the order among two different input sections: we match each
- /// input sections with their respective layout command and use the indexes
- /// of these commands to order these sections.
- ///
- /// Example:
- ///
- /// Given the linker script:
- /// SECTIONS {
- /// .text : { *(.text) }
- /// .data : { *(.data) }
- /// }
- ///
- /// The _layoutCommands vector should contain:
- /// id 0 : <OutputSectionDescription> (_sectionName = ".text")
- /// id 1 : <InputSectionsCmd> (_memberName = "*")
- /// id 2 : <InputSectionName> (_name = ".text)
- /// id 3 : <OutputSectionDescription> (_sectionName = ".data")
- /// id 4 : <InputSectionsCmd> (_memberName = "*")
- /// id 5 : <InputSectionName> (_name = ".data")
- ///
- /// If we need to sort the following input sections:
- ///
- /// input section A: .text from libc.a (member errno.o)
- /// input section B: .data from libc.a (member write.o)
- ///
- /// Then we match input section A with the InputSectionsCmd of id 1, and
- /// input section B with the InputSectionsCmd of id 4. Since 1 < 4, we
- /// put A before B.
- ///
- /// The second problem handled by the linearization of the AST is the task
- /// of finding all preceding expressions that need to be calculated before
- /// emitting a given section. This task is easier to deal with when all nodes
- /// are in a vector because otherwise we would need to traverse multiple
- /// levels of the AST to find the set of expressions that preceed a layout
- /// command.
- ///
- /// The linker script commands that are linearized ("layout commands") are:
- ///
- /// * OutputSectionDescription, containing an output section name
- /// * InputSectionsCmd, containing an input file name
- /// * InputSectionName, containing a single input section name
- /// * InputSectionSortedName, a group of input section names
- /// * SymbolAssignment, containing an expression that may
- /// change the address where the linker is outputting data
- ///
- void linearizeAST(const Sections *sections);
- void linearizeAST(const InputSectionsCmd *inputSections);
- void linearizeAST(const InputSection *inputSection);
-
- std::vector<std::unique_ptr<Parser>> _scripts;
- std::vector<const Command *> _layoutCommands;
- std::unordered_multimap<std::string, int> _memberToLayoutOrder;
- std::vector<std::pair<StringRef, int>> _memberNameWildcards;
- mutable std::unordered_map<SectionKey, int, SectionKeyHash, SectionKeyEq>
- _cacheSectionOrder, _cacheExpressionOrder;
- llvm::DenseSet<int> _deliveredExprs;
- mutable llvm::StringSet<> _definedSymbols;
-
- llvm::StringMap<llvm::SmallVector<const PHDR *, 2>> _sectionToPHDR;
- const PHDR *_programPHDR;
-
- Expression::SymbolTableTy _symbolTable;
-};
-
-llvm::BumpPtrAllocator &Command::getAllocator() const {
- return _ctx.getAllocator();
-}
-llvm::BumpPtrAllocator &Expression::getAllocator() const {
- return _ctx.getAllocator();
-}
-} // end namespace script
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/MachOLinkingContext.h b/include/lld/ReaderWriter/MachOLinkingContext.h
index dc44d3f303f8..7b673f0dad3e 100644
--- a/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -13,6 +13,7 @@
#include "lld/Core/LinkingContext.h"
#include "lld/Core/Reader.h"
#include "lld/Core/Writer.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/ErrorHandling.h"
@@ -71,10 +72,21 @@ public:
dynamicLookup
};
+ enum ObjCConstraint {
+ objc_unknown = 0,
+ objc_supports_gc = 2,
+ objc_gc_only = 4,
+ // Image optimized by dyld = 8
+ // GC compaction = 16
+ objc_retainReleaseForSimulator = 32,
+ objc_retainRelease
+ };
+
/// Initializes the context to sane default values given the specified output
/// file type, arch, os, and minimum os version. This should be called before
/// other setXXX() methods.
- void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion);
+ void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion,
+ bool exportDynamicSymbols);
void addPasses(PassManager &pm) override;
bool validateImpl(raw_ostream &diagnostics) override;
@@ -82,6 +94,18 @@ public:
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+ /// Creates a new file which is owned by the context. Returns a pointer to
+ /// the new file.
+ template <class T, class... Args>
+ typename std::enable_if<!std::is_array<T>::value, T *>::type
+ make_file(Args &&... args) const {
+ auto file = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+ auto *filePtr = file.get();
+ auto *ctx = const_cast<MachOLinkingContext *>(this);
+ ctx->getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
+ return filePtr;
+ }
+
uint32_t getCPUType() const;
uint32_t getCPUSubType() const;
@@ -118,6 +142,8 @@ public:
void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
bool demangleSymbols() const { return _demangle; }
void setDemangleSymbols(bool d) { _demangle = d; }
+ bool mergeObjCCategories() const { return _mergeObjCCategories; }
+ void setMergeObjCCategories(bool v) { _mergeObjCCategories = v; }
/// Create file at specified path which will contain a binary encoding
/// of all input and output file paths.
std::error_code createDependencyFile(StringRef path);
@@ -136,6 +162,26 @@ public:
const StringRefVector &sysLibRoots() const { return _syslibRoots; }
bool PIE() const { return _pie; }
void setPIE(bool pie) { _pie = pie; }
+ bool generateVersionLoadCommand() const {
+ return _generateVersionLoadCommand;
+ }
+ void setGenerateVersionLoadCommand(bool v) {
+ _generateVersionLoadCommand = v;
+ }
+
+ bool generateFunctionStartsLoadCommand() const {
+ return _generateFunctionStartsLoadCommand;
+ }
+ void setGenerateFunctionStartsLoadCommand(bool v) {
+ _generateFunctionStartsLoadCommand = v;
+ }
+
+ bool generateDataInCodeLoadCommand() const {
+ return _generateDataInCodeLoadCommand;
+ }
+ void setGenerateDataInCodeLoadCommand(bool v) {
+ _generateDataInCodeLoadCommand = v;
+ }
uint64_t stackSize() const { return _stackSize; }
void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
@@ -143,6 +189,18 @@ public:
uint64_t baseAddress() const { return _baseAddress; }
void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
+ ObjCConstraint objcConstraint() const { return _objcConstraint; }
+
+ uint32_t osMinVersion() const { return _osMinVersion; }
+
+ uint32_t sdkVersion() const { return _sdkVersion; }
+ void setSdkVersion(uint64_t v) { _sdkVersion = v; }
+
+ uint64_t sourceVersion() const { return _sourceVersion; }
+ void setSourceVersion(uint64_t v) { _sourceVersion = v; }
+
+ uint32_t swiftVersion() const { return _swiftVersion; }
+
/// \brief Checks whether a given path on the filesystem exists.
///
/// When running in -test_file_usage mode, this method consults an
@@ -167,12 +225,12 @@ public:
/// The -lFoo option is documented to search for libFoo.dylib and libFoo.a in
/// that order, unless Foo ends in ".o", in which case only the exact file
/// matches (e.g. -lfoo.o would only find foo.o).
- ErrorOr<StringRef> searchDirForLibrary(StringRef path,
- StringRef libName) const;
+ llvm::Optional<StringRef> searchDirForLibrary(StringRef path,
+ StringRef libName) const;
/// \brief Iterates through all search path entries looking for libName (as
/// specified by -lFoo).
- ErrorOr<StringRef> searchLibrary(StringRef libName) const;
+ llvm::Optional<StringRef> searchLibrary(StringRef libName) const;
/// Add a framework search path. Internally, this method may be prepended
/// the path with syslibroot.
@@ -180,7 +238,7 @@ public:
/// \brief Iterates through all framework directories looking for
/// Foo.framework/Foo (when fwName = "Foo").
- ErrorOr<StringRef> findPathForFramework(StringRef fwName) const;
+ llvm::Optional<StringRef> findPathForFramework(StringRef fwName) const;
/// \brief The dylib's binary compatibility version, in the raw uint32 format.
///
@@ -297,6 +355,9 @@ public:
/// Pass to add shims switching between thumb and arm mode.
bool needsShimPass() const;
+ /// Pass to add objc image info and optimized objc data.
+ bool needsObjCPass() const;
+
/// Magic symbol name stubs will need to help lazy bind.
StringRef binderSymbolName() const;
@@ -340,8 +401,14 @@ public:
/// bits are xxxx.yy.zz. Largest number is 65535.255.255
static bool parsePackedVersion(StringRef str, uint32_t &result);
+ /// Construct 64-bit value from string "A.B.C.D.E" where
+ /// bits are aaaa.bb.cc.dd.ee. Largest number is 16777215.1023.1023.1023.1023
+ static bool parsePackedVersion(StringRef str, uint64_t &result);
+
void finalizeInputFiles() override;
+ llvm::Error handleLoadedFile(File &file) override;
+
bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right,
bool &leftBeforeRight) const;
@@ -383,28 +450,36 @@ private:
StringRefVector _searchDirs;
StringRefVector _syslibRoots;
StringRefVector _frameworkDirs;
- HeaderFileType _outputMachOType; // e.g MH_EXECUTE
- bool _outputMachOTypeStatic; // Disambiguate static vs dynamic prog
- bool _doNothing; // for -help and -v which just print info
- bool _pie;
- Arch _arch;
- OS _os;
- uint32_t _osMinVersion;
- uint64_t _pageZeroSize;
- uint64_t _pageSize;
- uint64_t _baseAddress;
- uint64_t _stackSize;
- uint32_t _compatibilityVersion;
- uint32_t _currentVersion;
+ HeaderFileType _outputMachOType = llvm::MachO::MH_EXECUTE;
+ bool _outputMachOTypeStatic = false; // Disambiguate static vs dynamic prog
+ bool _doNothing = false; // for -help and -v which just print info
+ bool _pie = false;
+ Arch _arch = arch_unknown;
+ OS _os = OS::macOSX;
+ uint32_t _osMinVersion = 0;
+ uint32_t _sdkVersion = 0;
+ uint64_t _sourceVersion = 0;
+ uint64_t _pageZeroSize = 0;
+ uint64_t _pageSize = 4096;
+ uint64_t _baseAddress = 0;
+ uint64_t _stackSize = 0;
+ uint32_t _compatibilityVersion = 0;
+ uint32_t _currentVersion = 0;
+ ObjCConstraint _objcConstraint = objc_unknown;
+ uint32_t _swiftVersion = 0;
StringRef _installName;
StringRefVector _rpaths;
- bool _flatNamespace;
- UndefinedMode _undefinedMode;
- bool _deadStrippableDylib;
- bool _printAtoms;
- bool _testingFileUsage;
- bool _keepPrivateExterns;
- bool _demangle;
+ bool _flatNamespace = false;
+ UndefinedMode _undefinedMode = UndefinedMode::error;
+ bool _deadStrippableDylib = false;
+ bool _printAtoms = false;
+ bool _testingFileUsage = false;
+ bool _keepPrivateExterns = false;
+ bool _demangle = false;
+ bool _mergeObjCCategories = true;
+ bool _generateVersionLoadCommand = false;
+ bool _generateFunctionStartsLoadCommand = false;
+ bool _generateDataInCodeLoadCommand = false;
StringRef _bundleLoader;
mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
mutable std::unique_ptr<Writer> _writer;
@@ -414,13 +489,13 @@ private:
mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
mutable std::mutex _dylibsMutex;
- ExportMode _exportMode;
+ ExportMode _exportMode = ExportMode::globals;
llvm::StringSet<> _exportedSymbols;
- DebugInfoMode _debugInfoMode;
+ DebugInfoMode _debugInfoMode = DebugInfoMode::addDebugMap;
std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
- unsigned _orderFileEntries;
- File *_flatNamespaceFile;
+ unsigned _orderFileEntries = 0;
+ File *_flatNamespaceFile = nullptr;
mach_o::SectCreateFile *_sectCreateFile = nullptr;
};
diff --git a/lib/Config/Version.cpp b/lib/Config/Version.cpp
index b64ccef12c7b..60687b9d8940 100644
--- a/lib/Config/Version.cpp
+++ b/lib/Config/Version.cpp
@@ -13,8 +13,6 @@
#include "lld/Config/Version.h"
#include "llvm/Support/raw_ostream.h"
-#include <cstdlib>
-#include <cstring>
using namespace llvm;
@@ -37,22 +35,15 @@ StringRef getLLDRevision() {
}
std::string getLLDRepositoryVersion() {
- std::string buf;
- llvm::raw_string_ostream OS(buf);
- std::string Path = getLLDRepositoryPath();
- std::string Revision = getLLDRevision();
- if (!Path.empty() || !Revision.empty()) {
- OS << '(';
- if (!Path.empty())
- OS << Path;
- if (!Revision.empty()) {
- if (!Path.empty())
- OS << ' ';
- OS << Revision;
- }
- OS << ')';
- }
- return OS.str();
+ std::string S = getLLDRepositoryPath();
+ std::string T = getLLDRevision();
+ if (S.empty() && T.empty())
+ return "";
+ if (!S.empty() && !T.empty())
+ return "(" + S + " " + T + ")";
+ if (!S.empty())
+ return "(" + S + ")";
+ return "(" + T + ")";
}
StringRef getLLDVersion() {
diff --git a/lib/Core/DefinedAtom.cpp b/lib/Core/DefinedAtom.cpp
index f1d308088ed4..8dc4d4a16f96 100644
--- a/lib/Core/DefinedAtom.cpp
+++ b/lib/Core/DefinedAtom.cpp
@@ -41,8 +41,8 @@ DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
case typeDTraceDOF:
case typeCompactUnwindInfo:
case typeProcessedUnwindInfo:
- case typeRONote:
- case typeNoAlloc:
+ case typeObjCImageInfo:
+ case typeObjCMethodList:
return permR__;
case typeData:
@@ -52,8 +52,8 @@ DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
case typeObjC1Class:
case typeLazyPointer:
case typeLazyDylibPointer:
+ case typeNonLazyPointer:
case typeThunkTLV:
- case typeRWNote:
return permRW_;
case typeGOT:
@@ -68,15 +68,12 @@ DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
case typeTLVInitialData:
case typeTLVInitialZeroFill:
case typeTLVInitializerPtr:
- case typeThreadData:
- case typeThreadZeroFill:
return permRW_L;
- case typeGroupComdat:
- case typeGnuLinkOnce:
case typeUnknown:
case typeTempLTO:
case typeSectCreate:
+ case typeDSOHandle:
return permUnknown;
}
llvm_unreachable("unknown content type");
diff --git a/lib/Core/Error.cpp b/lib/Core/Error.cpp
index 3b7733746dcd..4df1ce120bd9 100644
--- a/lib/Core/Error.cpp
+++ b/lib/Core/Error.cpp
@@ -39,42 +39,6 @@ const std::error_category &lld::YamlReaderCategory() {
return o;
}
-class _LinkerScriptReaderErrorCategory : public std::error_category {
-public:
- const char *name() const LLVM_NOEXCEPT override {
- return "lld.linker-script.reader";
- }
-
- std::string message(int ev) const override {
- switch (static_cast<LinkerScriptReaderError>(ev)) {
- case LinkerScriptReaderError::success:
- return "Success";
- case LinkerScriptReaderError::parse_error:
- return "Error parsing linker script";
- case LinkerScriptReaderError::unknown_symbol_in_expr:
- return "Unknown symbol found when evaluating linker script expression";
- case LinkerScriptReaderError::unrecognized_function_in_expr:
- return "Unrecognized function call when evaluating linker script "
- "expression";
- case LinkerScriptReaderError::unknown_phdr_ids:
- return "Unknown header identifiers (missing in PHDRS command) are used";
- case LinkerScriptReaderError::extra_program_phdr:
- return "Extra program header is found";
- case LinkerScriptReaderError::misplaced_program_phdr:
- return "Program header must precede load segments";
- case LinkerScriptReaderError::program_phdr_wrong_phdrs:
- return "Program header has invalid PHDRS attribute";
- }
- llvm_unreachable("An enumerator of LinkerScriptReaderError does not have a "
- "message defined.");
- }
-};
-
-const std::error_category &lld::LinkerScriptReaderCategory() {
- static _LinkerScriptReaderErrorCategory o;
- return o;
-}
-
namespace lld {
/// Temporary class to enable make_dynamic_error_code() until
@@ -112,16 +76,16 @@ private:
static dynamic_error_category categorySingleton;
-std::error_code make_dynamic_error_code(const char *msg) {
- return make_dynamic_error_code(StringRef(msg));
-}
-
std::error_code make_dynamic_error_code(StringRef msg) {
return std::error_code(categorySingleton.add(msg), categorySingleton);
}
-std::error_code make_dynamic_error_code(const Twine &msg) {
- return std::error_code(categorySingleton.add(msg.str()), categorySingleton);
+char GenericError::ID = 0;
+
+GenericError::GenericError(Twine Msg) : Msg(Msg.str()) { }
+
+void GenericError::log(raw_ostream &OS) const {
+ OS << Msg;
}
} // namespace lld
diff --git a/lib/Core/File.cpp b/lib/Core/File.cpp
index ac95f1016797..b84132bfecd5 100644
--- a/lib/Core/File.cpp
+++ b/lib/Core/File.cpp
@@ -13,7 +13,7 @@
namespace lld {
-File::~File() {}
+File::~File() { }
File::AtomVector<DefinedAtom> File::_noDefinedAtoms;
File::AtomVector<UndefinedAtom> File::_noUndefinedAtoms;
diff --git a/lib/Core/LinkingContext.cpp b/lib/Core/LinkingContext.cpp
index cbcf25c17df2..2732543d306e 100644
--- a/lib/Core/LinkingContext.cpp
+++ b/lib/Core/LinkingContext.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/Alias.h"
#include "lld/Core/LinkingContext.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/Simple.h"
@@ -16,16 +15,7 @@
namespace lld {
-LinkingContext::LinkingContext()
- : _deadStrip(false), _allowDuplicates(false),
- _globalsAreDeadStripRoots(false),
- _searchArchivesToOverrideTentativeDefinitions(false),
- _searchSharedLibrariesToOverrideTentativeDefinitions(false),
- _warnIfCoalesableAtomsHaveDifferentCanBeNull(false),
- _warnIfCoalesableAtomsHaveDifferentLoadName(false),
- _printRemainingUndefines(true), _allowRemainingUndefines(false),
- _logInputFiles(false), _allowShlibUndefines(true),
- _outputFileType(OutputFileType::Default), _nextOrdinal(0) {}
+LinkingContext::LinkingContext() {}
LinkingContext::~LinkingContext() {}
@@ -33,15 +23,10 @@ bool LinkingContext::validate(raw_ostream &diagnostics) {
return validateImpl(diagnostics);
}
-std::error_code LinkingContext::writeFile(const File &linkedFile) const {
+llvm::Error LinkingContext::writeFile(const File &linkedFile) const {
return this->writer().writeFile(linkedFile, _outputPath);
}
-void LinkingContext::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- this->writer().createImplicitFiles(result);
-}
-
std::unique_ptr<File> LinkingContext::createEntrySymbolFile() const {
return createEntrySymbolFile("<command line option -e>");
}
@@ -50,7 +35,8 @@ std::unique_ptr<File>
LinkingContext::createEntrySymbolFile(StringRef filename) const {
if (entrySymbolName().empty())
return nullptr;
- std::unique_ptr<SimpleFile> entryFile(new SimpleFile(filename));
+ std::unique_ptr<SimpleFile> entryFile(new SimpleFile(filename,
+ File::kindEntryObject));
entryFile->addAtom(
*(new (_allocator) SimpleUndefinedAtom(*entryFile, entrySymbolName())));
return std::move(entryFile);
@@ -64,41 +50,20 @@ std::unique_ptr<File>
LinkingContext::createUndefinedSymbolFile(StringRef filename) const {
if (_initialUndefinedSymbols.empty())
return nullptr;
- std::unique_ptr<SimpleFile> undefinedSymFile(new SimpleFile(filename));
+ std::unique_ptr<SimpleFile> undefinedSymFile(
+ new SimpleFile(filename, File::kindUndefinedSymsObject));
for (StringRef undefSym : _initialUndefinedSymbols)
undefinedSymFile->addAtom(*(new (_allocator) SimpleUndefinedAtom(
*undefinedSymFile, undefSym)));
return std::move(undefinedSymFile);
}
-std::unique_ptr<File> LinkingContext::createAliasSymbolFile() const {
- if (getAliases().empty())
- return nullptr;
- std::unique_ptr<SimpleFile> file(new SimpleFile("<alias>"));
- for (const auto &i : getAliases()) {
- StringRef from = i.first;
- StringRef to = i.second;
- SimpleDefinedAtom *fromAtom = new (_allocator) AliasAtom(*file, from);
- UndefinedAtom *toAtom = new (_allocator) SimpleUndefinedAtom(*file, to);
- fromAtom->addReference(Reference::KindNamespace::all,
- Reference::KindArch::all, Reference::kindLayoutAfter,
- 0, toAtom, 0);
- file->addAtom(*fromAtom);
- file->addAtom(*toAtom);
- }
- return std::move(file);
-}
-
void LinkingContext::createInternalFiles(
std::vector<std::unique_ptr<File> > &result) const {
if (std::unique_ptr<File> file = createEntrySymbolFile())
result.push_back(std::move(file));
if (std::unique_ptr<File> file = createUndefinedSymbolFile())
result.push_back(std::move(file));
- if (std::unique_ptr<File> file = createAliasSymbolFile())
- result.push_back(std::move(file));
}
-void LinkingContext::addPasses(PassManager &pm) {}
-
} // end namespace lld
diff --git a/lib/Core/Reader.cpp b/lib/Core/Reader.cpp
index 6069093d211e..107db07891da 100644
--- a/lib/Core/Reader.cpp
+++ b/lib/Core/Reader.cpp
@@ -47,7 +47,6 @@ Registry::loadFile(std::unique_ptr<MemoryBuffer> mb) const {
static const Registry::KindStrings kindStrings[] = {
{Reference::kindLayoutAfter, "layout-after"},
- {Reference::kindGroupChild, "group-child"},
{Reference::kindAssociate, "associate"},
LLD_KIND_STRING_END};
diff --git a/lib/Core/Resolver.cpp b/lib/Core/Resolver.cpp
index 8f89856c4a47..ef694fd972fc 100644
--- a/lib/Core/Resolver.cpp
+++ b/lib/Core/Resolver.cpp
@@ -19,6 +19,7 @@
#include "lld/Core/UndefinedAtom.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -29,26 +30,27 @@
namespace lld {
-bool Resolver::handleFile(File &file) {
+llvm::Expected<bool> Resolver::handleFile(File &file) {
+ if (auto ec = _ctx.handleLoadedFile(file))
+ return std::move(ec);
bool undefAdded = false;
- for (const DefinedAtom *atom : file.defined())
- doDefinedAtom(*atom);
- for (const UndefinedAtom *atom : file.undefined()) {
- if (doUndefinedAtom(*atom)) {
+ for (auto &atom : file.defined().owning_ptrs())
+ doDefinedAtom(std::move(atom));
+ for (auto &atom : file.undefined().owning_ptrs()) {
+ if (doUndefinedAtom(std::move(atom)))
undefAdded = true;
- maybePreloadArchiveMember(atom->name());
- }
}
- for (const SharedLibraryAtom *atom : file.sharedLibrary())
- doSharedLibraryAtom(*atom);
- for (const AbsoluteAtom *atom : file.absolute())
- doAbsoluteAtom(*atom);
+ for (auto &atom : file.sharedLibrary().owning_ptrs())
+ doSharedLibraryAtom(std::move(atom));
+ for (auto &atom : file.absolute().owning_ptrs())
+ doAbsoluteAtom(std::move(atom));
return undefAdded;
}
-void Resolver::forEachUndefines(File &file, bool searchForOverrides,
- UndefCallback callback) {
+llvm::Expected<bool> Resolver::forEachUndefines(File &file,
+ UndefCallback callback) {
size_t i = _undefineIndex[&file];
+ bool undefAdded = false;
do {
for (; i < _undefines.size(); ++i) {
StringRef undefName = _undefines[i];
@@ -60,190 +62,120 @@ void Resolver::forEachUndefines(File &file, bool searchForOverrides,
_undefines[i] = "";
continue;
}
- callback(undefName, false);
- }
- if (!searchForOverrides)
- continue;
- for (StringRef tentDefName : _symbolTable.tentativeDefinitions()) {
- // Load for previous tentative may also have loaded
- // something that overrode this tentative, so always check.
- const Atom *curAtom = _symbolTable.findByName(tentDefName);
- assert(curAtom != nullptr);
- if (const DefinedAtom *curDefAtom = dyn_cast<DefinedAtom>(curAtom))
- if (curDefAtom->merge() == DefinedAtom::mergeAsTentative)
- callback(tentDefName, true);
+ auto undefAddedOrError = callback(undefName);
+ if (auto ec = undefAddedOrError.takeError())
+ return std::move(ec);
+ undefAdded |= undefAddedOrError.get();
}
} while (i < _undefines.size());
_undefineIndex[&file] = i;
+ return undefAdded;
}
-bool Resolver::handleArchiveFile(File &file) {
+llvm::Expected<bool> Resolver::handleArchiveFile(File &file) {
ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&file);
- bool searchForOverrides =
- _ctx.searchArchivesToOverrideTentativeDefinitions();
- bool undefAdded = false;
- forEachUndefines(file, searchForOverrides,
- [&](StringRef undefName, bool dataSymbolOnly) {
- if (File *member = archiveFile->find(undefName, dataSymbolOnly)) {
+ return forEachUndefines(file,
+ [&](StringRef undefName) -> llvm::Expected<bool> {
+ if (File *member = archiveFile->find(undefName)) {
member->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- member->beforeLink();
- updatePreloadArchiveMap();
- undefAdded = handleFile(*member) || undefAdded;
+ return handleFile(*member);
}
+ return false;
});
- return undefAdded;
}
-void Resolver::handleSharedLibrary(File &file) {
+llvm::Error Resolver::handleSharedLibrary(File &file) {
// Add all the atoms from the shared library
SharedLibraryFile *sharedLibrary = cast<SharedLibraryFile>(&file);
- handleFile(*sharedLibrary);
- bool searchForOverrides =
- _ctx.searchSharedLibrariesToOverrideTentativeDefinitions();
- forEachUndefines(file, searchForOverrides,
- [&](StringRef undefName, bool dataSymbolOnly) {
- if (const SharedLibraryAtom *atom =
- sharedLibrary->exports(undefName, dataSymbolOnly))
- doSharedLibraryAtom(*atom);
- });
+ auto undefAddedOrError = handleFile(*sharedLibrary);
+ if (auto ec = undefAddedOrError.takeError())
+ return ec;
+ undefAddedOrError =
+ forEachUndefines(file, [&](StringRef undefName) -> llvm::Expected<bool> {
+ auto atom = sharedLibrary->exports(undefName);
+ if (atom.get())
+ doSharedLibraryAtom(std::move(atom));
+ return false;
+ });
+
+ if (auto ec = undefAddedOrError.takeError())
+ return ec;
+ return llvm::Error();
}
-bool Resolver::doUndefinedAtom(const UndefinedAtom &atom) {
+bool Resolver::doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " UndefinedAtom: "
- << llvm::format("0x%09lX", &atom)
- << ", name=" << atom.name() << "\n");
-
- // add to list of known atoms
- _atoms.push_back(&atom);
+ << llvm::format("0x%09lX", atom.get())
+ << ", name=" << atom.get()->name() << "\n");
// tell symbol table
- bool newUndefAdded = _symbolTable.add(atom);
+ bool newUndefAdded = _symbolTable.add(*atom.get());
if (newUndefAdded)
- _undefines.push_back(atom.name());
-
- // If the undefined symbol has an alternative name, try to resolve the
- // symbol with the name to give it a second chance. This feature is used
- // for COFF "weak external" symbol.
- if (newUndefAdded || !_symbolTable.isDefined(atom.name())) {
- if (const UndefinedAtom *fallbackAtom = atom.fallback()) {
- doUndefinedAtom(*fallbackAtom);
- _symbolTable.addReplacement(&atom, fallbackAtom);
- }
- }
- return newUndefAdded;
-}
+ _undefines.push_back(atom.get()->name());
-/// \brief Add the section group and the group-child reference members.
-void Resolver::maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom) {
- // First time adding a group?
- bool isFirstTime = _symbolTable.addGroup(atom);
-
- if (!isFirstTime) {
- // If duplicate symbols are allowed, select the first group.
- if (_ctx.getAllowDuplicates())
- return;
- auto *prevGroup = dyn_cast<DefinedAtom>(_symbolTable.findGroup(atom.name()));
- assert(prevGroup &&
- "Internal Error: The group atom could only be a defined atom");
- // The atoms should be of the same content type, reject invalid group
- // resolution behaviors.
- if (atom.contentType() == prevGroup->contentType())
- return;
- llvm::errs() << "SymbolTable: error while merging " << atom.name()
- << "\n";
- llvm::report_fatal_error("duplicate symbol error");
- }
+ // add to list of known atoms
+ _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
- for (const Reference *r : atom) {
- if (r->kindNamespace() == lld::Reference::KindNamespace::all &&
- r->kindValue() == lld::Reference::kindGroupChild) {
- const DefinedAtom *target = dyn_cast<DefinedAtom>(r->target());
- assert(target && "Internal Error: kindGroupChild references need to "
- "be associated with Defined Atoms only");
- _atoms.push_back(target);
- _symbolTable.add(*target);
- }
- }
+ return newUndefAdded;
}
// Called on each atom when a file is added. Returns true if a given
// atom is added to the symbol table.
-void Resolver::doDefinedAtom(const DefinedAtom &atom) {
+void Resolver::doDefinedAtom(OwningAtomPtr<DefinedAtom> atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " DefinedAtom: "
- << llvm::format("0x%09lX", &atom)
+ << llvm::format("0x%09lX", atom.get())
<< ", file=#"
- << atom.file().ordinal()
+ << atom.get()->file().ordinal()
<< ", atom=#"
- << atom.ordinal()
+ << atom.get()->ordinal()
<< ", name="
- << atom.name()
+ << atom.get()->name()
<< ", type="
- << atom.contentType()
+ << atom.get()->contentType()
<< "\n");
- // add to list of known atoms
- _atoms.push_back(&atom);
-
- if (atom.isGroupParent()) {
- maybeAddSectionGroupOrGnuLinkOnce(atom);
- } else {
- _symbolTable.add(atom);
- }
-
// An atom that should never be dead-stripped is a dead-strip root.
- if (_ctx.deadStrip() && atom.deadStrip() == DefinedAtom::deadStripNever) {
- _deadStripRoots.insert(&atom);
+ if (_ctx.deadStrip() &&
+ atom.get()->deadStrip() == DefinedAtom::deadStripNever) {
+ _deadStripRoots.insert(atom.get());
}
+
+ // add to list of known atoms
+ _symbolTable.add(*atom.get());
+ _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
}
-void Resolver::doSharedLibraryAtom(const SharedLibraryAtom &atom) {
+void Resolver::doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " SharedLibraryAtom: "
- << llvm::format("0x%09lX", &atom)
+ << llvm::format("0x%09lX", atom.get())
<< ", name="
- << atom.name()
+ << atom.get()->name()
<< "\n");
- // add to list of known atoms
- _atoms.push_back(&atom);
-
// tell symbol table
- _symbolTable.add(atom);
+ _symbolTable.add(*atom.get());
+
+ // add to list of known atoms
+ _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
}
-void Resolver::doAbsoluteAtom(const AbsoluteAtom &atom) {
+void Resolver::doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " AbsoluteAtom: "
- << llvm::format("0x%09lX", &atom)
+ << llvm::format("0x%09lX", atom.get())
<< ", name="
- << atom.name()
+ << atom.get()->name()
<< "\n");
- // add to list of known atoms
- _atoms.push_back(&atom);
-
// tell symbol table
- if (atom.scope() != Atom::scopeTranslationUnit)
- _symbolTable.add(atom);
-}
+ if (atom.get()->scope() != Atom::scopeTranslationUnit)
+ _symbolTable.add(*atom.get());
-// utility to add a vector of atoms
-void Resolver::addAtoms(const std::vector<const DefinedAtom *> &newAtoms) {
- for (const DefinedAtom *newAtom : newAtoms)
- doDefinedAtom(*newAtom);
-}
-
-// Instantiate an archive file member if there's a file containing a
-// defined symbol for a given symbol name. Instantiation is done in a
-// different worker thread and has no visible side effect.
-void Resolver::maybePreloadArchiveMember(StringRef sym) {
- auto it = _archiveMap.find(sym);
- if (it == _archiveMap.end())
- return;
- ArchiveLibraryFile *archive = it->second;
- archive->preload(_ctx.getTaskGroup(), sym);
+ // add to list of known atoms
+ _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
}
// Returns true if at least one of N previous files has created an
@@ -276,23 +208,6 @@ File *Resolver::getFile(int &index) {
return cast<FileNode>(inputs[index++].get())->getFile();
}
-// Update a map of Symbol -> ArchiveFile. The map is used for speculative
-// file loading.
-void Resolver::updatePreloadArchiveMap() {
- std::vector<std::unique_ptr<Node>> &nodes = _ctx.getNodes();
- for (int i = nodes.size() - 1; i >= 0; --i) {
- auto *fnode = dyn_cast<FileNode>(nodes[i].get());
- if (!fnode)
- continue;
- auto *archive = dyn_cast<ArchiveLibraryFile>(fnode->getFile());
- if (!archive || _archiveSeen.count(archive))
- continue;
- _archiveSeen.insert(archive);
- for (StringRef sym : archive->getDefinedSymbols())
- _archiveMap[sym] = archive;
- }
-}
-
// Keep adding atoms until _ctx.getNextFile() returns an error. This
// function is where undefined atoms are resolved.
bool Resolver::resolveUndefines() {
@@ -315,10 +230,17 @@ bool Resolver::resolveUndefines() {
}
DEBUG_WITH_TYPE("resolver",
llvm::dbgs() << "Loaded file: " << file->path() << "\n");
- file->beforeLink();
- updatePreloadArchiveMap();
switch (file->kind()) {
- case File::kindObject:
+ case File::kindErrorObject:
+ case File::kindNormalizedObject:
+ case File::kindMachObject:
+ case File::kindCEntryObject:
+ case File::kindHeaderObject:
+ case File::kindEntryObject:
+ case File::kindUndefinedSymsObject:
+ case File::kindStubHelperObject:
+ case File::kindResolverMergedObject:
+ case File::kindSectCreateObject: {
// The same file may be visited more than once if the file is
// in --start-group and --end-group. Only library files should
// be processed more than once.
@@ -327,17 +249,41 @@ bool Resolver::resolveUndefines() {
seen.insert(file);
assert(!file->hasOrdinal());
file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- undefAdded = handleFile(*file);
+ auto undefAddedOrError = handleFile(*file);
+ if (auto EC = undefAddedOrError.takeError()) {
+ // FIXME: This should be passed to logAllUnhandledErrors but it needs
+ // to be passed a Twine instead of a string.
+ llvm::errs() << "Error in " + file->path() << ": ";
+ logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
+ return false;
+ }
+ undefAdded = undefAddedOrError.get();
break;
- case File::kindArchiveLibrary:
+ }
+ case File::kindArchiveLibrary: {
if (!file->hasOrdinal())
file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- undefAdded = handleArchiveFile(*file);
+ auto undefAddedOrError = handleArchiveFile(*file);
+ if (auto EC = undefAddedOrError.takeError()) {
+ // FIXME: This should be passed to logAllUnhandledErrors but it needs
+ // to be passed a Twine instead of a string.
+ llvm::errs() << "Error in " + file->path() << ": ";
+ logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
+ return false;
+ }
+ undefAdded = undefAddedOrError.get();
break;
+ }
case File::kindSharedLibrary:
if (!file->hasOrdinal())
file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- handleSharedLibrary(*file);
+ if (auto EC = handleSharedLibrary(*file)) {
+ // FIXME: This should be passed to logAllUnhandledErrors but it needs
+ // to be passed a Twine instead of a string.
+ llvm::errs() << "Error in " + file->path() << ": ";
+ logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
+ return false;
+ }
break;
}
_newUndefinesAdded[file] = undefAdded;
@@ -350,8 +296,8 @@ void Resolver::updateReferences() {
DEBUG_WITH_TYPE("resolver",
llvm::dbgs() << "******** Updating references:\n");
ScopedTask task(getDefaultDomain(), "updateReferences");
- for (const Atom *atom : _atoms) {
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
+ for (const OwningAtomPtr<Atom> &atom : _atoms) {
+ if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get())) {
for (const Reference *ref : *defAtom) {
// A reference of type kindAssociate should't be updated.
// Instead, an atom having such reference will be removed
@@ -359,7 +305,7 @@ void Resolver::updateReferences() {
// go away as a group.
if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
ref->kindValue() == lld::Reference::kindAssociate) {
- if (_symbolTable.isCoalescedAway(atom))
+ if (_symbolTable.isCoalescedAway(atom.get()))
_deadAtoms.insert(ref->target());
continue;
}
@@ -391,8 +337,7 @@ void Resolver::markLive(const Atom *atom) {
static bool isBackref(const Reference *ref) {
if (ref->kindNamespace() != lld::Reference::KindNamespace::all)
return false;
- return (ref->kindValue() == lld::Reference::kindLayoutAfter ||
- ref->kindValue() == lld::Reference::kindGroupChild);
+ return (ref->kindValue() == lld::Reference::kindLayoutAfter);
}
// remove all atoms not actually used
@@ -408,19 +353,19 @@ void Resolver::deadStripOptimize() {
// Make a reverse map of such references before traversing the graph.
// While traversing the list of atoms, mark AbsoluteAtoms as live
// in order to avoid reclaim.
- for (const Atom *atom : _atoms) {
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
+ for (const OwningAtomPtr<Atom> &atom : _atoms) {
+ if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
for (const Reference *ref : *defAtom)
if (isBackref(ref))
- _reverseRef.insert(std::make_pair(ref->target(), atom));
- if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom))
+ _reverseRef.insert(std::make_pair(ref->target(), atom.get()));
+ if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom.get()))
markLive(absAtom);
}
// By default, shared libraries are built with all globals as dead strip roots
if (_ctx.globalsAreDeadStripRoots())
- for (const Atom *atom : _atoms)
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
+ for (const OwningAtomPtr<Atom> &atom : _atoms)
+ if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
if (defAtom->scope() == DefinedAtom::scopeGlobal)
_deadStripRoots.insert(defAtom);
@@ -436,8 +381,9 @@ void Resolver::deadStripOptimize() {
markLive(dsrAtom);
// now remove all non-live atoms from _atoms
- _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
- return _liveAtoms.count(a) == 0;
+ _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
+ [&](OwningAtomPtr<Atom> &a) {
+ return _liveAtoms.count(a.get()) == 0;
}),
_atoms.end());
}
@@ -496,8 +442,10 @@ void Resolver::removeCoalescedAwayAtoms() {
DEBUG_WITH_TYPE("resolver",
llvm::dbgs() << "******** Removing coalesced away atoms:\n");
ScopedTask task(getDefaultDomain(), "removeCoalescedAwayAtoms");
- _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
- return _symbolTable.isCoalescedAway(a) || _deadAtoms.count(a);
+ _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
+ [&](OwningAtomPtr<Atom> &a) {
+ return _symbolTable.isCoalescedAway(a.get()) ||
+ _deadAtoms.count(a.get());
}),
_atoms.end());
}
@@ -505,7 +453,6 @@ void Resolver::removeCoalescedAwayAtoms() {
bool Resolver::resolve() {
DEBUG_WITH_TYPE("resolver",
llvm::dbgs() << "******** Resolving atom references:\n");
- updatePreloadArchiveMap();
if (!resolveUndefines())
return false;
updateReferences();
@@ -524,15 +471,16 @@ bool Resolver::resolve() {
return true;
}
-void Resolver::MergedFile::addAtoms(std::vector<const Atom *> &all) {
+void Resolver::MergedFile::addAtoms(
+ llvm::MutableArrayRef<OwningAtomPtr<Atom>> all) {
ScopedTask task(getDefaultDomain(), "addAtoms");
DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
- for (const Atom *atom : all) {
+ for (OwningAtomPtr<Atom> &atom : all) {
#ifndef NDEBUG
- if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) {
+ if (auto *definedAtom = dyn_cast<DefinedAtom>(atom.get())) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", atom)
+ << llvm::format(" 0x%09lX", definedAtom)
<< ", file=#"
<< definedAtom->file().ordinal()
<< ", atom=#"
@@ -544,13 +492,13 @@ void Resolver::MergedFile::addAtoms(std::vector<const Atom *> &all) {
<< "\n");
} else {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", atom)
+ << llvm::format(" 0x%09lX", atom.get())
<< ", name="
- << atom->name()
+ << atom.get()->name()
<< "\n");
}
#endif
- addAtom(*atom);
+ addAtom(*atom.release());
}
}
diff --git a/lib/Core/SymbolTable.cpp b/lib/Core/SymbolTable.cpp
index b85a83ffbfe6..44631a5d40dc 100644
--- a/lib/Core/SymbolTable.cpp
+++ b/lib/Core/SymbolTable.cpp
@@ -28,8 +28,6 @@
#include <vector>
namespace lld {
-SymbolTable::SymbolTable(LinkingContext &context) : _ctx(context) {}
-
bool SymbolTable::add(const UndefinedAtom &atom) { return addByName(atom); }
bool SymbolTable::add(const SharedLibraryAtom &atom) { return addByName(atom); }
@@ -55,25 +53,6 @@ bool SymbolTable::add(const DefinedAtom &atom) {
return false;
}
-const Atom *SymbolTable::findGroup(StringRef sym) {
- NameToAtom::iterator pos = _groupTable.find(sym);
- if (pos == _groupTable.end())
- return nullptr;
- return pos->second;
-}
-
-bool SymbolTable::addGroup(const DefinedAtom &da) {
- StringRef name = da.name();
- assert(!name.empty());
- const Atom *existing = findGroup(name);
- if (existing == nullptr) {
- _groupTable[name] = &da;
- return true;
- }
- _replacedAtoms[&da] = existing;
- return false;
-}
-
enum NameCollisionResolution {
NCR_First,
NCR_Second,
@@ -185,19 +164,16 @@ bool SymbolTable::addByName(const Atom &newAtom) {
// fallthrough
}
case MCR_Error:
- if (!_ctx.getAllowDuplicates()) {
- llvm::errs() << "Duplicate symbols: "
- << existing->name()
- << ":"
- << existing->file().path()
- << " and "
- << newAtom.name()
- << ":"
- << newAtom.file().path()
- << "\n";
- llvm::report_fatal_error("duplicate symbol error");
- }
- useNew = false;
+ llvm::errs() << "Duplicate symbols: "
+ << existing->name()
+ << ":"
+ << existing->file().path()
+ << " and "
+ << newAtom.name()
+ << ":"
+ << newAtom.file().path()
+ << "\n";
+ llvm::report_fatal_error("duplicate symbol error");
break;
}
break;
@@ -207,56 +183,13 @@ bool SymbolTable::addByName(const Atom &newAtom) {
const UndefinedAtom* newUndef = cast<UndefinedAtom>(&newAtom);
bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
- if (!sameCanBeNull && _ctx.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
- llvm::errs() << "lld warning: undefined symbol "
- << existingUndef->name()
- << " has different weakness in "
- << existingUndef->file().path()
- << " and in " << newUndef->file().path() << "\n";
- }
-
- const UndefinedAtom *existingFallback = existingUndef->fallback();
- const UndefinedAtom *newFallback = newUndef->fallback();
- bool hasDifferentFallback =
- (existingFallback && newFallback &&
- existingFallback->name() != newFallback->name());
- if (hasDifferentFallback) {
- llvm::errs() << "lld warning: undefined symbol "
- << existingUndef->name() << " has different fallback: "
- << existingFallback->name() << " in "
- << existingUndef->file().path() << " and "
- << newFallback->name() << " in "
- << newUndef->file().path() << "\n";
- }
-
- bool hasNewFallback = newUndef->fallback();
if (sameCanBeNull)
- useNew = hasNewFallback;
+ useNew = false;
else
useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
break;
}
case NCR_DupShLib: {
- const SharedLibraryAtom *curShLib = cast<SharedLibraryAtom>(existing);
- const SharedLibraryAtom *newShLib = cast<SharedLibraryAtom>(&newAtom);
- bool sameNullness =
- (curShLib->canBeNullAtRuntime() == newShLib->canBeNullAtRuntime());
- bool sameName = curShLib->loadName().equals(newShLib->loadName());
- if (sameName && !sameNullness &&
- _ctx.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
- // FIXME: need diagonstics interface for writing warning messages
- llvm::errs() << "lld warning: shared library symbol "
- << curShLib->name() << " has different weakness in "
- << curShLib->file().path() << " and in "
- << newShLib->file().path();
- }
- if (!sameName && _ctx.warnIfCoalesableAtomsHaveDifferentLoadName()) {
- // FIXME: need diagonstics interface for writing warning messages
- llvm::errs() << "lld warning: shared library symbol "
- << curShLib->name() << " has different load path in "
- << curShLib->file().path() << " and in "
- << newShLib->file().path();
- }
useNew = false;
break;
}
@@ -266,9 +199,6 @@ bool SymbolTable::addByName(const Atom &newAtom) {
break;
}
- // Give context a chance to change which is kept.
- _ctx.notifySymbolTableCoalesce(existing, &newAtom, useNew);
-
if (useNew) {
// Update name table to use new atom.
_nameTable[name] = &newAtom;
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 840ccce50ab3..1bd1f2125816 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -1,19 +1,9 @@
-set(LLVM_TARGET_DEFINITIONS UniversalDriverOptions.td)
-tablegen(LLVM UniversalDriverOptions.inc -gen-opt-parser-defs)
-set(LLVM_TARGET_DEFINITIONS GnuLdOptions.td)
-tablegen(LLVM GnuLdOptions.inc -gen-opt-parser-defs)
-set(LLVM_TARGET_DEFINITIONS CoreOptions.td)
-tablegen(LLVM CoreOptions.inc -gen-opt-parser-defs)
set(LLVM_TARGET_DEFINITIONS DarwinLdOptions.td)
tablegen(LLVM DarwinLdOptions.inc -gen-opt-parser-defs)
add_public_tablegen_target(DriverOptionsTableGen)
add_lld_library(lldDriver
- CoreDriver.cpp
DarwinLdDriver.cpp
- Driver.cpp
- GnuLdDriver.cpp
- UniversalDriver.cpp
ADDITIONAL_HEADER_DIRS
${LLD_INCLUDE_DIR}/lld/Driver
@@ -21,16 +11,6 @@ add_lld_library(lldDriver
LINK_LIBS
lldConfig
lldMachO
- lldCOFF
- lldELF
- lldELF2
- lldAArch64ELFTarget
- lldARMELFTarget
- lldHexagonELFTarget
- lldMipsELFTarget
- lldX86ELFTarget
- lldExampleSubTarget
- lldX86_64ELFTarget
lldCore
lldReaderWriter
lldYAML
@@ -40,4 +20,3 @@ add_lld_library(lldDriver
)
add_dependencies(lldDriver DriverOptionsTableGen)
-
diff --git a/lib/Driver/CoreDriver.cpp b/lib/Driver/CoreDriver.cpp
deleted file mode 100644
index ce8648595109..000000000000
--- a/lib/Driver/CoreDriver.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-//===- lib/Driver/CoreDriver.cpp ------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Reader.h"
-#include "lld/Driver/Driver.h"
-#include "lld/ReaderWriter/CoreLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lld;
-
-namespace {
-
-// Create enum with OPT_xxx values for each option in CoreOptions.td
-enum {
- OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELP, META) \
- OPT_##ID,
-#include "CoreOptions.inc"
-#undef OPTION
-};
-
-// Create prefix string literals used in CoreOptions.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "CoreOptions.inc"
-#undef PREFIX
-
-// Create table mapping all options defined in CoreOptions.td
-static const llvm::opt::OptTable::Info infoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
- { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
- PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
-#include "CoreOptions.inc"
-#undef OPTION
-};
-
-// Create OptTable class for parsing actual command line arguments
-class CoreOptTable : public llvm::opt::OptTable {
-public:
- CoreOptTable() : OptTable(infoTable) {}
-};
-
-} // namespace anonymous
-
-
-namespace lld {
-
-static const Registry::KindStrings coreKindStrings[] = {
- { CoreLinkingContext::TEST_RELOC_CALL32, "call32" },
- { CoreLinkingContext::TEST_RELOC_PCREL32, "pcrel32" },
- { CoreLinkingContext::TEST_RELOC_GOT_LOAD32, "gotLoad32" },
- { CoreLinkingContext::TEST_RELOC_GOT_USE32, "gotUse32" },
- { CoreLinkingContext::TEST_RELOC_LEA32_WAS_GOT, "lea32wasGot" },
- LLD_KIND_STRING_END
-};
-
-bool CoreDriver::link(llvm::ArrayRef<const char *> args,
- raw_ostream &diagnostics) {
- CoreLinkingContext ctx;
-
- // Register possible input file parsers.
- ctx.registry().addSupportYamlFiles();
- ctx.registry().addKindTable(Reference::KindNamespace::testing,
- Reference::KindArch::all, coreKindStrings);
-
- if (!parse(args, ctx))
- return false;
- return Driver::link(ctx);
-}
-
-bool CoreDriver::parse(llvm::ArrayRef<const char *> args,
- CoreLinkingContext &ctx, raw_ostream &diagnostics) {
- // Parse command line options using CoreOptions.td
- CoreOptTable table;
- unsigned missingIndex;
- unsigned missingCount;
- llvm::opt::InputArgList parsedArgs =
- table.ParseArgs(args.slice(1), missingIndex, missingCount);
- if (missingCount) {
- diagnostics << "error: missing arg value for '"
- << parsedArgs.getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
- return false;
- }
-
- // Set default options
- ctx.setOutputPath("-");
- ctx.setDeadStripping(false);
- ctx.setGlobalsAreDeadStripRoots(false);
- ctx.setPrintRemainingUndefines(false);
- ctx.setAllowRemainingUndefines(true);
- ctx.setSearchArchivesToOverrideTentativeDefinitions(false);
-
- // Process all the arguments and create input files.
- for (auto inputArg : parsedArgs) {
- switch (inputArg->getOption().getID()) {
- case OPT_mllvm:
- ctx.appendLLVMOption(inputArg->getValue());
- break;
-
- case OPT_entry:
- ctx.setEntrySymbolName(inputArg->getValue());
- break;
-
- case OPT_output:
- ctx.setOutputPath(inputArg->getValue());
- break;
-
- case OPT_dead_strip:
- ctx.setDeadStripping(true);
- break;
-
- case OPT_keep_globals:
- ctx.setGlobalsAreDeadStripRoots(true);
- break;
-
- case OPT_undefines_are_errors:
- ctx.setPrintRemainingUndefines(true);
- ctx.setAllowRemainingUndefines(false);
- break;
-
- case OPT_commons_search_archives:
- ctx.setSearchArchivesToOverrideTentativeDefinitions(true);
- break;
-
- case OPT_add_pass:
- ctx.addPassNamed(inputArg->getValue());
- break;
-
- case OPT_INPUT: {
- std::vector<std::unique_ptr<File>> files
- = loadFile(ctx, inputArg->getValue(), false);
- for (std::unique_ptr<File> &file : files)
- ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
- break;
- }
-
- default:
- break;
- }
- }
-
- parseLLVMOptions(ctx);
-
- if (ctx.getNodes().empty()) {
- diagnostics << "No input files\n";
- return false;
- }
-
- // Validate the combination of options used.
- return ctx.validate(diagnostics);
-}
-
-} // namespace lld
diff --git a/lib/Driver/CoreOptions.td b/lib/Driver/CoreOptions.td
deleted file mode 100644
index df7cb41737d2..000000000000
--- a/lib/Driver/CoreOptions.td
+++ /dev/null
@@ -1,15 +0,0 @@
-include "llvm/Option/OptParser.td"
-
-def output : Separate<["-"], "o">;
-def entry : Separate<["-"], "e">;
-
-def dead_strip : Flag<["--"], "dead-strip">;
-def undefines_are_errors : Flag<["--"], "undefines-are-errors">;
-def keep_globals : Flag<["--"], "keep-globals">;
-def commons_search_archives : Flag<["--"], "commons-search-archives">;
-
-def add_pass : Separate<["--"], "add-pass">;
-
-def target : Separate<["-"], "target">, HelpText<"Target triple to link for">;
-def mllvm : Separate<["-"], "mllvm">, HelpText<"Options to pass to LLVM">;
-
diff --git a/lib/Driver/DarwinLdDriver.cpp b/lib/Driver/DarwinLdDriver.cpp
index 40fad74c9529..496b651bab4f 100644
--- a/lib/Driver/DarwinLdDriver.cpp
+++ b/lib/Driver/DarwinLdDriver.cpp
@@ -13,8 +13,11 @@
///
//===----------------------------------------------------------------------===//
-#include "lld/Core/File.h"
#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Instrumentation.h"
+#include "lld/Core/PassManager.h"
+#include "lld/Core/Resolver.h"
#include "lld/Core/SharedLibraryFile.h"
#include "lld/Driver/Driver.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"
@@ -25,17 +28,10 @@
#include "llvm/Option/Arg.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MachO.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
using namespace lld;
@@ -72,6 +68,25 @@ public:
DarwinLdOptTable() : OptTable(infoTable) {}
};
+static std::vector<std::unique_ptr<File>>
+makeErrorFile(StringRef path, std::error_code ec) {
+ std::vector<std::unique_ptr<File>> result;
+ result.push_back(llvm::make_unique<ErrorFile>(path, ec));
+ return result;
+}
+
+static std::vector<std::unique_ptr<File>>
+parseMemberFiles(std::unique_ptr<File> file) {
+ std::vector<std::unique_ptr<File>> members;
+ if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) {
+ if (std::error_code ec = archive->parseAllMembers(members))
+ return makeErrorFile(file->path(), ec);
+ } else {
+ members.push_back(std::move(file));
+ }
+ return members;
+}
+
std::vector<std::unique_ptr<File>>
loadFile(MachOLinkingContext &ctx, StringRef path,
raw_ostream &diag, bool wholeArchive, bool upwardDylib) {
@@ -215,9 +230,9 @@ static std::error_code parseOrderFile(StringRef orderFilePath,
// In this variant, the path is to a text file which contains a partial path
// per line. The <dir> prefix is prepended to each partial path.
//
-static std::error_code loadFileList(StringRef fileListPath,
- MachOLinkingContext &ctx, bool forceLoad,
- raw_ostream &diagnostics) {
+static llvm::Error loadFileList(StringRef fileListPath,
+ MachOLinkingContext &ctx, bool forceLoad,
+ raw_ostream &diagnostics) {
// If there is a comma, split off <dir>.
std::pair<StringRef, StringRef> opt = fileListPath.split(',');
StringRef filePath = opt.first;
@@ -227,7 +242,7 @@ static std::error_code loadFileList(StringRef fileListPath,
ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
MemoryBuffer::getFileOrSTDIN(filePath);
if (std::error_code ec = mb.getError())
- return ec;
+ return llvm::errorCodeToError(ec);
StringRef buffer = mb->get()->getBuffer();
while (!buffer.empty()) {
// Split off each line in the file.
@@ -245,9 +260,9 @@ static std::error_code loadFileList(StringRef fileListPath,
path = ctx.copy(line);
}
if (!ctx.pathExists(path)) {
- return make_dynamic_error_code(Twine("File not found '")
- + path
- + "'");
+ return llvm::make_error<GenericError>(Twine("File not found '")
+ + path
+ + "'");
}
if (ctx.testingFileUsage()) {
diagnostics << "Found filelist entry " << canonicalizePath(path) << '\n';
@@ -255,7 +270,7 @@ static std::error_code loadFileList(StringRef fileListPath,
addFile(path, ctx, forceLoad, false, diagnostics);
buffer = lineAndRest.second;
}
- return std::error_code();
+ return llvm::Error();
}
/// Parse number assuming it is base 16, but allow 0x prefix.
@@ -265,20 +280,24 @@ static bool parseNumberBase16(StringRef numStr, uint64_t &baseAddress) {
return numStr.getAsInteger(16, baseAddress);
}
-namespace lld {
-
-bool DarwinLdDriver::linkMachO(llvm::ArrayRef<const char *> args,
- raw_ostream &diagnostics) {
- MachOLinkingContext ctx;
- if (!parse(args, ctx, diagnostics))
- return false;
- if (ctx.doNothing())
- return true;
- return link(ctx, diagnostics);
+static void parseLLVMOptions(const LinkingContext &ctx) {
+ // Honor -mllvm
+ if (!ctx.llvmOptions().empty()) {
+ unsigned numArgs = ctx.llvmOptions().size();
+ auto **args = new const char *[numArgs + 2];
+ args[0] = "lld (LLVM option parsing)";
+ for (unsigned i = 0; i != numArgs; ++i)
+ args[i + 1] = ctx.llvmOptions()[i];
+ args[numArgs + 1] = nullptr;
+ llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
+ }
}
-bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
- MachOLinkingContext &ctx, raw_ostream &diagnostics) {
+namespace lld {
+namespace mach_o {
+
+bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
+ raw_ostream &diagnostics) {
// Parse command line options using DarwinLdOptions.td
DarwinLdOptTable table;
unsigned missingIndex;
@@ -299,6 +318,7 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
// Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )
llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE;
+ bool isStaticExecutable = false;
if (llvm::opt::Arg *kind = parsedArgs.getLastArg(
OPT_dylib, OPT_relocatable, OPT_bundle, OPT_static, OPT_preload)) {
switch (kind->getOption().getID()) {
@@ -313,6 +333,7 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
break;
case OPT_static:
fileType = llvm::MachO::MH_EXECUTE;
+ isStaticExecutable = true;
break;
case OPT_preload:
fileType = llvm::MachO::MH_PRELOAD;
@@ -350,7 +371,7 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
}
// Handle -macosx_version_min or -ios_version_min
- MachOLinkingContext::OS os = MachOLinkingContext::OS::macOSX;
+ MachOLinkingContext::OS os = MachOLinkingContext::OS::unknown;
uint32_t minOSVersion = 0;
if (llvm::opt::Arg *minOS =
parsedArgs.getLastArg(OPT_macosx_version_min, OPT_ios_version_min,
@@ -385,9 +406,16 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
// No min-os version on command line, check environment variables
}
+ // Handle export_dynamic
+ // FIXME: Should we warn when this applies to something other than a static
+ // executable or dylib? Those are the only cases where this has an effect.
+ // Note, this has to come before ctx.configure() so that we get the correct
+ // value for _globalsAreDeadStripRoots.
+ bool exportDynamicSymbols = parsedArgs.hasArg(OPT_export_dynamic);
+
// Now that there's enough information parsed in, let the linking context
// set up default values.
- ctx.configure(fileType, arch, os, minOSVersion);
+ ctx.configure(fileType, arch, os, minOSVersion, exportDynamicSymbols);
// Handle -e xxx
if (llvm::opt::Arg *entry = parsedArgs.getLastArg(OPT_entry))
@@ -673,6 +701,22 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
}
}
+ // Handle obsolete ObjC options: -objc_gc_compaction, -objc_gc, -objc_gc_only
+ if (parsedArgs.getLastArg(OPT_objc_gc_compaction)) {
+ diagnostics << "error: -objc_gc_compaction is not supported\n";
+ return false;
+ }
+
+ if (parsedArgs.getLastArg(OPT_objc_gc)) {
+ diagnostics << "error: -objc_gc is not supported\n";
+ return false;
+ }
+
+ if (parsedArgs.getLastArg(OPT_objc_gc_only)) {
+ diagnostics << "error: -objc_gc_only is not supported\n";
+ return false;
+ }
+
// Handle -pie or -no_pie
if (llvm::opt::Arg *pie = parsedArgs.getLastArg(OPT_pie, OPT_no_pie)) {
switch (ctx.outputMachOType()) {
@@ -719,6 +763,182 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
}
}
+ // Handle -version_load_command or -no_version_load_command
+ {
+ bool flagOn = false;
+ bool flagOff = false;
+ if (auto *arg = parsedArgs.getLastArg(OPT_version_load_command,
+ OPT_no_version_load_command)) {
+ flagOn = arg->getOption().getID() == OPT_version_load_command;
+ flagOff = arg->getOption().getID() == OPT_no_version_load_command;
+ }
+
+ // default to adding version load command for dynamic code,
+ // static code must opt-in
+ switch (ctx.outputMachOType()) {
+ case llvm::MachO::MH_OBJECT:
+ ctx.setGenerateVersionLoadCommand(false);
+ break;
+ case llvm::MachO::MH_EXECUTE:
+ // dynamic executables default to generating a version load command,
+ // while static exectuables only generate it if required.
+ if (isStaticExecutable) {
+ if (flagOn)
+ ctx.setGenerateVersionLoadCommand(true);
+ } else {
+ if (!flagOff)
+ ctx.setGenerateVersionLoadCommand(true);
+ }
+ break;
+ case llvm::MachO::MH_PRELOAD:
+ case llvm::MachO::MH_KEXT_BUNDLE:
+ if (flagOn)
+ ctx.setGenerateVersionLoadCommand(true);
+ break;
+ case llvm::MachO::MH_DYLINKER:
+ case llvm::MachO::MH_DYLIB:
+ case llvm::MachO::MH_BUNDLE:
+ if (!flagOff)
+ ctx.setGenerateVersionLoadCommand(true);
+ break;
+ case llvm::MachO::MH_FVMLIB:
+ case llvm::MachO::MH_DYLDLINK:
+ case llvm::MachO::MH_DYLIB_STUB:
+ case llvm::MachO::MH_DSYM:
+ // We don't generate load commands for these file types, even if
+ // forced on.
+ break;
+ }
+ }
+
+ // Handle -function_starts or -no_function_starts
+ {
+ bool flagOn = false;
+ bool flagOff = false;
+ if (auto *arg = parsedArgs.getLastArg(OPT_function_starts,
+ OPT_no_function_starts)) {
+ flagOn = arg->getOption().getID() == OPT_function_starts;
+ flagOff = arg->getOption().getID() == OPT_no_function_starts;
+ }
+
+ // default to adding functions start for dynamic code, static code must
+ // opt-in
+ switch (ctx.outputMachOType()) {
+ case llvm::MachO::MH_OBJECT:
+ ctx.setGenerateFunctionStartsLoadCommand(false);
+ break;
+ case llvm::MachO::MH_EXECUTE:
+ // dynamic executables default to generating a version load command,
+ // while static exectuables only generate it if required.
+ if (isStaticExecutable) {
+ if (flagOn)
+ ctx.setGenerateFunctionStartsLoadCommand(true);
+ } else {
+ if (!flagOff)
+ ctx.setGenerateFunctionStartsLoadCommand(true);
+ }
+ break;
+ case llvm::MachO::MH_PRELOAD:
+ case llvm::MachO::MH_KEXT_BUNDLE:
+ if (flagOn)
+ ctx.setGenerateFunctionStartsLoadCommand(true);
+ break;
+ case llvm::MachO::MH_DYLINKER:
+ case llvm::MachO::MH_DYLIB:
+ case llvm::MachO::MH_BUNDLE:
+ if (!flagOff)
+ ctx.setGenerateFunctionStartsLoadCommand(true);
+ break;
+ case llvm::MachO::MH_FVMLIB:
+ case llvm::MachO::MH_DYLDLINK:
+ case llvm::MachO::MH_DYLIB_STUB:
+ case llvm::MachO::MH_DSYM:
+ // We don't generate load commands for these file types, even if
+ // forced on.
+ break;
+ }
+ }
+
+ // Handle -data_in_code_info or -no_data_in_code_info
+ {
+ bool flagOn = false;
+ bool flagOff = false;
+ if (auto *arg = parsedArgs.getLastArg(OPT_data_in_code_info,
+ OPT_no_data_in_code_info)) {
+ flagOn = arg->getOption().getID() == OPT_data_in_code_info;
+ flagOff = arg->getOption().getID() == OPT_no_data_in_code_info;
+ }
+
+ // default to adding data in code for dynamic code, static code must
+ // opt-in
+ switch (ctx.outputMachOType()) {
+ case llvm::MachO::MH_OBJECT:
+ if (!flagOff)
+ ctx.setGenerateDataInCodeLoadCommand(true);
+ break;
+ case llvm::MachO::MH_EXECUTE:
+ // dynamic executables default to generating a version load command,
+ // while static exectuables only generate it if required.
+ if (isStaticExecutable) {
+ if (flagOn)
+ ctx.setGenerateDataInCodeLoadCommand(true);
+ } else {
+ if (!flagOff)
+ ctx.setGenerateDataInCodeLoadCommand(true);
+ }
+ break;
+ case llvm::MachO::MH_PRELOAD:
+ case llvm::MachO::MH_KEXT_BUNDLE:
+ if (flagOn)
+ ctx.setGenerateDataInCodeLoadCommand(true);
+ break;
+ case llvm::MachO::MH_DYLINKER:
+ case llvm::MachO::MH_DYLIB:
+ case llvm::MachO::MH_BUNDLE:
+ if (!flagOff)
+ ctx.setGenerateDataInCodeLoadCommand(true);
+ break;
+ case llvm::MachO::MH_FVMLIB:
+ case llvm::MachO::MH_DYLDLINK:
+ case llvm::MachO::MH_DYLIB_STUB:
+ case llvm::MachO::MH_DSYM:
+ // We don't generate load commands for these file types, even if
+ // forced on.
+ break;
+ }
+ }
+
+ // Handle sdk_version
+ if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_sdk_version)) {
+ uint32_t sdkVersion = 0;
+ if (MachOLinkingContext::parsePackedVersion(arg->getValue(),
+ sdkVersion)) {
+ diagnostics << "error: malformed sdkVersion value\n";
+ return false;
+ }
+ ctx.setSdkVersion(sdkVersion);
+ } else if (ctx.generateVersionLoadCommand()) {
+ // If we don't have an sdk version, but were going to emit a load command
+ // with min_version, then we need to give an warning as we have no sdk
+ // version to put in that command.
+ // FIXME: We need to decide whether to make this an error.
+ diagnostics << "warning: -sdk_version is required when emitting "
+ "min version load command. "
+ "Setting sdk version to match provided min version\n";
+ ctx.setSdkVersion(ctx.osMinVersion());
+ }
+
+ // Handle source_version
+ if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_source_version)) {
+ uint64_t version = 0;
+ if (MachOLinkingContext::parsePackedVersion(arg->getValue(),
+ version)) {
+ diagnostics << "error: malformed source_version value\n";
+ return false;
+ }
+ ctx.setSourceVersion(version);
+ }
+
// Handle stack_size
if (llvm::opt::Arg *stackSize = parsedArgs.getLastArg(OPT_stack_size)) {
uint64_t stackSizeVal;
@@ -794,6 +1014,10 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
ctx.setUndefinedMode(UndefMode);
}
+ // Handle -no_objc_category_merging.
+ if (parsedArgs.getLastArg(OPT_no_objc_category_merging))
+ ctx.setMergeObjCCategories(false);
+
// Handle -rpath <path>
if (parsedArgs.hasArg(OPT_rpath)) {
switch (ctx.outputMachOType()) {
@@ -829,7 +1053,7 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
// Handle input files and sectcreate.
for (auto &arg : parsedArgs) {
bool upward;
- ErrorOr<StringRef> resolvedPath = StringRef();
+ llvm::Optional<StringRef> resolvedPath;
switch (arg->getOption().getID()) {
default:
continue;
@@ -852,9 +1076,10 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
return false;
} else if (ctx.testingFileUsage()) {
diagnostics << "Found " << (upward ? "upward " : " ") << "library "
- << canonicalizePath(resolvedPath.get()) << '\n';
+ << canonicalizePath(resolvedPath.getValue()) << '\n';
}
- addFile(resolvedPath.get(), ctx, globalWholeArchive, upward, diagnostics);
+ addFile(resolvedPath.getValue(), ctx, globalWholeArchive,
+ upward, diagnostics);
break;
case OPT_framework:
case OPT_upward_framework:
@@ -866,17 +1091,20 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
return false;
} else if (ctx.testingFileUsage()) {
diagnostics << "Found " << (upward ? "upward " : " ") << "framework "
- << canonicalizePath(resolvedPath.get()) << '\n';
+ << canonicalizePath(resolvedPath.getValue()) << '\n';
}
- addFile(resolvedPath.get(), ctx, globalWholeArchive, upward, diagnostics);
+ addFile(resolvedPath.getValue(), ctx, globalWholeArchive,
+ upward, diagnostics);
break;
case OPT_filelist:
- if (std::error_code ec = loadFileList(arg->getValue(),
- ctx, globalWholeArchive,
- diagnostics)) {
- diagnostics << "error: " << ec.message()
- << ", processing '-filelist " << arg->getValue()
- << "'\n";
+ if (auto ec = loadFileList(arg->getValue(),
+ ctx, globalWholeArchive,
+ diagnostics)) {
+ handleAllErrors(std::move(ec), [&](const llvm::ErrorInfoBase &EI) {
+ diagnostics << "error: ";
+ EI.log(diagnostics);
+ diagnostics << ", processing '-filelist " << arg->getValue() << "'\n";
+ });
return false;
}
break;
@@ -908,5 +1136,80 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
return ctx.validate(diagnostics);
}
+/// This is where the link is actually performed.
+bool link(llvm::ArrayRef<const char *> args, raw_ostream &diagnostics) {
+ MachOLinkingContext ctx;
+ if (!parse(args, ctx, diagnostics))
+ return false;
+ if (ctx.doNothing())
+ return true;
+ if (ctx.getNodes().empty())
+ return false;
+
+ for (std::unique_ptr<Node> &ie : ctx.getNodes())
+ if (FileNode *node = dyn_cast<FileNode>(ie.get()))
+ node->getFile()->parse();
+
+ std::vector<std::unique_ptr<File>> internalFiles;
+ ctx.createInternalFiles(internalFiles);
+ for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {
+ auto &members = ctx.getNodes();
+ members.insert(members.begin(), llvm::make_unique<FileNode>(std::move(*i)));
+ }
+
+ // Give target a chance to add files.
+ std::vector<std::unique_ptr<File>> implicitFiles;
+ ctx.createImplicitFiles(implicitFiles);
+ for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {
+ auto &members = ctx.getNodes();
+ members.insert(members.begin(), llvm::make_unique<FileNode>(std::move(*i)));
+ }
+
+ // Give target a chance to postprocess input files.
+ // Mach-O uses this chance to move all object files before library files.
+ ctx.finalizeInputFiles();
+ // Do core linking.
+ ScopedTask resolveTask(getDefaultDomain(), "Resolve");
+ Resolver resolver(ctx);
+ if (!resolver.resolve())
+ return false;
+ SimpleFile *merged = nullptr;
+ {
+ std::unique_ptr<SimpleFile> mergedFile = resolver.resultFile();
+ merged = mergedFile.get();
+ auto &members = ctx.getNodes();
+ members.insert(members.begin(),
+ llvm::make_unique<FileNode>(std::move(mergedFile)));
+ }
+ resolveTask.end();
+
+ // Run passes on linked atoms.
+ ScopedTask passTask(getDefaultDomain(), "Passes");
+ PassManager pm;
+ ctx.addPasses(pm);
+ if (auto ec = pm.runOnFile(*merged)) {
+ // FIXME: This should be passed to logAllUnhandledErrors but it needs
+ // to be passed a Twine instead of a string.
+ diagnostics << "Failed to run passes on file '" << ctx.outputPath()
+ << "': ";
+ logAllUnhandledErrors(std::move(ec), diagnostics, std::string());
+ return false;
+ }
+
+ passTask.end();
+
+ // Give linked atoms to Writer to generate output file.
+ ScopedTask writeTask(getDefaultDomain(), "Write");
+ if (auto ec = ctx.writeFile(*merged)) {
+ // FIXME: This should be passed to logAllUnhandledErrors but it needs
+ // to be passed a Twine instead of a string.
+ diagnostics << "Failed to write file '" << ctx.outputPath() << "': ";
+ logAllUnhandledErrors(std::move(ec), diagnostics, std::string());
+ return false;
+ }
+
+ return true;
+}
+} // namespace mach_o
} // namespace lld
diff --git a/lib/Driver/DarwinLdOptions.td b/lib/Driver/DarwinLdOptions.td
index cbf6ac1d4a4b..fa07f33646e7 100644
--- a/lib/Driver/DarwinLdOptions.td
+++ b/lib/Driver/DarwinLdOptions.td
@@ -33,6 +33,28 @@ def iphoneos_version_min : Separate<["-"], "iphoneos_version_min">,
def ios_simulator_version_min : Separate<["-"], "ios_simulator_version_min">,
MetaVarName<"<version>">,
HelpText<"Minimum iOS simulator version">, Group<grp_opts>;
+def sdk_version : Separate<["-"], "sdk_version">,
+ MetaVarName<"<version>">,
+ HelpText<"SDK version">, Group<grp_opts>;
+def source_version : Separate<["-"], "source_version">,
+ MetaVarName<"<version>">,
+ HelpText<"Source version">, Group<grp_opts>;
+def version_load_command : Flag<["-"], "version_load_command">,
+ HelpText<"Force generation of a version load command">, Group<grp_opts>;
+def no_version_load_command : Flag<["-"], "no_version_load_command">,
+ HelpText<"Disable generation of a version load command">, Group<grp_opts>;
+def function_starts : Flag<["-"], "function_starts">,
+ HelpText<"Force generation of a function starts load command">,
+ Group<grp_opts>;
+def no_function_starts : Flag<["-"], "no_function_starts">,
+ HelpText<"Disable generation of a function starts load command">,
+ Group<grp_opts>;
+def data_in_code_info : Flag<["-"], "data_in_code_info">,
+ HelpText<"Force generation of a data in code load command">,
+ Group<grp_opts>;
+def no_data_in_code_info : Flag<["-"], "no_data_in_code_info">,
+ HelpText<"Disable generation of a data in code load command">,
+ Group<grp_opts>;
def mllvm : Separate<["-"], "mllvm">,
MetaVarName<"<option>">,
HelpText<"Options to pass to LLVM during LTO">, Group<grp_opts>;
@@ -68,6 +90,10 @@ def undefined : Separate<["-"], "undefined">,
MetaVarName<"<undefined>">,
HelpText<"Determines how undefined symbols are handled.">,
Group<grp_opts>;
+def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">,
+ HelpText<"Disables the optimisation which merges Objective-C categories "
+ "on a class in to the class itself.">,
+ Group<grp_opts>;
// main executable options
def grp_main : OptionGroup<"opts">, HelpText<"MAIN EXECUTABLE OPTIONS">;
@@ -84,6 +110,9 @@ def stack_size : Separate<["-"], "stack_size">,
HelpText<"Specifies the maximum stack size for the main thread in a program. "
"Must be a page-size multiple. (default=8Mb)">,
Group<grp_main>;
+def export_dynamic : Flag<["-"], "export_dynamic">,
+ HelpText<"Preserves all global symbols in main executables during LTO">,
+ Group<grp_main>;
// dylib executable options
def grp_dylib : OptionGroup<"opts">, HelpText<"DYLIB EXECUTABLE OPTIONS">;
@@ -205,3 +234,9 @@ def single_module : Flag<["-"], "single_module">,
HelpText<"Default for dylibs">, Group<grp_obsolete>;
def multi_module : Flag<["-"], "multi_module">,
HelpText<"Unsupported way to build dylibs">, Group<grp_obsolete>;
+def objc_gc_compaction : Flag<["-"], "objc_gc_compaction">,
+ HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
+def objc_gc : Flag<["-"], "objc_gc">,
+ HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
+def objc_gc_only : Flag<["-"], "objc_gc_only">,
+ HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
deleted file mode 100644
index 6a7a26b3b0f6..000000000000
--- a/lib/Driver/Driver.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-//===- lib/Driver/Driver.cpp - Linker Driver Emulator -----------*- C++ -*-===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Parallel.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Resolver.h"
-#include "lld/Core/Writer.h"
-#include "lld/Driver/Driver.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/raw_ostream.h"
-#include <mutex>
-
-namespace lld {
-
-FileVector makeErrorFile(StringRef path, std::error_code ec) {
- std::vector<std::unique_ptr<File>> result;
- result.push_back(llvm::make_unique<ErrorFile>(path, ec));
- return result;
-}
-
-FileVector parseMemberFiles(std::unique_ptr<File> file) {
- std::vector<std::unique_ptr<File>> members;
- if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) {
- if (std::error_code ec = archive->parseAllMembers(members))
- return makeErrorFile(file->path(), ec);
- } else {
- members.push_back(std::move(file));
- }
- return members;
-}
-
-FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> mb
- = MemoryBuffer::getFileOrSTDIN(path);
- if (std::error_code ec = mb.getError())
- return makeErrorFile(path, ec);
- ErrorOr<std::unique_ptr<File>> fileOrErr =
- ctx.registry().loadFile(std::move(mb.get()));
- if (std::error_code ec = fileOrErr.getError())
- return makeErrorFile(path, ec);
- std::unique_ptr<File> &file = fileOrErr.get();
- if (wholeArchive)
- return parseMemberFiles(std::move(file));
- std::vector<std::unique_ptr<File>> files;
- files.push_back(std::move(file));
- return files;
-}
-
-void Driver::parseLLVMOptions(const LinkingContext &ctx) {
- // Honor -mllvm
- if (!ctx.llvmOptions().empty()) {
- unsigned numArgs = ctx.llvmOptions().size();
- auto **args = new const char *[numArgs + 2];
- args[0] = "lld (LLVM option parsing)";
- for (unsigned i = 0; i != numArgs; ++i)
- args[i + 1] = ctx.llvmOptions()[i];
- args[numArgs + 1] = nullptr;
- llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
- }
-}
-
-/// This is where the link is actually performed.
-bool Driver::link(LinkingContext &ctx, raw_ostream &diagnostics) {
- if (ctx.getNodes().empty())
- return false;
-
- for (std::unique_ptr<Node> &ie : ctx.getNodes())
- if (FileNode *node = dyn_cast<FileNode>(ie.get()))
- ctx.getTaskGroup().spawn([node] { node->getFile()->parse(); });
-
- std::vector<std::unique_ptr<File>> internalFiles;
- ctx.createInternalFiles(internalFiles);
- for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {
- auto &members = ctx.getNodes();
- members.insert(members.begin(), llvm::make_unique<FileNode>(std::move(*i)));
- }
-
- // Give target a chance to add files.
- std::vector<std::unique_ptr<File>> implicitFiles;
- ctx.createImplicitFiles(implicitFiles);
- for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {
- auto &members = ctx.getNodes();
- members.insert(members.begin(), llvm::make_unique<FileNode>(std::move(*i)));
- }
-
- // Give target a chance to postprocess input files.
- // Mach-O uses this chance to move all object files before library files.
- // ELF adds specific undefined symbols resolver.
- ctx.finalizeInputFiles();
-
- // Do core linking.
- ScopedTask resolveTask(getDefaultDomain(), "Resolve");
- Resolver resolver(ctx);
- if (!resolver.resolve()) {
- ctx.getTaskGroup().sync();
- return false;
- }
- std::unique_ptr<SimpleFile> merged = resolver.resultFile();
- resolveTask.end();
-
- // Run passes on linked atoms.
- ScopedTask passTask(getDefaultDomain(), "Passes");
- PassManager pm;
- ctx.addPasses(pm);
- if (std::error_code ec = pm.runOnFile(*merged)) {
- diagnostics << "Failed to write file '" << ctx.outputPath()
- << "': " << ec.message() << "\n";
- return false;
- }
-
- passTask.end();
-
- // Give linked atoms to Writer to generate output file.
- ScopedTask writeTask(getDefaultDomain(), "Write");
- if (std::error_code ec = ctx.writeFile(*merged)) {
- diagnostics << "Failed to write file '" << ctx.outputPath()
- << "': " << ec.message() << "\n";
- return false;
- }
-
- return true;
-}
-
-} // namespace lld
diff --git a/lib/Driver/GnuLdDriver.cpp b/lib/Driver/GnuLdDriver.cpp
deleted file mode 100644
index 1cff481dd8d7..000000000000
--- a/lib/Driver/GnuLdDriver.cpp
+++ /dev/null
@@ -1,782 +0,0 @@
-//===- lib/Driver/GnuLdDriver.cpp -----------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Concrete instance of the Driver for GNU's ld.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Driver/Driver.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "lld/ReaderWriter/LinkerScript.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstring>
-#include <tuple>
-
-using namespace lld;
-
-using llvm::BumpPtrAllocator;
-
-namespace {
-
-// Create enum with OPT_xxx values for each option in GnuLdOptions.td
-enum {
- OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELP, META) \
- OPT_##ID,
-#include "GnuLdOptions.inc"
-#undef OPTION
-};
-
-// Create prefix string literals used in GnuLdOptions.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "GnuLdOptions.inc"
-#undef PREFIX
-
-// Create table mapping all options defined in GnuLdOptions.td
-static const llvm::opt::OptTable::Info infoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
- { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
- PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
-#include "GnuLdOptions.inc"
-#undef OPTION
-};
-
-
-// Create OptTable class for parsing actual command line arguments
-class GnuLdOptTable : public llvm::opt::OptTable {
-public:
- GnuLdOptTable() : OptTable(infoTable){}
-};
-
-} // anonymous namespace
-
-// If a command line option starts with "@", the driver reads its suffix as a
-// file, parse its contents as a list of command line options, and insert them
-// at the original @file position. If file cannot be read, @file is not expanded
-// and left unmodified. @file can appear in a response file, so it's a recursive
-// process.
-static llvm::ArrayRef<const char *>
-maybeExpandResponseFiles(llvm::ArrayRef<const char *> args,
- BumpPtrAllocator &alloc) {
- // Expand response files.
- SmallVector<const char *, 256> smallvec;
- for (const char *arg : args)
- smallvec.push_back(arg);
- llvm::StringSaver saver(alloc);
- llvm::cl::ExpandResponseFiles(saver, llvm::cl::TokenizeGNUCommandLine, smallvec);
-
- // Pack the results to a C-array and return it.
- const char **copy = alloc.Allocate<const char *>(smallvec.size() + 1);
- std::copy(smallvec.begin(), smallvec.end(), copy);
- copy[smallvec.size()] = nullptr;
- return llvm::makeArrayRef(copy, smallvec.size() + 1);
-}
-
-// Parses an argument of --defsym=<sym>=<number>
-static bool parseDefsymAsAbsolute(StringRef opt, StringRef &sym,
- uint64_t &addr) {
- size_t equalPos = opt.find('=');
- if (equalPos == 0 || equalPos == StringRef::npos)
- return false;
- sym = opt.substr(0, equalPos);
- if (opt.substr(equalPos + 1).getAsInteger(0, addr))
- return false;
- return true;
-}
-
-// Parses an argument of --defsym=<sym>=<sym>
-static bool parseDefsymAsAlias(StringRef opt, StringRef &sym,
- StringRef &target) {
- size_t equalPos = opt.find('=');
- if (equalPos == 0 || equalPos == StringRef::npos)
- return false;
- sym = opt.substr(0, equalPos);
- target = opt.substr(equalPos + 1);
- return !target.empty();
-}
-
-// Parses -z max-page-size=<value>
-static bool parseMaxPageSize(StringRef opt, uint64_t &val) {
- size_t equalPos = opt.find('=');
- if (equalPos == 0 || equalPos == StringRef::npos)
- return false;
- StringRef value = opt.substr(equalPos + 1);
- val = 0;
- if (value.getAsInteger(0, val) || !val)
- return false;
- return true;
-}
-
-bool GnuLdDriver::linkELF(llvm::ArrayRef<const char *> args,
- raw_ostream &diag) {
- BumpPtrAllocator alloc;
- args = maybeExpandResponseFiles(args, alloc);
- std::unique_ptr<ELFLinkingContext> options;
- if (!parse(args, options, diag))
- return false;
- if (!options)
- return true;
- bool linked = link(*options, diag);
-
- // Handle --stats.
- if (options->collectStats()) {
- llvm::TimeRecord t = llvm::TimeRecord::getCurrentTime(true);
- diag << "total time in link " << t.getProcessTime() << "\n";
- diag << "data size " << t.getMemUsed() << "\n";
- }
- return linked;
-}
-
-static llvm::Optional<llvm::Triple::ArchType>
-getArchType(const llvm::Triple &triple, StringRef value) {
- switch (triple.getArch()) {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- if (value == "elf_i386")
- return llvm::Triple::x86;
- if (value == "elf_x86_64")
- return llvm::Triple::x86_64;
- return llvm::None;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return llvm::StringSwitch<llvm::Optional<llvm::Triple::ArchType>>(value)
- .Cases("elf32btsmip", "elf32btsmipn32", llvm::Triple::mips)
- .Cases("elf32ltsmip", "elf32ltsmipn32", llvm::Triple::mipsel)
- .Case("elf64btsmip", llvm::Triple::mips64)
- .Case("elf64ltsmip", llvm::Triple::mips64el)
- .Default(llvm::None);
- case llvm::Triple::aarch64:
- if (value == "aarch64linux")
- return llvm::Triple::aarch64;
- return llvm::None;
- case llvm::Triple::arm:
- if (value == "armelf_linux_eabi")
- return llvm::Triple::arm;
- return llvm::None;
- default:
- return llvm::None;
- }
-}
-
-static bool isLinkerScript(StringRef path, raw_ostream &diag) {
- llvm::sys::fs::file_magic magic = llvm::sys::fs::file_magic::unknown;
- if (std::error_code ec = llvm::sys::fs::identify_magic(path, magic)) {
- diag << "unknown input file format: " << path << ": "
- << ec.message() << "\n";
- return false;
- }
- return magic == llvm::sys::fs::file_magic::unknown;
-}
-
-static ErrorOr<StringRef>
-findFile(ELFLinkingContext &ctx, StringRef path, bool dashL) {
- // If the path was referred to by using a -l argument, let's search
- // for the file in the search path.
- if (dashL) {
- ErrorOr<StringRef> pathOrErr = ctx.searchLibrary(path);
- if (std::error_code ec = pathOrErr.getError())
- return make_dynamic_error_code(
- Twine("Unable to find library -l") + path + ": " + ec.message());
- path = pathOrErr.get();
- }
- if (!llvm::sys::fs::exists(path))
- return make_dynamic_error_code(
- Twine("lld: cannot find file ") + path);
- return path;
-}
-
-static bool isPathUnderSysroot(StringRef sysroot, StringRef path) {
- if (sysroot.empty())
- return false;
- while (!path.empty() && !llvm::sys::fs::equivalent(sysroot, path))
- path = llvm::sys::path::parent_path(path);
- return !path.empty();
-}
-
-static std::error_code
-addFilesFromLinkerScript(ELFLinkingContext &ctx, StringRef scriptPath,
- const std::vector<script::Path> &inputPaths,
- raw_ostream &diag) {
- bool sysroot = (!ctx.getSysroot().empty()
- && isPathUnderSysroot(ctx.getSysroot(), scriptPath));
- for (const script::Path &path : inputPaths) {
- ErrorOr<StringRef> pathOrErr = path._isDashlPrefix
- ? ctx.searchLibrary(path._path) : ctx.searchFile(path._path, sysroot);
- if (std::error_code ec = pathOrErr.getError()) {
- auto file = llvm::make_unique<ErrorFile>(path._path, ec);
- ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
- continue;
- }
-
- std::vector<std::unique_ptr<File>> files
- = loadFile(ctx, pathOrErr.get(), false);
- for (std::unique_ptr<File> &file : files) {
- if (ctx.logInputFiles())
- diag << file->path() << "\n";
- ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
- }
- }
- return std::error_code();
-}
-
-std::error_code GnuLdDriver::evalLinkerScript(ELFLinkingContext &ctx,
- std::unique_ptr<MemoryBuffer> mb,
- raw_ostream &diag,
- bool nostdlib) {
- // Read the script file from disk and parse.
- StringRef path = mb->getBufferIdentifier();
- auto parser = llvm::make_unique<script::Parser>(std::move(mb));
- if (std::error_code ec = parser->parse())
- return ec;
- script::LinkerScript *script = parser->get();
- if (!script)
- return LinkerScriptReaderError::parse_error;
- // Evaluate script commands.
- // Currently we only recognize this subset of linker script commands.
- for (const script::Command *c : script->_commands) {
- if (auto *input = dyn_cast<script::Input>(c))
- if (std::error_code ec = addFilesFromLinkerScript(
- ctx, path, input->getPaths(), diag))
- return ec;
- if (auto *group = dyn_cast<script::Group>(c)) {
- int origSize = ctx.getNodes().size();
- if (std::error_code ec = addFilesFromLinkerScript(
- ctx, path, group->getPaths(), diag))
- return ec;
- size_t groupSize = ctx.getNodes().size() - origSize;
- ctx.getNodes().push_back(llvm::make_unique<GroupEnd>(groupSize));
- }
- if (auto *searchDir = dyn_cast<script::SearchDir>(c))
- if (!nostdlib)
- ctx.addSearchPath(searchDir->getSearchPath());
- if (auto *entry = dyn_cast<script::Entry>(c))
- ctx.setEntrySymbolName(entry->getEntryName());
- if (auto *output = dyn_cast<script::Output>(c))
- ctx.setOutputPath(output->getOutputFileName());
- if (auto *externs = dyn_cast<script::Extern>(c)) {
- for (auto symbol : *externs) {
- ctx.addInitialUndefinedSymbol(symbol);
- }
- }
- }
- // Transfer ownership of the script to the linking context
- ctx.linkerScriptSema().addLinkerScript(std::move(parser));
- return std::error_code();
-}
-
-bool GnuLdDriver::applyEmulation(llvm::Triple &triple,
- llvm::opt::InputArgList &args,
- raw_ostream &diag) {
- llvm::opt::Arg *arg = args.getLastArg(OPT_m);
- if (!arg)
- return true;
- llvm::Optional<llvm::Triple::ArchType> arch =
- getArchType(triple, arg->getValue());
- if (!arch) {
- diag << "error: unsupported emulation '" << arg->getValue() << "'.\n";
- return false;
- }
- triple.setArch(*arch);
- return true;
-}
-
-void GnuLdDriver::addPlatformSearchDirs(ELFLinkingContext &ctx,
- llvm::Triple &triple,
- llvm::Triple &baseTriple) {
- if (triple.getOS() == llvm::Triple::NetBSD &&
- triple.getArch() == llvm::Triple::x86 &&
- baseTriple.getArch() == llvm::Triple::x86_64) {
- ctx.addSearchPath("=/usr/lib/i386");
- return;
- }
- ctx.addSearchPath("=/usr/lib");
-}
-
-std::unique_ptr<ELFLinkingContext>
-GnuLdDriver::createELFLinkingContext(llvm::Triple triple) {
- std::unique_ptr<ELFLinkingContext> p;
- if ((p = elf::createAArch64LinkingContext(triple))) return p;
- if ((p = elf::createARMLinkingContext(triple))) return p;
- if ((p = elf::createExampleLinkingContext(triple))) return p;
- if ((p = elf::createHexagonLinkingContext(triple))) return p;
- if ((p = elf::createMipsLinkingContext(triple))) return p;
- if ((p = elf::createX86LinkingContext(triple))) return p;
- if ((p = elf::createX86_64LinkingContext(triple))) return p;
- return nullptr;
-}
-
-static llvm::Optional<bool>
-getBool(const llvm::opt::InputArgList &parsedArgs,
- unsigned yesFlag, unsigned noFlag) {
- if (auto *arg = parsedArgs.getLastArg(yesFlag, noFlag))
- return arg->getOption().getID() == yesFlag;
- return llvm::None;
-}
-
-bool GnuLdDriver::parse(llvm::ArrayRef<const char *> args,
- std::unique_ptr<ELFLinkingContext> &context,
- raw_ostream &diag) {
- // Parse command line options using GnuLdOptions.td
- GnuLdOptTable table;
- unsigned missingIndex;
- unsigned missingCount;
-
- llvm::opt::InputArgList parsedArgs =
- table.ParseArgs(args.slice(1), missingIndex, missingCount);
- if (missingCount) {
- diag << "error: missing arg value for '"
- << parsedArgs.getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
- return false;
- }
-
- // Handle --help
- if (parsedArgs.hasArg(OPT_help)) {
- table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false);
- return true;
- }
-
- // Use -target or use default target triple to instantiate LinkingContext
- llvm::Triple baseTriple;
- if (auto *arg = parsedArgs.getLastArg(OPT_target)) {
- baseTriple = llvm::Triple(arg->getValue());
- } else {
- baseTriple = getDefaultTarget(args[0]);
- }
- llvm::Triple triple(baseTriple);
-
- if (!applyEmulation(triple, parsedArgs, diag))
- return false;
-
- std::unique_ptr<ELFLinkingContext> ctx(createELFLinkingContext(triple));
-
- if (!ctx) {
- diag << "unknown target triple\n";
- return false;
- }
-
- // Copy mllvm
- for (auto *arg : parsedArgs.filtered(OPT_mllvm))
- ctx->appendLLVMOption(arg->getValue());
-
- // Ignore unknown arguments.
- for (auto unknownArg : parsedArgs.filtered(OPT_UNKNOWN))
- diag << "warning: ignoring unknown argument: "
- << unknownArg->getValue() << "\n";
-
- // Set sys root path.
- if (auto *arg = parsedArgs.getLastArg(OPT_sysroot))
- ctx->setSysroot(arg->getValue());
-
- // Handle --demangle option(For compatibility)
- if (parsedArgs.hasArg(OPT_demangle))
- ctx->setDemangleSymbols(true);
-
- // Handle --no-demangle option.
- if (parsedArgs.hasArg(OPT_no_demangle))
- ctx->setDemangleSymbols(false);
-
- // Figure out output kind (-r, -static, -shared)
- if (parsedArgs.hasArg(OPT_relocatable)) {
- ctx->setOutputELFType(llvm::ELF::ET_REL);
- ctx->setPrintRemainingUndefines(false);
- ctx->setAllowRemainingUndefines(true);
- }
-
- if (parsedArgs.hasArg(OPT_static)) {
- ctx->setOutputELFType(llvm::ELF::ET_EXEC);
- ctx->setIsStaticExecutable(true);
- }
-
- if (parsedArgs.hasArg(OPT_shared)) {
- ctx->setOutputELFType(llvm::ELF::ET_DYN);
- ctx->setAllowShlibUndefines(true);
- ctx->setUseShlibUndefines(false);
- ctx->setPrintRemainingUndefines(false);
- ctx->setAllowRemainingUndefines(true);
- }
-
- // Handle --stats.
- if (parsedArgs.hasArg(OPT_stats)) {
- ctx->setCollectStats(true);
- }
-
- // Figure out if the output type is nmagic/omagic
- if (auto *arg =
- parsedArgs.getLastArg(OPT_nmagic, OPT_omagic, OPT_no_omagic)) {
- switch (arg->getOption().getID()) {
- case OPT_nmagic:
- ctx->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
- ctx->setIsStaticExecutable(true);
- break;
- case OPT_omagic:
- ctx->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC);
- ctx->setIsStaticExecutable(true);
- break;
- case OPT_no_omagic:
- ctx->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT);
- ctx->setNoAllowDynamicLibraries();
- break;
- }
- }
-
- if (parsedArgs.hasArg(OPT_discard_loc))
- ctx->setDiscardLocals(true);
-
- if (parsedArgs.hasArg(OPT_discard_temp_loc))
- ctx->setDiscardTempLocals(true);
-
- if (parsedArgs.hasArg(OPT_strip_all))
- ctx->setStripSymbols(true);
-
- if (auto *arg = parsedArgs.getLastArg(OPT_soname))
- ctx->setSharedObjectName(arg->getValue());
-
- if (parsedArgs.hasArg(OPT_rosegment))
- ctx->setCreateSeparateROSegment();
-
- if (parsedArgs.hasArg(OPT_no_align_segments))
- ctx->setAlignSegments(false);
-
- if (auto *arg = parsedArgs.getLastArg(OPT_image_base)) {
- uint64_t baseAddress = 0;
- StringRef inputValue = arg->getValue();
- if (inputValue.getAsInteger(0, baseAddress) || !baseAddress) {
- diag << "invalid value for image base " << inputValue << "\n";
- return false;
- }
- ctx->setBaseAddress(baseAddress);
- }
-
- if (parsedArgs.hasArg(OPT_merge_strings))
- ctx->setMergeCommonStrings(true);
-
- if (parsedArgs.hasArg(OPT_t))
- ctx->setLogInputFiles(true);
-
- if (parsedArgs.hasArg(OPT_use_shlib_undefs))
- ctx->setUseShlibUndefines(true);
-
- if (auto val = getBool(parsedArgs, OPT_allow_shlib_undefs,
- OPT_no_allow_shlib_undefs))
- ctx->setAllowShlibUndefines(*val);
-
- if (auto *arg = parsedArgs.getLastArg(OPT_e))
- ctx->setEntrySymbolName(arg->getValue());
-
- if (auto *arg = parsedArgs.getLastArg(OPT_output))
- ctx->setOutputPath(arg->getValue());
-
- if (parsedArgs.hasArg(OPT_noinhibit_exec))
- ctx->setAllowRemainingUndefines(true);
-
- if (auto val = getBool(parsedArgs, OPT_export_dynamic, OPT_no_export_dynamic))
- ctx->setExportDynamic(*val);
-
- if (parsedArgs.hasArg(OPT_allow_multiple_definition))
- ctx->setAllowDuplicates(true);
-
- if (auto *arg = parsedArgs.getLastArg(OPT_dynamic_linker))
- ctx->setInterpreter(arg->getValue());
-
- if (auto *arg = parsedArgs.getLastArg(OPT_init))
- ctx->setInitFunction(arg->getValue());
-
- if (auto *arg = parsedArgs.getLastArg(OPT_fini))
- ctx->setFiniFunction(arg->getValue());
-
- if (auto *arg = parsedArgs.getLastArg(OPT_output_filetype))
- ctx->setOutputFileType(arg->getValue());
-
- // Process ELF/ARM specific options
- bool hasArmTarget1Rel = parsedArgs.hasArg(OPT_target1_rel);
- bool hasArmTarget1Abs = parsedArgs.hasArg(OPT_target1_abs);
- if (triple.getArch() == llvm::Triple::arm) {
- if (hasArmTarget1Rel && hasArmTarget1Abs) {
- diag << "error: options --target1-rel and --target1-abs"
- " can't be used together.\n";
- return false;
- } else if (hasArmTarget1Rel || hasArmTarget1Abs) {
- ctx->setArmTarget1Rel(hasArmTarget1Rel && !hasArmTarget1Abs);
- }
- } else {
- for (const auto *arg : parsedArgs.filtered(OPT_grp_arm_targetopts)) {
- diag << "warning: ignoring unsupported ARM/ELF specific argument: "
- << arg->getSpelling() << "\n";
- }
- }
-
- // Process MIPS specific options.
- if (triple.getArch() == llvm::Triple::mips ||
- triple.getArch() == llvm::Triple::mipsel ||
- triple.getArch() == llvm::Triple::mips64 ||
- triple.getArch() == llvm::Triple::mips64el) {
- ctx->setMipsPcRelEhRel(parsedArgs.hasArg(OPT_pcrel_eh_reloc));
- auto *hashArg = parsedArgs.getLastArg(OPT_hash_style);
- if (hashArg && hashArg->getValue() != StringRef("sysv")) {
- diag << "error: .gnu.hash is incompatible with the MIPS ABI\n";
- return false;
- }
- }
- else {
- for (const auto *arg : parsedArgs.filtered(OPT_grp_mips_targetopts)) {
- diag << "warning: ignoring unsupported MIPS specific argument: "
- << arg->getSpelling() << "\n";
- }
- }
-
- for (auto *arg : parsedArgs.filtered(OPT_L))
- ctx->addSearchPath(arg->getValue());
-
- // Add the default search directory specific to the target.
- if (!parsedArgs.hasArg(OPT_nostdlib))
- addPlatformSearchDirs(*ctx, triple, baseTriple);
-
- for (auto *arg : parsedArgs.filtered(OPT_u))
- ctx->addInitialUndefinedSymbol(arg->getValue());
-
- for (auto *arg : parsedArgs.filtered(OPT_defsym)) {
- StringRef sym, target;
- uint64_t addr;
- if (parseDefsymAsAbsolute(arg->getValue(), sym, addr)) {
- ctx->addInitialAbsoluteSymbol(sym, addr);
- } else if (parseDefsymAsAlias(arg->getValue(), sym, target)) {
- ctx->addAlias(sym, target);
- } else {
- diag << "invalid --defsym: " << arg->getValue() << "\n";
- return false;
- }
- }
-
- for (auto *arg : parsedArgs.filtered(OPT_z)) {
- StringRef opt = arg->getValue();
- if (opt == "muldefs")
- ctx->setAllowDuplicates(true);
- else if (opt == "now")
- ctx->setDTFlag(ELFLinkingContext::DTFlag::DT_NOW);
- else if (opt == "origin")
- ctx->setDTFlag(ELFLinkingContext::DTFlag::DT_ORIGIN);
- else if (opt.startswith("max-page-size")) {
- // Parse -z max-page-size option.
- // The default page size is considered the minimum page size the user
- // can set, check the user input if its atleast the minimum page size
- // and does not exceed the maximum page size allowed for the target.
- uint64_t maxPageSize = 0;
-
- // Error if the page size user set is less than the maximum page size
- // and greather than the default page size and the user page size is a
- // modulo of the default page size.
- if ((!parseMaxPageSize(opt, maxPageSize)) ||
- (maxPageSize < ctx->getPageSize()) ||
- (maxPageSize % ctx->getPageSize())) {
- diag << "invalid option: " << opt << "\n";
- return false;
- }
- ctx->setMaxPageSize(maxPageSize);
- } else {
- diag << "warning: ignoring unknown argument for -z: " << opt << "\n";
- }
- }
-
- for (auto *arg : parsedArgs.filtered(OPT_rpath)) {
- SmallVector<StringRef, 2> rpaths;
- StringRef(arg->getValue()).split(rpaths, ":");
- for (auto path : rpaths)
- ctx->addRpath(path);
- }
-
- for (auto *arg : parsedArgs.filtered(OPT_rpath_link)) {
- SmallVector<StringRef, 2> rpaths;
- StringRef(arg->getValue()).split(rpaths, ":");
- for (auto path : rpaths)
- ctx->addRpathLink(path);
- }
-
- // Enable new dynamic tags.
- if (parsedArgs.hasArg(OPT_enable_newdtags))
- ctx->setEnableNewDtags(true);
-
- // Support --wrap option.
- for (auto *arg : parsedArgs.filtered(OPT_wrap))
- ctx->addWrapForSymbol(arg->getValue());
-
- // Register possible input file parsers.
- ctx->registry().addSupportELFObjects(*ctx);
- ctx->registry().addSupportArchives(ctx->logInputFiles());
- ctx->registry().addSupportYamlFiles();
- if (ctx->allowLinkWithDynamicLibraries())
- ctx->registry().addSupportELFDynamicSharedObjects(*ctx);
-
- // Parse the LLVM options before we process files in case the file handling
- // makes use of things like DEBUG().
- parseLLVMOptions(*ctx);
-
- std::stack<int> groupStack;
- int numfiles = 0;
- bool asNeeded = false;
- bool wholeArchive = false;
-
- // Process files
- for (auto arg : parsedArgs) {
- switch (arg->getOption().getID()) {
- case OPT_no_whole_archive:
- wholeArchive = false;
- break;
-
- case OPT_whole_archive:
- wholeArchive = true;
- break;
-
- case OPT_as_needed:
- asNeeded = true;
- break;
-
- case OPT_no_as_needed:
- asNeeded = false;
- break;
-
- case OPT_start_group:
- groupStack.push(numfiles);
- break;
-
- case OPT_end_group: {
- if (groupStack.empty()) {
- diag << "stray --end-group\n";
- return false;
- }
- int startGroupPos = groupStack.top();
- ctx->getNodes().push_back(
- llvm::make_unique<GroupEnd>(numfiles - startGroupPos));
- groupStack.pop();
- break;
- }
-
- case OPT_INPUT:
- case OPT_l:
- case OPT_T: {
- bool dashL = (arg->getOption().getID() == OPT_l);
- StringRef path = arg->getValue();
-
- ErrorOr<StringRef> pathOrErr = findFile(*ctx, path, dashL);
- if (std::error_code ec = pathOrErr.getError()) {
- auto file = llvm::make_unique<ErrorFile>(path, ec);
- auto node = llvm::make_unique<FileNode>(std::move(file));
- node->setAsNeeded(asNeeded);
- ctx->getNodes().push_back(std::move(node));
- break;
- }
- StringRef realpath = pathOrErr.get();
-
- bool isScript =
- (!path.endswith(".objtxt") && isLinkerScript(realpath, diag));
- if (isScript) {
- if (ctx->logInputFiles())
- diag << path << "\n";
- ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
- MemoryBuffer::getFileOrSTDIN(realpath);
- if (std::error_code ec = mb.getError()) {
- diag << "Cannot open " << path << ": " << ec.message() << "\n";
- return false;
- }
- bool nostdlib = parsedArgs.hasArg(OPT_nostdlib);
- std::error_code ec =
- evalLinkerScript(*ctx, std::move(mb.get()), diag, nostdlib);
- if (ec) {
- diag << path << ": Error parsing linker script: "
- << ec.message() << "\n";
- return false;
- }
- break;
- }
- std::vector<std::unique_ptr<File>> files
- = loadFile(*ctx, realpath, wholeArchive);
- for (std::unique_ptr<File> &file : files) {
- if (ctx->logInputFiles())
- diag << file->path() << "\n";
- auto node = llvm::make_unique<FileNode>(std::move(file));
- node->setAsNeeded(asNeeded);
- ctx->getNodes().push_back(std::move(node));
- }
- numfiles += files.size();
- break;
- }
- }
- }
-
- if (ctx->getNodes().empty()) {
- diag << "No input files\n";
- return false;
- }
-
- // Set default output file name if the output file was not specified.
- if (ctx->outputPath().empty()) {
- switch (ctx->outputFileType()) {
- case LinkingContext::OutputFileType::YAML:
- ctx->setOutputPath("-");
- break;
- default:
- ctx->setOutputPath("a.out");
- break;
- }
- }
-
- // Validate the combination of options used.
- if (!ctx->validate(diag))
- return false;
-
- // Perform linker script semantic actions
- if (auto ec = ctx->linkerScriptSema().perform()) {
- diag << "Error in the linker script's semantics: " << ec.message() << "\n";
- return false;
- }
-
- context.swap(ctx);
- return true;
-}
-
-/// Get the default target triple based on either the program name
-/// (e.g. "x86-ibm-linux-lld") or the primary target llvm was configured for.
-llvm::Triple GnuLdDriver::getDefaultTarget(const char *progName) {
- SmallVector<StringRef, 4> components;
- llvm::SplitString(llvm::sys::path::stem(progName), components, "-");
- // If has enough parts to be start with a triple.
- if (components.size() >= 4) {
- llvm::Triple triple(components[0], components[1], components[2],
- components[3]);
- // If first component looks like an arch.
- if (triple.getArch() != llvm::Triple::UnknownArch)
- return triple;
- }
-
- // Fallback to use whatever default triple llvm was configured for.
- return llvm::Triple(llvm::sys::getDefaultTargetTriple());
-}
diff --git a/lib/Driver/GnuLdOptions.td b/lib/Driver/GnuLdOptions.td
deleted file mode 100644
index 7d850d4d002e..000000000000
--- a/lib/Driver/GnuLdOptions.td
+++ /dev/null
@@ -1,378 +0,0 @@
-include "llvm/Option/OptParser.td"
-
-//===----------------------------------------------------------------------===//
-/// Utility Functions
-//===----------------------------------------------------------------------===//
-// Single and multiple dash options combined
-multiclass smDash<string opt1, string opt2, string help> {
- // Option
- def "" : Separate<["-"], opt1>, HelpText<help>;
- def opt1_eq : Joined<["-"], opt1#"=">,
- Alias<!cast<Option>(opt1)>;
- // Compatibility aliases
- def opt2_dashdash : Separate<["--"], opt2>,
- Alias<!cast<Option>(opt1)>;
- def opt2_dashdash_eq : Joined<["--"], opt2#"=">,
- Alias<!cast<Option>(opt1)>;
-}
-
-// Support -<option>,-<option>=
-multiclass dashEq<string opt1, string opt2, string help> {
- // Option
- def "" : Separate<["-"], opt1>, HelpText<help>;
- // Compatibility aliases
- def opt2_eq : Joined<["-"], opt2#"=">,
- Alias<!cast<Option>(opt1)>;
-}
-
-// Support --<option>,--<option>=
-multiclass mDashEq<string opt1, string help> {
- // Option
- def "" : Separate<["--"], opt1>, HelpText<help>;
- // Compatibility aliases
- def opt2_eq : Joined<["--"], opt1#"=">,
- Alias<!cast<Option>(opt1)>;
-}
-
-//===----------------------------------------------------------------------===//
-/// LLVM and Target options
-//===----------------------------------------------------------------------===//
-def grp_llvmtarget : OptionGroup<"opts">,
- HelpText<"LLVM and Target Options">;
-def mllvm : Separate<["-"], "mllvm">,
- HelpText<"Options to pass to LLVM">, Group<grp_llvmtarget>;
-def target : Separate<["-"], "target">, MetaVarName<"<triple>">,
- HelpText<"Target triple to link for">,
- Group<grp_llvmtarget>;
-
-//===----------------------------------------------------------------------===//
-/// Output Kinds
-//===----------------------------------------------------------------------===//
-def grp_kind : OptionGroup<"outs">,
- HelpText<"OUTPUT KIND">;
-def relocatable : Flag<["-"], "r">,
- HelpText<"Create relocatable object file">, Group<grp_kind>;
-def static : Flag<["-"], "static">,
- HelpText<"Create static executable">, Group<grp_kind>;
-def dynamic : Flag<["-"], "dynamic">,
- HelpText<"Create dynamic executable (default)">,Group<grp_kind>;
-def shared : Flag<["-"], "shared">,
- HelpText<"Create dynamic library">, Group<grp_kind>;
-
-// output kinds - compatibility aliases
-def Bstatic : Flag<["-"], "Bstatic">, Alias<static>;
-def Bshareable : Flag<["-"], "Bshareable">, Alias<shared>;
-
-//===----------------------------------------------------------------------===//
-/// General Options
-//===----------------------------------------------------------------------===//
-def grp_general : OptionGroup<"opts">,
- HelpText<"GENERAL OPTIONS">;
-def output : Separate<["-"], "o">, MetaVarName<"<path>">,
- HelpText<"Path to file to write output">,
- Group<grp_general>;
-def m : JoinedOrSeparate<["-"], "m">, MetaVarName<"<emulation>">,
- HelpText<"Select target emulation">,
- Group<grp_general>;
-def build_id : Flag<["--"], "build-id">,
- HelpText<"Request creation of \".note.gnu.build-id\" ELF note section">,
- Group<grp_general>;
-def sysroot : Joined<["--"], "sysroot=">,
- HelpText<"Set the system root">,
- Group<grp_general>;
-
-
-//===----------------------------------------------------------------------===//
-/// Executable Options
-//===----------------------------------------------------------------------===//
-def grp_main : OptionGroup<"opts">,
- HelpText<"EXECUTABLE OPTIONS">;
-def L : Joined<["-"], "L">, MetaVarName<"<dir>">,
- HelpText<"Directory to search for libraries">,
- Group<grp_main>;
-def l : Joined<["-"], "l">, MetaVarName<"<libName>">,
- HelpText<"Root name of library to use">,
- Group<grp_main>;
-def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
- HelpText<"Retain the executable output file whenever"
- " it is still usable">,
- Group<grp_main>;
-defm e : smDash<"e", "entry",
- "Name of entry point symbol">,
- Group<grp_main>;
-defm init: dashEq<"init", "init",
- "Specify an initializer function">,
- Group<grp_main>;
-defm fini: dashEq<"fini", "fini",
- "Specify a finalizer function">,
- Group<grp_main>;
-def whole_archive: Flag<["--"], "whole-archive">,
- HelpText<"Force load of all members in a static library">,
- Group<grp_main>;
-def no_whole_archive: Flag<["--"], "no-whole-archive">,
- HelpText<"Restores the default behavior of loading archive members">,
- Group<grp_main>;
-def nostdlib : Flag<["-"], "nostdlib">,
- HelpText<"Disable default search path for libraries">,
- Group<grp_main>;
-def image_base : Separate<["--"], "image-base">,
- HelpText<"Set the base address">,
- Group<grp_main>;
-
-//===----------------------------------------------------------------------===//
-/// Static Executable Options
-//===----------------------------------------------------------------------===//
-def grp_staticexec : OptionGroup<"opts">,
- HelpText<"STATIC EXECUTABLE OPTIONS">;
-def nmagic : Flag<["--"], "nmagic">,
- HelpText<"Turn off page alignment of sections,"
- " and disable linking against shared libraries">,
- Group<grp_staticexec>;
-def omagic : Flag<["--"], "omagic">,
- HelpText<"Set the text and data sections to be readable and writable."
- " Also, do not page-align the data segment, and"
- " disable linking against shared libraries.">,
- Group<grp_staticexec>;
-def no_omagic : Flag<["--"], "no-omagic">,
- HelpText<"This option negates most of the effects of the -N option."
- "Disable linking with shared libraries">,
- Group<grp_staticexec>;
-// Compatible Aliases
-def nmagic_alias : Flag<["-"], "n">,
- Alias<nmagic>;
-def omagic_alias : Flag<["-"], "N">,
- Alias<omagic>;
-
-//===----------------------------------------------------------------------===//
-/// Dynamic Library/Executable Options
-//===----------------------------------------------------------------------===//
-def grp_dynlibexec : OptionGroup<"opts">,
- HelpText<"DYNAMIC LIBRARY/EXECUTABLE OPTIONS">;
-def dynamic_linker : Joined<["--"], "dynamic-linker=">,
- HelpText<"Set the path to the dynamic linker">, Group<grp_dynlibexec>;
-// Executable options - compatibility aliases
-def dynamic_linker_alias : Separate<["-", "--"], "dynamic-linker">,
- Alias<dynamic_linker>;
-defm rpath : dashEq<"rpath", "rpath",
- "Add a directory to the runtime library search path">,
- Group<grp_dynlibexec>;
-def rpath_link : Separate<["-"], "rpath-link">,
- HelpText<"Specifies the first set of directories to search">,
- Group<grp_dynlibexec>;
-def export_dynamic : Flag<["-", "--"], "export-dynamic">,
- HelpText<"Add all symbols to the dynamic symbol table"
- " when creating executables">,
- Group<grp_main>;
-def alias_export_dynamic: Flag<["-"], "E">,
- Alias<export_dynamic>;
-def no_export_dynamic : Flag<["--"], "no-export-dynamic">,
- Group<grp_main>;
-
-//===----------------------------------------------------------------------===//
-/// Dynamic Library Options
-//===----------------------------------------------------------------------===//
-def grp_dynlib : OptionGroup<"opts">,
- HelpText<"DYNAMIC LIBRARY OPTIONS">;
-def soname : Joined<["-", "--"], "soname=">,
- HelpText<"Set the internal DT_SONAME field to the specified name">,
- Group<grp_dynlib>;
-def soname_separate : Separate<["-", "--"], "soname">, Alias<soname>;
-def soname_h : Separate<["-"], "h">, Alias<soname>;
-
-//===----------------------------------------------------------------------===//
-/// Resolver Options
-//===----------------------------------------------------------------------===//
-def grp_resolveropt : OptionGroup<"opts">,
- HelpText<"SYMBOL RESOLUTION OPTIONS">;
-defm u : smDash<"u", "undefined",
- "Force symbol to be entered in the output file"
- " as an undefined symbol">,
- Group<grp_resolveropt>;
-def start_group : Flag<["--"], "start-group">,
- HelpText<"Start a group">,
- Group<grp_resolveropt>;
-def alias_start_group: Flag<["-"], "(">,
- Alias<start_group>;
-def end_group : Flag<["--"], "end-group">,
- HelpText<"End a group">,
- Group<grp_resolveropt>;
-def alias_end_group: Flag<["-"], ")">,
- Alias<end_group>;
-def as_needed : Flag<["--"], "as-needed">,
- HelpText<"This option affects ELF DT_NEEDED tags for "
- "dynamic libraries mentioned on the command line">,
- Group<grp_resolveropt>;
-def no_as_needed : Flag<["--"], "no-as-needed">,
- HelpText<"This option restores the default behavior"
- " of adding DT_NEEDED entries">,
- Group<grp_resolveropt>;
-def no_allow_shlib_undefs : Flag<["--"], "no-allow-shlib-undefined">,
- HelpText<"Do not allow undefined symbols from dynamic"
- " library when creating executables">,
- Group<grp_resolveropt>;
-def allow_shlib_undefs : Flag<["-", "--"], "allow-shlib-undefined">,
- HelpText<"Allow undefined symbols from dynamic"
- " library when creating executables">,
- Group<grp_resolveropt>;
-def use_shlib_undefs: Flag<["--"], "use-shlib-undefines">,
- HelpText<"Resolve undefined symbols from dynamic libraries">,
- Group<grp_resolveropt>;
-def allow_multiple_definition: Flag<["--"], "allow-multiple-definition">,
- HelpText<"Allow multiple definitions">,
- Group<grp_resolveropt>;
-defm defsym : mDashEq<"defsym",
- "Create a global symbol in the output file "
- "containing the absolute address given by expression">,
- MetaVarName<"symbol=<expression>">,
- Group<grp_resolveropt>;
-
-//===----------------------------------------------------------------------===//
-/// Custom Options
-//===----------------------------------------------------------------------===//
-def grp_customopts : OptionGroup<"opts">,
- HelpText<"CUSTOM OPTIONS">;
-def disable_newdtags: Flag<["--"], "disable-new-dtags">,
- HelpText<"Disable new dynamic tags">,
- Group<grp_customopts>;
-def enable_newdtags: Flag<["--"], "enable-new-dtags">,
- HelpText<"Enable new dynamic tags">,
- Group<grp_customopts>;
-def rosegment: Flag<["--"], "rosegment">,
- HelpText<"Put read-only non-executable sections in their own segment">,
- Group<grp_customopts>;
-def z : Separate<["-"], "z">,
- HelpText<"Linker Option extensions">,
- Group<grp_customopts>;
-def no_align_segments: Flag<["--"], "no-align-segments">,
- HelpText<"Don't align ELF segments(virtualaddress/fileoffset) to page boundaries">,
- Group<grp_customopts>;
-
-//===----------------------------------------------------------------------===//
-/// Symbol options
-//===----------------------------------------------------------------------===//
-def grp_symbolopts : OptionGroup<"opts">,
- HelpText<"SYMBOL OPTIONS">;
-def demangle : Flag<["--"], "demangle">,
- HelpText<"Demangle C++ symbols">,
- Group<grp_symbolopts>;
-def discard_loc : Flag<["--"], "discard-all">,
- HelpText<"Discard all local symbols">,
- Group<grp_symbolopts>;
-def alias_discard_loc: Flag<["-"], "x">,
- Alias<discard_loc>;
-def discard_temp_loc : Flag<["--"], "discard-locals">,
- HelpText<"Discard temporary local symbols">,
- Group<grp_symbolopts>;
-def alias_discard_temp_loc : Flag<["-"], "X">,
- Alias<discard_temp_loc>;
-def no_demangle : Flag<["--"], "no-demangle">,
- HelpText<"Dont demangle C++ symbols">,
- Group<grp_symbolopts>;
-def strip_all : Flag<["--"], "strip-all">,
- HelpText<"Omit all symbol informations from output">,
- Group<grp_symbolopts>;
-def alias_strip_all : Flag<["-"], "s">,
- Alias<strip_all>;
-defm wrap : smDash<"wrap", "wrap",
- "Use a wrapper function for symbol. Any "
- " undefined reference to symbol will be resolved to "
- "\"__wrap_symbol\". Any undefined reference to \"__real_symbol\""
- " will be resolved to symbol.">,
- MetaVarName<"<symbol>">,
- Group<grp_symbolopts>;
-
-//===----------------------------------------------------------------------===//
-/// Script Options
-//===----------------------------------------------------------------------===//
-def grp_scriptopts : OptionGroup<"opts">,
- HelpText<"SCRIPT OPTIONS">;
-defm T : smDash<"T", "script",
- "Use the given linker script in place of the default script.">,
- Group<grp_scriptopts>;
-
-//===----------------------------------------------------------------------===//
-/// Optimization Options
-//===----------------------------------------------------------------------===//
-def grp_opts : OptionGroup<"opts">,
- HelpText<"OPTIMIZATIONS">;
-def hash_style : Joined <["--"], "hash-style=">,
- HelpText<"Set the type of linker's hash table(s)">,
- Group<grp_opts>;
-def merge_strings : Flag<["--"], "merge-strings">,
- HelpText<"Merge common strings across mergeable sections">,
- Group<grp_opts>;
-def eh_frame_hdr : Flag<["--"], "eh-frame-hdr">,
- HelpText<"Request creation of .eh_frame_hdr section and ELF "
- " PT_GNU_EH_FRAME segment header">,
- Group<grp_opts>;
-
-//===----------------------------------------------------------------------===//
-/// Tracing Options
-//===----------------------------------------------------------------------===//
-def grp_tracingopts : OptionGroup<"opts">,
- HelpText<"TRACING OPTIONS">;
-def t : Flag<["-"], "t">,
- HelpText<"Print the names of the input files as ld processes them">,
- Group<grp_tracingopts>;
-def stats : Flag<["--"], "stats">,
- HelpText<"Print time and memory usage stats">, Group<grp_tracingopts>;
-
-//===----------------------------------------------------------------------===//
-/// Extensions
-//===----------------------------------------------------------------------===//
-def grp_extns : OptionGroup<"opts">,
- HelpText<"Extensions">;
-def output_filetype: Separate<["--"], "output-filetype">,
- HelpText<"Specify yaml to create an output in YAML format">,
- Group<grp_extns>;
-def alias_output_filetype: Joined<["--"], "output-filetype=">,
- Alias<output_filetype>;
-
-//===----------------------------------------------------------------------===//
-/// Target Specific Options
-//===----------------------------------------------------------------------===//
-def grp_targetopts : OptionGroup<"opts">,
- HelpText<"ARCH SPECIFIC OPTIONS">;
-
-//===----------------------------------------------------------------------===//
-/// ARM Target Specific Options
-//===----------------------------------------------------------------------===//
-def grp_arm_targetopts : OptionGroup<"ARM SPECIFIC OPTIONS">,
- Group<grp_targetopts>;
-def target1_rel : Flag<["--"], "target1-rel">,
- Group<grp_arm_targetopts>, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">;
-def target1_abs : Flag<["--"], "target1-abs">,
- Group<grp_arm_targetopts>, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32">;
-
-//===----------------------------------------------------------------------===//
-/// MIPS Target Specific Options
-//===----------------------------------------------------------------------===//
-def grp_mips_targetopts : OptionGroup<"MIPS SPECIFIC OPTIONS">,
- Group<grp_targetopts>;
-def pcrel_eh_reloc : Flag<["-", "--"], "pcrel-eh-reloc">,
- Group<grp_mips_targetopts>,
- HelpText<"Interpret R_MIPS_EH as R_MIPS_PC32">;
-
-//===----------------------------------------------------------------------===//
-/// Ignored options
-//===----------------------------------------------------------------------===//
-def grp_ignored: OptionGroup<"ignored">,
- HelpText<"GNU Options ignored for Compatibility ">;
-def dashg : Flag<["-"], "g">,
- HelpText<"Ignored.">,
- Group<grp_ignored>;
-def Qy : Flag<["-"], "Qy">,
- HelpText<"Ignored for SVR4 Compatibility">,
- Group<grp_ignored>;
-def qmagic : Flag<["-"], "qmagic">,
- HelpText<"Ignored for Linux Compatibility">,
- Group<grp_ignored>;
-def G : Separate<["-"], "G">,
- HelpText<"Ignored for MIPS GNU Linker Compatibility">,
- Group<grp_ignored>;
-
-//===----------------------------------------------------------------------===//
-/// Help
-//===----------------------------------------------------------------------===//
-def help : Flag<["--"], "help">,
- HelpText<"Display this help message">;
diff --git a/lib/Driver/TODO.rst b/lib/Driver/TODO.rst
deleted file mode 100644
index 868eaf02290c..000000000000
--- a/lib/Driver/TODO.rst
+++ /dev/null
@@ -1,99 +0,0 @@
-GNU ld Driver
-~~~~~~~~~~~~~
-
-Missing Options
-###############
-
-* --audit
-* -A,--architecture
-* -b,--format
-* -d,-dc,-dp
-* -P,--depaudit
-* --exclude-libs
-* --exclude-modules-for-implib
-* -E,--export-dynamic,--no-export-dynamic
-* -EB (We probably shouldn't support this)
-* -EL (We probably shouldn't support this)
-* -f,--auxiliary
-* -F,--filter
-* -G,--gpsize
-* -h
-* -i
-* --library
-* -M
-* --print-map
-* -output
-* -O
-* -q,--emit-relocs
-* --force-dynamic
-* --relocatable
-* -R,--just-symbols
-* -s,--strip-all
-* -S,--strip-debug
-* --trace
-* -dT,--default-script
-* -Ur
-* --unique
-* -v,--version,-V
-* -y,--trace-symbol
-* -z (keywords need to be implemented)
-* --accept-unknown-input-arch,--no-accept-unknown-input-arch
-* -Bdynamic,-dy,-call_shared
-* -Bgroup
-* -dn,-non_shared
-* -Bsymbolic
-* -Bsymbolic-functions
-* --dynamic-list
-* --dynamic-list-data
-* --dynamic-list-cpp-new
-* --dynamic-list-cpp-typeinfo
-* --check-sections,--no-check-sections
-* --copy-dt-needed-entries,--no-copy-dt-needed-entires
-* --cref
-* --no-define-common
-* --defsym (only absolute value supported now)
-* --demangle,--no-demangle
-* -I
-* --fatal-warnings,--no-fatal-warnings
-* --force-exe-suffix
-* --gc-sections,--no-gc-sections
-* --print-gc-sections,--no-print-gc-sections
-* --print-output-format
-* --target-help
-* -Map
-* --no-keep-memory
-* --no-undefined,-z defs
-* --allow-shlib-undefined,--no-alow-shlib-undefined
-* --no-undefined-version
-* --default-symver
-* --default-imported-symver
-* --no-warn-mismatch
-* --no-warn-search-mismatch
-* --oformat
-* -pie,--pic-executable
-* --relax,--no-relax
-* --retain-symbols-file
-* --sort-common
-* --sort-section={name,alignment}
-* --split-by-file
-* --split-by-reloc
-* --stats
-* --section-start
-* -T{bss,data,text,{text,rodata,data}-segment}
-* --unresolved-symbols
-* -dll-verbose,--verbose
-* --version-script
-* --warn-common
-* --warn-constructors
-* --warn-multiple-gp
-* --warn-once
-* --warn-section-align
-* --warn-shared-textrel
-* --warn-alternate-em
-* --warn-unresolved-symbols
-* --error-unresolved-symbols
-* --wrap
-* --no-ld-generated-unwind-info
-* --hash-size
-* --reduce-memory-overheads
-* --build-id
diff --git a/lib/Driver/UniversalDriver.cpp b/lib/Driver/UniversalDriver.cpp
deleted file mode 100644
index 3dea7ebfae89..000000000000
--- a/lib/Driver/UniversalDriver.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-//===- lib/Driver/UniversalDriver.cpp -------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Driver for "universal" lld tool which can mimic any linker command line
-/// parsing once it figures out which command line flavor to use.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Driver/Driver.h"
-#include "lld/Config/Version.h"
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lld;
-
-namespace {
-
-// Create enum with OPT_xxx values for each option in GnuLdOptions.td
-enum {
- OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELP, META) \
- OPT_##ID,
-#include "UniversalDriverOptions.inc"
-#undef OPTION
-};
-
-// Create prefix string literals used in GnuLdOptions.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "UniversalDriverOptions.inc"
-#undef PREFIX
-
-// Create table mapping all options defined in GnuLdOptions.td
-static const llvm::opt::OptTable::Info infoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
- { \
- PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
- PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS \
- } \
- ,
-#include "UniversalDriverOptions.inc"
-#undef OPTION
-};
-
-// Create OptTable class for parsing actual command line arguments
-class UniversalDriverOptTable : public llvm::opt::OptTable {
-public:
- UniversalDriverOptTable()
- : OptTable(infoTable) {}
-};
-
-enum class Flavor {
- invalid,
- old_gnu_ld, // -flavor old-gnu
- gnu_ld, // -flavor gnu
- win_link, // -flavor link
- darwin_ld, // -flavor darwin
- core // -flavor core OR -core
-};
-
-struct ProgramNameParts {
- StringRef _target;
- StringRef _flavor;
-};
-
-} // anonymous namespace
-
-static Flavor strToFlavor(StringRef str) {
- return llvm::StringSwitch<Flavor>(str)
- .Case("old-gnu", Flavor::old_gnu_ld)
- .Case("gnu", Flavor::gnu_ld)
- .Case("ld.lld", Flavor::gnu_ld)
- .Case("link", Flavor::win_link)
- .Case("lld-link", Flavor::win_link)
- .Case("darwin", Flavor::darwin_ld)
- .Case("core", Flavor::core)
- .Case("ld", Flavor::gnu_ld)
- .Default(Flavor::invalid);
-}
-
-static ProgramNameParts parseProgramName(StringRef programName) {
- SmallVector<StringRef, 3> components;
- llvm::SplitString(programName, components, "-");
- ProgramNameParts ret;
-
- using std::begin;
- using std::end;
-
- // Erase any lld components.
- components.erase(std::remove(components.begin(), components.end(), "lld"),
- components.end());
-
- // Find the flavor component.
- auto flIter = std::find_if(components.begin(), components.end(),
- [](StringRef str) -> bool {
- return strToFlavor(str) != Flavor::invalid;
- });
-
- if (flIter != components.end()) {
- ret._flavor = *flIter;
- components.erase(flIter);
- }
-
- // Any remaining component must be the target.
- if (components.size() == 1)
- ret._target = components[0];
-
- return ret;
-}
-
-// Removes the argument from argv along with its value, if exists, and updates
-// argc.
-static void removeArg(llvm::opt::Arg *arg,
- llvm::MutableArrayRef<const char *> &args) {
- unsigned int numToRemove = arg->getNumValues() + 1;
- auto sub = args.slice(arg->getIndex() + 1);
- std::rotate(sub.begin(), sub.begin() + numToRemove, sub.end());
- args = args.drop_back(numToRemove);
-}
-
-static Flavor getFlavor(llvm::MutableArrayRef<const char *> &args,
- const llvm::opt::InputArgList &parsedArgs) {
- if (llvm::opt::Arg *argCore = parsedArgs.getLastArg(OPT_core)) {
- removeArg(argCore, args);
- return Flavor::core;
- }
- if (llvm::opt::Arg *argFlavor = parsedArgs.getLastArg(OPT_flavor)) {
- removeArg(argFlavor, args);
- return strToFlavor(argFlavor->getValue());
- }
-
-#if LLVM_ON_UNIX
- if (llvm::sys::path::filename(args[0]).equals("ld")) {
-#if __APPLE__
- // On a Darwin systems, if linker binary is named "ld", use Darwin driver.
- return Flavor::darwin_ld;
-#endif
- // On a ELF based systems, if linker binary is named "ld", use gnu driver.
- return Flavor::gnu_ld;
- }
-#endif
-
- StringRef name = llvm::sys::path::filename(args[0]);
- if (name.endswith_lower(".exe"))
- name = llvm::sys::path::stem(name);
- return strToFlavor(parseProgramName(name)._flavor);
-}
-
-namespace lld {
-
-bool UniversalDriver::link(llvm::MutableArrayRef<const char *> args,
- raw_ostream &diagnostics) {
- // Parse command line options using GnuLdOptions.td
- UniversalDriverOptTable table;
- unsigned missingIndex;
- unsigned missingCount;
-
- // Program name
- StringRef programName = llvm::sys::path::stem(args[0]);
-
- llvm::opt::InputArgList parsedArgs =
- table.ParseArgs(args.slice(1), missingIndex, missingCount);
-
- if (missingCount) {
- diagnostics << "error: missing arg value for '"
- << parsedArgs.getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
- return false;
- }
-
- // Handle -help
- if (parsedArgs.getLastArg(OPT_help)) {
- table.PrintHelp(llvm::outs(), programName.data(), "LLVM Linker", false);
- return true;
- }
-
- // Handle -version
- if (parsedArgs.getLastArg(OPT_version)) {
- diagnostics << "LLVM Linker Version: " << getLLDVersion()
- << getLLDRepositoryVersion() << "\n";
- return true;
- }
-
- Flavor flavor = getFlavor(args, parsedArgs);
-
- // Switch to appropriate driver.
- switch (flavor) {
- case Flavor::old_gnu_ld:
- return GnuLdDriver::linkELF(args, diagnostics);
- case Flavor::gnu_ld:
- elf2::link(args);
- return true;
- case Flavor::darwin_ld:
- return DarwinLdDriver::linkMachO(args, diagnostics);
- case Flavor::win_link:
- coff::link(args);
- return true;
- case Flavor::core:
- return CoreDriver::link(args, diagnostics);
- case Flavor::invalid:
- diagnostics << "Select the appropriate flavor\n";
- table.PrintHelp(llvm::outs(), programName.data(), "LLVM Linker", false);
- return false;
- }
- llvm_unreachable("Unrecognised flavor");
-}
-
-} // end namespace lld
diff --git a/lib/Driver/UniversalDriverOptions.td b/lib/Driver/UniversalDriverOptions.td
deleted file mode 100644
index 14abc9ce9911..000000000000
--- a/lib/Driver/UniversalDriverOptions.td
+++ /dev/null
@@ -1,19 +0,0 @@
-include "llvm/Option/OptParser.td"
-
-// Select an optional flavor
-def flavor: Separate<["-"], "flavor">,
- HelpText<"Flavor for linking, options are gnu/darwin/link">;
-
-// Select the core flavor
-def core : Flag<["-"], "core">,
- HelpText<"CORE linking">;
-
-def target: Separate<["-"], "target">,
- HelpText<"Select the target">;
-
-def version: Flag<["-"], "version">,
- HelpText<"Display the version">;
-
-// Help message
-def help : Flag<["-"], "help">,
- HelpText<"Display this help message">;
diff --git a/lib/ReaderWriter/CMakeLists.txt b/lib/ReaderWriter/CMakeLists.txt
index 2bb5655b9e35..4408d9c18b8b 100644
--- a/lib/ReaderWriter/CMakeLists.txt
+++ b/lib/ReaderWriter/CMakeLists.txt
@@ -1,4 +1,3 @@
-add_subdirectory(ELF)
add_subdirectory(MachO)
add_subdirectory(YAML)
@@ -7,9 +6,7 @@ if (MSVC)
endif()
add_lld_library(lldReaderWriter
- CoreLinkingContext.cpp
FileArchive.cpp
- LinkerScript.cpp
ADDITIONAL_HEADER_DIRS
${LLD_INCLUDE_DIR}/lld/ReaderWriter
diff --git a/lib/ReaderWriter/CoreLinkingContext.cpp b/lib/ReaderWriter/CoreLinkingContext.cpp
deleted file mode 100644
index 02f6263c0c3f..000000000000
--- a/lib/ReaderWriter/CoreLinkingContext.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//===- lib/ReaderWriter/CoreLinkingContext.cpp ----------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/CoreLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-
-using namespace lld;
-
-namespace {
-
-class OrderPass : public Pass {
-public:
- /// Sorts atoms by position
- std::error_code perform(SimpleFile &file) override {
- SimpleFile::DefinedAtomRange defined = file.definedAtoms();
- std::sort(defined.begin(), defined.end(), DefinedAtom::compareByPosition);
- return std::error_code();
- }
-};
-
-} // anonymous namespace
-
-CoreLinkingContext::CoreLinkingContext() {}
-
-bool CoreLinkingContext::validateImpl(raw_ostream &) {
- _writer = createWriterYAML(*this);
- return true;
-}
-
-void CoreLinkingContext::addPasses(PassManager &pm) {
- for (StringRef name : _passNames) {
- (void)name;
- assert(name == "order" && "bad pass name");
- pm.add(llvm::make_unique<OrderPass>());
- }
-}
-
-Writer &CoreLinkingContext::writer() const { return *_writer; }
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
deleted file mode 100644
index 73864d2b4c38..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h ---------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef AARCH64_DYNAMIC_LIBRARY_WRITER_H
-#define AARCH64_DYNAMIC_LIBRARY_WRITER_H
-
-#include "AArch64LinkingContext.h"
-#include "AArch64TargetHandler.h"
-#include "DynamicLibraryWriter.h"
-
-namespace lld {
-namespace elf {
-
-class AArch64DynamicLibraryWriter : public DynamicLibraryWriter<ELF64LE> {
-public:
- AArch64DynamicLibraryWriter(AArch64LinkingContext &ctx,
- TargetLayout<ELF64LE> &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-};
-
-AArch64DynamicLibraryWriter::AArch64DynamicLibraryWriter(
- AArch64LinkingContext &ctx, TargetLayout<ELF64LE> &layout)
- : DynamicLibraryWriter(ctx, layout) {}
-
-void AArch64DynamicLibraryWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter::createImplicitFiles(result);
- auto gotFile = llvm::make_unique<SimpleFile>("GOTFile");
- gotFile->addAtom(*new (gotFile->allocator()) GlobalOffsetTableAtom(*gotFile));
- gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile));
- result.push_back(std::move(gotFile));
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp
deleted file mode 100644
index 9a9ec6cba12b..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AArch64LinkingContext.h"
-#include "AArch64ExecutableWriter.h"
-#include "AArch64TargetHandler.h"
-#include "AArch64SectionChunks.h"
-
-namespace lld {
-namespace elf {
-
-AArch64ExecutableWriter::AArch64ExecutableWriter(AArch64LinkingContext &ctx,
- AArch64TargetLayout &layout)
- : ExecutableWriter(ctx, layout), _targetLayout(layout) {}
-
-void AArch64ExecutableWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter::createImplicitFiles(result);
- auto gotFile = llvm::make_unique<SimpleFile>("GOTFile");
- gotFile->addAtom(*new (gotFile->allocator()) GlobalOffsetTableAtom(*gotFile));
- if (this->_ctx.isDynamic())
- gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile));
- result.push_back(std::move(gotFile));
-}
-
-void AArch64ExecutableWriter::buildDynamicSymbolTable(const File &file) {
- for (auto sec : this->_layout.sections()) {
- if (auto section = dyn_cast<AtomSection<ELF64LE>>(sec)) {
- for (const auto &atom : section->atoms()) {
- // Add all globals GOT symbols (in both .got and .got.plt sections)
- // on dynamic symbol table.
- for (const auto &section : _targetLayout.getGOTSections()) {
- if (section->hasGlobalGOTEntry(atom->_atom))
- _dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
- atom->_virtualAddr, atom);
- }
- }
- }
- }
-
- ExecutableWriter<ELF64LE>::buildDynamicSymbolTable(file);
-}
-
-} // namespace elf
-} // namespace lld
-
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h b/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
deleted file mode 100644
index eef825040ffa..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef AARCH64_EXECUTABLE_WRITER_H
-#define AARCH64_EXECUTABLE_WRITER_H
-
-#include "ExecutableWriter.h"
-
-namespace lld {
-namespace elf {
-
-class AArch64TargetLayout;
-class AArch64LinkingContext;
-
-class AArch64ExecutableWriter : public ExecutableWriter<ELF64LE> {
-public:
- AArch64ExecutableWriter(AArch64LinkingContext &ctx,
- AArch64TargetLayout &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void buildDynamicSymbolTable(const File &file) override;
-
-private:
- AArch64TargetLayout &_targetLayout;
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
deleted file mode 100644
index ba883f7f59db..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AArch64LinkingContext.h"
-#include "AArch64RelocationPass.h"
-#include "AArch64TargetHandler.h"
-
-using namespace lld;
-using namespace lld::elf;
-
-std::unique_ptr<ELFLinkingContext>
-elf::createAArch64LinkingContext(llvm::Triple triple) {
- if (triple.getArch() == llvm::Triple::aarch64)
- return llvm::make_unique<AArch64LinkingContext>(triple);
- return nullptr;
-}
-
-AArch64LinkingContext::AArch64LinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, std::unique_ptr<TargetHandler>(
- new AArch64TargetHandler(*this))) {}
-
-void AArch64LinkingContext::addPasses(PassManager &pm) {
- auto pass = createAArch64RelocationPass(*this);
- if (pass)
- pm.add(std::move(pass));
- ELFLinkingContext::addPasses(pm);
-}
-
-static const Registry::KindStrings kindStrings[] = {
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-#include "llvm/Support/ELFRelocs/AArch64.def"
-#undef ELF_RELOC
- LLD_KIND_STRING_END
-};
-
-void AArch64LinkingContext::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::AArch64, kindStrings);
-}
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h b/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h
deleted file mode 100644
index 25a173158318..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_LINKING_CONTEXT_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-
-enum {
- /// \brief The offset to add operation for a R_AARCH64_ADR_GOT_PAGE
- ADD_AARCH64_GOTRELINDEX = 0xE000,
-};
-
-class AArch64LinkingContext final : public ELFLinkingContext {
-public:
- int getMachineType() const override { return llvm::ELF::EM_AARCH64; }
- AArch64LinkingContext(llvm::Triple);
-
- void addPasses(PassManager &) override;
- void registerRelocationNames(Registry &r) override;
-
- uint64_t getBaseAddress() const override {
- if (_baseAddress == 0)
- return 0x400000;
- return _baseAddress;
- }
-
- bool isDynamicRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::AArch64);
- switch (r.kindValue()) {
- case llvm::ELF::R_AARCH64_COPY:
- case llvm::ELF::R_AARCH64_GLOB_DAT:
- case llvm::ELF::R_AARCH64_RELATIVE:
- case llvm::ELF::R_AARCH64_TLS_DTPREL64:
- case llvm::ELF::R_AARCH64_TLS_DTPMOD64:
- case llvm::ELF::R_AARCH64_TLS_TPREL64:
- case llvm::ELF::R_AARCH64_TLSDESC:
- case llvm::ELF::R_AARCH64_IRELATIVE:
- return true;
- default:
- return false;
- }
- }
-
- bool isCopyRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::AArch64);
- if (r.kindValue() == llvm::ELF::R_AARCH64_COPY)
- return true;
- return false;
- }
-
- bool isPLTRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::AArch64);
- switch (r.kindValue()) {
- case llvm::ELF::R_AARCH64_JUMP_SLOT:
- case llvm::ELF::R_AARCH64_IRELATIVE:
- return true;
- default:
- return false;
- }
- }
-
- bool isRelativeReloc(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::AArch64);
- switch (r.kindValue()) {
- case llvm::ELF::R_AARCH64_IRELATIVE:
- case llvm::ELF::R_AARCH64_RELATIVE:
- return true;
- default:
- return false;
- }
- }
-
- /// \brief The path to the dynamic interpreter
- StringRef getDefaultInterpreter() const override {
- return "/lib/ld-linux-aarch64.so.1";
- }
-};
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
deleted file mode 100644
index ac7c769ec26d..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
+++ /dev/null
@@ -1,556 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp ----------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AArch64TargetHandler.h"
-#include "AArch64LinkingContext.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/MathExtras.h"
-
-#define DEBUG_TYPE "AArch64"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm;
-using namespace llvm::support::endian;
-
-static int64_t page(int64_t v) { return v & ~int64_t(0xFFF); }
-
-/// \brief Check X is in the interval (-2^(bits-1), 2^bits]
-static bool withinSignedUnsignedRange(int64_t X, int bits) {
- return isIntN(bits - 1, X) || isUIntN(bits, X);
-}
-
-/// \brief R_AARCH64_ABS64 - word64: S + A
-static void relocR_AARCH64_ABS64(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A) {
- int64_t result = (int64_t)S + A;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- write64le(location, result | read64le(location));
-}
-
-/// \brief R_AARCH64_ABS32 - word32: S + A
-static std::error_code relocR_AARCH64_ABS32(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int64_t result = S + A;
- if (!withinSignedUnsignedRange(result, 32))
- return make_out_of_range_reloc_error();
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_ABS16 - word16: S + A
-static std::error_code relocR_AARCH64_ABS16(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int64_t result = S + A;
- if (!withinSignedUnsignedRange(result, 16))
- return make_out_of_range_reloc_error();
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- write16le(location, result | read16le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_PREL64 - word64: S + A - P
-static void relocR_AARCH64_PREL64(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int64_t result = S + A - P;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- write64le(location, result + read64le(location));
-}
-
-/// \brief R_AARCH64_PREL32 - word32: S + A - P
-static std::error_code relocR_AARCH64_PREL32(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int64_t result = S + A - P;
- // ELF for the ARM 64-bit architecture manual states the overflow
- // for R_AARCH64_PREL32 to be -2^(-31) <= X < 2^32
- if (!withinSignedUnsignedRange(result, 32))
- return make_out_of_range_reloc_error();
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- write32le(location, result + read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_PREL16 - word16: S + A - P
-static std::error_code relocR_AARCH64_PREL16(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int64_t result = S + A - P;
- if (!withinSignedUnsignedRange(result, 16))
- return make_out_of_range_reloc_error();
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- write16le(location, result + read16le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_ADR_PREL_PG_HI21 - Page(S+A) - Page(P)
-static std::error_code relocR_AARCH64_ADR_PREL_PG_HI21(uint8_t *location,
- uint64_t P, uint64_t S,
- int64_t A) {
- int64_t result = page(S + A) - page(P);
- if (!isInt<32>(result))
- return make_out_of_range_reloc_error();
- result = result >> 12;
- uint32_t immlo = result & 0x3;
- uint32_t immhi = result & 0x1FFFFC;
- immlo = immlo << 29;
- immhi = immhi << 3;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
- llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, immlo | immhi | read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_ADR_PREL_LO21 - S + A - P
-static std::error_code relocR_AARCH64_ADR_PREL_LO21(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- uint64_t result = S + A - P;
- if (!isInt<20>(result))
- return make_out_of_range_reloc_error();
- uint32_t immlo = result & 0x3;
- uint32_t immhi = result & 0x1FFFFC;
- immlo = immlo << 29;
- immhi = immhi << 3;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
- llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, immlo | immhi | read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_ADD_ABS_LO12_NC
-static void relocR_AARCH64_ADD_ABS_LO12_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)((S + A) & 0xFFF);
- result <<= 10;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-/// \brief R_AARCH64_CALL26 and R_AARCH64_JUMP26
-static std::error_code relocJump26(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A) {
- int64_t result = S + A - P;
- if (!isInt<27>(result))
- return make_out_of_range_reloc_error();
- result &= 0x0FFFFFFC;
- result >>= 2;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_CONDBR19
-static std::error_code relocR_AARCH64_CONDBR19(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int64_t result = S + A - P;
- if (!isInt<20>(result))
- return make_out_of_range_reloc_error();
- result &= 0x01FFFFC;
- result <<= 3;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_LDST8_ABS_LO12_NC - S + A
-static void relocR_AARCH64_LDST8_ABS_LO12_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)((S + A) & 0xFFF);
- result <<= 10;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-/// \brief R_AARCH64_LDST16_ABS_LO12_NC
-static void relocR_AARCH64_LDST16_ABS_LO12_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)(S + A);
- result &= 0x0FFC;
- result <<= 9;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-/// \brief R_AARCH64_LDST32_ABS_LO12_NC
-static void relocR_AARCH64_LDST32_ABS_LO12_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)(S + A);
- result &= 0x0FFC;
- result <<= 8;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-/// \brief R_AARCH64_LDST64_ABS_LO12_NC
-static void relocR_AARCH64_LDST64_ABS_LO12_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)(S + A);
- result &= 0x0FF8;
- result <<= 7;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-/// \brief R_AARCH64_LDST128_ABS_LO12_NC
-static void relocR_AARCH64_LDST128_ABS_LO12_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)(S + A);
- result &= 0x0FF8;
- result <<= 6;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-static std::error_code relocR_AARCH64_ADR_GOT_PAGE(uint8_t *location,
- uint64_t P, uint64_t S,
- int64_t A) {
- uint64_t result = page(S + A) - page(P);
- if (!isInt<32>(result))
- return make_out_of_range_reloc_error();
- result = (result >> 12) & 0x3FFFF;
- uint32_t immlo = result & 0x3;
- uint32_t immhi = result & 0x1FFFFC;
- immlo = immlo << 29;
- immhi = immhi << 3;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
- llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, immlo | immhi | read32le(location));
- return std::error_code();
-}
-
-// R_AARCH64_LD64_GOT_LO12_NC
-static std::error_code relocR_AARCH64_LD64_GOT_LO12_NC(uint8_t *location,
- uint64_t P, uint64_t S,
- int64_t A) {
- int32_t result = S + A;
- DEBUG(llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- if ((result & 0x7) != 0)
- return make_unaligned_range_reloc_error();
- result &= 0xFF8;
- result <<= 7;
- write32le(location, result | read32le(location));
- return std::error_code();
-}
-
-// ADD_AARCH64_GOTRELINDEX
-static void relocADD_AARCH64_GOTRELINDEX(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = S + A;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- result &= 0xFFF;
- result <<= 10;
- write32le(location, result | read32le(location));
-}
-
-// R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
-static std::error_code relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(uint8_t *location,
- uint64_t P,
- uint64_t S,
- int64_t A) {
- int64_t result = page(S + A) - page(P);
- if (!isInt<32>(result))
- return make_out_of_range_reloc_error();
- result >>= 12;
- uint32_t immlo = result & 0x3;
- uint32_t immhi = result & 0x1FFFFC;
- immlo = immlo << 29;
- immhi = immhi << 3;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
- llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, immlo | immhi | read32le(location));
- return std::error_code();
-}
-
-// R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
-static void relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(uint8_t *location,
- uint64_t P, uint64_t S,
- int64_t A) {
- int32_t result = S + A;
- result &= 0xFF8;
- result <<= 7;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-/// \brief R_AARCH64_TLSLE_ADD_TPREL_HI12
-static std::error_code relocR_AARCH64_TLSLE_ADD_TPREL_HI12(uint8_t *location,
- uint64_t P,
- uint64_t S,
- int64_t A) {
- int64_t result = S + A;
- if (!isUInt<24>(result))
- return make_out_of_range_reloc_error();
- result &= 0x0FFF000;
- result >>= 2;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
-static void relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(uint8_t *location,
- uint64_t P, uint64_t S,
- int64_t A) {
- int32_t result = S + A;
- result &= 0x0FFF;
- result <<= 10;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-/// \brief R_AARCH64_TLSDESC_ADR_PAGE21 - Page(G(GTLSDESC(S+A))) - Page(P)
-static std::error_code relocR_AARCH64_TLSDESC_ADR_PAGE21(uint8_t *location,
- uint64_t P, uint64_t S,
- int64_t A) {
- int64_t result = page(S + A) - page(P);
- if (!isInt<32>(result))
- return make_out_of_range_reloc_error();
- result = result >> 12;
- uint32_t immlo = result & 0x3;
- uint32_t immhi = result & 0x1FFFFC;
- immlo = immlo << 29;
- immhi = immhi << 3;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
- llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, immlo | immhi | read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_TLSDESC_LD64_LO12_NC - G(GTLSDESC(S+A)) -> S + A
-static std::error_code relocR_AARCH64_TLSDESC_LD64_LO12_NC(uint8_t *location,
- uint64_t P,
- uint64_t S,
- int64_t A) {
- int32_t result = S + A;
- DEBUG(llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- if ((result & 0x7) != 0)
- return make_unaligned_range_reloc_error();
- result &= 0xFF8;
- result <<= 7;
- write32le(location, result | read32le(location));
- return std::error_code();
-}
-
-/// \brief R_AARCH64_TLSDESC_ADD_LO12_NC - G(GTLSDESC(S+A)) -> S + A
-static void relocR_AARCH64_TLSDESC_ADD_LO12_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)((S + A) & 0xFFF);
- result <<= 10;
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: " << Twine::utohexstr(S);
- llvm::dbgs() << " A: " << Twine::utohexstr(A);
- llvm::dbgs() << " P: " << Twine::utohexstr(P);
- llvm::dbgs() << " result: " << Twine::utohexstr(result) << "\n");
- write32le(location, result | read32le(location));
-}
-
-std::error_code AArch64TargetRelocationHandler::applyRelocation(
- ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
- const Reference &ref) const {
- uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *loc = atomContent + ref.offsetInAtom();
- uint64_t target = writer.addressOfAtom(ref.target());
- uint64_t reloc = atom._virtualAddr + ref.offsetInAtom();
- int64_t addend = ref.addend();
-
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return std::error_code();
- assert(ref.kindArch() == Reference::KindArch::AArch64);
- switch (ref.kindValue()) {
- case R_AARCH64_NONE:
- break;
- case R_AARCH64_ABS64:
- relocR_AARCH64_ABS64(loc, reloc, target, addend);
- break;
- case R_AARCH64_ABS32:
- return relocR_AARCH64_ABS32(loc, reloc, target, addend);
- case R_AARCH64_ABS16:
- return relocR_AARCH64_ABS16(loc, reloc, target, addend);
- case R_AARCH64_PREL64:
- relocR_AARCH64_PREL64(loc, reloc, target, addend);
- break;
- case R_AARCH64_PREL32:
- return relocR_AARCH64_PREL32(loc, reloc, target, addend);
- case R_AARCH64_PREL16:
- return relocR_AARCH64_PREL16(loc, reloc, target, addend);
- case R_AARCH64_ADR_PREL_PG_HI21:
- return relocR_AARCH64_ADR_PREL_PG_HI21(loc, reloc, target, addend);
- case R_AARCH64_ADR_PREL_LO21:
- return relocR_AARCH64_ADR_PREL_LO21(loc, reloc, target, addend);
- case R_AARCH64_ADD_ABS_LO12_NC:
- relocR_AARCH64_ADD_ABS_LO12_NC(loc, reloc, target, addend);
- break;
- case R_AARCH64_CALL26:
- case R_AARCH64_JUMP26:
- return relocJump26(loc, reloc, target, addend);
- case R_AARCH64_CONDBR19:
- return relocR_AARCH64_CONDBR19(loc, reloc, target, addend);
- case R_AARCH64_ADR_GOT_PAGE:
- return relocR_AARCH64_ADR_GOT_PAGE(loc, reloc, target, addend);
- case R_AARCH64_LD64_GOT_LO12_NC:
- return relocR_AARCH64_LD64_GOT_LO12_NC(loc, reloc, target, addend);
- case R_AARCH64_LDST8_ABS_LO12_NC:
- relocR_AARCH64_LDST8_ABS_LO12_NC(loc, reloc, target, addend);
- break;
- case R_AARCH64_LDST16_ABS_LO12_NC:
- relocR_AARCH64_LDST16_ABS_LO12_NC(loc, reloc, target, addend);
- break;
- case R_AARCH64_LDST32_ABS_LO12_NC:
- relocR_AARCH64_LDST32_ABS_LO12_NC(loc, reloc, target, addend);
- break;
- case R_AARCH64_LDST64_ABS_LO12_NC:
- relocR_AARCH64_LDST64_ABS_LO12_NC(loc, reloc, target, addend);
- break;
- case R_AARCH64_LDST128_ABS_LO12_NC:
- relocR_AARCH64_LDST128_ABS_LO12_NC(loc, reloc, target, addend);
- break;
- case ADD_AARCH64_GOTRELINDEX:
- relocADD_AARCH64_GOTRELINDEX(loc, reloc, target, addend);
- break;
- case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
- return relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(loc, reloc, target, addend);
- case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
- relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(loc, reloc, target, addend);
- break;
- case R_AARCH64_TLSLE_ADD_TPREL_HI12:
- case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: {
- auto tpoffset = _layout.getTPOffset();
- if (ref.kindValue() == R_AARCH64_TLSLE_ADD_TPREL_HI12)
- return relocR_AARCH64_TLSLE_ADD_TPREL_HI12(loc, reloc, target + tpoffset,
- addend);
- else
- relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(loc, reloc, target + tpoffset,
- addend);
- } break;
- case R_AARCH64_TLSDESC_ADR_PAGE21:
- return relocR_AARCH64_TLSDESC_ADR_PAGE21(loc, reloc, target, addend);
- case R_AARCH64_TLSDESC_LD64_LO12_NC:
- return relocR_AARCH64_TLSDESC_LD64_LO12_NC(loc, reloc, target, addend);
- case R_AARCH64_TLSDESC_ADD_LO12_NC:
- relocR_AARCH64_TLSDESC_ADD_LO12_NC(loc, reloc, target, addend);
- break;
- case R_AARCH64_TLSDESC_CALL:
- // Relaxation only to optimize TLS access. Ignore for now.
- break;
- // Runtime only relocations. Ignore here.
- case R_AARCH64_RELATIVE:
- case R_AARCH64_IRELATIVE:
- case R_AARCH64_JUMP_SLOT:
- case R_AARCH64_GLOB_DAT:
- case R_AARCH64_TLS_TPREL64:
- case R_AARCH64_TLSDESC:
- break;
- default:
- return make_unhandled_reloc_error();
- }
- return std::error_code();
-}
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h
deleted file mode 100644
index 8cde7a03e51a..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h ------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef AARCH64_RELOCATION_HANDLER_H
-#define AARCH64_RELOCATION_HANDLER_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-class AArch64TargetLayout;
-
-class AArch64TargetRelocationHandler final : public TargetRelocationHandler {
-public:
- AArch64TargetRelocationHandler(AArch64TargetLayout &layout)
- : _layout(layout) {}
-
- std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const AtomLayout &,
- const Reference &) const override;
-
-private:
- AArch64TargetLayout &_layout;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // AArch64_RELOCATION_HANDLER_H
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
deleted file mode 100644
index 4d94a793665c..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Defines the relocation processing pass for AArch64. This includes
-/// GOT and PLT entries, TLS, COPY, and ifunc.
-///
-/// This also includes additional behavior that gnu-ld and gold implement but
-/// which is not specified anywhere.
-///
-//===----------------------------------------------------------------------===//
-
-#include "AArch64RelocationPass.h"
-#include "AArch64LinkingContext.h"
-#include "Atoms.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::ELF;
-
-// .got values
-static const uint8_t AArch64GotAtomContent[8] = {0};
-
-// tls descriptor .got values, the layout is:
-// struct tlsdesc {
-// ptrdiff_t (*entry) (struct tlsdesc *);
-// void *arg;
-// };
-static const uint8_t AArch64TlsdescGotAtomContent[16] = {0};
-
-// .plt value (entry 0)
-static const uint8_t AArch64Plt0AtomContent[32] = {
- 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]!
- 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(eh_frame)
- 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16,#offset]
- 0x10, 0x02, 0x00, 0x91, // add x16, x16, #offset
- 0x20, 0x02, 0x1f, 0xd6, // br x17
- 0x1f, 0x20, 0x03, 0xd5, // nop
- 0x1f, 0x20, 0x03, 0xd5, // nop
- 0x1f, 0x20, 0x03, 0xd5 // nop
-};
-
-// .plt values (other entries)
-static const uint8_t AArch64PltAtomContent[16] = {
- 0x10, 0x00, 0x00, 0x90, // adrp x16, PAGE(<GLOBAL_OFFSET_TABLE>)
- 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16,#offset]
- 0x10, 0x02, 0x00, 0x91, // add x16, x16, #offset
- 0x20, 0x02, 0x1f, 0xd6 // br x17
-};
-
-// .plt tlsdesc values
-static const uint8_t AArch64PltTlsdescAtomContent[32] = {
- 0xe2, 0x0f, 0xbf, 0xa9, // stp x2, x3, [sp, #-16]
- 0x02, 0x00, 0x00, 0x90, // adpr x2, 0
- 0x03, 0x00, 0x00, 0x90, // adpr x3, 0
- 0x42, 0x00, 0x40, 0xf9, // ldr x2, [x2, #0]
- 0x63, 0x00, 0x00, 0x91, // add x3, x3, 0
- 0x40, 0x00, 0x1f, 0xd6, // br x2
- 0x1f, 0x20, 0x03, 0xd5, // nop
- 0x1f, 0x20, 0x03, 0xd5 // nop
-};
-
-namespace {
-
-/// \brief Atoms that are used by AArch64 dynamic linking
-class AArch64GOTAtom : public GOTAtom {
-public:
- AArch64GOTAtom(const File &f) : GOTAtom(f, ".got") {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return ArrayRef<uint8_t>(AArch64GotAtomContent, 8);
- }
-
-protected:
- // Constructor for AArch64GOTAtom
- AArch64GOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
-};
-
-class AArch64GOTPLTAtom : public AArch64GOTAtom {
-public:
- AArch64GOTPLTAtom(const File &f) : AArch64GOTAtom(f, ".got.plt") {}
-};
-
-class AArch64TLSDESCGOTAtom : public AArch64GOTPLTAtom {
-public:
- AArch64TLSDESCGOTAtom(const File &f) : AArch64GOTPLTAtom(f) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return ArrayRef<uint8_t>(AArch64TlsdescGotAtomContent, 16);
- }
-};
-
-
-class AArch64PLT0Atom : public PLT0Atom {
-public:
- AArch64PLT0Atom(const File &f) : PLT0Atom(f) {}
- ArrayRef<uint8_t> rawContent() const override {
- return ArrayRef<uint8_t>(AArch64Plt0AtomContent, 32);
- }
-};
-
-class AArch64PLTAtom : public PLTAtom {
-public:
- AArch64PLTAtom(const File &f) : PLTAtom(f, ".plt") {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return ArrayRef<uint8_t>(AArch64PltAtomContent, 16);
- }
-};
-
-class AArch64PLTTLSDESCAtom : public PLTAtom {
-public:
- AArch64PLTTLSDESCAtom(const File &f) : PLTAtom(f, ".plt") {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return ArrayRef<uint8_t>(AArch64PltTlsdescAtomContent, 32);
- }
-};
-
-class ELFPassFile : public SimpleFile {
-public:
- ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
- setOrdinal(eti.getNextOrdinalAndIncrement());
- }
-
- llvm::BumpPtrAllocator _alloc;
-};
-
-/// \brief CRTP base for handling relocations.
-template <class Derived> class AArch64RelocationPass : public Pass {
- /// \brief Handle a specific reference.
- void handleReference(const DefinedAtom &atom, const Reference &ref) {
- DEBUG_WITH_TYPE(
- "AArch64", llvm::dbgs()
- << "\t" << LLVM_FUNCTION_NAME << "()"
- << ": Name of Defined Atom: " << atom.name().str();
- llvm::dbgs() << " kindValue: " << ref.kindValue() << "\n");
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return;
- assert(ref.kindArch() == Reference::KindArch::AArch64);
- switch (ref.kindValue()) {
- case R_AARCH64_ABS32:
- case R_AARCH64_ABS16:
- case R_AARCH64_ABS64:
- case R_AARCH64_PREL16:
- case R_AARCH64_PREL32:
- case R_AARCH64_PREL64:
- static_cast<Derived *>(this)->handlePlain(ref);
- break;
- case R_AARCH64_GOTREL32:
- case R_AARCH64_GOTREL64:
- static_cast<Derived *>(this)->handleGOT(ref);
- break;
- case R_AARCH64_ADR_PREL_PG_HI21:
- static_cast<Derived *>(this)->handlePlain(ref);
- break;
- case R_AARCH64_LDST8_ABS_LO12_NC:
- case R_AARCH64_LDST16_ABS_LO12_NC:
- case R_AARCH64_LDST32_ABS_LO12_NC:
- case R_AARCH64_LDST64_ABS_LO12_NC:
- case R_AARCH64_LDST128_ABS_LO12_NC:
- static_cast<Derived *>(this)->handlePlain(ref);
- break;
- case R_AARCH64_ADD_ABS_LO12_NC:
- static_cast<Derived *>(this)->handlePlain(ref);
- break;
- case R_AARCH64_CALL26:
- case R_AARCH64_JUMP26:
- case R_AARCH64_CONDBR19:
- static_cast<Derived *>(this)->handlePlain(ref);
- break;
- case R_AARCH64_TLSLE_ADD_TPREL_HI12:
- case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
- static_cast<Derived *>(this)->handlePlain(ref);
- break;
- case R_AARCH64_ADR_GOT_PAGE:
- case R_AARCH64_LD64_GOT_LO12_NC:
- static_cast<Derived *>(this)->handleGOT(ref);
- break;
- case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
- case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
- static_cast<Derived *>(this)->handleGOTTPREL(ref);
- break;
- case R_AARCH64_TLSDESC_ADR_PAGE21:
- case R_AARCH64_TLSDESC_LD64_LO12_NC:
- case R_AARCH64_TLSDESC_ADD_LO12_NC:
- static_cast<Derived *>(this)->handleTLSDESC(ref);
- break;
- }
- }
-
-protected:
- /// \brief get the PLT entry for a given IFUNC Atom.
- ///
- /// If the entry does not exist. Both the GOT and PLT entry is created.
- const PLTAtom *getIFUNCPLTEntry(const DefinedAtom *da) {
- auto plt = _pltMap.find(da);
- if (plt != _pltMap.end())
- return plt->second;
- auto ga = new (_file._alloc) AArch64GOTPLTAtom(_file);
- ga->addReferenceELF_AArch64(R_AARCH64_IRELATIVE, 0, da, 0);
- auto pa = new (_file._alloc) AArch64PLTAtom(_file);
- pa->addReferenceELF_AArch64(R_AARCH64_PREL32, 2, ga, -4);
-#ifndef NDEBUG
- ga->_name = "__got_ifunc_";
- ga->_name += da->name();
- pa->_name = "__plt_ifunc_";
- pa->_name += da->name();
-#endif
- _gotMap[da] = ga;
- _pltMap[da] = pa;
- _gotVector.push_back(ga);
- _pltVector.push_back(pa);
- return pa;
- }
-
- /// \brief Redirect the call to the PLT stub for the target IFUNC.
- ///
- /// This create a PLT and GOT entry for the IFUNC if one does not exist. The
- /// GOT entry and a IRELATIVE relocation to the original target resolver.
- std::error_code handleIFUNC(const Reference &ref) {
- auto target = dyn_cast_or_null<const DefinedAtom>(ref.target());
- if (target && target->contentType() == DefinedAtom::typeResolver)
- const_cast<Reference &>(ref).setTarget(getIFUNCPLTEntry(target));
- return std::error_code();
- }
-
- /// \brief Create a GOT entry for the TP offset of a TLS atom.
- const GOTAtom *getGOTTPREL(const Atom *atom) {
- auto got = _gotMap.find(atom);
- if (got == _gotMap.end()) {
- auto g = new (_file._alloc) AArch64GOTAtom(_file);
- g->addReferenceELF_AArch64(R_AARCH64_TLS_TPREL64, 0, atom, 0);
-#ifndef NDEBUG
- g->_name = "__got_tls_";
- g->_name += atom->name();
-#endif
- _gotMap[atom] = g;
- _gotVector.push_back(g);
- return g;
- }
- return got->second;
- }
-
- /// \brief Create a GOT TPREL entry to local or external TLS variable.
- std::error_code handleGOTTPREL(const Reference &ref) {
- if (isa<DefinedAtom>(ref.target()) ||
- isa<SharedLibraryAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getGOTTPREL(ref.target()));
- return std::error_code();
- }
-
- /// \brief Generates a double GOT entry with R_AARCH64_TLSDESC dynamic
- /// relocation reference. Since the dynamic relocation is resolved
- /// lazily so the GOT associated should be in .got.plt.
- const GOTAtom *getTLSDESCPLTEntry(const Atom *da) {
- auto got = _gotMap.find(da);
- if (got != _gotMap.end())
- return got->second;
- auto ga = new (_file._alloc) AArch64TLSDESCGOTAtom(_file);
- ga->addReferenceELF_AArch64(R_AARCH64_TLSDESC, 0, da, 0);
- auto pa = new (_file._alloc) AArch64PLTTLSDESCAtom(_file);
- pa->addReferenceELF_AArch64(R_AARCH64_ADR_PREL_PG_HI21, 4, ga, 0);
- pa->addReferenceELF_AArch64(R_AARCH64_ADR_PREL_PG_HI21, 8, ga, 0);
- pa->addReferenceELF_AArch64(R_AARCH64_LDST64_ABS_LO12_NC, 12, ga, 0);
- pa->addReferenceELF_AArch64(R_AARCH64_ADD_ABS_LO12_NC, 16, ga, 0);
-#ifndef NDEBUG
- ga->_name = "__got_tlsdesc_";
- ga->_name += da->name();
- pa->_name = "__plt_tlsdesc_";
- pa->_name += da->name();
-#endif
- _gotMap[da] = ga;
- _pltMap[da] = pa;
- _tlsdescVector.push_back(ga);
- _pltVector.push_back(pa);
- return ga;
- }
-
- std::error_code handleTLSDESC(const Reference &ref) {
- if (isa<DefinedAtom>(ref.target()) ||
- isa<SharedLibraryAtom>(ref.target())) {
- const_cast<Reference &>(ref).setTarget(getTLSDESCPLTEntry(ref.target()));
- }
- return std::error_code();
- }
-
- /// \brief Create a GOT entry containing 0.
- const GOTAtom *getNullGOT() {
- if (!_null) {
- _null = new (_file._alloc) AArch64GOTPLTAtom(_file);
-#ifndef NDEBUG
- _null->_name = "__got_null";
-#endif
- }
- return _null;
- }
-
- const GOTAtom *getGOT(const DefinedAtom *da) {
- auto got = _gotMap.find(da);
- if (got == _gotMap.end()) {
- auto g = new (_file._alloc) AArch64GOTAtom(_file);
- g->addReferenceELF_AArch64(R_AARCH64_ABS64, 0, da, 0);
-#ifndef NDEBUG
- g->_name = "__got_";
- g->_name += da->name();
-#endif
- _gotMap[da] = g;
- _gotVector.push_back(g);
- return g;
- }
- return got->second;
- }
-
-public:
- AArch64RelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {}
-
- /// \brief Do the pass.
- ///
- /// The goal here is to first process each reference individually. Each call
- /// to handleReference may modify the reference itself and/or create new
- /// atoms which must be stored in one of the maps below.
- ///
- /// After all references are handled, the atoms created during that are all
- /// added to mf.
- std::error_code perform(SimpleFile &mf) override {
- ScopedTask task(getDefaultDomain(), "AArch64 GOT/PLT Pass");
- DEBUG_WITH_TYPE(
- "AArch64", llvm::dbgs() << "Undefined Atoms"
- << "\n";
- for (const auto &atom
- : mf.undefined()) {
- llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
- } llvm::dbgs()
- << "Shared Library Atoms"
- << "\n";
- for (const auto &atom
- : mf.sharedLibrary()) {
- llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
- } llvm::dbgs()
- << "Absolute Atoms"
- << "\n";
- for (const auto &atom
- : mf.absolute()) {
- llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
- }
- // Process all references.
- llvm::dbgs()
- << "Defined Atoms"
- << "\n");
- for (const auto &atom : mf.defined()) {
- for (const auto &ref : *atom) {
- handleReference(*atom, *ref);
- }
- }
-
- // Add all created atoms to the link.
- uint64_t ordinal = 0;
- if (_plt0) {
- _plt0->setOrdinal(ordinal++);
- mf.addAtom(*_plt0);
- }
- for (auto &plt : _pltVector) {
- plt->setOrdinal(ordinal++);
- mf.addAtom(*plt);
- }
- if (_null) {
- _null->setOrdinal(ordinal++);
- mf.addAtom(*_null);
- }
- if (_plt0) {
- _got0->setOrdinal(ordinal++);
- _got1->setOrdinal(ordinal++);
- mf.addAtom(*_got0);
- mf.addAtom(*_got1);
- }
- for (auto &got : _gotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
- // Add any tlsdesc GOT relocation after default PLT and iFUNC entries.
- for (auto &tlsdesc : _tlsdescVector) {
- tlsdesc->setOrdinal(ordinal++);
- mf.addAtom(*tlsdesc);
- }
- for (auto obj : _objectVector) {
- obj->setOrdinal(ordinal++);
- mf.addAtom(*obj);
- }
-
- return std::error_code();
- }
-
-protected:
- /// \brief Owner of all the Atoms created by this pass.
- ELFPassFile _file;
- const ELFLinkingContext &_ctx;
-
- /// \brief Map Atoms to their GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
-
- /// \brief Map Atoms to their PLT entries.
- llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
-
- /// \brief Map Atoms to their Object entries.
- llvm::DenseMap<const Atom *, ObjectAtom *> _objectMap;
-
- /// \brief the list of GOT/PLT atoms
- std::vector<GOTAtom *> _gotVector;
- std::vector<GOTAtom *> _tlsdescVector;
- std::vector<PLTAtom *> _pltVector;
- std::vector<ObjectAtom *> _objectVector;
-
- /// \brief GOT entry that is always 0. Used for undefined weaks.
- GOTAtom *_null = nullptr;
-
- /// \brief The got and plt entries for .PLT0. This is used to call into the
- /// dynamic linker for symbol resolution.
- /// @{
- PLT0Atom *_plt0 = nullptr;
- GOTAtom *_got0 = nullptr;
- GOTAtom *_got1 = nullptr;
- /// @}
-};
-
-/// This implements the static relocation model. Meaning GOT and PLT entries are
-/// not created for references that can be directly resolved. These are
-/// converted to a direct relocation. For entries that do require a GOT or PLT
-/// entry, that entry is statically bound.
-///
-/// TLS always assumes module 1 and attempts to remove indirection.
-class AArch64StaticRelocationPass final
- : public AArch64RelocationPass<AArch64StaticRelocationPass> {
-public:
- AArch64StaticRelocationPass(const elf::AArch64LinkingContext &ctx)
- : AArch64RelocationPass(ctx) {}
-
- std::error_code handlePlain(const Reference &ref) { return handleIFUNC(ref); }
-
- std::error_code handlePLT32(const Reference &ref) {
- // __tls_get_addr is handled elsewhere.
- if (ref.target() && ref.target()->name() == "__tls_get_addr") {
- const_cast<Reference &>(ref).setKindValue(R_AARCH64_NONE);
- return std::error_code();
- }
- // Static code doesn't need PLTs.
- const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
- // Handle IFUNC.
- if (const DefinedAtom *da =
- dyn_cast_or_null<const DefinedAtom>(ref.target()))
- if (da->contentType() == DefinedAtom::typeResolver)
- return handleIFUNC(ref);
- return std::error_code();
- }
-
- std::error_code handleGOT(const Reference &ref) {
- if (isa<UndefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getNullGOT());
- else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getGOT(da));
- return std::error_code();
- }
-};
-
-class AArch64DynamicRelocationPass final
- : public AArch64RelocationPass<AArch64DynamicRelocationPass> {
-public:
- AArch64DynamicRelocationPass(const elf::AArch64LinkingContext &ctx)
- : AArch64RelocationPass(ctx) {}
-
- const PLT0Atom *getPLT0() {
- if (_plt0)
- return _plt0;
- // Fill in the null entry.
- getNullGOT();
- _plt0 = new (_file._alloc) AArch64PLT0Atom(_file);
- _got0 = new (_file._alloc) AArch64GOTPLTAtom(_file);
- _got1 = new (_file._alloc) AArch64GOTPLTAtom(_file);
- _plt0->addReferenceELF_AArch64(R_AARCH64_ADR_GOT_PAGE, 4, _got0, 0);
- _plt0->addReferenceELF_AArch64(R_AARCH64_LD64_GOT_LO12_NC, 8, _got1, 0);
- _plt0->addReferenceELF_AArch64(ADD_AARCH64_GOTRELINDEX, 12, _got1, 0);
-#ifndef NDEBUG
- _plt0->_name = "__PLT0";
- _got0->_name = "__got0";
- _got1->_name = "__got1";
-#endif
- return _plt0;
- }
-
- const PLTAtom *getPLTEntry(const Atom *a) {
- auto plt = _pltMap.find(a);
- if (plt != _pltMap.end())
- return plt->second;
- auto ga = new (_file._alloc) AArch64GOTPLTAtom(_file);
- ga->addReferenceELF_AArch64(R_AARCH64_JUMP_SLOT, 0, a, 0);
- auto pa = new (_file._alloc) AArch64PLTAtom(_file);
- pa->addReferenceELF_AArch64(R_AARCH64_ADR_GOT_PAGE, 0, ga, 0);
- pa->addReferenceELF_AArch64(R_AARCH64_LD64_GOT_LO12_NC, 4, ga, 0);
- pa->addReferenceELF_AArch64(ADD_AARCH64_GOTRELINDEX, 8, ga, 0);
- pa->addReferenceELF_AArch64(R_AARCH64_NONE, 12, getPLT0(), 0);
- // Set the starting address of the got entry to the first instruction in
- // the plt0 entry.
- ga->addReferenceELF_AArch64(R_AARCH64_ABS32, 0, getPLT0(), 0);
-#ifndef NDEBUG
- ga->_name = "__got_";
- ga->_name += a->name();
- pa->_name = "__plt_";
- pa->_name += a->name();
-#endif
- _gotMap[a] = ga;
- _pltMap[a] = pa;
- _gotVector.push_back(ga);
- _pltVector.push_back(pa);
- return pa;
- }
-
- const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) {
- auto obj = _objectMap.find(a);
- if (obj != _objectMap.end())
- return obj->second;
-
- auto oa = new (_file._alloc) ObjectAtom(_file);
- // This needs to point to the atom that we just created.
- oa->addReferenceELF_AArch64(R_AARCH64_COPY, 0, oa, 0);
-
- oa->_name = a->name();
- oa->_size = a->size();
-
- _objectMap[a] = oa;
- _objectVector.push_back(oa);
- return oa;
- }
-
- std::error_code handlePlain(const Reference &ref) {
- if (!ref.target())
- return std::error_code();
- if (auto sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
- if (sla->type() == SharedLibraryAtom::Type::Data)
- const_cast<Reference &>(ref).setTarget(getObjectEntry(sla));
- else if (sla->type() == SharedLibraryAtom::Type::Code)
- const_cast<Reference &>(ref).setTarget(getPLTEntry(sla));
- } else
- return handleIFUNC(ref);
- return std::error_code();
- }
-
- std::error_code handlePLT32(const Reference &ref) {
- // Turn this into a PC32 to the PLT entry.
- const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
- // Handle IFUNC.
- if (const DefinedAtom *da =
- dyn_cast_or_null<const DefinedAtom>(ref.target()))
- if (da->contentType() == DefinedAtom::typeResolver)
- return handleIFUNC(ref);
- if (isa<const SharedLibraryAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
- return std::error_code();
- }
-
- const GOTAtom *getSharedGOT(const SharedLibraryAtom *sla) {
- auto got = _gotMap.find(sla);
- if (got == _gotMap.end()) {
- auto g = new (_file._alloc) AArch64GOTAtom(_file);
- g->addReferenceELF_AArch64(R_AARCH64_GLOB_DAT, 0, sla, 0);
-#ifndef NDEBUG
- g->_name = "__got_";
- g->_name += sla->name();
-#endif
- _gotMap[sla] = g;
- _gotVector.push_back(g);
- return g;
- }
- return got->second;
- }
-
- std::error_code handleGOT(const Reference &ref) {
- if (isa<UndefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getNullGOT());
- else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getGOT(da));
- else if (const auto sla = dyn_cast<const SharedLibraryAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getSharedGOT(sla));
- return std::error_code();
- }
-};
-} // end anon namespace
-
-std::unique_ptr<Pass>
-lld::elf::createAArch64RelocationPass(const AArch64LinkingContext &ctx) {
- switch (ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- if (ctx.isDynamic())
- return llvm::make_unique<AArch64DynamicRelocationPass>(ctx);
- return llvm::make_unique<AArch64StaticRelocationPass>(ctx);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<AArch64DynamicRelocationPass>(ctx);
- case llvm::ELF::ET_REL:
- return nullptr;
- default:
- llvm_unreachable("Unhandled output file type");
- }
-}
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h
deleted file mode 100644
index 73d784e3b52d..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Declares the relocation processing pass for AArch64. This includes
-/// GOT and PLT entries, TLS, COPY, and ifunc.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_RELOCATION_PASS_H
-#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_RELOCATION_PASS_H
-
-#include <memory>
-
-namespace lld {
-class Pass;
-namespace elf {
-class AArch64LinkingContext;
-
-/// \brief Create AArch64 relocation pass for the given linking context.
-std::unique_ptr<Pass>
-createAArch64RelocationPass(const AArch64LinkingContext &);
-}
-}
-
-#endif
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp
deleted file mode 100644
index 2734bcdbda5f..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp --------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AArch64SectionChunks.h"
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-AArch64GOTSection::AArch64GOTSection(const ELFLinkingContext &ctx,
- StringRef name, int32_t order)
- : AtomSection<ELF64LE>(ctx, name, DefinedAtom::typeGOT, DefinedAtom::permRW_,
- order) {
- _alignment = 8;
-}
-
-const AtomLayout *AArch64GOTSection::appendAtom(const Atom *atom) {
- const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
-
- for (const auto &r : *da) {
- if (r->kindNamespace() != Reference::KindNamespace::ELF)
- continue;
- assert(r->kindArch() == Reference::KindArch::AArch64);
- if ((r->kindValue() == R_AARCH64_TLS_TPREL64) ||
- (r->kindValue() == R_AARCH64_TLSDESC))
- _tlsMap[r->target()] = _tlsMap.size();
- }
-
- return AtomSection<ELF64LE>::appendAtom(atom);
-}
-
-} // elf
-} // lld
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h b/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h
deleted file mode 100644
index 2b7594c2db84..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_SECTION_CHUNKS_H
-#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_SECTION_CHUNKS_H
-
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-class AArch64GOTSection : public AtomSection<ELF64LE> {
-public:
- AArch64GOTSection(const ELFLinkingContext &ctx, StringRef name,
- int32_t order);
-
- bool hasGlobalGOTEntry(const Atom *a) const {
- return _tlsMap.count(a);
- }
-
- const AtomLayout *appendAtom(const Atom *atom) override;
-
-private:
- /// \brief Map TLS Atoms to their GOT entry index.
- llvm::DenseMap<const Atom *, std::size_t> _tlsMap;
-};
-
-} // elf
-} // lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
deleted file mode 100644
index 083b492c1607..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp --------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Atoms.h"
-#include "AArch64DynamicLibraryWriter.h"
-#include "AArch64ExecutableWriter.h"
-#include "AArch64LinkingContext.h"
-#include "AArch64TargetHandler.h"
-#include "AArch64SectionChunks.h"
-
-using namespace lld;
-using namespace elf;
-
-AArch64TargetLayout::AArch64TargetLayout(ELFLinkingContext &ctx) :
- TargetLayout(ctx) {}
-
-AtomSection<ELF64LE> *AArch64TargetLayout::createSection(
- StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions,
- TargetLayout<ELF64LE>::SectionOrder order) {
- if (type == DefinedAtom::typeGOT && (name == ".got" || name == ".got.plt")) {
- auto section = new (this->_allocator) AArch64GOTSection(this->_ctx, name,
- order);
- _gotSections.push_back(section);
- return section;
- }
- return TargetLayout<ELF64LE>::createSection(name, type, permissions, order);
-}
-
-
-AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &ctx)
- : _ctx(ctx), _targetLayout(new AArch64TargetLayout(ctx)),
- _relocationHandler(new AArch64TargetRelocationHandler(*_targetLayout)) {}
-
-std::unique_ptr<Writer> AArch64TargetHandler::getWriter() {
- switch (this->_ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- return llvm::make_unique<AArch64ExecutableWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<AArch64DynamicLibraryWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_REL:
- llvm_unreachable("TODO: support -r mode");
- default:
- llvm_unreachable("unsupported output type");
- }
-}
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h b/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
deleted file mode 100644
index c0ecbfa9e44b..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
+++ /dev/null
@@ -1,90 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_TARGET_HANDLER_H
-#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_TARGET_HANDLER_H
-
-#include "AArch64RelocationHandler.h"
-#include "ELFReader.h"
-#include "TargetLayout.h"
-#include "lld/Core/Simple.h"
-
-namespace lld {
-namespace elf {
-
-class AArch64LinkingContext;
-class AArch64GOTSection;
-
-class AArch64TargetLayout final : public TargetLayout<ELF64LE> {
- typedef llvm::object::Elf_Shdr_Impl<ELF64LE> Elf_Shdr;
-
-public:
- AArch64TargetLayout(ELFLinkingContext &ctx);
-
- AtomSection<ELF64LE> *
- createSection(StringRef name, int32_t type,
- DefinedAtom::ContentPermissions permissions,
- TargetLayout<ELF64LE>::SectionOrder order) override;
-
- const std::vector<AArch64GOTSection *> &getGOTSections() const {
- return _gotSections;
- }
-
- uint64_t getTPOffset() {
- std::call_once(_tpOffOnce, [this]() {
- for (const auto &phdr : *_programHeader) {
- if (phdr->p_type == llvm::ELF::PT_TLS) {
- _tpOff = llvm::RoundUpToAlignment(TCB_SIZE, phdr->p_align);
- break;
- }
- }
- assert(_tpOff != 0 && "TLS segment not found");
- });
- return _tpOff;
- }
-
-private:
- enum {
- TCB_SIZE = 16,
- };
-
-private:
- std::vector<AArch64GOTSection *> _gotSections;
- uint64_t _tpOff = 0;
- std::once_flag _tpOffOnce;
-};
-
-class AArch64TargetHandler final : public TargetHandler {
-public:
- AArch64TargetHandler(AArch64LinkingContext &ctx);
-
- const TargetRelocationHandler &getRelocationHandler() const override {
- return *_relocationHandler;
- }
-
- std::unique_ptr<Reader> getObjReader() override {
- return llvm::make_unique<ELFReader<ELFFile<ELF64LE>>>(_ctx);
- }
-
- std::unique_ptr<Reader> getDSOReader() override {
- return llvm::make_unique<ELFReader<DynamicFile<ELF64LE>>>(_ctx);
- }
-
- std::unique_ptr<Writer> getWriter() override;
-
-private:
- AArch64LinkingContext &_ctx;
- std::unique_ptr<AArch64TargetLayout> _targetLayout;
- std::unique_ptr<AArch64TargetRelocationHandler> _relocationHandler;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt b/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
deleted file mode 100644
index aae6420008a4..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-add_lld_library(lldAArch64ELFTarget
- AArch64LinkingContext.cpp
- AArch64TargetHandler.cpp
- AArch64RelocationHandler.cpp
- AArch64RelocationPass.cpp
- AArch64ExecutableWriter.cpp
- AArch64SectionChunks.cpp
- LINK_LIBS
- lldELF
- lldReaderWriter
- lldCore
- LLVMObject
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/ELF/AArch64/TODO.rst b/lib/ReaderWriter/ELF/AArch64/TODO.rst
deleted file mode 100644
index aa6f616ff33f..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/TODO.rst
+++ /dev/null
@@ -1,15 +0,0 @@
-ELF AArch64
-~~~~~~~~~~~
-
-Unimplemented Features
-######################
-
-* Just about everything!
-
-Unimplemented Relocations
-#########################
-
-All of these relocations are defined in:
-http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
-
-
diff --git a/lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h b/lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h
deleted file mode 100644
index da843b97abc0..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h -----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_DYNAMIC_LIBRARY_WRITER_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_DYNAMIC_LIBRARY_WRITER_H
-
-#include "DynamicLibraryWriter.h"
-#include "ARMELFWriters.h"
-#include "ARMLinkingContext.h"
-#include "ARMTargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-class ARMDynamicLibraryWriter
- : public ARMELFWriter<DynamicLibraryWriter<ELF32LE>> {
-public:
- ARMDynamicLibraryWriter(ARMLinkingContext &ctx, ARMTargetLayout &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
-private:
- ARMLinkingContext &_ctx;
-};
-
-ARMDynamicLibraryWriter::ARMDynamicLibraryWriter(ARMLinkingContext &ctx,
- ARMTargetLayout &layout)
- : ARMELFWriter(ctx, layout), _ctx(ctx) {}
-
-void ARMDynamicLibraryWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter::createImplicitFiles(result);
- auto file = llvm::make_unique<RuntimeFile<ELF32LE>>(_ctx, "ARM dynamic file");
- file->addAbsoluteAtom(gotSymbol);
- file->addAbsoluteAtom(dynamicSymbol);
- result.push_back(std::move(file));
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_ARM_ARM_DYNAMIC_LIBRARY_WRITER_H
diff --git a/lib/ReaderWriter/ELF/ARM/ARMELFFile.h b/lib/ReaderWriter/ELF/ARM/ARMELFFile.h
deleted file mode 100644
index 8f5477017e55..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMELFFile.h
+++ /dev/null
@@ -1,154 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMELFFile.h ----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_ELF_FILE_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_ELF_FILE_H
-
-#include "ELFReader.h"
-
-namespace lld {
-namespace elf {
-
-class ARMLinkingContext;
-
-class ARMELFBaseDefinedAtom : public ELFDefinedAtom<ELF32LE> {
-public:
- /// The values of custom content type enum must not interfere
- /// with ones in base defined atom class' enum.
- enum ARMContentType {
- typeARMExidx = 0x1000, // Identifies ARM_EXIDX section
- };
-
- template <typename... T>
- ARMELFBaseDefinedAtom(T &&... args)
- : ELFDefinedAtom<ELF32LE>(std::forward<T>(args)...) {}
-
- DefinedAtom::ContentPermissions permissions() const override {
- if (_permissions != DefinedAtom::permUnknown)
- return _permissions;
-
- switch (_section->sh_type) {
- case llvm::ELF::SHT_ARM_EXIDX:
- return _permissions = permR__;
- }
- return ELFDefinedAtom::permissions();
- }
-
- DefinedAtom::ContentType contentType() const override {
- if (_contentType != DefinedAtom::typeUnknown)
- return _contentType;
-
- switch (_section->sh_type) {
- case llvm::ELF::SHT_ARM_EXIDX:
- return _contentType = (DefinedAtom::ContentType)typeARMExidx;
- }
- return ELFDefinedAtom::contentType();
- }
-};
-
-class ARMELFMappingAtom : public ARMELFBaseDefinedAtom {
-public:
- template <typename... T>
- ARMELFMappingAtom(DefinedAtom::CodeModel model, T &&... args)
- : ARMELFBaseDefinedAtom(std::forward<T>(args)...), _model(model) {}
-
- DefinedAtom::CodeModel codeModel() const override { return _model; }
-
-private:
- DefinedAtom::CodeModel _model;
-};
-
-class ARMELFDefinedAtom : public ARMELFBaseDefinedAtom {
-public:
- template <typename... T>
- ARMELFDefinedAtom(T &&... args)
- : ARMELFBaseDefinedAtom(std::forward<T>(args)...) {}
-
- bool isThumbFunc() const {
- const auto *symbol = _symbol;
- return symbol->getType() == llvm::ELF::STT_FUNC &&
- (static_cast<uint64_t>(symbol->st_value) & 0x1);
- }
-
- /// Correct st_value for symbols addressing Thumb instructions
- /// by removing its zero bit.
- uint64_t getSymbolValue() const override {
- const auto value = static_cast<uint64_t>(_symbol->st_value);
- return isThumbFunc() ? value & ~0x1 : value;
- }
-
- DefinedAtom::CodeModel codeModel() const override {
- return isThumbFunc() ? DefinedAtom::codeARMThumb : DefinedAtom::codeNA;
- }
-};
-
-class ARMELFFile : public ELFFile<ELF32LE> {
- typedef llvm::object::Elf_Rel_Impl<ELF32LE, false> Elf_Rel;
-
-public:
- ARMELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
- : ELFFile(std::move(mb), ctx) {}
-
-protected:
- /// Returns initial addend; for ARM it is 0, because it is read
- /// during the relocations applying
- Reference::Addend getInitialAddend(ArrayRef<uint8_t>, uint64_t,
- const Elf_Rel &) const override {
- return 0;
- }
-
-private:
- typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELF32LE> Elf_Shdr;
-
- /// Correct st_value for symbols addressing Thumb instructions
- /// by removing its zero bit.
- uint64_t getSymbolValue(const Elf_Sym *symbol) const override {
- const auto value = static_cast<uint64_t>(symbol->st_value);
- return symbol->getType() == llvm::ELF::STT_FUNC ? value & ~0x1 : value;
- }
-
- /// Process the Defined symbol and create an atom for it.
- ELFDefinedAtom<ELF32LE> *createDefinedAtom(
- StringRef symName, StringRef sectionName, const Elf_Sym *sym,
- const Elf_Shdr *sectionHdr, ArrayRef<uint8_t> contentData,
- unsigned int referenceStart, unsigned int referenceEnd,
- std::vector<ELFReference<ELF32LE> *> &referenceList) override {
- if (symName.size() >= 2 && symName[0] == '$') {
- switch (symName[1]) {
- case 'a':
- return new (_readerStorage)
- ARMELFMappingAtom(DefinedAtom::codeARM_a, *this, symName,
- sectionName, sym, sectionHdr, contentData,
- referenceStart, referenceEnd, referenceList);
- case 'd':
- return new (_readerStorage)
- ARMELFMappingAtom(DefinedAtom::codeARM_d, *this, symName,
- sectionName, sym, sectionHdr, contentData,
- referenceStart, referenceEnd, referenceList);
- case 't':
- return new (_readerStorage)
- ARMELFMappingAtom(DefinedAtom::codeARM_t, *this, symName,
- sectionName, sym, sectionHdr, contentData,
- referenceStart, referenceEnd, referenceList);
- default:
- // Fall through and create regular defined atom.
- break;
- }
- }
- return new (_readerStorage) ARMELFDefinedAtom(
- *this, symName, sectionName, sym, sectionHdr, contentData,
- referenceStart, referenceEnd, referenceList);
- }
-};
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_ARM_ARM_ELF_FILE_H
diff --git a/lib/ReaderWriter/ELF/ARM/ARMELFWriters.h b/lib/ReaderWriter/ELF/ARM/ARMELFWriters.h
deleted file mode 100644
index a842ebe53038..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMELFWriters.h
+++ /dev/null
@@ -1,120 +0,0 @@
-//===- lib/ReaderWriter/ELF/ARM/ARMELFWriters.h ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_ELF_WRITERS_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_ELF_WRITERS_H
-
-#include "ARMLinkingContext.h"
-#include "ARMSymbolTable.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-
-template <class WriterT> class ARMELFWriter : public WriterT {
-public:
- ARMELFWriter(ARMLinkingContext &ctx, TargetLayout<ELF32LE> &layout);
-
- void finalizeDefaultAtomValues() override;
-
- /// \brief Create symbol table.
- unique_bump_ptr<SymbolTable<ELF32LE>> createSymbolTable() override;
-
- // Setup the ELF header.
- std::error_code setELFHeader() override;
-
-protected:
- static const char *gotSymbol;
- static const char *dynamicSymbol;
-
-private:
- ARMLinkingContext &_ctx;
- TargetLayout<ELF32LE> &_armLayout;
-};
-
-template <class WriterT>
-const char *ARMELFWriter<WriterT>::gotSymbol = "_GLOBAL_OFFSET_TABLE_";
-template <class WriterT>
-const char *ARMELFWriter<WriterT>::dynamicSymbol = "_DYNAMIC";
-
-template <class WriterT>
-ARMELFWriter<WriterT>::ARMELFWriter(ARMLinkingContext &ctx,
- TargetLayout<ELF32LE> &layout)
- : WriterT(ctx, layout), _ctx(ctx), _armLayout(layout) {}
-
-template <class WriterT>
-void ARMELFWriter<WriterT>::finalizeDefaultAtomValues() {
- // Finalize the atom values that are part of the parent.
- WriterT::finalizeDefaultAtomValues();
-
- if (auto *gotAtom = _armLayout.findAbsoluteAtom(gotSymbol)) {
- if (auto gotpltSection = _armLayout.findOutputSection(".got.plt"))
- gotAtom->_virtualAddr = gotpltSection->virtualAddr();
- else if (auto gotSection = _armLayout.findOutputSection(".got"))
- gotAtom->_virtualAddr = gotSection->virtualAddr();
- else
- gotAtom->_virtualAddr = 0;
- }
-
- if (auto *dynamicAtom = _armLayout.findAbsoluteAtom(dynamicSymbol)) {
- if (auto dynamicSection = _armLayout.findOutputSection(".dynamic"))
- dynamicAtom->_virtualAddr = dynamicSection->virtualAddr();
- else
- dynamicAtom->_virtualAddr = 0;
- }
-
- // Set required by gcc libc __ehdr_start symbol with pointer to ELF header
- if (auto ehdr = _armLayout.findAbsoluteAtom("__ehdr_start"))
- ehdr->_virtualAddr = this->_elfHeader->virtualAddr();
-
- // Set required by gcc libc symbols __exidx_start/__exidx_end
- this->updateScopeAtomValues("exidx", ".ARM.exidx");
-}
-
-template <class WriterT>
-unique_bump_ptr<SymbolTable<ELF32LE>>
-ARMELFWriter<WriterT>::createSymbolTable() {
- return unique_bump_ptr<SymbolTable<ELF32LE>>(new (this->_alloc)
- ARMSymbolTable(_ctx));
-}
-
-template <class WriterT> std::error_code ARMELFWriter<WriterT>::setELFHeader() {
- if (std::error_code ec = WriterT::setELFHeader())
- return ec;
-
- // Set ARM-specific flags.
- this->_elfHeader->e_flags(llvm::ELF::EF_ARM_EABI_VER5 |
- llvm::ELF::EF_ARM_VFP_FLOAT);
-
- StringRef entryName = _ctx.entrySymbolName();
- if (const AtomLayout *al = _armLayout.findAtomLayoutByName(entryName)) {
- if (const auto *ea = dyn_cast<DefinedAtom>(al->_atom)) {
- switch (ea->codeModel()) {
- case DefinedAtom::codeNA:
- if (al->_virtualAddr & 0x3) {
- llvm::report_fatal_error(
- "Two least bits must be zero for ARM entry point");
- }
- break;
- case DefinedAtom::codeARMThumb:
- // Fixup entry point for Thumb code.
- this->_elfHeader->e_entry(al->_virtualAddr | 0x1);
- break;
- default:
- llvm_unreachable("Wrong code model of entry point atom");
- }
- }
- }
-
- return std::error_code();
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_ARM_ARM_ELF_WRITERS_H
diff --git a/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h b/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
deleted file mode 100644
index 974dab63a126..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H
-
-#include "ExecutableWriter.h"
-#include "ARMELFWriters.h"
-#include "ARMLinkingContext.h"
-#include "ARMTargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-class ARMExecutableWriter : public ARMELFWriter<ExecutableWriter<ELF32LE>> {
-public:
- ARMExecutableWriter(ARMLinkingContext &ctx, ARMTargetLayout &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void processUndefinedSymbol(StringRef symName,
- RuntimeFile<ELF32LE> &file) const override;
-
-private:
- ARMLinkingContext &_ctx;
-};
-
-ARMExecutableWriter::ARMExecutableWriter(ARMLinkingContext &ctx,
- ARMTargetLayout &layout)
- : ARMELFWriter(ctx, layout), _ctx(ctx) {}
-
-void ARMExecutableWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter::createImplicitFiles(result);
- // Add default atoms for ARM.
- if (_ctx.isDynamic()) {
- auto file = llvm::make_unique<RuntimeFile<ELF32LE>>(_ctx, "ARM exec file");
- file->addAbsoluteAtom(gotSymbol);
- file->addAbsoluteAtom(dynamicSymbol);
- result.push_back(std::move(file));
- }
-}
-
-void ARMExecutableWriter::processUndefinedSymbol(
- StringRef symName, RuntimeFile<ELF32LE> &file) const {
- ARMELFWriter<ExecutableWriter<ELF32LE>>::processUndefinedSymbol(symName,
- file);
- if (symName == gotSymbol) {
- file.addAbsoluteAtom(gotSymbol);
- } else if (symName.startswith("__exidx")) {
- file.addAbsoluteAtom("__exidx_start");
- file.addAbsoluteAtom("__exidx_end");
- } else if (symName == "__ehdr_start") {
- file.addAbsoluteAtom("__ehdr_start");
- }
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H
diff --git a/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp b/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp
deleted file mode 100644
index 74905b47820f..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ARMLinkingContext.h"
-#include "ARMRelocationPass.h"
-#include "ARMTargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-std::unique_ptr<ELFLinkingContext>
-createARMLinkingContext(llvm::Triple triple) {
- if (triple.getArch() == llvm::Triple::arm)
- return llvm::make_unique<ARMLinkingContext>(triple);
- return nullptr;
-}
-
-ARMLinkingContext::ARMLinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, llvm::make_unique<ARMTargetHandler>(*this)) {}
-
-void ARMLinkingContext::addPasses(PassManager &pm) {
- auto pass = createARMRelocationPass(*this);
- if (pass)
- pm.add(std::move(pass));
- ELFLinkingContext::addPasses(pm);
-}
-
-bool isARMCode(const DefinedAtom *atom) {
- return isARMCode(atom->codeModel());
-}
-
-bool isARMCode(DefinedAtom::CodeModel codeModel) {
- return !isThumbCode(codeModel);
-}
-
-bool isThumbCode(const DefinedAtom *atom) {
- return isThumbCode(atom->codeModel());
-}
-
-bool isThumbCode(DefinedAtom::CodeModel codeModel) {
- return codeModel == DefinedAtom::codeARMThumb ||
- codeModel == DefinedAtom::codeARM_t;
-}
-
-static const Registry::KindStrings kindStrings[] = {
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-#include "llvm/Support/ELFRelocs/ARM.def"
-#undef ELF_RELOC
- LLD_KIND_STRING_END
-};
-
-void ARMLinkingContext::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF, Reference::KindArch::ARM,
- kindStrings);
-}
-
-} // namespace elf
-} // namespace lld
diff --git a/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h b/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h
deleted file mode 100644
index f687713b25b8..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_LINKING_CONTEXT_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-
-class ARMLinkingContext final : public ELFLinkingContext {
-public:
- int getMachineType() const override { return llvm::ELF::EM_ARM; }
- ARMLinkingContext(llvm::Triple);
-
- void addPasses(PassManager &) override;
- void registerRelocationNames(Registry &r) override;
-
- bool isRelaOutputFormat() const override { return false; }
-
- uint64_t getBaseAddress() const override {
- if (_baseAddress == 0)
- return 0x400000;
- return _baseAddress;
- }
-
- bool isDynamicRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::ARM);
- switch (r.kindValue()) {
- case llvm::ELF::R_ARM_GLOB_DAT:
- case llvm::ELF::R_ARM_TLS_TPOFF32:
- case llvm::ELF::R_ARM_COPY:
- return true;
- default:
- return false;
- }
- }
-
- bool isCopyRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::ARM);
- return r.kindValue() == llvm::ELF::R_ARM_COPY;
- }
-
- bool isPLTRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::ARM);
- switch (r.kindValue()) {
- case llvm::ELF::R_ARM_JUMP_SLOT:
- case llvm::ELF::R_ARM_IRELATIVE:
- return true;
- default:
- return false;
- }
- }
-};
-
-// Special methods to check code model of atoms.
-bool isARMCode(const DefinedAtom *atom);
-bool isARMCode(DefinedAtom::CodeModel codeModel);
-bool isThumbCode(const DefinedAtom *atom);
-bool isThumbCode(DefinedAtom::CodeModel codeModel);
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp b/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
deleted file mode 100644
index 97b149133ff2..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp ----------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ARMTargetHandler.h"
-#include "ARMLinkingContext.h"
-
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/MathExtras.h"
-
-#define DEBUG_TYPE "ARM"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::support::endian;
-
-static Reference::Addend readAddend_THM_MOV(const uint8_t *location) {
- const uint16_t halfHi = read16le(location);
- const uint16_t halfLo = read16le(location + 2);
-
- const uint16_t imm8 = halfLo & 0xFF;
- const uint16_t imm3 = (halfLo >> 12) & 0x7;
-
- const uint16_t imm4 = halfHi & 0xF;
- const uint16_t bitI = (halfHi >> 10) & 0x1;
-
- const auto result = int16_t((imm4 << 12) | (bitI << 11) | (imm3 << 8) | imm8);
- return result;
-}
-
-static Reference::Addend readAddend_ARM_MOV(const uint8_t *location) {
- const uint32_t value = read32le(location);
-
- const uint32_t imm12 = value & 0xFFF;
- const uint32_t imm4 = (value >> 16) & 0xF;
-
- const auto result = int32_t((imm4 << 12) | imm12);
- return result;
-}
-
-static Reference::Addend readAddend_THM_CALL(const uint8_t *location) {
- const uint16_t halfHi = read16le(location);
- const uint16_t halfLo = read16le(location + 2);
-
- const uint16_t imm10 = halfHi & 0x3FF;
- const uint16_t bitS = (halfHi >> 10) & 0x1;
-
- const uint16_t imm11 = halfLo & 0x7FF;
- const uint16_t bitJ2 = (halfLo >> 11) & 0x1;
- const uint16_t bitI2 = (~(bitJ2 ^ bitS)) & 0x1;
- const uint16_t bitJ1 = (halfLo >> 13) & 0x1;
- const uint16_t bitI1 = (~(bitJ1 ^ bitS)) & 0x1;
-
- const auto result = int32_t((bitS << 24) | (bitI1 << 23) | (bitI2 << 22) |
- (imm10 << 12) | (imm11 << 1));
- return llvm::SignExtend64<25>(result);
-}
-
-static Reference::Addend readAddend_ARM_CALL(const uint8_t *location) {
- const uint32_t value = read32le(location);
-
- const bool isBLX = (value & 0xF0000000) == 0xF0000000;
- const uint32_t bitH = isBLX ? ((value & 0x1000000) >> 24) : 0;
-
- const auto result = int32_t(((value & 0xFFFFFF) << 2) | (bitH << 1));
- return llvm::SignExtend64<26>(result);
-}
-
-static Reference::Addend readAddend_THM_JUMP11(const uint8_t *location) {
- const auto value = read16le(location);
- const uint16_t imm11 = value & 0x7FF;
-
- return llvm::SignExtend64<12>(imm11 << 1);
-}
-
-static Reference::Addend readAddend(const uint8_t *location,
- Reference::KindValue kindValue) {
- switch (kindValue) {
- case R_ARM_ABS32:
- case R_ARM_REL32:
- case R_ARM_TARGET1:
- case R_ARM_GOT_BREL:
- case R_ARM_BASE_PREL:
- case R_ARM_TLS_IE32:
- case R_ARM_TLS_LE32:
- case R_ARM_TLS_TPOFF32:
- return (int32_t)read32le(location);
- case R_ARM_PREL31:
- return llvm::SignExtend64<31>(read32le(location) & 0x7FFFFFFF);
- case R_ARM_THM_CALL:
- case R_ARM_THM_JUMP24:
- return readAddend_THM_CALL(location);
- case R_ARM_THM_JUMP11:
- return readAddend_THM_JUMP11(location);
- case R_ARM_CALL:
- case R_ARM_JUMP24:
- return readAddend_ARM_CALL(location);
- case R_ARM_MOVW_ABS_NC:
- case R_ARM_MOVT_ABS:
- return readAddend_ARM_MOV(location);
- case R_ARM_THM_MOVW_ABS_NC:
- case R_ARM_THM_MOVT_ABS:
- return readAddend_THM_MOV(location);
- default:
- return 0;
- }
-}
-
-static inline void report_unsupported_range_group_reloc_error() {
- llvm::report_fatal_error(
- "Negative offsets for group relocations are not implemented");
-}
-
-static inline std::error_code applyArmReloc(uint8_t *location, uint32_t result,
- uint32_t mask = 0xFFFFFFFF) {
- assert(!(result & ~mask));
- write32le(location, (read32le(location) & ~mask) | (result & mask));
- return std::error_code();
-}
-
-static inline std::error_code applyThumb32Reloc(uint8_t *location,
- uint16_t resHi, uint16_t resLo,
- uint16_t maskHi,
- uint16_t maskLo = 0xFFFF) {
- assert(!(resHi & ~maskHi) && !(resLo & ~maskLo));
- write16le(location, (read16le(location) & ~maskHi) | (resHi & maskHi));
- location += 2;
- write16le(location, (read16le(location) & ~maskLo) | (resLo & maskLo));
- return std::error_code();
-}
-
-static inline std::error_code
-applyThumb16Reloc(uint8_t *location, uint16_t result, uint16_t mask = 0xFFFF) {
- assert(!(result & ~mask));
- write16le(location, (read16le(location) & ~mask) | (result & mask));
- return std::error_code();
-}
-
-/// \brief R_ARM_ABS32 - (S + A) | T
-static std::error_code relocR_ARM_ABS32(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- uint32_t result = (uint32_t)((S + A) | T);
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return applyArmReloc(location, result);
-}
-
-/// \brief R_ARM_REL32 - ((S + A) | T) - P
-static std::error_code relocR_ARM_REL32(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- uint32_t result = (uint32_t)(((S + A) | T) - P);
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return applyArmReloc(location, result);
-}
-
-/// \brief R_ARM_PREL31 - ((S + A) | T) - P
-static std::error_code relocR_ARM_PREL31(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- uint32_t result = (uint32_t)(((S + A) | T) - P);
- if (!llvm::isInt<31>((int32_t)result))
- return make_out_of_range_reloc_error();
-
- const uint32_t mask = 0x7FFFFFFF;
- uint32_t rel31 = result & mask;
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result);
- llvm::dbgs() << " rel31: 0x" << Twine::utohexstr(rel31) << "\n");
-
- return applyArmReloc(location, rel31, mask);
-}
-
-/// \brief Relocate B/BL instructions. useJs defines whether J1 & J2 are used
-static std::error_code relocR_ARM_THM_B_L(uint8_t *location, uint32_t result,
- bool useJs) {
- if ((useJs && !llvm::isInt<25>((int32_t)result)) ||
- (!useJs && !llvm::isInt<23>((int32_t)result)))
- return make_out_of_range_reloc_error();
-
- result = (result & 0x01FFFFFE) >> 1;
-
- const uint16_t imm10 = (result >> 11) & 0x3FF;
- const uint16_t bitS = (result >> 23) & 0x1;
- const uint16_t resHi = (bitS << 10) | imm10;
-
- const uint16_t imm11 = result & 0x7FF;
- const uint16_t bitJ2 = useJs ? ((result >> 21) & 0x1) : bitS;
- const uint16_t bitI2 = (~(bitJ2 ^ bitS)) & 0x1;
- const uint16_t bitJ1 = useJs ? ((result >> 22) & 0x1) : bitS;
- const uint16_t bitI1 = (~(bitJ1 ^ bitS)) & 0x1;
- const uint16_t resLo = (bitI1 << 13) | (bitI2 << 11) | imm11;
-
- return applyThumb32Reloc(location, resHi, resLo, 0x7FF, 0x2FFF);
-}
-
-/// \brief R_ARM_THM_CALL - ((S + A) | T) - P
-static std::error_code relocR_ARM_THM_CALL(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A, bool useJs,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- const bool switchMode = !addressesThumb;
-
- if (switchMode) {
- P &= ~0x3; // Align(P, 4) by rounding down
- }
-
- uint32_t result = (uint32_t)(((S + A) | T) - P);
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- if (auto ec = relocR_ARM_THM_B_L(location, result, useJs))
- return ec;
-
- if (switchMode) {
- return applyThumb32Reloc(location, 0, 0, 0, 0x1001);
- }
- return std::error_code();
-}
-
-/// \brief R_ARM_THM_JUMP24 - ((S + A) | T) - P
-static std::error_code relocR_ARM_THM_JUMP24(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- uint32_t result = (uint32_t)(((S + A) | T) - P);
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return relocR_ARM_THM_B_L(location, result, true);
-}
-
-/// \brief R_ARM_THM_JUMP11 - S + A - P
-static std::error_code relocR_ARM_THM_JUMP11(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- uint32_t result = (uint32_t)(S + A - P);
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
-
- if (!llvm::isInt<12>((int32_t)result))
- return make_out_of_range_reloc_error();
-
- // we cut off first bit because it is always 1 according to p. 4.5.3
- result = (result & 0x0FFE) >> 1;
- return applyThumb16Reloc(location, result, 0x7FF);
-}
-
-/// \brief R_ARM_BASE_PREL - B(S) + A - P => S + A - P
-static std::error_code relocR_ARM_BASE_PREL(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- uint32_t result = (uint32_t)(S + A - P);
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return applyArmReloc(location, result);
-}
-
-/// \brief R_ARM_GOT_BREL - GOT(S) + A - GOT_ORG => S + A - GOT_ORG
-static std::error_code relocR_ARM_GOT_BREL(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- uint64_t GOT_ORG) {
- uint32_t result = (uint32_t)(S + A - GOT_ORG);
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return applyArmReloc(location, result);
-}
-
-/// \brief R_ARM_CALL - ((S + A) | T) - P
-static std::error_code relocR_ARM_CALL(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- const bool switchMode = addressesThumb;
-
- uint32_t result = (uint32_t)(((S + A) | T) - P);
- if (!llvm::isInt<26>((int32_t)result))
- return make_out_of_range_reloc_error();
-
- const uint32_t imm24 = (result & 0x03FFFFFC) >> 2;
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- if (auto ec = applyArmReloc(location, imm24, 0xFFFFFF))
- return ec;
-
- if (switchMode) {
- const uint32_t bitH = (result & 0x2) >> 1;
- return applyArmReloc(location, (0xFA | bitH) << 24, 0xFF000000);
- }
- return std::error_code();
-}
-
-/// \brief R_ARM_JUMP24 - ((S + A) | T) - P
-static std::error_code relocR_ARM_JUMP24(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- uint32_t result = (uint32_t)(((S + A) | T) - P);
- if (!llvm::isInt<26>((int32_t)result))
- return make_out_of_range_reloc_error();
-
- const uint32_t imm24 = (result & 0x03FFFFFC) >> 2;
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return applyArmReloc(location, imm24, 0xFFFFFF);
-}
-
-/// \brief Relocate ARM MOVW/MOVT instructions
-static std::error_code relocR_ARM_MOV(uint8_t *location, uint32_t result) {
- const uint32_t imm12 = result & 0xFFF;
- const uint32_t imm4 = (result >> 12) & 0xF;
-
- return applyArmReloc(location, (imm4 << 16) | imm12, 0xF0FFF);
-}
-
-/// \brief R_ARM_MOVW_ABS_NC - (S + A) | T
-static std::error_code relocR_ARM_MOVW_ABS_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- uint32_t result = (uint32_t)((S + A) | T);
- const uint32_t arg = result & 0x0000FFFF;
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return relocR_ARM_MOV(location, arg);
-}
-
-/// \brief R_ARM_MOVT_ABS - S + A
-static std::error_code relocR_ARM_MOVT_ABS(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- uint32_t result = (uint32_t)(S + A);
- const uint32_t arg = (result & 0xFFFF0000) >> 16;
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return relocR_ARM_MOV(location, arg);
-}
-
-/// \brief Relocate Thumb MOVW/MOVT instructions
-static std::error_code relocR_ARM_THM_MOV(uint8_t *location, uint32_t result) {
- const uint16_t imm8 = result & 0xFF;
- const uint16_t imm3 = (result >> 8) & 0x7;
- const uint16_t resLo = (imm3 << 12) | imm8;
-
- const uint16_t imm4 = (result >> 12) & 0xF;
- const uint16_t bitI = (result >> 11) & 0x1;
- const uint16_t resHi = (bitI << 10) | imm4;
-
- return applyThumb32Reloc(location, resHi, resLo, 0x40F, 0x70FF);
-}
-
-/// \brief R_ARM_THM_MOVW_ABS_NC - (S + A) | T
-static std::error_code relocR_ARM_THM_MOVW_ABS_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
- uint64_t T = addressesThumb;
- uint32_t result = (uint32_t)((S + A) | T);
- const uint32_t arg = result & 0x0000FFFF;
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " T: 0x" << Twine::utohexstr(T);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return relocR_ARM_THM_MOV(location, arg);
-}
-
-/// \brief R_ARM_THM_MOVT_ABS - S + A
-static std::error_code relocR_ARM_THM_MOVT_ABS(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- uint32_t result = (uint32_t)(S + A);
- const uint32_t arg = (result & 0xFFFF0000) >> 16;
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return relocR_ARM_THM_MOV(location, arg);
-}
-
-/// \brief R_ARM_TLS_IE32 - GOT(S) + A - P => S + A - P
-static std::error_code relocR_ARM_TLS_IE32(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- uint32_t result = (uint32_t)(S + A - P);
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return applyArmReloc(location, result);
-}
-
-/// \brief R_ARM_TLS_LE32 - S + A - tp => S + A + tpoff
-static std::error_code relocR_ARM_TLS_LE32(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- uint64_t tpoff) {
- uint32_t result = (uint32_t)(S + A + tpoff);
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return applyArmReloc(location, result);
-}
-
-/// \brief R_ARM_TLS_TPOFF32 - S + A - tp => S + A (offset within TLS block)
-static std::error_code relocR_ARM_TLS_TPOFF32(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- uint32_t result = (uint32_t)(S + A);
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
- return applyArmReloc(location, result);
-}
-
-template <uint32_t lshift>
-static std::error_code relocR_ARM_ALU_PC_GN_NC(uint8_t *location,
- uint32_t result) {
- static_assert(lshift < 32 && lshift % 2 == 0,
- "lshift must be even and less than word size");
-
- const uint32_t rshift = 32 - lshift;
- result = ((result >> lshift) & 0xFF) | ((rshift / 2) << 8);
-
- return applyArmReloc(location, result, 0xFFF);
-}
-
-/// \brief R_ARM_ALU_PC_G0_NC - ((S + A) | T) - P => S + A - P
-static std::error_code relocR_ARM_ALU_PC_G0_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)(S + A - P);
- if (result < 0)
- report_unsupported_range_group_reloc_error();
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr((uint32_t)result)
- << "\n");
-
- return relocR_ARM_ALU_PC_GN_NC<20>(location, (uint32_t)result);
-}
-
-/// \brief R_ARM_ALU_PC_G1_NC - ((S + A) | T) - P => S + A - P
-static std::error_code relocR_ARM_ALU_PC_G1_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)(S + A - P);
- if (result < 0)
- report_unsupported_range_group_reloc_error();
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr((uint32_t)result)
- << "\n");
-
- return relocR_ARM_ALU_PC_GN_NC<12>(location, (uint32_t)result);
-}
-
-/// \brief R_ARM_LDR_PC_G2 - S + A - P
-static std::error_code relocR_ARM_LDR_PC_G2(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = (int32_t)(S + A - P);
- if (result < 0)
- report_unsupported_range_group_reloc_error();
-
- DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
- llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
- llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
- llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
- llvm::dbgs() << " result: 0x" << Twine::utohexstr((uint32_t)result)
- << "\n");
-
- const uint32_t mask = 0xFFF;
- return applyArmReloc(location, (uint32_t)result & mask, mask);
-}
-
-/// \brief Fixup unresolved weak reference with NOP instruction
-static bool fixupUnresolvedWeakCall(uint8_t *location,
- Reference::KindValue kindValue) {
- // TODO: workaround for archs without NOP instruction
- switch (kindValue) {
- case R_ARM_THM_CALL:
- case R_ARM_THM_JUMP24:
- // Thumb32 NOP.W
- write32le(location, 0x8000F3AF);
- break;
- case R_ARM_THM_JUMP11:
- // Thumb16 NOP
- write16le(location, 0xBF00);
- break;
- case R_ARM_CALL:
- case R_ARM_JUMP24:
- // A1 NOP<c>, save condition bits
- applyArmReloc(location, 0x320F000, 0xFFFFFFF);
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-std::error_code ARMTargetRelocationHandler::applyRelocation(
- ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
- const Reference &ref) const {
- uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *loc = atomContent + ref.offsetInAtom();
- uint64_t target = writer.addressOfAtom(ref.target());
- uint64_t reloc = atom._virtualAddr + ref.offsetInAtom();
-
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return std::error_code();
- assert(ref.kindArch() == Reference::KindArch::ARM);
-
- // Fixup unresolved weak references
- if (!target) {
- bool isCallFixed = fixupUnresolvedWeakCall(loc, ref.kindValue());
-
- if (isCallFixed) {
- DEBUG(llvm::dbgs() << "\t\tFixup unresolved weak reference '";
- llvm::dbgs() << ref.target()->name() << "'";
- llvm::dbgs() << " at address: 0x" << Twine::utohexstr(reloc);
- llvm::dbgs() << (isCallFixed ? "\n" : " isn't possible\n"));
- return std::error_code();
- }
- }
-
- // Calculate proper initial addend for the relocation
- const Reference::Addend addend =
- readAddend(loc, ref.kindValue()) + ref.addend();
-
- // Flags that the relocation addresses Thumb instruction
- bool thumb = false;
- if (const auto *definedAtom = dyn_cast<DefinedAtom>(ref.target())) {
- thumb = isThumbCode(definedAtom);
- }
-
- switch (ref.kindValue()) {
- case R_ARM_NONE:
- return std::error_code();
- case R_ARM_ABS32:
- return relocR_ARM_ABS32(loc, reloc, target, addend, thumb);
- case R_ARM_REL32:
- return relocR_ARM_REL32(loc, reloc, target, addend, thumb);
- case R_ARM_TARGET1:
- if (_armLayout.target1Rel())
- return relocR_ARM_REL32(loc, reloc, target, addend, thumb);
- else
- return relocR_ARM_ABS32(loc, reloc, target, addend, thumb);
- case R_ARM_THM_CALL:
- // TODO: consider adding bool variable to disable J1 & J2 for archs
- // before ARMv6
- return relocR_ARM_THM_CALL(loc, reloc, target, addend, true, thumb);
- case R_ARM_CALL:
- return relocR_ARM_CALL(loc, reloc, target, addend, thumb);
- case R_ARM_JUMP24:
- return relocR_ARM_JUMP24(loc, reloc, target, addend, thumb);
- case R_ARM_THM_JUMP24:
- return relocR_ARM_THM_JUMP24(loc, reloc, target, addend, thumb);
- case R_ARM_THM_JUMP11:
- return relocR_ARM_THM_JUMP11(loc, reloc, target, addend);
- case R_ARM_MOVW_ABS_NC:
- return relocR_ARM_MOVW_ABS_NC(loc, reloc, target, addend, thumb);
- case R_ARM_MOVT_ABS:
- return relocR_ARM_MOVT_ABS(loc, reloc, target, addend);
- case R_ARM_THM_MOVW_ABS_NC:
- return relocR_ARM_THM_MOVW_ABS_NC(loc, reloc, target, addend, thumb);
- case R_ARM_THM_MOVT_ABS:
- return relocR_ARM_THM_MOVT_ABS(loc, reloc, target, addend);
- case R_ARM_PREL31:
- return relocR_ARM_PREL31(loc, reloc, target, addend, thumb);
- case R_ARM_TLS_IE32:
- return relocR_ARM_TLS_IE32(loc, reloc, target, addend);
- case R_ARM_TLS_LE32:
- return relocR_ARM_TLS_LE32(loc, reloc, target, addend,
- _armLayout.getTPOffset());
- case R_ARM_TLS_TPOFF32:
- return relocR_ARM_TLS_TPOFF32(loc, reloc, target, addend);
- case R_ARM_GOT_BREL:
- return relocR_ARM_GOT_BREL(loc, reloc, target, addend,
- _armLayout.getGOTSymAddr());
- case R_ARM_BASE_PREL:
- // GOT origin is used for NULL symbol and when explicitly specified
- if (!target || ref.target()->name().equals("_GLOBAL_OFFSET_TABLE_")) {
- target = _armLayout.getGOTSymAddr();
- } else {
- return make_dynamic_error_code(
- "Segment-base relative addressing is not supported");
- }
- return relocR_ARM_BASE_PREL(loc, reloc, target, addend);
- case R_ARM_ALU_PC_G0_NC:
- return relocR_ARM_ALU_PC_G0_NC(loc, reloc, target, addend);
- case R_ARM_ALU_PC_G1_NC:
- return relocR_ARM_ALU_PC_G1_NC(loc, reloc, target, addend);
- case R_ARM_LDR_PC_G2:
- return relocR_ARM_LDR_PC_G2(loc, reloc, target, addend);
- case R_ARM_JUMP_SLOT:
- case R_ARM_GLOB_DAT:
- case R_ARM_IRELATIVE:
- // Runtime only relocations. Ignore here.
- return std::error_code();
- case R_ARM_V4BX:
- // TODO implement
- return std::error_code();
- default:
- return make_unhandled_reloc_error();
- }
-
- llvm_unreachable("All switch cases must return directly");
-}
diff --git a/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h b/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h
deleted file mode 100644
index a1f3d091f204..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h ------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_RELOCATION_HANDLER_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_RELOCATION_HANDLER_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-class ARMTargetLayout;
-
-class ARMTargetRelocationHandler final : public TargetRelocationHandler {
-public:
- ARMTargetRelocationHandler(ARMTargetLayout &layout) : _armLayout(layout) {}
-
- std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const AtomLayout &,
- const Reference &) const override;
-
-private:
- ARMTargetLayout &_armLayout;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_ELF_ARM_ARM_RELOCATION_HANDLER_H
diff --git a/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp b/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
deleted file mode 100644
index fc2ae75cd7a7..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
+++ /dev/null
@@ -1,985 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Defines the relocation processing pass for ARM. This includes
-/// GOT and PLT entries, TLS, COPY, and ifunc.
-///
-/// This also includes additional behavior that gnu-ld and gold implement but
-/// which is not specified anywhere.
-///
-//===----------------------------------------------------------------------===//
-
-#include "ARMRelocationPass.h"
-#include "ARMLinkingContext.h"
-#include "Atoms.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::ELF;
-
-namespace {
-// ARM B/BL instructions of absolute relocation veneer.
-// TODO: consider different instruction set for archs below ARMv5
-// (one as for Thumb may be used though it's less optimal).
-static const uint8_t Veneer_ARM_B_BL_Abs_a_AtomContent[4] = {
- 0x04, 0xf0, 0x1f, 0xe5 // ldr pc, [pc, #-4]
-};
-static const uint8_t Veneer_ARM_B_BL_Abs_d_AtomContent[4] = {
- 0x00, 0x00, 0x00, 0x00 // <target_symbol_address>
-};
-
-// Thumb B/BL instructions of absolute relocation veneer.
-// TODO: consider different instruction set for archs above ARMv5
-// (one as for ARM may be used since it's more optimal).
-static const uint8_t Veneer_THM_B_BL_Abs_t_AtomContent[4] = {
- 0x78, 0x47, // bx pc
- 0x00, 0x00 // nop
-};
-static const uint8_t Veneer_THM_B_BL_Abs_a_AtomContent[4] = {
- 0xfe, 0xff, 0xff, 0xea // b <target_symbol_address>
-};
-
-// .got values
-static const uint8_t ARMGotAtomContent[4] = {0};
-
-// .plt value (entry 0)
-static const uint8_t ARMPlt0_a_AtomContent[16] = {
- 0x04, 0xe0, 0x2d, 0xe5, // push {lr}
- 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, [pc, #4]
- 0x0e, 0xe0, 0x8f, 0xe0, // add lr, pc, lr
- 0x00, 0xf0, 0xbe, 0xe5 // ldr pc, [lr, #0]!
-};
-static const uint8_t ARMPlt0_d_AtomContent[4] = {
- 0x00, 0x00, 0x00, 0x00 // <got1_symbol_address>
-};
-
-// .plt values (other entries)
-static const uint8_t ARMPltAtomContent[12] = {
- 0x00, 0xc0, 0x8f, 0xe2, // add ip, pc, #offset[G0]
- 0x00, 0xc0, 0x8c, 0xe2, // add ip, ip, #offset[G1]
- 0x00, 0xf0, 0xbc, 0xe5 // ldr pc, [ip, #offset[G2]]!
-};
-
-// Veneer for switching from Thumb to ARM code for PLT entries.
-static const uint8_t ARMPltVeneerAtomContent[4] = {
- 0x78, 0x47, // bx pc
- 0x00, 0x00 // nop
-};
-
-// Determine proper names for mapping symbols.
-static std::string getMappingAtomName(DefinedAtom::CodeModel model,
- const std::string &part) {
- switch (model) {
- case DefinedAtom::codeARM_a:
- return part.empty() ? "$a" : "$a." + part;
- case DefinedAtom::codeARM_d:
- return part.empty() ? "$d" : "$d." + part;
- case DefinedAtom::codeARM_t:
- return part.empty() ? "$t" : "$t." + part;
- default:
- llvm_unreachable("Wrong code model of mapping atom");
- }
-}
-
-/// \brief Atoms that hold veneer code.
-class VeneerAtom : public SimpleELFDefinedAtom {
- StringRef _section;
-
-public:
- VeneerAtom(const File &f, StringRef secName, const std::string &name = "")
- : SimpleELFDefinedAtom(f), _section(secName), _name(name) {}
-
- Scope scope() const override { return DefinedAtom::scopeTranslationUnit; }
-
- SectionChoice sectionChoice() const override {
- return DefinedAtom::sectionBasedOnContent;
- }
-
- StringRef customSectionName() const override { return _section; }
-
- ContentType contentType() const override { return DefinedAtom::typeCode; }
-
- uint64_t size() const override { return rawContent().size(); }
-
- ContentPermissions permissions() const override { return permR_X; }
-
- Alignment alignment() const override { return 4; }
-
- StringRef name() const override { return _name; }
-
-private:
- std::string _name;
-};
-
-/// \brief Atoms that hold veneer for relocated ARM B/BL instructions
-/// in absolute code.
-class Veneer_ARM_B_BL_Abs_a_Atom : public VeneerAtom {
-public:
- Veneer_ARM_B_BL_Abs_a_Atom(const File &f, StringRef secName,
- const std::string &name)
- : VeneerAtom(f, secName, name) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(Veneer_ARM_B_BL_Abs_a_AtomContent);
- }
-};
-
-class Veneer_ARM_B_BL_Abs_d_Atom : public VeneerAtom {
-public:
- Veneer_ARM_B_BL_Abs_d_Atom(const File &f, StringRef secName)
- : VeneerAtom(f, secName) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(Veneer_ARM_B_BL_Abs_d_AtomContent);
- }
-};
-
-/// \brief Atoms that hold veneer for relocated Thumb B/BL instructions
-/// in absolute code.
-class Veneer_THM_B_BL_Abs_t_Atom : public VeneerAtom {
-public:
- Veneer_THM_B_BL_Abs_t_Atom(const File &f, StringRef secName,
- const std::string &name)
- : VeneerAtom(f, secName, name) {}
-
- DefinedAtom::CodeModel codeModel() const override {
- return DefinedAtom::codeARMThumb;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(Veneer_THM_B_BL_Abs_t_AtomContent);
- }
-};
-
-class Veneer_THM_B_BL_Abs_a_Atom : public VeneerAtom {
-public:
- Veneer_THM_B_BL_Abs_a_Atom(const File &f, StringRef secName)
- : VeneerAtom(f, secName) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(Veneer_THM_B_BL_Abs_a_AtomContent);
- }
-};
-
-template <DefinedAtom::CodeModel Model>
-class ARMVeneerMappingAtom : public VeneerAtom {
-public:
- ARMVeneerMappingAtom(const File &f, StringRef secName, StringRef name)
- : VeneerAtom(f, secName, getMappingAtomName(Model, name)) {
- static_assert((Model == DefinedAtom::codeARM_a ||
- Model == DefinedAtom::codeARM_d ||
- Model == DefinedAtom::codeARM_t),
- "Only mapping atom types are allowed");
- }
-
- uint64_t size() const override { return 0; }
-
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-
- DefinedAtom::CodeModel codeModel() const override { return Model; }
-};
-
-template <class BaseAtom, DefinedAtom::CodeModel Model>
-class BaseMappingAtom : public BaseAtom {
-public:
- BaseMappingAtom(const File &f, StringRef secName, StringRef name)
- : BaseAtom(f, secName) {
- static_assert((Model == DefinedAtom::codeARM_a ||
- Model == DefinedAtom::codeARM_d ||
- Model == DefinedAtom::codeARM_t),
- "Only mapping atom types are allowed");
-#ifndef NDEBUG
- _name = name;
-#else
- _name = getMappingAtomName(Model, name);
-#endif
- }
-
- DefinedAtom::CodeModel codeModel() const override {
-#ifndef NDEBUG
- return isThumbCode(Model) ? DefinedAtom::codeARMThumb : DefinedAtom::codeNA;
-#else
- return Model;
-#endif
- }
-
- StringRef name() const override { return _name; }
-
-private:
- std::string _name;
-};
-
-/// \brief Atoms that are used by ARM dynamic linking
-class ARMGOTAtom : public GOTAtom {
-public:
- ARMGOTAtom(const File &f) : GOTAtom(f, ".got") {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(ARMGotAtomContent);
- }
-
- Alignment alignment() const override { return 4; }
-
-protected:
- // Constructor for PLTGOT atom.
- ARMGOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
-};
-
-class ARMGOTPLTAtom : public ARMGOTAtom {
-public:
- ARMGOTPLTAtom(const File &f) : ARMGOTAtom(f, ".got.plt") {}
-};
-
-/// \brief Proxy class to keep type compatibility with PLT0Atom.
-class ARMPLT0Atom : public PLT0Atom {
-public:
- ARMPLT0Atom(const File &f, StringRef) : PLT0Atom(f) {}
-};
-
-/// \brief PLT0 entry atom.
-/// Serves as a mapping symbol in the release mode.
-class ARMPLT0_a_Atom
- : public BaseMappingAtom<ARMPLT0Atom, DefinedAtom::codeARM_a> {
-public:
- ARMPLT0_a_Atom(const File &f, const std::string &name)
- : BaseMappingAtom(f, ".plt", name) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(ARMPlt0_a_AtomContent);
- }
-
- Alignment alignment() const override { return 4; }
-};
-
-class ARMPLT0_d_Atom
- : public BaseMappingAtom<ARMPLT0Atom, DefinedAtom::codeARM_d> {
-public:
- ARMPLT0_d_Atom(const File &f, const std::string &name)
- : BaseMappingAtom(f, ".plt", name) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(ARMPlt0_d_AtomContent);
- }
-
- Alignment alignment() const override { return 4; }
-};
-
-/// \brief PLT entry atom.
-/// Serves as a mapping symbol in the release mode.
-class ARMPLTAtom : public BaseMappingAtom<PLTAtom, DefinedAtom::codeARM_a> {
-public:
- ARMPLTAtom(const File &f, const std::string &name)
- : BaseMappingAtom(f, ".plt", name) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(ARMPltAtomContent);
- }
-
- Alignment alignment() const override { return 4; }
-};
-
-/// \brief Veneer atom for PLT entry.
-/// Serves as a mapping symbol in the release mode.
-class ARMPLTVeneerAtom
- : public BaseMappingAtom<PLTAtom, DefinedAtom::codeARM_t> {
-public:
- ARMPLTVeneerAtom(const File &f, const std::string &name)
- : BaseMappingAtom(f, ".plt", name) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(ARMPltVeneerAtomContent);
- }
-
- Alignment alignment() const override { return 4; }
-};
-
-/// \brief Atom which represents an object for which a COPY relocation will
-/// be generated.
-class ARMObjectAtom : public ObjectAtom {
-public:
- ARMObjectAtom(const File &f) : ObjectAtom(f) {}
- Alignment alignment() const override { return 4; }
-};
-
-class ELFPassFile : public SimpleFile {
-public:
- ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
- setOrdinal(eti.getNextOrdinalAndIncrement());
- }
-
- llvm::BumpPtrAllocator _alloc;
-};
-
-/// \brief CRTP base for handling relocations.
-template <class Derived> class ARMRelocationPass : public Pass {
- /// \brief Handle a specific reference.
- void handleReference(const DefinedAtom &atom, const Reference &ref) {
- DEBUG_WITH_TYPE(
- "ARM", llvm::dbgs() << "\t" << LLVM_FUNCTION_NAME << "()"
- << ": Name of Defined Atom: " << atom.name().str();
- llvm::dbgs() << " kindValue: " << ref.kindValue() << "\n");
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return;
- assert(ref.kindArch() == Reference::KindArch::ARM);
- switch (ref.kindValue()) {
- case R_ARM_ABS32:
- case R_ARM_REL32:
- case R_ARM_TARGET1:
- case R_ARM_MOVW_ABS_NC:
- case R_ARM_MOVT_ABS:
- case R_ARM_THM_MOVW_ABS_NC:
- case R_ARM_THM_MOVT_ABS:
- static_cast<Derived *>(this)->handlePlain(isThumbCode(&atom), ref);
- break;
- case R_ARM_THM_CALL:
- case R_ARM_CALL:
- case R_ARM_JUMP24:
- case R_ARM_THM_JUMP24:
- case R_ARM_THM_JUMP11: {
- const auto actualModel = actualSourceCodeModel(atom, ref);
- const bool fromThumb = isThumbCode(actualModel);
- static_cast<Derived *>(this)->handlePlain(fromThumb, ref);
- static_cast<Derived *>(this)->handleVeneer(atom, fromThumb, ref);
- } break;
- case R_ARM_TLS_IE32:
- static_cast<Derived *>(this)->handleTLSIE32(ref);
- break;
- case R_ARM_GOT_BREL:
- static_cast<Derived *>(this)->handleGOT(ref);
- break;
- default:
- break;
- }
- }
-
-protected:
- /// \brief Determine source atom's actual code model.
- ///
- /// Actual code model may differ from the existing one if fixup
- /// is possible on the later stages for given relocation type.
- DefinedAtom::CodeModel actualSourceCodeModel(const DefinedAtom &atom,
- const Reference &ref) {
- const auto kindValue = ref.kindValue();
- if (kindValue != R_ARM_CALL && kindValue != R_ARM_THM_CALL)
- return atom.codeModel();
-
- // TODO: For unconditional jump instructions (R_ARM_CALL and R_ARM_THM_CALL)
- // fixup isn't possible without veneer generation for archs below ARMv5.
-
- auto actualModel = atom.codeModel();
- if (const auto *da = dyn_cast<DefinedAtom>(ref.target())) {
- actualModel = da->codeModel();
- } else if (const auto *sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
- if (sla->type() == SharedLibraryAtom::Type::Code) {
- // PLT entry will be generated here - assume we don't want a veneer
- // on top of it and prefer instruction fixup if needed.
- actualModel = DefinedAtom::codeNA;
- }
- }
- return actualModel;
- }
-
- std::error_code handleVeneer(const DefinedAtom &atom, bool fromThumb,
- const Reference &ref) {
- // Actual instruction mode differs meaning that further fixup will be
- // applied.
- if (isThumbCode(&atom) != fromThumb)
- return std::error_code();
-
- const VeneerAtom *(Derived::*getVeneer)(const DefinedAtom *, StringRef) =
- nullptr;
- const auto kindValue = ref.kindValue();
- switch (kindValue) {
- case R_ARM_JUMP24:
- getVeneer = &Derived::getVeneer_ARM_B_BL;
- break;
- case R_ARM_THM_JUMP24:
- getVeneer = &Derived::getVeneer_THM_B_BL;
- break;
- default:
- return std::error_code();
- }
-
- // Target symbol and relocated place should have different
- // instruction sets in order a veneer to be generated in between.
- const auto *target = dyn_cast<DefinedAtom>(ref.target());
- if (!target || isThumbCode(target) == isThumbCode(&atom))
- return std::error_code();
-
- // Veneers may only be generated for STT_FUNC target symbols
- // or for symbols located in sections different to the place of relocation.
- StringRef secName = atom.customSectionName();
- if (DefinedAtom::typeCode != target->contentType() &&
- !target->customSectionName().equals(secName)) {
- StringRef kindValStr;
- if (!this->_ctx.registry().referenceKindToString(
- ref.kindNamespace(), ref.kindArch(), kindValue, kindValStr)) {
- kindValStr = "unknown";
- }
-
- std::string errStr =
- (Twine("Reference of type ") + Twine(kindValue) + " (" + kindValStr +
- ") from " + atom.name() + "+" + Twine(ref.offsetInAtom()) + " to " +
- ref.target()->name() + "+" + Twine(ref.addend()) +
- " cannot be effected without a veneer").str();
-
- llvm_unreachable(errStr.c_str());
- }
-
- assert(getVeneer && "The veneer handler is missing");
- const Atom *veneer =
- (static_cast<Derived *>(this)->*getVeneer)(target, secName);
-
- assert(veneer && "The veneer is not set");
- const_cast<Reference &>(ref).setTarget(veneer);
- return std::error_code();
- }
-
- /// \brief Get the veneer for ARM B/BL instructions
- /// in absolute code.
- const VeneerAtom *getVeneer_ARM_B_BL_Abs(const DefinedAtom *da,
- StringRef secName) {
- auto veneer = _veneerAtoms.lookup(da);
- if (!veneer.empty())
- return veneer._veneer;
-
- std::string name = "__";
- name += da->name();
- name += "_from_arm";
- // Create parts of veneer with mapping symbols.
- auto v_a =
- new (_file._alloc) Veneer_ARM_B_BL_Abs_a_Atom(_file, secName, name);
- addVeneerWithMapping<DefinedAtom::codeARM_a>(da, v_a, name);
- auto v_d = new (_file._alloc) Veneer_ARM_B_BL_Abs_d_Atom(_file, secName);
- addVeneerWithMapping<DefinedAtom::codeARM_d>(v_a, v_d, name);
-
- // Fake reference to show connection between parts of veneer.
- v_a->addReferenceELF_ARM(R_ARM_NONE, 0, v_d, 0);
- // Real reference to fixup.
- v_d->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0);
- return v_a;
- }
-
- /// \brief Get the veneer for Thumb B/BL instructions
- /// in absolute code.
- const VeneerAtom *getVeneer_THM_B_BL_Abs(const DefinedAtom *da,
- StringRef secName) {
- auto veneer = _veneerAtoms.lookup(da);
- if (!veneer.empty())
- return veneer._veneer;
-
- std::string name = "__";
- name += da->name();
- name += "_from_thumb";
- // Create parts of veneer with mapping symbols.
- auto v_t =
- new (_file._alloc) Veneer_THM_B_BL_Abs_t_Atom(_file, secName, name);
- addVeneerWithMapping<DefinedAtom::codeARM_t>(da, v_t, name);
- auto v_a = new (_file._alloc) Veneer_THM_B_BL_Abs_a_Atom(_file, secName);
- addVeneerWithMapping<DefinedAtom::codeARM_a>(v_t, v_a, name);
-
- // Fake reference to show connection between parts of veneer.
- v_t->addReferenceELF_ARM(R_ARM_NONE, 0, v_a, 0);
- // Real reference to fixup.
- v_a->addReferenceELF_ARM(R_ARM_JUMP24, 0, da, 0);
- return v_t;
- }
-
- std::error_code handleTLSIE32(const Reference &ref) {
- if (const auto *target = dyn_cast<DefinedAtom>(ref.target())) {
- const_cast<Reference &>(ref)
- .setTarget(static_cast<Derived *>(this)->getTLSTPOFF32(target));
- return std::error_code();
- }
- llvm_unreachable("R_ARM_TLS_IE32 reloc targets wrong atom type");
- }
-
- /// \brief Create a GOT entry for TLS with reloc type and addend specified.
- template <Reference::KindValue R_ARM_TLS, Reference::Addend A = 0>
- const GOTAtom *getGOTTLSEntry(const DefinedAtom *da) {
- StringRef source;
-#ifndef NDEBUG
- source = "_tls_";
-#endif
- return getGOT<R_ARM_TLS, A>(da, source);
- }
-
- /// \brief Add veneer with mapping symbol.
- template <DefinedAtom::CodeModel Model>
- void addVeneerWithMapping(const DefinedAtom *da, VeneerAtom *va,
- const std::string &name) {
- assert(_veneerAtoms.lookup(da).empty() &&
- "Veneer or mapping already exists");
- auto *ma = new (_file._alloc)
- ARMVeneerMappingAtom<Model>(_file, va->customSectionName(), name);
-
- // Fake reference to show connection between the mapping symbol and veneer.
- va->addReferenceELF_ARM(R_ARM_NONE, 0, ma, 0);
- _veneerAtoms[da] = VeneerWithMapping(va, ma);
- }
-
- /// \brief get a veneer for a PLT entry.
- const PLTAtom *getPLTVeneer(const Atom *da, PLTAtom *pa, StringRef source) {
- std::string name = "__plt_from_thumb";
- name += source.empty() ? "_" : source;
- name += da->name();
- // Create veneer for PLT entry.
- auto va = new (_file._alloc) ARMPLTVeneerAtom(_file, name);
- // Fake reference to show connection between veneer and PLT entry.
- va->addReferenceELF_ARM(R_ARM_NONE, 0, pa, 0);
-
- _pltAtoms[da] = PLTWithVeneer(pa, va);
- return va;
- }
-
- typedef const GOTAtom *(Derived::*GOTFactory)(const Atom *);
-
- /// \brief get a PLT entry referencing PLTGOT entry.
- ///
- /// If the entry does not exist, both GOT and PLT entry are created.
- const PLTAtom *getPLT(const Atom *da, bool fromThumb, GOTFactory gotFactory,
- StringRef source = "") {
- auto pltVeneer = _pltAtoms.lookup(da);
- if (!pltVeneer.empty()) {
- // Return clean PLT entry provided it is ARM code.
- if (!fromThumb)
- return pltVeneer._plt;
-
- // Check if veneer is present for Thumb to ARM transition.
- if (pltVeneer._veneer)
- return pltVeneer._veneer;
-
- // Create veneer for existing PLT entry.
- return getPLTVeneer(da, pltVeneer._plt, source);
- }
-
- // Create specific GOT entry.
- const auto *ga = (static_cast<Derived *>(this)->*gotFactory)(da);
- assert(_gotpltAtoms.lookup(da) == ga &&
- "GOT entry should be added to the PLTGOT map");
- assert(ga->customSectionName() == ".got.plt" &&
- "GOT entry should be in a special section");
-
- std::string name = "__plt";
- name += source.empty() ? "_" : source;
- name += da->name();
- // Create PLT entry for the GOT entry.
- auto pa = new (_file._alloc) ARMPLTAtom(_file, name);
- pa->addReferenceELF_ARM(R_ARM_ALU_PC_G0_NC, 0, ga, -8);
- pa->addReferenceELF_ARM(R_ARM_ALU_PC_G1_NC, 4, ga, -4);
- pa->addReferenceELF_ARM(R_ARM_LDR_PC_G2, 8, ga, 0);
-
- // Since all PLT entries are in ARM code, Thumb to ARM
- // switching should be added if the relocated place contais Thumb code.
- if (fromThumb)
- return getPLTVeneer(da, pa, source);
-
- // Otherwise just add PLT entry and return it to the caller.
- _pltAtoms[da] = PLTWithVeneer(pa);
- return pa;
- }
-
- /// \brief Create the GOT entry for a given IFUNC Atom.
- const GOTAtom *createIFUNCGOT(const Atom *da) {
- assert(!_gotpltAtoms.lookup(da) && "IFUNC GOT entry already exists");
- auto g = new (_file._alloc) ARMGOTPLTAtom(_file);
- g->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0);
- g->addReferenceELF_ARM(R_ARM_IRELATIVE, 0, da, 0);
-#ifndef NDEBUG
- g->_name = "__got_ifunc_";
- g->_name += da->name();
-#endif
- _gotpltAtoms[da] = g;
- return g;
- }
-
- /// \brief get the PLT entry for a given IFUNC Atom.
- const PLTAtom *getIFUNCPLTEntry(const DefinedAtom *da, bool fromThumb) {
- return getPLT(da, fromThumb, &Derived::createIFUNCGOT, "_ifunc_");
- }
-
- /// \brief Redirect the call to the PLT stub for the target IFUNC.
- ///
- /// This create a PLT and GOT entry for the IFUNC if one does not exist. The
- /// GOT entry and a IRELATIVE relocation to the original target resolver.
- std::error_code handleIFUNC(bool fromThumb, const Reference &ref) {
- auto target = dyn_cast<const DefinedAtom>(ref.target());
- if (target && target->contentType() == DefinedAtom::typeResolver) {
- const_cast<Reference &>(ref)
- .setTarget(getIFUNCPLTEntry(target, fromThumb));
- }
- return std::error_code();
- }
-
- /// \brief Create a GOT entry containing 0.
- const GOTAtom *getNullGOT() {
- if (!_null) {
- _null = new (_file._alloc) ARMGOTPLTAtom(_file);
-#ifndef NDEBUG
- _null->_name = "__got_null";
-#endif
- }
- return _null;
- }
-
- /// \brief Create regular GOT entry which cannot be used in PLTGOT operation.
- template <Reference::KindValue R_ARM_REL, Reference::Addend A = 0>
- const GOTAtom *getGOT(const Atom *da, StringRef source = "") {
- if (auto got = _gotAtoms.lookup(da))
- return got;
- auto g = new (_file._alloc) ARMGOTAtom(_file);
- g->addReferenceELF_ARM(R_ARM_REL, 0, da, A);
-#ifndef NDEBUG
- g->_name = "__got";
- g->_name += source.empty() ? "_" : source;
- g->_name += da->name();
-#endif
- _gotAtoms[da] = g;
- return g;
- }
-
- /// \brief get GOT entry for a regular defined atom.
- const GOTAtom *getGOTEntry(const DefinedAtom *da) {
- return getGOT<R_ARM_ABS32>(da);
- }
-
- std::error_code handleGOT(const Reference &ref) {
- if (isa<UndefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getNullGOT());
- else if (const auto *da = dyn_cast<DefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getGOTEntry(da));
- return std::error_code();
- }
-
-public:
- ARMRelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {}
-
- /// \brief Do the pass.
- ///
- /// The goal here is to first process each reference individually. Each call
- /// to handleReference may modify the reference itself and/or create new
- /// atoms which must be stored in one of the maps below.
- ///
- /// After all references are handled, the atoms created during that are all
- /// added to mf.
- std::error_code perform(SimpleFile &mf) override {
- ScopedTask task(getDefaultDomain(), "ARM GOT/PLT Pass");
- DEBUG_WITH_TYPE(
- "ARM", llvm::dbgs() << "Undefined Atoms" << "\n";
- for (const auto &atom
- : mf.undefined()) {
- llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
- }
-
- llvm::dbgs() << "Shared Library Atoms" << "\n";
- for (const auto &atom
- : mf.sharedLibrary()) {
- llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
- }
-
- llvm::dbgs() << "Absolute Atoms" << "\n";
- for (const auto &atom
- : mf.absolute()) {
- llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
- }
-
- llvm::dbgs() << "Defined Atoms" << "\n";
- for (const auto &atom
- : mf.defined()) {
- llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
- });
-
- // Process all references.
- for (const auto &atom : mf.defined()) {
- for (const auto &ref : *atom) {
- handleReference(*atom, *ref);
- }
- }
-
- // Add all created atoms to the link.
- uint64_t ordinal = 0;
- if (_plt0) {
- _plt0->setOrdinal(ordinal++);
- mf.addAtom(*_plt0);
- _plt0_d->setOrdinal(ordinal++);
- mf.addAtom(*_plt0_d);
- }
- for (auto &pltKV : _pltAtoms) {
- auto &plt = pltKV.second;
- if (auto *v = plt._veneer) {
- v->setOrdinal(ordinal++);
- mf.addAtom(*v);
- }
- auto *p = plt._plt;
- p->setOrdinal(ordinal++);
- mf.addAtom(*p);
- }
- if (_null) {
- _null->setOrdinal(ordinal++);
- mf.addAtom(*_null);
- }
- if (_plt0) {
- _got0->setOrdinal(ordinal++);
- mf.addAtom(*_got0);
- _got1->setOrdinal(ordinal++);
- mf.addAtom(*_got1);
- }
- for (auto &gotKV : _gotAtoms) {
- auto &got = gotKV.second;
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
- for (auto &gotKV : _gotpltAtoms) {
- auto &got = gotKV.second;
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
- for (auto &objectKV : _objectAtoms) {
- auto &obj = objectKV.second;
- obj->setOrdinal(ordinal++);
- mf.addAtom(*obj);
- }
- for (auto &veneerKV : _veneerAtoms) {
- auto &veneer = veneerKV.second;
- auto *m = veneer._mapping;
- m->setOrdinal(ordinal++);
- mf.addAtom(*m);
- auto *v = veneer._veneer;
- v->setOrdinal(ordinal++);
- mf.addAtom(*v);
- }
-
- return std::error_code();
- }
-
-protected:
- /// \brief Owner of all the Atoms created by this pass.
- ELFPassFile _file;
- const ELFLinkingContext &_ctx;
-
- /// \brief Map Atoms to their GOT entries.
- llvm::MapVector<const Atom *, GOTAtom *> _gotAtoms;
-
- /// \brief Map Atoms to their PLTGOT entries.
- llvm::MapVector<const Atom *, GOTAtom *> _gotpltAtoms;
-
- /// \brief Map Atoms to their Object entries.
- llvm::MapVector<const Atom *, ObjectAtom *> _objectAtoms;
-
- /// \brief Map Atoms to their PLT entries depending on the code model.
- struct PLTWithVeneer {
- PLTWithVeneer(PLTAtom *p = nullptr, PLTAtom *v = nullptr)
- : _plt(p), _veneer(v) {}
-
- bool empty() const {
- assert((_plt || !_veneer) && "Veneer appears without PLT entry");
- return !_plt && !_veneer;
- }
-
- PLTAtom *_plt;
- PLTAtom *_veneer;
- };
- llvm::MapVector<const Atom *, PLTWithVeneer> _pltAtoms;
-
- /// \brief Map Atoms to their veneers.
- struct VeneerWithMapping {
- VeneerWithMapping(VeneerAtom *v = nullptr, VeneerAtom *m = nullptr)
- : _veneer(v), _mapping(m) {}
-
- bool empty() const {
- assert(((bool)_veneer == (bool)_mapping) &&
- "Mapping symbol should always be paired with veneer");
- return !_veneer && !_mapping;
- }
-
- VeneerAtom *_veneer;
- VeneerAtom *_mapping;
- };
- llvm::MapVector<const Atom *, VeneerWithMapping> _veneerAtoms;
-
- /// \brief GOT entry that is always 0. Used for undefined weaks.
- GOTAtom *_null = nullptr;
-
- /// \brief The got and plt entries for .PLT0. This is used to call into the
- /// dynamic linker for symbol resolution.
- /// @{
- PLT0Atom *_plt0 = nullptr;
- PLT0Atom *_plt0_d = nullptr;
- GOTAtom *_got0 = nullptr;
- GOTAtom *_got1 = nullptr;
- /// @}
-};
-
-/// This implements the static relocation model. Meaning GOT and PLT entries are
-/// not created for references that can be directly resolved. These are
-/// converted to a direct relocation. For entries that do require a GOT or PLT
-/// entry, that entry is statically bound.
-///
-/// TLS always assumes module 1 and attempts to remove indirection.
-class ARMStaticRelocationPass final
- : public ARMRelocationPass<ARMStaticRelocationPass> {
-public:
- ARMStaticRelocationPass(const elf::ARMLinkingContext &ctx)
- : ARMRelocationPass(ctx) {}
-
- /// \brief Handle ordinary relocation references.
- std::error_code handlePlain(bool fromThumb, const Reference &ref) {
- return handleIFUNC(fromThumb, ref);
- }
-
- /// \brief Get the veneer for ARM B/BL instructions.
- const VeneerAtom *getVeneer_ARM_B_BL(const DefinedAtom *da,
- StringRef secName) {
- return getVeneer_ARM_B_BL_Abs(da, secName);
- }
-
- /// \brief Get the veneer for Thumb B/BL instructions.
- const VeneerAtom *getVeneer_THM_B_BL(const DefinedAtom *da,
- StringRef secName) {
- return getVeneer_THM_B_BL_Abs(da, secName);
- }
-
- /// \brief Create a GOT entry for R_ARM_TLS_TPOFF32 reloc.
- const GOTAtom *getTLSTPOFF32(const DefinedAtom *da) {
- return getGOTTLSEntry<R_ARM_TLS_LE32>(da);
- }
-};
-
-/// This implements the dynamic relocation model. GOT and PLT entries are
-/// created for references that cannot be directly resolved.
-class ARMDynamicRelocationPass final
- : public ARMRelocationPass<ARMDynamicRelocationPass> {
-public:
- ARMDynamicRelocationPass(const elf::ARMLinkingContext &ctx)
- : ARMRelocationPass(ctx) {}
-
- /// \brief get the PLT entry for a given atom.
- const PLTAtom *getPLTEntry(const SharedLibraryAtom *sla, bool fromThumb) {
- return getPLT(sla, fromThumb, &ARMDynamicRelocationPass::createPLTGOT);
- }
-
- /// \brief Create the GOT entry for a given atom.
- const GOTAtom *createPLTGOT(const Atom *da) {
- assert(!_gotpltAtoms.lookup(da) && "PLTGOT entry already exists");
- auto g = new (_file._alloc) ARMGOTPLTAtom(_file);
- g->addReferenceELF_ARM(R_ARM_ABS32, 0, getPLT0(), 0);
- g->addReferenceELF_ARM(R_ARM_JUMP_SLOT, 0, da, 0);
-#ifndef NDEBUG
- g->_name = "__got_plt0_";
- g->_name += da->name();
-#endif
- _gotpltAtoms[da] = g;
- return g;
- }
-
- const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) {
- if (auto obj = _objectAtoms.lookup(a))
- return obj;
-
- auto oa = new (_file._alloc) ARMObjectAtom(_file);
- oa->addReferenceELF_ARM(R_ARM_COPY, 0, oa, 0);
-
- oa->_name = a->name();
- oa->_size = a->size();
-
- _objectAtoms[a] = oa;
- return oa;
- }
-
- /// \brief Handle ordinary relocation references.
- std::error_code handlePlain(bool fromThumb, const Reference &ref) {
- if (auto sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
- if (sla->type() == SharedLibraryAtom::Type::Data &&
- _ctx.getOutputELFType() == llvm::ELF::ET_EXEC) {
- const_cast<Reference &>(ref).setTarget(getObjectEntry(sla));
- } else if (sla->type() == SharedLibraryAtom::Type::Code) {
- const_cast<Reference &>(ref).setTarget(getPLTEntry(sla, fromThumb));
- }
- return std::error_code();
- }
- return handleIFUNC(fromThumb, ref);
- }
-
- /// \brief Get the veneer for ARM B/BL instructions.
- const VeneerAtom *getVeneer_ARM_B_BL(const DefinedAtom *da,
- StringRef secName) {
- if (_ctx.getOutputELFType() == llvm::ELF::ET_EXEC) {
- return getVeneer_ARM_B_BL_Abs(da, secName);
- }
- llvm_unreachable("Handle ARM veneer for DSOs");
- }
-
- /// \brief Get the veneer for Thumb B/BL instructions.
- const VeneerAtom *getVeneer_THM_B_BL(const DefinedAtom *da,
- StringRef secName) {
- if (_ctx.getOutputELFType() == llvm::ELF::ET_EXEC) {
- return getVeneer_THM_B_BL_Abs(da, secName);
- }
- llvm_unreachable("Handle Thumb veneer for DSOs");
- }
-
- /// \brief Create a GOT entry for R_ARM_TLS_TPOFF32 reloc.
- const GOTAtom *getTLSTPOFF32(const DefinedAtom *da) {
- return getGOTTLSEntry<R_ARM_TLS_TPOFF32>(da);
- }
-
- const PLT0Atom *getPLT0() {
- if (_plt0)
- return _plt0;
- // Fill in the null entry.
- getNullGOT();
- _plt0 = new (_file._alloc) ARMPLT0_a_Atom(_file, "__PLT0");
- _plt0_d = new (_file._alloc) ARMPLT0_d_Atom(_file, "__PLT0_d");
- _got0 = new (_file._alloc) ARMGOTPLTAtom(_file);
- _got1 = new (_file._alloc) ARMGOTPLTAtom(_file);
- _plt0_d->addReferenceELF_ARM(R_ARM_REL32, 0, _got1, 0);
- // Fake reference to show connection between the GOT and PLT entries.
- _plt0->addReferenceELF_ARM(R_ARM_NONE, 0, _got0, 0);
- // Fake reference to show connection between parts of PLT entry.
- _plt0->addReferenceELF_ARM(R_ARM_NONE, 0, _plt0_d, 0);
-#ifndef NDEBUG
- _got0->_name = "__got0";
- _got1->_name = "__got1";
-#endif
- return _plt0;
- }
-
- const GOTAtom *getSharedGOTEntry(const SharedLibraryAtom *sla) {
- return getGOT<R_ARM_GLOB_DAT>(sla);
- }
-
- std::error_code handleGOT(const Reference &ref) {
- if (const auto sla = dyn_cast<const SharedLibraryAtom>(ref.target())) {
- const_cast<Reference &>(ref).setTarget(getSharedGOTEntry(sla));
- return std::error_code();
- }
- return ARMRelocationPass::handleGOT(ref);
- }
-};
-
-} // end of anon namespace
-
-std::unique_ptr<Pass>
-lld::elf::createARMRelocationPass(const ARMLinkingContext &ctx) {
- switch (ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- if (ctx.isDynamic())
- return llvm::make_unique<ARMDynamicRelocationPass>(ctx);
- return llvm::make_unique<ARMStaticRelocationPass>(ctx);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<ARMDynamicRelocationPass>(ctx);
- default:
- llvm_unreachable("Unhandled output file type");
- }
-}
diff --git a/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.h b/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.h
deleted file mode 100644
index 651e798f33b1..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMRelocationPass.h ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Declares the relocation processing pass for ARM. This includes
-/// GOT and PLT entries, TLS, COPY, and ifunc.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_RELOCATION_PASS_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_RELOCATION_PASS_H
-
-#include <memory>
-
-namespace lld {
-class Pass;
-namespace elf {
-class ARMLinkingContext;
-
-/// \brief Create ARM relocation pass for the given linking context.
-std::unique_ptr<Pass> createARMRelocationPass(const ARMLinkingContext &);
-}
-}
-
-#endif
diff --git a/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h b/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h
deleted file mode 100644
index 85b9c9162589..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h ------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_SYMBOL_TABLE_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_SYMBOL_TABLE_H
-
-#include "SectionChunks.h"
-#include "TargetLayout.h"
-#include "ARMELFFile.h"
-
-namespace lld {
-namespace elf {
-
-/// \brief The SymbolTable class represents the symbol table in a ELF file
-class ARMSymbolTable : public SymbolTable<ELF32LE> {
-public:
- typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
-
- ARMSymbolTable(const ELFLinkingContext &ctx);
-
- void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) override;
-};
-
-ARMSymbolTable::ARMSymbolTable(const ELFLinkingContext &ctx)
- : SymbolTable(ctx, ".symtab", TargetLayout<ELF32LE>::ORDER_SYMBOL_TABLE) {}
-
-void ARMSymbolTable::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) {
- SymbolTable::addDefinedAtom(sym, da, addr);
-
- if ((ARMELFDefinedAtom::ARMContentType)da->contentType() ==
- ARMELFDefinedAtom::typeARMExidx)
- sym.st_value = addr;
-
- // Set zero bit to distinguish real symbols addressing Thumb instructions.
- // Don't care about mapping symbols like $t and others.
- if (DefinedAtom::codeARMThumb == da->codeModel())
- sym.st_value = static_cast<int64_t>(sym.st_value) | 0x1;
-
- // Mapping symbols should have special values of binding, type and size set.
- if ((DefinedAtom::codeARM_a == da->codeModel()) ||
- (DefinedAtom::codeARM_d == da->codeModel()) ||
- (DefinedAtom::codeARM_t == da->codeModel())) {
- sym.setBindingAndType(llvm::ELF::STB_LOCAL, llvm::ELF::STT_NOTYPE);
- sym.st_size = 0;
- }
-}
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_ARM_ARM_SYMBOL_TABLE_H
diff --git a/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp b/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp
deleted file mode 100644
index e1f5eadbe789..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp --------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Atoms.h"
-#include "ARMExecutableWriter.h"
-#include "ARMDynamicLibraryWriter.h"
-#include "ARMTargetHandler.h"
-#include "ARMLinkingContext.h"
-
-using namespace lld;
-using namespace elf;
-
-ARMTargetHandler::ARMTargetHandler(ARMLinkingContext &ctx)
- : _ctx(ctx), _targetLayout(new ARMTargetLayout(ctx)),
- _relocationHandler(new ARMTargetRelocationHandler(*_targetLayout)) {}
-
-std::unique_ptr<Writer> ARMTargetHandler::getWriter() {
- switch (this->_ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- return llvm::make_unique<ARMExecutableWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<ARMDynamicLibraryWriter>(_ctx, *_targetLayout);
- default:
- llvm_unreachable("unsupported output type");
- }
-}
diff --git a/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h b/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
deleted file mode 100644
index 0352e81a1f61..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
+++ /dev/null
@@ -1,174 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_ARM_ARM_TARGET_HANDLER_H
-#define LLD_READER_WRITER_ELF_ARM_ARM_TARGET_HANDLER_H
-
-#include "ARMELFFile.h"
-#include "ARMRelocationHandler.h"
-#include "ELFReader.h"
-#include "TargetLayout.h"
-
-namespace lld {
-class ELFLinkingContext;
-
-namespace elf {
-
-/// \brief ARM specific section (.ARM.exidx) with indexes to exception handlers
-class ARMExidxSection : public AtomSection<ELF32LE> {
- typedef AtomSection<ELF32LE> Base;
-
-public:
- ARMExidxSection(const ELFLinkingContext &ctx, StringRef sectionName,
- int32_t permissions, int32_t order)
- : Base(ctx, sectionName, ARMELFDefinedAtom::typeARMExidx, permissions,
- order) {
- this->_type = SHT_ARM_EXIDX;
- this->_isLoadedInMemory = true;
- }
-
- bool hasOutputSegment() const override { return true; }
-
- const AtomLayout *appendAtom(const Atom *atom) override {
- const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
- assert((ARMELFDefinedAtom::ARMContentType)definedAtom->contentType() ==
- ARMELFDefinedAtom::typeARMExidx &&
- "atom content type for .ARM.exidx section has to be typeARMExidx");
-
- DefinedAtom::Alignment atomAlign = definedAtom->alignment();
- uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
- uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
-
- _atoms.push_back(new (_alloc) AtomLayout(atom, fOffset, 0));
- this->_fsize = fOffset + definedAtom->size();
- this->_msize = mOffset + definedAtom->size();
- DEBUG_WITH_TYPE("Section", llvm::dbgs()
- << "[" << this->name() << " " << this << "] "
- << "Adding atom: " << atom->name() << "@"
- << fOffset << "\n");
-
- uint64_t alignment = atomAlign.value;
- if (this->_alignment < alignment)
- this->_alignment = alignment;
-
- return _atoms.back();
- }
-};
-
-class ARMTargetLayout : public TargetLayout<ELF32LE> {
-public:
- enum ARMSectionOrder {
- ORDER_ARM_EXIDX = TargetLayout::ORDER_EH_FRAME + 1,
- };
-
- ARMTargetLayout(ELFLinkingContext &ctx) : TargetLayout(ctx) {}
-
- SectionOrder getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPermissions) override {
- switch (contentType) {
- case ARMELFDefinedAtom::typeARMExidx:
- return ORDER_ARM_EXIDX;
- default:
- return TargetLayout::getSectionOrder(name, contentType,
- contentPermissions);
- }
- }
-
- StringRef getOutputSectionName(StringRef archivePath, StringRef memberPath,
- StringRef inputSectionName) const override {
- return llvm::StringSwitch<StringRef>(inputSectionName)
- .StartsWith(".ARM.exidx", ".ARM.exidx")
- .StartsWith(".ARM.extab", ".ARM.extab")
- .Default(TargetLayout::getOutputSectionName(archivePath, memberPath,
- inputSectionName));
- }
-
- SegmentType getSegmentType(const Section<ELF32LE> *section) const override {
- switch (section->order()) {
- case ORDER_ARM_EXIDX:
- return llvm::ELF::PT_ARM_EXIDX;
- default:
- return TargetLayout::getSegmentType(section);
- }
- }
-
- AtomSection<ELF32LE> *
- createSection(StringRef name, int32_t contentType,
- DefinedAtom::ContentPermissions contentPermissions,
- SectionOrder sectionOrder) override {
- if ((ARMELFDefinedAtom::ARMContentType)contentType ==
- ARMELFDefinedAtom::typeARMExidx)
- return new ARMExidxSection(_ctx, name, contentPermissions, sectionOrder);
-
- return TargetLayout::createSection(name, contentType, contentPermissions,
- sectionOrder);
- }
-
- uint64_t getGOTSymAddr() {
- std::call_once(_gotSymOnce, [this]() {
- if (AtomLayout *gotAtom = findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"))
- _gotSymAddr = gotAtom->_virtualAddr;
- });
- return _gotSymAddr;
- }
-
- uint64_t getTPOffset() {
- std::call_once(_tpOffOnce, [this]() {
- for (const auto &phdr : *_programHeader) {
- if (phdr->p_type == llvm::ELF::PT_TLS) {
- _tpOff = llvm::RoundUpToAlignment(TCB_SIZE, phdr->p_align);
- break;
- }
- }
- assert(_tpOff != 0 && "TLS segment not found");
- });
- return _tpOff;
- }
-
- bool target1Rel() const { return _ctx.armTarget1Rel(); }
-
-private:
- // TCB block size of the TLS.
- enum { TCB_SIZE = 0x8 };
-
-private:
- uint64_t _gotSymAddr = 0;
- uint64_t _tpOff = 0;
- std::once_flag _gotSymOnce;
- std::once_flag _tpOffOnce;
-};
-
-class ARMTargetHandler final : public TargetHandler {
-public:
- ARMTargetHandler(ARMLinkingContext &ctx);
-
- const TargetRelocationHandler &getRelocationHandler() const override {
- return *_relocationHandler;
- }
-
- std::unique_ptr<Reader> getObjReader() override {
- return llvm::make_unique<ELFReader<ARMELFFile>>(_ctx);
- }
-
- std::unique_ptr<Reader> getDSOReader() override {
- return llvm::make_unique<ELFReader<DynamicFile<ELF32LE>>>(_ctx);
- }
-
- std::unique_ptr<Writer> getWriter() override;
-
-private:
- ARMLinkingContext &_ctx;
- std::unique_ptr<ARMTargetLayout> _targetLayout;
- std::unique_ptr<ARMTargetRelocationHandler> _relocationHandler;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_ELF_ARM_ARM_TARGET_HANDLER_H
diff --git a/lib/ReaderWriter/ELF/ARM/CMakeLists.txt b/lib/ReaderWriter/ELF/ARM/CMakeLists.txt
deleted file mode 100644
index c8cd6533d902..000000000000
--- a/lib/ReaderWriter/ELF/ARM/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-add_lld_library(lldARMELFTarget
- ARMLinkingContext.cpp
- ARMTargetHandler.cpp
- ARMRelocationHandler.cpp
- ARMRelocationPass.cpp
- LINK_LIBS
- lldELF
- lldReaderWriter
- lldCore
- LLVMObject
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/ELF/ARM/TODO.rst b/lib/ReaderWriter/ELF/ARM/TODO.rst
deleted file mode 100644
index 61b585ae698c..000000000000
--- a/lib/ReaderWriter/ELF/ARM/TODO.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-ELF ARM
-~~~~~~~~~~~
-
-Unimplemented Features
-######################
-
-* DSO linking
-* C++ code linking
-* PLT entries' generation for images larger than 2^28 bytes (see Sec. A.3 of the ARM ELF reference)
-* ARM/Thumb interwork veneers in position-independent code
-* .ARM.exidx section (exception handling)
-* -init/-fini options
-* Proper debug information (DWARF data)
-* TLS relocations for dynamic models
-* Lots of other relocations
-
-Unimplemented Relocations
-#########################
-
-All of these relocations are defined in:
-http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf
diff --git a/lib/ReaderWriter/ELF/Atoms.cpp b/lib/ReaderWriter/ELF/Atoms.cpp
deleted file mode 100644
index 639633393161..000000000000
--- a/lib/ReaderWriter/ELF/Atoms.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-//===- lib/ReaderWriter/ELF/Atoms.cpp -------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Atoms.h"
-#include "DynamicFile.h"
-#include "ELFFile.h"
-#include "TargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT> AbsoluteAtom::Scope ELFAbsoluteAtom<ELFT>::scope() const {
- if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
- return scopeLinkageUnit;
- if (_symbol->getBinding() == llvm::ELF::STB_LOCAL)
- return scopeTranslationUnit;
- return scopeGlobal;
-}
-
-template <class ELFT>
-UndefinedAtom::CanBeNull ELFUndefinedAtom<ELFT>::canBeNull() const {
- if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
- return CanBeNull::canBeNullAtBuildtime;
- return CanBeNull::canBeNullNever;
-}
-
-template <class ELFT> uint64_t ELFDefinedAtom<ELFT>::size() const {
- // Common symbols are not allocated in object files,
- // so use st_size to tell how many bytes are required.
- if (_symbol && (_symbol->getType() == llvm::ELF::STT_COMMON ||
- _symbol->st_shndx == llvm::ELF::SHN_COMMON))
- return (uint64_t)_symbol->st_size;
-
- return _contentData.size();
-}
-
-template <class ELFT> AbsoluteAtom::Scope ELFDefinedAtom<ELFT>::scope() const {
- if (!_symbol)
- return scopeGlobal;
- if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
- return scopeLinkageUnit;
- if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
- return scopeGlobal;
- return scopeTranslationUnit;
-}
-
-template <class ELFT> DefinedAtom::Merge ELFDefinedAtom<ELFT>::merge() const {
- if (!_symbol)
- return mergeNo;
- if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
- return mergeAsWeak;
- if (_symbol->getType() == llvm::ELF::STT_COMMON ||
- _symbol->st_shndx == llvm::ELF::SHN_COMMON)
- return mergeAsTentative;
- return mergeNo;
-}
-
-template <class ELFT>
-DefinedAtom::ContentType ELFDefinedAtom<ELFT>::doContentType() const {
- using namespace llvm::ELF;
-
- if (_section->sh_type == SHT_GROUP)
- return typeGroupComdat;
- if (!_symbol && _sectionName.startswith(".gnu.linkonce"))
- return typeGnuLinkOnce;
-
- uint64_t flags = _section->sh_flags;
-
- if (!(flags & SHF_ALLOC)) {
- if (_section->sh_type == SHT_NOTE)
- return (flags == SHF_WRITE) ? typeRWNote : typeRONote;
- return _contentType = typeNoAlloc;
- }
-
- if (_section->sh_flags == (SHF_ALLOC | SHF_WRITE | SHF_TLS))
- return _section->sh_type == SHT_NOBITS ? typeThreadZeroFill
- : typeThreadData;
-
- if (_section->sh_flags == SHF_ALLOC && _section->sh_type == SHT_PROGBITS)
- return _contentType = typeConstant;
- if (_symbol->getType() == STT_GNU_IFUNC)
- return _contentType = typeResolver;
- if (_symbol->st_shndx == SHN_COMMON)
- return _contentType = typeZeroFill;
-
- if (_section->sh_type == SHT_PROGBITS) {
- flags &= ~SHF_ALLOC;
- flags &= ~SHF_GROUP;
- if ((flags & SHF_STRINGS) || (flags & SHF_MERGE))
- return typeConstant;
- if (flags == SHF_WRITE)
- return typeData;
- return typeCode;
- }
- if (_section->sh_type == SHT_NOTE) {
- flags &= ~SHF_ALLOC;
- return (flags == SHF_WRITE) ? typeRWNote : typeRONote;
- }
- if (_section->sh_type == SHT_NOBITS)
- return typeZeroFill;
-
- if (_section->sh_type == SHT_NULL)
- if (_symbol->getType() == STT_COMMON || _symbol->st_shndx == SHN_COMMON)
- return typeZeroFill;
-
- if (_section->sh_type == SHT_INIT_ARRAY ||
- _section->sh_type == SHT_FINI_ARRAY)
- return typeData;
- return typeUnknown;
-}
-
-template <class ELFT>
-DefinedAtom::ContentType ELFDefinedAtom<ELFT>::contentType() const {
- if (_contentType != typeUnknown)
- return _contentType;
- _contentType = doContentType();
- return _contentType;
-}
-
-template <class ELFT>
-DefinedAtom::Alignment ELFDefinedAtom<ELFT>::alignment() const {
- if (!_symbol)
- return 1;
-
- // Obtain proper value of st_value field.
- const auto symValue = getSymbolValue();
-
- // Unallocated common symbols specify their alignment constraints in
- // st_value.
- if ((_symbol->getType() == llvm::ELF::STT_COMMON) ||
- _symbol->st_shndx == llvm::ELF::SHN_COMMON) {
- return symValue;
- }
- if (_section->sh_addralign == 0) {
- // sh_addralign of 0 means no alignment
- return Alignment(1, symValue);
- }
- return Alignment(_section->sh_addralign, symValue % _section->sh_addralign);
-}
-
-// Do we have a choice for ELF? All symbols live in explicit sections.
-template <class ELFT>
-DefinedAtom::SectionChoice ELFDefinedAtom<ELFT>::sectionChoice() const {
- switch (contentType()) {
- case typeCode:
- case typeData:
- case typeZeroFill:
- case typeThreadZeroFill:
- case typeThreadData:
- case typeConstant:
- if ((_sectionName == ".text") || (_sectionName == ".data") ||
- (_sectionName == ".bss") || (_sectionName == ".rodata") ||
- (_sectionName == ".tdata") || (_sectionName == ".tbss"))
- return sectionBasedOnContent;
- default:
- break;
- }
- return sectionCustomRequired;
-}
-
-template <class ELFT>
-StringRef ELFDefinedAtom<ELFT>::customSectionName() const {
- if ((contentType() == typeZeroFill) ||
- (_symbol && _symbol->st_shndx == llvm::ELF::SHN_COMMON))
- return ".bss";
- return _sectionName;
-}
-
-template <class ELFT>
-DefinedAtom::ContentPermissions ELFDefinedAtom<ELFT>::permissions() const {
- if (_permissions != permUnknown)
- return _permissions;
-
- uint64_t flags = _section->sh_flags;
-
- if (!(flags & llvm::ELF::SHF_ALLOC))
- return _permissions = perm___;
-
- switch (_section->sh_type) {
- // permRW_L is for sections modified by the runtime
- // loader.
- case llvm::ELF::SHT_REL:
- case llvm::ELF::SHT_RELA:
- return _permissions = permRW_L;
-
- case llvm::ELF::SHT_DYNAMIC:
- case llvm::ELF::SHT_PROGBITS:
- case llvm::ELF::SHT_NOTE:
- flags &= ~llvm::ELF::SHF_ALLOC;
- flags &= ~llvm::ELF::SHF_GROUP;
- switch (flags) {
- // Code
- case llvm::ELF::SHF_EXECINSTR:
- return _permissions = permR_X;
- case (llvm::ELF::SHF_WRITE | llvm::ELF::SHF_EXECINSTR):
- return _permissions = permRWX;
- // Data
- case llvm::ELF::SHF_WRITE:
- return _permissions = permRW_;
- // Strings
- case llvm::ELF::SHF_MERGE:
- case llvm::ELF::SHF_STRINGS:
- return _permissions = permR__;
-
- default:
- if (flags & llvm::ELF::SHF_WRITE)
- return _permissions = permRW_;
- return _permissions = permR__;
- }
-
- case llvm::ELF::SHT_NOBITS:
- return _permissions = permRW_;
-
- case llvm::ELF::SHT_INIT_ARRAY:
- case llvm::ELF::SHT_FINI_ARRAY:
- return _permissions = permRW_;
-
- default:
- return _permissions = perm___;
- }
-}
-
-template <class ELFT>
-DefinedAtom::reference_iterator ELFDefinedAtom<ELFT>::begin() const {
- uintptr_t index = _referenceStartIndex;
- const void *it = reinterpret_cast<const void *>(index);
- return reference_iterator(*this, it);
-}
-
-template <class ELFT>
-DefinedAtom::reference_iterator ELFDefinedAtom<ELFT>::end() const {
- uintptr_t index = _referenceEndIndex;
- const void *it = reinterpret_cast<const void *>(index);
- return reference_iterator(*this, it);
-}
-
-template <class ELFT>
-const Reference *ELFDefinedAtom<ELFT>::derefIterator(const void *It) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(It);
- assert(index >= _referenceStartIndex);
- assert(index < _referenceEndIndex);
- return ((_referenceList)[index]);
-}
-
-template <class ELFT>
-void ELFDefinedAtom<ELFT>::incrementIterator(const void *&It) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(It);
- ++index;
- It = reinterpret_cast<const void *>(index);
-}
-
-template <class ELFT>
-void ELFDefinedAtom<ELFT>::addReference(ELFReference<ELFT> *reference) {
- _referenceList.push_back(reference);
- _referenceEndIndex = _referenceList.size();
-}
-
-template <class ELFT> AbsoluteAtom::Scope ELFDynamicAtom<ELFT>::scope() const {
- if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
- return scopeLinkageUnit;
- if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
- return scopeGlobal;
- return scopeTranslationUnit;
-}
-
-template <class ELFT>
-SharedLibraryAtom::Type ELFDynamicAtom<ELFT>::type() const {
- switch (_symbol->getType()) {
- case llvm::ELF::STT_FUNC:
- case llvm::ELF::STT_GNU_IFUNC:
- return Type::Code;
- case llvm::ELF::STT_OBJECT:
- return Type::Data;
- default:
- return Type::Unknown;
- }
-}
-
-#define INSTANTIATE(klass) \
- template class klass<ELF32LE>; \
- template class klass<ELF32BE>; \
- template class klass<ELF64LE>; \
- template class klass<ELF64BE>
-
-INSTANTIATE(ELFAbsoluteAtom);
-INSTANTIATE(ELFDefinedAtom);
-INSTANTIATE(ELFDynamicAtom);
-INSTANTIATE(ELFUndefinedAtom);
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/Atoms.h b/lib/ReaderWriter/ELF/Atoms.h
deleted file mode 100644
index 390c0e16baf8..000000000000
--- a/lib/ReaderWriter/ELF/Atoms.h
+++ /dev/null
@@ -1,493 +0,0 @@
-//===- lib/ReaderWriter/ELF/Atoms.h ---------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_ATOMS_H
-#define LLD_READER_WRITER_ELF_ATOMS_H
-
-#include "TargetHandler.h"
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include <memory>
-#include <vector>
-
-namespace lld {
-namespace elf {
-template <class ELFT> class DynamicFile;
-template <typename ELFT> class ELFFile;
-
-/// \brief Relocation References: Defined Atoms may contain references that will
-/// need to be patched before the executable is written.
-///
-/// Construction of ELFReferences is two pass process. ELFReferences are
-/// instantiated while we are iterating over symbol tables to atomize
-/// symbols. At that time we only know the index of relocation target symbol
-/// (not target atom) about a relocation, so we store the index to
-/// ELFREference. In the second pass, ELFReferences are revisited to update
-/// target atoms by target symbol indexes.
-template <class ELFT> class ELFReference : public Reference {
- typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
-public:
- ELFReference(const Elf_Rela *rela, uint64_t off, Reference::KindArch arch,
- Reference::KindValue relocType, uint32_t idx)
- : Reference(Reference::KindNamespace::ELF, arch, relocType),
- _targetSymbolIndex(idx), _offsetInAtom(off), _addend(rela->r_addend) {}
-
- ELFReference(uint64_t off, Reference::KindArch arch,
- Reference::KindValue relocType, uint32_t idx)
- : Reference(Reference::KindNamespace::ELF, arch, relocType),
- _targetSymbolIndex(idx), _offsetInAtom(off) {}
-
- ELFReference(uint32_t edgeKind)
- : Reference(Reference::KindNamespace::all, Reference::KindArch::all,
- edgeKind) {}
-
- uint64_t offsetInAtom() const override { return _offsetInAtom; }
-
- const Atom *target() const override { return _target; }
-
- /// \brief The symbol table index that contains the target reference.
- uint64_t targetSymbolIndex() const {
- return _targetSymbolIndex;
- }
-
- Addend addend() const override { return _addend; }
-
- virtual void setOffset(uint64_t off) { _offsetInAtom = off; }
-
- void setAddend(Addend A) override { _addend = A; }
-
- void setTarget(const Atom *newAtom) override { _target = newAtom; }
-
-private:
- const Atom *_target = nullptr;
- uint64_t _targetSymbolIndex = 0;
- uint64_t _offsetInAtom = 0;
- Addend _addend = 0;
-};
-
-/// \brief These atoms store symbols that are fixed to a particular address.
-/// This atom has no content its address will be used by the writer to fixup
-/// references that point to it.
-template <class ELFT> class ELFAbsoluteAtom : public AbsoluteAtom {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
-public:
- ELFAbsoluteAtom(const ELFFile<ELFT> &file, StringRef name,
- const Elf_Sym *symbol, uint64_t value)
- : _owningFile(file), _name(name), _symbol(symbol), _value(value) {}
-
- const ELFFile<ELFT> &file() const override { return _owningFile; }
- Scope scope() const override;
- StringRef name() const override { return _name; }
- uint64_t value() const override { return _value; }
-
-private:
- const ELFFile<ELFT> &_owningFile;
- StringRef _name;
- const Elf_Sym *_symbol;
- uint64_t _value;
-};
-
-/// \brief ELFUndefinedAtom: These atoms store undefined symbols and are place
-/// holders that will be replaced by defined atoms later in the linking process.
-template <class ELFT> class ELFUndefinedAtom : public UndefinedAtom {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
-public:
- ELFUndefinedAtom(const File &file, StringRef name, const Elf_Sym *symbol)
- : _owningFile(file), _name(name), _symbol(symbol) {}
-
- const File &file() const override { return _owningFile; }
- StringRef name() const override { return _name; }
-
- // A symbol in ELF can be undefined at build time if the symbol is a undefined
- // weak symbol.
- CanBeNull canBeNull() const override;
-
-private:
- const File &_owningFile;
- StringRef _name;
- const Elf_Sym *_symbol;
-};
-
-/// \brief This atom stores defined symbols and will contain either data or
-/// code.
-template <class ELFT> class ELFDefinedAtom : public DefinedAtom {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
-
-public:
- ELFDefinedAtom(const ELFFile<ELFT> &file, StringRef symbolName,
- StringRef sectionName, const Elf_Sym *symbol,
- const Elf_Shdr *section, ArrayRef<uint8_t> contentData,
- unsigned int referenceStart, unsigned int referenceEnd,
- std::vector<ELFReference<ELFT> *> &referenceList)
- : _owningFile(file), _symbolName(symbolName), _sectionName(sectionName),
- _symbol(symbol), _section(section), _contentData(contentData),
- _referenceStartIndex(referenceStart), _referenceEndIndex(referenceEnd),
- _referenceList(referenceList), _contentType(typeUnknown),
- _permissions(permUnknown) {}
-
- ~ELFDefinedAtom() override = default;
-
- const ELFFile<ELFT> &file() const override { return _owningFile; }
- StringRef name() const override { return _symbolName; }
- uint64_t ordinal() const override { return _ordinal; }
- const Elf_Sym *symbol() const { return _symbol; }
- const Elf_Shdr *section() const { return _section; }
- uint64_t size() const override;
- Scope scope() const override;
-
- // FIXME: Need to revisit this in future.
- Interposable interposable() const override { return interposeNo; }
-
- Merge merge() const override;
- ContentType contentType() const override;
- Alignment alignment() const override;
- SectionChoice sectionChoice() const override;
- StringRef customSectionName() const override;
-
- // It isn't clear that __attribute__((used)) is transmitted to the ELF object
- // file.
- DeadStripKind deadStrip() const override { return deadStripNormal; }
-
- ContentPermissions permissions() const override;
- ArrayRef<uint8_t> rawContent() const override { return _contentData; }
-
- DefinedAtom::reference_iterator begin() const override;
- DefinedAtom::reference_iterator end() const override;
- const Reference *derefIterator(const void *It) const override;
- void incrementIterator(const void *&It) const override;
- void addReference(ELFReference<ELFT> *reference);
-
- virtual void setOrdinal(uint64_t ord) { _ordinal = ord; }
-
-protected:
- /// Returns correct st_value for the symbol depending on the architecture.
- /// For most architectures it's just a regular st_value with no changes.
- virtual uint64_t getSymbolValue() const {
- return _symbol->st_value;
- }
-
- ContentType doContentType() const;
-
- const ELFFile<ELFT> &_owningFile;
- StringRef _symbolName;
- StringRef _sectionName;
- const Elf_Sym *_symbol;
- const Elf_Shdr *_section;
- /// \brief Holds the bits that make up the atom.
- ArrayRef<uint8_t> _contentData;
-
- uint64_t _ordinal;
- unsigned int _referenceStartIndex;
- unsigned int _referenceEndIndex;
- std::vector<ELFReference<ELFT> *> &_referenceList;
- mutable ContentType _contentType;
- mutable ContentPermissions _permissions;
-};
-
-/// \brief This atom stores mergeable Strings
-template <class ELFT> class ELFMergeAtom : public DefinedAtom {
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
-
-public:
- ELFMergeAtom(const ELFFile<ELFT> &file, StringRef sectionName,
- const Elf_Shdr *section, ArrayRef<uint8_t> contentData,
- uint64_t offset)
- : _owningFile(file), _sectionName(sectionName), _section(section),
- _contentData(contentData), _offset(offset) {
- }
-
- const ELFFile<ELFT> &file() const override { return _owningFile; }
- StringRef name() const override { return ""; }
- virtual uint64_t section() const { return _section->sh_name; }
- virtual uint64_t offset() const { return _offset; }
- virtual void setOrdinal(uint64_t ord) { _ordinal = ord; }
- uint64_t ordinal() const override { return _ordinal; }
- uint64_t size() const override { return _contentData.size(); }
- Scope scope() const override { return scopeTranslationUnit; }
- Interposable interposable() const override { return interposeNo; }
- Merge merge() const override { return mergeByContent; }
- ContentType contentType() const override { return typeConstant; }
-
- Alignment alignment() const override {
- return Alignment(_section->sh_addralign);
- }
-
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return _sectionName; }
- DeadStripKind deadStrip() const override { return deadStripNormal; }
- ContentPermissions permissions() const override { return permR__; }
- ArrayRef<uint8_t> rawContent() const override { return _contentData; }
-
- DefinedAtom::reference_iterator begin() const override {
- uintptr_t index = 0;
- const void *it = reinterpret_cast<const void *>(index);
- return reference_iterator(*this, it);
- }
-
- DefinedAtom::reference_iterator end() const override {
- uintptr_t index = 0;
- const void *it = reinterpret_cast<const void *>(index);
- return reference_iterator(*this, it);
- }
-
- const Reference *derefIterator(const void *It) const override {
- return nullptr;
- }
-
- void incrementIterator(const void *&It) const override {}
-
-private:
- const ELFFile<ELFT> &_owningFile;
- StringRef _sectionName;
- const Elf_Shdr *_section;
- /// \brief Holds the bits that make up the atom.
- ArrayRef<uint8_t> _contentData;
- uint64_t _ordinal;
- uint64_t _offset;
-};
-
-template <class ELFT> class ELFCommonAtom : public DefinedAtom {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-public:
- ELFCommonAtom(const ELFFile<ELFT> &file, StringRef symbolName,
- const Elf_Sym *symbol)
- : _owningFile(file), _symbolName(symbolName), _symbol(symbol) {}
-
- const ELFFile<ELFT> &file() const override { return _owningFile; }
- StringRef name() const override { return _symbolName; }
- uint64_t ordinal() const override { return _ordinal; }
- virtual void setOrdinal(uint64_t ord) { _ordinal = ord; }
- uint64_t size() const override { return _symbol->st_size; }
-
- Scope scope() const override {
- if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
- return scopeLinkageUnit;
- if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
- return scopeGlobal;
- return scopeTranslationUnit;
- }
-
- Interposable interposable() const override { return interposeNo; }
- Merge merge() const override { return mergeAsTentative; }
- ContentType contentType() const override { return typeZeroFill; }
- Alignment alignment() const override { return Alignment(_symbol->st_value); }
- SectionChoice sectionChoice() const override { return sectionBasedOnContent; }
- StringRef customSectionName() const override { return ".bss"; }
- DeadStripKind deadStrip() const override { return deadStripNormal; }
- ContentPermissions permissions() const override { return permRW_; }
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-
- DefinedAtom::reference_iterator begin() const override {
- uintptr_t index = 0;
- const void *it = reinterpret_cast<const void *>(index);
- return reference_iterator(*this, it);
- }
-
- DefinedAtom::reference_iterator end() const override {
- uintptr_t index = 0;
- const void *it = reinterpret_cast<const void *>(index);
- return reference_iterator(*this, it);
- }
-
-protected:
- const Reference *derefIterator(const void *iter) const override {
- return nullptr;
- }
-
- void incrementIterator(const void *&iter) const override {}
-
- const ELFFile<ELFT> &_owningFile;
- StringRef _symbolName;
- const Elf_Sym *_symbol;
- uint64_t _ordinal;
-};
-
-/// \brief An atom from a shared library.
-template <class ELFT> class ELFDynamicAtom : public SharedLibraryAtom {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
-public:
- ELFDynamicAtom(const DynamicFile<ELFT> &file, StringRef symbolName,
- StringRef loadName, const Elf_Sym *symbol)
- : _owningFile(file), _symbolName(symbolName), _loadName(loadName),
- _symbol(symbol) {}
-
- const DynamicFile<ELFT> &file() const override { return _owningFile; }
- StringRef name() const override { return _symbolName; }
- virtual Scope scope() const;
- StringRef loadName() const override { return _loadName; }
-
- bool canBeNullAtRuntime() const override {
- return _symbol->getBinding() == llvm::ELF::STB_WEAK;
- }
-
- Type type() const override;
- uint64_t size() const override { return _symbol->st_size; }
-
-private:
-
- const DynamicFile<ELFT> &_owningFile;
- StringRef _symbolName;
- StringRef _loadName;
- const Elf_Sym *_symbol;
-};
-
-class SimpleELFDefinedAtom : public SimpleDefinedAtom {
-public:
- SimpleELFDefinedAtom(const File &f) : SimpleDefinedAtom(f) {}
-
- void addReferenceELF(Reference::KindArch arch, Reference::KindValue kindValue,
- uint64_t off, const Atom *t, Reference::Addend a) {
- addReference(Reference::KindNamespace::ELF, arch, kindValue, off, t, a);
- }
-
- void addReferenceELF_Hexagon(Reference::KindValue relocType, uint64_t off,
- const Atom *t, Reference::Addend a) {
- addReferenceELF(Reference::KindArch::Hexagon, relocType, off, t, a);
- }
-
- void addReferenceELF_x86_64(Reference::KindValue relocType, uint64_t off,
- const Atom *t, Reference::Addend a) {
- addReferenceELF(Reference::KindArch::x86_64, relocType, off, t, a);
- }
-
- void addReferenceELF_Mips(Reference::KindValue relocType, uint64_t off,
- const Atom *t, Reference::Addend a) {
- addReferenceELF(Reference::KindArch::Mips, relocType, off, t, a);
- }
-
- void addReferenceELF_AArch64(Reference::KindValue relocType, uint64_t off,
- const Atom *t, Reference::Addend a) {
- addReferenceELF(Reference::KindArch::AArch64, relocType, off, t, a);
- }
-
- void addReferenceELF_ARM(Reference::KindValue relocType, uint64_t off,
- const Atom *t, Reference::Addend a) {
- addReferenceELF(Reference::KindArch::ARM, relocType, off, t, a);
- }
-};
-
-/// \brief Atom which represents an object for which a COPY relocation will be
-/// generated.
-class ObjectAtom : public SimpleELFDefinedAtom {
-public:
- ObjectAtom(const File &f) : SimpleELFDefinedAtom(f) {}
- Scope scope() const override { return scopeGlobal; }
- SectionChoice sectionChoice() const override { return sectionBasedOnContent; }
- ContentType contentType() const override { return typeZeroFill; }
- uint64_t size() const override { return _size; }
- DynamicExport dynamicExport() const override { return dynamicExportAlways; }
- ContentPermissions permissions() const override { return permRW_; }
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
- Alignment alignment() const override { return 8; }
- StringRef name() const override { return _name; }
-
- std::string _name;
- uint64_t _size;
-};
-
-class GOTAtom : public SimpleELFDefinedAtom {
- StringRef _section;
-
-public:
- GOTAtom(const File &f, StringRef secName)
- : SimpleELFDefinedAtom(f), _section(secName) {}
-
- Scope scope() const override { return scopeTranslationUnit; }
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return _section; }
- ContentType contentType() const override { return typeGOT; }
- uint64_t size() const override { return rawContent().size(); }
- ContentPermissions permissions() const override { return permRW_; }
- Alignment alignment() const override { return 8; }
-
-#ifndef NDEBUG
- StringRef name() const override { return _name; }
- std::string _name;
-#else
- StringRef name() const override { return ""; }
-#endif
-};
-
-class PLTAtom : public SimpleELFDefinedAtom {
- StringRef _section;
-
-public:
- PLTAtom(const File &f, StringRef secName)
- : SimpleELFDefinedAtom(f), _section(secName) {}
-
- Scope scope() const override { return scopeTranslationUnit; }
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return _section; }
- ContentType contentType() const override { return typeStub; }
- uint64_t size() const override { return rawContent().size(); }
- ContentPermissions permissions() const override { return permR_X; }
- Alignment alignment() const override { return 16; }
-
-#ifndef NDEBUG
- StringRef name() const override { return _name; }
- std::string _name;
-#else
- StringRef name() const override { return ""; }
-#endif
-};
-
-class PLT0Atom : public PLTAtom {
-public:
- PLT0Atom(const File &f) : PLTAtom(f, ".plt") {
-#ifndef NDEBUG
- _name = ".PLT0";
-#endif
- }
-};
-
-class GlobalOffsetTableAtom : public SimpleELFDefinedAtom {
-public:
- GlobalOffsetTableAtom(const File &f) : SimpleELFDefinedAtom(f) {}
-
- StringRef name() const override { return "_GLOBAL_OFFSET_TABLE_"; }
- Scope scope() const override { return scopeLinkageUnit; }
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return ".got.plt"; }
- ContentType contentType() const override { return typeGOT; }
- uint64_t size() const override { return 0; }
- ContentPermissions permissions() const override { return permRW_; }
- Alignment alignment() const override { return 8; }
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-};
-
-class DynamicAtom : public SimpleELFDefinedAtom {
-public:
- DynamicAtom(const File &f) : SimpleELFDefinedAtom(f) {}
-
- StringRef name() const override { return "_DYNAMIC"; }
- Scope scope() const override { return scopeLinkageUnit; }
- Merge merge() const override { return mergeNo; }
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return ".dynamic"; }
- ContentType contentType() const override { return typeData; }
- uint64_t size() const override { return 0; }
- ContentPermissions permissions() const override { return permRW_; }
- Alignment alignment() const override { return 1; }
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_ELF_ATOMS_H
diff --git a/lib/ReaderWriter/ELF/CMakeLists.txt b/lib/ReaderWriter/ELF/CMakeLists.txt
deleted file mode 100644
index 3bc338507db6..000000000000
--- a/lib/ReaderWriter/ELF/CMakeLists.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-add_lld_library(lldELF
- Atoms.cpp
- DynamicFile.cpp
- ELFFile.cpp
- ELFLinkingContext.cpp
- FileCommon.cpp
- HeaderChunks.cpp
- OutputELFWriter.cpp
- Reader.cpp
- SectionChunks.cpp
- SegmentChunks.cpp
- TargetLayout.cpp
- Writer.cpp
- LINK_LIBS
- lldReaderWriter
- lldCore
- lldYAML
- LLVMObject
- LLVMSupport
- )
-
-include_directories(.)
-
-add_subdirectory(X86)
-add_subdirectory(X86_64)
-add_subdirectory(Mips)
-add_subdirectory(Hexagon)
-add_subdirectory(AArch64)
-add_subdirectory(ARM)
diff --git a/lib/ReaderWriter/ELF/Chunk.h b/lib/ReaderWriter/ELF/Chunk.h
deleted file mode 100644
index f223b6c54163..000000000000
--- a/lib/ReaderWriter/ELF/Chunk.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//===- lib/ReaderWriter/ELF/Chunks.h --------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_CHUNKS_H
-#define LLD_READER_WRITER_ELF_CHUNKS_H
-
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include <memory>
-
-namespace lld {
-class ELFLinkingContext;
-
-namespace elf {
-class ELFWriter;
-template <class ELFT> class TargetLayout;
-
-/// \brief A chunk is a contiguous region of space
-template <class ELFT> class Chunk {
-public:
- /// \brief Describes the type of Chunk
- enum Kind : uint8_t {
- ELFHeader, ///< ELF Header
- ProgramHeader, ///< Program Header
- SectionHeader, ///< Section header
- ELFSegment, ///< Segment
- ELFSection, ///< Section
- AtomSection, ///< A section containing atoms
- Expression ///< A linker script expression
- };
-
- /// \brief the ContentType of the chunk
- enum ContentType : uint8_t { Unknown, Header, Code, Data, Note, TLS };
-
- Chunk(StringRef name, Kind kind, const ELFLinkingContext &ctx)
- : _name(name), _kind(kind), _ctx(ctx) {}
-
- virtual ~Chunk() {}
-
- // The name of the chunk
- StringRef name() const { return _name; }
-
- // Kind of chunk
- Kind kind() const { return _kind; }
- virtual uint64_t fileSize() const { return _fsize; }
- virtual void setFileSize(uint64_t sz) { _fsize = sz; }
- virtual void setAlign(uint64_t align) { _alignment = align; }
- virtual uint64_t alignment() const { return _alignment; }
-
- // The ordinal value of the chunk
- uint64_t ordinal() const { return _ordinal; }
- void setOrdinal(uint64_t newVal) { _ordinal = newVal; }
-
- // The order in which the chunk would appear in the output file
- uint64_t order() const { return _order; }
- void setOrder(uint32_t order) { _order = order; }
-
- // Output file offset of the chunk
- uint64_t fileOffset() const { return _fileoffset; }
- void setFileOffset(uint64_t offset) { _fileoffset = offset; }
-
- // Output start address of the chunk
- virtual void setVirtualAddr(uint64_t start) { _start = start; }
- virtual uint64_t virtualAddr() const { return _start; }
-
- // Memory size of the chunk
- uint64_t memSize() const { return _msize; }
- void setMemSize(uint64_t msize) { _msize = msize; }
-
- // Returns the ContentType of the chunk
- virtual int getContentType() const = 0;
-
- // Writer the chunk
- virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) = 0;
-
- // Finalize the chunk before assigning offsets/virtual addresses
- virtual void doPreFlight() {}
-
- // Finalize the chunk before writing
- virtual void finalize() {}
-
-protected:
- StringRef _name;
- Kind _kind;
- const ELFLinkingContext &_ctx;
- uint64_t _fsize = 0;
- uint64_t _msize = 0;
- uint64_t _alignment = 1;
- uint32_t _order = 0;
- uint64_t _ordinal = 1;
- uint64_t _start = 0;
- uint64_t _fileoffset = 0;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/DynamicFile.cpp b/lib/ReaderWriter/ELF/DynamicFile.cpp
deleted file mode 100644
index 5339c7d66577..000000000000
--- a/lib/ReaderWriter/ELF/DynamicFile.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//===- lib/ReaderWriter/ELF/DynamicFile.cpp -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DynamicFile.h"
-#include "FileCommon.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Path.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-DynamicFile<ELFT>::DynamicFile(std::unique_ptr<MemoryBuffer> mb,
- ELFLinkingContext &ctx)
- : SharedLibraryFile(mb->getBufferIdentifier()), _mb(std::move(mb)),
- _ctx(ctx), _useShlibUndefines(ctx.useShlibUndefines()) {}
-
-template <typename ELFT>
-std::error_code DynamicFile<ELFT>::isCompatible(MemoryBufferRef mb,
- ELFLinkingContext &ctx) {
- return elf::isCompatible<ELFT>(mb, ctx);
-}
-
-template <class ELFT>
-const SharedLibraryAtom *DynamicFile<ELFT>::exports(StringRef name,
- bool dataSymbolOnly) const {
- assert(!dataSymbolOnly && "Invalid option for ELF exports!");
- // See if we have the symbol.
- auto sym = _nameToSym.find(name);
- if (sym == _nameToSym.end())
- return nullptr;
- // Have we already created a SharedLibraryAtom for it?
- if (sym->second._atom)
- return sym->second._atom;
- // Create a SharedLibraryAtom for this symbol.
- return sym->second._atom = new (_alloc)
- ELFDynamicAtom<ELFT>(*this, name, _soname, sym->second._symbol);
-}
-
-template <class ELFT> StringRef DynamicFile<ELFT>::getDSOName() const {
- return _soname;
-}
-
-template <class ELFT> bool DynamicFile<ELFT>::canParse(file_magic magic) {
- return magic == file_magic::elf_shared_object;
-}
-
-template <class ELFT> std::error_code DynamicFile<ELFT>::doParse() {
- typedef llvm::object::ELFFile<ELFT> ELFO;
- typedef typename ELFO::Elf_Shdr Elf_Shdr;
- typedef typename ELFO::Elf_Dyn Elf_Dyn;
-
- std::error_code ec;
- _objFile.reset(new ELFO(_mb->getBuffer(), ec));
- if (ec)
- return ec;
-
- ELFO &obj = *_objFile;
-
- const char *base = _mb->getBuffer().data();
- const Elf_Dyn *dynStart = nullptr;
- const Elf_Dyn *dynEnd = nullptr;
-
- const Elf_Shdr *dynSymSec = nullptr;
- for (const Elf_Shdr &sec : obj.sections()) {
- switch (sec.sh_type) {
- case llvm::ELF::SHT_DYNAMIC: {
- dynStart = reinterpret_cast<const Elf_Dyn *>(base + sec.sh_offset);
- uint64_t size = sec.sh_size;
- if (size % sizeof(Elf_Dyn))
- return llvm::object::object_error::parse_failed;
- dynEnd = dynStart + size / sizeof(Elf_Dyn);
- break;
- }
- case llvm::ELF::SHT_DYNSYM:
- dynSymSec = &sec;
- break;
- }
- }
-
- ErrorOr<StringRef> strTableOrErr = obj.getStringTableForSymtab(*dynSymSec);
- if (std::error_code ec = strTableOrErr.getError())
- return ec;
- StringRef stringTable = *strTableOrErr;
-
- for (const Elf_Dyn &dyn : llvm::make_range(dynStart, dynEnd)) {
- if (dyn.d_tag == llvm::ELF::DT_SONAME) {
- uint64_t offset = dyn.getVal();
- if (offset >= stringTable.size())
- return llvm::object::object_error::parse_failed;
- _soname = StringRef(stringTable.data() + offset);
- break;
- }
- }
-
- if (_soname.empty())
- _soname = llvm::sys::path::filename(path());
-
- // Create a map from names to dynamic symbol table entries.
- // TODO: This should use the object file's build in hash table instead if
- // it exists.
- for (auto i = obj.symbol_begin(dynSymSec), e = obj.symbol_end(dynSymSec);
- i != e; ++i) {
- auto name = i->getName(stringTable);
- if ((ec = name.getError()))
- return ec;
-
- // Dont add local symbols to dynamic entries. The first symbol in the
- // dynamic symbol table is a local symbol.
- if (i->getBinding() == llvm::ELF::STB_LOCAL)
- continue;
-
- // TODO: Add absolute symbols
- if (i->st_shndx == llvm::ELF::SHN_ABS)
- continue;
-
- if (i->st_shndx == llvm::ELF::SHN_UNDEF) {
- if (!_useShlibUndefines)
- continue;
- // Create an undefined atom.
- if (!name->empty()) {
- auto *newAtom = new (_alloc) ELFUndefinedAtom<ELFT>(*this, *name, &*i);
- _undefinedAtoms.push_back(newAtom);
- }
- continue;
- }
- _nameToSym[*name]._symbol = &*i;
- }
- return std::error_code();
-}
-
-template class DynamicFile<ELF32LE>;
-template class DynamicFile<ELF32BE>;
-template class DynamicFile<ELF64LE>;
-template class DynamicFile<ELF64BE>;
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/DynamicFile.h b/lib/ReaderWriter/ELF/DynamicFile.h
deleted file mode 100644
index a155900de781..000000000000
--- a/lib/ReaderWriter/ELF/DynamicFile.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- lib/ReaderWriter/ELF/DynamicFile.h ---------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_DYNAMIC_FILE_H
-#define LLD_READER_WRITER_ELF_DYNAMIC_FILE_H
-
-#include "Atoms.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include <unordered_map>
-
-namespace lld {
-class ELFLinkingContext;
-
-namespace elf {
-
-template <class ELFT> class DynamicFile : public SharedLibraryFile {
-public:
- DynamicFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
-
- static std::error_code isCompatible(MemoryBufferRef mb,
- ELFLinkingContext &ctx);
-
- const SharedLibraryAtom *exports(StringRef name,
- bool dataSymbolOnly) const override;
-
- StringRef getDSOName() const override;
-
- static bool canParse(file_magic magic);
-
-protected:
- std::error_code doParse() override;
-
-private:
- mutable llvm::BumpPtrAllocator _alloc;
- std::unique_ptr<llvm::object::ELFFile<ELFT>> _objFile;
- /// \brief DT_SONAME
- StringRef _soname;
-
- struct SymAtomPair {
- const typename llvm::object::ELFFile<ELFT>::Elf_Sym *_symbol = nullptr;
- const SharedLibraryAtom *_atom = nullptr;
- };
-
- std::unique_ptr<MemoryBuffer> _mb;
- ELFLinkingContext &_ctx;
- bool _useShlibUndefines;
- mutable std::unordered_map<StringRef, SymAtomPair> _nameToSym;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/DynamicLibraryWriter.h
deleted file mode 100644
index 5f2c1d1a8288..000000000000
--- a/lib/ReaderWriter/ELF/DynamicLibraryWriter.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//===- lib/ReaderWriter/ELF/DynamicLibraryWriter.h ------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_DYNAMIC_LIBRARY_WRITER_H
-#define LLD_READER_WRITER_ELF_DYNAMIC_LIBRARY_WRITER_H
-
-#include "OutputELFWriter.h"
-
-namespace lld {
-namespace elf {
-using namespace llvm;
-using namespace llvm::object;
-
-//===----------------------------------------------------------------------===//
-// DynamicLibraryWriter Class
-//===----------------------------------------------------------------------===//
-template<class ELFT>
-class DynamicLibraryWriter : public OutputELFWriter<ELFT> {
-public:
- DynamicLibraryWriter(ELFLinkingContext &ctx, TargetLayout<ELFT> &layout)
- : OutputELFWriter<ELFT>(ctx, layout) {}
-
-protected:
- void buildDynamicSymbolTable(const File &file) override;
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
- void finalizeDefaultAtomValues() override;
-};
-
-//===----------------------------------------------------------------------===//
-// DynamicLibraryWriter
-//===----------------------------------------------------------------------===//
-template <class ELFT>
-void DynamicLibraryWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
- // Add all the defined symbols to the dynamic symbol table
- // we need hooks into the Atom to find out which atoms need
- // to be exported
- for (auto sec : this->_layout.sections())
- if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
- for (const auto &atom : section->atoms()) {
- const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom);
- if (da && (da->scope() == DefinedAtom::scopeGlobal))
- this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
- atom->_virtualAddr, atom);
- }
-
- for (const UndefinedAtom *a : file.undefined())
- this->_dynamicSymbolTable->addSymbol(a, ELF::SHN_UNDEF);
-
- OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
-}
-
-/// \brief Hook in lld to add CRuntime file
-template <class ELFT>
-void DynamicLibraryWriter<ELFT>::createImplicitFiles(
- std::vector<std::unique_ptr<File> > &result) {
- OutputELFWriter<ELFT>::createImplicitFiles(result);
- // Add the default atoms as defined by executables
- auto file = llvm::make_unique<RuntimeFile<ELFT>>(this->_ctx, "C runtime");
- file->addAbsoluteAtom("_end");
- result.push_back(std::move(file));
-}
-
-template <class ELFT>
-void DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
- OutputELFWriter<ELFT>::finalizeDefaultAtomValues();
- AtomLayout *underScoreEndAtom = this->_layout.findAbsoluteAtom("_end");
- assert(underScoreEndAtom);
-
- if (auto bssSection = this->_layout.findOutputSection(".bss")) {
- underScoreEndAtom->_virtualAddr =
- bssSection->virtualAddr() + bssSection->memSize();
- } else if (auto dataSection = this->_layout.findOutputSection(".data")) {
- underScoreEndAtom->_virtualAddr =
- dataSection->virtualAddr() + dataSection->memSize();
- }
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_DYNAMIC_LIBRARY_WRITER_H
diff --git a/lib/ReaderWriter/ELF/ELFFile.cpp b/lib/ReaderWriter/ELF/ELFFile.cpp
deleted file mode 100644
index 1488f1862b8d..000000000000
--- a/lib/ReaderWriter/ELF/ELFFile.cpp
+++ /dev/null
@@ -1,829 +0,0 @@
-//===- lib/ReaderWriter/ELF/ELFFile.cpp -------------------------*- C++ -*-===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ELFFile.h"
-#include "FileCommon.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace elf {
-
-template <typename ELFT>
-ELFFile<ELFT>::ELFFile(StringRef name, ELFLinkingContext &ctx)
- : SimpleFile(name), _ordinal(0), _doStringsMerge(ctx.mergeCommonStrings()),
- _useWrap(false), _ctx(ctx) {
- setLastError(std::error_code());
-}
-
-template <typename ELFT>
-ELFFile<ELFT>::ELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
- : SimpleFile(mb->getBufferIdentifier()), _mb(std::move(mb)), _ordinal(0),
- _doStringsMerge(ctx.mergeCommonStrings()),
- _useWrap(ctx.wrapCalls().size()), _ctx(ctx) {}
-
-template <typename ELFT>
-std::error_code ELFFile<ELFT>::isCompatible(MemoryBufferRef mb,
- ELFLinkingContext &ctx) {
- return elf::isCompatible<ELFT>(mb, ctx);
-}
-
-template <typename ELFT>
-Atom *ELFFile<ELFT>::findAtom(const Elf_Sym *sourceSym,
- const Elf_Sym *targetSym) {
- // Return the atom for targetSym if we can do so.
- Atom *target = _symbolToAtomMapping.lookup(targetSym);
- if (!target)
- // Some realocations (R_ARM_V4BX) do not have a defined
- // target. For this cases make it points to itself.
- target = _symbolToAtomMapping.lookup(sourceSym);
-
- if (target->definition() != Atom::definitionRegular)
- return target;
- Atom::Scope scope = llvm::cast<DefinedAtom>(target)->scope();
- if (scope == DefinedAtom::scopeTranslationUnit)
- return target;
- if (!redirectReferenceUsingUndefAtom(sourceSym, targetSym))
- return target;
-
- // Otherwise, create a new undefined symbol and returns it.
- StringRef targetName = target->name();
- auto it = _undefAtomsForGroupChild.find(targetName);
- if (it != _undefAtomsForGroupChild.end())
- return it->getValue();
- auto atom = new (_readerStorage) SimpleUndefinedAtom(*this, targetName);
- _undefAtomsForGroupChild[targetName] = atom;
- addAtom(*atom);
- return atom;
-}
-
-template <typename ELFT>
-ErrorOr<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *shdr) const {
- if (!shdr)
- return StringRef();
- return _objFile->getSectionName(shdr);
-}
-
-template <class ELFT> std::error_code ELFFile<ELFT>::doParse() {
- std::error_code ec;
- _objFile.reset(new llvm::object::ELFFile<ELFT>(_mb->getBuffer(), ec));
- if (ec)
- return ec;
-
- if ((ec = createAtomsFromContext()))
- return ec;
-
- // Read input sections from the input file that need to be converted to
- // atoms
- if ((ec = createAtomizableSections()))
- return ec;
-
- // For mergeable strings, we would need to split the section into various
- // atoms
- if ((ec = createMergeableAtoms()))
- return ec;
-
- // Create the necessary symbols that are part of the section that we
- // created in createAtomizableSections function
- if ((ec = createSymbolsFromAtomizableSections()))
- return ec;
-
- // Create the appropriate atoms from the file
- if ((ec = createAtoms()))
- return ec;
- return std::error_code();
-}
-
-template <class ELFT> Reference::KindArch ELFFile<ELFT>::kindArch() {
- switch (_objFile->getHeader()->e_machine) {
- case llvm::ELF::EM_X86_64:
- return Reference::KindArch::x86_64;
- case llvm::ELF::EM_386:
- return Reference::KindArch::x86;
- case llvm::ELF::EM_ARM:
- return Reference::KindArch::ARM;
- case llvm::ELF::EM_HEXAGON:
- return Reference::KindArch::Hexagon;
- case llvm::ELF::EM_MIPS:
- return Reference::KindArch::Mips;
- case llvm::ELF::EM_AARCH64:
- return Reference::KindArch::AArch64;
- }
- llvm_unreachable("unsupported e_machine value");
-}
-
-template <class ELFT>
-std::error_code ELFFile<ELFT>::createAtomizableSections() {
- // Handle: SHT_REL and SHT_RELA sections:
- // Increment over the sections, when REL/RELA section types are found add
- // the contents to the RelocationReferences map.
- // Record the number of relocs to guess at preallocating the buffer.
- uint64_t totalRelocs = 0;
- for (const Elf_Shdr &section : _objFile->sections()) {
- switch (section.sh_type) {
- case llvm::ELF::SHT_SYMTAB:
- _symtab = &section;
- continue;
- case llvm::ELF::SHT_SYMTAB_SHNDX: {
- ErrorOr<ArrayRef<Elf_Word>> tableOrErr = _objFile->getSHNDXTable(section);
- if (std::error_code ec = tableOrErr.getError())
- return ec;
- _shndxTable = *tableOrErr;
- continue;
- }
- }
-
- if (isIgnoredSection(&section))
- continue;
-
- if (isMergeableStringSection(&section)) {
- _mergeStringSections.push_back(&section);
- continue;
- }
-
- if (section.sh_type == llvm::ELF::SHT_RELA) {
- auto sHdrOrErr = _objFile->getSection(section.sh_info);
- if (std::error_code ec = sHdrOrErr.getError())
- return ec;
- auto sHdr = *sHdrOrErr;
- auto rai = _objFile->rela_begin(&section);
- auto rae = _objFile->rela_end(&section);
- _relocationAddendReferences[sHdr] = make_range(rai, rae);
- totalRelocs += std::distance(rai, rae);
- } else if (section.sh_type == llvm::ELF::SHT_REL) {
- auto sHdrOrErr = _objFile->getSection(section.sh_info);
- if (std::error_code ec = sHdrOrErr.getError())
- return ec;
- auto sHdr = *sHdrOrErr;
- auto ri = _objFile->rel_begin(&section);
- auto re = _objFile->rel_end(&section);
- _relocationReferences[sHdr] = &section;
- totalRelocs += std::distance(ri, re);
- } else {
- auto sectionName = _objFile->getSectionName(&section);
- if (std::error_code ec = sectionName.getError())
- return ec;
- _ctx.notifyInputSectionName(*sectionName);
- _sectionSymbols[&section];
- }
- }
- _references.reserve(totalRelocs);
- return std::error_code();
-}
-
-template <class ELFT> std::error_code ELFFile<ELFT>::createMergeableAtoms() {
- // Divide the section that contains mergeable strings into tokens
- // TODO
- // a) add resolver support to recognize multibyte chars
- // b) Create a separate section chunk to write mergeable atoms
- std::vector<MergeString *> tokens;
- for (const Elf_Shdr *msi : _mergeStringSections) {
- auto sectionName = getSectionName(msi);
- if (std::error_code ec = sectionName.getError())
- return ec;
-
- auto sectionContents = getSectionContents(msi);
- if (std::error_code ec = sectionContents.getError())
- return ec;
-
- StringRef secCont(reinterpret_cast<const char *>(sectionContents->begin()),
- sectionContents->size());
-
- unsigned int prev = 0;
- for (std::size_t i = 0, e = sectionContents->size(); i != e; ++i) {
- if ((*sectionContents)[i] == '\0') {
- tokens.push_back(new (_readerStorage) MergeString(
- prev, secCont.slice(prev, i + 1), msi, *sectionName));
- prev = i + 1;
- }
- }
- }
-
- // Create Mergeable atoms
- for (const MergeString *tai : tokens) {
- ArrayRef<uint8_t> content((const uint8_t *)tai->_string.data(),
- tai->_string.size());
- ELFMergeAtom<ELFT> *atom = createMergedString(tai->_sectionName, tai->_shdr,
- content, tai->_offset);
- atom->setOrdinal(++_ordinal);
- addAtom(*atom);
- _mergeAtoms.push_back(atom);
- }
- return std::error_code();
-}
-
-template <class ELFT>
-std::error_code ELFFile<ELFT>::createSymbolsFromAtomizableSections() {
- // Increment over all the symbols collecting atoms and symbol names for
- // later use.
- if (!_symtab)
- return std::error_code();
-
- ErrorOr<StringRef> strTableOrErr =
- _objFile->getStringTableForSymtab(*_symtab);
- if (std::error_code ec = strTableOrErr.getError())
- return ec;
- StringRef strTable = *strTableOrErr;
-
- auto SymI = _objFile->symbol_begin(_symtab),
- SymE = _objFile->symbol_end(_symtab);
- // Skip over dummy sym.
- ++SymI;
-
- for (; SymI != SymE; ++SymI) {
- ErrorOr<const Elf_Shdr *> section =
- _objFile->getSection(SymI, _symtab, _shndxTable);
- if (std::error_code ec = section.getError())
- return ec;
-
- auto symbolName = SymI->getName(strTable);
- if (std::error_code ec = symbolName.getError())
- return ec;
-
- if (SymI->isAbsolute()) {
- ELFAbsoluteAtom<ELFT> *absAtom = createAbsoluteAtom(
- *symbolName, &*SymI, (int64_t)getSymbolValue(&*SymI));
- addAtom(*absAtom);
- _symbolToAtomMapping.insert(std::make_pair(&*SymI, absAtom));
- } else if (SymI->isUndefined()) {
- if (_useWrap &&
- (_wrapSymbolMap.find(*symbolName) != _wrapSymbolMap.end())) {
- auto wrapAtom = _wrapSymbolMap.find(*symbolName);
- _symbolToAtomMapping.insert(
- std::make_pair(&*SymI, wrapAtom->getValue()));
- continue;
- }
- ELFUndefinedAtom<ELFT> *undefAtom =
- createUndefinedAtom(*symbolName, &*SymI);
- addAtom(*undefAtom);
- _symbolToAtomMapping.insert(std::make_pair(&*SymI, undefAtom));
- } else if (isCommonSymbol(&*SymI)) {
- ELFCommonAtom<ELFT> *commonAtom = createCommonAtom(*symbolName, &*SymI);
- commonAtom->setOrdinal(++_ordinal);
- addAtom(*commonAtom);
- _symbolToAtomMapping.insert(std::make_pair(&*SymI, commonAtom));
- } else if (SymI->isDefined()) {
- _sectionSymbols[*section].push_back(SymI);
- } else {
- llvm::errs() << "Unable to create atom for: " << *symbolName << "\n";
- return llvm::object::object_error::parse_failed;
- }
- }
-
- return std::error_code();
-}
-
-template <class ELFT> std::error_code ELFFile<ELFT>::createAtoms() {
- // Holds all the atoms that are part of the section. They are the targets of
- // the kindGroupChild reference.
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> atomsForSection;
-
- // Contains a list of comdat sections for a group.
- for (auto &i : _sectionSymbols) {
- const Elf_Shdr *section = i.first;
- std::vector<const Elf_Sym *> &symbols = i.second;
-
- // Sort symbols by position.
- std::stable_sort(symbols.begin(), symbols.end(),
- [this](const Elf_Sym *a, const Elf_Sym *b) {
- return getSymbolValue(&*a) < getSymbolValue(&*b);
- });
-
- ErrorOr<StringRef> sectionName = this->getSectionName(section);
- if (std::error_code ec = sectionName.getError())
- return ec;
-
- auto sectionContents = getSectionContents(section);
- if (std::error_code ec = sectionContents.getError())
- return ec;
-
- // SHT_GROUP sections are handled in the following loop.
- if (isGroupSection(section))
- continue;
-
- bool addAtoms = (!isGnuLinkOnceSection(*sectionName) &&
- !isSectionMemberOfGroup(section));
-
- if (handleSectionWithNoSymbols(section, symbols)) {
- ELFDefinedAtom<ELFT> *newAtom =
- createSectionAtom(section, *sectionName, *sectionContents);
- newAtom->setOrdinal(++_ordinal);
- if (addAtoms)
- addAtom(*newAtom);
- else
- atomsForSection[*sectionName].push_back(newAtom);
- continue;
- }
-
- ELFDefinedAtom<ELFT> *previousAtom = nullptr;
- ELFReference<ELFT> *anonFollowedBy = nullptr;
-
- if (!_symtab)
- continue;
- ErrorOr<StringRef> strTableOrErr =
- _objFile->getStringTableForSymtab(*_symtab);
- if (std::error_code ec = strTableOrErr.getError())
- return ec;
- StringRef strTable = *strTableOrErr;
- for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
- auto symbol = *si;
- StringRef symbolName = "";
- if (symbol->getType() != llvm::ELF::STT_SECTION) {
- auto symName = symbol->getName(strTable);
- if (std::error_code ec = symName.getError())
- return ec;
- symbolName = *symName;
- }
-
- uint64_t contentSize = symbolContentSize(
- section, &*symbol, (si + 1 == se) ? nullptr : &**(si + 1));
-
- // Check to see if we need to add the FollowOn Reference
- ELFReference<ELFT> *followOn = nullptr;
- if (previousAtom) {
- // Replace the followon atom with the anonymous atom that we created,
- // so that the next symbol that we create is a followon from the
- // anonymous atom.
- if (anonFollowedBy) {
- followOn = anonFollowedBy;
- } else {
- followOn = new (_readerStorage)
- ELFReference<ELFT>(Reference::kindLayoutAfter);
- previousAtom->addReference(followOn);
- }
- }
-
- ArrayRef<uint8_t> symbolData((const uint8_t *)sectionContents->data() +
- getSymbolValue(&*symbol),
- contentSize);
-
- // If the linker finds that a section has global atoms that are in a
- // mergeable section, treat them as defined atoms as they shouldn't be
- // merged away as well as these symbols have to be part of symbol
- // resolution
- if (isMergeableStringSection(section)) {
- if (symbol->getBinding() != llvm::ELF::STB_GLOBAL)
- continue;
- ELFDefinedAtom<ELFT> *atom = createDefinedAtom(
- symbolName, *sectionName, &**si, section, symbolData,
- _references.size(), _references.size(), _references);
- atom->setOrdinal(++_ordinal);
- if (addAtoms)
- addAtom(*atom);
- else
- atomsForSection[*sectionName].push_back(atom);
- continue;
- }
-
- // Don't allocate content to a weak symbol, as they may be merged away.
- // Create an anonymous atom to hold the data.
- ELFDefinedAtom<ELFT> *anonAtom = nullptr;
- anonFollowedBy = nullptr;
- if (symbol->getBinding() == llvm::ELF::STB_WEAK) {
- // Create anonymous new non-weak ELF symbol that holds the symbol
- // data.
- auto sym = new (_readerStorage) Elf_Sym(*symbol);
- sym->setBinding(llvm::ELF::STB_GLOBAL);
- anonAtom = createDefinedAtomAndAssignRelocations(
- "", *sectionName, sym, section, symbolData, *sectionContents);
- symbolData = ArrayRef<uint8_t>();
-
- // If this is the last atom, let's not create a followon reference.
- if (anonAtom && (si + 1) != se) {
- anonFollowedBy = new (_readerStorage)
- ELFReference<ELFT>(Reference::kindLayoutAfter);
- anonAtom->addReference(anonFollowedBy);
- }
- }
-
- ELFDefinedAtom<ELFT> *newAtom = createDefinedAtomAndAssignRelocations(
- symbolName, *sectionName, &*symbol, section, symbolData,
- *sectionContents);
- newAtom->setOrdinal(++_ordinal);
-
- // If the atom was a weak symbol, let's create a followon reference to
- // the anonymous atom that we created.
- if (anonAtom)
- createEdge(newAtom, anonAtom, Reference::kindLayoutAfter);
-
- if (previousAtom) {
- // Set the followon atom to the weak atom that we have created, so
- // that they would alias when the file gets written.
- followOn->setTarget(anonAtom ? anonAtom : newAtom);
- }
-
- // The previous atom is always the atom created before unless the atom
- // is a weak atom.
- previousAtom = anonAtom ? anonAtom : newAtom;
-
- if (addAtoms)
- addAtom(*newAtom);
- else
- atomsForSection[*sectionName].push_back(newAtom);
-
- _symbolToAtomMapping.insert(std::make_pair(&*symbol, newAtom));
- if (anonAtom) {
- anonAtom->setOrdinal(++_ordinal);
- if (addAtoms)
- addAtom(*anonAtom);
- else
- atomsForSection[*sectionName].push_back(anonAtom);
- }
- }
- }
-
- for (auto &i : _sectionSymbols)
- if (std::error_code ec = handleSectionGroup(i.first, atomsForSection))
- return ec;
- for (auto &i : _sectionSymbols)
- if (std::error_code ec = handleGnuLinkOnceSection(i.first, atomsForSection))
- return ec;
-
- updateReferences();
- return std::error_code();
-}
-
-template <class ELFT>
-std::error_code ELFFile<ELFT>::handleGnuLinkOnceSection(
- const Elf_Shdr *section,
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection) {
- ErrorOr<StringRef> sectionName = this->getSectionName(section);
- if (std::error_code ec = sectionName.getError())
- return ec;
- if (!isGnuLinkOnceSection(*sectionName))
- return std::error_code();
-
- unsigned int referenceStart = _references.size();
- std::vector<ELFReference<ELFT> *> refs;
- for (auto ha : atomsForSection[*sectionName]) {
- _groupChild[ha->symbol()] = std::make_pair(*sectionName, section);
- auto *ref =
- new (_readerStorage) ELFReference<ELFT>(Reference::kindGroupChild);
- ref->setTarget(ha);
- refs.push_back(ref);
- }
- atomsForSection[*sectionName].clear();
- // Create a gnu linkonce atom.
- ELFDefinedAtom<ELFT> *atom = createDefinedAtom(
- *sectionName, *sectionName, nullptr, section, ArrayRef<uint8_t>(),
- referenceStart, _references.size(), _references);
- atom->setOrdinal(++_ordinal);
- addAtom(*atom);
- for (auto reference : refs)
- atom->addReference(reference);
- return std::error_code();
-}
-
-template <class ELFT>
-std::error_code ELFFile<ELFT>::handleSectionGroup(
- const Elf_Shdr *section,
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection) {
- ErrorOr<StringRef> sectionName = this->getSectionName(section);
- if (std::error_code ec = sectionName.getError())
- return ec;
- if (!isGroupSection(section))
- return std::error_code();
-
- auto sectionContents = getSectionContents(section);
- if (std::error_code ec = sectionContents.getError())
- return ec;
-
- // A section of type SHT_GROUP defines a grouping of sections. The
- // name of a symbol from one of the containing object's symbol tables
- // provides a signature for the section group. The section header of
- // the SHT_GROUP section specifies the identifying symbol entry, as
- // described: the sh_link member contains the section header index of
- // the symbol table section that contains the entry. The sh_info
- // member contains the symbol table index of the identifying entry.
- // The sh_flags member of the section header contains 0. The name of
- // the section (sh_name) is not specified.
- std::vector<StringRef> sectionNames;
- const Elf_Word *groupMembers =
- reinterpret_cast<const Elf_Word *>(sectionContents->data());
- const size_t count = section->sh_size / sizeof(Elf_Word);
- for (size_t i = 1; i < count; i++) {
- ErrorOr<const Elf_Shdr *> shdr = _objFile->getSection(groupMembers[i]);
- if (std::error_code ec = shdr.getError())
- return ec;
- ErrorOr<StringRef> sectionName = _objFile->getSectionName(*shdr);
- if (std::error_code ec = sectionName.getError())
- return ec;
- sectionNames.push_back(*sectionName);
- }
- ErrorOr<const Elf_Shdr *> symtab = _objFile->getSection(section->sh_link);
- if (std::error_code ec = symtab.getError())
- return ec;
- const Elf_Sym *symbol = _objFile->getSymbol(*symtab, section->sh_info);
- ErrorOr<const Elf_Shdr *> strtab_sec =
- _objFile->getSection((*symtab)->sh_link);
- if (std::error_code ec = strtab_sec.getError())
- return ec;
- ErrorOr<StringRef> strtab_or_err = _objFile->getStringTable(*strtab_sec);
- if (std::error_code ec = strtab_or_err.getError())
- return ec;
- StringRef strtab = *strtab_or_err;
- ErrorOr<StringRef> symbolName = symbol->getName(strtab);
- if (std::error_code ec = symbolName.getError())
- return ec;
-
- unsigned int referenceStart = _references.size();
- std::vector<ELFReference<ELFT> *> refs;
- for (auto name : sectionNames) {
- for (auto ha : atomsForSection[name]) {
- _groupChild[ha->symbol()] = std::make_pair(*symbolName, section);
- auto *ref =
- new (_readerStorage) ELFReference<ELFT>(Reference::kindGroupChild);
- ref->setTarget(ha);
- refs.push_back(ref);
- }
- atomsForSection[name].clear();
- }
-
- // Create an atom for comdat signature.
- ELFDefinedAtom<ELFT> *atom = createDefinedAtom(
- *symbolName, *sectionName, nullptr, section, ArrayRef<uint8_t>(),
- referenceStart, _references.size(), _references);
- atom->setOrdinal(++_ordinal);
- addAtom(*atom);
- for (auto reference : refs)
- atom->addReference(reference);
- return std::error_code();
-}
-
-template <class ELFT> std::error_code ELFFile<ELFT>::createAtomsFromContext() {
- if (!_useWrap)
- return std::error_code();
- // Steps:
- // a) Create an undefined atom for the symbol specified by the --wrap option,
- // as that may be needed to be pulled from an archive.
- // b) Create an undefined atom for __wrap_<symbolname>.
- // c) All references to the symbol specified by wrap should point to
- // __wrap_<symbolname>
- // d) All references to __real_symbol should point to the <symbol>
- for (auto &wrapsym : _ctx.wrapCalls()) {
- StringRef wrapStr = wrapsym.getKey();
- // Create a undefined symbol fror the wrap symbol.
- UndefinedAtom *wrapSymAtom =
- new (_readerStorage) SimpleUndefinedAtom(*this, wrapStr);
- StringRef wrapCallSym =
- _ctx.allocateString((llvm::Twine("__wrap_") + wrapStr).str());
- StringRef realCallSym =
- _ctx.allocateString((llvm::Twine("__real_") + wrapStr).str());
- UndefinedAtom *wrapCallAtom =
- new (_readerStorage) SimpleUndefinedAtom(*this, wrapCallSym);
- // Create maps, when there is call to sym, it should point to wrapCallSym.
- _wrapSymbolMap.insert(std::make_pair(wrapStr, wrapCallAtom));
- // Whenever there is a reference to realCall it should point to the symbol
- // created for each wrap usage.
- _wrapSymbolMap.insert(std::make_pair(realCallSym, wrapSymAtom));
- addAtom(*wrapSymAtom);
- addAtom(*wrapCallAtom);
- }
- return std::error_code();
-}
-
-template <class ELFT>
-ELFDefinedAtom<ELFT> *ELFFile<ELFT>::createDefinedAtomAndAssignRelocations(
- StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol,
- const Elf_Shdr *section, ArrayRef<uint8_t> symContent,
- ArrayRef<uint8_t> secContent) {
- unsigned int referenceStart = _references.size();
-
- // Add Rela (those with r_addend) references:
- auto rari = _relocationAddendReferences.find(section);
- if (rari != _relocationAddendReferences.end())
- createRelocationReferences(symbol, symContent, rari->second);
-
- // Add Rel references.
- auto rri = _relocationReferences.find(section);
- if (rri != _relocationReferences.end())
- createRelocationReferences(symbol, symContent, secContent, rri->second);
-
- // Create the DefinedAtom and add it to the list of DefinedAtoms.
- return createDefinedAtom(symbolName, sectionName, symbol, section, symContent,
- referenceStart, _references.size(), _references);
-}
-
-template <class ELFT>
-void ELFFile<ELFT>::createRelocationReferences(const Elf_Sym *symbol,
- ArrayRef<uint8_t> content,
- range<const Elf_Rela *> rels) {
- bool isMips64EL = _objFile->isMips64EL();
- const auto symValue = getSymbolValue(symbol);
- for (const auto &rel : rels) {
- if (rel.r_offset < symValue || symValue + content.size() <= rel.r_offset)
- continue;
- auto elfRelocation = new (_readerStorage)
- ELFReference<ELFT>(&rel, rel.r_offset - symValue, kindArch(),
- rel.getType(isMips64EL), rel.getSymbol(isMips64EL));
- addReferenceToSymbol(elfRelocation, symbol);
- _references.push_back(elfRelocation);
- }
-}
-
-template <class ELFT>
-void ELFFile<ELFT>::createRelocationReferences(const Elf_Sym *symbol,
- ArrayRef<uint8_t> symContent,
- ArrayRef<uint8_t> secContent,
- const Elf_Shdr *relSec) {
- auto rels = _objFile->rels(relSec);
- bool isMips64EL = _objFile->isMips64EL();
- const auto symValue = getSymbolValue(symbol);
- for (const auto &rel : rels) {
- if (rel.r_offset < symValue || symValue + symContent.size() <= rel.r_offset)
- continue;
- auto elfRelocation = new (_readerStorage)
- ELFReference<ELFT>(rel.r_offset - symValue, kindArch(),
- rel.getType(isMips64EL), rel.getSymbol(isMips64EL));
- Reference::Addend addend = getInitialAddend(symContent, symValue, rel);
- elfRelocation->setAddend(addend);
- addReferenceToSymbol(elfRelocation, symbol);
- _references.push_back(elfRelocation);
- }
-}
-
-template <class ELFT>
-void ELFFile<ELFT>::updateReferenceForMergeStringAccess(ELFReference<ELFT> *ref,
- const Elf_Sym *symbol,
- const Elf_Shdr *shdr) {
- // If the target atom is mergeable strefng atom, the atom might have been
- // merged with other atom having the same contents. Try to find the
- // merged one if that's the case.
- int64_t addend = ref->addend();
- if (addend < 0)
- addend = 0;
-
- const MergeSectionKey ms = {shdr, addend};
- auto msec = _mergedSectionMap.find(ms);
- if (msec != _mergedSectionMap.end()) {
- ref->setTarget(msec->second);
- return;
- }
-
- // The target atom was not merged. Mergeable atoms are not in
- // _symbolToAtomMapping, so we cannot find it by calling findAtom(). We
- // instead call findMergeAtom().
- if (symbol->getType() != llvm::ELF::STT_SECTION)
- addend = getSymbolValue(symbol) + addend;
- ELFMergeAtom<ELFT> *mergedAtom = findMergeAtom(shdr, addend);
- ref->setOffset(addend - mergedAtom->offset());
- ref->setAddend(0);
- ref->setTarget(mergedAtom);
-}
-
-template <class ELFT> void ELFFile<ELFT>::updateReferences() {
- for (auto &ri : _references) {
- if (ri->kindNamespace() != Reference::KindNamespace::ELF)
- continue;
- const Elf_Sym *symbol =
- _objFile->getSymbol(_symtab, ri->targetSymbolIndex());
- ErrorOr<const Elf_Shdr *> shdr =
- _objFile->getSection(symbol, _symtab, _shndxTable);
-
- // If the atom is not in mergeable string section, the target atom is
- // simply that atom.
- if (isMergeableStringSection(*shdr))
- updateReferenceForMergeStringAccess(ri, symbol, *shdr);
- else
- ri->setTarget(findAtom(findSymbolForReference(ri), symbol));
- }
-}
-
-template <class ELFT>
-bool ELFFile<ELFT>::isIgnoredSection(const Elf_Shdr *section) {
- switch (section->sh_type) {
- case llvm::ELF::SHT_NULL:
- case llvm::ELF::SHT_STRTAB:
- case llvm::ELF::SHT_SYMTAB:
- case llvm::ELF::SHT_SYMTAB_SHNDX:
- return true;
- default:
- break;
- }
- return false;
-}
-
-template <class ELFT>
-bool ELFFile<ELFT>::isMergeableStringSection(const Elf_Shdr *section) {
- if (_doStringsMerge && section) {
- int64_t sectionFlags = section->sh_flags;
- sectionFlags &= ~llvm::ELF::SHF_ALLOC;
- // Mergeable string sections have both SHF_MERGE and SHF_STRINGS flags
- // set. sh_entsize is the size of each character which is normally 1.
- if ((section->sh_entsize < 2) &&
- (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) {
- return true;
- }
- }
- return false;
-}
-
-template <class ELFT>
-ELFDefinedAtom<ELFT> *
-ELFFile<ELFT>::createSectionAtom(const Elf_Shdr *section, StringRef sectionName,
- ArrayRef<uint8_t> content) {
- auto *sym = new (_readerStorage) Elf_Sym;
- sym->st_name = 0;
- sym->setBindingAndType(llvm::ELF::STB_LOCAL, llvm::ELF::STT_SECTION);
- sym->st_other = 0;
- sym->st_shndx = 0;
- sym->st_value = 0;
- sym->st_size = 0;
- auto *newAtom = createDefinedAtomAndAssignRelocations(
- "", sectionName, sym, section, content, content);
- newAtom->setOrdinal(++_ordinal);
- return newAtom;
-}
-
-template <class ELFT>
-uint64_t ELFFile<ELFT>::symbolContentSize(const Elf_Shdr *section,
- const Elf_Sym *symbol,
- const Elf_Sym *nextSymbol) {
- const auto symValue = getSymbolValue(symbol);
- // if this is the last symbol, take up the remaining data.
- return nextSymbol ? getSymbolValue(nextSymbol) - symValue
- : section->sh_size - symValue;
-}
-
-template <class ELFT>
-void ELFFile<ELFT>::createEdge(ELFDefinedAtom<ELFT> *from,
- ELFDefinedAtom<ELFT> *to, uint32_t edgeKind) {
- auto reference = new (_readerStorage) ELFReference<ELFT>(edgeKind);
- reference->setTarget(to);
- from->addReference(reference);
-}
-
-/// Does the atom need to be redirected using a separate undefined atom?
-template <class ELFT>
-bool ELFFile<ELFT>::redirectReferenceUsingUndefAtom(
- const Elf_Sym *sourceSymbol, const Elf_Sym *targetSymbol) const {
- auto groupChildTarget = _groupChild.find(targetSymbol);
-
- // If the reference is not to a group child atom, there is no need to redirect
- // using a undefined atom. Its also not needed if the source and target are
- // from the same section.
- if ((groupChildTarget == _groupChild.end()) ||
- (sourceSymbol->st_shndx == targetSymbol->st_shndx))
- return false;
-
- auto groupChildSource = _groupChild.find(sourceSymbol);
-
- // If the source symbol is not in a group, use a undefined symbol too.
- if (groupChildSource == _groupChild.end())
- return true;
-
- // If the source and child are from the same group, we dont need the
- // relocation to go through a undefined symbol.
- if (groupChildSource->second.second == groupChildTarget->second.second)
- return false;
- return true;
-}
-
-template <class ELFT>
-void RuntimeFile<ELFT>::addAbsoluteAtom(StringRef symbolName, bool isHidden) {
- assert(!symbolName.empty() && "AbsoluteAtoms must have a name");
- auto *sym = new (this->_readerStorage) Elf_Sym;
- sym->st_name = 0;
- sym->st_value = 0;
- sym->st_shndx = llvm::ELF::SHN_ABS;
- sym->setBindingAndType(llvm::ELF::STB_GLOBAL, llvm::ELF::STT_OBJECT);
- if (isHidden)
- sym->setVisibility(llvm::ELF::STV_HIDDEN);
- else
- sym->setVisibility(llvm::ELF::STV_DEFAULT);
- sym->st_size = 0;
- ELFAbsoluteAtom<ELFT> *atom = this->createAbsoluteAtom(symbolName, sym, -1);
- this->addAtom(*atom);
-}
-
-template <class ELFT>
-void RuntimeFile<ELFT>::addUndefinedAtom(StringRef symbolName) {
- assert(!symbolName.empty() && "UndefinedAtoms must have a name");
- auto *sym = new (this->_readerStorage) Elf_Sym;
- sym->st_name = 0;
- sym->st_value = 0;
- sym->st_shndx = llvm::ELF::SHN_UNDEF;
- sym->setBindingAndType(llvm::ELF::STB_GLOBAL, llvm::ELF::STT_NOTYPE);
- sym->setVisibility(llvm::ELF::STV_DEFAULT);
- sym->st_size = 0;
- ELFUndefinedAtom<ELFT> *atom = this->createUndefinedAtom(symbolName, sym);
- this->addAtom(*atom);
-}
-
-template class ELFFile<ELF32LE>;
-template class ELFFile<ELF32BE>;
-template class ELFFile<ELF64LE>;
-template class ELFFile<ELF64BE>;
-
-template class RuntimeFile<ELF32LE>;
-template class RuntimeFile<ELF32BE>;
-template class RuntimeFile<ELF64LE>;
-template class RuntimeFile<ELF64BE>;
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/ELFFile.h b/lib/ReaderWriter/ELF/ELFFile.h
deleted file mode 100644
index 5e0c2fc75a87..000000000000
--- a/lib/ReaderWriter/ELF/ELFFile.h
+++ /dev/null
@@ -1,395 +0,0 @@
-//===- lib/ReaderWriter/ELF/ELFFile.h ---------------------------*- C++ -*-===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_FILE_H
-#define LLD_READER_WRITER_ELF_FILE_H
-
-#include "Atoms.h"
-#include "FileCommon.h"
-#include "llvm/ADT/MapVector.h"
-#include <map>
-#include <unordered_map>
-
-namespace lld {
-
-namespace elf {
-/// \brief Read a binary, find out based on the symbol table contents what kind
-/// of symbol it is and create corresponding atoms for it
-template <class ELFT> class ELFFile : public SimpleFile {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
- typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
-
- // A Map is used to hold the atoms that have been divided up
- // after reading the section that contains Merge String attributes
- struct MergeSectionKey {
- const Elf_Shdr *_shdr;
- int64_t _offset;
- };
-
- struct MergeSectionEq {
- int64_t operator()(const MergeSectionKey &k) const {
- return llvm::hash_combine((int64_t)(k._shdr->sh_name),
- (int64_t)k._offset);
- }
- bool operator()(const MergeSectionKey &lhs,
- const MergeSectionKey &rhs) const {
- return ((lhs._shdr->sh_name == rhs._shdr->sh_name) &&
- (lhs._offset == rhs._offset));
- }
- };
-
- struct MergeString {
- MergeString(int64_t offset, StringRef str, const Elf_Shdr *shdr,
- StringRef sectionName)
- : _offset(offset), _string(str), _shdr(shdr),
- _sectionName(sectionName) {}
- // the offset of this atom
- int64_t _offset;
- // The content
- StringRef _string;
- // Section header
- const Elf_Shdr *_shdr;
- // Section name
- StringRef _sectionName;
- };
-
- // This is used to find the MergeAtom given a relocation
- // offset
- typedef std::vector<ELFMergeAtom<ELFT> *> MergeAtomsT;
-
- /// \brief find a merge atom given a offset
- ELFMergeAtom<ELFT> *findMergeAtom(const Elf_Shdr *shdr, int64_t offset) {
- auto it = std::find_if(_mergeAtoms.begin(), _mergeAtoms.end(),
- [=](const ELFMergeAtom<ELFT> *a) {
- int64_t off = a->offset();
- return shdr->sh_name == a->section() &&
- offset >= off &&
- offset <= off + (int64_t)a->size();
- });
- assert(it != _mergeAtoms.end());
- return *it;
- }
-
- typedef std::unordered_map<MergeSectionKey, DefinedAtom *, MergeSectionEq,
- MergeSectionEq> MergedSectionMapT;
- typedef typename MergedSectionMapT::iterator MergedSectionMapIterT;
-
-public:
- ELFFile(StringRef name, ELFLinkingContext &ctx);
- ELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
-
- static std::error_code isCompatible(MemoryBufferRef mb,
- ELFLinkingContext &ctx);
-
- static bool canParse(file_magic magic) {
- return magic == file_magic::elf_relocatable;
- }
-
- virtual Reference::KindArch kindArch();
-
- /// \brief Create symbols from LinkingContext.
- std::error_code createAtomsFromContext();
-
- /// \brief Read input sections and populate necessary data structures
- /// to read them later and create atoms
- std::error_code createAtomizableSections();
-
- /// \brief Create mergeable atoms from sections that have the merge attribute
- /// set
- std::error_code createMergeableAtoms();
-
- /// \brief Add the symbols that the sections contain. The symbols will be
- /// converted to atoms for
- /// Undefined symbols, absolute symbols
- std::error_code createSymbolsFromAtomizableSections();
-
- /// \brief Create individual atoms
- std::error_code createAtoms();
-
- // Assuming sourceSymbol has a reference to targetSym, find an atom
- // for targetSym. Usually it's just the atom for targetSym.
- // However, if an atom is in a section group, we may want to return an
- // undefined atom for targetSym to let the resolver to resolve the
- // symbol. (It's because if targetSym is in a section group A, and the
- // group A is not linked in because other file already provides a
- // section group B, we want to resolve references to B, not to A.)
- Atom *findAtom(const Elf_Sym *sourceSym, const Elf_Sym *targetSym);
-
-protected:
- ELFDefinedAtom<ELFT> *createDefinedAtomAndAssignRelocations(
- StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol,
- const Elf_Shdr *section, ArrayRef<uint8_t> symContent,
- ArrayRef<uint8_t> secContent);
-
- std::error_code doParse() override;
-
- /// \brief Iterate over Elf_Rela relocations list and create references.
- virtual void createRelocationReferences(const Elf_Sym *symbol,
- ArrayRef<uint8_t> content,
- range<const Elf_Rela *> rels);
-
- /// \brief Iterate over Elf_Rel relocations list and create references.
- virtual void createRelocationReferences(const Elf_Sym *symbol,
- ArrayRef<uint8_t> symContent,
- ArrayRef<uint8_t> secContent,
- const Elf_Shdr *relSec);
-
- /// \brief After all the Atoms and References are created, update each
- /// Reference's target with the Atom pointer it refers to.
- void updateReferences();
-
- /// \brief Update the reference if the access corresponds to a merge string
- /// section.
- void updateReferenceForMergeStringAccess(ELFReference<ELFT> *ref,
- const Elf_Sym *symbol,
- const Elf_Shdr *shdr);
-
- /// \brief Do we want to ignore the section. Ignored sections are
- /// not processed to create atoms
- bool isIgnoredSection(const Elf_Shdr *section);
-
- /// \brief Is the current section be treated as a mergeable string section.
- /// The contents of a mergeable string section are null-terminated strings.
- /// If the section have mergeable strings, the linker would need to split
- /// the section into multiple atoms and mark them mergeByContent.
- bool isMergeableStringSection(const Elf_Shdr *section);
-
- /// \brief Returns a new anonymous atom whose size is equal to the
- /// section size. That atom will be used to represent the entire
- /// section that have no symbols.
- ELFDefinedAtom<ELFT> *createSectionAtom(const Elf_Shdr *section,
- StringRef sectionName,
- ArrayRef<uint8_t> contents);
-
- /// Returns the symbol's content size. The nextSymbol should be null if the
- /// symbol is the last one in the section.
- uint64_t symbolContentSize(const Elf_Shdr *section,
- const Elf_Sym *symbol,
- const Elf_Sym *nextSymbol);
-
- void createEdge(ELFDefinedAtom<ELFT> *from, ELFDefinedAtom<ELFT> *to,
- uint32_t edgeKind);
-
- /// Get the section name for a section.
- ErrorOr<StringRef> getSectionName(const Elf_Shdr *shdr) const;
-
- /// Determines if the section occupy memory space.
- bool sectionOccupiesMemorySpace(const Elf_Shdr *shdr) const {
- return (shdr->sh_type != llvm::ELF::SHT_NOBITS);
- }
-
- /// Return the section contents.
- ErrorOr<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *shdr) const {
- if (!shdr || !sectionOccupiesMemorySpace(shdr))
- return ArrayRef<uint8_t>();
- return _objFile->getSectionContents(shdr);
- }
-
- /// Determines if the target wants to create an atom for a section that has no
- /// symbol references.
- bool
- handleSectionWithNoSymbols(const Elf_Shdr *shdr,
- std::vector<const Elf_Sym *> &syms) const {
- return shdr &&
- (shdr->sh_type == llvm::ELF::SHT_PROGBITS ||
- shdr->sh_type == llvm::ELF::SHT_INIT_ARRAY ||
- shdr->sh_type == llvm::ELF::SHT_FINI_ARRAY ||
- shdr->sh_type == llvm::ELF::SHT_NOTE) &&
- syms.empty();
- }
-
- /// Handle creation of atoms for .gnu.linkonce sections.
- std::error_code handleGnuLinkOnceSection(
- const Elf_Shdr *section,
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection);
-
- // Handle COMDAT scetions.
- std::error_code handleSectionGroup(
- const Elf_Shdr *section,
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection);
-
- /// Process the Undefined symbol and create an atom for it.
- ELFUndefinedAtom<ELFT> *createUndefinedAtom(StringRef symName,
- const Elf_Sym *sym) {
- return new (_readerStorage) ELFUndefinedAtom<ELFT>(*this, symName, sym);
- }
-
- /// Process the Absolute symbol and create an atom for it.
- ELFAbsoluteAtom<ELFT> *createAbsoluteAtom(StringRef symName,
- const Elf_Sym *sym, int64_t value) {
- return new (_readerStorage)
- ELFAbsoluteAtom<ELFT>(*this, symName, sym, value);
- }
-
- /// Returns true if the symbol is common symbol. A common symbol represents a
- /// tentive definition in C. It has name, size and alignment constraint, but
- /// actual storage has not yet been allocated. (The linker will allocate
- /// storage for them in the later pass after coalescing tentative symbols by
- /// name.)
- virtual bool isCommonSymbol(const Elf_Sym *symbol) const {
- return symbol->getType() == llvm::ELF::STT_COMMON ||
- symbol->st_shndx == llvm::ELF::SHN_COMMON;
- }
-
- /// Returns true if the section is a gnulinkonce section.
- bool isGnuLinkOnceSection(StringRef sectionName) const {
- return sectionName.startswith(".gnu.linkonce.");
- }
-
- /// Returns true if the section is a COMDAT group section.
- bool isGroupSection(const Elf_Shdr *shdr) const {
- return (shdr->sh_type == llvm::ELF::SHT_GROUP);
- }
-
- /// Returns true if the section is a member of some group.
- bool isSectionMemberOfGroup(const Elf_Shdr *shdr) const {
- return (shdr->sh_flags & llvm::ELF::SHF_GROUP);
- }
-
- /// Returns correct st_value for the symbol depending on the architecture.
- /// For most architectures it's just a regular st_value with no changes.
- virtual uint64_t getSymbolValue(const Elf_Sym *symbol) const {
- return symbol->st_value;
- }
-
- /// Returns initial addend
- virtual Reference::Addend getInitialAddend(ArrayRef<uint8_t> symContent,
- uint64_t symbolValue,
- const Elf_Rel& reference) const {
- return *(symContent.data() + reference.r_offset - symbolValue);
- }
-
- /// Process the common symbol and create an atom for it.
- virtual ELFCommonAtom<ELFT> *createCommonAtom(StringRef symName,
- const Elf_Sym *sym) {
- return new (_readerStorage) ELFCommonAtom<ELFT>(*this, symName, sym);
- }
-
- /// Creates an atom for a given defined symbol.
- virtual ELFDefinedAtom<ELFT> *
- createDefinedAtom(StringRef symName, StringRef sectionName,
- const Elf_Sym *sym, const Elf_Shdr *sectionHdr,
- ArrayRef<uint8_t> contentData, unsigned int referenceStart,
- unsigned int referenceEnd,
- std::vector<ELFReference<ELFT> *> &referenceList) {
- return new (_readerStorage) ELFDefinedAtom<ELFT>(
- *this, symName, sectionName, sym, sectionHdr, contentData,
- referenceStart, referenceEnd, referenceList);
- }
-
- /// Process the Merge string and create an atom for it.
- ELFMergeAtom<ELFT> *createMergedString(StringRef sectionName,
- const Elf_Shdr *sectionHdr,
- ArrayRef<uint8_t> contentData,
- unsigned int offset) {
- auto *mergeAtom = new (_readerStorage)
- ELFMergeAtom<ELFT>(*this, sectionName, sectionHdr, contentData, offset);
- const MergeSectionKey mergedSectionKey = {sectionHdr, offset};
- if (_mergedSectionMap.find(mergedSectionKey) == _mergedSectionMap.end())
- _mergedSectionMap.insert(std::make_pair(mergedSectionKey, mergeAtom));
- return mergeAtom;
- }
-
- /// References to the sections comprising a group, from sections
- /// outside the group, must be made via global UNDEF symbols,
- /// referencing global symbols defined as addresses in the group
- /// sections. They may not reference local symbols for addresses in
- /// the group's sections, including section symbols.
- /// ABI Doc : https://mentorembedded.github.io/cxx-abi/abi/prop-72-comdat.html
- /// Does the atom need to be redirected using a separate undefined atom?
- bool redirectReferenceUsingUndefAtom(const Elf_Sym *sourceSymbol,
- const Elf_Sym *targetSymbol) const;
-
- void addReferenceToSymbol(const ELFReference<ELFT> *r, const Elf_Sym *sym) {
- _referenceToSymbol[r] = sym;
- }
-
- const Elf_Sym *findSymbolForReference(const ELFReference<ELFT> *r) const {
- auto elfReferenceToSymbol = _referenceToSymbol.find(r);
- if (elfReferenceToSymbol != _referenceToSymbol.end())
- return elfReferenceToSymbol->second;
- return nullptr;
- }
-
- llvm::BumpPtrAllocator _readerStorage;
- std::unique_ptr<llvm::object::ELFFile<ELFT> > _objFile;
- const Elf_Shdr *_symtab = nullptr;
- ArrayRef<Elf_Word> _shndxTable;
-
- /// \brief _relocationAddendReferences and _relocationReferences contain the
- /// list of relocations references. In ELF, if a section named, ".text" has
- /// relocations will also have a section named ".rel.text" or ".rela.text"
- /// which will hold the entries.
- std::unordered_map<const Elf_Shdr *, range<const Elf_Rela *>>
- _relocationAddendReferences;
- MergedSectionMapT _mergedSectionMap;
- std::unordered_map<const Elf_Shdr *, const Elf_Shdr *> _relocationReferences;
- std::vector<ELFReference<ELFT> *> _references;
- llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
- llvm::DenseMap<const ELFReference<ELFT> *, const Elf_Sym *>
- _referenceToSymbol;
- // Group child atoms have a pair corresponding to the signature and the
- // section header of the section that was used for generating the signature.
- llvm::DenseMap<const Elf_Sym *, std::pair<StringRef, const Elf_Shdr *>>
- _groupChild;
- llvm::StringMap<Atom *> _undefAtomsForGroupChild;
-
- /// \brief Atoms that are created for a section that has the merge property
- /// set
- MergeAtomsT _mergeAtoms;
-
- /// \brief the section and the symbols that are contained within it to create
- /// used to create atoms
- llvm::MapVector<const Elf_Shdr *, std::vector<const Elf_Sym *>>
- _sectionSymbols;
-
- /// \brief Sections that have merge string property
- std::vector<const Elf_Shdr *> _mergeStringSections;
-
- std::unique_ptr<MemoryBuffer> _mb;
- int64_t _ordinal;
-
- /// \brief the cached options relevant while reading the ELF File
- bool _doStringsMerge;
-
- /// \brief Is --wrap on?
- bool _useWrap;
-
- /// \brief The LinkingContext.
- ELFLinkingContext &_ctx;
-
- // Wrap map
- llvm::StringMap<UndefinedAtom *> _wrapSymbolMap;
-};
-
-/// \brief All atoms are owned by a File. To add linker specific atoms
-/// the atoms need to be inserted to a file called (RuntimeFile) which
-/// are basically additional symbols required by libc and other runtime
-/// libraries part of executing a program. This class provides support
-/// for adding absolute symbols and undefined symbols
-template <class ELFT> class RuntimeFile : public ELFFile<ELFT> {
-public:
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- RuntimeFile(ELFLinkingContext &ctx, StringRef name)
- : ELFFile<ELFT>(name, ctx) {}
-
- /// \brief add a global absolute atom
- virtual void addAbsoluteAtom(StringRef symbolName, bool isHidden = false);
-
- /// \brief add an undefined atom
- virtual void addUndefinedAtom(StringRef symbolName);
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_ELF_FILE_H
diff --git a/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
deleted file mode 100644
index 70d6d618207d..000000000000
--- a/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-//===- lib/ReaderWriter/ELF/ELFLinkingContext.cpp -------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "ELFFile.h"
-#include "OrderPass.h"
-#include "TargetHandler.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-
-#if defined(HAVE_CXXABI_H)
-#include <cxxabi.h>
-#endif
-
-using llvm::sys::fs::exists;
-using llvm::sys::path::is_absolute;
-
-namespace lld {
-
-class CommandLineUndefinedAtom : public SimpleUndefinedAtom {
-public:
- CommandLineUndefinedAtom(const File &f, StringRef name)
- : SimpleUndefinedAtom(f, name) {}
-
- CanBeNull canBeNull() const override {
- return CanBeNull::canBeNullAtBuildtime;
- }
-};
-
-void ELFLinkingContext::addPasses(PassManager &pm) {
- pm.add(llvm::make_unique<elf::OrderPass>());
-}
-
-uint16_t ELFLinkingContext::getOutputMachine() const {
- switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- return llvm::ELF::EM_386;
- case llvm::Triple::x86_64:
- return llvm::ELF::EM_X86_64;
- case llvm::Triple::hexagon:
- return llvm::ELF::EM_HEXAGON;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return llvm::ELF::EM_MIPS;
- case llvm::Triple::aarch64:
- return llvm::ELF::EM_AARCH64;
- case llvm::Triple::arm:
- return llvm::ELF::EM_ARM;
- default:
- llvm_unreachable("Unhandled arch");
- }
-}
-
-StringRef ELFLinkingContext::entrySymbolName() const {
- if (_outputELFType == llvm::ELF::ET_EXEC && _entrySymbolName.empty())
- return "_start";
- return _entrySymbolName;
-}
-
-bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
- switch (outputFileType()) {
- case LinkingContext::OutputFileType::YAML:
- _writer = createWriterYAML(*this);
- break;
- default:
- _writer = createWriterELF(*this);
- break;
- }
-
- // If -dead_strip, set up initial live symbols.
- if (deadStrip())
- addDeadStripRoot(entrySymbolName());
- return true;
-}
-
-bool ELFLinkingContext::isDynamic() const {
- switch (_outputELFType) {
- case llvm::ELF::ET_EXEC:
- return !_isStaticExecutable;
- case llvm::ELF::ET_DYN:
- return true;
- }
- return false;
-}
-
-bool ELFLinkingContext::isRelativeReloc(const Reference &) const {
- return false;
-}
-
-Writer &ELFLinkingContext::writer() const { return *_writer; }
-
-static void buildSearchPath(SmallString<128> &path, StringRef dir,
- StringRef sysRoot) {
- if (dir.startswith("=/")) {
- // If a search directory begins with "=", "=" is replaced
- // with the sysroot path.
- path.assign(sysRoot);
- path.append(dir.substr(1));
- } else {
- path.assign(dir);
- }
-}
-
-ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
- bool hasColonPrefix = libName[0] == ':';
- SmallString<128> path;
- for (StringRef dir : _inputSearchPaths) {
- // Search for dynamic library
- if (!_isStaticExecutable) {
- buildSearchPath(path, dir, _sysrootPath);
- llvm::sys::path::append(path, hasColonPrefix
- ? libName.drop_front()
- : Twine("lib", libName) + ".so");
- if (exists(path.str()))
- return path.str().copy(_allocator);
- }
- // Search for static libraries too
- buildSearchPath(path, dir, _sysrootPath);
- llvm::sys::path::append(path, hasColonPrefix
- ? libName.drop_front()
- : Twine("lib", libName) + ".a");
- if (exists(path.str()))
- return path.str().copy(_allocator);
- }
- if (hasColonPrefix && exists(libName.drop_front()))
- return libName.drop_front();
-
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-ErrorOr<StringRef> ELFLinkingContext::searchFile(StringRef fileName,
- bool isSysRooted) const {
- SmallString<128> path;
- if (is_absolute(fileName) && isSysRooted) {
- path.assign(_sysrootPath);
- path.append(fileName);
- if (exists(path.str()))
- return path.str().copy(_allocator);
- } else if (exists(fileName)) {
- return fileName;
- }
-
- if (is_absolute(fileName))
- return make_error_code(llvm::errc::no_such_file_or_directory);
-
- for (StringRef dir : _inputSearchPaths) {
- buildSearchPath(path, dir, _sysrootPath);
- llvm::sys::path::append(path, fileName);
- if (exists(path.str()))
- return path.str().copy(_allocator);
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-void ELFLinkingContext::createInternalFiles(
- std::vector<std::unique_ptr<File>> &files) const {
- std::unique_ptr<SimpleFile> file(
- new SimpleFile("<internal file for --defsym>"));
- for (auto &i : getAbsoluteSymbols()) {
- StringRef sym = i.first;
- uint64_t val = i.second;
- file->addAtom(*(new (_allocator) SimpleAbsoluteAtom(
- *file, sym, Atom::scopeGlobal, val)));
- }
- files.push_back(std::move(file));
- LinkingContext::createInternalFiles(files);
-}
-
-void ELFLinkingContext::finalizeInputFiles() {
- // Add virtual archive that resolves undefined symbols.
- if (_resolver)
- getNodes().push_back(llvm::make_unique<FileNode>(std::move(_resolver)));
-}
-
-std::unique_ptr<File> ELFLinkingContext::createUndefinedSymbolFile() const {
- if (_initialUndefinedSymbols.empty())
- return nullptr;
- std::unique_ptr<SimpleFile> undefinedSymFile(
- new SimpleFile("command line option -u"));
- for (auto undefSymStr : _initialUndefinedSymbols)
- undefinedSymFile->addAtom(*(new (_allocator) CommandLineUndefinedAtom(
- *undefinedSymFile, undefSymStr)));
- return std::move(undefinedSymFile);
-}
-
-void ELFLinkingContext::notifySymbolTableCoalesce(const Atom *existingAtom,
- const Atom *newAtom,
- bool &useNew) {
- // First suppose that the `existingAtom` is defined
- // and the `newAtom` is undefined.
- auto *da = dyn_cast<DefinedAtom>(existingAtom);
- auto *ua = dyn_cast<UndefinedAtom>(newAtom);
- if (!da && !ua) {
- // Then try to reverse the assumption.
- da = dyn_cast<DefinedAtom>(newAtom);
- ua = dyn_cast<UndefinedAtom>(existingAtom);
- }
-
- if (da && ua && da->scope() == Atom::scopeGlobal &&
- isa<SharedLibraryFile>(ua->file()))
- // If strong defined atom coalesces away an atom declared
- // in the shared object the strong atom needs to be dynamically exported.
- // Save its name.
- _dynamicallyExportedSymbols.insert(ua->name());
-}
-
-std::string ELFLinkingContext::demangle(StringRef symbolName) const {
-#if defined(HAVE_CXXABI_H)
- if (!demangleSymbols())
- return symbolName;
-
- // Only try to demangle symbols that look like C++ symbols
- if (!symbolName.startswith("_Z"))
- return symbolName;
-
- SmallString<256> symBuff;
- StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
- const char *cstr = nullTermSym.data();
- int status;
- char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
- if (!demangled)
- return symbolName;
- std::string result(demangled);
- // __cxa_demangle() always uses a malloc'ed buffer to return the result.
- free(demangled);
- return result;
-#else
- return symbolName;
-#endif
-}
-
-void ELFLinkingContext::setUndefinesResolver(std::unique_ptr<File> resolver) {
- assert(isa<ArchiveLibraryFile>(resolver.get()) && "Wrong resolver type");
- _resolver = std::move(resolver);
-}
-
-void ELFLinkingContext::notifyInputSectionName(StringRef name) {
- // Save sections names which can be represented as a C identifier.
- if (name.find_first_not_of("0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "_") == StringRef::npos) {
- std::lock_guard<std::mutex> lock(_cidentMutex);
- _cidentSections.insert(name);
- }
-}
-
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/ELFReader.h b/lib/ReaderWriter/ELF/ELFReader.h
deleted file mode 100644
index 60af6dff9980..000000000000
--- a/lib/ReaderWriter/ELF/ELFReader.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- lib/ReaderWriter/ELF/ELFReader.h -----------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_READER_H
-#define LLD_READER_WRITER_ELF_READER_H
-
-#include "DynamicFile.h"
-#include "ELFFile.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reader.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Object/ELF.h"
-
-namespace lld {
-namespace elf {
-
-template <typename FileT> class ELFReader : public Reader {
-public:
- ELFReader(ELFLinkingContext &ctx) : _ctx(ctx) {}
-
- bool canParse(file_magic magic, MemoryBufferRef mb) const override {
- return FileT::canParse(magic);
- }
-
- ErrorOr<std::unique_ptr<File>>
- loadFile(std::unique_ptr<MemoryBuffer> mb,
- const class Registry &) const override {
- if (std::error_code ec = FileT::isCompatible(mb->getMemBufferRef(), _ctx))
- return ec;
- std::unique_ptr<File> ret = llvm::make_unique<FileT>(std::move(mb), _ctx);
- return std::move(ret);
- }
-
-private:
- ELFLinkingContext &_ctx;
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_READER_H
diff --git a/lib/ReaderWriter/ELF/ExecutableWriter.h b/lib/ReaderWriter/ELF/ExecutableWriter.h
deleted file mode 100644
index 9d9f4d9ce0a5..000000000000
--- a/lib/ReaderWriter/ELF/ExecutableWriter.h
+++ /dev/null
@@ -1,157 +0,0 @@
-//===- lib/ReaderWriter/ELF/ExecutableWriter.h ----------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
-#define LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
-
-#include "OutputELFWriter.h"
-
-namespace lld {
-namespace elf {
-using namespace llvm;
-using namespace llvm::object;
-
-//===----------------------------------------------------------------------===//
-// ExecutableWriter Class
-//===----------------------------------------------------------------------===//
-template<class ELFT>
-class ExecutableWriter : public OutputELFWriter<ELFT> {
-public:
- ExecutableWriter(ELFLinkingContext &ctx, TargetLayout<ELFT> &layout)
- : OutputELFWriter<ELFT>(ctx, layout) {}
-
-protected:
- void buildDynamicSymbolTable(const File &file) override;
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
- void finalizeDefaultAtomValues() override;
- void createDefaultSections() override;
-
- bool isNeededTagRequired(const SharedLibraryAtom *sla) const override {
- return this->_layout.isCopied(sla);
- }
-
- unique_bump_ptr<InterpSection<ELFT>> _interpSection;
-
-private:
- std::unique_ptr<RuntimeFile<ELFT>> createRuntimeFile();
-};
-
-//===----------------------------------------------------------------------===//
-// ExecutableWriter
-//===----------------------------------------------------------------------===//
-template<class ELFT>
-void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
- for (auto sec : this->_layout.sections())
- if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
- for (const auto &atom : section->atoms()) {
- const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom);
- if (!da)
- continue;
- if (da->dynamicExport() != DefinedAtom::dynamicExportAlways &&
- !this->_ctx.isDynamicallyExportedSymbol(da->name()) &&
- !(this->_ctx.shouldExportDynamic() &&
- da->scope() == Atom::Scope::scopeGlobal))
- continue;
- this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
- atom->_virtualAddr, atom);
- }
-
- // Put weak symbols in the dynamic symbol table.
- if (this->_ctx.isDynamic()) {
- for (const UndefinedAtom *a : file.undefined()) {
- if (this->_layout.isReferencedByDefinedAtom(a) &&
- a->canBeNull() != UndefinedAtom::canBeNullNever)
- this->_dynamicSymbolTable->addSymbol(a, ELF::SHN_UNDEF);
- }
- }
-
- OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
-}
-
-template<class ELFT>
-std::unique_ptr<RuntimeFile<ELFT>> ExecutableWriter<ELFT>::createRuntimeFile() {
- auto file = llvm::make_unique<RuntimeFile<ELFT>>(this->_ctx, "C runtime");
- file->addUndefinedAtom(this->_ctx.entrySymbolName());
- file->addAbsoluteAtom("__bss_start");
- file->addAbsoluteAtom("__bss_end");
- file->addAbsoluteAtom("_end");
- file->addAbsoluteAtom("end");
- file->addAbsoluteAtom("__preinit_array_start", true);
- file->addAbsoluteAtom("__preinit_array_end", true);
- file->addAbsoluteAtom("__init_array_start", true);
- file->addAbsoluteAtom("__init_array_end", true);
- if (this->_ctx.isRelaOutputFormat()) {
- file->addAbsoluteAtom("__rela_iplt_start");
- file->addAbsoluteAtom("__rela_iplt_end");
- } else {
- file->addAbsoluteAtom("__rel_iplt_start");
- file->addAbsoluteAtom("__rel_iplt_end");
- }
- file->addAbsoluteAtom("__fini_array_start", true);
- file->addAbsoluteAtom("__fini_array_end", true);
- return file;
-}
-
-/// \brief Hook in lld to add CRuntime file
-template <class ELFT>
-void ExecutableWriter<ELFT>::createImplicitFiles(
- std::vector<std::unique_ptr<File> > &result) {
- OutputELFWriter<ELFT>::createImplicitFiles(result);
- result.push_back(createRuntimeFile());
-}
-
-template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() {
- OutputELFWriter<ELFT>::createDefaultSections();
- if (this->_ctx.isDynamic()) {
- _interpSection.reset(new (this->_alloc) InterpSection<ELFT>(
- this->_ctx, ".interp", TargetLayout<ELFT>::ORDER_INTERP,
- this->_ctx.getInterpreter()));
- this->_layout.addSection(_interpSection.get());
- }
-}
-
-/// Finalize the value of all the absolute symbols that we
-/// created
-template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
- OutputELFWriter<ELFT>::finalizeDefaultAtomValues();
- AtomLayout *bssStartAtom = this->_layout.findAbsoluteAtom("__bss_start");
- AtomLayout *bssEndAtom = this->_layout.findAbsoluteAtom("__bss_end");
- AtomLayout *underScoreEndAtom = this->_layout.findAbsoluteAtom("_end");
- AtomLayout *endAtom = this->_layout.findAbsoluteAtom("end");
-
- assert((bssStartAtom || bssEndAtom || underScoreEndAtom || endAtom) &&
- "Unable to find the absolute atoms that have been added by lld");
-
- this->updateScopeAtomValues("preinit_array", ".preinit_array");
- this->updateScopeAtomValues("init_array", ".init_array");
- if (this->_ctx.isRelaOutputFormat())
- this->updateScopeAtomValues("rela_iplt", ".rela.plt");
- else
- this->updateScopeAtomValues("rel_iplt", ".rel.plt");
- this->updateScopeAtomValues("fini_array", ".fini_array");
-
- auto bssSection = this->_layout.findOutputSection(".bss");
-
- // If we don't find a bss section, then don't set these values
- if (bssSection) {
- bssStartAtom->_virtualAddr = bssSection->virtualAddr();
- bssEndAtom->_virtualAddr =
- bssSection->virtualAddr() + bssSection->memSize();
- underScoreEndAtom->_virtualAddr = bssEndAtom->_virtualAddr;
- endAtom->_virtualAddr = bssEndAtom->_virtualAddr;
- } else if (auto dataSection = this->_layout.findOutputSection(".data")) {
- underScoreEndAtom->_virtualAddr =
- dataSection->virtualAddr() + dataSection->memSize();
- endAtom->_virtualAddr = underScoreEndAtom->_virtualAddr;
- }
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
diff --git a/lib/ReaderWriter/ELF/FileCommon.cpp b/lib/ReaderWriter/ELF/FileCommon.cpp
deleted file mode 100644
index c23e3f6656cd..000000000000
--- a/lib/ReaderWriter/ELF/FileCommon.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-//===- lib/ReaderWriter/ELF/FileCommon.cpp --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ELFFile.h"
-#include "FileCommon.h"
-
-using namespace llvm::ELF;
-
-namespace lld {
-namespace elf {
-
-static const char *elf32_expected = "ELF32 expected, but got ELF64";
-static const char *elf64_expected = "ELF64 expected, but got ELF32";
-static const char *le_expected =
- "Little endian files are expected, but got a big endian file.";
-static const char *be_expected =
- "Big endian files are expected, but got a little endian file.";
-
-template <>
-std::error_code checkCompatibility<ELF32LE>(unsigned char size,
- unsigned char endian) {
- if (size == ELFCLASS64)
- return make_dynamic_error_code(elf32_expected);
- if (endian == ELFDATA2MSB)
- return make_dynamic_error_code(le_expected);
- return std::error_code();
-}
-
-template <>
-std::error_code checkCompatibility<ELF32BE>(unsigned char size,
- unsigned char endian) {
- if (size == ELFCLASS64)
- return make_dynamic_error_code(elf32_expected);
- if (endian == ELFDATA2LSB)
- return make_dynamic_error_code(be_expected);
- return std::error_code();
-}
-
-template <>
-std::error_code checkCompatibility<ELF64LE>(unsigned char size,
- unsigned char endian) {
- if (size == ELFCLASS32)
- return make_dynamic_error_code(elf64_expected);
- if (endian == ELFDATA2MSB)
- return make_dynamic_error_code(le_expected);
- return std::error_code();
-}
-
-template <>
-std::error_code checkCompatibility<ELF64BE>(unsigned char size,
- unsigned char endian) {
- if (size == ELFCLASS32)
- return make_dynamic_error_code(elf64_expected);
- if (endian == ELFDATA2LSB)
- return make_dynamic_error_code(be_expected);
- return std::error_code();
-}
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/FileCommon.h b/lib/ReaderWriter/ELF/FileCommon.h
deleted file mode 100644
index eaff12afe72f..000000000000
--- a/lib/ReaderWriter/ELF/FileCommon.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- lib/ReaderWriter/ELF/FileCommon.h ----------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_FILE_COMMON_H
-#define LLD_READER_WRITER_ELF_FILE_COMMON_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-std::error_code checkCompatibility(unsigned char size, unsigned char endian);
-
-template <typename ELFT>
-std::error_code isCompatible(MemoryBufferRef mb, ELFLinkingContext &ctx) {
- typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
-
- if (uintptr_t(mb.getBufferStart()) & 1)
- return make_dynamic_error_code("invalid alignment");
-
- auto *hdr = reinterpret_cast<const Elf_Ehdr *>(mb.getBuffer().data());
- if (hdr->e_machine != ctx.getMachineType())
- return make_dynamic_error_code("incompatible machine type");
-
- unsigned char size;
- unsigned char endian;
- std::tie(size, endian) = llvm::object::getElfArchType(mb.getBuffer());
- if (std::error_code ec = checkCompatibility<ELFT>(size, endian))
- return ec;
- return std::error_code();
-}
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/HeaderChunks.cpp b/lib/ReaderWriter/ELF/HeaderChunks.cpp
deleted file mode 100644
index 193937c18061..000000000000
--- a/lib/ReaderWriter/ELF/HeaderChunks.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-//===- lib/ReaderWriter/ELF/HeaderChunks.cpp --------------------*- C++ -*-===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "HeaderChunks.h"
-#include "TargetLayout.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT> void ELFHeader<ELFT>::finalize() {
- _eh.e_ident[llvm::ELF::EI_CLASS] =
- (ELFT::Is64Bits) ? llvm::ELF::ELFCLASS64 : llvm::ELF::ELFCLASS32;
- _eh.e_ident[llvm::ELF::EI_DATA] =
- (ELFT::TargetEndianness == llvm::support::little)
- ? llvm::ELF::ELFDATA2LSB
- : llvm::ELF::ELFDATA2MSB;
- _eh.e_type = this->_ctx.getOutputELFType();
- _eh.e_machine = this->_ctx.getOutputMachine();
-}
-
-template <class ELFT>
-ELFHeader<ELFT>::ELFHeader(const ELFLinkingContext &ctx)
- : Chunk<ELFT>("elfhdr", Chunk<ELFT>::Kind::ELFHeader, ctx) {
- this->_alignment = ELFT::Is64Bits ? 8 : 4;
- this->_fsize = sizeof(Elf_Ehdr);
- this->_msize = sizeof(Elf_Ehdr);
- memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
- e_ident(llvm::ELF::EI_MAG0, 0x7f);
- e_ident(llvm::ELF::EI_MAG1, 'E');
- e_ident(llvm::ELF::EI_MAG2, 'L');
- e_ident(llvm::ELF::EI_MAG3, 'F');
- e_ehsize(sizeof(Elf_Ehdr));
- e_flags(0);
-}
-
-template <class ELFT>
-void ELFHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *atomContent = chunkBuffer + this->fileOffset();
- memcpy(atomContent, &_eh, fileSize());
-}
-
-template <class ELFT>
-bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
- bool allocatedNew = false;
- ELFLinkingContext::OutputMagic outputMagic = this->_ctx.getOutputMagic();
- // For segments that are not a loadable segment, we
- // just pick the values directly from the segment as there
- // wouldnt be any slices within that
- if (segment->segmentType() != llvm::ELF::PT_LOAD) {
- Elf_Phdr *phdr = allocateProgramHeader(allocatedNew);
- phdr->p_type = segment->segmentType();
- phdr->p_offset = segment->fileOffset();
- phdr->p_vaddr = segment->virtualAddr();
- phdr->p_paddr = segment->virtualAddr();
- phdr->p_filesz = segment->fileSize();
- phdr->p_memsz = segment->memSize();
- phdr->p_flags = segment->flags();
- phdr->p_align = segment->alignment();
- this->_fsize = fileSize();
- this->_msize = this->_fsize;
- return allocatedNew;
- }
- // For all other segments, use the slice
- // to derive program headers
- for (auto slice : segment->slices()) {
- Elf_Phdr *phdr = allocateProgramHeader(allocatedNew);
- phdr->p_type = segment->segmentType();
- phdr->p_offset = slice->fileOffset();
- phdr->p_vaddr = slice->virtualAddr();
- phdr->p_paddr = slice->virtualAddr();
- phdr->p_filesz = slice->fileSize();
- phdr->p_memsz = slice->memSize();
- phdr->p_flags = segment->flags();
- phdr->p_align = slice->alignment();
- uint64_t segPageSize = segment->pageSize();
- uint64_t sliceAlign = slice->alignment();
- // Alignment of PT_LOAD segments are set to the page size, but if the
- // alignment of the slice is greater than the page size, set the alignment
- // of the segment appropriately.
- if (outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
- outputMagic != ELFLinkingContext::OutputMagic::OMAGIC) {
- phdr->p_align =
- (phdr->p_type == llvm::ELF::PT_LOAD)
- ? (segPageSize < sliceAlign) ? sliceAlign : segPageSize
- : sliceAlign;
- } else
- phdr->p_align = slice->alignment();
- }
- this->_fsize = fileSize();
- this->_msize = this->_fsize;
-
- return allocatedNew;
-}
-
-template <class ELFT>
-void ProgramHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- for (auto phi : _ph) {
- memcpy(dest, phi, sizeof(Elf_Phdr));
- dest += sizeof(Elf_Phdr);
- }
-}
-
-template <class ELFT>
-typename ProgramHeader<ELFT>::Elf_Phdr *
-ProgramHeader<ELFT>::allocateProgramHeader(bool &allocatedNew) {
- Elf_Phdr *phdr;
- if (_phi == _ph.end()) {
- phdr = new (_allocator) Elf_Phdr;
- _ph.push_back(phdr);
- _phi = _ph.end();
- allocatedNew = true;
- } else {
- phdr = (*_phi);
- ++_phi;
- }
- return phdr;
-}
-
-template <class ELFT>
-SectionHeader<ELFT>::SectionHeader(const ELFLinkingContext &ctx, int32_t order)
- : Chunk<ELFT>("shdr", Chunk<ELFT>::Kind::SectionHeader, ctx) {
- this->_fsize = 0;
- this->_alignment = 8;
- this->setOrder(order);
- // The first element in the list is always NULL
- auto *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
- ::memset(nullshdr, 0, sizeof(Elf_Shdr));
- _sectionInfo.push_back(nullshdr);
- this->_fsize += sizeof(Elf_Shdr);
-}
-
-template <class ELFT>
-void SectionHeader<ELFT>::appendSection(OutputSection<ELFT> *section) {
- auto *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
- shdr->sh_name = _stringSection->addString(section->name());
- shdr->sh_type = section->type();
- shdr->sh_flags = section->flags();
- shdr->sh_offset = section->fileOffset();
- shdr->sh_addr = section->virtualAddr();
- if (section->isLoadableSection())
- shdr->sh_size = section->memSize();
- else
- shdr->sh_size = section->fileSize();
- shdr->sh_link = section->link();
- shdr->sh_info = section->shinfo();
- shdr->sh_addralign = section->alignment();
- shdr->sh_entsize = section->entsize();
- _sectionInfo.push_back(shdr);
-}
-
-template <class ELFT>
-void SectionHeader<ELFT>::updateSection(Section<ELFT> *section) {
- Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
- shdr->sh_type = section->getType();
- shdr->sh_flags = section->getFlags();
- shdr->sh_offset = section->fileOffset();
- shdr->sh_addr = section->virtualAddr();
- shdr->sh_size = section->fileSize();
- shdr->sh_link = section->getLink();
- shdr->sh_info = section->getInfo();
- shdr->sh_addralign = section->alignment();
- shdr->sh_entsize = section->getEntSize();
-}
-
-template <class ELFT>
-void SectionHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- for (auto shi : _sectionInfo) {
- memcpy(dest, shi, sizeof(Elf_Shdr));
- dest += sizeof(Elf_Shdr);
- }
- _stringSection->write(writer, layout, buffer);
-}
-
-template class ELFHeader<ELF32LE>;
-template class ELFHeader<ELF32BE>;
-template class ELFHeader<ELF64LE>;
-template class ELFHeader<ELF64BE>;
-
-template class ProgramHeader<ELF32LE>;
-template class ProgramHeader<ELF32BE>;
-template class ProgramHeader<ELF64LE>;
-template class ProgramHeader<ELF64BE>;
-
-template class SectionHeader<ELF32LE>;
-template class SectionHeader<ELF32BE>;
-template class SectionHeader<ELF64LE>;
-template class SectionHeader<ELF64BE>;
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/HeaderChunks.h b/lib/ReaderWriter/ELF/HeaderChunks.h
deleted file mode 100644
index 51fbe38f1a00..000000000000
--- a/lib/ReaderWriter/ELF/HeaderChunks.h
+++ /dev/null
@@ -1,154 +0,0 @@
-//===- lib/ReaderWriter/ELF/HeaderChunks.h --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_HEADER_CHUNKS_H
-#define LLD_READER_WRITER_ELF_HEADER_CHUNKS_H
-
-#include "SegmentChunks.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-
-/// \brief An Header represents the Elf[32/64]_Ehdr structure at the
-/// start of an ELF executable file.
-namespace lld {
-namespace elf {
-
-template <class ELFT> class ELFHeader : public Chunk<ELFT> {
-public:
- typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
-
- ELFHeader(const ELFLinkingContext &);
-
- void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
- void e_type(uint16_t type) { _eh.e_type = type; }
- void e_machine(uint16_t machine) { _eh.e_machine = machine; }
- void e_version(uint32_t version) { _eh.e_version = version; }
- void e_entry(int64_t entry) { _eh.e_entry = entry; }
- void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
- void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
- void e_flags(uint32_t flags) { _eh.e_flags = flags; }
- void e_ehsize(uint16_t ehsize) { _eh.e_ehsize = ehsize; }
- void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
- void e_phnum(uint16_t phnum) { _eh.e_phnum = phnum; }
- void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
- void e_shnum(uint16_t shnum) { _eh.e_shnum = shnum; }
- void e_shstrndx(uint16_t shstrndx) { _eh.e_shstrndx = shstrndx; }
- uint64_t fileSize() const override { return sizeof(Elf_Ehdr); }
-
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::ELFHeader;
- }
-
- int getContentType() const override {
- return Chunk<ELFT>::ContentType::Header;
- }
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- void finalize() override;
-
-private:
- Elf_Ehdr _eh;
-};
-
-/// \brief An ProgramHeader represents the Elf[32/64]_Phdr structure at the
-/// start of an ELF executable file.
-template<class ELFT>
-class ProgramHeader : public Chunk<ELFT> {
-public:
- typedef llvm::object::Elf_Phdr_Impl<ELFT> Elf_Phdr;
- typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
- typedef typename std::reverse_iterator<PhIterT> ReversePhIterT;
-
- ProgramHeader(const ELFLinkingContext &ctx)
- : Chunk<ELFT>("elfphdr", Chunk<ELFT>::Kind::ProgramHeader, ctx) {
- this->_alignment = ELFT::Is64Bits ? 8 : 4;
- resetProgramHeaders();
- }
-
- bool addSegment(Segment<ELFT> *segment);
- void resetProgramHeaders() { _phi = _ph.begin(); }
- uint64_t fileSize() const override { return sizeof(Elf_Phdr) * _ph.size(); }
-
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::ProgramHeader;
- }
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- PhIterT begin() { return _ph.begin(); }
- PhIterT end() { return _ph.end(); }
- ReversePhIterT rbegin() { return _ph.rbegin(); }
- ReversePhIterT rend() { return _ph.rend(); }
-
- int64_t entsize() { return sizeof(Elf_Phdr); }
- int64_t numHeaders() { return _ph.size(); }
-
- int getContentType() const override {
- return Chunk<ELFT>::ContentType::Header;
- }
-
-private:
- Elf_Phdr *allocateProgramHeader(bool &allocatedNew);
-
- std::vector<Elf_Phdr *> _ph;
- PhIterT _phi;
- llvm::BumpPtrAllocator _allocator;
-};
-
-/// \brief An SectionHeader represents the Elf[32/64]_Shdr structure
-/// at the end of the file
-template<class ELFT>
-class SectionHeader : public Chunk<ELFT> {
-public:
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
-
- SectionHeader(const ELFLinkingContext &, int32_t order);
- void appendSection(OutputSection<ELFT> *section);
- void updateSection(Section<ELFT> *section);
-
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::SectionHeader;
- }
-
- void setStringSection(StringTable<ELFT> *s) {
- _stringSection = s;
- }
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- uint64_t fileSize() const override {
- return sizeof(Elf_Shdr) * _sectionInfo.size();
- }
-
- uint64_t entsize() { return sizeof(Elf_Shdr); }
-
- int getContentType() const override {
- return Chunk<ELFT>::ContentType::Header;
- }
-
- uint64_t numHeaders() { return _sectionInfo.size(); }
-
-private:
- StringTable<ELFT> *_stringSection;
- std::vector<Elf_Shdr *> _sectionInfo;
- llvm::BumpPtrAllocator _sectionAllocate;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt b/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt
deleted file mode 100644
index e5c5cb77f38c..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-add_lld_library(lldHexagonELFTarget
- HexagonLinkingContext.cpp
- HexagonRelocationHandler.cpp
- HexagonTargetHandler.cpp
- LINK_LIBS
- lldELF
- lldReaderWriter
- lldCore
- LLVMObject
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h b/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h
deleted file mode 100644
index 84415b273f44..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h ---------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef HEXAGON_DYNAMIC_LIBRARY_WRITER_H
-#define HEXAGON_DYNAMIC_LIBRARY_WRITER_H
-
-#include "DynamicLibraryWriter.h"
-#include "HexagonLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-class HexagonTargetLayout;
-
-class HexagonDynamicLibraryWriter : public DynamicLibraryWriter<ELF32LE> {
-public:
- HexagonDynamicLibraryWriter(HexagonLinkingContext &ctx,
- HexagonTargetLayout &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void finalizeDefaultAtomValues() override;
-
- std::error_code setELFHeader() override {
- DynamicLibraryWriter::setELFHeader();
- setHexagonELFHeader(*_elfHeader);
- return std::error_code();
- }
-
-private:
- HexagonLinkingContext &_ctx;
- HexagonTargetLayout &_targetLayout;
-};
-
-HexagonDynamicLibraryWriter::HexagonDynamicLibraryWriter(
- HexagonLinkingContext &ctx, HexagonTargetLayout &layout)
- : DynamicLibraryWriter(ctx, layout), _ctx(ctx), _targetLayout(layout) {}
-
-void HexagonDynamicLibraryWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter::createImplicitFiles(result);
- // Add the default atoms as defined for hexagon
- auto file =
- llvm::make_unique<RuntimeFile<ELF32LE>>(_ctx, "Hexagon runtime file");
- file->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
- file->addAbsoluteAtom("_DYNAMIC");
- result.push_back(std::move(file));
-}
-
-void HexagonDynamicLibraryWriter::finalizeDefaultAtomValues() {
- // Finalize the atom values that are part of the parent.
- DynamicLibraryWriter::finalizeDefaultAtomValues();
- if (_ctx.isDynamic())
- finalizeHexagonRuntimeAtomValues(_targetLayout);
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif // HEXAGON_DYNAMIC_LIBRARY_WRITER_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h b/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
deleted file mode 100644
index 3d0d38f387dd..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
+++ /dev/null
@@ -1,149 +0,0 @@
-//===- lib/ReaderWriter/ELF/HexagonELFFile.h ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H
-#define LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H
-
-#include "ELFReader.h"
-#include "HexagonLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-class HexagonELFFile;
-
-class HexagonELFDefinedAtom : public ELFDefinedAtom<ELF32LE> {
- typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELF32LE> Elf_Shdr;
-
-public:
- template <typename... T>
- HexagonELFDefinedAtom(T &&... args)
- : ELFDefinedAtom(std::forward<T>(args)...) {}
-
- DefinedAtom::ContentType contentType() const override {
- if (_contentType != DefinedAtom::typeUnknown)
- return _contentType;
- if (_section->sh_flags & llvm::ELF::SHF_HEX_GPREL) {
- if (_section->sh_type == llvm::ELF::SHT_NOBITS)
- return (_contentType = DefinedAtom::typeZeroFillFast);
- return (_contentType = DefinedAtom::typeDataFast);
- }
- return ELFDefinedAtom::contentType();
- }
-
- DefinedAtom::ContentPermissions permissions() const override {
- if (_section->sh_flags & llvm::ELF::SHF_HEX_GPREL)
- return DefinedAtom::permRW_;
- return ELFDefinedAtom::permissions();
- }
-};
-
-class HexagonELFCommonAtom : public ELFCommonAtom<ELF32LE> {
- typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELF32LE> Elf_Shdr;
-
-public:
- HexagonELFCommonAtom(const ELFFile<ELF32LE> &file, StringRef symbolName,
- const Elf_Sym *symbol)
- : ELFCommonAtom(file, symbolName, symbol) {}
-
- virtual bool isSmallCommonSymbol() const {
- switch (_symbol->st_shndx) {
- // Common symbols
- case llvm::ELF::SHN_HEXAGON_SCOMMON:
- case llvm::ELF::SHN_HEXAGON_SCOMMON_1:
- case llvm::ELF::SHN_HEXAGON_SCOMMON_2:
- case llvm::ELF::SHN_HEXAGON_SCOMMON_4:
- case llvm::ELF::SHN_HEXAGON_SCOMMON_8:
- return true;
- default:
- break;
- }
- return false;
- }
-
- uint64_t size() const override {
- if (isSmallCommonSymbol())
- return _symbol->st_size;
- return ELFCommonAtom::size();
- }
-
- DefinedAtom::Merge merge() const override {
- if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
- return DefinedAtom::mergeAsWeak;
- if (isSmallCommonSymbol())
- return DefinedAtom::mergeAsTentative;
- return ELFCommonAtom::merge();
- }
-
- DefinedAtom::ContentType contentType() const override {
- if (isSmallCommonSymbol())
- return DefinedAtom::typeZeroFillFast;
- return ELFCommonAtom::contentType();
- }
-
- DefinedAtom::Alignment alignment() const override {
- if (isSmallCommonSymbol())
- return DefinedAtom::Alignment(_symbol->st_value);
- return 1;
- }
-
- DefinedAtom::ContentPermissions permissions() const override {
- if (isSmallCommonSymbol())
- return DefinedAtom::permRW_;
- return ELFCommonAtom::permissions();
- }
-};
-
-class HexagonELFFile : public ELFFile<ELF32LE> {
- typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELF32LE> Elf_Shdr;
-
-public:
- HexagonELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
- : ELFFile(std::move(mb), ctx) {}
-
- bool isCommonSymbol(const Elf_Sym *symbol) const override {
- switch (symbol->st_shndx) {
- // Common symbols
- case llvm::ELF::SHN_HEXAGON_SCOMMON:
- case llvm::ELF::SHN_HEXAGON_SCOMMON_1:
- case llvm::ELF::SHN_HEXAGON_SCOMMON_2:
- case llvm::ELF::SHN_HEXAGON_SCOMMON_4:
- case llvm::ELF::SHN_HEXAGON_SCOMMON_8:
- return true;
- default:
- break;
- }
- return ELFFile::isCommonSymbol(symbol);
- }
-
- /// Process the Defined symbol and create an atom for it.
- ELFDefinedAtom<ELF32LE> *createDefinedAtom(
- StringRef symName, StringRef sectionName, const Elf_Sym *sym,
- const Elf_Shdr *sectionHdr, ArrayRef<uint8_t> contentData,
- unsigned int referenceStart, unsigned int referenceEnd,
- std::vector<ELFReference<ELF32LE> *> &referenceList) override {
- return new (_readerStorage) HexagonELFDefinedAtom(
- *this, symName, sectionName, sym, sectionHdr, contentData,
- referenceStart, referenceEnd, referenceList);
- }
-
- /// Process the Common symbol and create an atom for it.
- ELFCommonAtom<ELF32LE> *createCommonAtom(StringRef symName,
- const Elf_Sym *sym) override {
- return new (_readerStorage) HexagonELFCommonAtom(*this, symName, sym);
- }
-};
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h b/lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h
deleted file mode 100644
index 6af43d88afbb..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h
+++ /dev/null
@@ -1,638 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h -------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-
-namespace lld {
-namespace elf {
-
-/// \brief Applying fixup on Hexagon requires the relocator to fetch the fixup
-/// mask from the instruction. To fetch the fixup encoding, the linker uses a
-/// static array that contains the instruction mask, the compare mask and the
-/// relocation mask.
-typedef struct {
- uint32_t insnMask; // Instruction mask.
- uint32_t insnCmpMask; // Compare mask.
- uint32_t insnBitMask; // Relocation mask.
- bool isDuplex; // Indicates if the instruction is a duplex instruction.
-} Instruction;
-
-Instruction insn_encodings[] = {
- // InsnMask CompareMask BitMask IsDuplexInstruction
- { 0xffe00004, 0x40000000, 0x20f8, 0x0 },
- { 0xffe03080, 0x9ca03080, 0xf60, 0x0 },
- { 0xf9e00000, 0x48c00000, 0x61f20ff, 0x0 },
- { 0xf7c02300, 0x13802100, 0x3000fe, 0x0 },
- { 0xffe00000, 0x60c00000, 0x1f18, 0x0 },
- { 0xffe00000, 0x69c00000, 0x1f18, 0x0 },
- { 0xffe02000, 0x43000000, 0x7e0, 0x0 },
- { 0xff602060, 0x3e000060, 0x1f80, 0x0 },
- { 0xffe03000, 0x9ae01000, 0xf60, 0x0 },
- { 0xf9e00000, 0x91600000, 0x6003fe0, 0x0 },
- { 0xffe02084, 0xaf000084, 0x30078, 0x0 },
- { 0xff602060, 0x3e000020, 0x1f80, 0x0 },
- { 0xff602060, 0x3e200040, 0x1f80, 0x0 },
- { 0xf7c02000, 0x10c02000, 0x3000fe, 0x0 },
- { 0xffe00000, 0x60200000, 0x1f18, 0x0 },
- { 0xffe00000, 0x69200000, 0x1f18, 0x0 },
- { 0xffe038c0, 0xada00880, 0x3f, 0x0 },
- { 0xff602000, 0x73002000, 0x1fe0, 0x0 },
- { 0xf7c02000, 0x26c02000, 0x3000fe, 0x0 },
- { 0xffe03880, 0x9f403880, 0x1f0100, 0x0 },
- { 0xf9e00000, 0x48400000, 0x61f20ff, 0x0 },
- { 0xffe02000, 0x41600000, 0x7e0, 0x0 },
- { 0xffe02084, 0xaf000080, 0x30078, 0x0 },
- { 0xf7c02300, 0x13800100, 0x3000fe, 0x0 },
- { 0xffe01804, 0x46a00000, 0x20f8, 0x0 },
- { 0xffe00004, 0x42400000, 0x20f8, 0x0 },
- { 0xf7c02000, 0x22400000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x12402000, 0x3000fe, 0x0 },
- { 0xfc003d18, 0x28003c18, 0x3f00000, 0x1 },
- { 0xffe00000, 0x39000000, 0x201f, 0x0 },
- { 0xff601018, 0xdd400008, 0xfe0, 0x0 },
- { 0xffc0001c, 0x75400000, 0x203fe0, 0x0 },
- { 0xfc003fc7, 0x48003f47, 0x3f00000, 0x1 },
- { 0xffe03080, 0x9ca03000, 0xf60, 0x0 },
- { 0xf9e00000, 0x90800000, 0x6003fe0, 0x0 },
- { 0xf8003fc7, 0x40003fc4, 0x7f00000, 0x1 },
- { 0xfc003e00, 0x68003c00, 0x3f00000, 0x1 },
- { 0xf8003fc7, 0x40003fc5, 0x7f00000, 0x1 },
- { 0xf9e00000, 0x91800000, 0x6003fe0, 0x0 },
- { 0xff602060, 0x3e400060, 0x1f80, 0x0 },
- { 0xff602060, 0x3e000000, 0x1f80, 0x0 },
- { 0xf8003d18, 0x20003c18, 0x7f00000, 0x1 },
- { 0xf8003f00, 0x20003800, 0x7f00000, 0x1 },
- { 0xf8003d18, 0x20003c10, 0x7f00000, 0x1 },
- { 0xff602000, 0x73602000, 0x1fe0, 0x0 },
- { 0xffe03880, 0x9f002080, 0x1f0100, 0x0 },
- { 0xffe02000, 0x47000000, 0x7e0, 0x0 },
- { 0xf9e00000, 0x91400000, 0x6003fe0, 0x0 },
- { 0xffe02080, 0xabc00080, 0x3f, 0x0 },
- { 0xf7c02000, 0x20802000, 0x3000fe, 0x0 },
- { 0xf8003fc7, 0x40003f44, 0x7f00000, 0x1 },
- { 0xffe03884, 0xafa03084, 0x30078, 0x0 },
- { 0xffe03000, 0x9b001000, 0xf60, 0x0 },
- { 0xffe01804, 0x42a00800, 0x20f8, 0x0 },
- { 0xfc003f00, 0x28003100, 0x3f00000, 0x1 },
- { 0xffe02080, 0xab800080, 0x3f, 0x0 },
- { 0xf7c02000, 0x24c00000, 0x3000fe, 0x0 },
- { 0xffe00000, 0x39a00000, 0x201f, 0x0 },
- { 0xf7c02300, 0x13802300, 0x3000fe, 0x0 },
- { 0xffe01804, 0x46a00800, 0x20f8, 0x0 },
- { 0xffe020c0, 0xad602080, 0x3f, 0x0 },
- { 0xfc003f00, 0x28003500, 0x3f00000, 0x1 },
- { 0xfc003f00, 0x28003400, 0x3f00000, 0x1 },
- { 0xffe020c0, 0xad6000c0, 0x3f, 0x0 },
- { 0xffe00000, 0x60000000, 0x1f18, 0x0 },
- { 0xf8003000, 0x40000000, 0x7f00000, 0x1 },
- { 0xffe00000, 0x69000000, 0x1f18, 0x0 },
- { 0xffe03080, 0x9c601080, 0xf60, 0x0 },
- { 0xffe03080, 0x9ce01000, 0xf60, 0x0 },
- { 0xffe03080, 0x9c601000, 0xf60, 0x0 },
- { 0xf7c02000, 0x13402000, 0x3000fe, 0x0 },
- { 0xffe03080, 0x9c603000, 0xf60, 0x0 },
- { 0xf7c02000, 0x21c00000, 0x3000fe, 0x0 },
- { 0xfc003000, 0x68000000, 0x3f00000, 0x1 },
- { 0xf8003800, 0x60002000, 0x7f00000, 0x1 },
- { 0xffe02084, 0xaf802084, 0x30078, 0x0 },
- { 0xfc003000, 0x48000000, 0x3f00000, 0x1 },
- { 0xf7c02300, 0x11c02100, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x12800000, 0x3000fe, 0x0 },
- { 0xfc003e70, 0x28003a40, 0x3f00000, 0x1 },
- { 0xfc003f00, 0x28003300, 0x3f00000, 0x1 },
- { 0xff800000, 0xe0000000, 0x1fe0, 0x0 },
- { 0xff602060, 0x3f400000, 0x1f80, 0x0 },
- { 0xffe00004, 0x42000000, 0x20f8, 0x0 },
- { 0xf8003f00, 0x60003300, 0x7f00000, 0x1 },
- { 0xffe01804, 0x42a00000, 0x20f8, 0x0 },
- { 0xf7c02000, 0x12c00000, 0x3000fe, 0x0 },
- { 0xf0000000, 0x0, 0xfff3fff, 0x0 },
- { 0xff000016, 0xde000016, 0xe020e8, 0x0 },
- { 0xffe03000, 0x9b201000, 0xf60, 0x0 },
- { 0xffe03880, 0xaba00880, 0x3f, 0x0 },
- { 0xf8003e00, 0x40003c00, 0x7f00000, 0x1 },
- { 0xff602060, 0x3f200040, 0x1f80, 0x0 },
- { 0xffe03880, 0x9f203880, 0x1f0100, 0x0 },
- { 0xf7c02000, 0x20c00000, 0x3000fe, 0x0 },
- { 0xf9e01800, 0x48a00800, 0x61f20ff, 0x0 },
- { 0xf9e00000, 0x90a00000, 0x6003fe0, 0x0 },
- { 0xff802000, 0x74802000, 0x1fe0, 0x0 },
- { 0xffe03000, 0x9a401000, 0xf60, 0x0 },
- { 0xf7c02000, 0x10002000, 0x3000fe, 0x0 },
- { 0xf7c03000, 0x14803000, 0x3000fe, 0x0 },
- { 0xffe020c0, 0xad0020c0, 0x3f, 0x0 },
- { 0xffe0001c, 0x75800000, 0x3fe0, 0x0 },
- { 0xf9e01800, 0x48a01000, 0x61f20ff, 0x0 },
- { 0xffe03080, 0x9dc03000, 0xf60, 0x0 },
- { 0xffe03080, 0x9dc03080, 0xf60, 0x0 },
- { 0xffe03080, 0x9dc01000, 0xf60, 0x0 },
- { 0xffe03080, 0x9dc01080, 0xf60, 0x0 },
- { 0xffe03080, 0x9d601000, 0xf60, 0x0 },
- { 0xffe03080, 0x9d601080, 0xf60, 0x0 },
- { 0xffe03080, 0x9d603000, 0xf60, 0x0 },
- { 0xffe03080, 0x9d603080, 0xf60, 0x0 },
- { 0xfc003e00, 0x48003c00, 0x3f00000, 0x1 },
- { 0xffe02084, 0xaf402084, 0x30078, 0x0 },
- { 0xffe00004, 0x46600000, 0x20f8, 0x0 },
- { 0xffe03880, 0x9f203080, 0x1f0100, 0x0 },
- { 0xf8003f00, 0x20003100, 0x7f00000, 0x1 },
- { 0xf7c02000, 0x11402000, 0x3000fe, 0x0 },
- { 0xf8003d08, 0x20003d00, 0x7f00000, 0x1 },
- { 0xffe03080, 0x9ca01080, 0xf60, 0x0 },
- { 0xffe03080, 0x9ca01000, 0xf60, 0x0 },
- { 0xffe00000, 0x38a00000, 0x201f, 0x0 },
- { 0xf7c02300, 0x11800000, 0x3000fe, 0x0 },
- { 0xf7c02300, 0x13c02300, 0x3000fe, 0x0 },
- { 0xffe03080, 0x9ce03000, 0xf60, 0x0 },
- { 0xf9e00000, 0x90e00000, 0x6003fe0, 0x0 },
- { 0xffe02084, 0xaf400080, 0x30078, 0x0 },
- { 0xffe03080, 0x9ce03080, 0xf60, 0x0 },
- { 0xff000000, 0x78000000, 0xdf3fe0, 0x0 },
- { 0xffe03080, 0x9ce01080, 0xf60, 0x0 },
- { 0xffe03880, 0xaba01080, 0x3f, 0x0 },
- { 0xffe020c0, 0xad002080, 0x3f, 0x0 },
- { 0xffe020c0, 0xad0000c0, 0x3f, 0x0 },
- { 0xffe020c0, 0xad000080, 0x3f, 0x0 },
- { 0xf7c02000, 0x25000000, 0x3000fe, 0x0 },
- { 0xff602060, 0x3f200020, 0x1f80, 0x0 },
- { 0xffe02084, 0xafc00084, 0x30078, 0x0 },
- { 0xf7c02000, 0x24400000, 0x3000fe, 0x0 },
- { 0xfc003000, 0x48001000, 0x3f00000, 0x1 },
- { 0xf9e01800, 0xa1a01000, 0x60020ff, 0x0 },
- { 0xff602060, 0x3f000040, 0x1f80, 0x0 },
- { 0xffe02084, 0xaf602084, 0x30078, 0x0 },
- { 0xf8003f00, 0x20003400, 0x7f00000, 0x1 },
- { 0xffe02084, 0xaf400084, 0x30078, 0x0 },
- { 0xffe01804, 0x44a01000, 0x20f8, 0x0 },
- { 0xff602060, 0x3e200000, 0x1f80, 0x0 },
- { 0xf8003e70, 0x20003a70, 0x7f00000, 0x1 },
- { 0xf8003f00, 0x40003e00, 0x7f00000, 0x1 },
- { 0xf8003f00, 0x20003300, 0x7f00000, 0x1 },
- { 0xf7c02300, 0x13800300, 0x3000fe, 0x0 },
- { 0xffe038c0, 0xada00080, 0x3f, 0x0 },
- { 0xf9e00000, 0x49400000, 0x61f3fe0, 0x0 },
- { 0xf8003800, 0x40002800, 0x7f00000, 0x1 },
- { 0xffe038c0, 0xada020c0, 0x3f, 0x0 },
- { 0xffe03884, 0xafa00880, 0x30078, 0x0 },
- { 0xf9e00000, 0x49000000, 0x61f3fe0, 0x0 },
- { 0xff800000, 0xd7000000, 0x6020e0, 0x0 },
- { 0xffc00000, 0xda000000, 0x203fe0, 0x0 },
- { 0xf7c02000, 0x12802000, 0x3000fe, 0x0 },
- { 0xf9e00000, 0x49600000, 0x61f3fe0, 0x0 },
- { 0xffe02000, 0x47400000, 0x7e0, 0x0 },
- { 0xf9e00000, 0x49c00000, 0x61f3fe0, 0x0 },
- { 0xffe03000, 0x9bc01000, 0xf60, 0x0 },
- { 0xf7c02300, 0x13c00100, 0x3000fe, 0x0 },
- { 0xffe03880, 0x9f002880, 0x1f0100, 0x0 },
- { 0xffe03000, 0x9b601000, 0xf60, 0x0 },
- { 0xffe01804, 0x40a00800, 0x20f8, 0x0 },
- { 0xffe00004, 0x42800000, 0x20f8, 0x0 },
- { 0xf7c03000, 0x14800000, 0x3000fe, 0x0 },
- { 0xfc003000, 0x68001000, 0x3f00000, 0x1 },
- { 0xfc003fc7, 0x48003f44, 0x3f00000, 0x1 },
- { 0xfc003fc7, 0x48003f45, 0x3f00000, 0x1 },
- { 0xf7c02000, 0x10800000, 0x3000fe, 0x0 },
- { 0xf8003e70, 0x20003a50, 0x7f00000, 0x1 },
- { 0xf7c02000, 0x21002000, 0x3000fe, 0x0 },
- { 0xf8003fc4, 0x40003fc0, 0x7f00000, 0x1 },
- { 0xf9e00000, 0x48000000, 0x61f20ff, 0x0 },
- { 0xffc0001c, 0x75000010, 0x203fe0, 0x0 },
- { 0xf8003f00, 0x20003800, 0x7f00000, 0x1 },
- { 0xf9e00000, 0xa1800000, 0x60020ff, 0x0 },
- { 0xffc01000, 0x61c00000, 0x202ffe, 0x0 },
- { 0xffe02084, 0xaf402080, 0x30078, 0x0 },
- { 0xffe03880, 0x9f602880, 0x1f0100, 0x0 },
- { 0xfc003f00, 0x68003000, 0x3f00000, 0x1 },
- { 0xfc003f00, 0x68003100, 0x3f00000, 0x1 },
- { 0xff602060, 0x3f200000, 0x1f80, 0x0 },
- { 0xffe03000, 0x9a801000, 0xf60, 0x0 },
- { 0xf7c02000, 0x24802000, 0x3000fe, 0x0 },
- { 0xffe00004, 0x42c00000, 0x20f8, 0x0 },
- { 0xf7c02300, 0x11802000, 0x3000fe, 0x0 },
- { 0xffc01000, 0x61401000, 0x202ffe, 0x0 },
- { 0xffe02000, 0x43c00000, 0x7e0, 0x0 },
- { 0xf7c02000, 0x11400000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x21800000, 0x3000fe, 0x0 },
- { 0xfc003c00, 0x28002c00, 0x3f00000, 0x1 },
- { 0xfc003f00, 0x28003200, 0x3f00000, 0x1 },
- { 0xffe03080, 0x9c803080, 0xf60, 0x0 },
- { 0xf7c03000, 0x14c03000, 0x3000fe, 0x0 },
- { 0xff800000, 0xdb800000, 0x6020e0, 0x0 },
- { 0xf7c02000, 0x22402000, 0x3000fe, 0x0 },
- { 0xffe00004, 0x46800000, 0x20f8, 0x0 },
- { 0xffe00000, 0x69a00000, 0x1f18, 0x0 },
- { 0xfc003e00, 0x68002a00, 0x3f00000, 0x1 },
- { 0xffe00000, 0x60a00000, 0x1f18, 0x0 },
- { 0xf7c02000, 0x25400000, 0x3000fe, 0x0 },
- { 0xfc003e70, 0x28003a70, 0x3f00000, 0x1 },
- { 0xffe03080, 0x9c803000, 0xf60, 0x0 },
- { 0xffc01000, 0x61400000, 0x202ffe, 0x0 },
- { 0xffe01804, 0x42a01000, 0x20f8, 0x0 },
- { 0xffc0001c, 0x75000000, 0x203fe0, 0x0 },
- { 0xffe02084, 0xafc02080, 0x30078, 0x0 },
- { 0xffe03884, 0xafa00884, 0x30078, 0x0 },
- { 0xffe03884, 0xafa02080, 0x30078, 0x0 },
- { 0xffe00000, 0x38c00000, 0x201f, 0x0 },
- { 0xffc01000, 0x61001000, 0x202ffe, 0x0 },
- { 0xf9e00000, 0x48800000, 0x61f20ff, 0x0 },
- { 0xf8003800, 0x40003000, 0x7f00000, 0x1 },
- { 0xf7c03000, 0x15403000, 0x3000fe, 0x0 },
- { 0xf7c03000, 0x15400000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x21000000, 0x3000fe, 0x0 },
- { 0xffe00004, 0x40c00000, 0x20f8, 0x0 },
- { 0xffe01804, 0x46a01000, 0x20f8, 0x0 },
- { 0xf8003d08, 0x20003d08, 0x7f00000, 0x1 },
- { 0xffe038c0, 0xada02080, 0x3f, 0x0 },
- { 0xffe03080, 0x9c203000, 0xf60, 0x0 },
- { 0xfc003800, 0x68002000, 0x3f00000, 0x1 },
- { 0xf9e00000, 0x90600000, 0x6003fe0, 0x0 },
- { 0xf7c03000, 0x14000000, 0x3000fe, 0x0 },
- { 0xf8003e70, 0x20003a40, 0x7f00000, 0x1 },
- { 0xff201800, 0x5c000800, 0xdf20fe, 0x0 },
- { 0xffe02000, 0x41800000, 0x7e0, 0x0 },
- { 0xff800000, 0xdb000000, 0x6020e0, 0x0 },
- { 0xfc003f00, 0x48003e00, 0x3f00000, 0x1 },
- { 0xf7c03000, 0x14002000, 0x3000fe, 0x0 },
- { 0xf7c02300, 0x11800100, 0x3000fe, 0x0 },
- { 0xfc003e00, 0x68002800, 0x3f00000, 0x1 },
- { 0xffe00004, 0x44c00000, 0x20f8, 0x0 },
- { 0xffe03880, 0x9f003880, 0x1f0100, 0x0 },
- { 0xff602000, 0x73402000, 0x1fe0, 0x0 },
- { 0xffe00000, 0x38200000, 0x201f, 0x0 },
- { 0xf7c02000, 0x24800000, 0x3000fe, 0x0 },
- { 0xf7c03000, 0x15001000, 0x3000fe, 0x0 },
- { 0xff800000, 0x7c800000, 0x1f2000, 0x0 },
- { 0xf8003fc7, 0x40003fc6, 0x7f00000, 0x1 },
- { 0xf7c02000, 0x12000000, 0x3000fe, 0x0 },
- { 0xff602000, 0x73202000, 0x1fe0, 0x0 },
- { 0xf7c02300, 0x13c00000, 0x3000fe, 0x0 },
- { 0xff602060, 0x3f400040, 0x1f80, 0x0 },
- { 0xf7c02000, 0x24002000, 0x3000fe, 0x0 },
- { 0xffe02084, 0xaf800080, 0x30078, 0x0 },
- { 0xffe00000, 0x38800000, 0x201f, 0x0 },
- { 0xfc003f00, 0x28003800, 0x3f00000, 0x1 },
- { 0xffe03080, 0x9c801080, 0xf60, 0x0 },
- { 0xffe020c0, 0xad4000c0, 0x3f, 0x0 },
- { 0xffe00000, 0x39400000, 0x201f, 0x0 },
- { 0xf7c02300, 0x13c02100, 0x3000fe, 0x0 },
- { 0xffe020c0, 0xad400080, 0x3f, 0x0 },
- { 0xffe03880, 0x9f603880, 0x1f0100, 0x0 },
- { 0xff000016, 0xde000002, 0xe020e8, 0x0 },
- { 0xfc003d08, 0x28003d00, 0x3f00000, 0x1 },
- { 0xfc003f00, 0x28003000, 0x3f00000, 0x1 },
- { 0xffe03080, 0x9c401000, 0xf60, 0x0 },
- { 0xf7c02000, 0x21402000, 0x3000fe, 0x0 },
- { 0xff201800, 0x5c200800, 0xdf20fe, 0x0 },
- { 0xffe01804, 0x40a01000, 0x20f8, 0x0 },
- { 0xfc003f00, 0x68003300, 0x3f00000, 0x1 },
- { 0xfc003f00, 0x68003200, 0x3f00000, 0x1 },
- { 0xf7c03000, 0x15401000, 0x3000fe, 0x0 },
- { 0xffe01804, 0x44a00800, 0x20f8, 0x0 },
- { 0xf7c02000, 0x26000000, 0x3000fe, 0x0 },
- { 0xffc00000, 0xda400000, 0x203fe0, 0x0 },
- { 0xffe00004, 0x40600000, 0x20f8, 0x0 },
- { 0xffe02080, 0xab600080, 0x3f, 0x0 },
- { 0xf8003f00, 0x20003600, 0x7f00000, 0x1 },
- { 0xf7c02300, 0x11c00300, 0x3000fe, 0x0 },
- { 0xf8003f00, 0x20003700, 0x7f00000, 0x1 },
- { 0xf7c02000, 0x25c00000, 0x3000fe, 0x0 },
- { 0xf7c02300, 0x11800300, 0x3000fe, 0x0 },
- { 0xffe03880, 0x9f802880, 0x1f0100, 0x0 },
- { 0xfc003800, 0x48003000, 0x3f00000, 0x1 },
- { 0xf8003c00, 0x20002c00, 0x7f00000, 0x1 },
- { 0xf7c02000, 0x10400000, 0x3000fe, 0x0 },
- { 0xff602060, 0x3f400060, 0x1f80, 0x0 },
- { 0xffe03080, 0x9c801000, 0xf60, 0x0 },
- { 0xff602060, 0x3e400040, 0x1f80, 0x0 },
- { 0xf7c03000, 0x14402000, 0x3000fe, 0x0 },
- { 0xffe0001c, 0x75800010, 0x3fe0, 0x0 },
- { 0xff000016, 0xde000014, 0xe020e8, 0x0 },
- { 0xf7c02300, 0x11c02000, 0x3000fe, 0x0 },
- { 0xff600018, 0xdd200008, 0x1fe0, 0x0 },
- { 0xff602060, 0x3e200060, 0x1f80, 0x0 },
- { 0xff000016, 0xde000006, 0xe020e8, 0x0 },
- { 0xffe00004, 0x44600000, 0x20f8, 0x0 },
- { 0xf8003e00, 0x60002800, 0x7f00000, 0x1 },
- { 0xfe600000, 0x3c000000, 0x207f, 0x0 },
- { 0xffe03884, 0xafa02884, 0x30078, 0x0 },
- { 0xf7c02300, 0x11802300, 0x3000fe, 0x0 },
- { 0xffe00000, 0x38000000, 0x201f, 0x0 },
- { 0xff200800, 0x5c000000, 0xdf20fe, 0x0 },
- { 0xf7c02000, 0x13400000, 0x3000fe, 0x0 },
- { 0xff200800, 0x5c200000, 0xdf20fe, 0x0 },
- { 0xffe02000, 0x41000000, 0x7e0, 0x0 },
- { 0xffe03880, 0x9fc02880, 0x1f0100, 0x0 },
- { 0xffe00004, 0x46000000, 0x20f8, 0x0 },
- { 0xff602060, 0x3f000020, 0x1f80, 0x0 },
- { 0xfc003d08, 0x28003d08, 0x3f00000, 0x1 },
- { 0xff602060, 0x3f200060, 0x1f80, 0x0 },
- { 0xffe038c0, 0xada028c0, 0x3f, 0x0 },
- { 0xffe038c0, 0xada008c0, 0x3f, 0x0 },
- { 0xf8003f00, 0x20003500, 0x7f00000, 0x1 },
- { 0xfc003fc4, 0x48003f40, 0x3f00000, 0x1 },
- { 0xf9e01800, 0x48a00000, 0x61f20ff, 0x0 },
- { 0xf7c03000, 0x14802000, 0x3000fe, 0x0 },
- { 0xfc003f00, 0x28003900, 0x3f00000, 0x1 },
- { 0xf8003fc7, 0x40003fc7, 0x7f00000, 0x1 },
- { 0xffe02000, 0x45400000, 0x7e0, 0x0 },
- { 0xffe038c0, 0xada02880, 0x3f, 0x0 },
- { 0xffe02084, 0xaf002080, 0x30078, 0x0 },
- { 0xffe03880, 0x9f803880, 0x1f0100, 0x0 },
- { 0xf7c03000, 0x15000000, 0x3000fe, 0x0 },
- { 0xfc003f00, 0x28003700, 0x3f00000, 0x1 },
- { 0xfc003f00, 0x28003600, 0x3f00000, 0x1 },
- { 0xffe02000, 0x47200000, 0x7e0, 0x0 },
- { 0xffe03880, 0xaba00080, 0x3f, 0x0 },
- { 0xffe02084, 0xafc00080, 0x30078, 0x0 },
- { 0xff802000, 0x73800000, 0x1fe0, 0x0 },
- { 0xffe03880, 0x9f202880, 0x1f0100, 0x0 },
- { 0xf8003d18, 0x20003c00, 0x7f00000, 0x1 },
- { 0xf9e00000, 0xa1600000, 0x60020ff, 0x0 },
- { 0xffe00004, 0x44800000, 0x20f8, 0x0 },
- { 0xf7c02000, 0x21802000, 0x3000fe, 0x0 },
- { 0xff000000, 0xd8000000, 0x6020e0, 0x0 },
- { 0xf9e00000, 0xa1000000, 0x60020ff, 0x0 },
- { 0xffe03884, 0xafa00084, 0x30078, 0x0 },
- { 0xff201800, 0x5c201800, 0xdf20fe, 0x0 },
- { 0xff000016, 0xde000010, 0xe020e8, 0x0 },
- { 0xffe03880, 0x9f603080, 0x1f0100, 0x0 },
- { 0xffe02000, 0x41c00000, 0x7e0, 0x0 },
- { 0xf7c02000, 0x20402000, 0x3000fe, 0x0 },
- { 0xff800000, 0xe1000000, 0x1fe0, 0x0 },
- { 0xf9e00000, 0xa1400000, 0x60020ff, 0x0 },
- { 0xf7c03000, 0x14c00000, 0x3000fe, 0x0 },
- { 0xf8003fc7, 0x40003f47, 0x7f00000, 0x1 },
- { 0xffe00004, 0x40800000, 0x20f8, 0x0 },
- { 0xff800000, 0xe1800000, 0x1fe0, 0x0 },
- { 0xf7c02300, 0x11802100, 0x3000fe, 0x0 },
- { 0xf9e00000, 0x49800000, 0x61f3fe0, 0x0 },
- { 0xf7c02000, 0x26400000, 0x3000fe, 0x0 },
- { 0xf8003c00, 0x20002800, 0x7f00000, 0x1 },
- { 0xff902000, 0x7e002000, 0xf1fe0, 0x0 },
- { 0xff902000, 0x7e802000, 0xf1fe0, 0x0 },
- { 0xf9e00000, 0x91c00000, 0x6003fe0, 0x0 },
- { 0xffe03884, 0xafa02880, 0x30078, 0x0 },
- { 0xf7c02000, 0x22000000, 0x3000fe, 0x0 },
- { 0xffe03080, 0x9d203000, 0xf60, 0x0 },
- { 0xf7c02000, 0x26002000, 0x3000fe, 0x0 },
- { 0xff800000, 0xe2000000, 0x1fe0, 0x0 },
- { 0xf7c02000, 0x26c00000, 0x3000fe, 0x0 },
- { 0xff602060, 0x3e400000, 0x1f80, 0x0 },
- { 0xffe00000, 0x38400000, 0x201f, 0x0 },
- { 0xfc003800, 0x48002000, 0x3f00000, 0x1 },
- { 0xff000016, 0xde000000, 0xe020e8, 0x0 },
- { 0xf8003f00, 0x20003000, 0x7f00000, 0x1 },
- { 0xf8003e70, 0x20003a60, 0x7f00000, 0x1 },
- { 0xff902000, 0x7e800000, 0xf1fe0, 0x0 },
- { 0xffe020c0, 0xad6020c0, 0x3f, 0x0 },
- { 0xf7c02300, 0x13802000, 0x3000fe, 0x0 },
- { 0xffe020c0, 0xad600080, 0x3f, 0x0 },
- { 0xff902000, 0x7e000000, 0xf1fe0, 0x0 },
- { 0xf7000000, 0x17000000, 0x3000fe, 0x0 },
- { 0xf7000000, 0x16000000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x25002000, 0x3000fe, 0x0 },
- { 0xfc003fc7, 0x48003fc7, 0x3f00000, 0x1 },
- { 0xffc01000, 0x61801000, 0x202ffe, 0x0 },
- { 0xffe03884, 0xafa03080, 0x30078, 0x0 },
- { 0xf8003fc4, 0x40003f40, 0x7f00000, 0x1 },
- { 0xfc003e70, 0x28003a60, 0x3f00000, 0x1 },
- { 0xf7c02300, 0x13800000, 0x3000fe, 0x0 },
- { 0xffe03880, 0x9f802080, 0x1f0100, 0x0 },
- { 0xf0000000, 0xb0000000, 0xfe03fe0, 0x0 },
- { 0xffe03880, 0x9f402080, 0x1f0100, 0x0 },
- { 0xffe02000, 0x43200000, 0x7e0, 0x0 },
- { 0xffe00000, 0x39800000, 0x201f, 0x0 },
- { 0xffe03880, 0x9fc03880, 0x1f0100, 0x0 },
- { 0xffe02000, 0x45600000, 0x7e0, 0x0 },
- { 0xf9e00000, 0x91200000, 0x6003fe0, 0x0 },
- { 0xffe02000, 0x43600000, 0x7e0, 0x0 },
- { 0xfc003f00, 0x28003800, 0x3f00000, 0x1 },
- { 0xff802000, 0x74000000, 0x1fe0, 0x0 },
- { 0xffe02084, 0xaf002084, 0x30078, 0x0 },
- { 0xff802000, 0x74800000, 0x1fe0, 0x0 },
- { 0xf7c03000, 0x14c02000, 0x3000fe, 0x0 },
- { 0xfe000001, 0x5a000000, 0x1ff3ffe, 0x0 },
- { 0xff602060, 0x3f400020, 0x1f80, 0x0 },
- { 0xf7c02000, 0x10802000, 0x3000fe, 0x0 },
- { 0xffe02084, 0xaf802080, 0x30078, 0x0 },
- { 0xffe00004, 0x46400000, 0x20f8, 0x0 },
- { 0xffe020c0, 0xad800080, 0x3f, 0x0 },
- { 0xffe020c0, 0xad8000c0, 0x3f, 0x0 },
- { 0xf8003fc7, 0x40003f45, 0x7f00000, 0x1 },
- { 0xf8003e00, 0x60002a00, 0x7f00000, 0x1 },
- { 0xffe02084, 0xaf600084, 0x30078, 0x0 },
- { 0xffe03080, 0x9c201000, 0xf60, 0x0 },
- { 0xffe02000, 0x43400000, 0x7e0, 0x0 },
- { 0xffe03080, 0x9c203080, 0xf60, 0x0 },
- { 0xffe02000, 0x41200000, 0x7e0, 0x0 },
- { 0xffe03080, 0x9c201080, 0xf60, 0x0 },
- { 0xf7c02300, 0x11c02300, 0x3000fe, 0x0 },
- { 0xffe03880, 0x9fc03080, 0x1f0100, 0x0 },
- { 0xffe03880, 0x9f402880, 0x1f0100, 0x0 },
- { 0xf8003800, 0x40002000, 0x7f00000, 0x1 },
- { 0xf7c02000, 0x24402000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x20c02000, 0x3000fe, 0x0 },
- { 0xf7c02300, 0x11c00000, 0x3000fe, 0x0 },
- { 0xffe02000, 0x45200000, 0x7e0, 0x0 },
- { 0xf8003f00, 0x20003900, 0x7f00000, 0x1 },
- { 0xf7c02300, 0x11c00100, 0x3000fe, 0x0 },
- { 0xffe02084, 0xaf800084, 0x30078, 0x0 },
- { 0xfe600000, 0x3c200000, 0x207f, 0x0 },
- { 0xf7c02000, 0x26800000, 0x3000fe, 0x0 },
- { 0xffe03880, 0x9f003080, 0x1f0100, 0x0 },
- { 0xffe03884, 0xafa01084, 0x30078, 0x0 },
- { 0xffc00000, 0x76000000, 0x203fe0, 0x0 },
- { 0xff602060, 0x3e000040, 0x1f80, 0x0 },
- { 0xffe020c0, 0xadc020c0, 0x3f, 0x0 },
- { 0xffe00004, 0x44400000, 0x20f8, 0x0 },
- { 0xffe020c0, 0xadc02080, 0x3f, 0x0 },
- { 0xfe600000, 0x3c400000, 0x207f, 0x0 },
- { 0xf7c02000, 0x20400000, 0x3000fe, 0x0 },
- { 0xff800000, 0x7c000000, 0x1fe0, 0x0 },
- { 0xffe03884, 0xafa00080, 0x30078, 0x0 },
- { 0xff201800, 0x5c001800, 0xdf20fe, 0x0 },
- { 0xffe02000, 0x47800000, 0x7e0, 0x0 },
- { 0xff601018, 0xdd400000, 0xfe0, 0x0 },
- { 0xffe020c0, 0xad4020c0, 0x3f, 0x0 },
- { 0xffe020c0, 0xad402080, 0x3f, 0x0 },
- { 0xf8003000, 0x40001000, 0x7f00000, 0x1 },
- { 0xffe02084, 0xafc02084, 0x30078, 0x0 },
- { 0xffe03080, 0x9c403080, 0xf60, 0x0 },
- { 0xfc003e40, 0x28003a00, 0x3f00000, 0x1 },
- { 0xffe038c0, 0xada010c0, 0x3f, 0x0 },
- { 0xffe038c0, 0xada01080, 0x3f, 0x0 },
- { 0xffe038c0, 0xada030c0, 0x3f, 0x0 },
- { 0xffe038c0, 0xada03080, 0x3f, 0x0 },
- { 0xf7c02000, 0x20800000, 0x3000fe, 0x0 },
- { 0xfc003fc7, 0x48003f46, 0x3f00000, 0x1 },
- { 0xffe01804, 0x44a00000, 0x20f8, 0x0 },
- { 0xf7c02000, 0x20002000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x12c02000, 0x3000fe, 0x0 },
- { 0xffe03000, 0x9a601000, 0xf60, 0x0 },
- { 0xffc00000, 0xda800000, 0x203fe0, 0x0 },
- { 0xf9e00000, 0x90400000, 0x6003fe0, 0x0 },
- { 0xffe02000, 0x47600000, 0x7e0, 0x0 },
- { 0xffe03080, 0x9d403000, 0xf60, 0x0 },
- { 0xffe03080, 0x9d403080, 0xf60, 0x0 },
- { 0xffe03080, 0x9d401000, 0xf60, 0x0 },
- { 0xffe03080, 0x9d401080, 0xf60, 0x0 },
- { 0xffe02000, 0x41400000, 0x7e0, 0x0 },
- { 0xff800000, 0xdf800000, 0x6020e0, 0x0 },
- { 0xffc01000, 0x61000000, 0x202ffe, 0x0 },
- { 0xffe03880, 0x9f202080, 0x1f0100, 0x0 },
- { 0xfc003fc7, 0x48003fc6, 0x3f00000, 0x1 },
- { 0xfe000000, 0x7a000000, 0x1fe0, 0x0 },
- { 0xffff0000, 0x6a490000, 0x1f80, 0x0 },
- { 0xff802000, 0x73000000, 0x1fe0, 0x0 },
- { 0xff602060, 0x3e200020, 0x1f80, 0x0 },
- { 0xf7c02000, 0x24000000, 0x3000fe, 0x0 },
- { 0xf8003e40, 0x20003a00, 0x7f00000, 0x1 },
- { 0xf7c03000, 0x14401000, 0x3000fe, 0x0 },
- { 0xf8003f00, 0x20003200, 0x7f00000, 0x1 },
- { 0xffc00000, 0x76400000, 0x203fe0, 0x0 },
- { 0xf7c02000, 0x22002000, 0x3000fe, 0x0 },
- { 0xffc01000, 0x61c01000, 0x202ffe, 0x0 },
- { 0xf7c03000, 0x14801000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x12002000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x10402000, 0x3000fe, 0x0 },
- { 0xff201800, 0x5d200000, 0xdf20fe, 0x0 },
- { 0xf7c02000, 0x21400000, 0x3000fe, 0x0 },
- { 0xff201800, 0x5d000000, 0xdf20fe, 0x0 },
- { 0xffe02000, 0x45c00000, 0x7e0, 0x0 },
- { 0xf7c02000, 0x25802000, 0x3000fe, 0x0 },
- { 0xfc003e70, 0x28003a50, 0x3f00000, 0x1 },
- { 0xf7c02300, 0x13c00300, 0x3000fe, 0x0 },
- { 0xf9e01800, 0xa1a00800, 0x60020ff, 0x0 },
- { 0xffe02000, 0x43800000, 0x7e0, 0x0 },
- { 0xfc003fc4, 0x48003fc0, 0x3f00000, 0x1 },
- { 0xff800000, 0xe2800000, 0x1fe0, 0x0 },
- { 0xf7c02300, 0x13c02000, 0x3000fe, 0x0 },
- { 0xffe03080, 0x9d803080, 0xf60, 0x0 },
- { 0xffe03080, 0x9d803000, 0xf60, 0x0 },
- { 0xffe03080, 0x9d801080, 0xf60, 0x0 },
- { 0xf8003fc4, 0x40003f00, 0x7f00000, 0x1 },
- { 0xffe00000, 0x39c00000, 0x201f, 0x0 },
- { 0xffe03080, 0x9d203080, 0xf60, 0x0 },
- { 0xffe02080, 0xab000080, 0x3f, 0x0 },
- { 0xf8003e00, 0x60003c00, 0x7f00000, 0x1 },
- { 0xffe03880, 0x9f602080, 0x1f0100, 0x0 },
- { 0xffc00000, 0x76800000, 0x203fe0, 0x0 },
- { 0xffe03884, 0xafa02084, 0x30078, 0x0 },
- { 0xf7c02000, 0x13002000, 0x3000fe, 0x0 },
- { 0xf9e00000, 0x91000000, 0x6003fe0, 0x0 },
- { 0xffe03080, 0x9d201080, 0xf60, 0x0 },
- { 0xf7c03000, 0x15002000, 0x3000fe, 0x0 },
- { 0xf8003000, 0x60000000, 0x7f00000, 0x1 },
- { 0xffc01000, 0x61800000, 0x202ffe, 0x0 },
- { 0xf7c03000, 0x14400000, 0x3000fe, 0x0 },
- { 0xffe03000, 0x9b401000, 0xf60, 0x0 },
- { 0xf7c03000, 0x14003000, 0x3000fe, 0x0 },
- { 0xffe03880, 0x9fc02080, 0x1f0100, 0x0 },
- { 0xfc003fc4, 0x48003f00, 0x3f00000, 0x1 },
- { 0xffe02000, 0x45000000, 0x7e0, 0x0 },
- { 0xfc003800, 0x48002800, 0x3f00000, 0x1 },
- { 0xfc003fc7, 0x48003fc5, 0x3f00000, 0x1 },
- { 0xfc003d18, 0x28003c00, 0x3f00000, 0x1 },
- { 0xfc003fc7, 0x48003fc4, 0x3f00000, 0x1 },
- { 0xf8003f00, 0x60003200, 0x7f00000, 0x1 },
- { 0xffe02084, 0xaf600080, 0x30078, 0x0 },
- { 0xf9e01800, 0xa1a00000, 0x60020ff, 0x0 },
- { 0xf7c03000, 0x14001000, 0x3000fe, 0x0 },
- { 0xf7c03000, 0x14c01000, 0x3000fe, 0x0 },
- { 0xffe00004, 0x46c00000, 0x20f8, 0x0 },
- { 0xf7c03000, 0x15003000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x10000000, 0x3000fe, 0x0 },
- { 0xf8003d18, 0x20003c08, 0x7f00000, 0x1 },
- { 0xffc0001c, 0x75400010, 0x203fe0, 0x0 },
- { 0xf9e00000, 0x48600000, 0x61f20ff, 0x0 },
- { 0xffe03080, 0x9c603080, 0xf60, 0x0 },
- { 0xfe000000, 0x58000000, 0x1ff3ffe, 0x0 },
- { 0xffe03000, 0x9a201000, 0xf60, 0x0 },
- { 0xffe00000, 0x69e00000, 0x1f18, 0x0 },
- { 0xffe020c0, 0xad802080, 0x3f, 0x0 },
- { 0xffe02000, 0x47c00000, 0x7e0, 0x0 },
- { 0xffe00000, 0x60e00000, 0x1f18, 0x0 },
- { 0xf7c03000, 0x15402000, 0x3000fe, 0x0 },
- { 0xffe020c0, 0xad8020c0, 0x3f, 0x0 },
- { 0xff000016, 0xde000012, 0xe020e8, 0x0 },
- { 0xf7c02000, 0x25c02000, 0x3000fe, 0x0 },
- { 0xf8003f00, 0x60003100, 0x7f00000, 0x1 },
- { 0xf8003f00, 0x60003000, 0x7f00000, 0x1 },
- { 0xf7c02000, 0x25800000, 0x3000fe, 0x0 },
- { 0xf7c03000, 0x14403000, 0x3000fe, 0x0 },
- { 0xfc003d18, 0x28003c08, 0x3f00000, 0x1 },
- { 0xffe03880, 0x9f403080, 0x1f0100, 0x0 },
- { 0xf7c02000, 0x25402000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x10c00000, 0x3000fe, 0x0 },
- { 0xffe02000, 0x45800000, 0x7e0, 0x0 },
- { 0xffe03880, 0x9f803080, 0x1f0100, 0x0 },
- { 0xffe03080, 0x9d001000, 0xf60, 0x0 },
- { 0xffe03080, 0x9d001080, 0xf60, 0x0 },
- { 0xffe03080, 0x9d003000, 0xf60, 0x0 },
- { 0xffe03080, 0x9d003080, 0xf60, 0x0 },
- { 0xffe03080, 0x9d801000, 0xf60, 0x0 },
- { 0xf9e00000, 0x49200000, 0x61f3fe0, 0x0 },
- { 0xf9e00000, 0xa1c00000, 0x60020ff, 0x0 },
- { 0xf9e00000, 0x90200000, 0x6003fe0, 0x0 },
- { 0xffe03080, 0x9d201000, 0xf60, 0x0 },
- { 0xffe03884, 0xafa01080, 0x30078, 0x0 },
- { 0xffe02084, 0xaf602080, 0x30078, 0x0 },
- { 0xffe038c0, 0xada000c0, 0x3f, 0x0 },
- { 0xffe02080, 0xab400080, 0x3f, 0x0 },
- { 0xff000016, 0xde000004, 0xe020e8, 0x0 },
- { 0xffe00004, 0x44000000, 0x20f8, 0x0 },
- { 0xf7c02000, 0x20000000, 0x3000fe, 0x0 },
- { 0xfc003d18, 0x28003c10, 0x3f00000, 0x1 },
- { 0xff600018, 0xdd000008, 0x1fe0, 0x0 },
- { 0xffe020c0, 0xadc000c0, 0x3f, 0x0 },
- { 0xffe020c0, 0xadc00080, 0x3f, 0x0 },
- { 0xffe03000, 0x9b801000, 0xf60, 0x0 },
- { 0xf8003fc7, 0x40003f46, 0x7f00000, 0x1 },
- { 0xf7c02000, 0x21c02000, 0x3000fe, 0x0 },
- { 0xffe01804, 0x40a00000, 0x20f8, 0x0 },
- { 0xf7c02000, 0x26402000, 0x3000fe, 0x0 },
- { 0xffe03080, 0x9c401080, 0xf60, 0x0 },
- { 0xffe00000, 0x39200000, 0x201f, 0x0 },
- { 0xffe03080, 0x9c403000, 0xf60, 0x0 },
- { 0xf7c02000, 0x11002000, 0x3000fe, 0x0 },
- { 0xfc003c00, 0x28002800, 0x3f00000, 0x1 },
- { 0xffe00004, 0x40400000, 0x20f8, 0x0 },
- { 0xf7c02000, 0x26802000, 0x3000fe, 0x0 },
- { 0xf7c02000, 0x13000000, 0x3000fe, 0x0 },
- { 0xffe00004, 0x42600000, 0x20f8, 0x0 },
- { 0xf8003000, 0x60001000, 0x7f00000, 0x1 },
- { 0xff602060, 0x3e400020, 0x1f80, 0x0 },
- { 0xff602060, 0x3f000000, 0x1f80, 0x0 },
- { 0xf7c02000, 0x24c02000, 0x3000fe, 0x0 },
- { 0xff802000, 0x74002000, 0x1fe0, 0x0 },
- { 0xf8003800, 0x20002000, 0x7f00000, 0x1 },
- { 0xffe03000, 0x9aa01000, 0xf60, 0x0 },
- { 0xf7c02000, 0x12400000, 0x3000fe, 0x0 },
- { 0xff602060, 0x3f000060, 0x1f80, 0x0 },
- { 0xf7c02000, 0x11000000, 0x3000fe, 0x0 },
-};
-
-/// \brief finds the scatter Bits that need to be used to apply relocations
-inline uint32_t findv4bitmask(uint8_t *location) {
- uint32_t insn = llvm::support::endian::read32le(location);
- for (int32_t i = 0, e = llvm::array_lengthof(insn_encodings); i < e; i++) {
- if ((insn & 0xc000) == 0 && !insn_encodings[i].isDuplex)
- continue;
- if ((insn & 0xc000) != 0 && insn_encodings[i].isDuplex)
- continue;
- if ((insn_encodings[i].insnMask & insn) == insn_encodings[i].insnCmpMask)
- return insn_encodings[i].insnBitMask;
- }
- llvm_unreachable("found unknown Hexagon instruction");
-}
-
-} // namespace elf
-} // namespace lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h b/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h
deleted file mode 100644
index 390694954a75..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef HEXAGON_EXECUTABLE_WRITER_H
-#define HEXAGON_EXECUTABLE_WRITER_H
-
-#include "ExecutableWriter.h"
-#include "HexagonLinkingContext.h"
-#include "HexagonTargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-class HexagonTargetLayout;
-
-class HexagonExecutableWriter : public ExecutableWriter<ELF32LE> {
-public:
- HexagonExecutableWriter(HexagonLinkingContext &ctx,
- HexagonTargetLayout &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void finalizeDefaultAtomValues() override;
-
- std::error_code setELFHeader() override {
- ExecutableWriter::setELFHeader();
- setHexagonELFHeader(*_elfHeader);
- return std::error_code();
- }
-
-private:
- HexagonLinkingContext &_ctx;
- HexagonTargetLayout &_targetLayout;
-};
-
-HexagonExecutableWriter::HexagonExecutableWriter(HexagonLinkingContext &ctx,
- HexagonTargetLayout &layout)
- : ExecutableWriter(ctx, layout), _ctx(ctx), _targetLayout(layout) {}
-
-void HexagonExecutableWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter::createImplicitFiles(result);
- // Add the default atoms as defined for hexagon
- auto file =
- llvm::make_unique<RuntimeFile<ELF32LE>>(_ctx, "Hexagon runtime file");
- file->addAbsoluteAtom("_SDA_BASE_");
- if (_ctx.isDynamic()) {
- file->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
- file->addAbsoluteAtom("_DYNAMIC");
- }
- result.push_back(std::move(file));
-}
-
-void HexagonExecutableWriter::finalizeDefaultAtomValues() {
- // Finalize the atom values that are part of the parent.
- ExecutableWriter::finalizeDefaultAtomValues();
- AtomLayout *sdabaseAtom = _targetLayout.findAbsoluteAtom("_SDA_BASE_");
- sdabaseAtom->_virtualAddr = _targetLayout.getSDataSection()->virtualAddr();
- if (_ctx.isDynamic())
- finalizeHexagonRuntimeAtomValues(_targetLayout);
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif // HEXAGON_EXECUTABLE_WRITER_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp b/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp
deleted file mode 100644
index 11eabf7e26fc..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "HexagonLinkingContext.h"
-#include "HexagonTargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-std::unique_ptr<ELFLinkingContext>
-createHexagonLinkingContext(llvm::Triple triple) {
- if (triple.getArch() == llvm::Triple::hexagon)
- return llvm::make_unique<HexagonLinkingContext>(triple);
- return nullptr;
-}
-
-HexagonLinkingContext::HexagonLinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, std::unique_ptr<TargetHandler>(
- new HexagonTargetHandler(*this))) {}
-
-static const Registry::KindStrings kindStrings[] = {
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-#include "llvm/Support/ELFRelocs/Hexagon.def"
-#undef ELF_RELOC
- LLD_KIND_STRING_END
-};
-
-void HexagonLinkingContext::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::Hexagon, kindStrings);
-}
-
-void setHexagonELFHeader(ELFHeader<ELF32LE> &elfHeader) {
- elfHeader.e_ident(llvm::ELF::EI_VERSION, 1);
- elfHeader.e_ident(llvm::ELF::EI_OSABI, 0);
- elfHeader.e_version(1);
- elfHeader.e_flags(0x3);
-}
-
-} // namespace elf
-} // namespace lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h b/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h
deleted file mode 100644
index ab91e405fd56..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_LINKING_CONTEXT_H
-
-#include "OutputELFWriter.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-
-class HexagonLinkingContext final : public ELFLinkingContext {
-public:
- int getMachineType() const override { return llvm::ELF::EM_HEXAGON; }
- HexagonLinkingContext(llvm::Triple triple);
-
- void addPasses(PassManager &) override;
- void registerRelocationNames(Registry &r) override;
-
- bool isDynamicRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- switch (r.kindValue()) {
- case llvm::ELF::R_HEX_RELATIVE:
- case llvm::ELF::R_HEX_GLOB_DAT:
- return true;
- default:
- return false;
- }
- }
-
- bool isPLTRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- return r.kindValue() == llvm::ELF::R_HEX_JMP_SLOT;
- }
-
- /// \brief Hexagon has only one relative relocation
- /// a) for supporting relative relocs - R_HEX_RELATIVE
- bool isRelativeReloc(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- return r.kindValue() == llvm::ELF::R_HEX_RELATIVE;
- }
-};
-
-void setHexagonELFHeader(ELFHeader<ELF32LE> &elfHeader);
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_LINKING_CONTEXT_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
deleted file mode 100644
index 0a201b32b5f1..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp ---------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "HexagonEncodings.h"
-#include "HexagonLinkingContext.h"
-#include "HexagonRelocationHandler.h"
-#include "HexagonTargetHandler.h"
-#include "llvm/Support/Endian.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::ELF;
-using namespace llvm::support::endian;
-
-// Scatter val's bits as specified by the mask. Example:
-//
-// Val: 0bABCDEFG
-// Mask: 0b10111100001011
-// Output: 0b00ABCD0000E0FG
-static uint32_t scatterBits(uint32_t val, uint32_t mask) {
- uint32_t result = 0;
- size_t off = 0;
- for (size_t bit = 0; bit < 32; ++bit) {
- if ((mask >> bit) & 1) {
- uint32_t valBit = (val >> off) & 1;
- result |= valBit << bit;
- ++off;
- }
- }
- return result;
-}
-
-static void relocBNPCREL(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A,
- int32_t nBits) {
- int32_t result = (S + A - P) >> 2;
- int32_t range = 1 << nBits;
- if (result < range && result > -range) {
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
- }
-}
-
-/// \brief Word32_LO: 0x00c03fff : (S + A) : Truncate
-static void relocLO16(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = S + A;
- result = scatterBits(result, 0x00c03fff);
- write32le(loc, result | read32le(loc));
-}
-
-/// \brief Word32_LO: 0x00c03fff : (S + A) >> 16 : Truncate
-static void relocHI16(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (S + A) >> 16;
- result = scatterBits(result, 0x00c03fff);
- write32le(loc, result | read32le(loc));
-}
-
-/// \brief Word32: 0xffffffff : (S + A) : Truncate
-static void reloc32(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = S + A;
- write32le(loc, result | read32le(loc));
-}
-
-static void reloc32_6_X(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
- int64_t result = (S + A) >> 6;
- int64_t range = int64_t(1) << 32;
- if (result > range)
- result = scatterBits(result, 0xfff3fff);
- write32le(loc, result | read32le(loc));
-}
-
-// R_HEX_B32_PCREL_X
-static void relocHexB32PCRELX(uint8_t *loc, uint64_t P, uint64_t S,
- uint64_t A) {
- int64_t result = (S + A - P) >> 6;
- result = scatterBits(result, 0xfff3fff);
- write32le(loc, result | read32le(loc));
-}
-
-// R_HEX_BN_PCREL_X
-static void relocHexBNPCRELX(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A,
- int nbits) {
- int32_t result = (S + A - P) & 0x3f;
- int32_t range = 1 << nbits;
- if (result < range && result > -range) {
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
- }
-}
-
-// R_HEX_6_PCREL_X
-static void relocHex6PCRELX(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
- int32_t result = S + A - P;
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
-}
-
-// R_HEX_N_X : Word32_U6 : (S + A) : Unsigned Truncate
-static void relocHex_N_X(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = S + A;
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
-}
-
-// GP REL relocs
-static void relocHexGPRELN(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A,
- uint64_t GP, int nShiftBits) {
- int32_t result = (S + A - GP) >> nShiftBits;
- int32_t range = 1L << 16;
- if (result <= range) {
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
- }
-}
-
-/// \brief Word32_LO: 0x00c03fff : (G) : Truncate
-static void relocHexGOTLO16(uint8_t *loc, uint64_t A, uint64_t GOT) {
- int32_t result = A - GOT;
- result = scatterBits(result, 0x00c03fff);
- write32le(loc, result | read32le(loc));
-}
-
-/// \brief Word32_LO: 0x00c03fff : (G) >> 16 : Truncate
-static void relocHexGOTHI16(uint8_t *loc, uint64_t A, uint64_t GOT) {
- int32_t result = (A - GOT) >> 16;
- result = scatterBits(result, 0x00c03fff);
- write32le(loc, result | read32le(loc));
-}
-
-/// \brief Word32: 0xffffffff : (G) : Truncate
-static void relocHexGOT32(uint8_t *loc, uint64_t A, uint64_t GOT) {
- int32_t result = GOT - A;
- write32le(loc, result | read32le(loc));
-}
-
-/// \brief Word32_U16 : (G) : Truncate
-static void relocHexGOT16(uint8_t *loc, uint64_t A, uint64_t GOT) {
- int32_t result = GOT - A;
- int32_t range = 1L << 16;
- if (result <= range) {
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
- }
-}
-
-static void relocHexGOT32_6_X(uint8_t *loc, uint64_t A, uint64_t GOT) {
- int32_t result = (A - GOT) >> 6;
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
-}
-
-static void relocHexGOT16_X(uint8_t *loc, uint64_t A, uint64_t GOT) {
- int32_t result = A - GOT;
- int32_t range = 1L << 6;
- if (result <= range) {
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
- }
-}
-
-static void relocHexGOT11_X(uint8_t *loc, uint64_t A, uint64_t GOT) {
- uint32_t result = A - GOT;
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
-}
-
-static void relocHexGOTRELSigned(uint8_t *loc, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT, int shiftBits) {
- int32_t result = (S + A - GOT) >> shiftBits;
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
-}
-
-static void relocHexGOTRELUnsigned(uint8_t *loc, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT) {
- uint32_t result = S + A - GOT;
- result = scatterBits(result, findv4bitmask(loc));
- write32le(loc, result | read32le(loc));
-}
-
-static void relocHexGOTREL_HILO16(uint8_t *loc, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT, int shiftBits) {
- int32_t result = (S + A - GOT) >> shiftBits;
- result = scatterBits(result, 0x00c03fff);
- write32le(loc, result | read32le(loc));
-}
-
-static void relocHexGOTREL_32(uint8_t *loc, uint64_t P, uint64_t S, uint64_t A,
- uint64_t GOT) {
- int32_t result = S + A - GOT;
- write32le(loc, result | read32le(loc));
-}
-
-std::error_code HexagonTargetRelocationHandler::applyRelocation(
- ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
- const Reference &ref) const {
- uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *loc = atomContent + ref.offsetInAtom();
- uint64_t target = writer.addressOfAtom(ref.target());
- uint64_t reloc = atom._virtualAddr + ref.offsetInAtom();
-
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return std::error_code();
- assert(ref.kindArch() == Reference::KindArch::Hexagon);
- switch (ref.kindValue()) {
- case R_HEX_B22_PCREL:
- relocBNPCREL(loc, reloc, target, ref.addend(), 21);
- break;
- case R_HEX_B15_PCREL:
- relocBNPCREL(loc, reloc, target, ref.addend(), 14);
- break;
- case R_HEX_B9_PCREL:
- relocBNPCREL(loc, reloc, target, ref.addend(), 8);
- break;
- case R_HEX_LO16:
- relocLO16(loc, reloc, target, ref.addend());
- break;
- case R_HEX_HI16:
- relocHI16(loc, reloc, target, ref.addend());
- break;
- case R_HEX_32:
- reloc32(loc, reloc, target, ref.addend());
- break;
- case R_HEX_32_6_X:
- reloc32_6_X(loc, reloc, target, ref.addend());
- break;
- case R_HEX_B32_PCREL_X:
- relocHexB32PCRELX(loc, reloc, target, ref.addend());
- break;
- case R_HEX_B22_PCREL_X:
- relocHexBNPCRELX(loc, reloc, target, ref.addend(), 21);
- break;
- case R_HEX_B15_PCREL_X:
- relocHexBNPCRELX(loc, reloc, target, ref.addend(), 14);
- break;
- case R_HEX_B13_PCREL_X:
- relocHexBNPCRELX(loc, reloc, target, ref.addend(), 12);
- break;
- case R_HEX_B9_PCREL_X:
- relocHexBNPCRELX(loc, reloc, target, ref.addend(), 8);
- break;
- case R_HEX_B7_PCREL_X:
- relocHexBNPCRELX(loc, reloc, target, ref.addend(), 6);
- break;
- case R_HEX_GPREL16_0:
- relocHexGPRELN(loc, reloc, target, ref.addend(),
- _targetLayout.getSDataSection()->virtualAddr(), 0);
- break;
- case R_HEX_GPREL16_1:
- relocHexGPRELN(loc, reloc, target, ref.addend(),
- _targetLayout.getSDataSection()->virtualAddr(), 1);
- break;
- case R_HEX_GPREL16_2:
- relocHexGPRELN(loc, reloc, target, ref.addend(),
- _targetLayout.getSDataSection()->virtualAddr(), 2);
- break;
- case R_HEX_GPREL16_3:
- relocHexGPRELN(loc, reloc, target, ref.addend(),
- _targetLayout.getSDataSection()->virtualAddr(), 3);
- break;
- case R_HEX_16_X:
- case R_HEX_12_X:
- case R_HEX_11_X:
- case R_HEX_10_X:
- case R_HEX_9_X:
- case R_HEX_8_X:
- case R_HEX_7_X:
- case R_HEX_6_X:
- relocHex_N_X(loc, reloc, target, ref.addend());
- break;
- case R_HEX_6_PCREL_X:
- relocHex6PCRELX(loc, reloc, target, ref.addend());
- break;
- case R_HEX_JMP_SLOT:
- case R_HEX_GLOB_DAT:
- break;
- case R_HEX_GOTREL_32:
- relocHexGOTREL_32(loc, reloc, target, ref.addend(),
- _targetLayout.getGOTSymAddr());
- break;
- case R_HEX_GOTREL_LO16:
- relocHexGOTREL_HILO16(loc, reloc, target, ref.addend(),
- _targetLayout.getGOTSymAddr(), 0);
- break;
- case R_HEX_GOTREL_HI16:
- relocHexGOTREL_HILO16(loc, reloc, target, ref.addend(),
- _targetLayout.getGOTSymAddr(), 16);
- break;
- case R_HEX_GOT_LO16:
- relocHexGOTLO16(loc, target, _targetLayout.getGOTSymAddr());
- break;
- case R_HEX_GOT_HI16:
- relocHexGOTHI16(loc, target, _targetLayout.getGOTSymAddr());
- break;
- case R_HEX_GOT_32:
- relocHexGOT32(loc, target, _targetLayout.getGOTSymAddr());
- break;
- case R_HEX_GOT_16:
- relocHexGOT16(loc, target, _targetLayout.getGOTSymAddr());
- break;
- case R_HEX_GOT_32_6_X:
- relocHexGOT32_6_X(loc, target, _targetLayout.getGOTSymAddr());
- break;
- case R_HEX_GOT_16_X:
- relocHexGOT16_X(loc, target, _targetLayout.getGOTSymAddr());
- break;
- case R_HEX_GOT_11_X:
- relocHexGOT11_X(loc, target, _targetLayout.getGOTSymAddr());
- break;
- case R_HEX_GOTREL_32_6_X:
- relocHexGOTRELSigned(loc, reloc, target, ref.addend(),
- _targetLayout.getGOTSymAddr(), 6);
- break;
- case R_HEX_GOTREL_16_X:
- case R_HEX_GOTREL_11_X:
- relocHexGOTRELUnsigned(loc, reloc, target, ref.addend(),
- _targetLayout.getGOTSymAddr());
- break;
-
- default:
- return make_unhandled_reloc_error();
- }
-
- return std::error_code();
-}
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h
deleted file mode 100644
index 6afba0ddb8f3..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- lld/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h -----------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_RELOCATION_HANDLER_H
-#define LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_RELOCATION_HANDLER_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-
-namespace lld {
-namespace elf {
-class HexagonTargetHandler;
-class HexagonTargetLayout;
-
-class HexagonTargetRelocationHandler final : public TargetRelocationHandler {
-public:
- HexagonTargetRelocationHandler(HexagonTargetLayout &layout)
- : _targetLayout(layout) {}
-
- std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const AtomLayout &,
- const Reference &) const override;
-
-private:
- HexagonTargetLayout &_targetLayout;
-};
-} // elf
-} // lld
-#endif
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp b/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
deleted file mode 100644
index 6c0360c310f4..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp --------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "HexagonExecutableWriter.h"
-#include "HexagonDynamicLibraryWriter.h"
-#include "HexagonLinkingContext.h"
-#include "HexagonTargetHandler.h"
-
-using namespace llvm::ELF;
-
-using llvm::makeArrayRef;
-
-namespace lld {
-namespace elf {
-
-HexagonTargetHandler::HexagonTargetHandler(HexagonLinkingContext &ctx)
- : _ctx(ctx), _targetLayout(new HexagonTargetLayout(ctx)),
- _relocationHandler(new HexagonTargetRelocationHandler(*_targetLayout)) {}
-
-std::unique_ptr<Writer> HexagonTargetHandler::getWriter() {
- switch (_ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- return llvm::make_unique<HexagonExecutableWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<HexagonDynamicLibraryWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_REL:
- llvm_unreachable("TODO: support -r mode");
- default:
- llvm_unreachable("unsupported output type");
- }
-}
-
-using namespace llvm::ELF;
-
-// .got atom
-const uint8_t hexagonGotAtomContent[4] = { 0 };
-// .got.plt atom (entry 0)
-const uint8_t hexagonGotPlt0AtomContent[16] = { 0 };
-// .got.plt atom (all other entries)
-const uint8_t hexagonGotPltAtomContent[4] = { 0 };
-// .plt (entry 0)
-const uint8_t hexagonPlt0AtomContent[28] = {
- 0x00, 0x40, 0x00, 0x00, // { immext (#0)
- 0x1c, 0xc0, 0x49, 0x6a, // r28 = add (pc, ##GOT0@PCREL) } # address of GOT0
- 0x0e, 0x42, 0x9c, 0xe2, // { r14 -= add (r28, #16) # offset of GOTn from GOTa
- 0x4f, 0x40, 0x9c, 0x91, // r15 = memw (r28 + #8) # object ID at GOT2
- 0x3c, 0xc0, 0x9c, 0x91, // r28 = memw (r28 + #4) }# dynamic link at GOT1
- 0x0e, 0x42, 0x0e, 0x8c, // { r14 = asr (r14, #2) # index of PLTn
- 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 } # call dynamic linker
-};
-
-// .plt (other entries)
-const uint8_t hexagonPltAtomContent[16] = {
- 0x00, 0x40, 0x00, 0x00, // { immext (#0)
- 0x0e, 0xc0, 0x49, 0x6a, // r14 = add (pc, ##GOTn@PCREL) } # address of GOTn
- 0x1c, 0xc0, 0x8e, 0x91, // r28 = memw (r14) # contents of GOTn
- 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 # call it
-};
-
-class HexagonGOTAtom : public GOTAtom {
-public:
- HexagonGOTAtom(const File &f) : GOTAtom(f, ".got") {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return makeArrayRef(hexagonGotAtomContent);
- }
-
- Alignment alignment() const override { return 4; }
-};
-
-class HexagonGOTPLTAtom : public GOTAtom {
-public:
- HexagonGOTPLTAtom(const File &f) : GOTAtom(f, ".got.plt") {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return makeArrayRef(hexagonGotPltAtomContent);
- }
-
- Alignment alignment() const override { return 4; }
-};
-
-class HexagonGOTPLT0Atom : public GOTAtom {
-public:
- HexagonGOTPLT0Atom(const File &f) : GOTAtom(f, ".got.plt") {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return makeArrayRef(hexagonGotPlt0AtomContent);
- }
-
- Alignment alignment() const override { return 8; }
-};
-
-class HexagonPLT0Atom : public PLT0Atom {
-public:
- HexagonPLT0Atom(const File &f) : PLT0Atom(f) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return makeArrayRef(hexagonPlt0AtomContent);
- }
-};
-
-class HexagonPLTAtom : public PLTAtom {
-
-public:
- HexagonPLTAtom(const File &f, StringRef secName) : PLTAtom(f, secName) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return makeArrayRef(hexagonPltAtomContent);
- }
-};
-
-class ELFPassFile : public SimpleFile {
-public:
- ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
- setOrdinal(eti.getNextOrdinalAndIncrement());
- }
-
- llvm::BumpPtrAllocator _alloc;
-};
-
-/// \brief Create GOT and PLT entries for relocations. Handles standard GOT/PLT
-template <class Derived> class GOTPLTPass : public Pass {
- /// \brief Handle a specific reference.
- void handleReference(const DefinedAtom &atom, const Reference &ref) {
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return;
- assert(ref.kindArch() == Reference::KindArch::Hexagon);
- switch (ref.kindValue()) {
- case R_HEX_PLT_B22_PCREL:
- case R_HEX_B22_PCREL:
- static_cast<Derived *>(this)->handlePLT32(ref);
- break;
- case R_HEX_GOT_LO16:
- case R_HEX_GOT_HI16:
- case R_HEX_GOT_32_6_X:
- case R_HEX_GOT_16_X:
- case R_HEX_GOT_11_X:
- static_cast<Derived *>(this)->handleGOTREL(ref);
- break;
- }
- }
-
-protected:
- /// \brief Create a GOT entry containing 0.
- const GOTAtom *getNullGOT() {
- if (!_null) {
- _null = new (_file._alloc) HexagonGOTPLTAtom(_file);
-#ifndef NDEBUG
- _null->_name = "__got_null";
-#endif
- }
- return _null;
- }
-
-public:
- GOTPLTPass(const ELFLinkingContext &ctx) : _file(ctx) {}
-
- /// \brief Do the pass.
- ///
- /// The goal here is to first process each reference individually. Each call
- /// to handleReference may modify the reference itself and/or create new
- /// atoms which must be stored in one of the maps below.
- ///
- /// After all references are handled, the atoms created during that are all
- /// added to mf.
- std::error_code perform(SimpleFile &mf) override {
- // Process all references.
- for (const auto &atom : mf.defined())
- for (const auto &ref : *atom)
- handleReference(*atom, *ref);
-
- // Add all created atoms to the link.
- uint64_t ordinal = 0;
- if (_plt0) {
- _plt0->setOrdinal(ordinal++);
- mf.addAtom(*_plt0);
- }
- for (auto &plt : _pltVector) {
- plt->setOrdinal(ordinal++);
- mf.addAtom(*plt);
- }
- if (_null) {
- _null->setOrdinal(ordinal++);
- mf.addAtom(*_null);
- }
- if (_got0) {
- _got0->setOrdinal(ordinal++);
- mf.addAtom(*_got0);
- }
- for (auto &got : _gotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
-
- return std::error_code();
- }
-
-protected:
- /// \brief Owner of all the Atoms created by this pass.
- ELFPassFile _file;
-
- /// \brief Map Atoms to their GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
-
- /// \brief Map Atoms to their PLT entries.
- llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
-
- /// \brief the list of GOT/PLT atoms
- std::vector<GOTAtom *> _gotVector;
- std::vector<PLTAtom *> _pltVector;
-
- /// \brief GOT entry that is always 0. Used for undefined weaks.
- GOTAtom *_null = nullptr;
-
- /// \brief The got and plt entries for .PLT0. This is used to call into the
- /// dynamic linker for symbol resolution.
- /// @{
- PLT0Atom *_plt0 = nullptr;
- GOTAtom *_got0 = nullptr;
- /// @}
-};
-
-class DynamicGOTPLTPass final : public GOTPLTPass<DynamicGOTPLTPass> {
-public:
- DynamicGOTPLTPass(const HexagonLinkingContext &ctx) : GOTPLTPass(ctx) {
- _got0 = new (_file._alloc) HexagonGOTPLT0Atom(_file);
-#ifndef NDEBUG
- _got0->_name = "__got0";
-#endif
- }
-
- const PLT0Atom *getPLT0() {
- if (_plt0)
- return _plt0;
- _plt0 = new (_file._alloc) HexagonPLT0Atom(_file);
- _plt0->addReferenceELF_Hexagon(R_HEX_B32_PCREL_X, 0, _got0, 0);
- _plt0->addReferenceELF_Hexagon(R_HEX_6_PCREL_X, 4, _got0, 4);
- DEBUG_WITH_TYPE("PLT", llvm::dbgs() << "[ PLT0/GOT0 ] "
- << "Adding plt0/got0 \n");
- return _plt0;
- }
-
- const PLTAtom *getPLTEntry(const Atom *a) {
- auto plt = _pltMap.find(a);
- if (plt != _pltMap.end())
- return plt->second;
- auto ga = new (_file._alloc) HexagonGOTPLTAtom(_file);
- ga->addReferenceELF_Hexagon(R_HEX_JMP_SLOT, 0, a, 0);
- auto pa = new (_file._alloc) HexagonPLTAtom(_file, ".plt");
- pa->addReferenceELF_Hexagon(R_HEX_B32_PCREL_X, 0, ga, 0);
- pa->addReferenceELF_Hexagon(R_HEX_6_PCREL_X, 4, ga, 4);
-
- // Point the got entry to the PLT0 atom initially
- ga->addReferenceELF_Hexagon(R_HEX_32, 0, getPLT0(), 0);
-#ifndef NDEBUG
- ga->_name = "__got_";
- ga->_name += a->name();
- pa->_name = "__plt_";
- pa->_name += a->name();
- DEBUG_WITH_TYPE("PLT", llvm::dbgs() << "[" << a->name() << "] "
- << "Adding plt/got: " << pa->_name
- << "/" << ga->_name << "\n");
-#endif
- _gotMap[a] = ga;
- _pltMap[a] = pa;
- _gotVector.push_back(ga);
- _pltVector.push_back(pa);
- return pa;
- }
-
- const GOTAtom *getGOTEntry(const Atom *a) {
- auto got = _gotMap.find(a);
- if (got != _gotMap.end())
- return got->second;
- auto ga = new (_file._alloc) HexagonGOTAtom(_file);
- ga->addReferenceELF_Hexagon(R_HEX_GLOB_DAT, 0, a, 0);
-
-#ifndef NDEBUG
- ga->_name = "__got_";
- ga->_name += a->name();
- DEBUG_WITH_TYPE("GOT", llvm::dbgs() << "[" << a->name() << "] "
- << "Adding got: " << ga->_name << "\n");
-#endif
- _gotMap[a] = ga;
- _gotVector.push_back(ga);
- return ga;
- }
-
- std::error_code handleGOTREL(const Reference &ref) {
- // Turn this so that the target is set to the GOT entry
- const_cast<Reference &>(ref).setTarget(getGOTEntry(ref.target()));
- return std::error_code();
- }
-
- std::error_code handlePLT32(const Reference &ref) {
- // Turn this into a PC32 to the PLT entry.
- assert(ref.kindNamespace() == Reference::KindNamespace::ELF);
- assert(ref.kindArch() == Reference::KindArch::Hexagon);
- const_cast<Reference &>(ref).setKindValue(R_HEX_B22_PCREL);
- const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
- return std::error_code();
- }
-};
-
-void HexagonLinkingContext::addPasses(PassManager &pm) {
- if (isDynamic())
- pm.add(llvm::make_unique<DynamicGOTPLTPass>(*this));
- ELFLinkingContext::addPasses(pm);
-}
-
-void SDataSection::doPreFlight() {
- // sort the atoms on the alignments they have been set
- std::stable_sort(_atoms.begin(), _atoms.end(), [](const AtomLayout *A,
- const AtomLayout *B) {
- const DefinedAtom *definedAtomA = cast<DefinedAtom>(A->_atom);
- const DefinedAtom *definedAtomB = cast<DefinedAtom>(B->_atom);
- int64_t alignmentA = definedAtomA->alignment().value;
- int64_t alignmentB = definedAtomB->alignment().value;
- if (alignmentA == alignmentB) {
- if (definedAtomA->merge() == DefinedAtom::mergeAsTentative)
- return false;
- if (definedAtomB->merge() == DefinedAtom::mergeAsTentative)
- return true;
- }
- return alignmentA < alignmentB;
- });
-
- // Set the fileOffset, and the appropriate size of the section
- for (auto &ai : _atoms) {
- const DefinedAtom *definedAtom = cast<DefinedAtom>(ai->_atom);
- DefinedAtom::Alignment atomAlign = definedAtom->alignment();
- uint64_t fOffset = alignOffset(fileSize(), atomAlign);
- uint64_t mOffset = alignOffset(memSize(), atomAlign);
- ai->_fileOffset = fOffset;
- _fsize = fOffset + definedAtom->size();
- _msize = mOffset + definedAtom->size();
- }
-} // finalize
-
-SDataSection::SDataSection(const HexagonLinkingContext &ctx)
- : AtomSection(ctx, ".sdata", DefinedAtom::typeDataFast, 0,
- HexagonTargetLayout::ORDER_SDATA) {
- _type = SHT_PROGBITS;
- _flags = SHF_ALLOC | SHF_WRITE;
- _alignment = 4096;
-}
-
-const AtomLayout *SDataSection::appendAtom(const Atom *atom) {
- const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
- DefinedAtom::Alignment atomAlign = definedAtom->alignment();
- uint64_t alignment = atomAlign.value;
- _atoms.push_back(new (_alloc) AtomLayout(atom, 0, 0));
- // Set the section alignment to the largest alignment
- // std::max doesn't support uint64_t
- if (_alignment < alignment)
- _alignment = alignment;
- return _atoms.back();
-}
-
-void finalizeHexagonRuntimeAtomValues(HexagonTargetLayout &layout) {
- AtomLayout *gotAtom = layout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
- OutputSection<ELF32LE> *gotpltSection = layout.findOutputSection(".got.plt");
- if (gotpltSection)
- gotAtom->_virtualAddr = gotpltSection->virtualAddr();
- else
- gotAtom->_virtualAddr = 0;
- AtomLayout *dynamicAtom = layout.findAbsoluteAtom("_DYNAMIC");
- OutputSection<ELF32LE> *dynamicSection = layout.findOutputSection(".dynamic");
- if (dynamicSection)
- dynamicAtom->_virtualAddr = dynamicSection->virtualAddr();
- else
- dynamicAtom->_virtualAddr = 0;
-}
-
-} // namespace elf
-} // namespace lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h b/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
deleted file mode 100644
index b1366bed09ea..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
+++ /dev/null
@@ -1,134 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef HEXAGON_TARGET_HANDLER_H
-#define HEXAGON_TARGET_HANDLER_H
-
-#include "ELFReader.h"
-#include "HexagonELFFile.h"
-#include "HexagonRelocationHandler.h"
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-class HexagonLinkingContext;
-
-/// \brief Handle Hexagon SData section
-class SDataSection : public AtomSection<ELF32LE> {
-public:
- SDataSection(const HexagonLinkingContext &ctx);
-
- /// \brief Finalize the section contents before writing
- void doPreFlight() override;
-
- /// \brief Does this section have an output segment.
- bool hasOutputSegment() const override { return true; }
-
- const AtomLayout *appendAtom(const Atom *atom) override;
-};
-
-/// \brief TargetLayout for Hexagon
-class HexagonTargetLayout final : public TargetLayout<ELF32LE> {
-public:
- enum HexagonSectionOrder {
- ORDER_SDATA = 205
- };
-
- HexagonTargetLayout(HexagonLinkingContext &ctx)
- : TargetLayout(ctx), _sdataSection(ctx) {}
-
- /// \brief Return the section order for a input section
- TargetLayout::SectionOrder
- getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPermissions) override {
- if (contentType == DefinedAtom::typeDataFast ||
- contentType == DefinedAtom::typeZeroFillFast)
- return ORDER_SDATA;
- return TargetLayout::getSectionOrder(name, contentType, contentPermissions);
- }
-
- /// \brief Return the appropriate input section name.
- StringRef getInputSectionName(const DefinedAtom *da) const override {
- switch (da->contentType()) {
- case DefinedAtom::typeDataFast:
- case DefinedAtom::typeZeroFillFast:
- return ".sdata";
- default:
- break;
- }
- return TargetLayout::getInputSectionName(da);
- }
-
- /// \brief Gets or creates a section.
- AtomSection<ELF32LE> *
- createSection(StringRef name, int32_t contentType,
- DefinedAtom::ContentPermissions contentPermissions,
- TargetLayout::SectionOrder sectionOrder) override {
- if (contentType == DefinedAtom::typeDataFast ||
- contentType == DefinedAtom::typeZeroFillFast)
- return &_sdataSection;
- return TargetLayout::createSection(name, contentType, contentPermissions,
- sectionOrder);
- }
-
- /// \brief get the segment type for the section thats defined by the target
- TargetLayout::SegmentType
- getSegmentType(const Section<ELF32LE> *section) const override {
- if (section->order() == ORDER_SDATA)
- return PT_LOAD;
- return TargetLayout::getSegmentType(section);
- }
-
- Section<ELF32LE> *getSDataSection() { return &_sdataSection; }
-
- uint64_t getGOTSymAddr() {
- std::call_once(_gotOnce, [this]() {
- if (AtomLayout *got = findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"))
- _gotAddr = got->_virtualAddr;
- });
- return _gotAddr;
- }
-
-private:
- SDataSection _sdataSection;
- uint64_t _gotAddr = 0;
- std::once_flag _gotOnce;
-};
-
-/// \brief TargetHandler for Hexagon
-class HexagonTargetHandler final : public TargetHandler {
-public:
- HexagonTargetHandler(HexagonLinkingContext &targetInfo);
-
- const TargetRelocationHandler &getRelocationHandler() const override {
- return *_relocationHandler;
- }
-
- std::unique_ptr<Reader> getObjReader() override {
- return llvm::make_unique<ELFReader<HexagonELFFile>>(_ctx);
- }
-
- std::unique_ptr<Reader> getDSOReader() override {
- return llvm::make_unique<ELFReader<DynamicFile<ELF32LE>>>(_ctx);
- }
-
- std::unique_ptr<Writer> getWriter() override;
-
-private:
- HexagonLinkingContext &_ctx;
- std::unique_ptr<HexagonTargetLayout> _targetLayout;
- std::unique_ptr<HexagonTargetRelocationHandler> _relocationHandler;
-};
-
-void finalizeHexagonRuntimeAtomValues(HexagonTargetLayout &layout);
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/CMakeLists.txt b/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
deleted file mode 100644
index fd52a08ad2d8..000000000000
--- a/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-add_lld_library(lldMipsELFTarget
- MipsAbiInfoHandler.cpp
- MipsCtorsOrderPass.cpp
- MipsELFFile.cpp
- MipsELFWriters.cpp
- MipsLinkingContext.cpp
- MipsRelocationHandler.cpp
- MipsRelocationPass.cpp
- MipsSectionChunks.cpp
- MipsTargetHandler.cpp
- MipsTargetLayout.cpp
- LINK_LIBS
- lldELF
- lldReaderWriter
- lldCore
- LLVMObject
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp b/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
deleted file mode 100644
index ad4e62e64680..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
+++ /dev/null
@@ -1,675 +0,0 @@
-//===- lib/ReaderWriter/ELF/MipsAbiInfoHandler.cpp ------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsAbiInfoHandler.h"
-#include "lld/Core/Error.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/MipsABIFlags.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm;
-using namespace llvm::ELF;
-using namespace llvm::Mips;
-
-namespace {
-
-// The joined set of MIPS ISAs and MIPS ISA extensions.
-enum MipsISAs {
- ArchNone,
-
- // General ISAs
- Arch1,
- Arch2,
- Arch3,
- Arch4,
- Arch5,
- Arch32,
- Arch32r2,
- Arch32r3,
- Arch32r5,
- Arch32r6,
- Arch64,
- Arch64r2,
- Arch64r3,
- Arch64r5,
- Arch64r6,
-
- // CPU specific ISAs
- Arch3900,
- Arch4010,
- Arch4100,
- Arch4111,
- Arch4120,
- Arch4650,
- Arch5400,
- Arch5500,
- Arch5900,
- Arch9000,
- Arch10000,
- ArchLs2e,
- ArchLs2f,
- ArchLs3a,
- ArchOcteon,
- ArchOcteonP,
- ArchOcteon2,
- ArchOcteon3,
- ArchSB1,
- ArchXLR
-};
-
-struct MipsISATreeEdge {
- MipsISAs child;
- MipsISAs parent;
-};
-
-struct ElfArchPair {
- uint32_t _elfFlag;
- MipsISAs _arch;
-};
-
-struct AbiIsaArchPair {
- uint8_t _isaLevel;
- uint8_t _isaRev;
- uint8_t _isaExt;
- MipsISAs _arch;
-};
-}
-
-static const MipsISATreeEdge isaTree[] = {
- // MIPS32R6 and MIPS64R6 are not compatible with other extensions
-
- // MIPS64R2 extensions.
- {ArchOcteon3, ArchOcteon2},
- {ArchOcteon2, ArchOcteonP},
- {ArchOcteonP, ArchOcteon},
- {ArchOcteon, Arch64r2},
- {ArchLs3a, Arch64r2},
-
- // MIPS64 extensions.
- {Arch64r2, Arch64},
- {ArchSB1, Arch64},
- {ArchXLR, Arch64},
-
- // MIPS V extensions.
- {Arch64, Arch5},
-
- // R5000 extensions.
- {Arch5500, Arch5400},
-
- // MIPS IV extensions.
- {Arch5, Arch4},
- {Arch5400, Arch4},
- {Arch9000, Arch4},
-
- // VR4100 extensions.
- {Arch4120, Arch4100},
- {Arch4111, Arch4100},
-
- // MIPS III extensions.
- {ArchLs2e, Arch3},
- {ArchLs2f, Arch3},
- {Arch4650, Arch3},
- {Arch4100, Arch3},
- {Arch4010, Arch3},
- {Arch5900, Arch3},
- {Arch4, Arch3},
-
- // MIPS32 extensions.
- {Arch32r2, Arch32},
-
- // MIPS II extensions.
- {Arch3, Arch2},
- {Arch32, Arch2},
-
- // MIPS I extensions.
- {Arch3900, Arch1},
- {Arch2, Arch1},
-};
-
-// Conversion ELF arch flags => MipsISAs
-static const ElfArchPair elfArchPairs[] = {
- {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, Arch3900},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, Arch4010},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, Arch4100},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, Arch4111},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, Arch4120},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, Arch4650},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, Arch5400},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, Arch5500},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, Arch5900},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, Arch9000},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, ArchLs2e},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, ArchLs2f},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, ArchLs3a},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteon},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, ArchOcteon2},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, ArchOcteon3},
- {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchSB1},
- {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, ArchXLR},
- {EF_MIPS_ARCH_1, Arch1},
- {EF_MIPS_ARCH_2, Arch2},
- {EF_MIPS_ARCH_3, Arch3},
- {EF_MIPS_ARCH_4, Arch4},
- {EF_MIPS_ARCH_5, Arch5},
- {EF_MIPS_ARCH_32, Arch32},
- {EF_MIPS_ARCH_32R2, Arch32r2},
- {EF_MIPS_ARCH_32R6, Arch32r6},
- {EF_MIPS_ARCH_64, Arch64},
- {EF_MIPS_ARCH_64R2, Arch64r2},
- {EF_MIPS_ARCH_64R6, Arch64r6}
-};
-
-// Conversion MipsISAs => ELF arch flags
-static const ElfArchPair archElfPairs[] = {
- {EF_MIPS_ARCH_1, Arch1},
- {EF_MIPS_ARCH_2, Arch2},
- {EF_MIPS_ARCH_3, Arch3},
- {EF_MIPS_ARCH_4, Arch4},
- {EF_MIPS_ARCH_5, Arch5},
- {EF_MIPS_ARCH_32, Arch32},
- {EF_MIPS_ARCH_32R2, Arch32r2},
- {EF_MIPS_ARCH_32R2, Arch32r3},
- {EF_MIPS_ARCH_32R2, Arch32r5},
- {EF_MIPS_ARCH_32R6, Arch32r6},
- {EF_MIPS_ARCH_64, Arch64},
- {EF_MIPS_ARCH_64R2, Arch64r2},
- {EF_MIPS_ARCH_64R2, Arch64r3},
- {EF_MIPS_ARCH_64R2, Arch64r5},
- {EF_MIPS_ARCH_64R6, Arch64r6},
- {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, Arch3900},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, Arch4010},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, Arch4100},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, Arch4111},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, Arch4120},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, Arch4650},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, Arch5400},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, Arch5500},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, Arch5900},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, Arch9000},
- {EF_MIPS_ARCH_4, Arch10000},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, ArchLs2e},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, ArchLs2f},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, ArchLs3a},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteon},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteonP},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, ArchOcteon2},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, ArchOcteon3},
- {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchSB1},
- {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchXLR}
-};
-
-// Conversion .MIPS.abiflags isa/level/extension <=> MipsISAs
-static const AbiIsaArchPair abiIsaArchPair[] = {
- { 0, 0, 0, ArchNone},
- { 1, 0, 0, Arch1},
- { 2, 0, 0, Arch2},
- { 3, 0, 0, Arch3},
- { 4, 0, 0, Arch4},
- { 5, 0, 0, Arch5},
- {32, 1, 0, Arch32},
- {32, 2, 0, Arch32r2},
- {32, 3, 0, Arch32r3},
- {32, 5, 0, Arch32r5},
- {32, 6, 0, Arch32r6},
- {64, 1, 0, Arch64},
- {64, 2, 0, Arch64r2},
- {64, 3, 0, Arch64r3},
- {64, 5, 0, Arch64r5},
- {64, 6, 0, Arch64r6},
- { 1, 0, AFL_EXT_3900, Arch3900},
- { 3, 0, AFL_EXT_4010, Arch4010},
- { 3, 0, AFL_EXT_4100, Arch4100},
- { 3, 0, AFL_EXT_4111, Arch4111},
- { 3, 0, AFL_EXT_4120, Arch4120},
- { 3, 0, AFL_EXT_4650, Arch4650},
- { 4, 0, AFL_EXT_5400, Arch5400},
- { 4, 0, AFL_EXT_5500, Arch5500},
- { 3, 0, AFL_EXT_5900, Arch5900},
- { 4, 0, AFL_EXT_10000, Arch10000},
- { 3, 0, AFL_EXT_LOONGSON_2E, ArchLs2e},
- { 3, 0, AFL_EXT_LOONGSON_2F, ArchLs2f},
- {64, 2, AFL_EXT_LOONGSON_3A, ArchLs3a},
- {64, 2, AFL_EXT_OCTEON, ArchOcteon},
- {64, 2, AFL_EXT_OCTEON2, ArchOcteon2},
- {64, 2, AFL_EXT_OCTEON3, ArchOcteon3},
- {64, 1, AFL_EXT_SB1, ArchSB1},
- {64, 1, AFL_EXT_XLR, ArchXLR}
-};
-
-static bool matchMipsISA(MipsISAs base, MipsISAs ext) {
- if (base == ext)
- return true;
- if (base == Arch32 && matchMipsISA(Arch64, ext))
- return true;
- if (base == Arch32r2 && matchMipsISA(Arch64r2, ext))
- return true;
- for (const auto &edge : isaTree) {
- if (ext == edge.child) {
- ext = edge.parent;
- if (ext == base)
- return true;
- }
- }
- return false;
-}
-
-static bool is32BitElfFlags(unsigned flags) {
- if (flags & EF_MIPS_32BITMODE)
- return true;
-
- unsigned arch = flags & EF_MIPS_ARCH;
- if (arch == EF_MIPS_ARCH_1 || arch == EF_MIPS_ARCH_2 ||
- arch == EF_MIPS_ARCH_32 || arch == EF_MIPS_ARCH_32R2 ||
- arch == EF_MIPS_ARCH_32R6)
- return true;
-
- unsigned abi = flags & EF_MIPS_ABI;
- if (abi == EF_MIPS_ABI_O32 || abi == EF_MIPS_ABI_EABI32)
- return true;
-
- return false;
-}
-
-static ErrorOr<MipsISAs> headerFlagsToIsa(uint32_t flags) {
- uint32_t arch = flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
- for (const auto &p : elfArchPairs)
- if (p._elfFlag == arch)
- return p._arch;
- return make_dynamic_error_code(
- StringRef("Unknown EF_MIPS_ARCH | EF_MIPS_MACH flags (0x") +
- Twine::utohexstr(arch) + ")");
-}
-
-static uint32_t isaToHeaderFlags(unsigned isa) {
- for (const auto &p : archElfPairs)
- if (p._arch == isa)
- return p._elfFlag;
- llvm_unreachable("Unknown MIPS ISA");
-}
-
-static ErrorOr<uint32_t> flagsToAses(uint32_t flags) {
- uint32_t ases = flags & EF_MIPS_ARCH_ASE;
- switch (ases) {
- case 0:
- return 0;
- case EF_MIPS_MICROMIPS:
- return AFL_ASE_MICROMIPS;
- case EF_MIPS_ARCH_ASE_M16:
- return AFL_ASE_MIPS16;
- case EF_MIPS_ARCH_ASE_MDMX:
- return AFL_ASE_MDMX;
- default:
- return make_dynamic_error_code(
- StringRef("Unknown EF_MIPS_ARCH_ASE flag (0x") +
- Twine::utohexstr(ases) + ")");
- }
-}
-
-static uint32_t asesToFlags(uint32_t ases) {
- switch (ases) {
- case AFL_ASE_MICROMIPS:
- return EF_MIPS_MICROMIPS;
- case AFL_ASE_MIPS16:
- return EF_MIPS_ARCH_ASE_M16;
- case AFL_ASE_MDMX:
- return EF_MIPS_ARCH_ASE_MDMX;
- default:
- return 0;
- }
-}
-
-static ErrorOr<MipsISAs> sectionFlagsToIsa(uint8_t isaLevel, uint8_t isaRev,
- uint8_t isaExt) {
- for (const auto &p : abiIsaArchPair)
- if (p._isaLevel == isaLevel && p._isaRev == isaRev && p._isaExt == isaExt)
- return p._arch;
- return make_dynamic_error_code(
- StringRef("Unknown ISA level/revision/extension ") + Twine(isaLevel) +
- "/" + Twine(isaRev) + "/" + Twine(isaExt));
-}
-
-static std::tuple<uint8_t, uint8_t, uint32_t> isaToSectionFlags(unsigned isa) {
- for (const auto &p : abiIsaArchPair)
- if (p._arch == isa)
- return std::make_tuple(p._isaLevel, p._isaRev, p._isaExt);
- llvm_unreachable("Unknown MIPS ISA");
-}
-
-static bool checkCompatibility(const MipsAbiFlags &hdr,
- const MipsAbiFlags &sec) {
- uint32_t secIsa = ArchNone;
- switch (sec._isa) {
- case Arch32r3:
- case Arch32r5:
- secIsa = Arch32r2;
- break;
- case Arch64r3:
- case Arch64r5:
- secIsa = Arch64r2;
- break;
- default:
- secIsa = sec._isa;
- break;
- }
- if (secIsa != hdr._isa) {
- llvm::errs() << "inconsistent ISA between .MIPS.abiflags "
- "and ELF header e_flags field\n";
- return false;
- }
- if ((sec._ases & hdr._ases) != hdr._ases) {
- llvm::errs() << "inconsistent ASEs between .MIPS.abiflags "
- "and ELF header e_flags field\n";
- return false;
- }
- return true;
-}
-
-static int compareFpAbi(uint32_t fpA, uint32_t fpB) {
- if (fpA == fpB)
- return 0;
- if (fpB == Val_GNU_MIPS_ABI_FP_ANY)
- return 1;
- if (fpB == Val_GNU_MIPS_ABI_FP_64A && fpA == Val_GNU_MIPS_ABI_FP_64)
- return 1;
- if (fpB != Val_GNU_MIPS_ABI_FP_XX)
- return -1;
- if (fpA == Val_GNU_MIPS_ABI_FP_DOUBLE || fpA == Val_GNU_MIPS_ABI_FP_64 ||
- fpA == Val_GNU_MIPS_ABI_FP_64A)
- return 1;
- return -1;
-}
-
-static StringRef getFpAbiName(uint32_t fpAbi) {
- switch (fpAbi) {
- case Val_GNU_MIPS_ABI_FP_ANY:
- return "<any>";
- case Val_GNU_MIPS_ABI_FP_DOUBLE:
- return "-mdouble-float";
- case Val_GNU_MIPS_ABI_FP_SINGLE:
- return "-msingle-float";
- case Val_GNU_MIPS_ABI_FP_SOFT:
- return "-msoft-float";
- case Val_GNU_MIPS_ABI_FP_OLD_64:
- return "-mips32r2 -mfp64 (old)";
- case Val_GNU_MIPS_ABI_FP_XX:
- return "-mfpxx";
- case Val_GNU_MIPS_ABI_FP_64:
- return "-mgp32 -mfp64";
- case Val_GNU_MIPS_ABI_FP_64A:
- return "-mgp32 -mfp64 -mno-odd-spreg";
- default:
- return "<unknown>";
- }
-}
-
-static uint32_t selectFpAbiFlag(uint32_t oldFp, uint32_t newFp) {
- if (compareFpAbi(newFp, oldFp) >= 0)
- return newFp;
- if (compareFpAbi(oldFp, newFp) < 0)
- llvm::errs() << "FP ABI " << getFpAbiName(oldFp) << " is incompatible with "
- << getFpAbiName(newFp) << "\n";
- return oldFp;
-}
-
-namespace lld {
-namespace elf {
-
-template <class ELFT> bool MipsAbiInfoHandler<ELFT>::isMicroMips() const {
- assert(_abiFlags.hasValue());
- return _abiFlags->_ases & AFL_ASE_MICROMIPS;
-}
-
-template <class ELFT> bool MipsAbiInfoHandler<ELFT>::isMipsR6() const {
- assert(_abiFlags.hasValue());
- return _abiFlags->_isa == Arch32r6 || _abiFlags->_isa == Arch64r6;
-}
-
-template <class ELFT> bool MipsAbiInfoHandler<ELFT>::isFp64() const {
- assert(_abiFlags.hasValue());
- return _abiFlags->_fpAbi == Val_GNU_MIPS_ABI_FP_64 ||
- _abiFlags->_fpAbi == Val_GNU_MIPS_ABI_FP_64A;
-}
-
-template <class ELFT> bool MipsAbiInfoHandler<ELFT>::isCPicOnly() const {
- assert(_abiFlags.hasValue());
- return _abiFlags->_isCPic && !_abiFlags->_isPic;
-}
-
-template <class ELFT> uint32_t MipsAbiInfoHandler<ELFT>::getFlags() const {
- std::lock_guard<std::mutex> lock(_mutex);
- uint32_t flags = 0;
- if (_abiFlags.hasValue()) {
- flags |= isaToHeaderFlags(_abiFlags->_isa);
- flags |= asesToFlags(_abiFlags->_ases);
- flags |= _abiFlags->_abi;
- flags |= _abiFlags->_isPic ? EF_MIPS_PIC : 0u;
- flags |= _abiFlags->_isCPic ? EF_MIPS_CPIC : 0u;
- flags |= _abiFlags->_isNoReorder ? EF_MIPS_NOREORDER : 0u;
- flags |= _abiFlags->_is32BitMode ? EF_MIPS_32BITMODE : 0u;
- flags |= _abiFlags->_isNan2008 ? EF_MIPS_NAN2008 : 0u;
- }
- return flags;
-}
-
-template <class ELFT>
-llvm::Optional<typename MipsAbiInfoHandler<ELFT>::Elf_Mips_RegInfo>
-MipsAbiInfoHandler<ELFT>::getRegistersMask() const {
- std::lock_guard<std::mutex> lock(_mutex);
- return _regMask;
-}
-
-template <class ELFT>
-llvm::Optional<typename MipsAbiInfoHandler<ELFT>::Elf_Mips_ABIFlags>
-MipsAbiInfoHandler<ELFT>::getAbiFlags() const {
- std::lock_guard<std::mutex> lock(_mutex);
- if (!_hasAbiSection)
- return llvm::Optional<Elf_Mips_ABIFlags>();
-
- Elf_Mips_ABIFlags sec;
- sec.version = 0;
- std::tie(sec.isa_level, sec.isa_rev, sec.isa_ext) =
- isaToSectionFlags(_abiFlags->_isa);
- sec.gpr_size = _abiFlags->_gprSize;
- sec.cpr1_size = _abiFlags->_cpr1Size;
- sec.cpr2_size = _abiFlags->_cpr2Size;
- sec.fp_abi = _abiFlags->_fpAbi;
- sec.ases = _abiFlags->_ases;
- sec.flags1 = _abiFlags->_flags1;
- sec.flags2 = 0;
- return sec;
-}
-
-template <class ELFT> MipsAbi MipsAbiInfoHandler<ELFT>::getAbi() const {
- if (!_abiFlags.hasValue())
- return ELFT::Is64Bits ? MipsAbi::N64 : MipsAbi::O32;
- switch (_abiFlags->_abi & (EF_MIPS_ABI_O32 | EF_MIPS_ABI2)) {
- case EF_MIPS_ABI_O32:
- return MipsAbi::O32;
- case EF_MIPS_ABI2:
- return MipsAbi::N32;
- case 0:
- return MipsAbi::N64;
- default:
- llvm_unreachable("Unknown ABI flag");
- }
-}
-
-template <class ELFT>
-std::error_code
-MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags,
- const Elf_Mips_ABIFlags *newSec) {
- std::lock_guard<std::mutex> lock(_mutex);
-
- ErrorOr<MipsAbiFlags> abiFlags = createAbiFlags(newFlags, newSec);
- if (auto ec = abiFlags.getError())
- return ec;
-
- // We support three ABI: O32, N32, and N64. The last one does not have
- // the corresponding ELF flag.
- if (ELFT::Is64Bits) {
- if (abiFlags->_abi)
- return make_dynamic_error_code("Unsupported ABI");
- } else {
- if (!(abiFlags->_abi & (EF_MIPS_ABI_O32 | EF_MIPS_ABI2)))
- return make_dynamic_error_code("Unsupported ABI");
- }
-
- // ... and still do not support MIPS-16 extension.
- if (abiFlags->_ases & AFL_ASE_MIPS16)
- return make_dynamic_error_code("Unsupported extension: MIPS16");
-
- // PIC code is inherently CPIC and may not set CPIC flag explicitly.
- // Ensure that this flag will exist in the linked file.
- if (abiFlags->_isPic)
- abiFlags->_isCPic = true;
-
- // If the old set of flags is empty, use the new one as a result.
- if (!_abiFlags.hasValue()) {
- _abiFlags = *abiFlags;
- return std::error_code();
- }
-
- // Check ABI compatibility.
- if (abiFlags->_abi != _abiFlags->_abi)
- return make_dynamic_error_code("Linking modules with incompatible ABI");
-
- // Check PIC / CPIC flags compatibility.
- if (abiFlags->_isCPic != _abiFlags->_isCPic)
- llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
-
- if (!abiFlags->_isPic)
- _abiFlags->_isPic = false;
- if (abiFlags->_isCPic)
- _abiFlags->_isCPic = true;
-
- // Check mixing -mnan=2008 / -mnan=legacy modules.
- if (abiFlags->_isNan2008 != _abiFlags->_isNan2008)
- return make_dynamic_error_code(
- "Linking -mnan=2008 and -mnan=legacy modules");
-
- // Check ISA compatibility and update the extension flag.
- if (!matchMipsISA(MipsISAs(abiFlags->_isa), MipsISAs(_abiFlags->_isa))) {
- if (!matchMipsISA(MipsISAs(_abiFlags->_isa), MipsISAs(abiFlags->_isa)))
- return make_dynamic_error_code("Linking modules with incompatible ISA");
- _abiFlags->_isa = abiFlags->_isa;
- }
-
- _abiFlags->_ases |= abiFlags->_ases;
- _abiFlags->_isNoReorder = _abiFlags->_isNoReorder || abiFlags->_isNoReorder;
- _abiFlags->_is32BitMode = _abiFlags->_is32BitMode || abiFlags->_is32BitMode;
-
- _abiFlags->_fpAbi = selectFpAbiFlag(_abiFlags->_fpAbi, abiFlags->_fpAbi);
- _abiFlags->_gprSize = std::max(_abiFlags->_gprSize, abiFlags->_gprSize);
- _abiFlags->_cpr1Size = std::max(_abiFlags->_cpr1Size, abiFlags->_cpr1Size);
- _abiFlags->_cpr2Size = std::max(_abiFlags->_cpr2Size, abiFlags->_cpr2Size);
- _abiFlags->_flags1 |= abiFlags->_flags1;
-
- return std::error_code();
-}
-
-template <class ELFT>
-void MipsAbiInfoHandler<ELFT>::mergeRegistersMask(
- const Elf_Mips_RegInfo &info) {
- std::lock_guard<std::mutex> lock(_mutex);
- if (!_regMask.hasValue()) {
- _regMask = info;
- return;
- }
- _regMask->ri_gprmask = _regMask->ri_gprmask | info.ri_gprmask;
- _regMask->ri_cprmask[0] = _regMask->ri_cprmask[0] | info.ri_cprmask[0];
- _regMask->ri_cprmask[1] = _regMask->ri_cprmask[1] | info.ri_cprmask[1];
- _regMask->ri_cprmask[2] = _regMask->ri_cprmask[2] | info.ri_cprmask[2];
- _regMask->ri_cprmask[3] = _regMask->ri_cprmask[3] | info.ri_cprmask[3];
-}
-
-template <class ELFT>
-ErrorOr<MipsAbiFlags>
-MipsAbiInfoHandler<ELFT>::createAbiFlags(uint32_t flags,
- const Elf_Mips_ABIFlags *sec) {
- ErrorOr<MipsAbiFlags> hdrFlags = createAbiFromHeaderFlags(flags);
- if (auto ec = hdrFlags.getError())
- return ec;
- if (!sec)
- return *hdrFlags;
- ErrorOr<MipsAbiFlags> secFlags = createAbiFromSection(*sec);
- if (auto ec = secFlags.getError())
- return ec;
- if (!checkCompatibility(*hdrFlags, *secFlags))
- return *hdrFlags;
-
- _hasAbiSection = true;
-
- secFlags->_abi = hdrFlags->_abi;
- secFlags->_isPic = hdrFlags->_isPic;
- secFlags->_isCPic = hdrFlags->_isCPic;
- secFlags->_isNoReorder = hdrFlags->_isNoReorder;
- secFlags->_is32BitMode = hdrFlags->_is32BitMode;
- secFlags->_isNan2008 = hdrFlags->_isNan2008;
- return *secFlags;
-}
-
-template <class ELFT>
-ErrorOr<MipsAbiFlags>
-MipsAbiInfoHandler<ELFT>::createAbiFromHeaderFlags(uint32_t flags) {
- MipsAbiFlags abi;
- ErrorOr<MipsISAs> isa = headerFlagsToIsa(flags);
- if (auto ec = isa.getError())
- return ec;
- abi._isa = *isa;
-
- abi._fpAbi = Val_GNU_MIPS_ABI_FP_ANY;
- abi._cpr1Size = AFL_REG_NONE;
- abi._cpr2Size = AFL_REG_NONE;
- abi._gprSize = is32BitElfFlags(flags) ? AFL_REG_32 : AFL_REG_64;
-
- ErrorOr<uint32_t> ases = flagsToAses(flags);
- if (auto ec = ases.getError())
- return ec;
- abi._ases = *ases;
- abi._flags1 = 0;
- abi._abi = flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
- abi._isPic = flags & EF_MIPS_PIC;
- abi._isCPic = flags & EF_MIPS_CPIC;
- abi._isNoReorder = flags & EF_MIPS_NOREORDER;
- abi._is32BitMode = flags & EF_MIPS_32BITMODE;
- abi._isNan2008 = flags & EF_MIPS_NAN2008;
- return abi;
-}
-
-template <class ELFT>
-ErrorOr<MipsAbiFlags>
-MipsAbiInfoHandler<ELFT>::createAbiFromSection(const Elf_Mips_ABIFlags &sec) {
- MipsAbiFlags abi;
- ErrorOr<MipsISAs> isa =
- sectionFlagsToIsa(sec.isa_level, sec.isa_rev, sec.isa_ext);
- if (auto ec = isa.getError())
- return ec;
- abi._isa = *isa;
- abi._fpAbi = sec.fp_abi;
- abi._cpr1Size = sec.cpr1_size;
- abi._cpr2Size = sec.cpr2_size;
- abi._gprSize = sec.gpr_size;
- abi._ases = sec.ases;
- abi._flags1 = sec.flags1;
- if (sec.flags2 != 0)
- return make_dynamic_error_code("unexpected non-zero 'flags2' value");
- return abi;
-}
-
-template class MipsAbiInfoHandler<ELF32BE>;
-template class MipsAbiInfoHandler<ELF32LE>;
-template class MipsAbiInfoHandler<ELF64BE>;
-template class MipsAbiInfoHandler<ELF64LE>;
-
-}
-}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h b/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
deleted file mode 100644
index 44da29f09214..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
+++ /dev/null
@@ -1,83 +0,0 @@
-//===- lib/ReaderWriter/ELF/MipsAbiInfoHandler.h --------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_ABI_INFO_HANDLER_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_ABI_INFO_HANDLER_H
-
-#include "llvm/ADT/Optional.h"
-#include "llvm/Object/ELFTypes.h"
-#include "llvm/Support/ErrorOr.h"
-#include <mutex>
-#include <system_error>
-
-namespace lld {
-namespace elf {
-
-enum class MipsAbi { O32, N32, N64 };
-
-struct MipsAbiFlags {
- unsigned _isa = 0;
- unsigned _fpAbi = 0;
- unsigned _ases = 0;
- unsigned _flags1 = 0;
- unsigned _gprSize = 0;
- unsigned _cpr1Size = 0;
- unsigned _cpr2Size = 0;
-
- unsigned _abi = 0;
-
- bool _isPic = false;
- bool _isCPic = false;
- bool _isNoReorder = false;
- bool _is32BitMode = false;
- bool _isNan2008 = false;
-};
-
-template <class ELFT> class MipsAbiInfoHandler {
-public:
- typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
- typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
-
- MipsAbiInfoHandler() = default;
-
- bool hasMipsAbiSection() const { return _hasAbiSection; }
- bool isMicroMips() const;
- bool isMipsR6() const;
- bool isFp64() const;
- bool isCPicOnly() const;
-
- uint32_t getFlags() const;
- llvm::Optional<Elf_Mips_RegInfo> getRegistersMask() const;
- llvm::Optional<Elf_Mips_ABIFlags> getAbiFlags() const;
-
- MipsAbi getAbi() const;
-
- /// \brief Merge saved ELF header flags and the new set of flags.
- std::error_code mergeFlags(uint32_t newFlags,
- const Elf_Mips_ABIFlags *newAbi);
-
- /// \brief Merge saved and new sets of registers usage masks.
- void mergeRegistersMask(const Elf_Mips_RegInfo &info);
-
-private:
- mutable std::mutex _mutex;
- bool _hasAbiSection = false;
- llvm::Optional<MipsAbiFlags> _abiFlags;
- llvm::Optional<Elf_Mips_RegInfo> _regMask;
-
- llvm::ErrorOr<MipsAbiFlags> createAbiFlags(uint32_t flags,
- const Elf_Mips_ABIFlags *sec);
- static llvm::ErrorOr<MipsAbiFlags> createAbiFromHeaderFlags(uint32_t flags);
- static llvm::ErrorOr<MipsAbiFlags>
- createAbiFromSection(const Elf_Mips_ABIFlags &sec);
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp b/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp
deleted file mode 100644
index a7062813df42..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/Mips/CtorsOrderPass.cpp ------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsCtorsOrderPass.h"
-#include "lld/Core/Simple.h"
-#include <algorithm>
-#include <climits>
-
-using namespace lld;
-using namespace lld::elf;
-
-static bool matchCrtObjName(StringRef objName, StringRef objPath) {
- if (!objPath.endswith(".o"))
- return false;
-
- // check *<objName> case
- objPath = objPath.drop_back(2);
- if (objPath.endswith(objName))
- return true;
-
- // check *<objName>? case
- return !objPath.empty() && objPath.drop_back(1).endswith(objName);
-}
-
-static int32_t getSectionPriority(StringRef path, StringRef sectionName) {
- // Arrange .ctors/.dtors sections in the following order:
- // .ctors from crtbegin.o or crtbegin?.o
- // .ctors from regular object files
- // .ctors.* (sorted) from regular object files
- // .ctors from crtend.o or crtend?.o
-
- if (matchCrtObjName("crtbegin", path))
- return std::numeric_limits<int32_t>::min();
- if (matchCrtObjName("crtend", path))
- return std::numeric_limits<int32_t>::max();
-
- StringRef num = sectionName.drop_front().rsplit('.').second;
-
- int32_t priority = std::numeric_limits<int32_t>::min() + 1;
- if (!num.empty())
- num.getAsInteger(10, priority);
-
- return priority;
-}
-
-std::error_code MipsCtorsOrderPass::perform(SimpleFile &f) {
- auto definedAtoms = f.definedAtoms();
-
- auto last = std::stable_partition(definedAtoms.begin(), definedAtoms.end(),
- [](const DefinedAtom *atom) {
- if (atom->sectionChoice() != DefinedAtom::sectionCustomRequired)
- return false;
-
- StringRef name = atom->customSectionName();
- return name.startswith(".ctors") || name.startswith(".dtors");
- });
-
- std::stable_sort(definedAtoms.begin(), last,
- [](const DefinedAtom *left, const DefinedAtom *right) {
- StringRef leftSec = left->customSectionName();
- StringRef rightSec = right->customSectionName();
-
- int32_t leftPriority = getSectionPriority(left->file().path(), leftSec);
- int32_t rightPriority = getSectionPriority(right->file().path(), rightSec);
-
- return leftPriority < rightPriority;
- });
-
- return std::error_code();
-}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h b/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h
deleted file mode 100644
index 5b12b7de0fa2..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h ---------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_CTORS_ORDER_PASS_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_CTORS_ORDER_PASS_H
-
-#include "lld/Core/Pass.h"
-
-namespace lld {
-namespace elf {
-/// \brief This pass sorts atoms in .{ctors,dtors}.<priority> sections.
-class MipsCtorsOrderPass : public Pass {
-public:
- std::error_code perform(SimpleFile &mergedFile) override;
-};
-}
-}
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h b/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h
deleted file mode 100644
index 480c69cf4600..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h
+++ /dev/null
@@ -1,124 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h -----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_TABLE_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_TABLE_H
-
-#include "TargetLayout.h"
-#include "SectionChunks.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT> class MipsTargetLayout;
-
-template <class ELFT> class MipsDynamicTable : public DynamicTable<ELFT> {
-public:
- MipsDynamicTable(const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
- : DynamicTable<ELFT>(ctx, layout, ".dynamic",
- TargetLayout<ELFT>::ORDER_DYNAMIC),
- _targetLayout(layout) {}
-
- void createDefaultEntries() override {
- DynamicTable<ELFT>::createDefaultEntries();
-
- // Version id for the Runtime Linker Interface.
- this->addEntry(DT_MIPS_RLD_VERSION, 1);
-
- // The .rld_map section address.
- if (this->_ctx.getOutputELFType() == ET_EXEC) {
- _dt_rldmap = this->addEntry(DT_MIPS_RLD_MAP, 0);
- _dt_rldmaprel = this->addEntry(DT_MIPS_RLD_MAP_REL, 0);
- }
-
- // MIPS flags.
- this->addEntry(DT_MIPS_FLAGS, RHF_NOTPOT);
-
- // The base address of the segment.
- _dt_baseaddr = this->addEntry(DT_MIPS_BASE_ADDRESS, 0);
-
- // Number of local global offset table entries.
- _dt_localgot = this->addEntry(DT_MIPS_LOCAL_GOTNO, 0);
-
- // Number of entries in the .dynsym section.
- _dt_symtabno = this->addEntry(DT_MIPS_SYMTABNO, 0);
-
- // The index of the first dynamic symbol table entry that corresponds
- // to an entry in the global offset table.
- _dt_gotsym = this->addEntry(DT_MIPS_GOTSYM, 0);
-
- // Address of the .got section.
- _dt_pltgot = this->addEntry(DT_PLTGOT, 0);
- }
-
- void doPreFlight() override {
- DynamicTable<ELFT>::doPreFlight();
-
- if (_targetLayout.findOutputSection(".MIPS.options")) {
- _dt_options = this->addEntry(DT_MIPS_OPTIONS, 0);
- }
- }
-
- void updateDynamicTable() override {
- DynamicTable<ELFT>::updateDynamicTable();
-
- // Assign the minimum segment address to the DT_MIPS_BASE_ADDRESS tag.
- auto baseAddr = std::numeric_limits<uint64_t>::max();
- for (auto si : _targetLayout.segments())
- if (si->segmentType() != llvm::ELF::PT_NULL)
- baseAddr = std::min(baseAddr, si->virtualAddr());
- this->_entries[_dt_baseaddr].d_un.d_val = baseAddr;
-
- auto &got = _targetLayout.getGOTSection();
-
- this->_entries[_dt_symtabno].d_un.d_val = this->getSymbolTable()->size();
- this->_entries[_dt_gotsym].d_un.d_val =
- this->getSymbolTable()->size() - got.getGlobalCount();
- this->_entries[_dt_localgot].d_un.d_val = got.getLocalCount();
- this->_entries[_dt_pltgot].d_un.d_ptr = got.virtualAddr();
-
- if (const auto *sec = _targetLayout.findOutputSection(".MIPS.options"))
- this->_entries[_dt_options].d_un.d_ptr = sec->virtualAddr();
-
- if (const auto *sec = _targetLayout.findOutputSection(".rld_map")) {
- this->_entries[_dt_rldmap].d_un.d_ptr = sec->virtualAddr();
- this->_entries[_dt_rldmaprel].d_un.d_ptr =
- sec->virtualAddr() -
- (this->virtualAddr() +
- _dt_rldmaprel * sizeof(typename DynamicTable<ELFT>::Elf_Dyn));
- }
- }
-
- int64_t getGotPltTag() override { return DT_MIPS_PLTGOT; }
-
-protected:
- /// \brief Adjust the symbol's value for microMIPS code.
- uint64_t getAtomVirtualAddress(const AtomLayout *al) const override {
- if (const auto *da = dyn_cast<DefinedAtom>(al->_atom))
- if (da->codeModel() == DefinedAtom::codeMipsMicro ||
- da->codeModel() == DefinedAtom::codeMipsMicroPIC)
- return al->_virtualAddr | 1;
- return al->_virtualAddr;
- }
-
-private:
- std::size_t _dt_symtabno;
- std::size_t _dt_localgot;
- std::size_t _dt_gotsym;
- std::size_t _dt_pltgot;
- std::size_t _dt_baseaddr;
- std::size_t _dt_options;
- std::size_t _dt_rldmap;
- std::size_t _dt_rldmaprel;
- MipsTargetLayout<ELFT> &_targetLayout;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp b/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp
deleted file mode 100644
index b081b63d77f7..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-//===- lib/ReaderWriter/ELF/MipsELFFile.cpp -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsELFFile.h"
-#include "MipsTargetHandler.h"
-#include "llvm/ADT/StringExtras.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-MipsELFDefinedAtom<ELFT>::MipsELFDefinedAtom(
- const MipsELFFile<ELFT> &file, StringRef symbolName, StringRef sectionName,
- const Elf_Sym *symbol, const Elf_Shdr *section,
- ArrayRef<uint8_t> contentData, unsigned int referenceStart,
- unsigned int referenceEnd, std::vector<ELFReference<ELFT> *> &referenceList)
- : ELFDefinedAtom<ELFT>(file, symbolName, sectionName, symbol, section,
- contentData, referenceStart, referenceEnd,
- referenceList) {}
-
-template <class ELFT>
-const MipsELFFile<ELFT> &MipsELFDefinedAtom<ELFT>::file() const {
- return static_cast<const MipsELFFile<ELFT> &>(this->_owningFile);
-}
-
-template <class ELFT>
-DefinedAtom::CodeModel MipsELFDefinedAtom<ELFT>::codeModel() const {
- switch (this->_symbol->st_other & llvm::ELF::STO_MIPS_MIPS16) {
- case llvm::ELF::STO_MIPS_MIPS16:
- return DefinedAtom::codeMips16;
- case llvm::ELF::STO_MIPS_PIC:
- return DefinedAtom::codeMipsPIC;
- case llvm::ELF::STO_MIPS_MICROMIPS:
- return DefinedAtom::codeMipsMicro;
- case llvm::ELF::STO_MIPS_MICROMIPS | llvm::ELF::STO_MIPS_PIC:
- return DefinedAtom::codeMipsMicroPIC;
- default:
- return DefinedAtom::codeNA;
- }
-}
-
-template <class ELFT> bool MipsELFDefinedAtom<ELFT>::isPIC() const {
- return file().isPIC() || codeModel() == DefinedAtom::codeMipsMicroPIC ||
- codeModel() == DefinedAtom::codeMipsPIC;
-}
-
-template class MipsELFDefinedAtom<ELF32BE>;
-template class MipsELFDefinedAtom<ELF32LE>;
-template class MipsELFDefinedAtom<ELF64BE>;
-template class MipsELFDefinedAtom<ELF64LE>;
-
-template <class ELFT> static bool isMips64EL() {
- return ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
-}
-
-template <class ELFT, bool isRela>
-static uint32_t
-extractTag(const llvm::object::Elf_Rel_Impl<ELFT, isRela> &rel) {
- return (rel.getType(isMips64EL<ELFT>()) & 0xffffff00) >> 8;
-}
-
-template <class ELFT>
-MipsELFReference<ELFT>::MipsELFReference(uint64_t symValue, const Elf_Rela &rel)
- : ELFReference<ELFT>(&rel, rel.r_offset - symValue,
- Reference::KindArch::Mips,
- rel.getType(isMips64EL<ELFT>()) & 0xff,
- rel.getSymbol(isMips64EL<ELFT>())),
- _tag(extractTag(rel)) {}
-
-template <class ELFT>
-MipsELFReference<ELFT>::MipsELFReference(uint64_t symValue, const Elf_Rel &rel)
- : ELFReference<ELFT>(rel.r_offset - symValue, Reference::KindArch::Mips,
- rel.getType(isMips64EL<ELFT>()) & 0xff,
- rel.getSymbol(isMips64EL<ELFT>())),
- _tag(extractTag(rel)) {}
-
-template class MipsELFReference<ELF32BE>;
-template class MipsELFReference<ELF32LE>;
-template class MipsELFReference<ELF64BE>;
-template class MipsELFReference<ELF64LE>;
-
-template <class ELFT>
-MipsELFFile<ELFT>::MipsELFFile(std::unique_ptr<MemoryBuffer> mb,
- ELFLinkingContext &ctx)
- : ELFFile<ELFT>(std::move(mb), ctx) {}
-
-template <class ELFT> bool MipsELFFile<ELFT>::isPIC() const {
- return this->_objFile->getHeader()->e_flags & llvm::ELF::EF_MIPS_PIC;
-}
-
-template <class ELFT> std::error_code MipsELFFile<ELFT>::doParse() {
- if (std::error_code ec = ELFFile<ELFT>::doParse())
- return ec;
- // Retrieve some auxiliary data like GP value, TLS section address etc
- // from the object file.
- return readAuxData();
-}
-
-template <class ELFT>
-ELFDefinedAtom<ELFT> *MipsELFFile<ELFT>::createDefinedAtom(
- StringRef symName, StringRef sectionName, const Elf_Sym *sym,
- const Elf_Shdr *sectionHdr, ArrayRef<uint8_t> contentData,
- unsigned int referenceStart, unsigned int referenceEnd,
- std::vector<ELFReference<ELFT> *> &referenceList) {
- return new (this->_readerStorage) MipsELFDefinedAtom<ELFT>(
- *this, symName, sectionName, sym, sectionHdr, contentData, referenceStart,
- referenceEnd, referenceList);
-}
-
-template <class ELFT>
-const typename MipsELFFile<ELFT>::Elf_Shdr *
-MipsELFFile<ELFT>::findSectionByType(uint64_t type) const {
- for (const Elf_Shdr &section : this->_objFile->sections())
- if (section.sh_type == type)
- return &section;
- return nullptr;
-}
-
-template <class ELFT>
-const typename MipsELFFile<ELFT>::Elf_Shdr *
-MipsELFFile<ELFT>::findSectionByFlags(uint64_t flags) const {
- for (const Elf_Shdr &section : this->_objFile->sections())
- if (section.sh_flags & flags)
- return &section;
- return nullptr;
-}
-
-template <class ELFT>
-ErrorOr<const typename MipsELFFile<ELFT>::Elf_Mips_RegInfo *>
-MipsELFFile<ELFT>::findRegInfoSec() const {
- using namespace llvm::ELF;
- if (const Elf_Shdr *sec = findSectionByType(SHT_MIPS_OPTIONS)) {
- auto contents = this->getSectionContents(sec);
- if (std::error_code ec = contents.getError())
- return ec;
-
- ArrayRef<uint8_t> raw = contents.get();
- while (!raw.empty()) {
- if (raw.size() < sizeof(Elf_Mips_Options))
- return make_dynamic_error_code(
- StringRef("Invalid size of MIPS_OPTIONS section"));
-
- const auto *opt = reinterpret_cast<const Elf_Mips_Options *>(raw.data());
- if (opt->kind == ODK_REGINFO)
- return &opt->getRegInfo();
- raw = raw.slice(opt->size);
- }
- } else if (const Elf_Shdr *sec = findSectionByType(SHT_MIPS_REGINFO)) {
- auto contents = this->getSectionContents(sec);
- if (std::error_code ec = contents.getError())
- return ec;
-
- ArrayRef<uint8_t> raw = contents.get();
- if (raw.size() != sizeof(Elf_Mips_RegInfo))
- return make_dynamic_error_code(
- StringRef("Invalid size of MIPS_REGINFO section"));
-
- return reinterpret_cast<const Elf_Mips_RegInfo *>(raw.data());
- }
- return nullptr;
-}
-
-template <class ELFT>
-ErrorOr<const typename MipsELFFile<ELFT>::Elf_Mips_ABIFlags *>
-MipsELFFile<ELFT>::findAbiFlagsSec() const {
- const Elf_Shdr *sec = findSectionByType(SHT_MIPS_ABIFLAGS);
- if (!sec)
- return nullptr;
-
- auto contents = this->getSectionContents(sec);
- if (std::error_code ec = contents.getError())
- return ec;
-
- ArrayRef<uint8_t> raw = contents.get();
- if (raw.size() != sizeof(Elf_Mips_ABIFlags))
- return make_dynamic_error_code(
- StringRef("Invalid size of MIPS_ABIFLAGS section"));
-
- const auto *abi = reinterpret_cast<const Elf_Mips_ABIFlags *>(raw.data());
- if (abi->version != 0)
- return make_dynamic_error_code(
- StringRef(".MIPS.abiflags section has unsupported version '") +
- llvm::utostr(abi->version) + "'");
-
- return abi;
-}
-
-template <class ELFT> std::error_code MipsELFFile<ELFT>::readAuxData() {
- using namespace llvm::ELF;
- if (const Elf_Shdr *sec = findSectionByFlags(SHF_TLS)) {
- _tpOff = sec->sh_addr + TP_OFFSET;
- _dtpOff = sec->sh_addr + DTP_OFFSET;
- }
-
- auto &handler =
- static_cast<MipsTargetHandler<ELFT> &>(this->_ctx.getTargetHandler());
- auto &abi = handler.getAbiInfoHandler();
-
- ErrorOr<const Elf_Mips_RegInfo *> regInfoSec = findRegInfoSec();
- if (auto ec = regInfoSec.getError())
- return ec;
- if (const Elf_Mips_RegInfo *regInfo = regInfoSec.get()) {
- abi.mergeRegistersMask(*regInfo);
- _gp0 = regInfo->ri_gp_value;
- }
-
- ErrorOr<const Elf_Mips_ABIFlags *> abiFlagsSec = findAbiFlagsSec();
- if (auto ec = abiFlagsSec.getError())
- return ec;
-
- const Elf_Ehdr *hdr = this->_objFile->getHeader();
- if (std::error_code ec = abi.mergeFlags(hdr->e_flags, abiFlagsSec.get()))
- return ec;
-
- return std::error_code();
-}
-
-template <class ELFT>
-void MipsELFFile<ELFT>::createRelocationReferences(
- const Elf_Sym *symbol, ArrayRef<uint8_t> content,
- range<const Elf_Rela *> rels) {
- const auto value = this->getSymbolValue(symbol);
- unsigned numInGroup = 0;
- for (const auto &rel : rels) {
- if (rel.r_offset < value || value + content.size() <= rel.r_offset) {
- numInGroup = 0;
- continue;
- }
- if (numInGroup > 0) {
- auto &last =
- *static_cast<MipsELFReference<ELFT> *>(this->_references.back());
- if (last.offsetInAtom() + value == rel.r_offset) {
- last.setTag(last.tag() |
- (rel.getType(isMips64EL<ELFT>()) << 8 * (numInGroup - 1)));
- ++numInGroup;
- continue;
- }
- }
- auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, rel);
- this->addReferenceToSymbol(r, symbol);
- this->_references.push_back(r);
- numInGroup = 1;
- }
-}
-
-template <class ELFT>
-void MipsELFFile<ELFT>::createRelocationReferences(const Elf_Sym *symbol,
- ArrayRef<uint8_t> symContent,
- ArrayRef<uint8_t> secContent,
- const Elf_Shdr *relSec) {
- const Elf_Shdr *symtab = *this->_objFile->getSection(relSec->sh_link);
- auto rels = this->_objFile->rels(relSec);
- const auto value = this->getSymbolValue(symbol);
- for (const Elf_Rel *rit = rels.begin(), *eit = rels.end(); rit != eit;
- ++rit) {
- if (rit->r_offset < value || value + symContent.size() <= rit->r_offset)
- continue;
-
- auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, *rit);
- this->addReferenceToSymbol(r, symbol);
- this->_references.push_back(r);
-
- auto addend = readAddend(*rit, secContent);
- auto pairRelType = getPairRelocation(symtab, *rit);
- if (pairRelType != llvm::ELF::R_MIPS_NONE) {
- addend <<= 16;
- auto mit = findMatchingRelocation(pairRelType, rit, eit);
- if (mit != eit)
- addend += int16_t(readAddend(*mit, secContent));
- else
- // FIXME (simon): Show detailed warning.
- llvm::errs() << "lld warning: cannot matching LO16 relocation\n";
- }
- this->_references.back()->setAddend(addend);
- }
-}
-
-template <class ELFT>
-static uint8_t
-getPrimaryType(const llvm::object::Elf_Rel_Impl<ELFT, false> &rel) {
- return rel.getType(isMips64EL<ELFT>()) & 0xff;
-}
-
-template <class ELFT>
-Reference::Addend
-MipsELFFile<ELFT>::readAddend(const Elf_Rel &ri,
- const ArrayRef<uint8_t> content) const {
- return readMipsRelocAddend<ELFT>(getPrimaryType(ri),
- content.data() + ri.r_offset);
-}
-
-template <class ELFT>
-uint32_t MipsELFFile<ELFT>::getPairRelocation(const Elf_Shdr *symtab,
- const Elf_Rel &rel) const {
- switch (getPrimaryType(rel)) {
- case llvm::ELF::R_MIPS_HI16:
- return llvm::ELF::R_MIPS_LO16;
- case llvm::ELF::R_MIPS_PCHI16:
- return llvm::ELF::R_MIPS_PCLO16;
- case llvm::ELF::R_MIPS_GOT16:
- if (isLocalBinding(symtab, rel))
- return llvm::ELF::R_MIPS_LO16;
- break;
- case llvm::ELF::R_MICROMIPS_HI16:
- return llvm::ELF::R_MICROMIPS_LO16;
- case llvm::ELF::R_MICROMIPS_GOT16:
- if (isLocalBinding(symtab, rel))
- return llvm::ELF::R_MICROMIPS_LO16;
- break;
- default:
- // Nothing to do.
- break;
- }
- return llvm::ELF::R_MIPS_NONE;
-}
-
-template <class ELFT>
-const typename MipsELFFile<ELFT>::Elf_Rel *
-MipsELFFile<ELFT>::findMatchingRelocation(uint32_t pairRelType,
- const Elf_Rel *rit,
- const Elf_Rel *eit) const {
- return std::find_if(rit, eit, [&](const Elf_Rel &rel) {
- return getPrimaryType(rel) == pairRelType &&
- rel.getSymbol(isMips64EL<ELFT>()) ==
- rit->getSymbol(isMips64EL<ELFT>());
- });
-}
-
-template <class ELFT>
-bool MipsELFFile<ELFT>::isLocalBinding(const Elf_Shdr *symtab,
- const Elf_Rel &rel) const {
- return this->_objFile->getSymbol(symtab, rel.getSymbol(isMips64EL<ELFT>()))
- ->getBinding() == llvm::ELF::STB_LOCAL;
-}
-
-template class MipsELFFile<ELF32BE>;
-template class MipsELFFile<ELF32LE>;
-template class MipsELFFile<ELF64BE>;
-template class MipsELFFile<ELF64LE>;
-
-} // elf
-} // lld
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFFile.h b/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
deleted file mode 100644
index 934934b539cc..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
+++ /dev/null
@@ -1,126 +0,0 @@
-//===- lib/ReaderWriter/ELF/MipsELFFile.h ---------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_FILE_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_FILE_H
-
-#include "ELFReader.h"
-#include "MipsLinkingContext.h"
-#include "MipsRelocationHandler.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT> class MipsELFFile;
-
-template <class ELFT>
-class MipsELFDefinedAtom : public ELFDefinedAtom<ELFT> {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
-
-public:
- MipsELFDefinedAtom(const MipsELFFile<ELFT> &file, StringRef symbolName,
- StringRef sectionName, const Elf_Sym *symbol,
- const Elf_Shdr *section, ArrayRef<uint8_t> contentData,
- unsigned int referenceStart, unsigned int referenceEnd,
- std::vector<ELFReference<ELFT> *> &referenceList);
-
- const MipsELFFile<ELFT>& file() const override;
- DefinedAtom::CodeModel codeModel() const override;
-
- bool isPIC() const;
-};
-
-template <class ELFT> class MipsELFReference : public ELFReference<ELFT> {
- typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
-
-public:
- MipsELFReference(uint64_t symValue, const Elf_Rela &rel);
- MipsELFReference(uint64_t symValue, const Elf_Rel &rel);
-
- uint32_t tag() const override { return _tag; }
- void setTag(uint32_t tag) { _tag = tag; }
-
-private:
- uint32_t _tag;
-};
-
-template <class ELFT> class MipsELFFile : public ELFFile<ELFT> {
-public:
- MipsELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
-
- bool isPIC() const;
-
- /// \brief gp register value stored in the .reginfo section.
- int64_t getGP0() const { return _gp0; }
-
- /// \brief .tdata section address plus fixed offset.
- uint64_t getTPOffset() const { return _tpOff; }
- uint64_t getDTPOffset() const { return _dtpOff; }
-
-protected:
- std::error_code doParse() override;
-
-private:
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
-
- enum { TP_OFFSET = 0x7000, DTP_OFFSET = 0x8000 };
-
- int64_t _gp0 = 0;
- uint64_t _tpOff = 0;
- uint64_t _dtpOff = 0;
-
- ELFDefinedAtom<ELFT> *
- createDefinedAtom(StringRef symName, StringRef sectionName,
- const Elf_Sym *sym, const Elf_Shdr *sectionHdr,
- ArrayRef<uint8_t> contentData, unsigned int referenceStart,
- unsigned int referenceEnd,
- std::vector<ELFReference<ELFT> *> &referenceList) override;
-
- void createRelocationReferences(const Elf_Sym *symbol,
- ArrayRef<uint8_t> content,
- range<const Elf_Rela *> rels) override;
- void createRelocationReferences(const Elf_Sym *symbol,
- ArrayRef<uint8_t> symContent,
- ArrayRef<uint8_t> secContent,
- const Elf_Shdr *RelSec) override;
-
- const Elf_Shdr *findSectionByType(uint64_t type) const;
- const Elf_Shdr *findSectionByFlags(uint64_t flags) const;
-
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
- typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
- typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
- typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
-
- ErrorOr<const Elf_Mips_RegInfo *> findRegInfoSec() const;
- ErrorOr<const Elf_Mips_ABIFlags*> findAbiFlagsSec() const;
-
- std::error_code readAuxData();
-
- Reference::Addend readAddend(const Elf_Rel &ri,
- const ArrayRef<uint8_t> content) const;
-
- uint32_t getPairRelocation(const Elf_Shdr *Symtab, const Elf_Rel &rel) const;
-
- const Elf_Rel *findMatchingRelocation(uint32_t pairRelType,
- const Elf_Rel *rit,
- const Elf_Rel *eit) const;
-
- bool isLocalBinding(const Elf_Shdr *Symtab, const Elf_Rel &rel) const;
-};
-
-} // elf
-} // lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp b/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp
deleted file mode 100644
index b97a4f5a9070..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp -----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsDynamicTable.h"
-#include "MipsELFWriters.h"
-#include "MipsLinkingContext.h"
-#include "MipsTargetHandler.h"
-#include "MipsTargetLayout.h"
-
-namespace {
-class MipsDynamicAtom : public lld::elf::DynamicAtom {
-public:
- MipsDynamicAtom(const lld::File &f) : DynamicAtom(f) {}
-
- ContentPermissions permissions() const override { return permR__; }
-};
-}
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-MipsELFWriter<ELFT>::MipsELFWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &targetLayout,
- const MipsAbiInfoHandler<ELFT> &abiInfo)
- : _ctx(ctx), _targetLayout(targetLayout), _abiInfo(abiInfo) {}
-
-template <class ELFT>
-void MipsELFWriter<ELFT>::setELFHeader(ELFHeader<ELFT> &elfHeader) {
- elfHeader.e_version(1);
- elfHeader.e_ident(llvm::ELF::EI_VERSION, llvm::ELF::EV_CURRENT);
- elfHeader.e_ident(llvm::ELF::EI_OSABI, llvm::ELF::ELFOSABI_NONE);
-
- unsigned char abiVer = 0;
- if (_ctx.getOutputELFType() == ET_EXEC && _abiInfo.isCPicOnly())
- abiVer = 1;
- if (_abiInfo.isFp64())
- abiVer = 3;
-
- elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, abiVer);
- elfHeader.e_flags(_abiInfo.getFlags());
-}
-
-template <class ELFT>
-void MipsELFWriter<ELFT>::finalizeMipsRuntimeAtomValues() {
- auto gotSection = _targetLayout.findOutputSection(".got");
- auto got = gotSection ? gotSection->virtualAddr() : 0;
- auto gp = gotSection ? got + _targetLayout.getGPOffset() : 0;
-
- setAtomValue("_gp", gp);
- setAtomValue("_gp_disp", gp);
- setAtomValue("__gnu_local_gp", gp);
-
- if (_ctx.isDynamic() && _ctx.getOutputELFType() == ET_EXEC)
- setAtomValue("_DYNAMIC_LINKING", 1);
-}
-
-template <class ELFT>
-std::unique_ptr<RuntimeFile<ELFT>> MipsELFWriter<ELFT>::createRuntimeFile() {
- auto file = llvm::make_unique<RuntimeFile<ELFT>>(_ctx, "Mips runtime file");
- file->addAbsoluteAtom("_gp");
- file->addAbsoluteAtom("_gp_disp");
- file->addAbsoluteAtom("__gnu_local_gp");
- if (_ctx.isDynamic()) {
- file->addAtom(*new (file->allocator()) MipsDynamicAtom(*file));
- if (_ctx.getOutputELFType() == ET_EXEC)
- file->addAbsoluteAtom("_DYNAMIC_LINKING");
- }
- return file;
-}
-
-template <class ELFT>
-unique_bump_ptr<Section<ELFT>>
-MipsELFWriter<ELFT>::createOptionsSection(llvm::BumpPtrAllocator &alloc) {
- typedef unique_bump_ptr<Section<ELFT>> Ptr;
- const auto &regMask = _abiInfo.getRegistersMask();
- if (!regMask.hasValue())
- return Ptr();
- return ELFT::Is64Bits
- ? Ptr(new (alloc)
- MipsOptionsSection<ELFT>(_ctx, _targetLayout, *regMask))
- : Ptr(new (alloc)
- MipsReginfoSection<ELFT>(_ctx, _targetLayout, *regMask));
-}
-
-template <class ELFT>
-unique_bump_ptr<Section<ELFT>>
-MipsELFWriter<ELFT>::createAbiFlagsSection(llvm::BumpPtrAllocator &alloc) {
- typedef unique_bump_ptr<Section<ELFT>> Ptr;
- const auto &abi = _abiInfo.getAbiFlags();
- if (!abi.hasValue())
- return Ptr();
- return Ptr(new (alloc) MipsAbiFlagsSection<ELFT>(_ctx, _targetLayout, *abi));
-}
-
-template <class ELFT>
-void MipsELFWriter<ELFT>::setAtomValue(StringRef name, uint64_t value) {
- AtomLayout *atom = _targetLayout.findAbsoluteAtom(name);
- assert(atom);
- atom->_virtualAddr = value;
-}
-
-template <class ELFT>
-MipsDynamicLibraryWriter<ELFT>::MipsDynamicLibraryWriter(
- MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
- const MipsAbiInfoHandler<ELFT> &abiInfo)
- : DynamicLibraryWriter<ELFT>(ctx, layout),
- _writeHelper(ctx, layout, abiInfo), _targetLayout(layout) {}
-
-template <class ELFT>
-void MipsDynamicLibraryWriter<ELFT>::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
- result.push_back(_writeHelper.createRuntimeFile());
-}
-
-template <class ELFT>
-void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
- DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues();
- _writeHelper.finalizeMipsRuntimeAtomValues();
-}
-
-template <class ELFT>
-void MipsDynamicLibraryWriter<ELFT>::createDefaultSections() {
- DynamicLibraryWriter<ELFT>::createDefaultSections();
- _reginfo = _writeHelper.createOptionsSection(this->_alloc);
- if (_reginfo)
- this->_layout.addSection(_reginfo.get());
- _abiFlags = _writeHelper.createAbiFlagsSection(this->_alloc);
- if (_abiFlags)
- this->_layout.addSection(_abiFlags.get());
-}
-
-template <class ELFT>
-std::error_code MipsDynamicLibraryWriter<ELFT>::setELFHeader() {
- DynamicLibraryWriter<ELFT>::setELFHeader();
- _writeHelper.setELFHeader(*this->_elfHeader);
- return std::error_code();
-}
-
-template <class ELFT>
-unique_bump_ptr<SymbolTable<ELFT>>
-MipsDynamicLibraryWriter<ELFT>::createSymbolTable() {
- return unique_bump_ptr<SymbolTable<ELFT>>(
- new (this->_alloc) MipsSymbolTable<ELFT>(this->_ctx));
-}
-
-template <class ELFT>
-unique_bump_ptr<DynamicTable<ELFT>>
-MipsDynamicLibraryWriter<ELFT>::createDynamicTable() {
- return unique_bump_ptr<DynamicTable<ELFT>>(
- new (this->_alloc) MipsDynamicTable<ELFT>(this->_ctx, _targetLayout));
-}
-
-template <class ELFT>
-unique_bump_ptr<DynamicSymbolTable<ELFT>>
-MipsDynamicLibraryWriter<ELFT>::createDynamicSymbolTable() {
- return unique_bump_ptr<DynamicSymbolTable<ELFT>>(new (
- this->_alloc) MipsDynamicSymbolTable<ELFT>(this->_ctx, _targetLayout));
-}
-
-template class MipsDynamicLibraryWriter<ELF32BE>;
-template class MipsDynamicLibraryWriter<ELF32LE>;
-template class MipsDynamicLibraryWriter<ELF64BE>;
-template class MipsDynamicLibraryWriter<ELF64LE>;
-
-template <class ELFT>
-MipsExecutableWriter<ELFT>::MipsExecutableWriter(
- MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
- const MipsAbiInfoHandler<ELFT> &abiInfo)
- : ExecutableWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout, abiInfo),
- _targetLayout(layout) {}
-
-template <class ELFT>
-std::error_code MipsExecutableWriter<ELFT>::setELFHeader() {
- std::error_code ec = ExecutableWriter<ELFT>::setELFHeader();
- if (ec)
- return ec;
-
- StringRef entryName = this->_ctx.entrySymbolName();
- if (const AtomLayout *al = this->_layout.findAtomLayoutByName(entryName)) {
- const auto *ea = cast<DefinedAtom>(al->_atom);
- if (ea->codeModel() == DefinedAtom::codeMipsMicro ||
- ea->codeModel() == DefinedAtom::codeMipsMicroPIC)
- // Adjust entry symbol value if this symbol is microMIPS encoded.
- this->_elfHeader->e_entry(al->_virtualAddr | 1);
- }
-
- _writeHelper.setELFHeader(*this->_elfHeader);
- return std::error_code();
-}
-
-template <class ELFT>
-void MipsExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
- // MIPS ABI requires to add to dynsym even undefined symbols
- // if they have a corresponding entries in a global part of GOT.
- for (auto sec : this->_layout.sections())
- if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
- for (const auto &atom : section->atoms()) {
- if (_targetLayout.getGOTSection().hasGlobalGOTEntry(atom->_atom)) {
- this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
- atom->_virtualAddr, atom);
- continue;
- }
-
- const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom);
- if (!da)
- continue;
-
- if (da->dynamicExport() != DefinedAtom::dynamicExportAlways &&
- !this->_ctx.isDynamicallyExportedSymbol(da->name()) &&
- !(this->_ctx.shouldExportDynamic() &&
- da->scope() == Atom::Scope::scopeGlobal))
- continue;
-
- this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
- atom->_virtualAddr, atom);
- }
-
- for (const UndefinedAtom *a : file.undefined())
- // FIXME (simon): Consider to move this check to the
- // MipsELFUndefinedAtom class method. That allows to
- // handle more complex coditions in the future.
- if (_targetLayout.getGOTSection().hasGlobalGOTEntry(a))
- this->_dynamicSymbolTable->addSymbol(a, ELF::SHN_UNDEF);
-
- // Skip our immediate parent class method
- // ExecutableWriter<ELFT>::buildDynamicSymbolTable because we replaced it
- // with our own version. Call OutputELFWriter directly.
- OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
-}
-
-template <class ELFT>
-void MipsExecutableWriter<ELFT>::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter<ELFT>::createImplicitFiles(result);
- result.push_back(_writeHelper.createRuntimeFile());
-}
-
-template <class ELFT>
-void MipsExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
- // Finalize the atom values that are part of the parent.
- ExecutableWriter<ELFT>::finalizeDefaultAtomValues();
- _writeHelper.finalizeMipsRuntimeAtomValues();
-}
-
-template <class ELFT> void MipsExecutableWriter<ELFT>::createDefaultSections() {
- ExecutableWriter<ELFT>::createDefaultSections();
- _reginfo = _writeHelper.createOptionsSection(this->_alloc);
- if (_reginfo)
- this->_layout.addSection(_reginfo.get());
- _abiFlags = _writeHelper.createAbiFlagsSection(this->_alloc);
- if (_abiFlags)
- this->_layout.addSection(_abiFlags.get());
-}
-
-template <class ELFT>
-unique_bump_ptr<SymbolTable<ELFT>>
-MipsExecutableWriter<ELFT>::createSymbolTable() {
- return unique_bump_ptr<SymbolTable<ELFT>>(
- new (this->_alloc) MipsSymbolTable<ELFT>(this->_ctx));
-}
-
-/// \brief create dynamic table
-template <class ELFT>
-unique_bump_ptr<DynamicTable<ELFT>>
-MipsExecutableWriter<ELFT>::createDynamicTable() {
- return unique_bump_ptr<DynamicTable<ELFT>>(
- new (this->_alloc) MipsDynamicTable<ELFT>(this->_ctx, _targetLayout));
-}
-
-/// \brief create dynamic symbol table
-template <class ELFT>
-unique_bump_ptr<DynamicSymbolTable<ELFT>>
-MipsExecutableWriter<ELFT>::createDynamicSymbolTable() {
- return unique_bump_ptr<DynamicSymbolTable<ELFT>>(new (
- this->_alloc) MipsDynamicSymbolTable<ELFT>(this->_ctx, _targetLayout));
-}
-
-template class MipsExecutableWriter<ELF32BE>;
-template class MipsExecutableWriter<ELF32LE>;
-template class MipsExecutableWriter<ELF64BE>;
-template class MipsExecutableWriter<ELF64LE>;
-
-} // elf
-} // lld
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h b/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
deleted file mode 100644
index 31b84f947c95..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
+++ /dev/null
@@ -1,102 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsELFWriters.h -------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_WRITERS_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_WRITERS_H
-
-#include "DynamicLibraryWriter.h"
-#include "ExecutableWriter.h"
-#include "MipsAbiInfoHandler.h"
-#include "MipsLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT> class MipsTargetLayout;
-
-template <typename ELFT> class MipsELFWriter {
-public:
- MipsELFWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
- const MipsAbiInfoHandler<ELFT> &abiInfo);
-
- void setELFHeader(ELFHeader<ELFT> &elfHeader);
-
- void finalizeMipsRuntimeAtomValues();
-
- std::unique_ptr<RuntimeFile<ELFT>> createRuntimeFile();
- unique_bump_ptr<Section<ELFT>>
- createOptionsSection(llvm::BumpPtrAllocator &alloc);
- unique_bump_ptr<Section<ELFT>>
- createAbiFlagsSection(llvm::BumpPtrAllocator &alloc);
-
-private:
- MipsLinkingContext &_ctx;
- MipsTargetLayout<ELFT> &_targetLayout;
- const MipsAbiInfoHandler<ELFT> &_abiInfo;
-
- void setAtomValue(StringRef name, uint64_t value);
-};
-
-template <class ELFT>
-class MipsDynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
-public:
- MipsDynamicLibraryWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout,
- const MipsAbiInfoHandler<ELFT> &abiInfo);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void finalizeDefaultAtomValues() override;
- void createDefaultSections() override;
-
- std::error_code setELFHeader() override;
-
- unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
- unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable() override;
- unique_bump_ptr<DynamicSymbolTable<ELFT>> createDynamicSymbolTable() override;
-
-private:
- MipsELFWriter<ELFT> _writeHelper;
- MipsTargetLayout<ELFT> &_targetLayout;
- unique_bump_ptr<Section<ELFT>> _reginfo;
- unique_bump_ptr<Section<ELFT>> _abiFlags;
-};
-
-template <class ELFT>
-class MipsExecutableWriter : public ExecutableWriter<ELFT> {
-public:
- MipsExecutableWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout,
- const MipsAbiInfoHandler<ELFT> &abiInfo);
-
-protected:
- void buildDynamicSymbolTable(const File &file) override;
-
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void finalizeDefaultAtomValues() override;
- void createDefaultSections() override;
- std::error_code setELFHeader() override;
-
- unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
- unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable() override;
- unique_bump_ptr<DynamicSymbolTable<ELFT>> createDynamicSymbolTable() override;
-
-private:
- MipsELFWriter<ELFT> _writeHelper;
- MipsTargetLayout<ELFT> &_targetLayout;
- unique_bump_ptr<Section<ELFT>> _reginfo;
- unique_bump_ptr<Section<ELFT>> _abiFlags;
-};
-
-} // elf
-} // lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
deleted file mode 100644
index b6cdd5c1487c..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp -------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Atoms.h"
-#include "MipsCtorsOrderPass.h"
-#include "MipsLinkingContext.h"
-#include "MipsRelocationPass.h"
-#include "MipsTargetHandler.h"
-
-using namespace lld;
-using namespace lld::elf;
-
-std::unique_ptr<ELFLinkingContext>
-elf::createMipsLinkingContext(llvm::Triple triple) {
- if (triple.getArch() == llvm::Triple::mips ||
- triple.getArch() == llvm::Triple::mipsel ||
- triple.getArch() == llvm::Triple::mips64 ||
- triple.getArch() == llvm::Triple::mips64el)
- return llvm::make_unique<MipsLinkingContext>(triple);
- return nullptr;
-}
-
-static std::unique_ptr<TargetHandler> createTarget(llvm::Triple triple,
- MipsLinkingContext &ctx) {
- switch (triple.getArch()) {
- case llvm::Triple::mips:
- return llvm::make_unique<MipsTargetHandler<ELF32BE>>(ctx);
- case llvm::Triple::mipsel:
- return llvm::make_unique<MipsTargetHandler<ELF32LE>>(ctx);
- case llvm::Triple::mips64:
- return llvm::make_unique<MipsTargetHandler<ELF64BE>>(ctx);
- case llvm::Triple::mips64el:
- return llvm::make_unique<MipsTargetHandler<ELF64LE>>(ctx);
- default:
- llvm_unreachable("Unhandled arch");
- }
-}
-
-MipsLinkingContext::MipsLinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, createTarget(triple, *this)) {}
-
-uint64_t MipsLinkingContext::getBaseAddress() const {
- if (_baseAddress != 0 || getOutputELFType() != llvm::ELF::ET_EXEC)
- return _baseAddress;
- switch (getAbi()) {
- case MipsAbi::O32:
- return 0x0400000;
- case MipsAbi::N32:
- return 0x10000000;
- case MipsAbi::N64:
- return 0x120000000;
- }
- llvm_unreachable("unknown MIPS ABI flag");
-}
-
-StringRef MipsLinkingContext::entrySymbolName() const {
- if (_outputELFType == elf::ET_EXEC && _entrySymbolName.empty())
- return "__start";
- return _entrySymbolName;
-}
-
-StringRef MipsLinkingContext::getDefaultInterpreter() const {
- switch (getAbi()) {
- case MipsAbi::O32:
- return "/lib/ld.so.1";
- case MipsAbi::N32:
- return "/lib32/ld.so.1";
- case MipsAbi::N64:
- return "/lib64/ld.so.1";
- }
- llvm_unreachable("unknown MIPS ABI flag");
-}
-
-void MipsLinkingContext::addPasses(PassManager &pm) {
- auto pass = createMipsRelocationPass(*this);
- if (pass)
- pm.add(std::move(pass));
- ELFLinkingContext::addPasses(pm);
- pm.add(llvm::make_unique<elf::MipsCtorsOrderPass>());
-}
-
-bool MipsLinkingContext::isDynamicRelocation(const Reference &r) const {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::Mips);
- switch (r.kindValue()) {
- case llvm::ELF::R_MIPS_COPY:
- case llvm::ELF::R_MIPS_REL32:
- return true;
- case llvm::ELF::R_MIPS_TLS_DTPMOD32:
- case llvm::ELF::R_MIPS_TLS_DTPREL32:
- case llvm::ELF::R_MIPS_TLS_TPREL32:
- case llvm::ELF::R_MIPS_TLS_DTPMOD64:
- case llvm::ELF::R_MIPS_TLS_DTPREL64:
- case llvm::ELF::R_MIPS_TLS_TPREL64:
- return isDynamic();
- default:
- return false;
- }
-}
-
-bool MipsLinkingContext::isCopyRelocation(const Reference &r) const {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::Mips);
- if (r.kindValue() == llvm::ELF::R_MIPS_COPY)
- return true;
- return false;
-}
-
-bool MipsLinkingContext::isPLTRelocation(const Reference &r) const {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::Mips);
- switch (r.kindValue()) {
- case llvm::ELF::R_MIPS_JUMP_SLOT:
- return true;
- default:
- return false;
- }
-}
-
-bool MipsLinkingContext::isRelativeReloc(const Reference &r) const {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::Mips);
- switch (r.kindValue()) {
- case llvm::ELF::R_MIPS_REL32:
- case llvm::ELF::R_MIPS_GPREL16:
- case llvm::ELF::R_MIPS_GPREL32:
- return true;
- default:
- return false;
- }
-}
-
-MipsAbi MipsLinkingContext::getAbi() const {
- auto &handler = static_cast<MipsBaseTargetHandler &>(getTargetHandler());
- return handler.getAbi();
-}
-
-const Registry::KindStrings kindStrings[] = {
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-#include "llvm/Support/ELFRelocs/Mips.def"
-#undef ELF_RELOC
- LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT),
- LLD_KIND_STRING_ENTRY(LLD_R_MIPS_32_HI16),
- LLD_KIND_STRING_ENTRY(LLD_R_MIPS_64_HI16),
- LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_26),
- LLD_KIND_STRING_ENTRY(LLD_R_MIPS_STO_PLT),
- LLD_KIND_STRING_ENTRY(LLD_R_MICROMIPS_GLOBAL_26_S1),
- LLD_KIND_STRING_END
-};
-
-void MipsLinkingContext::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::Mips, kindStrings);
-}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h b/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
deleted file mode 100644
index 414d2c785e17..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h ---------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
-
-#include "MipsAbiInfoHandler.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-/// \brief Mips internal references.
-enum {
- /// \brief Do nothing but mark GOT entry as a global one.
- LLD_R_MIPS_GLOBAL_GOT = 1024,
- /// \brief Apply high 16 bits of symbol + addend.
- LLD_R_MIPS_32_HI16 = 1025,
- /// \brief The same as R_MIPS_26 but for global symbols.
- LLD_R_MIPS_GLOBAL_26 = 1026,
- /// \brief Represents a reference between PLT and dynamic symbol.
- LLD_R_MIPS_STO_PLT = 1029,
- /// \brief The same as R_MICROMIPS_26_S1 but for global symbols.
- LLD_R_MICROMIPS_GLOBAL_26_S1 = 1030,
- /// \brief Apply high 32+16 bits of symbol + addend.
- LLD_R_MIPS_64_HI16 = 1031,
-};
-
-class MipsLinkingContext final : public ELFLinkingContext {
-public:
- MipsLinkingContext(llvm::Triple triple);
-
- void registerRelocationNames(Registry &r) override;
- int getMachineType() const override { return llvm::ELF::EM_MIPS; }
- uint64_t getBaseAddress() const override;
- StringRef entrySymbolName() const override;
- StringRef getDefaultInterpreter() const override;
- void addPasses(PassManager &pm) override;
- bool isRelaOutputFormat() const override { return false; }
- bool isDynamicRelocation(const Reference &r) const override;
- bool isCopyRelocation(const Reference &r) const override;
- bool isPLTRelocation(const Reference &r) const override;
- bool isRelativeReloc(const Reference &r) const override;
-
- MipsAbi getAbi() const;
-};
-
-} // elf
-} // lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
deleted file mode 100644
index c55a7a4116e6..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
+++ /dev/null
@@ -1,687 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsLinkingContext.h"
-#include "MipsRelocationHandler.h"
-#include "MipsTargetLayout.h"
-#include "llvm/Support/Format.h"
-
-using namespace lld;
-using namespace elf;
-using namespace llvm::ELF;
-using namespace llvm::support;
-
-namespace {
-enum class CrossJumpMode {
- None, // Not a jump or non-isa-cross jump
- ToRegular, // cross isa jump to regular symbol
- ToMicro, // cross isa jump to microMips symbol
- ToMicroJalr// cross isa jump to microMips symbol referenced by R_MIPS_JALR
-};
-
-typedef std::function<std::error_code(int64_t, bool)> OverflowChecker;
-
-static std::error_code dummyCheck(int64_t, bool) {
- return std::error_code();
-}
-
-template <int BITS> static std::error_code signedCheck(int64_t res, bool) {
- if (llvm::isInt<BITS>(res))
- return std::error_code();
- return make_out_of_range_reloc_error();
-}
-
-template <int BITS>
-static std::error_code gpDispCheck(int64_t res, bool isGpDisp) {
- if (!isGpDisp || llvm::isInt<BITS>(res))
- return std::error_code();
- return make_out_of_range_reloc_error();
-}
-
-struct MipsRelocationParams {
- uint8_t _size; // Relocations's size in bytes
- uint64_t _mask; // Read/write mask of relocation
- uint8_t _shift; // Relocation's addendum left shift size
- bool _shuffle; // Relocation's addendum/result needs to be shuffled
- OverflowChecker _overflow; // Check the relocation result
-};
-
-template <class ELFT> class RelocationHandler : public TargetRelocationHandler {
-public:
- RelocationHandler(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
- : _ctx(ctx), _targetLayout(layout) {}
-
- std::error_code applyRelocation(ELFWriter &writer,
- llvm::FileOutputBuffer &buf,
- const AtomLayout &atom,
- const Reference &ref) const override;
-
-private:
- MipsLinkingContext &_ctx;
- MipsTargetLayout<ELFT> &_targetLayout;
-};
-}
-
-static MipsRelocationParams getRelocationParams(uint32_t rType) {
- switch (rType) {
- case R_MIPS_NONE:
- return {4, 0x0, 0, false, dummyCheck};
- case R_MIPS_64:
- case R_MIPS_SUB:
- return {8, 0xffffffffffffffffull, 0, false, dummyCheck};
- case R_MICROMIPS_SUB:
- return {8, 0xffffffffffffffffull, 0, true, dummyCheck};
- case R_MIPS_32:
- case R_MIPS_GPREL32:
- case R_MIPS_REL32:
- case R_MIPS_PC32:
- case R_MIPS_EH:
- return {4, 0xffffffff, 0, false, dummyCheck};
- case LLD_R_MIPS_32_HI16:
- return {4, 0xffff0000, 0, false, dummyCheck};
- case LLD_R_MIPS_64_HI16:
- return {8, 0xffffffffffff0000ull, 0, false, dummyCheck};
- case R_MIPS_26:
- case LLD_R_MIPS_GLOBAL_26:
- return {4, 0x3ffffff, 2, false, dummyCheck};
- case R_MIPS_PC16:
- return {4, 0xffff, 2, false, signedCheck<18>};
- case R_MIPS_PC18_S3:
- return {4, 0x3ffff, 3, false, signedCheck<21>};
- case R_MIPS_PC19_S2:
- return {4, 0x7ffff, 2, false, signedCheck<21>};
- case R_MIPS_PC21_S2:
- return {4, 0x1fffff, 2, false, signedCheck<23>};
- case R_MIPS_PC26_S2:
- return {4, 0x3ffffff, 2, false, signedCheck<28>};
- case R_MIPS_HI16:
- return {4, 0xffff, 0, false, gpDispCheck<16>};
- case R_MIPS_LO16:
- case R_MIPS_HIGHER:
- case R_MIPS_HIGHEST:
- return {4, 0xffff, 0, false, dummyCheck};
- case R_MIPS_16:
- case R_MIPS_PCHI16:
- case R_MIPS_PCLO16:
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- case R_MIPS_GOT_DISP:
- case R_MIPS_GOT_PAGE:
- case R_MIPS_GOT_OFST:
- case R_MIPS_GPREL16:
- case R_MIPS_TLS_GD:
- case R_MIPS_TLS_LDM:
- case R_MIPS_TLS_GOTTPREL:
- case R_MIPS_LITERAL:
- return {4, 0xffff, 0, false, signedCheck<16>};
- case R_MIPS_GOT_HI16:
- case R_MIPS_GOT_LO16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- case R_MIPS_TLS_DTPREL_HI16:
- case R_MIPS_TLS_DTPREL_LO16:
- case R_MIPS_TLS_TPREL_HI16:
- case R_MIPS_TLS_TPREL_LO16:
- return {4, 0xffff, 0, false, dummyCheck};
- case R_MICROMIPS_GPREL16:
- case R_MICROMIPS_LITERAL:
- return {4, 0xffff, 0, true, signedCheck<16>};
- case R_MICROMIPS_GPREL7_S2:
- return {4, 0x7f, 2, false, signedCheck<9>};
- case R_MICROMIPS_GOT_HI16:
- case R_MICROMIPS_GOT_LO16:
- case R_MICROMIPS_CALL_HI16:
- case R_MICROMIPS_CALL_LO16:
- case R_MICROMIPS_TLS_DTPREL_HI16:
- case R_MICROMIPS_TLS_DTPREL_LO16:
- case R_MICROMIPS_TLS_TPREL_HI16:
- case R_MICROMIPS_TLS_TPREL_LO16:
- return {4, 0xffff, 0, true, dummyCheck};
- case R_MICROMIPS_26_S1:
- case LLD_R_MICROMIPS_GLOBAL_26_S1:
- return {4, 0x3ffffff, 1, true, dummyCheck};
- case R_MICROMIPS_HI16:
- return {4, 0xffff, 0, true, gpDispCheck<16>};
- case R_MICROMIPS_LO16:
- case R_MICROMIPS_HI0_LO16:
- case R_MICROMIPS_HIGHER:
- case R_MICROMIPS_HIGHEST:
- return {4, 0xffff, 0, true, dummyCheck};
- case R_MICROMIPS_PC16_S1:
- return {4, 0xffff, 1, true, signedCheck<17>};
- case R_MICROMIPS_PC7_S1:
- return {4, 0x7f, 1, false, signedCheck<8>};
- case R_MICROMIPS_PC10_S1:
- return {4, 0x3ff, 1, false, signedCheck<11>};
- case R_MICROMIPS_PC23_S2:
- return {4, 0x7fffff, 2, true, signedCheck<25>};
- case R_MICROMIPS_PC18_S3:
- return {4, 0x3ffff, 3, true, signedCheck<21>};
- case R_MICROMIPS_PC19_S2:
- return {4, 0x7ffff, 2, true, signedCheck<21>};
- case R_MICROMIPS_PC21_S2:
- return {4, 0x1fffff, 2, true, signedCheck<23>};
- case R_MICROMIPS_PC26_S2:
- return {4, 0x3ffffff, 2, true, signedCheck<28>};
- case R_MICROMIPS_GOT16:
- case R_MICROMIPS_CALL16:
- case R_MICROMIPS_TLS_GD:
- case R_MICROMIPS_TLS_LDM:
- case R_MICROMIPS_TLS_GOTTPREL:
- case R_MICROMIPS_GOT_DISP:
- case R_MICROMIPS_GOT_PAGE:
- case R_MICROMIPS_GOT_OFST:
- return {4, 0xffff, 0, true, signedCheck<16>};
- case R_MIPS_JALR:
- return {4, 0xffffffff, 0, false, dummyCheck};
- case R_MICROMIPS_JALR:
- return {4, 0x0, 0, true, dummyCheck};
- case R_MIPS_JUMP_SLOT:
- case R_MIPS_COPY:
- case R_MIPS_TLS_DTPMOD32:
- case R_MIPS_TLS_DTPREL32:
- case R_MIPS_TLS_TPREL32:
- return {4, 0xffffffff, 0, false, dummyCheck};
- case R_MIPS_TLS_DTPMOD64:
- case R_MIPS_TLS_DTPREL64:
- case R_MIPS_TLS_TPREL64:
- return {8, 0xffffffffffffffffull, 0, false, dummyCheck};
- case LLD_R_MIPS_GLOBAL_GOT:
- case LLD_R_MIPS_STO_PLT:
- // Do nothing.
- return {4, 0x0, 0, false, dummyCheck};
- default:
- llvm_unreachable("Unknown relocation");
- }
-}
-
-template <class ELFT>
-static uint64_t relocRead(const MipsRelocationParams &params,
- const uint8_t *loc);
-
-static int64_t getHi16(int64_t value) {
- return ((value + 0x8000) >> 16) & 0xffff;
-}
-
-static int64_t getHigher16(int64_t value) {
- return ((value + 0x80008000ull) >> 32) & 0xffff;
-}
-
-static int64_t getHighest16(int64_t value) {
- return ((value + 0x800080008000ull) >> 48) & 0xffff;
-}
-
-static int64_t maskLow16(int64_t value) {
- return (value + 0x8000) & ~0xffff;
-}
-
-/// R_MIPS_GOT_OFST, R_MICROMIPS_GOT_OFST
-/// rel16 offset of (S+A) from the page pointer (verify)
-static int32_t relocGOTOfst(uint64_t S, int64_t A) {
- int64_t page = maskLow16(S + A);
- return S + A - page;
-}
-
-/// \brief R_MIPS_PC16
-/// local/external: (S + A - P) >> 2
-static ErrorOr<int64_t> relocPc16(uint64_t P, uint64_t S, int64_t A) {
- if ((S + A) & 3)
- return make_unaligned_range_reloc_error();
- return S + A - P;
-}
-
-/// \brief R_MIPS_PC18_S3, R_MICROMIPS_PC18_S3
-/// local/external: (S + A - P) >> 3 (P with cleared 3 less significant bits)
-static ErrorOr<int64_t> relocPc18(uint64_t P, uint64_t S, int64_t A) {
- if ((S + A) & 6)
- return make_unaligned_range_reloc_error();
- return S + A - ((P | 7) ^ 7);
-}
-
-/// \brief R_MIPS_PC19_S2, R_MICROMIPS_PC19_S2, R_MIPS_PC21_S2,
-/// R_MICROMIPS_PC21_S2, R_MIPS_PC26_S2, R_MICROMIPS_PC26_S2
-/// local/external: (S + A - P) >> 2
-static ErrorOr<int64_t> relocPcS2(uint64_t P, uint64_t S, int64_t A) {
- if ((S + A) & 2)
- return make_unaligned_range_reloc_error();
- return S + A - P;
-}
-
-template <class ELFT>
-static ErrorOr<int64_t> relocJalr(uint64_t P, uint64_t S, bool isCrossJump,
- uint8_t *location) {
- uint64_t ins = relocRead<ELFT>(getRelocationParams(R_MIPS_JALR), location);
- if (isCrossJump)
- return ins;
- int64_t off = S - P - 4;
- if (!llvm::isInt<18>(off))
- return ins;
- if (ins == 0x0320f809) // jalr t9
- return 0x04110000 | ((off >> 2) & 0xffff);
- if (ins == 0x03200008) // jr t9
- return 0x10000000 | ((off >> 2) & 0xffff);
- return ins;
-}
-
-static int64_t relocRel32(uint64_t S, int64_t A, bool isLocal) {
- // If output relocation format is REL and the input one is RELA, the only
- // method to transfer the relocation addend from the input relocation
- // to the output dynamic relocation is to save this addend to the location
- // modified by R_MIPS_REL32.
- return isLocal ? S + A : A;
-}
-
-static std::error_code adjustJumpOpCode(uint64_t &ins, uint64_t tgt,
- CrossJumpMode mode) {
- if (mode == CrossJumpMode::None || mode == CrossJumpMode::ToMicroJalr)
- return std::error_code();
-
- bool toMicro = mode == CrossJumpMode::ToMicro;
- uint32_t opNative = toMicro ? 0x03 : 0x3d;
- uint32_t opCross = toMicro ? 0x1d : 0x3c;
-
- if ((tgt & 1) != toMicro)
- return make_dynamic_error_code("Incorrect bit 0 for the jalx target");
-
- if (tgt & 2)
- return make_dynamic_error_code(Twine("The jalx target 0x") +
- Twine::utohexstr(tgt) +
- " is not word-aligned");
- uint8_t op = ins >> 26;
- if (op != opNative && op != opCross)
- return make_dynamic_error_code(Twine("Unsupported jump opcode (0x") +
- Twine::utohexstr(op) +
- ") for ISA modes cross call");
-
- ins = (ins & ~(0x3f << 26)) | (opCross << 26);
- return std::error_code();
-}
-
-static bool isMicroMipsAtom(const Atom *a) {
- if (const auto *da = dyn_cast<DefinedAtom>(a))
- return da->codeModel() == DefinedAtom::codeMipsMicro ||
- da->codeModel() == DefinedAtom::codeMipsMicroPIC;
- return false;
-}
-
-static CrossJumpMode getCrossJumpMode(const Reference &ref) {
- if (!isa<DefinedAtom>(ref.target()))
- return CrossJumpMode::None;
- bool isTgtMicro = isMicroMipsAtom(ref.target());
- switch (ref.kindValue()) {
- case R_MIPS_JALR:
- return isTgtMicro ? CrossJumpMode::ToMicroJalr : CrossJumpMode::None;
- case R_MIPS_26:
- case LLD_R_MIPS_GLOBAL_26:
- return isTgtMicro ? CrossJumpMode::ToMicro : CrossJumpMode::None;
- case R_MICROMIPS_26_S1:
- case LLD_R_MICROMIPS_GLOBAL_26_S1:
- return isTgtMicro ? CrossJumpMode::None : CrossJumpMode::ToRegular;
- default:
- return CrossJumpMode::None;
- }
-}
-
-template <class ELFT>
-static ErrorOr<int64_t>
-calculateRelocation(Reference::KindValue kind, Reference::Addend addend,
- uint64_t tgtAddr, uint64_t relAddr, uint64_t gpAddr,
- uint8_t *location, bool isGP, bool isCrossJump,
- bool isDynamic, bool isLocalSym) {
- switch (kind) {
- case R_MIPS_NONE:
- return 0;
- case R_MIPS_16:
- case R_MIPS_32:
- case R_MIPS_64:
- case R_MIPS_TLS_DTPREL_LO16:
- case R_MIPS_TLS_TPREL_LO16:
- case R_MICROMIPS_TLS_DTPREL_LO16:
- case R_MICROMIPS_TLS_TPREL_LO16:
- case LLD_R_MIPS_GLOBAL_26:
- case LLD_R_MICROMIPS_GLOBAL_26_S1:
- return tgtAddr + addend;
- case R_MIPS_SUB:
- case R_MICROMIPS_SUB:
- return tgtAddr - addend;
- case R_MIPS_26:
- return tgtAddr + (addend | (relAddr & 0xf0000000));
- case R_MICROMIPS_26_S1:
- return tgtAddr + (addend | (relAddr & 0xf8000000));
- case R_MIPS_HI16:
- case R_MICROMIPS_HI16:
- return getHi16(tgtAddr + addend - (isGP ? relAddr : 0));
- case R_MIPS_PCHI16:
- return getHi16(tgtAddr + addend - relAddr);
- case R_MIPS_LO16:
- return tgtAddr + addend - (isGP ? relAddr - 4 : 0);
- case R_MICROMIPS_LO16:
- case R_MICROMIPS_HI0_LO16:
- return tgtAddr + addend - (isGP ? relAddr - 3 : 0);
- case R_MIPS_GOT_HI16:
- case R_MIPS_CALL_HI16:
- case R_MICROMIPS_GOT_HI16:
- case R_MICROMIPS_CALL_HI16:
- return getHi16(tgtAddr - gpAddr);
- case R_MIPS_HIGHER:
- case R_MICROMIPS_HIGHER:
- return getHigher16(tgtAddr + addend);
- case R_MIPS_HIGHEST:
- case R_MICROMIPS_HIGHEST:
- return getHighest16(tgtAddr + addend);
- case R_MIPS_GOT_LO16:
- case R_MIPS_CALL_LO16:
- case R_MICROMIPS_GOT_LO16:
- case R_MICROMIPS_CALL_LO16:
- case R_MIPS_EH:
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- case R_MIPS_GOT_DISP:
- case R_MIPS_GOT_PAGE:
- case R_MICROMIPS_GOT_DISP:
- case R_MICROMIPS_GOT_PAGE:
- case R_MICROMIPS_GOT16:
- case R_MICROMIPS_CALL16:
- case R_MIPS_TLS_GD:
- case R_MIPS_TLS_LDM:
- case R_MIPS_TLS_GOTTPREL:
- case R_MICROMIPS_TLS_GD:
- case R_MICROMIPS_TLS_LDM:
- case R_MICROMIPS_TLS_GOTTPREL:
- return tgtAddr - gpAddr;
- case R_MIPS_GPREL16:
- case R_MIPS_GPREL32:
- case R_MIPS_LITERAL:
- case R_MICROMIPS_GPREL16:
- case R_MICROMIPS_GPREL7_S2:
- case R_MICROMIPS_LITERAL:
- return tgtAddr + addend - gpAddr;
- case R_MIPS_GOT_OFST:
- case R_MICROMIPS_GOT_OFST:
- return relocGOTOfst(tgtAddr, addend);
- case R_MIPS_PC16:
- return relocPc16(relAddr, tgtAddr, addend);
- case R_MIPS_PC18_S3:
- case R_MICROMIPS_PC18_S3:
- return relocPc18(relAddr, tgtAddr, addend);
- case R_MIPS_PC19_S2:
- case R_MICROMIPS_PC19_S2:
- case R_MIPS_PC21_S2:
- case R_MICROMIPS_PC21_S2:
- case R_MIPS_PC26_S2:
- case R_MICROMIPS_PC26_S2:
- return relocPcS2(relAddr, tgtAddr, addend);
- case R_MIPS_PC32:
- case R_MIPS_PCLO16:
- case R_MICROMIPS_PC7_S1:
- case R_MICROMIPS_PC10_S1:
- case R_MICROMIPS_PC16_S1:
- case R_MICROMIPS_PC23_S2:
- return tgtAddr + addend - relAddr;
- case R_MIPS_TLS_DTPREL_HI16:
- case R_MIPS_TLS_TPREL_HI16:
- case R_MICROMIPS_TLS_DTPREL_HI16:
- case R_MICROMIPS_TLS_TPREL_HI16:
- return getHi16(tgtAddr + addend);
- case R_MIPS_JALR:
- return relocJalr<ELFT>(relAddr, tgtAddr, isCrossJump, location);
- case R_MICROMIPS_JALR:
- // We do not do JALR optimization now.
- return 0;
- case R_MIPS_REL32:
- return relocRel32(tgtAddr, addend, isLocalSym);
- case R_MIPS_JUMP_SLOT:
- case R_MIPS_COPY:
- // Ignore runtime relocations.
- return 0;
- case R_MIPS_TLS_DTPMOD32:
- case R_MIPS_TLS_DTPMOD64:
- return isDynamic ? 0 : 1;
- case R_MIPS_TLS_DTPREL32:
- case R_MIPS_TLS_DTPREL64:
- return isDynamic ? 0 : tgtAddr + addend - 0x8000;
- case R_MIPS_TLS_TPREL32:
- case R_MIPS_TLS_TPREL64:
- return isDynamic ? 0 : tgtAddr + addend - 0x7000;
- case LLD_R_MIPS_32_HI16:
- case LLD_R_MIPS_64_HI16:
- return maskLow16(tgtAddr + addend);
- case LLD_R_MIPS_STO_PLT:
- case LLD_R_MIPS_GLOBAL_GOT:
- // Do nothing.
- return 0;
- default:
- return make_unhandled_reloc_error();
- }
-}
-
-template <class ELFT>
-static uint64_t relocRead(const MipsRelocationParams &params,
- const uint8_t *loc) {
- assert((params._size == 4 || params._size == 8) && "Unexpected size");
- uint64_t data = 0;
- memcpy(&data, loc, params._size);
- if (params._shuffle) {
- using namespace endian;
- auto p = reinterpret_cast<const uint8_t *>(&data);
- uint32_t a = readNext<uint16_t, ELFT::TargetEndianness, unaligned>(p);
- uint32_t b = read<uint16_t, ELFT::TargetEndianness, unaligned>(p);
- write<uint32_t, ELFT::TargetEndianness, unaligned>(&data, a << 16 | b);
- }
- switch (params._size) {
- case 4:
- return endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(&data);
- case 8:
- return endian::read<uint64_t, ELFT::TargetEndianness, unaligned>(&data);
- default:
- llvm_unreachable("Unexpected size");
- }
-}
-
-template <class ELFT>
-static void relocWrite(uint64_t data, const MipsRelocationParams &params,
- uint8_t *loc) {
- switch (params._size) {
- case 4:
- endian::write<uint32_t, ELFT::TargetEndianness, unaligned>(loc, data);
- break;
- case 8:
- endian::write<uint64_t, ELFT::TargetEndianness, unaligned>(loc, data);
- break;
- default:
- llvm_unreachable("Unexpected size");
- }
- if (params._shuffle) {
- uint32_t v = endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(loc);
- uint16_t a = v >> 16;
- uint16_t b = v & 0xffff;
- endian::write<uint16_t, ELFT::TargetEndianness, unaligned>(loc, a);
- endian::write<uint16_t, ELFT::TargetEndianness, unaligned>(loc + 2, b);
- }
-}
-
-static uint32_t getRelKind(const Reference &ref, size_t num) {
- if (num == 0)
- return ref.kindValue();
- if (num > 2)
- return R_MIPS_NONE;
- return (ref.tag() >> (8 * (num - 1))) & 0xff;
-}
-
-static uint8_t getRelShift(Reference::KindValue kind,
- const MipsRelocationParams &params,
- bool isCrossJump) {
- uint8_t shift = params._shift;
- if (isCrossJump &&
- (kind == R_MICROMIPS_26_S1 || kind == LLD_R_MICROMIPS_GLOBAL_26_S1))
- return 2;
- return shift;
-}
-
-static bool isLocalTarget(const Atom *a) {
- if (auto *da = dyn_cast<DefinedAtom>(a))
- return da->scope() == Atom::scopeTranslationUnit;
- return false;
-}
-
-template <class ELFT>
-std::error_code RelocationHandler<ELFT>::applyRelocation(
- ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
- const Reference &ref) const {
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return std::error_code();
- assert(ref.kindArch() == Reference::KindArch::Mips);
-
- uint64_t gpAddr = _targetLayout.getGPAddr();
- bool isGpDisp = ref.target()->name() == "_gp_disp";
- bool isLocalSym = isLocalTarget(ref.target());
-
- uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *location = atomContent + ref.offsetInAtom();
- uint64_t tgtAddr = writer.addressOfAtom(ref.target());
- uint64_t relAddr = atom._virtualAddr + ref.offsetInAtom();
-
- if (isMicroMipsAtom(ref.target()))
- tgtAddr |= 1;
-
- CrossJumpMode jumpMode = getCrossJumpMode(ref);
- bool isCrossJump = jumpMode != CrossJumpMode::None;
-
- uint64_t sym = tgtAddr;
- ErrorOr<int64_t> res = ref.addend();
- Reference::KindValue lastRel = R_MIPS_NONE;
-
- for (size_t relNum = 0; relNum < 3; ++relNum) {
- Reference::KindValue kind = getRelKind(ref, relNum);
- if (kind == R_MIPS_NONE)
- break;
- auto params = getRelocationParams(kind);
- res = calculateRelocation<ELFT>(kind, *res, sym, relAddr, gpAddr, location,
- isGpDisp, isCrossJump, _ctx.isDynamic(),
- isLocalSym);
- if (auto ec = res.getError())
- return ec;
- // Check result for the last relocation only.
- if (getRelKind(ref, relNum + 1) == R_MIPS_NONE) {
- if (auto ec = params._overflow(*res, isGpDisp))
- return ec;
- }
- res = *res >> getRelShift(kind, params, isCrossJump);
- // FIXME (simon): Handle r_ssym value.
- sym = 0;
- isGpDisp = false;
- isCrossJump = false;
- lastRel = kind;
- }
-
- auto params = getRelocationParams(lastRel);
- uint64_t ins = relocRead<ELFT>(params, location);
- if (auto ec = adjustJumpOpCode(ins, tgtAddr, jumpMode))
- return ec;
-
- ins = (ins & ~params._mask) | (*res & params._mask);
- relocWrite<ELFT>(ins, params, location);
-
- return std::error_code();
-}
-
-namespace lld {
-namespace elf {
-
-template <>
-std::unique_ptr<TargetRelocationHandler>
-createMipsRelocationHandler<ELF32BE>(MipsLinkingContext &ctx,
- MipsTargetLayout<ELF32BE> &layout) {
- return llvm::make_unique<RelocationHandler<ELF32BE>>(ctx, layout);
-}
-
-template <>
-std::unique_ptr<TargetRelocationHandler>
-createMipsRelocationHandler<ELF32LE>(MipsLinkingContext &ctx,
- MipsTargetLayout<ELF32LE> &layout) {
- return llvm::make_unique<RelocationHandler<ELF32LE>>(ctx, layout);
-}
-
-template <>
-std::unique_ptr<TargetRelocationHandler>
-createMipsRelocationHandler<ELF64BE>(MipsLinkingContext &ctx,
- MipsTargetLayout<ELF64BE> &layout) {
- return llvm::make_unique<RelocationHandler<ELF64BE>>(ctx, layout);
-}
-
-template <>
-std::unique_ptr<TargetRelocationHandler>
-createMipsRelocationHandler<ELF64LE>(MipsLinkingContext &ctx,
- MipsTargetLayout<ELF64LE> &layout) {
- return llvm::make_unique<RelocationHandler<ELF64LE>>(ctx, layout);
-}
-
-template <class ELFT>
-Reference::Addend readMipsRelocAddend(Reference::KindValue kind,
- const uint8_t *content) {
- auto params = getRelocationParams(kind);
- uint64_t ins = relocRead<ELFT>(params, content);
- int64_t res = (ins & params._mask) << params._shift;
- switch (kind) {
- case R_MIPS_GPREL16:
- case R_MICROMIPS_GPREL16:
- case R_MIPS_PCLO16:
- case R_MIPS_LITERAL:
- case R_MICROMIPS_LITERAL:
- return llvm::SignExtend32<16>(res);
- case R_MIPS_PC16:
- return llvm::SignExtend32<18>(res);
- case R_MICROMIPS_GPREL7_S2:
- return llvm::SignExtend32<9>(res);
- case R_MICROMIPS_PC7_S1:
- return llvm::SignExtend32<8>(res);
- case R_MICROMIPS_PC10_S1:
- return llvm::SignExtend32<11>(res);
- case R_MIPS_16:
- return llvm::SignExtend32<16>(res);
- case R_MICROMIPS_PC16_S1:
- return llvm::SignExtend32<17>(res);
- case R_MIPS_PC18_S3:
- case R_MIPS_PC19_S2:
- case R_MICROMIPS_PC18_S3:
- case R_MICROMIPS_PC19_S2:
- return llvm::SignExtend32<21>(res);
- case R_MIPS_PC21_S2:
- case R_MICROMIPS_PC21_S2:
- return llvm::SignExtend32<23>(res);
- case R_MICROMIPS_PC23_S2:
- return llvm::SignExtend32<25>(res);
- case R_MICROMIPS_26_S1:
- return llvm::SignExtend32<27>(res);
- case R_MIPS_26:
- case R_MIPS_PC26_S2:
- case R_MICROMIPS_PC26_S2:
- return llvm::SignExtend32<28>(res);
- default:
- // Nothing to do
- break;
- }
- return res;
-}
-
-template
-Reference::Addend readMipsRelocAddend<ELF32BE>(Reference::KindValue kind,
- const uint8_t *content);
-template
-Reference::Addend readMipsRelocAddend<ELF32LE>(Reference::KindValue kind,
- const uint8_t *content);
-template
-Reference::Addend readMipsRelocAddend<ELF64BE>(Reference::KindValue kind,
- const uint8_t *content);
-template
-Reference::Addend readMipsRelocAddend<ELF64LE>(Reference::KindValue kind,
- const uint8_t *content);
-
-} // elf
-} // lld
diff --git a/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h b/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
deleted file mode 100644
index 62a7aee34496..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- lld/ReaderWriter/ELF/Mips/MipsRelocationHandler.h ------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_RELOCATION_HANDLER_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_RELOCATION_HANDLER_H
-
-#include "lld/Core/Reference.h"
-
-namespace lld {
-namespace elf {
-
-class MipsLinkingContext;
-template<typename ELFT> class MipsTargetLayout;
-
-template <class ELFT>
-std::unique_ptr<TargetRelocationHandler>
-createMipsRelocationHandler(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout);
-
-template <class ELFT>
-Reference::Addend readMipsRelocAddend(Reference::KindValue kind,
- const uint8_t *content);
-} // elf
-} // lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
deleted file mode 100644
index b47c7d2210db..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
+++ /dev/null
@@ -1,1415 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp -------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsELFFile.h"
-#include "MipsLinkingContext.h"
-#include "MipsRelocationPass.h"
-#include "MipsTargetHandler.h"
-#include "llvm/ADT/DenseSet.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::ELF;
-
-// Lazy resolver
-static const uint8_t mipsGot0AtomContent[] = {
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-// Module pointer
-static const uint8_t mipsGotModulePointerAtomContent[] = {
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80
-};
-
-// TLS GD Entry
-static const uint8_t mipsGotTlsGdAtomContent[] = {
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-// Regular big-endian PLT0 entry
-static const uint8_t mipsBePlt0AtomContent[] = {
- 0x3c, 0x1c, 0x00, 0x00, // lui $28, %hi(&GOTPLT[0])
- 0x8f, 0x99, 0x00, 0x00, // lw $25, %lo(&GOTPLT[0])($28)
- 0x27, 0x9c, 0x00, 0x00, // addiu $28, $28, %lo(&GOTPLT[0])
- 0x03, 0x1c, 0xc0, 0x23, // subu $24, $24, $28
- 0x03, 0xe0, 0x78, 0x25, // move $15, $31
- 0x00, 0x18, 0xc0, 0x82, // srl $24, $24, 2
- 0x03, 0x20, 0xf8, 0x09, // jalr $25
- 0x27, 0x18, 0xff, 0xfe // subu $24, $24, 2
-};
-
-// Regular little-endian PLT0 entry
-static const uint8_t mipsLePlt0AtomContent[] = {
- 0x00, 0x00, 0x1c, 0x3c, // lui $28, %hi(&GOTPLT[0])
- 0x00, 0x00, 0x99, 0x8f, // lw $25, %lo(&GOTPLT[0])($28)
- 0x00, 0x00, 0x9c, 0x27, // addiu $28, $28, %lo(&GOTPLT[0])
- 0x23, 0xc0, 0x1c, 0x03, // subu $24, $24, $28
- 0x25, 0x78, 0xe0, 0x03, // move $15, $31
- 0x82, 0xc0, 0x18, 0x00, // srl $24, $24, 2
- 0x09, 0xf8, 0x20, 0x03, // jalr $25
- 0xfe, 0xff, 0x18, 0x27 // subu $24, $24, 2
-};
-
-// N32 big-endian PLT0 entry
-static const uint8_t mipsN32BePlt0AtomContent[] = {
- 0x3c, 0x0e, 0x00, 0x00, // lui $14, %hi(&GOTPLT[0])
- 0x8d, 0xd9, 0x00, 0x00, // lw $25, %lo(&GOTPLT[0])($14)
- 0x25, 0xce, 0x00, 0x00, // addiu $14, $14, %lo(&GOTPLT[0])
- 0x03, 0x0e, 0xc0, 0x23, // subu $24, $24, $14
- 0x03, 0xe0, 0x78, 0x25, // move $15, $31
- 0x00, 0x18, 0xc0, 0x82, // srl $24, $24, 2
- 0x03, 0x20, 0xf8, 0x09, // jalr $25
- 0x27, 0x18, 0xff, 0xfe // subu $24, $24, 2
-};
-
-// N32 little-endian PLT0 entry
-static const uint8_t mipsN32LePlt0AtomContent[] = {
- 0x00, 0x00, 0x0e, 0x3c, // lui $14, %hi(&GOTPLT[0])
- 0x00, 0x00, 0xd9, 0x8d, // lw $25, %lo(&GOTPLT[0])($14)
- 0x00, 0x00, 0xce, 0x25, // addiu $14, $14, %lo(&GOTPLT[0])
- 0x23, 0xc0, 0x0e, 0x03, // subu $24, $24, $14
- 0x25, 0x78, 0xe0, 0x03, // move $15, $31
- 0x82, 0xc0, 0x18, 0x00, // srl $24, $24, 2
- 0x09, 0xf8, 0x20, 0x03, // jalr $25
- 0xfe, 0xff, 0x18, 0x27 // subu $24, $24, 2
-};
-
-// microMIPS big-endian PLT0 entry
-static const uint8_t microMipsBePlt0AtomContent[] = {
- 0x79, 0x80, 0x00, 0x00, // addiupc $3, (&GOTPLT[0]) - .
- 0xff, 0x23, 0x00, 0x00, // lw $25, 0($3)
- 0x05, 0x35, // subu $2, $2, $3
- 0x25, 0x25, // srl $2, $2, 2
- 0x33, 0x02, 0xff, 0xfe, // subu $24, $2, 2
- 0x0d, 0xff, // move $15, $31
- 0x45, 0xf9, // jalrs $25
- 0x0f, 0x83, // move $28, $3
- 0x0c, 0x00 // nop
-};
-
-// microMIPS little-endian PLT0 entry
-static const uint8_t microMipsLePlt0AtomContent[] = {
- 0x80, 0x79, 0x00, 0x00, // addiupc $3, (&GOTPLT[0]) - .
- 0x23, 0xff, 0x00, 0x00, // lw $25, 0($3)
- 0x35, 0x05, // subu $2, $2, $3
- 0x25, 0x25, // srl $2, $2, 2
- 0x02, 0x33, 0xfe, 0xff, // subu $24, $2, 2
- 0xff, 0x0d, // move $15, $31
- 0xf9, 0x45, // jalrs $25
- 0x83, 0x0f, // move $28, $3
- 0x00, 0x0c // nop
-};
-
-// Regular big-endian PLT entry
-static const uint8_t mipsBePltAAtomContent[] = {
- 0x3c, 0x0f, 0x00, 0x00, // lui $15, %hi(.got.plt entry)
- 0x8d, 0xf9, 0x00, 0x00, // l[wd] $25, %lo(.got.plt entry)($15)
- 0x03, 0x20, 0x00, 0x08, // jr $25
- 0x25, 0xf8, 0x00, 0x00 // addiu $24, $15, %lo(.got.plt entry)
-};
-
-// Regular little-endian PLT entry
-static const uint8_t mipsLePltAAtomContent[] = {
- 0x00, 0x00, 0x0f, 0x3c, // lui $15, %hi(.got.plt entry)
- 0x00, 0x00, 0xf9, 0x8d, // l[wd] $25, %lo(.got.plt entry)($15)
- 0x08, 0x00, 0x20, 0x03, // jr $25
- 0x00, 0x00, 0xf8, 0x25 // addiu $24, $15, %lo(.got.plt entry)
-};
-
-// microMIPS big-endian PLT entry
-static const uint8_t microMipsBePltAAtomContent[] = {
- 0x79, 0x00, 0x00, 0x00, // addiupc $2, (.got.plt entry) - .
- 0xff, 0x22, 0x00, 0x00, // lw $25, 0($2)
- 0x45, 0x99, // jr $25
- 0x0f, 0x02 // move $24, $2
-};
-
-// microMIPS little-endian PLT entry
-static const uint8_t microMipsLePltAAtomContent[] = {
- 0x00, 0x79, 0x00, 0x00, // addiupc $2, (.got.plt entry) - .
- 0x22, 0xff, 0x00, 0x00, // lw $25, 0($2)
- 0x99, 0x45, // jr $25
- 0x02, 0x0f // move $24, $2
-};
-
-// R6 big-endian PLT entry
-static const uint8_t mipsR6BePltAAtomContent[] = {
- 0x3c, 0x0f, 0x00, 0x00, // lui $15, %hi(.got.plt entry)
- 0x8d, 0xf9, 0x00, 0x00, // l[wd] $25, %lo(.got.plt entry)($15)
- 0x03, 0x20, 0x00, 0x09, // jr $25
- 0x25, 0xf8, 0x00, 0x00 // addiu $24, $15, %lo(.got.plt entry)
-};
-
-// R6 little-endian PLT entry
-static const uint8_t mipsR6LePltAAtomContent[] = {
- 0x00, 0x00, 0x0f, 0x3c, // lui $15, %hi(.got.plt entry)
- 0x00, 0x00, 0xf9, 0x8d, // l[wd] $25, %lo(.got.plt entry)($15)
- 0x09, 0x00, 0x20, 0x03, // jr $25
- 0x00, 0x00, 0xf8, 0x25 // addiu $24, $15, %lo(.got.plt entry)
-};
-
-// LA25 big-endian stub entry
-static const uint8_t mipsBeLA25AtomContent[] = {
- 0x3c, 0x19, 0x00, 0x00, // lui $25, %hi(func)
- 0x08, 0x00, 0x00, 0x00, // j func
- 0x27, 0x39, 0x00, 0x00, // addiu $25, $25, %lo(func)
- 0x00, 0x00, 0x00, 0x00 // nop
-};
-
-// LA25 little-endian stub entry
-static const uint8_t mipsLeLA25AtomContent[] = {
- 0x00, 0x00, 0x19, 0x3c, // lui $25, %hi(func)
- 0x00, 0x00, 0x00, 0x08, // j func
- 0x00, 0x00, 0x39, 0x27, // addiu $25, $25, %lo(func)
- 0x00, 0x00, 0x00, 0x00 // nop
-};
-
-// microMIPS LA25 big-endian stub entry
-static const uint8_t microMipsBeLA25AtomContent[] = {
- 0x41, 0xbe, 0x00, 0x00, // lui $25, %hi(func)
- 0xd4, 0x00, 0x00, 0x00, // j func
- 0x33, 0x39, 0x00, 0x00, // addiu $25, $25, %lo(func)
- 0x00, 0x00, 0x00, 0x00 // nop
-};
-
-// microMIPS LA25 little-endian stub entry
-static const uint8_t microMipsLeLA25AtomContent[] = {
- 0xb9, 0x41, 0x00, 0x00, // lui $25, %hi(func)
- 0x00, 0xd4, 0x00, 0x00, // j func
- 0x39, 0x33, 0x00, 0x00, // addiu $25, $25, %lo(func)
- 0x00, 0x00, 0x00, 0x00 // nop
-};
-
-namespace {
-
-/// \brief Abstract base class represent MIPS GOT entries.
-class MipsGOTAtom : public GOTAtom {
-public:
- MipsGOTAtom(const File &f) : GOTAtom(f, ".got") {}
-
- Alignment alignment() const override { return 4; }
-};
-
-/// \brief MIPS GOT entry initialized by zero.
-template <typename ELFT> class GOT0Atom : public MipsGOTAtom {
-public:
- GOT0Atom(const File &f) : MipsGOTAtom(f) {}
-
- ArrayRef<uint8_t> rawContent() const override;
-};
-
-template <> ArrayRef<uint8_t> GOT0Atom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGot0AtomContent).slice(4);
-}
-template <> ArrayRef<uint8_t> GOT0Atom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGot0AtomContent).slice(4);
-}
-template <> ArrayRef<uint8_t> GOT0Atom<ELF64BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGot0AtomContent);
-}
-template <> ArrayRef<uint8_t> GOT0Atom<ELF64LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGot0AtomContent);
-}
-
-/// \brief MIPS GOT entry initialized by zero.
-template <typename ELFT> class GOTModulePointerAtom : public MipsGOTAtom {
-public:
- GOTModulePointerAtom(const File &f) : MipsGOTAtom(f) {}
-
- ArrayRef<uint8_t> rawContent() const override;
-};
-
-template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotModulePointerAtomContent).slice(4);
-}
-template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotModulePointerAtomContent).slice(4);
-}
-template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<ELF64BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotModulePointerAtomContent);
-}
-template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<ELF64LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotModulePointerAtomContent);
-}
-
-/// \brief MIPS GOT TLS GD entry.
-template <typename ELFT> class GOTTLSGdAtom : public MipsGOTAtom {
-public:
- GOTTLSGdAtom(const File &f) : MipsGOTAtom(f) {}
-
- ArrayRef<uint8_t> rawContent() const override;
-};
-
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent).slice(8);
-}
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent).slice(8);
-}
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF64BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent);
-}
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF64LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent);
-}
-
-class GOTPLTAtom : public GOTAtom {
-public:
- GOTPLTAtom(const File &f) : GOTAtom(f, ".got.plt") {}
- GOTPLTAtom(const Atom *a, const File &f) : GOTAtom(f, ".got.plt") {
- // Create dynamic relocation to adjust the .got.plt entry at runtime.
- addReferenceELF_Mips(R_MIPS_JUMP_SLOT, 0, a, 0);
- }
-
- /// Setup reference to assign initial value to the .got.plt entry.
- void setPLT0(const PLTAtom *plt0) {
- addReferenceELF_Mips(R_MIPS_32, 0, plt0, 0);
- }
-
- Alignment alignment() const override { return 4; }
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(mipsGot0AtomContent).slice(4);
- }
-};
-
-template <class ELFT> class PLT0Atom : public PLTAtom {
-public:
- PLT0Atom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the PLT0 entry.
- addReferenceELF_Mips(R_MIPS_HI16, 0, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 4, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 8, got, 0);
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT0 is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLT0Atom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsBePlt0AtomContent);
-}
-template <> ArrayRef<uint8_t> PLT0Atom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsLePlt0AtomContent);
-}
-
-template <class ELFT> class PLT0N32Atom : public PLTAtom {
-public:
- PLT0N32Atom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the PLT0 entry.
- addReferenceELF_Mips(R_MIPS_HI16, 0, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 4, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 8, got, 0);
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT0 is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLT0N32Atom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsN32BePlt0AtomContent);
-}
-template <> ArrayRef<uint8_t> PLT0N32Atom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsN32LePlt0AtomContent);
-}
-
-template <class ELFT> class PLT0MicroAtom : public PLTAtom {
-public:
- PLT0MicroAtom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the PLT0 entry.
- addReferenceELF_Mips(R_MICROMIPS_PC23_S2, 0, got, 0);
- }
-
- CodeModel codeModel() const override { return codeMipsMicro; }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT0 is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLT0MicroAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(microMipsBePlt0AtomContent);
-}
-template <> ArrayRef<uint8_t> PLT0MicroAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(microMipsLePlt0AtomContent);
-}
-
-class PLTAAtom : public PLTAtom {
-public:
- PLTAAtom(const GOTPLTAtom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the PLT entry.
- addReferenceELF_Mips(R_MIPS_HI16, 0, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 4, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 12, got, 0);
- }
-};
-
-template <class ELFT> class PLTARegAtom : public PLTAAtom {
-public:
- PLTARegAtom(const GOTPLTAtom *got, const File &f) : PLTAAtom(got, f) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLTARegAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsBePltAAtomContent);
-}
-template <> ArrayRef<uint8_t> PLTARegAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsLePltAAtomContent);
-}
-
-template <class ELFT> class PLTR6Atom : public PLTAAtom {
-public:
- PLTR6Atom(const GOTPLTAtom *got, const File &f) : PLTAAtom(got, f) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLTR6Atom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsR6BePltAAtomContent);
-}
-template <> ArrayRef<uint8_t> PLTR6Atom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsR6LePltAAtomContent);
-}
-
-template <class ELFT> class PLTMicroAtom : public PLTAtom {
-public:
- PLTMicroAtom(const GOTPLTAtom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the microMIPS PLT entry.
- addReferenceELF_Mips(R_MICROMIPS_PC23_S2, 0, got, 0);
- }
-
- Alignment alignment() const override { return 2; }
- CodeModel codeModel() const override { return codeMipsMicro; }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLTMicroAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(microMipsBePltAAtomContent);
-}
-template <> ArrayRef<uint8_t> PLTMicroAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(microMipsLePltAAtomContent);
-}
-
-class LA25Atom : public PLTAtom {
-public:
- LA25Atom(const File &f) : PLTAtom(f, ".text") {}
-};
-
-template <typename ELFT> class LA25RegAtom : public LA25Atom {
-public:
- LA25RegAtom(const Atom *a, const File &f) : LA25Atom(f) {
- // Setup reference to fixup the LA25 stub entry.
- addReferenceELF_Mips(R_MIPS_HI16, 0, a, 0);
- addReferenceELF_Mips(R_MIPS_26, 4, a, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 8, a, 0);
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("LA25 stubs are not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> LA25RegAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsBeLA25AtomContent);
-}
-template <> ArrayRef<uint8_t> LA25RegAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsLeLA25AtomContent);
-}
-
-template <typename ELFT> class LA25MicroAtom : public LA25Atom {
-public:
- LA25MicroAtom(const Atom *a, const File &f) : LA25Atom(f) {
- // Setup reference to fixup the microMIPS LA25 stub entry.
- addReferenceELF_Mips(R_MICROMIPS_HI16, 0, a, 0);
- addReferenceELF_Mips(R_MICROMIPS_26_S1, 4, a, 0);
- addReferenceELF_Mips(R_MICROMIPS_LO16, 8, a, 0);
- }
-
- CodeModel codeModel() const override { return codeMipsMicro; }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("LA25 stubs are not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> LA25MicroAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(microMipsBeLA25AtomContent);
-}
-template <> ArrayRef<uint8_t> LA25MicroAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(microMipsLeLA25AtomContent);
-}
-
-class MipsGlobalOffsetTableAtom : public GlobalOffsetTableAtom {
-public:
- MipsGlobalOffsetTableAtom(const File &f) : GlobalOffsetTableAtom(f) {}
-
- StringRef customSectionName() const override { return ".got"; }
-};
-
-template <typename ELFT> class MipsRldAtom : public SimpleELFDefinedAtom {
-public:
- MipsRldAtom(const File &f) : SimpleELFDefinedAtom(f) {}
-
- Scope scope() const override { return scopeGlobal; }
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return ".rld_map"; }
- ContentType contentType() const override { return typeData; }
- uint64_t size() const override { return rawContent().size(); }
- ContentPermissions permissions() const override { return permRW_; }
- Alignment alignment() const override { return rawContent().size(); }
- StringRef name() const override { return "__RLD_MAP"; }
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(mipsGot0AtomContent)
- .slice(ELFT::Is64Bits ? 0 : 4);
- }
-};
-
-class RelocationPassFile : public SimpleFile {
-public:
- RelocationPassFile(const ELFLinkingContext &ctx)
- : SimpleFile("RelocationPassFile") {
- setOrdinal(ctx.getNextOrdinalAndIncrement());
- }
-
- llvm::BumpPtrAllocator _alloc;
-};
-
-template <typename ELFT> class RelocationPass : public Pass {
-public:
- RelocationPass(MipsLinkingContext &ctx);
-
- std::error_code perform(SimpleFile &mf) override;
-
-private:
- /// \brief Reference to the linking context.
- const MipsLinkingContext &_ctx;
-
- /// \brief Owner of all the Atoms created by this pass.
- RelocationPassFile _file;
-
- /// \brief Map Atoms and addend to local GOT entries.
- typedef std::pair<const Atom *, int64_t> LocalGotMapKeyT;
- llvm::DenseMap<LocalGotMapKeyT, GOTAtom *> _gotLocalMap;
- llvm::DenseMap<LocalGotMapKeyT, GOTAtom *> _gotLocalPageMap;
-
- /// \brief Map Atoms to global GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotGlobalMap;
-
- /// \brief Map Atoms to TLS GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotTLSMap;
-
- /// \brief Map Atoms to TLS GD GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotTLSGdMap;
-
- /// \brief GOT entry for the R_xxxMIPS_TLS_LDM relocations.
- GOTTLSGdAtom<ELFT> *_gotLDMEntry = nullptr;
-
- /// \brief the list of local GOT atoms.
- std::vector<GOTAtom *> _localGotVector;
-
- /// \brief the list of global GOT atoms.
- std::vector<GOTAtom *> _globalGotVector;
-
- /// \brief the list of TLS GOT atoms.
- std::vector<GOTAtom *> _tlsGotVector;
-
- /// \brief Map Atoms to their GOTPLT entries.
- llvm::DenseMap<const Atom *, GOTPLTAtom *> _gotpltMap;
-
- /// \brief Map Atoms to their PLT entries.
- llvm::DenseMap<const Atom *, PLTAAtom *> _pltRegMap;
- llvm::DenseMap<const Atom *, PLTMicroAtom<ELFT> *> _pltMicroMap;
-
- /// \brief Map Atoms to their Object entries.
- llvm::DenseMap<const Atom *, ObjectAtom *> _objectMap;
-
- /// \brief Map Atoms to their LA25 entries.
- llvm::DenseMap<const Atom *, LA25Atom *> _la25RegMap;
- llvm::DenseMap<const Atom *, LA25Atom *> _la25MicroMap;
-
- /// \brief Atoms referenced by static relocations.
- llvm::DenseSet<const Atom *> _hasStaticRelocations;
-
- /// \brief Atoms require pointers equality.
- llvm::DenseSet<const Atom *> _requiresPtrEquality;
-
- /// \brief References which are candidates for converting
- /// to the R_MIPS_REL32 relocation.
- std::vector<Reference *> _rel32Candidates;
-
- /// \brief the list of PLT atoms.
- std::vector<PLTAtom *> _pltRegVector;
- std::vector<PLTAtom *> _pltMicroVector;
-
- /// \brief the list of GOTPLT atoms.
- std::vector<GOTPLTAtom *> _gotpltVector;
-
- /// \brief the list of Object entries.
- std::vector<ObjectAtom *> _objectVector;
-
- /// \brief the list of LA25 entries.
- std::vector<LA25Atom *> _la25Vector;
-
- /// \brief Handle a specific reference.
- void handleReference(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
-
- /// \brief Collect information about the reference to use it
- /// later in the handleReference() routine.
- std::error_code collectReferenceInfo(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref);
-
- /// \brief Check that the relocation is valid for the current linking mode.
- std::error_code validateRelocation(const DefinedAtom &atom,
- const Reference &ref) const;
-
- void handlePlain(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
- void handleBranch(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
- void handleGOT(Reference &ref);
-
- const GOTAtom *getLocalGOTEntry(const Reference &ref);
- const GOTAtom *getLocalGOTPageEntry(const Reference &ref);
- const GOTAtom *getGlobalGOTEntry(const Atom *a);
- const GOTAtom *getTLSGOTEntry(const Atom *a, Reference::Addend addend);
- const GOTAtom *getTLSGdGOTEntry(const Atom *a, Reference::Addend addend);
- const GOTAtom *getTLSLdmGOTEntry(const Atom *a);
- const GOTPLTAtom *getGOTPLTEntry(const Atom *a);
- const PLTAtom *getPLTEntry(const Atom *a);
- const PLTAtom *getPLTRegEntry(const Atom *a);
- const PLTAtom *getPLTMicroEntry(const Atom *a);
- const LA25Atom *getLA25RegEntry(const Atom *a);
- const LA25Atom *getLA25MicroEntry(const Atom *a);
- const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a);
-
- PLTAtom *createPLTHeader(bool isMicroMips);
-
- bool isLocal(const Atom *a) const;
- bool isLocalCall(const Atom *a) const;
- bool isDynamic(const Atom *atom) const;
- bool requireLA25Stub(const MipsELFDefinedAtom<ELFT> &atom,
- const Reference &ref) const;
- bool requirePLTEntry(const Atom *a) const;
- bool requireCopy(const Atom *a) const;
- bool mightBeDynamic(const MipsELFDefinedAtom<ELFT> &atom,
- Reference::KindValue refKind) const;
- bool hasPLTEntry(const Atom *atom) const;
-
- /// \brief Linked files contain microMIPS code.
- bool isMicroMips();
- /// \brief Linked files contain MIPS R6 code.
- bool isMipsR6();
-};
-
-template <typename ELFT>
-RelocationPass<ELFT>::RelocationPass(MipsLinkingContext &ctx)
- : _ctx(ctx), _file(ctx) {
- _localGotVector.push_back(new (_file._alloc) GOT0Atom<ELFT>(_file));
- _localGotVector.push_back(new (_file._alloc)
- GOTModulePointerAtom<ELFT>(_file));
-}
-
-template <typename ELFT>
-std::error_code RelocationPass<ELFT>::perform(SimpleFile &mf) {
- for (const auto &atom : mf.defined())
- for (const auto &ref : *atom) {
- const auto &da = *cast<MipsELFDefinedAtom<ELFT>>(atom);
- if (auto ec = collectReferenceInfo(da, const_cast<Reference &>(*ref)))
- return ec;
- }
-
- // Process all references.
- for (const auto &atom : mf.defined())
- for (const auto &ref : *atom)
- handleReference(*cast<MipsELFDefinedAtom<ELFT>>(atom),
- const_cast<Reference &>(*ref));
-
- // Create R_MIPS_REL32 relocations.
- for (auto *ref : _rel32Candidates) {
- bool forceRel = isLocal(ref->target()) && _ctx.getOutputELFType() == ET_DYN;
- if (!forceRel && (!isDynamic(ref->target()) || hasPLTEntry(ref->target())))
- continue;
- ref->setKindValue(R_MIPS_REL32);
- if (ELFT::Is64Bits)
- static_cast<MipsELFReference<ELFT> *>(ref)->setTag(R_MIPS_64);
- if (!isLocalCall(ref->target()))
- getGlobalGOTEntry(ref->target());
- }
-
- uint64_t ordinal = 0;
-
- if (_ctx.isDynamic() && _ctx.getOutputELFType() == ET_EXEC) {
- auto rlda = new (_file._alloc) MipsRldAtom<ELFT>(_file);
- rlda->setOrdinal(ordinal++);
- mf.addAtom(*rlda);
- }
-
- if (!_localGotVector.empty() || !_globalGotVector.empty() ||
- !_tlsGotVector.empty()) {
- SimpleDefinedAtom *ga = new (_file._alloc) MipsGlobalOffsetTableAtom(_file);
- ga->setOrdinal(ordinal++);
- mf.addAtom(*ga);
- }
-
- for (auto &got : _localGotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
-
- for (auto &got : _globalGotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
-
- for (auto &got : _tlsGotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
-
- // Create and emit PLT0 entry.
- PLTAtom *plt0Atom = nullptr;
- if (!_pltRegVector.empty())
- plt0Atom = createPLTHeader(false);
- else if (!_pltMicroVector.empty())
- plt0Atom = createPLTHeader(true);
-
- if (plt0Atom) {
- plt0Atom->setOrdinal(ordinal++);
- mf.addAtom(*plt0Atom);
- }
-
- // Emit regular PLT entries firts.
- for (auto &plt : _pltRegVector) {
- plt->setOrdinal(ordinal++);
- mf.addAtom(*plt);
- }
-
- // microMIPS PLT entries come after regular ones.
- for (auto &plt : _pltMicroVector) {
- plt->setOrdinal(ordinal++);
- mf.addAtom(*plt);
- }
-
- // Assign PLT0 to GOTPLT entries.
- assert(_gotpltMap.empty() || plt0Atom);
- for (auto &a: _gotpltMap)
- a.second->setPLT0(plt0Atom);
-
- for (auto &gotplt : _gotpltVector) {
- gotplt->setOrdinal(ordinal++);
- mf.addAtom(*gotplt);
- }
-
- for (auto obj : _objectVector) {
- obj->setOrdinal(ordinal++);
- mf.addAtom(*obj);
- }
-
- for (auto la25 : _la25Vector) {
- la25->setOrdinal(ordinal++);
- mf.addAtom(*la25);
- }
-
- return std::error_code();
-}
-
-static bool isMicroMipsReloc(Reference::KindValue kind) {
- return R_MICROMIPS_26_S1 <= kind && kind <= R_MICROMIPS_PC19_S2;
-}
-
-static bool isHiLo16Reloc(Reference::KindValue kind) {
- return kind == R_MIPS_HI16 || kind == R_MIPS_LO16 || kind == R_MIPS_PCHI16 ||
- kind == R_MIPS_PCLO16 || kind == R_MICROMIPS_HI16 ||
- kind == R_MICROMIPS_LO16 || kind == R_MICROMIPS_HI0_LO16;
-}
-
-static bool isBranchReloc(Reference::KindValue kind) {
- return kind == R_MIPS_26 || kind == R_MICROMIPS_26_S1 ||
- kind == R_MIPS_PC16 || kind == R_MIPS_PC21_S2 ||
- kind == R_MIPS_PC26_S2 || kind == R_MICROMIPS_PC7_S1 ||
- kind == R_MICROMIPS_PC10_S1 || kind == R_MICROMIPS_PC16_S1 ||
- kind == R_MICROMIPS_PC23_S2;
-}
-
-static bool isGotReloc(Reference::KindValue kind) {
- return kind == R_MIPS_GOT16 || kind == R_MICROMIPS_GOT16;
-}
-
-static bool isAllGotReloc(Reference::KindValue kind) {
- return isGotReloc(kind) || kind == R_MIPS_GOT_HI16 ||
- kind == R_MIPS_GOT_LO16 || kind == R_MICROMIPS_GOT_HI16 ||
- kind == R_MICROMIPS_GOT_LO16;
-}
-
-static bool isCallReloc(Reference::KindValue kind) {
- return kind == R_MIPS_CALL16 || kind == R_MICROMIPS_CALL16;
-}
-
-static bool isAllCallReloc(Reference::KindValue kind) {
- return isCallReloc(kind) || kind == R_MIPS_CALL_HI16 ||
- kind == R_MIPS_CALL_LO16 || kind == R_MICROMIPS_CALL_HI16 ||
- kind == R_MICROMIPS_CALL_LO16;
-}
-
-static bool isGotDispReloc(Reference::KindValue kind) {
- return kind == R_MIPS_GOT_DISP || kind == R_MICROMIPS_GOT_DISP;
-}
-
-static bool isGotPageReloc(Reference::KindValue kind) {
- return kind == R_MIPS_GOT_PAGE || kind == R_MICROMIPS_GOT_PAGE;
-}
-
-static bool isTlsDtpReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_DTPREL_HI16 || kind == R_MIPS_TLS_DTPREL_LO16 ||
- kind == R_MICROMIPS_TLS_DTPREL_HI16 ||
- kind == R_MICROMIPS_TLS_DTPREL_LO16;
-}
-
-static bool isTlsTpReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_TPREL_HI16 || kind == R_MIPS_TLS_TPREL_LO16 ||
- kind == R_MICROMIPS_TLS_TPREL_HI16 ||
- kind == R_MICROMIPS_TLS_TPREL_LO16;
-}
-
-static bool isTlsGdReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_GD || kind == R_MICROMIPS_TLS_GD;
-}
-
-static bool isTlsLdmReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_LDM || kind == R_MICROMIPS_TLS_LDM;
-}
-
-static bool isTlsGotTpReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_GOTTPREL || kind == R_MICROMIPS_TLS_GOTTPREL;
-}
-
-static bool isGpRelReloc(Reference::KindValue kind) {
- return kind == R_MIPS_GPREL32 || kind == R_MIPS_GPREL16 ||
- kind == R_MICROMIPS_GPREL16 || kind == R_MICROMIPS_GPREL7_S2 ||
- kind == R_MIPS_LITERAL || kind == R_MICROMIPS_LITERAL;
-}
-
-template <typename ELFT>
-void RelocationPass<ELFT>::handleReference(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- if (!ref.target())
- return;
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return;
-
- assert(ref.kindArch() == Reference::KindArch::Mips);
- Reference::KindValue kind = ref.kindValue();
- if (isHiLo16Reloc(kind) || kind == R_MIPS_32 || kind == R_MIPS_PC32)
- handlePlain(atom, ref);
- else if (isBranchReloc(kind))
- handleBranch(atom, ref);
- else if (isAllGotReloc(kind) || isAllCallReloc(kind) ||
- isGotDispReloc(kind) || isGotPageReloc(kind) || kind == R_MIPS_EH)
- handleGOT(ref);
- else if (isTlsDtpReloc(kind))
- ref.setAddend(ref.addend() - atom.file().getDTPOffset());
- else if (isTlsTpReloc(kind))
- ref.setAddend(ref.addend() - atom.file().getTPOffset());
- else if (isTlsGdReloc(kind))
- ref.setTarget(getTLSGdGOTEntry(ref.target(), ref.addend()));
- else if (isTlsLdmReloc(kind))
- ref.setTarget(getTLSLdmGOTEntry(ref.target()));
- else if (isTlsGotTpReloc(kind))
- ref.setTarget(getTLSGOTEntry(ref.target(), ref.addend()));
- else if (kind == R_MIPS_GPREL32 || (isLocal(ref.target()) && isGpRelReloc(kind)))
- ref.setAddend(ref.addend() + atom.file().getGP0());
- else if (kind == R_MIPS_JALR) {
- if (_ctx.getOutputELFType() != ET_EXEC || !isLocalCall(ref.target()))
- ref.setKindValue(R_MIPS_NONE);
- }
-}
-
-template <typename ELFT>
-static bool isConstrainSym(const MipsELFDefinedAtom<ELFT> &atom,
- Reference::KindValue refKind) {
- if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
- return false;
- switch (refKind) {
- case R_MIPS_NONE:
- case R_MIPS_JALR:
- case R_MICROMIPS_JALR:
- case R_MIPS_GPREL16:
- case R_MIPS_GPREL32:
- case R_MICROMIPS_GPREL16:
- case R_MICROMIPS_GPREL7_S2:
- case R_MIPS_LITERAL:
- case R_MICROMIPS_LITERAL:
- return false;
- default:
- return true;
- }
-}
-
-template <typename ELFT>
-std::error_code
-RelocationPass<ELFT>::collectReferenceInfo(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- if (!ref.target())
- return std::error_code();
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return std::error_code();
-
- auto refKind = ref.kindValue();
- if (refKind == R_MIPS_EH && this->_ctx.mipsPcRelEhRel())
- ref.setKindValue(R_MIPS_PC32);
-
- if (auto ec = validateRelocation(atom, ref))
- return ec;
-
- if (!isConstrainSym(atom, refKind))
- return std::error_code();
-
- if (!mightBeDynamic(atom, refKind))
- _hasStaticRelocations.insert(ref.target());
- else if (refKind == R_MIPS_32 || refKind == R_MIPS_64)
- _rel32Candidates.push_back(&ref);
-
- if (!isBranchReloc(refKind) && !isAllCallReloc(refKind) &&
- refKind != R_MIPS_EH)
- _requiresPtrEquality.insert(ref.target());
-
- return std::error_code();
-}
-
-static std::error_code
-make_reject_for_shared_lib_reloc_error(const ELFLinkingContext &ctx,
- const DefinedAtom &atom,
- const Reference &ref) {
- StringRef kindValStr = "unknown";
- ctx.registry().referenceKindToString(ref.kindNamespace(), ref.kindArch(),
- ref.kindValue(), kindValStr);
-
- return make_dynamic_error_code(Twine(kindValStr) + " (" +
- Twine(ref.kindValue()) +
- ") relocation cannot be used "
- "when making a shared object, recompile " +
- atom.file().path() + " with -fPIC");
-}
-
-static std::error_code
-make_local_call16_reloc_error(const ELFLinkingContext &ctx,
- const DefinedAtom &atom, const Reference &ref) {
- return make_dynamic_error_code("R_MIPS_CALL16 (11) relocation cannot be used "
- "against local symbol " +
- ref.target()->name() + " in file " +
- atom.file().path());
-}
-
-template <typename ELFT>
-std::error_code
-RelocationPass<ELFT>::validateRelocation(const DefinedAtom &atom,
- const Reference &ref) const {
- if (!ref.target())
- return std::error_code();
-
- if (isCallReloc(ref.kindValue()) && isLocal(ref.target()))
- return make_local_call16_reloc_error(this->_ctx, atom, ref);
-
- if (this->_ctx.getOutputELFType() != ET_DYN)
- return std::error_code();
-
- switch (ref.kindValue()) {
- case R_MIPS16_HI16:
- case R_MIPS_HI16:
- case R_MIPS_HIGHER:
- case R_MIPS_HIGHEST:
- case R_MICROMIPS_HI16:
- case R_MICROMIPS_HIGHER:
- case R_MICROMIPS_HIGHEST:
- // For shared object we accepts "high" relocations
- // against the "_gp_disp" symbol only.
- if (ref.target()->name() != "_gp_disp")
- return make_reject_for_shared_lib_reloc_error(this->_ctx, atom, ref);
- break;
- case R_MIPS16_26:
- case R_MIPS_26:
- case R_MICROMIPS_26_S1:
- // These relocations are position dependent
- // and not acceptable in a shared object.
- return make_reject_for_shared_lib_reloc_error(this->_ctx, atom, ref);
- default:
- break;
- }
- return std::error_code();
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::isLocal(const Atom *a) const {
- if (auto *da = dyn_cast<DefinedAtom>(a))
- return da->scope() == Atom::scopeTranslationUnit;
- return false;
-}
-
-template <typename ELFT>
-static bool isMipsReadonly(const MipsELFDefinedAtom<ELFT> &atom) {
- auto secFlags = atom.section()->sh_flags;
- auto secType = atom.section()->sh_type;
-
- if ((secFlags & SHF_ALLOC) == 0)
- return false;
- if (secType == SHT_NOBITS)
- return false;
- if ((secFlags & SHF_WRITE) != 0)
- return false;
- return true;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::mightBeDynamic(const MipsELFDefinedAtom<ELFT> &atom,
- Reference::KindValue refKind) const {
- if (isAllGotReloc(refKind) || isAllCallReloc(refKind))
- return true;
-
- if (refKind != R_MIPS_32 && refKind != R_MIPS_64)
- return false;
- if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
- return false;
-
- if (_ctx.getOutputELFType() == ET_DYN)
- return true;
- if (!isMipsReadonly(atom))
- return true;
- if (atom.isPIC())
- return true;
-
- return false;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::hasPLTEntry(const Atom *atom) const {
- return _pltRegMap.count(atom) || _pltMicroMap.count(atom);
-}
-
-template <typename ELFT> bool RelocationPass<ELFT>::isMicroMips() {
- TargetHandler &handler = this->_ctx.getTargetHandler();
- return static_cast<MipsTargetHandler<ELFT> &>(handler)
- .getAbiInfoHandler()
- .isMicroMips();
-}
-
-template <typename ELFT> bool RelocationPass<ELFT>::isMipsR6() {
- TargetHandler &handler = this->_ctx.getTargetHandler();
- return static_cast<MipsTargetHandler<ELFT> &>(handler)
- .getAbiInfoHandler()
- .isMipsR6();
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::requirePLTEntry(const Atom *a) const {
- if (!_hasStaticRelocations.count(a))
- return false;
- const auto *sa = dyn_cast<ELFDynamicAtom<ELFT>>(a);
- if (sa && sa->type() != SharedLibraryAtom::Type::Code)
- return false;
- const auto *da = dyn_cast<ELFDefinedAtom<ELFT>>(a);
- if (da && da->contentType() != DefinedAtom::typeCode)
- return false;
- if (isLocalCall(a))
- return false;
- return true;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::requireCopy(const Atom *a) const {
- if (!_hasStaticRelocations.count(a))
- return false;
- const auto *sa = dyn_cast<ELFDynamicAtom<ELFT>>(a);
- return sa && sa->type() == SharedLibraryAtom::Type::Data;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::isDynamic(const Atom *atom) const {
- const auto *da = dyn_cast<const DefinedAtom>(atom);
- if (da && da->dynamicExport() == DefinedAtom::dynamicExportAlways)
- return true;
- if (isa<SharedLibraryAtom>(atom))
- return true;
- if (_ctx.getOutputELFType() != ET_DYN)
- return false;
- if (da && da->scope() != DefinedAtom::scopeTranslationUnit)
- return true;
- return isa<UndefinedAtom>(atom);
-}
-
-template <typename ELFT>
-static bool isMicroMips(const MipsELFDefinedAtom<ELFT> &atom) {
- return atom.codeModel() == DefinedAtom::codeMipsMicro ||
- atom.codeModel() == DefinedAtom::codeMipsMicroPIC;
-}
-
-template <typename ELFT>
-const PLTAtom *RelocationPass<ELFT>::getPLTEntry(const Atom *a) {
- // If file contains microMIPS code try to reuse compressed PLT entry...
- if (isMicroMips()) {
- auto microPLT = _pltMicroMap.find(a);
- if (microPLT != _pltMicroMap.end())
- return microPLT->second;
- }
-
- // ... then try to reuse a regular PLT entry ...
- auto regPLT = _pltRegMap.find(a);
- if (regPLT != _pltRegMap.end())
- return regPLT->second;
-
- // ... and finally prefer to create new compressed PLT entry.
- return isMicroMips() ? getPLTMicroEntry(a) : getPLTRegEntry(a);
-}
-
-template <typename ELFT>
-void RelocationPass<ELFT>::handlePlain(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- if (!isDynamic(ref.target()))
- return;
-
- if (requirePLTEntry(ref.target()))
- ref.setTarget(getPLTEntry(ref.target()));
- else if (requireCopy(ref.target()))
- ref.setTarget(getObjectEntry(cast<SharedLibraryAtom>(ref.target())));
-}
-
-template <typename ELFT>
-void RelocationPass<ELFT>::handleBranch(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- bool isMicro = isMicroMipsReloc(ref.kindValue());
- if (const auto *sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
- if (sla->type() == SharedLibraryAtom::Type::Code)
- ref.setTarget(isMicro ? getPLTMicroEntry(sla) : getPLTRegEntry(sla));
- } else if (requireLA25Stub(atom, ref)) {
- if (isMicro)
- ref.setTarget(getLA25MicroEntry(ref.target()));
- else
- ref.setTarget(getLA25RegEntry(ref.target()));
- }
-
- if (!isLocal(ref.target())) {
- if (ref.kindValue() == R_MICROMIPS_26_S1)
- ref.setKindValue(LLD_R_MICROMIPS_GLOBAL_26_S1);
- else if (ref.kindValue() == R_MIPS_26)
- ref.setKindValue(LLD_R_MIPS_GLOBAL_26);
- }
-}
-
-template <typename ELFT> void RelocationPass<ELFT>::handleGOT(Reference &ref) {
- if (!isLocalCall(ref.target()))
- ref.setTarget(getGlobalGOTEntry(ref.target()));
- else if (isGotPageReloc(ref.kindValue()))
- ref.setTarget(getLocalGOTPageEntry(ref));
- else if (isLocal(ref.target()) &&
- (isCallReloc(ref.kindValue()) || isGotReloc(ref.kindValue())))
- ref.setTarget(getLocalGOTPageEntry(ref));
- else
- ref.setTarget(getLocalGOTEntry(ref));
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::isLocalCall(const Atom *a) const {
- Atom::Scope scope;
- if (auto *da = dyn_cast<DefinedAtom>(a))
- scope = da->scope();
- else if (auto *aa = dyn_cast<AbsoluteAtom>(a))
- scope = aa->scope();
- else
- return false;
-
- // Local and hidden symbols must be local.
- if (scope == Atom::scopeTranslationUnit || scope == Atom::scopeLinkageUnit)
- return true;
-
- // Calls to external symbols defined in an executable file resolved locally.
- if (_ctx.getOutputELFType() == ET_EXEC)
- return true;
-
- return false;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::requireLA25Stub(const MipsELFDefinedAtom<ELFT> &atom,
- const Reference &ref) const {
- if (atom.file().isPIC())
- return false;
- if (auto *da = dyn_cast<DefinedAtom>(ref.target()))
- return static_cast<const MipsELFDefinedAtom<ELFT> *>(da)->isPIC();
- return false;
-}
-
-template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getLocalGOTEntry(const Reference &ref) {
- const Atom *a = ref.target();
- LocalGotMapKeyT key(a, ref.addend());
-
- auto got = _gotLocalMap.find(key);
- if (got != _gotLocalMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOT0Atom<ELFT>(_file);
- _gotLocalMap[key] = ga;
-
- _localGotVector.push_back(ga);
-
- Reference::KindValue relKind = ELFT::Is64Bits ? R_MIPS_64 : R_MIPS_32;
- ga->addReferenceELF_Mips(relKind, 0, a, 0);
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *
-RelocationPass<ELFT>::getLocalGOTPageEntry(const Reference &ref) {
- const Atom *a = ref.target();
- LocalGotMapKeyT key(a, ref.addend());
-
- auto got = _gotLocalPageMap.find(key);
- if (got != _gotLocalPageMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOT0Atom<ELFT>(_file);
- _gotLocalPageMap[key] = ga;
-
- _localGotVector.push_back(ga);
-
- Reference::KindValue relKind =
- ELFT::Is64Bits ? LLD_R_MIPS_64_HI16 : LLD_R_MIPS_32_HI16;
- ga->addReferenceELF_Mips(relKind, 0, a, ref.addend());
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getGlobalGOTEntry(const Atom *a) {
- auto got = _gotGlobalMap.find(a);
- if (got != _gotGlobalMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOT0Atom<ELFT>(_file);
- _gotGlobalMap[a] = ga;
-
- _globalGotVector.push_back(ga);
- ga->addReferenceELF_Mips(LLD_R_MIPS_GLOBAL_GOT, 0, a, 0);
-
- if (const DefinedAtom *da = dyn_cast<DefinedAtom>(a))
- ga->addReferenceELF_Mips(R_MIPS_32, 0, da, 0);
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getTLSGOTEntry(const Atom *a,
- Reference::Addend addend) {
- auto got = _gotTLSMap.find(a);
- if (got != _gotTLSMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOT0Atom<ELFT>(_file);
- _gotTLSMap[a] = ga;
-
- _tlsGotVector.push_back(ga);
- Reference::KindValue relKind =
- ELFT::Is64Bits ? R_MIPS_TLS_TPREL64 : R_MIPS_TLS_TPREL32;
- ga->addReferenceELF_Mips(relKind, 0, a, addend);
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *
-RelocationPass<ELFT>::getTLSGdGOTEntry(const Atom *a,
- Reference::Addend addend) {
- auto got = _gotTLSGdMap.find(a);
- if (got != _gotTLSGdMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOTTLSGdAtom<ELFT>(_file);
- _gotTLSGdMap[a] = ga;
-
- _tlsGotVector.push_back(ga);
- if (ELFT::Is64Bits) {
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD64, 0, a, addend);
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPREL64, 8, a, addend);
- } else {
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD32, 0, a, addend);
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPREL32, 4, a, addend);
- }
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getTLSLdmGOTEntry(const Atom *a) {
- if (_gotLDMEntry)
- return _gotLDMEntry;
-
- _gotLDMEntry = new (_file._alloc) GOTTLSGdAtom<ELFT>(_file);
- _tlsGotVector.push_back(_gotLDMEntry);
- if (ELFT::Is64Bits)
- _gotLDMEntry->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD64, 0, _gotLDMEntry, 0);
- else
- _gotLDMEntry->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD32, 0, _gotLDMEntry, 0);
-
- return _gotLDMEntry;
-}
-
-template <typename ELFT>
-PLTAtom *RelocationPass<ELFT>::createPLTHeader(bool isMicroMips) {
- auto ga1 = new (_file._alloc) GOTPLTAtom(_file);
- _gotpltVector.insert(_gotpltVector.begin(), ga1);
- auto ga0 = new (_file._alloc) GOTPLTAtom(_file);
- _gotpltVector.insert(_gotpltVector.begin(), ga0);
-
- if (isMicroMips)
- return new (_file._alloc) PLT0MicroAtom<ELFT>(ga0, _file);
- if (_ctx.getAbi() == MipsAbi::N32)
- return new (_file._alloc) PLT0N32Atom<ELFT>(ga0, _file);
- return new (_file._alloc) PLT0Atom<ELFT>(ga0, _file);
-}
-
-template <typename ELFT>
-const GOTPLTAtom *RelocationPass<ELFT>::getGOTPLTEntry(const Atom *a) {
- auto it = _gotpltMap.find(a);
- if (it != _gotpltMap.end())
- return it->second;
-
- auto ga = new (_file._alloc) GOTPLTAtom(a, _file);
- _gotpltMap[a] = ga;
- _gotpltVector.push_back(ga);
- return ga;
-}
-
-template <typename ELFT>
-const PLTAtom *RelocationPass<ELFT>::getPLTRegEntry(const Atom *a) {
- auto plt = _pltRegMap.find(a);
- if (plt != _pltRegMap.end())
- return plt->second;
-
- PLTAAtom *pa = nullptr;
- if (isMipsR6())
- pa = new (_file._alloc) PLTR6Atom<ELFT>(getGOTPLTEntry(a), _file);
- else
- pa = new (_file._alloc) PLTARegAtom<ELFT>(getGOTPLTEntry(a), _file);
- _pltRegMap[a] = pa;
- _pltRegVector.push_back(pa);
-
- // Check that 'a' dynamic symbol table record should point to the PLT.
- if (_hasStaticRelocations.count(a) && _requiresPtrEquality.count(a))
- pa->addReferenceELF_Mips(LLD_R_MIPS_STO_PLT, 0, a, 0);
-
- return pa;
-}
-
-template <typename ELFT>
-const PLTAtom *RelocationPass<ELFT>::getPLTMicroEntry(const Atom *a) {
- auto plt = _pltMicroMap.find(a);
- if (plt != _pltMicroMap.end())
- return plt->second;
-
- auto pa = new (_file._alloc) PLTMicroAtom<ELFT>(getGOTPLTEntry(a), _file);
- _pltMicroMap[a] = pa;
- _pltMicroVector.push_back(pa);
-
- // Check that 'a' dynamic symbol table record should point to the PLT.
- if (_hasStaticRelocations.count(a) && _requiresPtrEquality.count(a))
- pa->addReferenceELF_Mips(LLD_R_MIPS_STO_PLT, 0, a, 0);
-
- return pa;
-}
-
-template <typename ELFT>
-const LA25Atom *RelocationPass<ELFT>::getLA25RegEntry(const Atom *a) {
- auto la25 = _la25RegMap.find(a);
- if (la25 != _la25RegMap.end())
- return la25->second;
-
- auto sa = new (_file._alloc) LA25RegAtom<ELFT>(a, _file);
- _la25RegMap[a] = sa;
- _la25Vector.push_back(sa);
-
- return sa;
-}
-
-template <typename ELFT>
-const LA25Atom *RelocationPass<ELFT>::getLA25MicroEntry(const Atom *a) {
- auto la25 = _la25MicroMap.find(a);
- if (la25 != _la25MicroMap.end())
- return la25->second;
-
- auto sa = new (_file._alloc) LA25MicroAtom<ELFT>(a, _file);
- _la25MicroMap[a] = sa;
- _la25Vector.push_back(sa);
-
- return sa;
-}
-
-template <typename ELFT>
-const ObjectAtom *
-RelocationPass<ELFT>::getObjectEntry(const SharedLibraryAtom *a) {
- auto obj = _objectMap.find(a);
- if (obj != _objectMap.end())
- return obj->second;
-
- auto oa = new (_file._alloc) ObjectAtom(_file);
- oa->addReferenceELF_Mips(R_MIPS_COPY, 0, oa, 0);
- oa->_name = a->name();
- oa->_size = a->size();
-
- _objectMap[a] = oa;
- _objectVector.push_back(oa);
-
- return oa;
-}
-
-} // end anon namespace
-
-static std::unique_ptr<Pass> createPass(MipsLinkingContext &ctx) {
- switch (ctx.getTriple().getArch()) {
- case llvm::Triple::mips:
- return llvm::make_unique<RelocationPass<ELF32BE>>(ctx);
- case llvm::Triple::mipsel:
- return llvm::make_unique<RelocationPass<ELF32LE>>(ctx);
- case llvm::Triple::mips64:
- return llvm::make_unique<RelocationPass<ELF64BE>>(ctx);
- case llvm::Triple::mips64el:
- return llvm::make_unique<RelocationPass<ELF64LE>>(ctx);
- default:
- llvm_unreachable("Unhandled arch");
- }
-}
-
-std::unique_ptr<Pass>
-lld::elf::createMipsRelocationPass(MipsLinkingContext &ctx) {
- switch (ctx.getOutputELFType()) {
- case ET_EXEC:
- case ET_DYN:
- return createPass(ctx);
- case ET_REL:
- return nullptr;
- default:
- llvm_unreachable("Unhandled output file type");
- }
-}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h b/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h
deleted file mode 100644
index af343de5f027..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h ---------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_RELOCATION_PASS_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_RELOCATION_PASS_H
-
-#include <memory>
-
-namespace lld {
-class Pass;
-
-namespace elf {
-class MipsLinkingContext;
-
-std::unique_ptr<Pass> createMipsRelocationPass(MipsLinkingContext &ctx);
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp
deleted file mode 100644
index 98cc059787ef..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp --------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsLinkingContext.h"
-#include "MipsSectionChunks.h"
-#include "MipsTargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-MipsReginfoSection<ELFT>::MipsReginfoSection(
- const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
- const Elf_Mips_RegInfo &reginfo)
- : Section<ELFT>(ctx, ".reginfo", "MipsReginfo"), _reginfo(reginfo),
- _targetLayout(targetLayout) {
- this->setOrder(MipsTargetLayout<ELFT>::ORDER_MIPS_REGINFO);
- this->_entSize = sizeof(Elf_Mips_RegInfo);
- this->_fsize = sizeof(Elf_Mips_RegInfo);
- this->_msize = sizeof(Elf_Mips_RegInfo);
- this->_alignment = 4;
- this->_type = SHT_MIPS_REGINFO;
- this->_flags = SHF_ALLOC;
-}
-
-template <class ELFT>
-void MipsReginfoSection<ELFT>::write(ELFWriter *writer,
- TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
- std::memcpy(dest, &_reginfo, this->_fsize);
-}
-
-template <class ELFT> void MipsReginfoSection<ELFT>::finalize() {
- _reginfo.ri_gp_value = _targetLayout.getGPAddr();
-
- if (this->_outputSection)
- this->_outputSection->setType(this->_type);
-}
-
-template class MipsReginfoSection<ELF32BE>;
-template class MipsReginfoSection<ELF32LE>;
-template class MipsReginfoSection<ELF64BE>;
-template class MipsReginfoSection<ELF64LE>;
-
-template <class ELFT>
-MipsOptionsSection<ELFT>::MipsOptionsSection(
- const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
- const Elf_Mips_RegInfo &reginfo)
- : Section<ELFT>(ctx, ".MIPS.options", "MipsOptions"), _reginfo(reginfo),
- _targetLayout(targetLayout) {
- this->setOrder(MipsTargetLayout<ELFT>::ORDER_MIPS_OPTIONS);
- this->_entSize = 1;
- this->_alignment = 8;
- this->_fsize = llvm::RoundUpToAlignment(
- sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo), this->_alignment);
- this->_msize = this->_fsize;
- this->_type = SHT_MIPS_OPTIONS;
- this->_flags = SHF_ALLOC | SHF_MIPS_NOSTRIP;
-
- _header.kind = ODK_REGINFO;
- _header.size = this->_fsize;
- _header.section = 0;
- _header.info = 0;
-}
-
-template <class ELFT>
-void MipsOptionsSection<ELFT>::write(ELFWriter *writer,
- TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
- std::memset(dest, 0, this->_fsize);
- std::memcpy(dest, &_header, sizeof(_header));
- std::memcpy(dest + sizeof(_header), &_reginfo, sizeof(_reginfo));
-}
-
-template <class ELFT> void MipsOptionsSection<ELFT>::finalize() {
- _reginfo.ri_gp_value = _targetLayout.getGPAddr();
-
- if (this->_outputSection)
- this->_outputSection->setType(this->_type);
-}
-
-template class MipsOptionsSection<ELF32BE>;
-template class MipsOptionsSection<ELF32LE>;
-template class MipsOptionsSection<ELF64BE>;
-template class MipsOptionsSection<ELF64LE>;
-
-template <class ELFT>
-MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(
- const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
- const Elf_Mips_ABIFlags &abiFlags)
- : Section<ELFT>(ctx, ".MIPS.abiflags", "MipsAbiFlags"), _abiFlags(abiFlags),
- _targetLayout(targetLayout) {
- this->setOrder(MipsTargetLayout<ELFT>::ORDER_MIPS_ABI_FLAGS);
- this->_alignment = 8;
- this->_fsize = llvm::RoundUpToAlignment(sizeof(_abiFlags), this->_alignment);
- this->_msize = this->_fsize;
- this->_entSize = this->_fsize;
- this->_type = SHT_MIPS_ABIFLAGS;
- this->_flags = SHF_ALLOC;
-}
-
-template <class ELFT>
-void MipsAbiFlagsSection<ELFT>::write(ELFWriter *writer,
- TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
- std::memcpy(dest, &_abiFlags, this->_fsize);
-}
-
-template <class ELFT> void MipsAbiFlagsSection<ELFT>::finalize() {
- if (this->_outputSection)
- this->_outputSection->setType(this->_type);
-}
-
-template class MipsAbiFlagsSection<ELF32BE>;
-template class MipsAbiFlagsSection<ELF32LE>;
-template class MipsAbiFlagsSection<ELF64BE>;
-template class MipsAbiFlagsSection<ELF64LE>;
-
-template <class ELFT>
-MipsGOTSection<ELFT>::MipsGOTSection(const MipsLinkingContext &ctx)
- : AtomSection<ELFT>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_,
- MipsTargetLayout<ELFT>::ORDER_GOT),
- _hasNonLocal(false), _localCount(0) {
- this->_flags |= SHF_MIPS_GPREL;
- this->_alignment = 4;
-}
-
-template <class ELFT>
-bool MipsGOTSection<ELFT>::compare(const Atom *a, const Atom *b) const {
- auto ia = _posMap.find(a);
- auto ib = _posMap.find(b);
-
- if (ia != _posMap.end() && ib != _posMap.end())
- return ia->second < ib->second;
-
- return ia == _posMap.end() && ib != _posMap.end();
-}
-
-template <class ELFT>
-const AtomLayout *MipsGOTSection<ELFT>::appendAtom(const Atom *atom) {
- const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
-
- if (atom->name() == "_GLOBAL_OFFSET_TABLE_")
- return AtomSection<ELFT>::appendAtom(atom);
-
- for (const auto &r : *da) {
- if (r->kindNamespace() != Reference::KindNamespace::ELF)
- continue;
- assert(r->kindArch() == Reference::KindArch::Mips);
- switch (r->kindValue()) {
- case LLD_R_MIPS_GLOBAL_GOT:
- _hasNonLocal = true;
- _posMap[r->target()] = _posMap.size();
- return AtomSection<ELFT>::appendAtom(atom);
- case R_MIPS_TLS_TPREL32:
- case R_MIPS_TLS_DTPREL32:
- case R_MIPS_TLS_TPREL64:
- case R_MIPS_TLS_DTPREL64:
- _hasNonLocal = true;
- _tlsMap[r->target()] = _tlsMap.size();
- return AtomSection<ELFT>::appendAtom(atom);
- case R_MIPS_TLS_DTPMOD32:
- case R_MIPS_TLS_DTPMOD64:
- _hasNonLocal = true;
- break;
- }
- }
-
- if (!_hasNonLocal)
- ++_localCount;
-
- return AtomSection<ELFT>::appendAtom(atom);
-}
-
-template class MipsGOTSection<ELF32BE>;
-template class MipsGOTSection<ELF32LE>;
-template class MipsGOTSection<ELF64BE>;
-template class MipsGOTSection<ELF64LE>;
-
-template <class ELFT>
-MipsPLTSection<ELFT>::MipsPLTSection(const MipsLinkingContext &ctx)
- : AtomSection<ELFT>(ctx, ".plt", DefinedAtom::typeGOT, DefinedAtom::permR_X,
- MipsTargetLayout<ELFT>::ORDER_PLT) {}
-
-template <class ELFT>
-const AtomLayout *MipsPLTSection<ELFT>::findPLTLayout(const Atom *plt) const {
- auto it = _pltLayoutMap.find(plt);
- return it != _pltLayoutMap.end() ? it->second : nullptr;
-}
-
-template <class ELFT>
-const AtomLayout *MipsPLTSection<ELFT>::appendAtom(const Atom *atom) {
- const auto *layout = AtomSection<ELFT>::appendAtom(atom);
-
- const DefinedAtom *da = cast<DefinedAtom>(atom);
-
- for (const auto &r : *da) {
- if (r->kindNamespace() != Reference::KindNamespace::ELF)
- continue;
- assert(r->kindArch() == Reference::KindArch::Mips);
- if (r->kindValue() == LLD_R_MIPS_STO_PLT) {
- _pltLayoutMap[r->target()] = layout;
- break;
- }
- }
-
- return layout;
-}
-
-template class MipsPLTSection<ELF32BE>;
-template class MipsPLTSection<ELF32LE>;
-template class MipsPLTSection<ELF64BE>;
-template class MipsPLTSection<ELF64LE>;
-
-template <class ELFT> static bool isMips64EL() {
- return ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
-}
-
-template <class ELFT>
-MipsRelocationTable<ELFT>::MipsRelocationTable(const ELFLinkingContext &ctx,
- StringRef str, int32_t order)
- : RelocationTable<ELFT>(ctx, str, order) {}
-
-template <class ELFT>
-void MipsRelocationTable<ELFT>::writeRela(ELFWriter *writer, Elf_Rela &r,
- const DefinedAtom &atom,
- const Reference &ref) {
- uint32_t rType = ref.kindValue() | (ref.tag() << 8);
- r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType,
- isMips64EL<ELFT>());
- r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
- // The addend is used only by relative relocations
- if (this->_ctx.isRelativeReloc(ref))
- r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
- else
- r.r_addend = 0;
-}
-
-template <class ELFT>
-void MipsRelocationTable<ELFT>::writeRel(ELFWriter *writer, Elf_Rel &r,
- const DefinedAtom &atom,
- const Reference &ref) {
- uint32_t rType = ref.kindValue() | (ref.tag() << 8);
- r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType,
- isMips64EL<ELFT>());
- r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
-}
-
-template class MipsRelocationTable<ELF32BE>;
-template class MipsRelocationTable<ELF32LE>;
-template class MipsRelocationTable<ELF64BE>;
-template class MipsRelocationTable<ELF64LE>;
-
-} // elf
-} // lld
diff --git a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
deleted file mode 100644
index e545f65dc419..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
+++ /dev/null
@@ -1,150 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h ----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H
-
-#include "SectionChunks.h"
-
-namespace lld {
-namespace elf {
-
-template <typename ELFT> class MipsTargetLayout;
-class MipsLinkingContext;
-
-/// \brief Handle Mips .reginfo section
-template <class ELFT> class MipsReginfoSection : public Section<ELFT> {
-public:
- typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
-
- MipsReginfoSection(const ELFLinkingContext &ctx,
- MipsTargetLayout<ELFT> &targetLayout,
- const Elf_Mips_RegInfo &reginfo);
-
- StringRef segmentKindToStr() const override { return "REGINFO"; }
- bool hasOutputSegment() const override { return true; }
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
- void finalize() override;
-
-private:
- Elf_Mips_RegInfo _reginfo;
- MipsTargetLayout<ELFT> &_targetLayout;
-};
-
-/// \brief Handle .MIPS.options section
-template <class ELFT> class MipsOptionsSection : public Section<ELFT> {
-public:
- typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
- typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
-
- MipsOptionsSection(const ELFLinkingContext &ctx,
- MipsTargetLayout<ELFT> &targetLayout,
- const Elf_Mips_RegInfo &reginfo);
-
- bool hasOutputSegment() const override { return true; }
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
- void finalize() override;
-
-private:
- Elf_Mips_Options _header;
- Elf_Mips_RegInfo _reginfo;
- MipsTargetLayout<ELFT> &_targetLayout;
-};
-
-/// \brief Handle .MIPS.abiflags section
-template <class ELFT> class MipsAbiFlagsSection : public Section<ELFT> {
-public:
- typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
-
- MipsAbiFlagsSection(const ELFLinkingContext &ctx,
- MipsTargetLayout<ELFT> &targetLayout,
- const Elf_Mips_ABIFlags &abiFlags);
-
- bool hasOutputSegment() const override { return true; }
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
- void finalize() override;
-
-private:
- Elf_Mips_ABIFlags _abiFlags;
- MipsTargetLayout<ELFT> &_targetLayout;
-};
-
-/// \brief Handle Mips GOT section
-template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> {
-public:
- MipsGOTSection(const MipsLinkingContext &ctx);
-
- /// \brief Number of local GOT entries.
- std::size_t getLocalCount() const { return _localCount; }
-
- /// \brief Number of global GOT entries.
- std::size_t getGlobalCount() const { return _posMap.size(); }
-
- /// \brief Does the atom have a global GOT entry?
- bool hasGlobalGOTEntry(const Atom *a) const {
- return _posMap.count(a) || _tlsMap.count(a);
- }
-
- /// \brief Compare two atoms accordingly theirs positions in the GOT.
- bool compare(const Atom *a, const Atom *b) const;
-
- const AtomLayout *appendAtom(const Atom *atom) override;
-
-private:
- /// \brief True if the GOT contains non-local entries.
- bool _hasNonLocal;
-
- /// \brief Number of local GOT entries.
- std::size_t _localCount;
-
- /// \brief Map TLS Atoms to their GOT entry index.
- llvm::DenseMap<const Atom *, std::size_t> _tlsMap;
-
- /// \brief Map Atoms to their GOT entry index.
- llvm::DenseMap<const Atom *, std::size_t> _posMap;
-};
-
-/// \brief Handle Mips PLT section
-template <class ELFT> class MipsPLTSection : public AtomSection<ELFT> {
-public:
- MipsPLTSection(const MipsLinkingContext &ctx);
-
- const AtomLayout *findPLTLayout(const Atom *plt) const;
-
- const AtomLayout *appendAtom(const Atom *atom) override;
-
-private:
- /// \brief Map PLT Atoms to their layouts.
- std::unordered_map<const Atom *, const AtomLayout *> _pltLayoutMap;
-};
-
-template <class ELFT> class MipsRelocationTable : public RelocationTable<ELFT> {
- typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
-
-public:
- MipsRelocationTable(const ELFLinkingContext &ctx, StringRef str,
- int32_t order);
-
-protected:
- void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom,
- const Reference &ref) override;
- void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom,
- const Reference &ref) override;
-};
-
-} // elf
-} // lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp b/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
deleted file mode 100644
index 817e29444666..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler32EL.cpp ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ELFReader.h"
-#include "MipsELFFile.h"
-#include "MipsELFWriters.h"
-#include "MipsTargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-MipsTargetHandler<ELFT>::MipsTargetHandler(MipsLinkingContext &ctx)
- : _ctx(ctx), _targetLayout(new MipsTargetLayout<ELFT>(ctx, _abiInfoHandler)),
- _relocationHandler(
- createMipsRelocationHandler<ELFT>(ctx, *_targetLayout)) {}
-
-template <class ELFT>
-std::unique_ptr<Reader> MipsTargetHandler<ELFT>::getObjReader() {
- return llvm::make_unique<ELFReader<MipsELFFile<ELFT>>>(_ctx);
-}
-
-template <class ELFT>
-std::unique_ptr<Reader> MipsTargetHandler<ELFT>::getDSOReader() {
- return llvm::make_unique<ELFReader<DynamicFile<ELFT>>>(_ctx);
-}
-
-template <class ELFT>
-const TargetRelocationHandler &
-MipsTargetHandler<ELFT>::getRelocationHandler() const {
- return *_relocationHandler;
-}
-
-template <class ELFT>
-std::unique_ptr<Writer> MipsTargetHandler<ELFT>::getWriter() {
- switch (_ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- return llvm::make_unique<MipsExecutableWriter<ELFT>>(_ctx, *_targetLayout,
- _abiInfoHandler);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<MipsDynamicLibraryWriter<ELFT>>(
- _ctx, *_targetLayout, _abiInfoHandler);
- case llvm::ELF::ET_REL:
- llvm_unreachable("TODO: support -r mode");
- default:
- llvm_unreachable("unsupported output type");
- }
-}
-
-template <class ELFT> MipsAbi MipsTargetHandler<ELFT>::getAbi() const {
- return _abiInfoHandler.getAbi();
-}
-
-template class MipsTargetHandler<ELF32BE>;
-template class MipsTargetHandler<ELF32LE>;
-template class MipsTargetHandler<ELF64BE>;
-template class MipsTargetHandler<ELF64LE>;
-
-template <class ELFT>
-MipsSymbolTable<ELFT>::MipsSymbolTable(const ELFLinkingContext &ctx)
- : SymbolTable<ELFT>(ctx, ".symtab",
- TargetLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
-
-template <class ELFT>
-void MipsSymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) {
- SymbolTable<ELFT>::addDefinedAtom(sym, da, addr);
-
- switch (da->codeModel()) {
- case DefinedAtom::codeMipsMicro:
- sym.st_other |= llvm::ELF::STO_MIPS_MICROMIPS;
- break;
- case DefinedAtom::codeMipsMicroPIC:
- sym.st_other |= llvm::ELF::STO_MIPS_MICROMIPS | llvm::ELF::STO_MIPS_PIC;
- break;
- default:
- break;
- }
-}
-
-template <class ELFT> void MipsSymbolTable<ELFT>::finalize(bool sort) {
- SymbolTable<ELFT>::finalize(sort);
-
- for (auto &ste : this->_symbolTable) {
- if (!ste._atom)
- continue;
- if (const auto *da = dyn_cast<DefinedAtom>(ste._atom)) {
- if (da->codeModel() == DefinedAtom::codeMipsMicro ||
- da->codeModel() == DefinedAtom::codeMipsMicroPIC) {
- // Adjust dynamic microMIPS symbol value. That allows a dynamic
- // linker to recognize and handle this symbol correctly.
- ste._symbol.st_value = ste._symbol.st_value | 1;
- }
- }
- }
-}
-
-template class MipsSymbolTable<ELF32BE>;
-template class MipsSymbolTable<ELF32LE>;
-template class MipsSymbolTable<ELF64BE>;
-template class MipsSymbolTable<ELF64LE>;
-
-template <class ELFT>
-MipsDynamicSymbolTable<ELFT>::MipsDynamicSymbolTable(
- const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
- : DynamicSymbolTable<ELFT>(ctx, layout, ".dynsym",
- TargetLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS),
- _targetLayout(layout) {}
-
-template <class ELFT> void MipsDynamicSymbolTable<ELFT>::sortSymbols() {
- typedef typename DynamicSymbolTable<ELFT>::SymbolEntry SymbolEntry;
- std::stable_sort(this->_symbolTable.begin(), this->_symbolTable.end(),
- [this](const SymbolEntry &A, const SymbolEntry &B) {
- if (A._symbol.getBinding() != STB_GLOBAL &&
- B._symbol.getBinding() != STB_GLOBAL)
- return A._symbol.getBinding() < B._symbol.getBinding();
-
- return _targetLayout.getGOTSection().compare(A._atom,
- B._atom);
- });
-}
-
-template <class ELFT> void MipsDynamicSymbolTable<ELFT>::finalize() {
- DynamicSymbolTable<ELFT>::finalize();
-
- const auto &pltSection = _targetLayout.getPLTSection();
-
- for (auto &ste : this->_symbolTable) {
- const Atom *a = ste._atom;
- if (!a)
- continue;
- if (auto *layout = pltSection.findPLTLayout(a)) {
- a = layout->_atom;
- // Under some conditions a dynamic symbol table record should hold
- // a symbol value of the corresponding PLT entry. For details look
- // at the PLT entry creation code in the class MipsRelocationPass.
- // Let's update atomLayout fields for such symbols.
- assert(!ste._atomLayout);
- ste._symbol.st_value = layout->_virtualAddr;
- ste._symbol.st_other |= ELF::STO_MIPS_PLT;
- }
-
- if (const auto *da = dyn_cast<DefinedAtom>(a)) {
- if (da->codeModel() == DefinedAtom::codeMipsMicro ||
- da->codeModel() == DefinedAtom::codeMipsMicroPIC) {
- // Adjust dynamic microMIPS symbol value. That allows a dynamic
- // linker to recognize and handle this symbol correctly.
- ste._symbol.st_value = ste._symbol.st_value | 1;
- }
- }
- }
-}
-
-template class MipsDynamicSymbolTable<ELF32BE>;
-template class MipsDynamicSymbolTable<ELF32LE>;
-template class MipsDynamicSymbolTable<ELF64BE>;
-template class MipsDynamicSymbolTable<ELF64LE>;
-
-}
-}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h b/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
deleted file mode 100644
index e4a35bdd323d..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h ----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
-
-#include "MipsAbiInfoHandler.h"
-#include "MipsLinkingContext.h"
-#include "MipsTargetLayout.h"
-#include "TargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-class MipsBaseTargetHandler : public TargetHandler {
-public:
- virtual MipsAbi getAbi() const = 0;
-};
-
-/// \brief TargetHandler for Mips
-template <class ELFT>
-class MipsTargetHandler final : public MipsBaseTargetHandler {
-public:
- MipsTargetHandler(MipsLinkingContext &ctx);
-
- MipsAbiInfoHandler<ELFT> &getAbiInfoHandler() { return _abiInfoHandler; }
-
- std::unique_ptr<Reader> getObjReader() override;
- std::unique_ptr<Reader> getDSOReader() override;
- const TargetRelocationHandler &getRelocationHandler() const override;
- std::unique_ptr<Writer> getWriter() override;
- MipsAbi getAbi() const override;
-
-private:
- MipsLinkingContext &_ctx;
- MipsAbiInfoHandler<ELFT> _abiInfoHandler;
- std::unique_ptr<MipsTargetLayout<ELFT>> _targetLayout;
- std::unique_ptr<TargetRelocationHandler> _relocationHandler;
-};
-
-template <class ELFT> class MipsSymbolTable : public SymbolTable<ELFT> {
-public:
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
- MipsSymbolTable(const ELFLinkingContext &ctx);
-
- void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) override;
- void finalize(bool sort) override;
-};
-
-template <class ELFT>
-class MipsDynamicSymbolTable : public DynamicSymbolTable<ELFT> {
-public:
- MipsDynamicSymbolTable(const ELFLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout);
-
- void sortSymbols() override;
- void finalize() override;
-
-private:
- MipsTargetLayout<ELFT> &_targetLayout;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp b/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
deleted file mode 100644
index 710f8320a8b9..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp ---------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsLinkingContext.h"
-#include "MipsTargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-MipsTargetLayout<ELFT>::MipsTargetLayout(MipsLinkingContext &ctx,
- MipsAbiInfoHandler<ELFT> &abi)
- : TargetLayout<ELFT>(ctx), _abiInfo(abi),
- _gotSection(new (this->_allocator) MipsGOTSection<ELFT>(ctx)),
- _pltSection(new (this->_allocator) MipsPLTSection<ELFT>(ctx)) {}
-
-template <class ELFT>
-AtomSection<ELFT> *MipsTargetLayout<ELFT>::createSection(
- StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions,
- typename TargetLayout<ELFT>::SectionOrder order) {
- if (type == DefinedAtom::typeGOT && name == ".got")
- return _gotSection;
- if (type == DefinedAtom::typeStub && name == ".plt")
- return _pltSection;
- return TargetLayout<ELFT>::createSection(name, type, permissions, order);
-}
-
-template <class ELFT>
-typename TargetLayout<ELFT>::SegmentType
-MipsTargetLayout<ELFT>::getSegmentType(const Section<ELFT> *section) const {
- switch (section->order()) {
- case ORDER_MIPS_REGINFO:
- return _abiInfo.hasMipsAbiSection() ? llvm::ELF::PT_LOAD
- : llvm::ELF::PT_MIPS_REGINFO;
- case ORDER_MIPS_OPTIONS:
- return llvm::ELF::PT_LOAD;
- case ORDER_MIPS_ABI_FLAGS:
- return llvm::ELF::PT_MIPS_ABIFLAGS;
- default:
- return TargetLayout<ELFT>::getSegmentType(section);
- }
-}
-
-template <class ELFT> uint64_t MipsTargetLayout<ELFT>::getGPAddr() {
- std::call_once(_gpOnce, [this]() {
- if (AtomLayout *a = this->findAbsoluteAtom("_gp"))
- _gpAddr = a->_virtualAddr;
- });
- return _gpAddr;
-}
-
-template <class ELFT>
-typename TargetLayout<ELFT>::SectionOrder
-MipsTargetLayout<ELFT>::getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPermissions) {
- if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text")))
- return TargetLayout<ELFT>::ORDER_TEXT;
-
- return TargetLayout<ELFT>::getSectionOrder(name, contentType,
- contentPermissions);
-}
-
-template <class ELFT>
-unique_bump_ptr<RelocationTable<ELFT>>
-MipsTargetLayout<ELFT>::createRelocationTable(StringRef name, int32_t order) {
- return unique_bump_ptr<RelocationTable<ELFT>>(new (
- this->_allocator) MipsRelocationTable<ELFT>(this->_ctx, name, order));
-}
-
-template <class ELFT>
-uint64_t MipsTargetLayout<ELFT>::getLookupSectionFlags(
- const OutputSection<ELFT> *os) const {
- uint64_t flags = TargetLayout<ELFT>::getLookupSectionFlags(os);
- return flags & ~llvm::ELF::SHF_MIPS_NOSTRIP;
-}
-
-template <class ELFT> void MipsTargetLayout<ELFT>::sortSegments() {
- using namespace llvm::ELF;
- TargetLayout<ELFT>::sortSegments();
- // Move PT_MIPS_ABIFLAGS or PT_MIPS_REGINFO right after PT_INTERP.
- auto abiIt =
- std::find_if(this->_segments.begin(), this->_segments.end(),
- [](const Segment<ELFT> *s) {
- auto typ = s->segmentType();
- return typ == PT_MIPS_ABIFLAGS || typ == PT_MIPS_REGINFO;
- });
- if (abiIt == this->_segments.end())
- return;
- Segment<ELFT> *abiSeg = *abiIt;
- this->_segments.erase(abiIt);
- auto outIt = std::find_if(this->_segments.begin(), this->_segments.end(),
- [](const Segment<ELFT> *s) {
- auto typ = s->segmentType();
- return typ != PT_PHDR && typ != PT_INTERP;
- });
- this->_segments.insert(outIt, abiSeg);
-}
-
-template class MipsTargetLayout<ELF32BE>;
-template class MipsTargetLayout<ELF32LE>;
-template class MipsTargetLayout<ELF64BE>;
-template class MipsTargetLayout<ELF64LE>;
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h b/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h
deleted file mode 100644
index 08855438d20e..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h -----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_LAYOUT_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_LAYOUT_H
-
-#include "MipsAbiInfoHandler.h"
-#include "MipsSectionChunks.h"
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-class MipsLinkingContext;
-
-/// \brief TargetLayout for Mips
-template <class ELFT> class MipsTargetLayout final : public TargetLayout<ELFT> {
-public:
- enum MipsSectionOrder {
- ORDER_MIPS_ABI_FLAGS = TargetLayout<ELFT>::ORDER_RO_NOTE + 1,
- ORDER_MIPS_REGINFO,
- ORDER_MIPS_OPTIONS,
- };
-
- MipsTargetLayout(MipsLinkingContext &ctx, MipsAbiInfoHandler<ELFT> &abi);
-
- const MipsGOTSection<ELFT> &getGOTSection() const { return *_gotSection; }
- const MipsPLTSection<ELFT> &getPLTSection() const { return *_pltSection; }
-
- AtomSection<ELFT> *
- createSection(StringRef name, int32_t type,
- DefinedAtom::ContentPermissions permissions,
- typename TargetLayout<ELFT>::SectionOrder order) override;
-
- typename TargetLayout<ELFT>::SegmentType
- getSegmentType(const Section<ELFT> *section) const override;
-
- /// \brief GP offset relative to .got section.
- uint64_t getGPOffset() const { return 0x7FF0; }
-
- /// \brief Get '_gp' symbol address.
- uint64_t getGPAddr();
-
- /// \brief Return the section order for a input section
- typename TargetLayout<ELFT>::SectionOrder
- getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPermissions) override;
-
-protected:
- unique_bump_ptr<RelocationTable<ELFT>>
- createRelocationTable(StringRef name, int32_t order) override;
- uint64_t getLookupSectionFlags(const OutputSection<ELFT> *os) const override;
- void sortSegments() override;
-
-private:
- MipsAbiInfoHandler<ELFT> &_abiInfo;
- MipsGOTSection<ELFT> *_gotSection;
- MipsPLTSection<ELFT> *_pltSection;
- uint64_t _gpAddr = 0;
- std::once_flag _gpOnce;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/OrderPass.h b/lib/ReaderWriter/ELF/OrderPass.h
deleted file mode 100644
index 11f88056c8c4..000000000000
--- a/lib/ReaderWriter/ELF/OrderPass.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- lib/ReaderWriter/ELF/OrderPass.h -----------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_ORDER_PASS_H
-#define LLD_READER_WRITER_ELF_ORDER_PASS_H
-
-#include "lld/Core/Parallel.h"
-#include <limits>
-
-namespace lld {
-namespace elf {
-
-/// \brief This pass sorts atoms by file and atom ordinals.
-class OrderPass : public Pass {
-public:
- std::error_code perform(SimpleFile &file) override {
- parallel_sort(file.definedAtoms().begin(), file.definedAtoms().end(),
- DefinedAtom::compareByPosition);
- return std::error_code();
- }
-};
-}
-}
-
-#endif
diff --git a/lib/ReaderWriter/ELF/OutputELFWriter.cpp b/lib/ReaderWriter/ELF/OutputELFWriter.cpp
deleted file mode 100644
index 4f8b0eac655f..000000000000
--- a/lib/ReaderWriter/ELF/OutputELFWriter.cpp
+++ /dev/null
@@ -1,514 +0,0 @@
-//===- lib/ReaderWriter/ELF/OutputELFWriter.cpp --------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "OutputELFWriter.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Support/Path.h"
-
-namespace lld {
-namespace elf {
-
-namespace {
-
-template <class ELFT> class SymbolFile : public RuntimeFile<ELFT> {
-public:
- SymbolFile(ELFLinkingContext &ctx)
- : RuntimeFile<ELFT>(ctx, "Dynamic absolute symbols") {}
-
- void addUndefinedAtom(StringRef) override {
- llvm_unreachable("Cannot add undefined atoms to resolve undefined symbols");
- }
-
- bool hasAtoms() const { return this->absolute().size(); }
-};
-
-template <class ELFT>
-class DynamicSymbolFile : public SimpleArchiveLibraryFile {
- typedef std::function<void(StringRef, RuntimeFile<ELFT> &)> Resolver;
-
-public:
- DynamicSymbolFile(ELFLinkingContext &ctx, Resolver resolver)
- : SimpleArchiveLibraryFile("Dynamically added runtime symbols"),
- _ctx(ctx), _resolver(resolver) {}
-
- File *find(StringRef sym, bool dataSymbolOnly) override {
- if (!_file)
- _file.reset(new (_alloc) SymbolFile<ELFT>(_ctx));
-
- assert(!_file->hasAtoms() && "The file shouldn't have atoms yet");
- _resolver(sym, *_file);
-
- if (!_file->hasAtoms())
- return nullptr;
-
- // If atoms were added - return the file but also store it for later
- // destruction.
- File *result = _file.get();
- _returnedFiles.push_back(std::move(_file));
- return result;
- }
-
-private:
- ELFLinkingContext &_ctx;
- Resolver _resolver;
-
- // The allocator should go before bump pointers because of
- // reversed destruction order.
- llvm::BumpPtrAllocator _alloc;
- unique_bump_ptr<SymbolFile<ELFT>> _file;
- std::vector<unique_bump_ptr<SymbolFile<ELFT>>> _returnedFiles;
-};
-
-} // end anon namespace
-
-template <class ELFT>
-OutputELFWriter<ELFT>::OutputELFWriter(ELFLinkingContext &ctx,
- TargetLayout<ELFT> &layout)
- : _ctx(ctx), _targetHandler(ctx.getTargetHandler()), _layout(layout) {}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::buildChunks(const File &file) {
- ScopedTask task(getDefaultDomain(), "buildChunks");
- for (const DefinedAtom *definedAtom : file.defined()) {
- DefinedAtom::ContentType contentType = definedAtom->contentType();
- // Dont add COMDAT group atoms and GNU linkonce atoms, as they are used for
- // symbol resolution.
- // TODO: handle partial linking.
- if (contentType == DefinedAtom::typeGroupComdat ||
- contentType == DefinedAtom::typeGnuLinkOnce)
- continue;
- _layout.addAtom(definedAtom);
- }
- for (const AbsoluteAtom *absoluteAtom : file.absolute())
- _layout.addAtom(absoluteAtom);
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::buildStaticSymbolTable(const File &file) {
- ScopedTask task(getDefaultDomain(), "buildStaticSymbolTable");
- for (auto sec : _layout.sections())
- if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
- for (const auto &atom : section->atoms())
- _symtab->addSymbol(atom->_atom, section->ordinal(), atom->_virtualAddr);
- for (auto &atom : _layout.absoluteAtoms())
- _symtab->addSymbol(atom->_atom, ELF::SHN_ABS, atom->_virtualAddr);
- for (const UndefinedAtom *a : file.undefined())
- _symtab->addSymbol(a, ELF::SHN_UNDEF);
-}
-
-// Returns the DSO name for a given input file if it's a shared library
-// file and not marked as --as-needed.
-template <class ELFT>
-StringRef OutputELFWriter<ELFT>::maybeGetSOName(Node *node) {
- if (auto *fnode = dyn_cast<FileNode>(node))
- if (!fnode->asNeeded())
- if (auto *file = dyn_cast<SharedLibraryFile>(fnode->getFile()))
- return file->getDSOName();
- return "";
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
- ScopedTask task(getDefaultDomain(), "buildDynamicSymbolTable");
- for (const auto &sla : file.sharedLibrary()) {
- if (isDynSymEntryRequired(sla)) {
- _dynamicSymbolTable->addSymbol(sla, ELF::SHN_UNDEF);
- _soNeeded.insert(sla->loadName());
- continue;
- }
- if (isNeededTagRequired(sla))
- _soNeeded.insert(sla->loadName());
- }
- for (const std::unique_ptr<Node> &node : _ctx.getNodes()) {
- StringRef soname = maybeGetSOName(node.get());
- if (!soname.empty())
- _soNeeded.insert(soname);
- }
- // Never mark the dynamic linker as DT_NEEDED
- _soNeeded.erase(sys::path::filename(_ctx.getInterpreter()));
- for (const auto &loadName : _soNeeded)
- _dynamicTable->addEntry(DT_NEEDED,
- _dynamicStringTable->addString(loadName.getKey()));
- const auto &rpathList = _ctx.getRpathList();
- if (!rpathList.empty()) {
- auto rpath =
- new (_alloc) std::string(join(rpathList.begin(), rpathList.end(), ":"));
- _dynamicTable->addEntry(_ctx.getEnableNewDtags() ? DT_RUNPATH : DT_RPATH,
- _dynamicStringTable->addString(*rpath));
- }
- StringRef soname = _ctx.sharedObjectName();
- if (!soname.empty() && _ctx.getOutputELFType() == llvm::ELF::ET_DYN)
- _dynamicTable->addEntry(DT_SONAME, _dynamicStringTable->addString(soname));
-
- // Add DT_FLAGS/DT_FLAGS_1 entries if necessary.
- uint32_t dtflags = 0, dt1flags = 0;
- if (_ctx.getDTFlag(ELFLinkingContext::DTFlag::DT_NOW)) {
- dtflags |= DF_BIND_NOW;
- dt1flags |= DF_1_NOW;
- }
- if (_ctx.getDTFlag(ELFLinkingContext::DTFlag::DT_ORIGIN)) {
- dtflags |= DF_ORIGIN;
- dt1flags |= DF_1_ORIGIN;
- }
- if (dtflags != 0)
- _dynamicTable->addEntry(DT_FLAGS, dtflags);
- if (dt1flags != 0)
- _dynamicTable->addEntry(DT_FLAGS_1, dt1flags);
-
- // The dynamic symbol table need to be sorted earlier because the hash
- // table needs to be built using the dynamic symbol table. It would be
- // late to sort the symbols due to that in finalize. In the dynamic symbol
- // table finalize, we call the symbol table finalize and we don't want to
- // sort again
- _dynamicSymbolTable->sortSymbols();
-
- // Add the dynamic symbols into the hash table
- _dynamicSymbolTable->addSymbolsToHashTable();
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::buildAtomToAddressMap(const File &file) {
- ScopedTask task(getDefaultDomain(), "buildAtomToAddressMap");
- int64_t totalAbsAtoms = _layout.absoluteAtoms().size();
- int64_t totalUndefinedAtoms = file.undefined().size();
- int64_t totalDefinedAtoms = 0;
- for (auto sec : _layout.sections())
- if (auto section = dyn_cast<AtomSection<ELFT>>(sec)) {
- totalDefinedAtoms += section->atoms().size();
- for (const auto &atom : section->atoms())
- _atomToAddressMap[atom->_atom] = atom->_virtualAddr;
- }
- // build the atomToAddressMap that contains absolute symbols too
- for (auto &atom : _layout.absoluteAtoms())
- _atomToAddressMap[atom->_atom] = atom->_virtualAddr;
-
- // Set the total number of atoms in the symbol table, so that appropriate
- // resizing of the string table can be done.
- // There's no such thing as symbol table if we're stripping all the symbols
- if (!_ctx.stripSymbols())
- _symtab->setNumEntries(totalDefinedAtoms + totalAbsAtoms +
- totalUndefinedAtoms);
-}
-
-template <class ELFT> void OutputELFWriter<ELFT>::buildSectionHeaderTable() {
- ScopedTask task(getDefaultDomain(), "buildSectionHeaderTable");
- for (auto outputSection : _layout.outputSections()) {
- if (outputSection->kind() != Chunk<ELFT>::Kind::ELFSection &&
- outputSection->kind() != Chunk<ELFT>::Kind::AtomSection)
- continue;
- if (outputSection->hasSegment())
- _shdrtab->appendSection(outputSection);
- }
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::assignSectionsWithNoSegments() {
- ScopedTask task(getDefaultDomain(), "assignSectionsWithNoSegments");
- for (auto outputSection : _layout.outputSections()) {
- if (outputSection->kind() != Chunk<ELFT>::Kind::ELFSection &&
- outputSection->kind() != Chunk<ELFT>::Kind::AtomSection)
- continue;
- if (!outputSection->hasSegment())
- _shdrtab->appendSection(outputSection);
- }
- _layout.assignFileOffsetsForMiscSections();
- for (auto sec : _layout.sections())
- if (auto section = dyn_cast<Section<ELFT>>(sec))
- if (!TargetLayout<ELFT>::hasOutputSegment(section))
- _shdrtab->updateSection(section);
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- // Add the virtual archive to resolve undefined symbols.
- // The file will be added later in the linking context.
- auto callback = [this](StringRef sym, RuntimeFile<ELFT> &file) {
- processUndefinedSymbol(sym, file);
- };
- _ctx.setUndefinesResolver(
- llvm::make_unique<DynamicSymbolFile<ELFT>>(_ctx, std::move(callback)));
- // Add script defined symbols
- auto file =
- llvm::make_unique<RuntimeFile<ELFT>>(_ctx, "Linker script runtime");
- for (auto &sym : this->_ctx.linkerScriptSema().getScriptDefinedSymbols())
- file->addAbsoluteAtom(sym.getKey());
- result.push_back(std::move(file));
-}
-
-template <class ELFT> void OutputELFWriter<ELFT>::finalizeDefaultAtomValues() {
- const llvm::StringSet<> &symbols =
- _ctx.linkerScriptSema().getScriptDefinedSymbols();
- for (auto &sym : symbols) {
- uint64_t res =
- _ctx.linkerScriptSema().getLinkerScriptExprValue(sym.getKey());
- AtomLayout *a = _layout.findAbsoluteAtom(sym.getKey());
- assert(a);
- a->_virtualAddr = res;
- }
- // If there is a section named XXX, and XXX is a valid C identifier,
- // and there are undefined or weak __start_XXX/__stop_XXX symbols,
- // set the symbols values to the begin/end of the XXX section
- // correspondingly.
- for (const auto &name : _ctx.cidentSectionNames())
- updateScopeAtomValues((Twine("__start_") + name.getKey()).str(),
- (Twine("__stop_") + name.getKey()).str(),
- name.getKey());
-}
-
-template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
- _elfHeader.reset(new (_alloc) ELFHeader<ELFT>(_ctx));
- _programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_ctx));
- _layout.setHeader(_elfHeader.get());
- _layout.setProgramHeader(_programHeader.get());
-
- // Don't create .symtab and .strtab sections if we're going to
- // strip all the symbols.
- if (!_ctx.stripSymbols()) {
- _symtab = this->createSymbolTable();
- _strtab.reset(new (_alloc) StringTable<ELFT>(
- _ctx, ".strtab", TargetLayout<ELFT>::ORDER_STRING_TABLE));
- _layout.addSection(_symtab.get());
- _layout.addSection(_strtab.get());
- _symtab->setStringSection(_strtab.get());
- }
-
- _shstrtab.reset(new (_alloc) StringTable<ELFT>(
- _ctx, ".shstrtab", TargetLayout<ELFT>::ORDER_SECTION_STRINGS));
- _shdrtab.reset(new (_alloc) SectionHeader<ELFT>(
- _ctx, TargetLayout<ELFT>::ORDER_SECTION_HEADERS));
- _layout.addSection(_shstrtab.get());
- _shdrtab->setStringSection(_shstrtab.get());
- _layout.addSection(_shdrtab.get());
-
- for (auto sec : _layout.sections()) {
- // TODO: use findOutputSection
- auto section = dyn_cast<Section<ELFT>>(sec);
- if (!section || section->outputSectionName() != ".eh_frame")
- continue;
- _ehFrameHeader.reset(new (_alloc) EHFrameHeader<ELFT>(
- _ctx, ".eh_frame_hdr", _layout, TargetLayout<ELFT>::ORDER_EH_FRAMEHDR));
- _layout.addSection(_ehFrameHeader.get());
- break;
- }
-
- if (_ctx.isDynamic()) {
- _dynamicTable = createDynamicTable();
- _dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
- _ctx, ".dynstr", TargetLayout<ELFT>::ORDER_DYNAMIC_STRINGS, true));
- _dynamicSymbolTable = createDynamicSymbolTable();
- _hashTable.reset(new (_alloc) HashSection<ELFT>(
- _ctx, ".hash", TargetLayout<ELFT>::ORDER_HASH));
- // Set the hash table in the dynamic symbol table so that the entries in the
- // hash table can be created
- _dynamicSymbolTable->setHashTable(_hashTable.get());
- _hashTable->setSymbolTable(_dynamicSymbolTable.get());
- _layout.addSection(_dynamicTable.get());
- _layout.addSection(_dynamicStringTable.get());
- _layout.addSection(_dynamicSymbolTable.get());
- _layout.addSection(_hashTable.get());
- _dynamicSymbolTable->setStringSection(_dynamicStringTable.get());
- _dynamicTable->setSymbolTable(_dynamicSymbolTable.get());
- _dynamicTable->setHashTable(_hashTable.get());
- if (_layout.hasDynamicRelocationTable())
- _layout.getDynamicRelocationTable()->setSymbolTable(
- _dynamicSymbolTable.get());
- if (_layout.hasPLTRelocationTable())
- _layout.getPLTRelocationTable()->setSymbolTable(
- _dynamicSymbolTable.get());
- }
-}
-
-template <class ELFT>
-unique_bump_ptr<SymbolTable<ELFT>> OutputELFWriter<ELFT>::createSymbolTable() {
- return unique_bump_ptr<SymbolTable<ELFT>>(new (_alloc) SymbolTable<ELFT>(
- this->_ctx, ".symtab", TargetLayout<ELFT>::ORDER_SYMBOL_TABLE));
-}
-
-/// \brief create dynamic table
-template <class ELFT>
-unique_bump_ptr<DynamicTable<ELFT>>
-OutputELFWriter<ELFT>::createDynamicTable() {
- return unique_bump_ptr<DynamicTable<ELFT>>(new (_alloc) DynamicTable<ELFT>(
- this->_ctx, _layout, ".dynamic", TargetLayout<ELFT>::ORDER_DYNAMIC));
-}
-
-/// \brief create dynamic symbol table
-template <class ELFT>
-unique_bump_ptr<DynamicSymbolTable<ELFT>>
-OutputELFWriter<ELFT>::createDynamicSymbolTable() {
- return unique_bump_ptr<DynamicSymbolTable<ELFT>>(
- new (_alloc)
- DynamicSymbolTable<ELFT>(this->_ctx, _layout, ".dynsym",
- TargetLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
-}
-
-template <class ELFT>
-std::error_code OutputELFWriter<ELFT>::buildOutput(const File &file) {
- ScopedTask buildTask(getDefaultDomain(), "ELF Writer buildOutput");
- buildChunks(file);
-
- // Create the default sections like the symbol table, string table, and the
- // section string table
- createDefaultSections();
-
- // Set the Layout
- _layout.assignSectionsToSegments();
-
- // Create the dynamic table entries
- if (_ctx.isDynamic()) {
- _dynamicTable->createDefaultEntries();
- buildDynamicSymbolTable(file);
- }
-
- // Call the preFlight callbacks to modify the sections and the atoms
- // contained in them, in anyway the targets may want
- _layout.doPreFlight();
-
- _layout.assignVirtualAddress();
-
- // Finalize the default value of symbols that the linker adds
- finalizeDefaultAtomValues();
-
- // Build the Atom To Address map for applying relocations
- buildAtomToAddressMap(file);
-
- // Create symbol table and section string table
- // Do it only if -s is not specified.
- if (!_ctx.stripSymbols())
- buildStaticSymbolTable(file);
-
- // Finalize the layout by calling the finalize() functions
- _layout.finalize();
-
- // build Section Header table
- buildSectionHeaderTable();
-
- // assign Offsets and virtual addresses
- // for sections with no segments
- assignSectionsWithNoSegments();
-
- if (_ctx.isDynamic())
- _dynamicTable->updateDynamicTable();
-
- return std::error_code();
-}
-
-template <class ELFT> std::error_code OutputELFWriter<ELFT>::setELFHeader() {
- _elfHeader->e_type(_ctx.getOutputELFType());
- _elfHeader->e_machine(_ctx.getOutputMachine());
- _elfHeader->e_ident(ELF::EI_VERSION, 1);
- _elfHeader->e_ident(ELF::EI_OSABI, 0);
- _elfHeader->e_version(1);
- _elfHeader->e_phoff(_programHeader->fileOffset());
- _elfHeader->e_shoff(_shdrtab->fileOffset());
- _elfHeader->e_phentsize(_programHeader->entsize());
- _elfHeader->e_phnum(_programHeader->numHeaders());
- _elfHeader->e_shentsize(_shdrtab->entsize());
- _elfHeader->e_shnum(_shdrtab->numHeaders());
- _elfHeader->e_shstrndx(_shstrtab->ordinal());
- if (const auto *al = _layout.findAtomLayoutByName(_ctx.entrySymbolName()))
- _elfHeader->e_entry(al->_virtualAddr);
- else
- _elfHeader->e_entry(0);
-
- return std::error_code();
-}
-
-template <class ELFT> uint64_t OutputELFWriter<ELFT>::outputFileSize() const {
- return _shdrtab->fileOffset() + _shdrtab->fileSize();
-}
-
-template <class ELFT>
-std::error_code OutputELFWriter<ELFT>::writeOutput(const File &file,
- StringRef path) {
-
- ScopedTask createOutputTask(getDefaultDomain(), "ELF Writer Create Output");
- ErrorOr<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
- FileOutputBuffer::create(path, outputFileSize(),
- FileOutputBuffer::F_executable);
- if (std::error_code ec = bufferOrErr.getError())
- return ec;
- std::unique_ptr<FileOutputBuffer> &buffer = *bufferOrErr;
- createOutputTask.end();
-
- ScopedTask writeTask(getDefaultDomain(), "ELF Writer write to memory");
-
- // HACK: We have to write out the header and program header here even though
- // they are a member of a segment because only sections are written in the
- // following loop.
-
- // Finalize ELF Header / Program Headers.
- _elfHeader->finalize();
- _programHeader->finalize();
-
- _elfHeader->write(this, _layout, *buffer);
- _programHeader->write(this, _layout, *buffer);
-
- auto sections = _layout.sections();
- parallel_for_each(
- sections.begin(), sections.end(),
- [&](Chunk<ELFT> *section) { section->write(this, _layout, *buffer); });
- writeTask.end();
-
- ScopedTask commitTask(getDefaultDomain(), "ELF Writer commit to disk");
- return buffer->commit();
-}
-
-template <class ELFT>
-std::error_code OutputELFWriter<ELFT>::writeFile(const File &file,
- StringRef path) {
- if (std::error_code ec = buildOutput(file))
- return ec;
- if (std::error_code ec = setELFHeader())
- return ec;
- return writeOutput(file, path);
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::processUndefinedSymbol(
- StringRef symName, RuntimeFile<ELFT> &file) const {
- if (symName.startswith("__start_")) {
- if (_ctx.cidentSectionNames().count(symName.drop_front(8)))
- file.addAbsoluteAtom(symName);
- } else if (symName.startswith("__stop_")) {
- if (_ctx.cidentSectionNames().count(symName.drop_front(7)))
- file.addAbsoluteAtom(symName);
- }
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::updateScopeAtomValues(StringRef sym,
- StringRef sec) {
- updateScopeAtomValues(("__" + sym + "_start").str().c_str(),
- ("__" + sym + "_end").str().c_str(), sec);
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::updateScopeAtomValues(StringRef start,
- StringRef end,
- StringRef sec) {
- AtomLayout *s = _layout.findAbsoluteAtom(start);
- AtomLayout *e = _layout.findAbsoluteAtom(end);
- const OutputSection<ELFT> *section = _layout.findOutputSection(sec);
- if (s)
- s->_virtualAddr = section ? section->virtualAddr() : 0;
- if (e)
- e->_virtualAddr = section ? section->virtualAddr() + section->memSize() : 0;
-}
-
-template class OutputELFWriter<ELF32LE>;
-template class OutputELFWriter<ELF32BE>;
-template class OutputELFWriter<ELF64LE>;
-template class OutputELFWriter<ELF64BE>;
-
-} // namespace elf
-} // namespace lld
diff --git a/lib/ReaderWriter/ELF/OutputELFWriter.h b/lib/ReaderWriter/ELF/OutputELFWriter.h
deleted file mode 100644
index bb3901010634..000000000000
--- a/lib/ReaderWriter/ELF/OutputELFWriter.h
+++ /dev/null
@@ -1,153 +0,0 @@
-//===- lib/ReaderWriter/ELF/OutputELFWriter.h ----------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
-#define LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
-
-#include "ELFFile.h"
-#include "TargetLayout.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/StringSet.h"
-
-namespace lld {
-class ELFLinkingContext;
-
-namespace elf {
-using namespace llvm;
-using namespace llvm::object;
-
-// OutputELFWriter Class
-//
-/// \brief This acts as the base class for all the ELF writers that are output
-/// for emitting an ELF output file. This class also acts as a common class for
-/// creating static and dynamic executables. All the function in this class
-/// can be overridden and an appropriate writer be created
-template<class ELFT>
-class OutputELFWriter : public ELFWriter {
-public:
- typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
- typedef Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef Elf_Dyn_Impl<ELFT> Elf_Dyn;
-
- OutputELFWriter(ELFLinkingContext &ctx, TargetLayout<ELFT> &layout);
-
-protected:
- // build the sections that need to be created
- virtual void createDefaultSections();
-
- // Build all the output sections
- void buildChunks(const File &file) override;
-
- // Build the output file
- virtual std::error_code buildOutput(const File &file);
-
- // Setup the ELF header.
- virtual std::error_code setELFHeader();
-
- // Write the file to the path specified
- std::error_code writeFile(const File &File, StringRef path) override;
-
- // Write to the output file.
- virtual std::error_code writeOutput(const File &file, StringRef path);
-
- // Get the size of the output file that the linker would emit.
- virtual uint64_t outputFileSize() const;
-
- // Build the atom to address map, this has to be called
- // before applying relocations
- virtual void buildAtomToAddressMap(const File &file);
-
- // Build the symbol table for static linking
- virtual void buildStaticSymbolTable(const File &file);
-
- // Build the dynamic symbol table for dynamic linking
- virtual void buildDynamicSymbolTable(const File &file);
-
- // Build the section header table
- virtual void buildSectionHeaderTable();
-
- // Assign sections that have no segments such as the symbol table,
- // section header table, string table etc
- virtual void assignSectionsWithNoSegments();
-
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- // Finalize the default atom values
- virtual void finalizeDefaultAtomValues();
-
- // This is called by the write section to apply relocations
- uint64_t addressOfAtom(const Atom *atom) override {
- auto addr = _atomToAddressMap.find(atom);
- return addr == _atomToAddressMap.end() ? 0 : addr->second;
- }
-
- // This is a hook for creating default dynamic entries
- virtual void createDefaultDynamicEntries() {}
-
- /// \brief Create symbol table.
- virtual unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable();
-
- /// \brief create dynamic table.
- virtual unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable();
-
- /// \brief create dynamic symbol table.
- virtual unique_bump_ptr<DynamicSymbolTable<ELFT>>
- createDynamicSymbolTable();
-
- /// \brief Create entry in the dynamic symbols table for this atom.
- virtual bool isDynSymEntryRequired(const SharedLibraryAtom *sla) const {
- return _layout.isReferencedByDefinedAtom(sla);
- }
-
- /// \brief Create DT_NEEDED dynamic tage for the shared library.
- virtual bool isNeededTagRequired(const SharedLibraryAtom *sla) const {
- return false;
- }
-
- /// \brief Process undefined symbols that left after resolution step.
- virtual void processUndefinedSymbol(StringRef symName,
- RuntimeFile<ELFT> &file) const;
-
- /// \brief Assign addresses to atoms marking section's start and end.
- void updateScopeAtomValues(StringRef sym, StringRef sec);
-
- llvm::BumpPtrAllocator _alloc;
-
- ELFLinkingContext &_ctx;
- TargetHandler &_targetHandler;
-
- typedef llvm::DenseMap<const Atom *, uint64_t> AtomToAddress;
- AtomToAddress _atomToAddressMap;
- TargetLayout<ELFT> &_layout;
- unique_bump_ptr<ELFHeader<ELFT>> _elfHeader;
- unique_bump_ptr<ProgramHeader<ELFT>> _programHeader;
- unique_bump_ptr<SymbolTable<ELFT>> _symtab;
- unique_bump_ptr<StringTable<ELFT>> _strtab;
- unique_bump_ptr<StringTable<ELFT>> _shstrtab;
- unique_bump_ptr<SectionHeader<ELFT>> _shdrtab;
- unique_bump_ptr<EHFrameHeader<ELFT>> _ehFrameHeader;
- /// \name Dynamic sections.
- /// @{
- unique_bump_ptr<DynamicTable<ELFT>> _dynamicTable;
- unique_bump_ptr<DynamicSymbolTable<ELFT>> _dynamicSymbolTable;
- unique_bump_ptr<StringTable<ELFT>> _dynamicStringTable;
- unique_bump_ptr<HashSection<ELFT>> _hashTable;
- llvm::StringSet<> _soNeeded;
- /// @}
-
-private:
- static StringRef maybeGetSOName(Node *node);
- void updateScopeAtomValues(StringRef start, StringRef end, StringRef sec);
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
diff --git a/lib/ReaderWriter/ELF/Reader.cpp b/lib/ReaderWriter/ELF/Reader.cpp
deleted file mode 100644
index 801f1abaed7a..000000000000
--- a/lib/ReaderWriter/ELF/Reader.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- lib/ReaderWriter/ELF/Reader.cpp ------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Defines the ELF Reader and all helper sub classes to consume an ELF
-/// file and produces atoms out of it.
-///
-//===----------------------------------------------------------------------===//
-
-#include "ELFReader.h"
-#include <map>
-#include <vector>
-
-using llvm::support::endianness;
-using namespace llvm::object;
-
-namespace lld {
-
-// This dynamic registration of a handler causes support for all ELF
-// architectures to be pulled into the linker. If we want to support making a
-// linker that only supports one ELF architecture, we'd need to change this
-// to have a different registration method for each architecture.
-void Registry::addSupportELFObjects(ELFLinkingContext &ctx) {
-
- // Tell registry about the ELF object file parser.
- add(ctx.getTargetHandler().getObjReader());
-
- // Tell registry about the relocation name to number mapping for this arch.
- ctx.registerRelocationNames(*this);
-}
-
-void Registry::addSupportELFDynamicSharedObjects(ELFLinkingContext &ctx) {
- // Tell registry about the ELF dynamic shared library file parser.
- add(ctx.getTargetHandler().getDSOReader());
-}
-
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/SectionChunks.cpp b/lib/ReaderWriter/ELF/SectionChunks.cpp
deleted file mode 100644
index 520fbe24af3b..000000000000
--- a/lib/ReaderWriter/ELF/SectionChunks.cpp
+++ /dev/null
@@ -1,996 +0,0 @@
-//===- lib/ReaderWriter/ELF/SectionChunks.h -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SectionChunks.h"
-#include "TargetLayout.h"
-#include "lld/Core/Parallel.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Dwarf.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-Section<ELFT>::Section(const ELFLinkingContext &ctx, StringRef sectionName,
- StringRef chunkName, typename Chunk<ELFT>::Kind k)
- : Chunk<ELFT>(chunkName, k, ctx), _inputSectionName(sectionName),
- _outputSectionName(sectionName) {}
-
-template <class ELFT> int Section<ELFT>::getContentType() const {
- if (_flags & llvm::ELF::SHF_EXECINSTR)
- return Chunk<ELFT>::ContentType::Code;
- else if (_flags & llvm::ELF::SHF_WRITE)
- return Chunk<ELFT>::ContentType::Data;
- else if (_flags & llvm::ELF::SHF_ALLOC)
- return Chunk<ELFT>::ContentType::Code;
- else
- return Chunk<ELFT>::ContentType::Unknown;
-}
-
-template <class ELFT>
-AtomSection<ELFT>::AtomSection(const ELFLinkingContext &ctx,
- StringRef sectionName, int32_t contentType,
- int32_t permissions, int32_t order)
- : Section<ELFT>(ctx, sectionName, "AtomSection",
- Chunk<ELFT>::Kind::AtomSection),
- _contentType(contentType), _contentPermissions(permissions) {
- this->setOrder(order);
-
- switch (contentType) {
- case DefinedAtom::typeCode:
- case DefinedAtom::typeDataFast:
- case DefinedAtom::typeData:
- case DefinedAtom::typeConstant:
- case DefinedAtom::typeGOT:
- case DefinedAtom::typeStub:
- case DefinedAtom::typeResolver:
- case DefinedAtom::typeThreadData:
- this->_type = SHT_PROGBITS;
- break;
-
- case DefinedAtom::typeThreadZeroFill:
- case DefinedAtom::typeZeroFillFast:
- case DefinedAtom::typeZeroFill:
- this->_type = SHT_NOBITS;
- break;
-
- case DefinedAtom::typeRONote:
- case DefinedAtom::typeRWNote:
- this->_type = SHT_NOTE;
- break;
-
- case DefinedAtom::typeNoAlloc:
- this->_type = SHT_PROGBITS;
- this->_isLoadedInMemory = false;
- break;
- }
-
- switch (permissions) {
- case DefinedAtom::permR__:
- this->_flags = SHF_ALLOC;
- break;
- case DefinedAtom::permR_X:
- this->_flags = SHF_ALLOC | SHF_EXECINSTR;
- break;
- case DefinedAtom::permRW_:
- case DefinedAtom::permRW_L:
- this->_flags = SHF_ALLOC | SHF_WRITE;
- if (_contentType == DefinedAtom::typeThreadData ||
- _contentType == DefinedAtom::typeThreadZeroFill)
- this->_flags |= SHF_TLS;
- break;
- case DefinedAtom::permRWX:
- this->_flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR;
- break;
- case DefinedAtom::perm___:
- this->_flags = 0;
- break;
- }
-}
-
-template <class ELFT>
-void AtomSection<ELFT>::assignVirtualAddress(uint64_t addr) {
- parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
- ai->_virtualAddr = addr + ai->_fileOffset;
- });
-}
-
-template <class ELFT>
-void AtomSection<ELFT>::assignFileOffsets(uint64_t offset) {
- parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
- ai->_fileOffset = offset + ai->_fileOffset;
- });
-}
-
-template <class ELFT>
-const AtomLayout *
-AtomSection<ELFT>::findAtomLayoutByName(StringRef name) const {
- for (auto ai : _atoms)
- if (ai->_atom->name() == name)
- return ai;
- return nullptr;
-}
-
-template <class ELFT>
-std::string AtomSection<ELFT>::formatError(const std::string &errorStr,
- const AtomLayout &atom,
- const Reference &ref) const {
- StringRef kindValStr;
- if (!this->_ctx.registry().referenceKindToString(
- ref.kindNamespace(), ref.kindArch(), ref.kindValue(), kindValStr)) {
- kindValStr = "unknown";
- }
-
- return
- (Twine(errorStr) + " in file " + atom._atom->file().path() +
- ": reference from " + atom._atom->name() + "+" +
- Twine(ref.offsetInAtom()) + " to " + ref.target()->name() + "+" +
- Twine(ref.addend()) + " of type " + Twine(ref.kindValue()) + " (" +
- kindValStr + ")\n")
- .str();
-}
-
-/// Align the offset to the required modulus defined by the atom alignment
-template <class ELFT>
-uint64_t AtomSection<ELFT>::alignOffset(uint64_t offset,
- DefinedAtom::Alignment &atomAlign) {
- uint64_t requiredModulus = atomAlign.modulus;
- uint64_t alignment = atomAlign.value;
- uint64_t currentModulus = (offset % alignment);
- uint64_t retOffset = offset;
- if (currentModulus != requiredModulus) {
- if (requiredModulus > currentModulus)
- retOffset += requiredModulus - currentModulus;
- else
- retOffset += alignment + requiredModulus - currentModulus;
- }
- return retOffset;
-}
-
-// \brief Append an atom to a Section. The atom gets pushed into a vector
-// contains the atom, the atom file offset, the atom virtual address
-// the atom file offset is aligned appropriately as set by the Reader
-template <class ELFT>
-const AtomLayout *AtomSection<ELFT>::appendAtom(const Atom *atom) {
- const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
-
- DefinedAtom::Alignment atomAlign = definedAtom->alignment();
- uint64_t alignment = atomAlign.value;
- // Align the atom to the required modulus/ align the file offset and the
- // memory offset separately this is required so that BSS symbols are handled
- // properly as the BSS symbols only occupy memory size and not file size
- uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
- uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
- switch (definedAtom->contentType()) {
- case DefinedAtom::typeCode:
- case DefinedAtom::typeConstant:
- case DefinedAtom::typeData:
- case DefinedAtom::typeDataFast:
- case DefinedAtom::typeZeroFillFast:
- case DefinedAtom::typeGOT:
- case DefinedAtom::typeStub:
- case DefinedAtom::typeResolver:
- case DefinedAtom::typeThreadData:
- case DefinedAtom::typeRONote:
- case DefinedAtom::typeRWNote:
- _atoms.push_back(new (_alloc) AtomLayout(atom, fOffset, 0));
- this->_fsize = fOffset + definedAtom->size();
- this->_msize = mOffset + definedAtom->size();
- DEBUG_WITH_TYPE("Section", llvm::dbgs()
- << "[" << this->name() << " " << this << "] "
- << "Adding atom: " << atom->name() << "@"
- << fOffset << "\n");
- break;
- case DefinedAtom::typeNoAlloc:
- _atoms.push_back(new (_alloc) AtomLayout(atom, fOffset, 0));
- this->_fsize = fOffset + definedAtom->size();
- DEBUG_WITH_TYPE("Section", llvm::dbgs()
- << "[" << this->name() << " " << this << "] "
- << "Adding atom: " << atom->name() << "@"
- << fOffset << "\n");
- break;
- case DefinedAtom::typeThreadZeroFill:
- case DefinedAtom::typeZeroFill:
- _atoms.push_back(new (_alloc) AtomLayout(atom, mOffset, 0));
- this->_msize = mOffset + definedAtom->size();
- break;
- default:
- llvm::dbgs() << definedAtom->contentType() << "\n";
- llvm_unreachable("Uexpected content type.");
- }
- // Set the section alignment to the largest alignment
- // std::max doesn't support uint64_t
- if (this->_alignment < alignment)
- this->_alignment = alignment;
-
- if (_atoms.size())
- return _atoms.back();
- return nullptr;
-}
-
-/// \brief convert the segment type to a String for diagnostics
-/// and printing purposes
-template <class ELFT> StringRef Section<ELFT>::segmentKindToStr() const {
- switch (_segmentType) {
- case llvm::ELF::PT_DYNAMIC:
- return "DYNAMIC";
- case llvm::ELF::PT_INTERP:
- return "INTERP";
- case llvm::ELF::PT_LOAD:
- return "LOAD";
- case llvm::ELF::PT_GNU_EH_FRAME:
- return "EH_FRAME";
- case llvm::ELF::PT_GNU_RELRO:
- return "GNU_RELRO";
- case llvm::ELF::PT_NOTE:
- return "NOTE";
- case llvm::ELF::PT_NULL:
- return "NULL";
- case llvm::ELF::PT_TLS:
- return "TLS";
- default:
- return "UNKNOWN";
- }
-}
-
-/// \brief Write the section and the atom contents to the buffer
-template <class ELFT>
-void AtomSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- bool success = true;
-
- // parallel_for_each() doesn't have deterministic order. To guarantee
- // deterministic error output, collect errors in this vector and sort it
- // by atom file offset before printing all errors.
- std::vector<std::pair<size_t, std::string>> errors;
- parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
- DEBUG_WITH_TYPE("Section", llvm::dbgs()
- << "Writing atom: " << ai->_atom->name()
- << " | " << ai->_fileOffset << "\n");
- const DefinedAtom *definedAtom = cast<DefinedAtom>(ai->_atom);
- if (!definedAtom->occupiesDiskSpace())
- return;
- // Copy raw content of atom to file buffer.
- ArrayRef<uint8_t> content = definedAtom->rawContent();
- uint64_t contentSize = content.size();
- if (contentSize == 0)
- return;
- uint8_t *atomContent = chunkBuffer + ai->_fileOffset;
- std::memcpy(atomContent, content.data(), contentSize);
- const TargetRelocationHandler &relHandler =
- this->_ctx.getTargetHandler().getRelocationHandler();
- for (const auto ref : *definedAtom) {
- if (std::error_code ec =
- relHandler.applyRelocation(*writer, buffer, *ai, *ref)) {
- std::lock_guard<std::mutex> lock(_outputMutex);
- errors.push_back(std::make_pair(ai->_fileOffset,
- formatError(ec.message(), *ai, *ref)));
- success = false;
- }
- }
- });
- if (!success) {
- std::sort(errors.begin(), errors.end());
- for (auto &&error : errors)
- llvm::errs() << error.second;
- llvm::report_fatal_error("relocating output");
- }
-}
-
-template <class ELFT>
-void OutputSection<ELFT>::appendSection(Section<ELFT> *section) {
- if (section->alignment() > _alignment)
- _alignment = section->alignment();
- assert(!_link && "Section already has a link!");
- _link = section->getLink();
- _shInfo = section->getInfo();
- _entSize = section->getEntSize();
- _type = section->getType();
- if (_flags < section->getFlags())
- _flags = section->getFlags();
- section->setOutputSection(this, (_sections.size() == 0));
- _kind = section->kind();
- _sections.push_back(section);
-}
-
-template <class ELFT>
-StringTable<ELFT>::StringTable(const ELFLinkingContext &ctx, const char *str,
- int32_t order, bool dynamic)
- : Section<ELFT>(ctx, str, "StringTable") {
- // the string table has a NULL entry for which
- // add an empty string
- _strings.push_back("");
- this->_fsize = 1;
- this->_alignment = 1;
- this->setOrder(order);
- this->_type = SHT_STRTAB;
- if (dynamic) {
- this->_flags = SHF_ALLOC;
- this->_msize = this->_fsize;
- }
-}
-
-template <class ELFT> uint64_t StringTable<ELFT>::addString(StringRef symname) {
- if (symname.empty())
- return 0;
- StringMapTIter stringIter = _stringMap.find(symname);
- if (stringIter == _stringMap.end()) {
- _strings.push_back(symname);
- uint64_t offset = this->_fsize;
- this->_fsize += symname.size() + 1;
- if (this->_flags & SHF_ALLOC)
- this->_msize = this->_fsize;
- _stringMap[symname] = offset;
- return offset;
- }
- return stringIter->second;
-}
-
-template <class ELFT>
-void StringTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- for (auto si : _strings) {
- memcpy(dest, si.data(), si.size());
- dest += si.size();
- memcpy(dest, "", 1);
- dest += 1;
- }
-}
-
-/// ELF Symbol Table
-template <class ELFT>
-SymbolTable<ELFT>::SymbolTable(const ELFLinkingContext &ctx, const char *str,
- int32_t order)
- : Section<ELFT>(ctx, str, "SymbolTable") {
- this->setOrder(order);
- Elf_Sym symbol;
- std::memset(&symbol, 0, sizeof(Elf_Sym));
- _symbolTable.push_back(SymbolEntry(nullptr, symbol, nullptr));
- this->_entSize = sizeof(Elf_Sym);
- this->_fsize = sizeof(Elf_Sym);
- this->_alignment = sizeof(Elf_Addr);
- this->_type = SHT_SYMTAB;
-}
-
-template <class ELFT>
-void SymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) {
- unsigned char binding = 0, type = 0;
- sym.st_size = da->size();
- DefinedAtom::ContentType ct;
- switch (ct = da->contentType()) {
- case DefinedAtom::typeCode:
- case DefinedAtom::typeStub:
- sym.st_value = addr;
- type = llvm::ELF::STT_FUNC;
- break;
- case DefinedAtom::typeResolver:
- sym.st_value = addr;
- type = llvm::ELF::STT_GNU_IFUNC;
- break;
- case DefinedAtom::typeDataFast:
- case DefinedAtom::typeData:
- case DefinedAtom::typeConstant:
- sym.st_value = addr;
- type = llvm::ELF::STT_OBJECT;
- break;
- case DefinedAtom::typeGOT:
- sym.st_value = addr;
- type = llvm::ELF::STT_NOTYPE;
- break;
- case DefinedAtom::typeZeroFill:
- case DefinedAtom::typeZeroFillFast:
- type = llvm::ELF::STT_OBJECT;
- sym.st_value = addr;
- break;
- case DefinedAtom::typeThreadData:
- case DefinedAtom::typeThreadZeroFill:
- type = llvm::ELF::STT_TLS;
- sym.st_value = addr;
- break;
- default:
- type = llvm::ELF::STT_NOTYPE;
- }
- if (da->customSectionName() == da->name())
- type = llvm::ELF::STT_SECTION;
-
- if (da->scope() == DefinedAtom::scopeTranslationUnit)
- binding = llvm::ELF::STB_LOCAL;
- else
- binding = llvm::ELF::STB_GLOBAL;
-
- sym.setBindingAndType(binding, type);
-}
-
-template <class ELFT>
-void SymbolTable<ELFT>::addAbsoluteAtom(Elf_Sym &sym, const AbsoluteAtom *aa,
- int64_t addr) {
- unsigned char binding = 0, type = 0;
- type = llvm::ELF::STT_OBJECT;
- sym.st_shndx = llvm::ELF::SHN_ABS;
- switch (aa->scope()) {
- case AbsoluteAtom::scopeLinkageUnit:
- sym.setVisibility(llvm::ELF::STV_HIDDEN);
- binding = llvm::ELF::STB_LOCAL;
- break;
- case AbsoluteAtom::scopeTranslationUnit:
- binding = llvm::ELF::STB_LOCAL;
- break;
- case AbsoluteAtom::scopeGlobal:
- binding = llvm::ELF::STB_GLOBAL;
- break;
- }
- sym.st_value = addr;
- sym.setBindingAndType(binding, type);
-}
-
-template <class ELFT>
-void SymbolTable<ELFT>::addSharedLibAtom(Elf_Sym &sym,
- const SharedLibraryAtom *aa) {
- unsigned char binding = 0, type = 0;
- if (aa->type() == SharedLibraryAtom::Type::Data) {
- type = llvm::ELF::STT_OBJECT;
- sym.st_size = aa->size();
- } else
- type = llvm::ELF::STT_FUNC;
- sym.st_shndx = llvm::ELF::SHN_UNDEF;
- binding = llvm::ELF::STB_GLOBAL;
- sym.setBindingAndType(binding, type);
-}
-
-template <class ELFT>
-void SymbolTable<ELFT>::addUndefinedAtom(Elf_Sym &sym,
- const UndefinedAtom *ua) {
- unsigned char binding = 0, type = 0;
- sym.st_value = 0;
- type = llvm::ELF::STT_NOTYPE;
- if (ua->canBeNull())
- binding = llvm::ELF::STB_WEAK;
- else
- binding = llvm::ELF::STB_GLOBAL;
- sym.setBindingAndType(binding, type);
-}
-
-/// Add a symbol to the symbol Table, definedAtoms which get added to the symbol
-/// section don't have their virtual addresses set at the time of adding the
-/// symbol to the symbol table(Example: dynamic symbols), the addresses needs
-/// to be updated in the table before writing the dynamic symbol table
-/// information
-template <class ELFT>
-void SymbolTable<ELFT>::addSymbol(const Atom *atom, int32_t sectionIndex,
- uint64_t addr, const AtomLayout *atomLayout) {
- Elf_Sym symbol;
-
- if (atom->name().empty())
- return;
-
- symbol.st_name = _stringSection->addString(atom->name());
- symbol.st_size = 0;
- symbol.st_shndx = sectionIndex;
- symbol.st_value = 0;
- symbol.st_other = 0;
- symbol.setVisibility(llvm::ELF::STV_DEFAULT);
-
- // Add all the atoms
- if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom))
- addDefinedAtom(symbol, da, addr);
- else if (const AbsoluteAtom *aa = dyn_cast<const AbsoluteAtom>(atom))
- addAbsoluteAtom(symbol, aa, addr);
- else if (isa<const SharedLibraryAtom>(atom))
- addSharedLibAtom(symbol, dyn_cast<SharedLibraryAtom>(atom));
- else
- addUndefinedAtom(symbol, dyn_cast<UndefinedAtom>(atom));
-
- // If --discard-all is on, don't add to the symbol table
- // symbols with local binding.
- if (this->_ctx.discardLocals() && symbol.getBinding() == llvm::ELF::STB_LOCAL)
- return;
-
- // Temporary locals are all the symbols which name starts with .L.
- // This is defined by the ELF standard.
- if (this->_ctx.discardTempLocals() && atom->name().startswith(".L"))
- return;
-
- _symbolTable.push_back(SymbolEntry(atom, symbol, atomLayout));
- this->_fsize += sizeof(Elf_Sym);
- if (this->_flags & SHF_ALLOC)
- this->_msize = this->_fsize;
-}
-
-template <class ELFT> void SymbolTable<ELFT>::finalize(bool sort) {
- // sh_info should be one greater than last symbol with STB_LOCAL binding
- // we sort the symbol table to keep all local symbols at the beginning
- if (sort)
- sortSymbols();
-
- uint16_t shInfo = 0;
- for (const auto &i : _symbolTable) {
- if (i._symbol.getBinding() != llvm::ELF::STB_LOCAL)
- break;
- shInfo++;
- }
- this->_info = shInfo;
- this->_link = _stringSection->ordinal();
- if (this->_outputSection) {
- this->_outputSection->setInfo(this->_info);
- this->_outputSection->setLink(this->_link);
- }
-}
-
-template <class ELFT>
-void SymbolTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- for (const auto &sti : _symbolTable) {
- memcpy(dest, &sti._symbol, sizeof(Elf_Sym));
- dest += sizeof(Elf_Sym);
- }
-}
-
-template <class ELFT>
-DynamicSymbolTable<ELFT>::DynamicSymbolTable(const ELFLinkingContext &ctx,
- TargetLayout<ELFT> &layout,
- const char *str, int32_t order)
- : SymbolTable<ELFT>(ctx, str, order), _layout(layout) {
- this->_type = SHT_DYNSYM;
- this->_flags = SHF_ALLOC;
- this->_msize = this->_fsize;
-}
-
-template <class ELFT> void DynamicSymbolTable<ELFT>::addSymbolsToHashTable() {
- int index = 0;
- for (auto &ste : this->_symbolTable) {
- if (!ste._atom)
- _hashTable->addSymbol("", index);
- else
- _hashTable->addSymbol(ste._atom->name(), index);
- ++index;
- }
-}
-
-template <class ELFT> void DynamicSymbolTable<ELFT>::finalize() {
- // Defined symbols which have been added into the dynamic symbol table
- // don't have their addresses known until addresses have been assigned
- // so let's update the symbol values after they have got assigned
- for (auto &ste : this->_symbolTable) {
- const AtomLayout *atomLayout = ste._atomLayout;
- if (!atomLayout)
- continue;
- ste._symbol.st_value = atomLayout->_virtualAddr;
- }
-
- // Don't sort the symbols
- SymbolTable<ELFT>::finalize(false);
-}
-
-template <class ELFT>
-RelocationTable<ELFT>::RelocationTable(const ELFLinkingContext &ctx,
- StringRef str, int32_t order)
- : Section<ELFT>(ctx, str, "RelocationTable") {
- this->setOrder(order);
- this->_flags = SHF_ALLOC;
- // Set the alignment properly depending on the target architecture
- this->_alignment = ELFT::Is64Bits ? 8 : 4;
- if (ctx.isRelaOutputFormat()) {
- this->_entSize = sizeof(Elf_Rela);
- this->_type = SHT_RELA;
- } else {
- this->_entSize = sizeof(Elf_Rel);
- this->_type = SHT_REL;
- }
-}
-
-template <class ELFT>
-uint32_t RelocationTable<ELFT>::addRelocation(const DefinedAtom &da,
- const Reference &r) {
- _relocs.emplace_back(&da, &r);
- this->_fsize = _relocs.size() * this->_entSize;
- this->_msize = this->_fsize;
- return _relocs.size() - 1;
-}
-
-template <class ELFT>
-bool RelocationTable<ELFT>::getRelocationIndex(const Reference &r,
- uint32_t &res) {
- auto rel = std::find_if(
- _relocs.begin(), _relocs.end(),
- [&](const std::pair<const DefinedAtom *, const Reference *> &p) {
- if (p.second == &r)
- return true;
- return false;
- });
- if (rel == _relocs.end())
- return false;
- res = std::distance(_relocs.begin(), rel);
- return true;
-}
-
-template <class ELFT>
-bool RelocationTable<ELFT>::canModifyReadonlySection() const {
- for (const auto &rel : _relocs) {
- const DefinedAtom *atom = rel.first;
- if ((atom->permissions() & DefinedAtom::permRW_) != DefinedAtom::permRW_)
- return true;
- }
- return false;
-}
-
-template <class ELFT> void RelocationTable<ELFT>::finalize() {
- this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
- if (this->_outputSection)
- this->_outputSection->setLink(this->_link);
-}
-
-template <class ELFT>
-void RelocationTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- for (const auto &rel : _relocs) {
- if (this->_ctx.isRelaOutputFormat()) {
- auto &r = *reinterpret_cast<Elf_Rela *>(dest);
- writeRela(writer, r, *rel.first, *rel.second);
- DEBUG_WITH_TYPE("ELFRelocationTable",
- llvm::dbgs()
- << rel.second->kindValue() << " relocation at "
- << rel.first->name() << "@" << r.r_offset << " to "
- << rel.second->target()->name() << "@" << r.r_addend
- << "\n";);
- } else {
- auto &r = *reinterpret_cast<Elf_Rel *>(dest);
- writeRel(writer, r, *rel.first, *rel.second);
- DEBUG_WITH_TYPE("ELFRelocationTable",
- llvm::dbgs() << rel.second->kindValue()
- << " relocation at " << rel.first->name()
- << "@" << r.r_offset << " to "
- << rel.second->target()->name() << "\n";);
- }
- dest += this->_entSize;
- }
-}
-
-template <class ELFT>
-void RelocationTable<ELFT>::writeRela(ELFWriter *writer, Elf_Rela &r,
- const DefinedAtom &atom,
- const Reference &ref) {
- r.setSymbolAndType(getSymbolIndex(ref.target()), ref.kindValue(), false);
- r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
- // The addend is used only by relative relocations
- if (this->_ctx.isRelativeReloc(ref))
- r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
- else
- r.r_addend = 0;
-}
-
-template <class ELFT>
-void RelocationTable<ELFT>::writeRel(ELFWriter *writer, Elf_Rel &r,
- const DefinedAtom &atom,
- const Reference &ref) {
- r.setSymbolAndType(getSymbolIndex(ref.target()), ref.kindValue(), false);
- r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
-}
-
-template <class ELFT>
-uint32_t RelocationTable<ELFT>::getSymbolIndex(const Atom *a) {
- return _symbolTable ? _symbolTable->getSymbolTableIndex(a)
- : (uint32_t)STN_UNDEF;
-}
-
-template <class ELFT>
-DynamicTable<ELFT>::DynamicTable(const ELFLinkingContext &ctx,
- TargetLayout<ELFT> &layout, StringRef str,
- int32_t order)
- : Section<ELFT>(ctx, str, "DynamicSection"), _layout(layout) {
- this->setOrder(order);
- this->_entSize = sizeof(Elf_Dyn);
- this->_alignment = ELFT::Is64Bits ? 8 : 4;
- // Reserve space for the DT_NULL entry.
- this->_fsize = sizeof(Elf_Dyn);
- this->_msize = sizeof(Elf_Dyn);
- this->_type = SHT_DYNAMIC;
- this->_flags = SHF_ALLOC;
-}
-
-template <class ELFT>
-std::size_t DynamicTable<ELFT>::addEntry(int64_t tag, uint64_t val) {
- Elf_Dyn dyn;
- dyn.d_tag = tag;
- dyn.d_un.d_val = val;
- _entries.push_back(dyn);
- this->_fsize = (_entries.size() * sizeof(Elf_Dyn)) + sizeof(Elf_Dyn);
- this->_msize = this->_fsize;
- return _entries.size() - 1;
-}
-
-template <class ELFT>
-void DynamicTable<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- // Add the null entry.
- Elf_Dyn d;
- d.d_tag = 0;
- d.d_un.d_val = 0;
- _entries.push_back(d);
- std::memcpy(dest, _entries.data(), this->_fsize);
-}
-
-template <class ELFT> void DynamicTable<ELFT>::createDefaultEntries() {
- bool isRela = this->_ctx.isRelaOutputFormat();
- _dt_hash = addEntry(DT_HASH, 0);
- _dt_strtab = addEntry(DT_STRTAB, 0);
- _dt_symtab = addEntry(DT_SYMTAB, 0);
- _dt_strsz = addEntry(DT_STRSZ, 0);
- _dt_syment = addEntry(DT_SYMENT, 0);
- if (_layout.hasDynamicRelocationTable()) {
- _dt_rela = addEntry(isRela ? DT_RELA : DT_REL, 0);
- _dt_relasz = addEntry(isRela ? DT_RELASZ : DT_RELSZ, 0);
- _dt_relaent = addEntry(isRela ? DT_RELAENT : DT_RELENT, 0);
- if (_layout.getDynamicRelocationTable()->canModifyReadonlySection())
- _dt_textrel = addEntry(DT_TEXTREL, 0);
- }
- if (_layout.hasPLTRelocationTable()) {
- _dt_pltrelsz = addEntry(DT_PLTRELSZ, 0);
- _dt_pltgot = addEntry(getGotPltTag(), 0);
- _dt_pltrel = addEntry(DT_PLTREL, isRela ? DT_RELA : DT_REL);
- _dt_jmprel = addEntry(DT_JMPREL, 0);
- }
-}
-
-template <class ELFT> void DynamicTable<ELFT>::doPreFlight() {
- auto initArray = _layout.findOutputSection(".init_array");
- auto finiArray = _layout.findOutputSection(".fini_array");
- if (initArray) {
- _dt_init_array = addEntry(DT_INIT_ARRAY, 0);
- _dt_init_arraysz = addEntry(DT_INIT_ARRAYSZ, 0);
- }
- if (finiArray) {
- _dt_fini_array = addEntry(DT_FINI_ARRAY, 0);
- _dt_fini_arraysz = addEntry(DT_FINI_ARRAYSZ, 0);
- }
- if (getInitAtomLayout())
- _dt_init = addEntry(DT_INIT, 0);
- if (getFiniAtomLayout())
- _dt_fini = addEntry(DT_FINI, 0);
-}
-
-template <class ELFT> void DynamicTable<ELFT>::finalize() {
- StringTable<ELFT> *dynamicStringTable = _dynamicSymbolTable->getStringTable();
- this->_link = dynamicStringTable->ordinal();
- if (this->_outputSection) {
- this->_outputSection->setType(this->_type);
- this->_outputSection->setInfo(this->_info);
- this->_outputSection->setLink(this->_link);
- }
-}
-
-template <class ELFT> void DynamicTable<ELFT>::updateDynamicTable() {
- StringTable<ELFT> *dynamicStringTable = _dynamicSymbolTable->getStringTable();
- _entries[_dt_hash].d_un.d_val = _hashTable->virtualAddr();
- _entries[_dt_strtab].d_un.d_val = dynamicStringTable->virtualAddr();
- _entries[_dt_symtab].d_un.d_val = _dynamicSymbolTable->virtualAddr();
- _entries[_dt_strsz].d_un.d_val = dynamicStringTable->memSize();
- _entries[_dt_syment].d_un.d_val = _dynamicSymbolTable->getEntSize();
- auto initArray = _layout.findOutputSection(".init_array");
- if (initArray) {
- _entries[_dt_init_array].d_un.d_val = initArray->virtualAddr();
- _entries[_dt_init_arraysz].d_un.d_val = initArray->memSize();
- }
- auto finiArray = _layout.findOutputSection(".fini_array");
- if (finiArray) {
- _entries[_dt_fini_array].d_un.d_val = finiArray->virtualAddr();
- _entries[_dt_fini_arraysz].d_un.d_val = finiArray->memSize();
- }
- if (const auto *al = getInitAtomLayout())
- _entries[_dt_init].d_un.d_val = getAtomVirtualAddress(al);
- if (const auto *al = getFiniAtomLayout())
- _entries[_dt_fini].d_un.d_val = getAtomVirtualAddress(al);
- if (_layout.hasDynamicRelocationTable()) {
- auto relaTbl = _layout.getDynamicRelocationTable();
- _entries[_dt_rela].d_un.d_val = relaTbl->virtualAddr();
- _entries[_dt_relasz].d_un.d_val = relaTbl->memSize();
- _entries[_dt_relaent].d_un.d_val = relaTbl->getEntSize();
- }
- if (_layout.hasPLTRelocationTable()) {
- auto relaTbl = _layout.getPLTRelocationTable();
- _entries[_dt_jmprel].d_un.d_val = relaTbl->virtualAddr();
- _entries[_dt_pltrelsz].d_un.d_val = relaTbl->memSize();
- auto gotplt = _layout.findOutputSection(".got.plt");
- _entries[_dt_pltgot].d_un.d_val = gotplt->virtualAddr();
- }
-}
-
-template <class ELFT>
-const AtomLayout *DynamicTable<ELFT>::getInitAtomLayout() {
- auto al = _layout.findAtomLayoutByName(this->_ctx.initFunction());
- if (al && isa<DefinedAtom>(al->_atom))
- return al;
- return nullptr;
-}
-
-template <class ELFT>
-const AtomLayout *DynamicTable<ELFT>::getFiniAtomLayout() {
- auto al = _layout.findAtomLayoutByName(this->_ctx.finiFunction());
- if (al && isa<DefinedAtom>(al->_atom))
- return al;
- return nullptr;
-}
-
-template <class ELFT>
-InterpSection<ELFT>::InterpSection(const ELFLinkingContext &ctx, StringRef str,
- int32_t order, StringRef interp)
- : Section<ELFT>(ctx, str, "Dynamic:Interp"), _interp(interp) {
- this->setOrder(order);
- this->_alignment = 1;
- // + 1 for null term.
- this->_fsize = interp.size() + 1;
- this->_msize = this->_fsize;
- this->_type = SHT_PROGBITS;
- this->_flags = SHF_ALLOC;
-}
-
-template <class ELFT>
-void InterpSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- std::memcpy(dest, _interp.data(), _interp.size());
-}
-
-template <class ELFT>
-HashSection<ELFT>::HashSection(const ELFLinkingContext &ctx, StringRef name,
- int32_t order)
- : Section<ELFT>(ctx, name, "Dynamic:Hash") {
- this->setOrder(order);
- this->_entSize = 4;
- this->_type = SHT_HASH;
- this->_flags = SHF_ALLOC;
- this->_alignment = ELFT::Is64Bits ? 8 : 4;
- this->_fsize = 0;
- this->_msize = 0;
-}
-
-template <class ELFT>
-void HashSection<ELFT>::addSymbol(StringRef name, uint32_t index) {
- SymbolTableEntry ste;
- ste._name = name;
- ste._index = index;
- _entries.push_back(ste);
-}
-
-/// \brief Set the dynamic symbol table
-template <class ELFT>
-void HashSection<ELFT>::setSymbolTable(
- const DynamicSymbolTable<ELFT> *symbolTable) {
- _symbolTable = symbolTable;
-}
-
-template <class ELFT> void HashSection<ELFT>::doPreFlight() {
- // The number of buckets to use for a certain number of symbols.
- // If there are less than 3 symbols, 1 bucket will be used. If
- // there are less than 17 symbols, 3 buckets will be used, and so
- // forth. The bucket numbers are defined by GNU ld. We use the
- // same rules here so we generate hash sections with the same
- // size as those generated by GNU ld.
- uint32_t hashBuckets[] = {1, 3, 17, 37, 67, 97, 131,
- 197, 263, 521, 1031, 2053, 4099, 8209,
- 16411, 32771, 65537, 131101, 262147};
- int hashBucketsCount = sizeof(hashBuckets) / sizeof(uint32_t);
-
- unsigned int bucketsCount = 0;
- unsigned int dynSymCount = _entries.size();
-
- // Get the number of buckes that we want to use
- for (int i = 0; i < hashBucketsCount; ++i) {
- if (dynSymCount < hashBuckets[i])
- break;
- bucketsCount = hashBuckets[i];
- }
- _buckets.resize(bucketsCount);
- _chains.resize(_entries.size());
-
- // Create the hash table for the dynamic linker
- for (auto ai : _entries) {
- unsigned int dynsymIndex = ai._index;
- unsigned int bucketpos = llvm::object::elf_hash(ai._name) % bucketsCount;
- _chains[dynsymIndex] = _buckets[bucketpos];
- _buckets[bucketpos] = dynsymIndex;
- }
-
- this->_fsize = (2 + _chains.size() + _buckets.size()) * sizeof(uint32_t);
- this->_msize = this->_fsize;
-}
-
-template <class ELFT> void HashSection<ELFT>::finalize() {
- this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
- if (this->_outputSection)
- this->_outputSection->setLink(this->_link);
-}
-
-template <class ELFT>
-void HashSection<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- Elf_Word bucketChainCounts[2];
- bucketChainCounts[0] = _buckets.size();
- bucketChainCounts[1] = _chains.size();
- std::memcpy(dest, bucketChainCounts, sizeof(bucketChainCounts));
- dest += sizeof(bucketChainCounts);
- // write bucket values
- std::memcpy(dest, _buckets.data(), _buckets.size() * sizeof(Elf_Word));
- dest += _buckets.size() * sizeof(Elf_Word);
- // write chain values
- std::memcpy(dest, _chains.data(), _chains.size() * sizeof(Elf_Word));
-}
-
-template <class ELFT>
-EHFrameHeader<ELFT>::EHFrameHeader(const ELFLinkingContext &ctx, StringRef name,
- TargetLayout<ELFT> &layout, int32_t order)
- : Section<ELFT>(ctx, name, "EHFrameHeader"), _layout(layout) {
- this->setOrder(order);
- this->_entSize = 0;
- this->_type = SHT_PROGBITS;
- this->_flags = SHF_ALLOC;
- this->_alignment = ELFT::Is64Bits ? 8 : 4;
- // Minimum size for empty .eh_frame_hdr.
- this->_fsize = 1 + 1 + 1 + 1 + 4;
- this->_msize = this->_fsize;
-}
-
-template <class ELFT> void EHFrameHeader<ELFT>::doPreFlight() {
- // TODO: Generate a proper binary search table.
-}
-
-template <class ELFT> void EHFrameHeader<ELFT>::finalize() {
- OutputSection<ELFT> *s = _layout.findOutputSection(".eh_frame");
- OutputSection<ELFT> *h = _layout.findOutputSection(".eh_frame_hdr");
- if (s && h)
- _ehFrameOffset = s->virtualAddr() - (h->virtualAddr() + 4);
-}
-
-template <class ELFT>
-void EHFrameHeader<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- int pos = 0;
- dest[pos++] = 1; // version
- dest[pos++] = llvm::dwarf::DW_EH_PE_pcrel |
- llvm::dwarf::DW_EH_PE_sdata4; // eh_frame_ptr_enc
- dest[pos++] = llvm::dwarf::DW_EH_PE_omit; // fde_count_enc
- dest[pos++] = llvm::dwarf::DW_EH_PE_omit; // table_enc
- *reinterpret_cast<typename llvm::object::ELFFile<ELFT>::Elf_Sword *>(
- dest + pos) = _ehFrameOffset;
-}
-
-#define INSTANTIATE(klass) \
- template class klass<ELF32LE>; \
- template class klass<ELF32BE>; \
- template class klass<ELF64LE>; \
- template class klass<ELF64BE>
-
-INSTANTIATE(AtomSection);
-INSTANTIATE(DynamicSymbolTable);
-INSTANTIATE(DynamicTable);
-INSTANTIATE(EHFrameHeader);
-INSTANTIATE(HashSection);
-INSTANTIATE(InterpSection);
-INSTANTIATE(OutputSection);
-INSTANTIATE(RelocationTable);
-INSTANTIATE(Section);
-INSTANTIATE(StringTable);
-INSTANTIATE(SymbolTable);
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/SectionChunks.h b/lib/ReaderWriter/ELF/SectionChunks.h
deleted file mode 100644
index b10ba05237ff..000000000000
--- a/lib/ReaderWriter/ELF/SectionChunks.h
+++ /dev/null
@@ -1,616 +0,0 @@
-//===- lib/ReaderWriter/ELF/SectionChunks.h -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_SECTION_CHUNKS_H
-#define LLD_READER_WRITER_ELF_SECTION_CHUNKS_H
-
-#include "Chunk.h"
-#include "TargetHandler.h"
-#include "Writer.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/range.h"
-#include "lld/ReaderWriter/AtomLayout.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include <memory>
-#include <mutex>
-
-namespace lld {
-namespace elf {
-template <class> class OutputSection;
-using namespace llvm::ELF;
-template <class ELFT> class Segment;
-template <class ELFT> class TargetLayout;
-
-/// \brief An ELF section.
-template <class ELFT> class Section : public Chunk<ELFT> {
-public:
- Section(const ELFLinkingContext &ctx, StringRef sectionName,
- StringRef chunkName,
- typename Chunk<ELFT>::Kind k = Chunk<ELFT>::Kind::ELFSection);
-
- /// \brief Modify the section contents before assigning virtual addresses
- // or assigning file offsets
-
- /// \brief Finalize the section contents before writing
-
- /// \brief Does this section have an output segment.
- virtual bool hasOutputSegment() const { return false; }
-
- /// Return if the section is a loadable section that occupies memory
- virtual bool isLoadableSection() const { return false; }
-
- /// \brief Assign file offsets starting at offset.
- virtual void assignFileOffsets(uint64_t offset) {}
-
- /// \brief Assign virtual addresses starting at addr.
- virtual void assignVirtualAddress(uint64_t addr) {}
-
- uint64_t getFlags() const { return _flags; }
- uint64_t getEntSize() const { return _entSize; }
- uint32_t getType() const { return _type; }
- uint32_t getLink() const { return _link; }
- uint32_t getInfo() const { return _info; }
-
- typename TargetLayout<ELFT>::SegmentType getSegmentType() const {
- return _segmentType;
- }
-
- /// \brief Return the type of content that the section contains
- int getContentType() const override;
-
- /// \brief convert the segment type to a String for diagnostics and printing
- /// purposes
- virtual StringRef segmentKindToStr() const;
-
- /// \brief Records the segmentType, that this section belongs to
- void
- setSegmentType(const typename TargetLayout<ELFT>::SegmentType segmentType) {
- this->_segmentType = segmentType;
- }
-
- virtual const AtomLayout *findAtomLayoutByName(StringRef) const {
- return nullptr;
- }
-
- const OutputSection<ELFT> *getOutputSection() const {
- return _outputSection;
- }
-
- void setOutputSection(OutputSection<ELFT> *os, bool isFirst = false) {
- _outputSection = os;
- _isFirstSectionInOutputSection = isFirst;
- }
-
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::ELFSection ||
- c->kind() == Chunk<ELFT>::Kind::AtomSection;
- }
-
- uint64_t alignment() const override {
- return _isFirstSectionInOutputSection ? _outputSection->alignment()
- : this->_alignment;
- }
-
- virtual StringRef inputSectionName() const { return _inputSectionName; }
-
- virtual StringRef outputSectionName() const { return _outputSectionName; }
-
- virtual void setOutputSectionName(StringRef outputSectionName) {
- _outputSectionName = outputSectionName;
- }
-
- void setArchiveNameOrPath(StringRef name) { _archivePath = name; }
-
- void setMemberNameOrPath(StringRef name) { _memberPath = name; }
-
- StringRef archivePath() { return _archivePath; }
-
- StringRef memberPath() { return _memberPath; }
-
-protected:
- /// \brief OutputSection this Section is a member of, or nullptr.
- OutputSection<ELFT> *_outputSection = nullptr;
- /// \brief ELF SHF_* flags.
- uint64_t _flags = 0;
- /// \brief The size of each entity.
- uint64_t _entSize = 0;
- /// \brief ELF SHT_* type.
- uint32_t _type = 0;
- /// \brief sh_link field.
- uint32_t _link = 0;
- /// \brief the sh_info field.
- uint32_t _info = 0;
- /// \brief Is this the first section in the output section.
- bool _isFirstSectionInOutputSection = false;
- /// \brief the output ELF segment type of this section.
- typename TargetLayout<ELFT>::SegmentType _segmentType = SHT_NULL;
- /// \brief Input section name.
- StringRef _inputSectionName;
- /// \brief Output section name.
- StringRef _outputSectionName;
- StringRef _archivePath;
- StringRef _memberPath;
-};
-
-/// \brief A section containing atoms.
-template <class ELFT> class AtomSection : public Section<ELFT> {
-public:
- AtomSection(const ELFLinkingContext &ctx, StringRef sectionName,
- int32_t contentType, int32_t permissions, int32_t order);
-
- /// Align the offset to the required modulus defined by the atom alignment
- uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign);
-
- /// Return if the section is a loadable section that occupies memory
- bool isLoadableSection() const override { return _isLoadedInMemory; }
-
- // \brief Append an atom to a Section. The atom gets pushed into a vector
- // contains the atom, the atom file offset, the atom virtual address
- // the atom file offset is aligned appropriately as set by the Reader
- virtual const AtomLayout *appendAtom(const Atom *atom);
-
- /// \brief Set the virtual address of each Atom in the Section. This
- /// routine gets called after the linker fixes up the virtual address
- /// of the section
- void assignVirtualAddress(uint64_t addr) override;
-
- /// \brief Set the file offset of each Atom in the section. This routine
- /// gets called after the linker fixes up the section offset
- void assignFileOffsets(uint64_t offset) override;
-
- /// \brief Find the Atom address given a name, this is needed to properly
- /// apply relocation. The section class calls this to find the atom address
- /// to fix the relocation
- const AtomLayout *findAtomLayoutByName(StringRef name) const override;
-
- /// \brief Return the raw flags, we need this to sort segments
- int64_t atomflags() const { return _contentPermissions; }
-
- /// Atom Iterators
- typedef typename std::vector<AtomLayout *>::iterator atom_iter;
-
- range<atom_iter> atoms() { return _atoms; }
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::AtomSection;
- }
-
-protected:
- llvm::BumpPtrAllocator _alloc;
- int32_t _contentType;
- int32_t _contentPermissions;
- bool _isLoadedInMemory = true;
- std::vector<AtomLayout *> _atoms;
- mutable std::mutex _outputMutex;
-
- std::string formatError(const std::string &errorStr, const AtomLayout &atom,
- const Reference &ref) const;
-};
-
-/// \brief A OutputSection represents a set of sections grouped by the same
-/// name. The output file that gets written by the linker has sections grouped
-/// by similar names
-template <class ELFT> class OutputSection {
-public:
- // Iterators
- typedef typename std::vector<Section<ELFT> *>::iterator SectionIter;
-
- OutputSection(StringRef name) : _name(name) {}
-
- // Appends a section into the list of sections that are part of this Output
- // Section
- void appendSection(Section<ELFT> *c);
-
- // Set the OutputSection is associated with a segment
- void setHasSegment() { _hasSegment = true; }
-
- /// Sets the ordinal
- void setOrdinal(uint64_t ordinal) { _ordinal = ordinal; }
-
- /// Sets the Memory size
- void setMemSize(uint64_t memsz) { _memSize = memsz; }
-
- /// Sets the size fo the output Section.
- void setSize(uint64_t fsiz) { _size = fsiz; }
-
- // The offset of the first section contained in the output section is
- // contained here.
- void setFileOffset(uint64_t foffset) { _fileOffset = foffset; }
-
- // Sets the starting address of the section
- void setAddr(uint64_t addr) { _virtualAddr = addr; }
-
- // Is the section loadable?
- bool isLoadableSection() const { return _isLoadableSection; }
-
- // Set section Loadable
- void setLoadableSection(bool isLoadable) {
- _isLoadableSection = isLoadable;
- }
-
- void setLink(uint64_t link) { _link = link; }
- void setInfo(uint64_t info) { _shInfo = info; }
- void setFlag(uint64_t flags) { _flags = flags; }
- void setType(int64_t type) { _type = type; }
- range<SectionIter> sections() { return _sections; }
-
- // The below functions returns the properties of the OutputSection.
- bool hasSegment() const { return _hasSegment; }
- StringRef name() const { return _name; }
- int64_t shinfo() const { return _shInfo; }
- uint64_t alignment() const { return _alignment; }
- int64_t link() const { return _link; }
- int64_t type() const { return _type; }
- uint64_t virtualAddr() const { return _virtualAddr; }
- int64_t ordinal() const { return _ordinal; }
- int64_t kind() const { return _kind; }
- uint64_t fileSize() const { return _size; }
- int64_t entsize() const { return _entSize; }
- uint64_t fileOffset() const { return _fileOffset; }
- uint64_t flags() const { return _flags; }
- uint64_t memSize() const { return _memSize; }
-
-private:
- StringRef _name;
- bool _hasSegment = false;
- uint64_t _ordinal = 0;
- uint64_t _flags = 0;
- uint64_t _size = 0;
- uint64_t _memSize = 0;
- uint64_t _fileOffset = 0;
- uint64_t _virtualAddr = 0;
- int64_t _shInfo = 0;
- int64_t _entSize = 0;
- int64_t _link = 0;
- uint64_t _alignment = 1;
- int64_t _kind = 0;
- int64_t _type = 0;
- bool _isLoadableSection = false;
- std::vector<Section<ELFT> *> _sections;
-};
-
-/// \brief The class represents the ELF String Table
-template <class ELFT> class StringTable : public Section<ELFT> {
-public:
- StringTable(const ELFLinkingContext &, const char *str, int32_t order,
- bool dynamic = false);
-
- uint64_t addString(StringRef symname);
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- void setNumEntries(int64_t numEntries) { _stringMap.resize(numEntries); }
-
-private:
- std::vector<StringRef> _strings;
-
- struct StringRefMappingInfo {
- static StringRef getEmptyKey() { return StringRef(); }
- static StringRef getTombstoneKey() { return StringRef(" ", 1); }
- static unsigned getHashValue(StringRef const val) {
- return llvm::HashString(val);
- }
- static bool isEqual(StringRef const lhs, StringRef const rhs) {
- return lhs.equals(rhs);
- }
- };
- typedef typename llvm::DenseMap<StringRef, uint64_t, StringRefMappingInfo>
- StringMapT;
- typedef typename StringMapT::iterator StringMapTIter;
- StringMapT _stringMap;
-};
-
-/// \brief The SymbolTable class represents the symbol table in a ELF file
-template <class ELFT> class SymbolTable : public Section<ELFT> {
- typedef
- typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Addr Elf_Addr;
-
-public:
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
- SymbolTable(const ELFLinkingContext &ctx, const char *str, int32_t order);
-
- /// \brief set the number of entries that would exist in the symbol
- /// table for the current link
- void setNumEntries(int64_t numEntries) const {
- if (_stringSection)
- _stringSection->setNumEntries(numEntries);
- }
-
- /// \brief return number of entries
- std::size_t size() const { return _symbolTable.size(); }
-
- void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0,
- const AtomLayout *layout = nullptr);
-
- /// \brief Get the symbol table index for an Atom. If it's not in the symbol
- /// table, return STN_UNDEF.
- uint32_t getSymbolTableIndex(const Atom *a) const {
- for (size_t i = 0, e = _symbolTable.size(); i < e; ++i)
- if (_symbolTable[i]._atom == a)
- return i;
- return STN_UNDEF;
- }
-
- void finalize() override { finalize(true); }
-
- virtual void sortSymbols() {
- std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
- [](const SymbolEntry &A, const SymbolEntry &B) {
- return A._symbol.getBinding() < B._symbol.getBinding();
- });
- }
-
- virtual void addAbsoluteAtom(Elf_Sym &sym, const AbsoluteAtom *aa,
- int64_t addr);
-
- virtual void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr);
-
- virtual void addUndefinedAtom(Elf_Sym &sym, const UndefinedAtom *ua);
-
- virtual void addSharedLibAtom(Elf_Sym &sym, const SharedLibraryAtom *sla);
-
- virtual void finalize(bool sort);
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- void setStringSection(StringTable<ELFT> *s) { _stringSection = s; }
-
- StringTable<ELFT> *getStringTable() const { return _stringSection; }
-
-protected:
- struct SymbolEntry {
- SymbolEntry(const Atom *a, const Elf_Sym &sym, const AtomLayout *layout)
- : _atom(a), _atomLayout(layout), _symbol(sym) {}
-
- const Atom *_atom;
- const AtomLayout *_atomLayout;
- Elf_Sym _symbol;
- };
-
- llvm::BumpPtrAllocator _symbolAllocate;
- StringTable<ELFT> *_stringSection;
- std::vector<SymbolEntry> _symbolTable;
-};
-
-template <class ELFT> class HashSection;
-
-template <class ELFT> class DynamicSymbolTable : public SymbolTable<ELFT> {
-public:
- DynamicSymbolTable(const ELFLinkingContext &ctx, TargetLayout<ELFT> &layout,
- const char *str, int32_t order);
-
- // Set the dynamic hash table for symbols to be added into
- void setHashTable(HashSection<ELFT> *hashTable) { _hashTable = hashTable; }
-
- // Add all the dynamic symbos to the hash table
- void addSymbolsToHashTable();
-
- void finalize() override;
-
-protected:
- HashSection<ELFT> *_hashTable = nullptr;
- TargetLayout<ELFT> &_layout;
-};
-
-template <class ELFT> class RelocationTable : public Section<ELFT> {
-public:
- typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
-
- RelocationTable(const ELFLinkingContext &ctx, StringRef str, int32_t order);
-
- /// \returns the index of the relocation added.
- uint32_t addRelocation(const DefinedAtom &da, const Reference &r);
-
- bool getRelocationIndex(const Reference &r, uint32_t &res);
-
- void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable) {
- _symbolTable = symbolTable;
- }
-
- /// \brief Check if any relocation modifies a read-only section.
- bool canModifyReadonlySection() const;
-
- void finalize() override;
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
-protected:
- const DynamicSymbolTable<ELFT> *_symbolTable = nullptr;
-
- virtual void writeRela(ELFWriter *writer, Elf_Rela &r,
- const DefinedAtom &atom, const Reference &ref);
- virtual void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom,
- const Reference &ref);
- uint32_t getSymbolIndex(const Atom *a);
-
-private:
- std::vector<std::pair<const DefinedAtom *, const Reference *>> _relocs;
-};
-
-template <class ELFT> class HashSection;
-
-template <class ELFT> class DynamicTable : public Section<ELFT> {
-public:
- typedef llvm::object::Elf_Dyn_Impl<ELFT> Elf_Dyn;
- typedef std::vector<Elf_Dyn> EntriesT;
-
- DynamicTable(const ELFLinkingContext &ctx, TargetLayout<ELFT> &layout,
- StringRef str, int32_t order);
-
- range<typename EntriesT::iterator> entries() { return _entries; }
-
- /// \returns the index of the entry.
- std::size_t addEntry(int64_t tag, uint64_t val);
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- virtual void createDefaultEntries();
- void doPreFlight() override;
-
- /// \brief Dynamic table tag for .got.plt section referencing.
- /// Usually but not always targets use DT_PLTGOT for that.
- virtual int64_t getGotPltTag() { return DT_PLTGOT; }
-
- void finalize() override;
-
- void setSymbolTable(DynamicSymbolTable<ELFT> *dynsym) {
- _dynamicSymbolTable = dynsym;
- }
-
- const DynamicSymbolTable<ELFT> *getSymbolTable() const {
- return _dynamicSymbolTable;
- }
-
- void setHashTable(HashSection<ELFT> *hsh) { _hashTable = hsh; }
-
- virtual void updateDynamicTable();
-
-protected:
- EntriesT _entries;
-
- /// \brief Return a virtual address (maybe adjusted) for the atom layout
- /// Some targets like microMIPS and ARM Thumb use the last bit
- /// of a symbol's value to mark 'compressed' code. This function allows
- /// to adjust a virtal address before using it in the dynamic table tag.
- virtual uint64_t getAtomVirtualAddress(const AtomLayout *al) const {
- return al->_virtualAddr;
- }
-
-private:
- std::size_t _dt_hash;
- std::size_t _dt_strtab;
- std::size_t _dt_symtab;
- std::size_t _dt_rela;
- std::size_t _dt_relasz;
- std::size_t _dt_relaent;
- std::size_t _dt_strsz;
- std::size_t _dt_syment;
- std::size_t _dt_pltrelsz;
- std::size_t _dt_pltgot;
- std::size_t _dt_pltrel;
- std::size_t _dt_jmprel;
- std::size_t _dt_init_array;
- std::size_t _dt_init_arraysz;
- std::size_t _dt_fini_array;
- std::size_t _dt_fini_arraysz;
- std::size_t _dt_textrel;
- std::size_t _dt_init;
- std::size_t _dt_fini;
- TargetLayout<ELFT> &_layout;
- DynamicSymbolTable<ELFT> *_dynamicSymbolTable;
- HashSection<ELFT> *_hashTable;
-
- const AtomLayout *getInitAtomLayout();
-
- const AtomLayout *getFiniAtomLayout();
-};
-
-template <class ELFT> class InterpSection : public Section<ELFT> {
-public:
- InterpSection(const ELFLinkingContext &ctx, StringRef str, int32_t order,
- StringRef interp);
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
-private:
- StringRef _interp;
-};
-
-/// The hash table in the dynamic linker is organized into
-///
-/// [ nbuckets ]
-/// [ nchains ]
-/// [ buckets[0] ]
-/// .........................
-/// [ buckets[nbuckets-1] ]
-/// [ chains[0] ]
-/// .........................
-/// [ chains[nchains - 1] ]
-///
-/// nbuckets - total number of hash buckets
-/// nchains is equal to the number of dynamic symbols.
-///
-/// The symbol is searched by the dynamic linker using the below approach.
-/// * Calculate the hash of the symbol that needs to be searched
-/// * Take the value from the buckets[hash % nbuckets] as the index of symbol
-/// * Compare the symbol's name, if true return, if false, look through the
-/// * array since there was a collision
-template <class ELFT> class HashSection : public Section<ELFT> {
- struct SymbolTableEntry {
- StringRef _name;
- uint32_t _index;
- };
-
-public:
- HashSection(const ELFLinkingContext &ctx, StringRef name, int32_t order);
-
- /// \brief add the dynamic symbol into the table so that the
- /// hash could be calculated
- void addSymbol(StringRef name, uint32_t index);
-
- /// \brief Set the dynamic symbol table
- void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable);
-
- // The size of the section has to be determined so that fileoffsets
- // may be properly assigned. Let's calculate the buckets and the chains
- // and fill the chains and the buckets hash table used by the dynamic
- // linker and update the filesize and memory size accordingly
- void doPreFlight() override;
-
- void finalize() override;
-
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
-private:
- typedef
- typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Word Elf_Word;
-
- std::vector<SymbolTableEntry> _entries;
- std::vector<Elf_Word> _buckets;
- std::vector<Elf_Word> _chains;
- const DynamicSymbolTable<ELFT> *_symbolTable = nullptr;
-};
-
-template <class ELFT> class EHFrameHeader : public Section<ELFT> {
-public:
- EHFrameHeader(const ELFLinkingContext &ctx, StringRef name,
- TargetLayout<ELFT> &layout, int32_t order);
- void doPreFlight() override;
- void finalize() override;
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
-private:
- int32_t _ehFrameOffset = 0;
- TargetLayout<ELFT> &_layout;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_ELF_SECTION_CHUNKS_H
diff --git a/lib/ReaderWriter/ELF/SegmentChunks.cpp b/lib/ReaderWriter/ELF/SegmentChunks.cpp
deleted file mode 100644
index 99449f7d45aa..000000000000
--- a/lib/ReaderWriter/ELF/SegmentChunks.cpp
+++ /dev/null
@@ -1,519 +0,0 @@
-//===- lib/ReaderWriter/ELF/SegmentChunks.h -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SegmentChunks.h"
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-bool SegmentSlice<ELFT>::compare_slices(SegmentSlice<ELFT> *a,
- SegmentSlice<ELFT> *b) {
- return a->startSection() < b->startSection();
-}
-
-template <class ELFT>
-Segment<ELFT>::Segment(const ELFLinkingContext &ctx, StringRef name,
- const typename TargetLayout<ELFT>::SegmentType type)
- : Chunk<ELFT>(name, Chunk<ELFT>::Kind::ELFSegment, ctx), _segmentType(type),
- _flags(0), _atomflags(0), _segmentFlags(false) {
- this->_alignment = 1;
- this->_fsize = 0;
- _outputMagic = ctx.getOutputMagic();
-}
-
-// This function actually is used, but not in all instantiations of Segment.
-LLVM_ATTRIBUTE_UNUSED
-static DefinedAtom::ContentPermissions toAtomPerms(uint64_t flags) {
- switch (flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR)) {
- case SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR:
- return DefinedAtom::permRWX;
- case SHF_ALLOC | SHF_EXECINSTR:
- return DefinedAtom::permR_X;
- case SHF_ALLOC:
- return DefinedAtom::permR__;
- case SHF_ALLOC | SHF_WRITE:
- return DefinedAtom::permRW_;
- default:
- return DefinedAtom::permUnknown;
- }
-}
-
-// This function actually is used, but not in all instantiations of Segment.
-LLVM_ATTRIBUTE_UNUSED
-static DefinedAtom::ContentPermissions toAtomPermsSegment(uint64_t flags) {
- switch (flags & (llvm::ELF::PF_R | llvm::ELF::PF_W | llvm::ELF::PF_X)) {
- case llvm::ELF::PF_R | llvm::ELF::PF_W | llvm::ELF::PF_X:
- return DefinedAtom::permRWX;
- case llvm::ELF::PF_R | llvm::ELF::PF_X:
- return DefinedAtom::permR_X;
- case llvm::ELF::PF_R:
- return DefinedAtom::permR__;
- case llvm::ELF::PF_R | llvm::ELF::PF_W:
- return DefinedAtom::permRW_;
- default:
- return DefinedAtom::permUnknown;
- }
-}
-
-template <class ELFT> void Segment<ELFT>::append(Chunk<ELFT> *chunk) {
- _sections.push_back(chunk);
- Section<ELFT> *section = dyn_cast<Section<ELFT>>(chunk);
- if (!section)
- return;
- if (this->_alignment < section->alignment())
- this->_alignment = section->alignment();
-
- if (_segmentFlags)
- return;
- if (_flags < section->getFlags())
- _flags |= section->getFlags();
- if (_atomflags < toAtomPerms(_flags))
- _atomflags = toAtomPerms(_flags);
-}
-
-template <class ELFT>
-bool Segment<ELFT>::compareSegments(Segment<ELFT> *sega, Segment<ELFT> *segb) {
- int64_t type1 = sega->segmentType();
- int64_t type2 = segb->segmentType();
-
- if (type1 == type2)
- return sega->atomflags() < segb->atomflags();
-
- // The single PT_PHDR segment is required to precede any loadable
- // segment. We simply make it always first.
- if (type1 == llvm::ELF::PT_PHDR)
- return true;
- if (type2 == llvm::ELF::PT_PHDR)
- return false;
-
- // The single PT_INTERP segment is required to precede any loadable
- // segment. We simply make it always second.
- if (type1 == llvm::ELF::PT_INTERP)
- return true;
- if (type2 == llvm::ELF::PT_INTERP)
- return false;
-
- // We then put PT_LOAD segments before any other segments.
- if (type1 == llvm::ELF::PT_LOAD)
- return true;
- if (type2 == llvm::ELF::PT_LOAD)
- return false;
-
- // We put the PT_GNU_RELRO segment last, because that is where the
- // dynamic linker expects to find it
- if (type1 == llvm::ELF::PT_GNU_RELRO)
- return false;
- if (type2 == llvm::ELF::PT_GNU_RELRO)
- return true;
-
- // We put the PT_TLS segment last except for the PT_GNU_RELRO
- // segment, because that is where the dynamic linker expects to find
- if (type1 == llvm::ELF::PT_TLS)
- return false;
- if (type2 == llvm::ELF::PT_TLS)
- return true;
-
- // Otherwise compare the types to establish an arbitrary ordering.
- // FIXME: Should figure out if we should just make all other types compare
- // equal, but if so, we should probably do the same for atom flags and change
- // users of this to use stable_sort.
- return type1 < type2;
-}
-
-template <class ELFT>
-void Segment<ELFT>::assignFileOffsets(uint64_t startOffset) {
- uint64_t fileOffset = startOffset;
- uint64_t curSliceFileOffset = fileOffset;
- bool isDataPageAlignedForNMagic = false;
- bool alignSegments = this->_ctx.alignSegments();
- uint64_t p_align = this->_ctx.getPageSize();
- uint64_t lastVirtualAddress = 0;
-
- this->setFileOffset(startOffset);
- bool changeOffset = false;
- uint64_t newOffset = 0;
- for (auto &slice : slices()) {
- bool isFirstSection = true;
- for (auto section : slice->sections()) {
- // Handle linker script expressions, which may change the offset
- if (auto expr = dyn_cast<ExpressionChunk<ELFT>>(section)) {
- if (!isFirstSection) {
- changeOffset = true;
- newOffset = fileOffset + expr->virtualAddr() - lastVirtualAddress;
- }
- continue;
- }
- if (changeOffset) {
- changeOffset = false;
- fileOffset = newOffset;
- }
- // Align fileoffset to the alignment of the section.
- fileOffset = llvm::RoundUpToAlignment(fileOffset, section->alignment());
- // If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data
- // to a page boundary
- if (isFirstSection &&
- _outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
- _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC) {
- // Align to a page only if the output is not
- // OutputMagic::NMAGIC/OutputMagic::OMAGIC
- if (alignSegments)
- fileOffset = llvm::RoundUpToAlignment(fileOffset, p_align);
- // Align according to ELF spec.
- // in p75, http://www.sco.com/developers/devspecs/gabi41.pdf
- uint64_t virtualAddress = slice->virtualAddr();
- Section<ELFT> *sect = dyn_cast<Section<ELFT>>(section);
- if (sect && sect->isLoadableSection() &&
- ((virtualAddress & (p_align - 1)) != (fileOffset & (p_align - 1))))
- fileOffset = llvm::RoundUpToAlignment(fileOffset, p_align) +
- (virtualAddress % p_align);
- } else if (!isDataPageAlignedForNMagic && needAlign(section)) {
- fileOffset =
- llvm::RoundUpToAlignment(fileOffset, this->_ctx.getPageSize());
- isDataPageAlignedForNMagic = true;
- }
- if (isFirstSection) {
- slice->setFileOffset(fileOffset);
- isFirstSection = false;
- curSliceFileOffset = fileOffset;
- }
- section->setFileOffset(fileOffset);
- fileOffset += section->fileSize();
- lastVirtualAddress = section->virtualAddr() + section->memSize();
- }
- changeOffset = false;
- slice->setFileSize(fileOffset - curSliceFileOffset);
- }
- this->setFileSize(fileOffset - startOffset);
-}
-
-/// \brief Assign virtual addresses to the slices
-template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t addr) {
- int startSection = 0;
- int currSection = 0;
- SectionIter startSectionIter;
-
- // slice align is set to the max alignment of the chunks that are
- // contained in the slice
- uint64_t sliceAlign = 0;
- // Current slice size
- uint64_t curSliceSize = 0;
- // Current Slice File Offset
- uint64_t curSliceAddress = 0;
-
- startSectionIter = _sections.begin();
- startSection = 0;
- bool isDataPageAlignedForNMagic = false;
- uint64_t startAddr = addr;
- SegmentSlice<ELFT> *slice = nullptr;
- uint64_t tlsStartAddr = 0;
- bool alignSegments = this->_ctx.alignSegments();
- StringRef prevOutputSectionName = StringRef();
- uint64_t tbssMemsize = 0;
-
- // If this is first section in the segment, page align the section start
- // address. The linker needs to align the data section to a page boundary
- // only if NMAGIC is set.
- auto si = _sections.begin();
- if (si != _sections.end()) {
- if (alignSegments &&
- _outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
- _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC) {
- // Align to a page only if the output is not
- // OutputMagic::NMAGIC/OutputMagic::OMAGIC
- startAddr = llvm::RoundUpToAlignment(startAddr, this->_ctx.getPageSize());
- } else if (needAlign(*si)) {
- // If the linker outputmagic is set to OutputMagic::NMAGIC, align the
- // Data to a page boundary.
- startAddr = llvm::RoundUpToAlignment(startAddr, this->_ctx.getPageSize());
- isDataPageAlignedForNMagic = true;
- }
- // align the startOffset to the section alignment
- uint64_t newAddr = llvm::RoundUpToAlignment(startAddr, (*si)->alignment());
- // Handle linker script expressions, which *may update newAddr* if the
- // expression assigns to "."
- if (auto expr = dyn_cast<ExpressionChunk<ELFT>>(*si))
- expr->evalExpr(newAddr);
- curSliceAddress = newAddr;
- sliceAlign = (*si)->alignment();
- (*si)->setVirtualAddr(curSliceAddress);
-
- // Handle TLS.
- if (auto section = dyn_cast<Section<ELFT>>(*si)) {
- if (section->getSegmentType() == llvm::ELF::PT_TLS) {
- tlsStartAddr =
- llvm::RoundUpToAlignment(tlsStartAddr, (*si)->alignment());
- section->assignVirtualAddress(tlsStartAddr);
- tlsStartAddr += (*si)->memSize();
- } else {
- section->assignVirtualAddress(newAddr);
- }
- }
- // TBSS section is special in that it doesn't contribute to memory of any
- // segment. If we see a tbss section, don't add memory size to addr The
- // fileOffset is automatically taken care of since TBSS section does not
- // end up using file size
- if ((*si)->order() != TargetLayout<ELFT>::ORDER_TBSS) {
- curSliceSize = (*si)->memSize();
- tbssMemsize = 0;
- } else {
- tbssMemsize = (*si)->memSize();
- }
- ++currSection;
- ++si;
- }
-
- uint64_t scriptAddr = 0;
- bool forceScriptAddr = false;
- for (auto e = _sections.end(); si != e; ++si) {
- uint64_t curAddr = curSliceAddress + curSliceSize;
- if (!isDataPageAlignedForNMagic && needAlign(*si)) {
- // If the linker outputmagic is set to OutputMagic::NMAGIC, align the
- // Data
- // to a page boundary
- curAddr = llvm::RoundUpToAlignment(curAddr, this->_ctx.getPageSize());
- isDataPageAlignedForNMagic = true;
- }
- uint64_t newAddr = llvm::RoundUpToAlignment(
- forceScriptAddr ? scriptAddr : curAddr, (*si)->alignment());
- forceScriptAddr = false;
-
- // Handle linker script expressions, which may force an address change if
- // the expression assigns to "."
- if (auto expr = dyn_cast<ExpressionChunk<ELFT>>(*si)) {
- uint64_t oldAddr = newAddr;
- expr->evalExpr(newAddr);
- if (oldAddr != newAddr) {
- forceScriptAddr = true;
- scriptAddr = newAddr;
- }
- (*si)->setVirtualAddr(newAddr);
- continue;
- }
- Section<ELFT> *sec = dyn_cast<Section<ELFT>>(*si);
- StringRef curOutputSectionName =
- sec ? sec->outputSectionName() : (*si)->name();
- bool autoCreateSlice = true;
- if (curOutputSectionName == prevOutputSectionName)
- autoCreateSlice = false;
- // If the newAddress computed is more than a page away, let's create
- // a separate segment, so that memory is not used up while running.
- // Dont create a slice, if the new section falls in the same output
- // section as the previous section.
- if (autoCreateSlice && ((newAddr - curAddr) > this->_ctx.getPageSize()) &&
- (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
- _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)) {
- auto sliceIter =
- std::find_if(_segmentSlices.begin(), _segmentSlices.end(),
- [startSection](SegmentSlice<ELFT> *s) -> bool {
- return s->startSection() == startSection;
- });
- if (sliceIter == _segmentSlices.end()) {
- slice = new (_segmentAllocate.Allocate<SegmentSlice<ELFT>>())
- SegmentSlice<ELFT>();
- _segmentSlices.push_back(slice);
- } else {
- slice = *sliceIter;
- }
- slice->setStart(startSection);
- slice->setSections(make_range(startSectionIter, si));
- slice->setMemSize(curSliceSize);
- slice->setAlign(sliceAlign);
- slice->setVirtualAddr(curSliceAddress);
- // Start new slice
- curSliceAddress = newAddr;
- if ((*si)->order() == TargetLayout<ELFT>::ORDER_TBSS)
- curSliceAddress += tbssMemsize;
- (*si)->setVirtualAddr(curSliceAddress);
- startSectionIter = si;
- startSection = currSection;
- if (auto section = dyn_cast<Section<ELFT>>(*si))
- section->assignVirtualAddress(newAddr);
- curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
- sliceAlign = (*si)->alignment();
- } else {
- if (sliceAlign < (*si)->alignment())
- sliceAlign = (*si)->alignment();
- if ((*si)->order() == TargetLayout<ELFT>::ORDER_TBSS)
- newAddr += tbssMemsize;
- (*si)->setVirtualAddr(newAddr);
- // Handle TLS.
- if (auto section = dyn_cast<Section<ELFT>>(*si)) {
- if (section->getSegmentType() == llvm::ELF::PT_TLS) {
- tlsStartAddr =
- llvm::RoundUpToAlignment(tlsStartAddr, (*si)->alignment());
- section->assignVirtualAddress(tlsStartAddr);
- tlsStartAddr += (*si)->memSize();
- } else {
- section->assignVirtualAddress(newAddr);
- }
- }
- // TBSS section is special in that it doesn't contribute to memory of
- // any segment. If we see a tbss section, don't add memory size to addr
- // The fileOffset is automatically taken care of since TBSS section does
- // not end up using file size.
- if ((*si)->order() != TargetLayout<ELFT>::ORDER_TBSS) {
- curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
- tbssMemsize = 0;
- } else {
- // Although TBSS section does not contribute to memory of any segment,
- // we still need to keep track its total size to correct write it
- // down. Since it is done based on curSliceAddress, we need to add
- // add it to virtual address.
- tbssMemsize = (*si)->memSize();
- }
- }
- prevOutputSectionName = curOutputSectionName;
- ++currSection;
- }
-
- auto sliceIter = std::find_if(_segmentSlices.begin(), _segmentSlices.end(),
- [startSection](SegmentSlice<ELFT> *s) -> bool {
- return s->startSection() == startSection;
- });
- if (sliceIter == _segmentSlices.end()) {
- slice = new (_segmentAllocate.Allocate<SegmentSlice<ELFT>>())
- SegmentSlice<ELFT>();
- _segmentSlices.push_back(slice);
- } else {
- slice = *sliceIter;
- }
-
- slice->setStart(startSection);
- slice->setVirtualAddr(curSliceAddress);
- slice->setMemSize(curSliceSize);
- slice->setSections(make_range(startSectionIter, _sections.end()));
- slice->setAlign(sliceAlign);
-
- // Set the segment memory size and the virtual address.
- this->setMemSize(curSliceAddress - startAddr + curSliceSize);
- this->setVirtualAddr(startAddr);
- std::stable_sort(_segmentSlices.begin(), _segmentSlices.end(),
- SegmentSlice<ELFT>::compare_slices);
-}
-
-// Write the Segment
-template <class ELFT>
-void Segment<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) {
- for (auto slice : slices())
- for (auto section : slice->sections())
- section->write(writer, layout, buffer);
-}
-
-template <class ELFT> int64_t Segment<ELFT>::flags() const {
- if (_segmentFlags)
- return (int64_t)_flags;
-
- int64_t fl = 0;
- if (_flags & llvm::ELF::SHF_ALLOC)
- fl |= llvm::ELF::PF_R;
- if (_flags & llvm::ELF::SHF_WRITE)
- fl |= llvm::ELF::PF_W;
- if (_flags & llvm::ELF::SHF_EXECINSTR)
- fl |= llvm::ELF::PF_X;
- return fl;
-}
-
-template <class ELFT> void Segment<ELFT>::setSegmentFlags(uint64_t flags) {
- assert(!_segmentFlags && "Segment flags have already been set");
- _segmentFlags = true;
- _flags = flags;
- _atomflags = toAtomPermsSegment(flags);
-}
-
-template <class ELFT> void Segment<ELFT>::finalize() {
- // We want to finalize the segment values for now only for non loadable
- // segments, since those values are not set in the Layout
- if (_segmentType == llvm::ELF::PT_LOAD)
- return;
- // The size is the difference of the
- // last section to the first section, especially for TLS because
- // the TLS segment contains both .tdata/.tbss
- this->setFileOffset(_sections.front()->fileOffset());
- this->setVirtualAddr(_sections.front()->virtualAddr());
- size_t startFileOffset = _sections.front()->fileOffset();
- size_t startAddr = _sections.front()->virtualAddr();
- for (auto ai : _sections) {
- this->_fsize = ai->fileOffset() + ai->fileSize() - startFileOffset;
- this->_msize = ai->virtualAddr() + ai->memSize() - startAddr;
- }
-}
-
-template <class ELFT> int Segment<ELFT>::getContentType() const {
- int64_t fl = flags();
- switch (_segmentType) {
- case llvm::ELF::PT_LOAD: {
- if (fl && llvm::ELF::PF_X)
- return Chunk<ELFT>::ContentType::Code;
- if (fl && llvm::ELF::PF_W)
- return Chunk<ELFT>::ContentType::Data;
- }
- case llvm::ELF::PT_TLS:
- return Chunk<ELFT>::ContentType::TLS;
- case llvm::ELF::PT_NOTE:
- return Chunk<ELFT>::ContentType::Note;
- default:
- return Chunk<ELFT>::ContentType::Unknown;
- }
-}
-
-template <class ELFT> int64_t Segment<ELFT>::atomflags() const {
- switch (_atomflags) {
- case DefinedAtom::permUnknown:
- return permUnknown;
- case DefinedAtom::permRWX:
- return permRWX;
- case DefinedAtom::permR_X:
- return permRX;
- case DefinedAtom::permR__:
- return permR;
- case DefinedAtom::permRW_L:
- return permRWL;
- case DefinedAtom::permRW_:
- return permRW;
- case DefinedAtom::perm___:
- default:
- return permNonAccess;
- }
-}
-
-/// \brief Check if the chunk needs to be aligned
-template <class ELFT> bool Segment<ELFT>::needAlign(Chunk<ELFT> *chunk) const {
- if (chunk->getContentType() == Chunk<ELFT>::ContentType::Data &&
- _outputMagic == ELFLinkingContext::OutputMagic::NMAGIC)
- return true;
- return false;
-}
-
-template <class ELFT> void ProgramHeaderSegment<ELFT>::finalize() {
- // If the segment is of type Program Header, then the values fileOffset
- // and the fileSize need to be picked up from the last section, the first
- // section points to the ELF header and the second chunk points to the
- // actual program headers
- this->setFileOffset(this->_sections.back()->fileOffset());
- this->setVirtualAddr(this->_sections.back()->virtualAddr());
- this->_fsize = this->_sections.back()->fileSize();
- this->_msize = this->_sections.back()->memSize();
-}
-
-#define INSTANTIATE(klass) \
- template class klass<ELF32LE>; \
- template class klass<ELF32BE>; \
- template class klass<ELF64LE>; \
- template class klass<ELF64BE>
-
-INSTANTIATE(ExpressionChunk);
-INSTANTIATE(ProgramHeaderSegment);
-INSTANTIATE(Segment);
-INSTANTIATE(SegmentSlice);
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/SegmentChunks.h b/lib/ReaderWriter/ELF/SegmentChunks.h
deleted file mode 100644
index b444f44c04eb..000000000000
--- a/lib/ReaderWriter/ELF/SegmentChunks.h
+++ /dev/null
@@ -1,246 +0,0 @@
-//===- lib/ReaderWriter/ELF/SegmentChunks.h -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H
-#define LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H
-
-#include "Chunk.h"
-#include "SectionChunks.h"
-#include "Writer.h"
-#include "lld/Core/range.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include <memory>
-
-namespace lld {
-namespace elf {
-
-template <typename ELFT> class TargetLayout;
-
-/// \brief A segment can be divided into segment slices
-/// depending on how the segments can be split
-template<class ELFT>
-class SegmentSlice {
-public:
- typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
-
- /// Set the start of the slice.
- void setStart(int32_t s) { _startSection = s; }
-
- // Set the segment slice start and end iterators. This is used to walk through
- // the sections that are part of the Segment slice
- void setSections(range<SectionIter> sections) { _sections = sections; }
-
- // Return the fileOffset of the slice
- uint64_t fileOffset() const { return _offset; }
- void setFileOffset(uint64_t offset) { _offset = offset; }
-
- // Return the size of the slice
- uint64_t fileSize() const { return _fsize; }
- void setFileSize(uint64_t filesz) { _fsize = filesz; }
-
- // Return the start of the slice
- int32_t startSection() const { return _startSection; }
-
- // Return the start address of the slice
- uint64_t virtualAddr() const { return _addr; }
-
- // Return the memory size of the slice
- uint64_t memSize() const { return _memSize; }
-
- // Return the alignment of the slice
- uint64_t alignment() const { return _alignment; }
-
- void setMemSize(uint64_t memsz) { _memSize = memsz; }
-
- void setVirtualAddr(uint64_t addr) { _addr = addr; }
-
- void setAlign(uint64_t align) { _alignment = align; }
-
- static bool compare_slices(SegmentSlice<ELFT> *a, SegmentSlice<ELFT> *b);
-
- range<SectionIter> sections() { return _sections; }
-
-private:
- range<SectionIter> _sections;
- int32_t _startSection;
- uint64_t _addr;
- uint64_t _offset;
- uint64_t _alignment;
- uint64_t _fsize;
- uint64_t _memSize;
-};
-
-/// \brief A segment contains a set of sections, that have similar properties
-// the sections are already separated based on different flags and properties
-// the segment is just a way to concatenate sections to segments
-template<class ELFT>
-class Segment : public Chunk<ELFT> {
-public:
- typedef typename std::vector<SegmentSlice<ELFT> *>::iterator SliceIter;
- typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
-
- Segment(const ELFLinkingContext &ctx, StringRef name,
- const typename TargetLayout<ELFT>::SegmentType type);
-
- /// \brief the Order of segments that appear in the output file
- enum SegmentOrder {
- permUnknown,
- permRWX,
- permRX,
- permR,
- permRWL,
- permRW,
- permNonAccess
- };
-
- /// append a section to a segment
- virtual void append(Chunk<ELFT> *chunk);
-
- /// Sort segments depending on the property
- /// If we have a Program Header segment, it should appear first
- /// If we have a INTERP segment, that should appear after the Program Header
- /// All Loadable segments appear next in this order
- /// All Read Write Execute segments follow
- /// All Read Execute segments appear next
- /// All Read only segments appear first
- /// All Write execute segments follow
- static bool compareSegments(Segment<ELFT> *sega, Segment<ELFT> *segb);
-
- /// \brief Start assigning file offset to the segment chunks The fileoffset
- /// needs to be page at the start of the segment and in addition the
- /// fileoffset needs to be aligned to the max section alignment within the
- /// segment. This is required so that the ELF property p_poffset % p_align =
- /// p_vaddr mod p_align holds true.
- /// The algorithm starts off by assigning the startOffset thats passed in as
- /// parameter to the first section in the segment, if the difference between
- /// the newly computed offset is greater than a page, then we create a segment
- /// slice, as it would be a waste of virtual memory just to be filled with
- /// zeroes
- void assignFileOffsets(uint64_t startOffset);
-
- /// \brief Assign virtual addresses to the slices
- void assignVirtualAddress(uint64_t addr);
-
- // Write the Segment
- void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override;
-
- int64_t flags() const;
-
- // Set segment flags directly.
- void setSegmentFlags(uint64_t flags);
-
- /// Prepend a generic chunk to the segment.
- void prepend(Chunk<ELFT> *c) {
- _sections.insert(_sections.begin(), c);
- }
-
- /// Finalize the segment, before we want to write the segment header
- /// information
- void finalize() override;
-
- // For LLVM RTTI
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::ELFSegment;
- }
-
- // Getters
- int32_t sectionCount() const { return _sections.size(); }
-
- /// \brief, this function returns the type of segment (PT_*)
- typename TargetLayout<ELFT>::SegmentType segmentType() const {
- return _segmentType;
- }
-
- /// \brief return the segment type depending on the content,
- /// If the content corresponds to Code, this will return Segment::Code
- /// If the content corresponds to Data, this will return Segment::Data
- /// If the content corresponds to TLS, this will return Segment::TLS
- int getContentType() const override;
-
- int pageSize() const { return this->_ctx.getPageSize(); }
- int rawflags() const { return _atomflags; }
- int64_t atomflags() const;
- int64_t numSlices() const { return _segmentSlices.size(); }
- range<SliceIter> slices() { return _segmentSlices; }
- Chunk<ELFT> *firstSection() { return _sections[0]; }
-
-private:
- /// \brief Check if the chunk needs to be aligned
- bool needAlign(Chunk<ELFT> *chunk) const;
-
- // Cached value of outputMagic
- ELFLinkingContext::OutputMagic _outputMagic;
-
-protected:
- /// \brief Section or some other chunk type.
- std::vector<Chunk<ELFT> *> _sections;
- std::vector<SegmentSlice<ELFT> *> _segmentSlices;
- typename TargetLayout<ELFT>::SegmentType _segmentType;
- uint64_t _flags;
- int64_t _atomflags;
- bool _segmentFlags;
- llvm::BumpPtrAllocator _segmentAllocate;
-};
-
-/// This chunk represents a linker script expression that needs to be calculated
-/// at the time the virtual addresses for the parent segment are being assigned.
-template <class ELFT> class ExpressionChunk : public Chunk<ELFT> {
-public:
- ExpressionChunk(ELFLinkingContext &ctx, const script::SymbolAssignment *expr)
- : Chunk<ELFT>(StringRef(), Chunk<ELFT>::Kind::Expression, ctx),
- _expr(expr), _linkerScriptSema(ctx.linkerScriptSema()) {
- this->_alignment = 1;
- }
-
- static bool classof(const Chunk<ELFT> *c) {
- return c->kind() == Chunk<ELFT>::Kind::Expression;
- }
-
- int getContentType() const override {
- return Chunk<ELFT>::ContentType::Unknown;
- }
-
- void write(ELFWriter *, TargetLayout<ELFT> &,
- llvm::FileOutputBuffer &) override {}
-
- std::error_code evalExpr(uint64_t &curPos) {
- return _linkerScriptSema.evalExpr(_expr, curPos);
- }
-
-private:
- const script::SymbolAssignment *_expr;
- script::Sema &_linkerScriptSema;
-};
-
-/// \brief A Program Header segment contains a set of chunks instead of sections
-/// The segment doesn't contain any slice
-template <class ELFT> class ProgramHeaderSegment : public Segment<ELFT> {
-public:
- ProgramHeaderSegment(const ELFLinkingContext &ctx)
- : Segment<ELFT>(ctx, "PHDR", llvm::ELF::PT_PHDR) {
- this->_alignment = 8;
- this->_flags = (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR);
- }
-
- /// Finalize the segment, before we want to write the segment header
- /// information
- void finalize() override;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H
diff --git a/lib/ReaderWriter/ELF/TODO.txt b/lib/ReaderWriter/ELF/TODO.txt
deleted file mode 100644
index 90c334b781ba..000000000000
--- a/lib/ReaderWriter/ELF/TODO.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-lib/ReaderWriter/ELF
-~~~~~~~~~~~~~~~~~~~~
-
-- Implement processing of DT_NEEDED elements including -rpath-link /
- -rpath processing.
-
-- _GLOBAL_OFFSET_TABLE should be hidden and normally dropped from the output.
-
-- Merge SHT_NOTE sections only if applicable.
-
-- Do not create __got_* / __plt_* symbol table entries by default.
-
-- Weak references to symbols defined in a DSO should remain weak.
-
-- Fix section flags as they appear in input (update content permissions)
-
-- Check for errors in the ELFReader when creating atoms for LinkOnce
- sections/Group sections. Add tests to account for the change when it happens.
diff --git a/lib/ReaderWriter/ELF/TargetHandler.h b/lib/ReaderWriter/ELF/TargetHandler.h
deleted file mode 100644
index 406ac670fc83..000000000000
--- a/lib/ReaderWriter/ELF/TargetHandler.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- lib/ReaderWriter/ELF/TargetHandler.h -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_TARGET_HANDLER_H
-#define LLD_READER_WRITER_ELF_TARGET_HANDLER_H
-
-#include "lld/Core/Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ErrorHandling.h"
-
-namespace lld {
-namespace elf {
-
-inline std::error_code make_unhandled_reloc_error() {
- return make_dynamic_error_code("Unhandled reference type");
-}
-
-inline std::error_code make_out_of_range_reloc_error() {
- return make_dynamic_error_code("Relocation out of range");
-}
-
-inline std::error_code make_unaligned_range_reloc_error() {
- return make_dynamic_error_code("Relocation not aligned");
-}
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/TargetLayout.cpp b/lib/ReaderWriter/ELF/TargetLayout.cpp
deleted file mode 100644
index 09c49f62d64f..000000000000
--- a/lib/ReaderWriter/ELF/TargetLayout.cpp
+++ /dev/null
@@ -1,747 +0,0 @@
-//===- lib/ReaderWriter/ELF/TargetLayout.cpp ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TargetLayout.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Errc.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT>
-typename TargetLayout<ELFT>::SectionOrder
-TargetLayout<ELFT>::getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPermissions) {
- switch (contentType) {
- case DefinedAtom::typeResolver:
- case DefinedAtom::typeCode:
- return llvm::StringSwitch<typename TargetLayout<ELFT>::SectionOrder>(name)
- .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
- .StartsWith(".eh_frame", ORDER_EH_FRAME)
- .StartsWith(".init", ORDER_INIT)
- .StartsWith(".fini", ORDER_FINI)
- .StartsWith(".hash", ORDER_HASH)
- .Default(ORDER_TEXT);
-
- case DefinedAtom::typeConstant:
- return ORDER_RODATA;
-
- case DefinedAtom::typeData:
- case DefinedAtom::typeDataFast:
- return llvm::StringSwitch<typename TargetLayout<ELFT>::SectionOrder>(name)
- .StartsWith(".init_array", ORDER_INIT_ARRAY)
- .StartsWith(".fini_array", ORDER_FINI_ARRAY)
- .StartsWith(".dynamic", ORDER_DYNAMIC)
- .StartsWith(".ctors", ORDER_CTORS)
- .StartsWith(".dtors", ORDER_DTORS)
- .Default(ORDER_DATA);
-
- case DefinedAtom::typeZeroFill:
- case DefinedAtom::typeZeroFillFast:
- return ORDER_BSS;
-
- case DefinedAtom::typeGOT:
- return llvm::StringSwitch<typename TargetLayout<ELFT>::SectionOrder>(name)
- .StartsWith(".got.plt", ORDER_GOT_PLT)
- .Default(ORDER_GOT);
-
- case DefinedAtom::typeStub:
- return ORDER_PLT;
-
- case DefinedAtom::typeRONote:
- return ORDER_RO_NOTE;
-
- case DefinedAtom::typeRWNote:
- return ORDER_RW_NOTE;
-
- case DefinedAtom::typeNoAlloc:
- return ORDER_NOALLOC;
-
- case DefinedAtom::typeThreadData:
- return ORDER_TDATA;
- case DefinedAtom::typeThreadZeroFill:
- return ORDER_TBSS;
- default:
- // If we get passed in a section push it to OTHER
- if (contentPermissions == DefinedAtom::perm___)
- return ORDER_OTHER;
-
- return ORDER_NOT_DEFINED;
- }
-}
-
-/// \brief This maps the input sections to the output section names
-template <class ELFT>
-StringRef TargetLayout<ELFT>::getInputSectionName(const DefinedAtom *da) const {
- if (da->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
- switch (da->contentType()) {
- case DefinedAtom::typeCode:
- return ".text";
- case DefinedAtom::typeData:
- return ".data";
- case DefinedAtom::typeConstant:
- return ".rodata";
- case DefinedAtom::typeZeroFill:
- return ".bss";
- case DefinedAtom::typeThreadData:
- return ".tdata";
- case DefinedAtom::typeThreadZeroFill:
- return ".tbss";
- default:
- break;
- }
- }
- return da->customSectionName();
-}
-
-/// \brief This maps the input sections to the output section names.
-template <class ELFT>
-StringRef
-TargetLayout<ELFT>::getOutputSectionName(StringRef archivePath,
- StringRef memberPath,
- StringRef inputSectionName) const {
- StringRef outputSectionName;
- if (_linkerScriptSema.hasLayoutCommands()) {
- script::Sema::SectionKey key = {archivePath, memberPath, inputSectionName};
- outputSectionName = _linkerScriptSema.getOutputSection(key);
- if (!outputSectionName.empty())
- return outputSectionName;
- }
- return llvm::StringSwitch<StringRef>(inputSectionName)
- .StartsWith(".text", ".text")
- .StartsWith(".ctors", ".ctors")
- .StartsWith(".dtors", ".dtors")
- .StartsWith(".rodata", ".rodata")
- .StartsWith(".gcc_except_table", ".gcc_except_table")
- .StartsWith(".data.rel.ro", ".data.rel.ro")
- .StartsWith(".data.rel.local", ".data.rel.local")
- .StartsWith(".data", ".data")
- .StartsWith(".tdata", ".tdata")
- .StartsWith(".tbss", ".tbss")
- .StartsWith(".init_array", ".init_array")
- .StartsWith(".fini_array", ".fini_array")
- .Default(inputSectionName);
-}
-
-/// \brief Gets the segment for a output section
-template <class ELFT>
-typename TargetLayout<ELFT>::SegmentType
-TargetLayout<ELFT>::getSegmentType(const Section<ELFT> *section) const {
- switch (section->order()) {
- case ORDER_INTERP:
- return llvm::ELF::PT_INTERP;
-
- case ORDER_TEXT:
- case ORDER_HASH:
- case ORDER_DYNAMIC_SYMBOLS:
- case ORDER_DYNAMIC_STRINGS:
- case ORDER_DYNAMIC_RELOCS:
- case ORDER_DYNAMIC_PLT_RELOCS:
- case ORDER_REL:
- case ORDER_INIT:
- case ORDER_PLT:
- case ORDER_FINI:
- case ORDER_RODATA:
- case ORDER_EH_FRAME:
- case ORDER_CTORS:
- case ORDER_DTORS:
- return llvm::ELF::PT_LOAD;
-
- case ORDER_RO_NOTE:
- case ORDER_RW_NOTE:
- return llvm::ELF::PT_NOTE;
-
- case ORDER_DYNAMIC:
- return llvm::ELF::PT_DYNAMIC;
-
- case ORDER_EH_FRAMEHDR:
- return llvm::ELF::PT_GNU_EH_FRAME;
-
- case ORDER_GOT:
- case ORDER_GOT_PLT:
- case ORDER_DATA:
- case ORDER_BSS:
- case ORDER_INIT_ARRAY:
- case ORDER_FINI_ARRAY:
- return llvm::ELF::PT_LOAD;
-
- case ORDER_TDATA:
- case ORDER_TBSS:
- return llvm::ELF::PT_TLS;
-
- default:
- return llvm::ELF::PT_NULL;
- }
-}
-
-template <class ELFT>
-bool TargetLayout<ELFT>::hasOutputSegment(Section<ELFT> *section) {
- switch (section->order()) {
- case ORDER_INTERP:
- case ORDER_HASH:
- case ORDER_DYNAMIC_SYMBOLS:
- case ORDER_DYNAMIC_STRINGS:
- case ORDER_DYNAMIC_RELOCS:
- case ORDER_DYNAMIC_PLT_RELOCS:
- case ORDER_REL:
- case ORDER_INIT:
- case ORDER_PLT:
- case ORDER_TEXT:
- case ORDER_FINI:
- case ORDER_RODATA:
- case ORDER_EH_FRAME:
- case ORDER_EH_FRAMEHDR:
- case ORDER_TDATA:
- case ORDER_TBSS:
- case ORDER_RO_NOTE:
- case ORDER_RW_NOTE:
- case ORDER_DYNAMIC:
- case ORDER_CTORS:
- case ORDER_DTORS:
- case ORDER_GOT:
- case ORDER_GOT_PLT:
- case ORDER_DATA:
- case ORDER_INIT_ARRAY:
- case ORDER_FINI_ARRAY:
- case ORDER_BSS:
- case ORDER_NOALLOC:
- return true;
- default:
- return section->hasOutputSegment();
- }
-}
-
-template <class ELFT>
-AtomSection<ELFT> *
-TargetLayout<ELFT>::createSection(StringRef sectionName, int32_t contentType,
- DefinedAtom::ContentPermissions permissions,
- SectionOrder sectionOrder) {
- return new (_allocator) AtomSection<ELFT>(_ctx, sectionName, contentType,
- permissions, sectionOrder);
-}
-
-template <class ELFT>
-AtomSection<ELFT> *
-TargetLayout<ELFT>::getSection(StringRef sectionName, int32_t contentType,
- DefinedAtom::ContentPermissions permissions,
- const DefinedAtom *da) {
- const SectionKey sectionKey(sectionName, permissions, da->file().path());
- SectionOrder sectionOrder =
- getSectionOrder(sectionName, contentType, permissions);
- auto sec = _sectionMap.find(sectionKey);
- if (sec != _sectionMap.end())
- return sec->second;
- AtomSection<ELFT> *newSec =
- createSection(sectionName, contentType, permissions, sectionOrder);
-
- newSec->setOutputSectionName(getOutputSectionName(
- da->file().archivePath(), da->file().memberPath(), sectionName));
- newSec->setOrder(sectionOrder);
- newSec->setArchiveNameOrPath(da->file().archivePath());
- newSec->setMemberNameOrPath(da->file().memberPath());
- _sections.push_back(newSec);
- _sectionMap.insert(std::make_pair(sectionKey, newSec));
- return newSec;
-}
-
-template <class ELFT>
-ErrorOr<const AtomLayout *> TargetLayout<ELFT>::addAtom(const Atom *atom) {
- if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
- // HACK: Ignore undefined atoms. We need to adjust the interface so that
- // undefined atoms can still be included in the output symbol table for
- // -noinhibit-exec.
- if (definedAtom->contentType() == DefinedAtom::typeUnknown)
- return make_error_code(llvm::errc::invalid_argument);
- const DefinedAtom::ContentPermissions permissions =
- definedAtom->permissions();
- const DefinedAtom::ContentType contentType = definedAtom->contentType();
-
- StringRef sectionName = getInputSectionName(definedAtom);
- AtomSection<ELFT> *section =
- getSection(sectionName, contentType, permissions, definedAtom);
-
- // Add runtime relocations to the .rela section.
- for (const auto &reloc : *definedAtom) {
- bool isLocalReloc = true;
- if (_ctx.isDynamicRelocation(*reloc)) {
- getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc);
- isLocalReloc = false;
- } else if (_ctx.isPLTRelocation(*reloc)) {
- getPLTRelocationTable()->addRelocation(*definedAtom, *reloc);
- isLocalReloc = false;
- }
-
- if (!reloc->target())
- continue;
-
- // Ignore undefined atoms that are not target of dynamic relocations
- if (isa<UndefinedAtom>(reloc->target()) && isLocalReloc)
- continue;
-
- if (_ctx.isCopyRelocation(*reloc)) {
- _copiedDynSymNames.insert(definedAtom->name());
- continue;
- }
-
- _referencedDynAtoms.insert(reloc->target());
- }
- return section->appendAtom(atom);
- }
-
- const AbsoluteAtom *absoluteAtom = cast<AbsoluteAtom>(atom);
- // Absolute atoms are not part of any section, they are global for the whole
- // link
- _absoluteAtoms.push_back(
- new (_allocator) AtomLayout(absoluteAtom, 0, absoluteAtom->value()));
- return _absoluteAtoms.back();
-}
-
-/// Output sections with the same name into a OutputSection
-template <class ELFT> void TargetLayout<ELFT>::createOutputSections() {
- OutputSection<ELFT> *outputSection;
-
- for (auto &si : _sections) {
- Section<ELFT> *section = dyn_cast<Section<ELFT>>(si);
- if (!section)
- continue;
- const std::pair<StringRef, OutputSection<ELFT> *> currentOutputSection(
- section->outputSectionName(), nullptr);
- std::pair<typename OutputSectionMapT::iterator, bool> outputSectionInsert(
- _outputSectionMap.insert(currentOutputSection));
- if (!outputSectionInsert.second) {
- outputSection = outputSectionInsert.first->second;
- } else {
- outputSection = new (_allocator.Allocate<OutputSection<ELFT>>())
- OutputSection<ELFT>(section->outputSectionName());
- _outputSections.push_back(outputSection);
- outputSectionInsert.first->second = outputSection;
- }
- outputSection->appendSection(section);
- }
-}
-
-template <class ELFT>
-std::vector<typename TargetLayout<ELFT>::SegmentKey>
-TargetLayout<ELFT>::getSegmentsForSection(const OutputSection<ELFT> *os,
- const Section<ELFT> *sec) const {
- std::vector<SegmentKey> segKeys;
- auto phdrs = _linkerScriptSema.getPHDRsForOutputSection(os->name());
- if (!phdrs.empty()) {
- if (phdrs.size() == 1 && phdrs[0]->isNone()) {
- segKeys.emplace_back("NONE", llvm::ELF::PT_NULL, 0, false);
- return segKeys;
- }
-
- for (auto phdr : phdrs) {
- segKeys.emplace_back(phdr->name(), phdr->type(), phdr->flags(), true);
- }
- return segKeys;
- }
-
- uint64_t flags = getLookupSectionFlags(os);
- int64_t segmentType = getSegmentType(sec);
- StringRef segmentName = sec->segmentKindToStr();
-
- // We need a separate segment for sections that don't have
- // the segment type to be PT_LOAD
- if (segmentType != llvm::ELF::PT_LOAD)
- segKeys.emplace_back(segmentName, segmentType, flags, false);
-
- if (segmentType == llvm::ELF::PT_NULL)
- return segKeys;
-
- // If the output magic is set to OutputMagic::NMAGIC or
- // OutputMagic::OMAGIC, Place the data alongside text in one single
- // segment
- ELFLinkingContext::OutputMagic outputMagic = _ctx.getOutputMagic();
- if (outputMagic == ELFLinkingContext::OutputMagic::NMAGIC ||
- outputMagic == ELFLinkingContext::OutputMagic::OMAGIC)
- flags =
- llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
-
- segKeys.emplace_back("LOAD", llvm::ELF::PT_LOAD, flags, false);
- return segKeys;
-}
-
-template <class ELFT>
-uint64_t
-TargetLayout<ELFT>::getLookupSectionFlags(const OutputSection<ELFT> *os) const {
- uint64_t flags = os->flags();
- if (!(flags & llvm::ELF::SHF_WRITE) && _ctx.mergeRODataToTextSegment())
- flags &= ~llvm::ELF::SHF_EXECINSTR;
-
- // Merge string sections into Data segment itself
- flags &= ~(llvm::ELF::SHF_STRINGS | llvm::ELF::SHF_MERGE);
-
- // Merge the TLS section into the DATA segment itself
- flags &= ~(llvm::ELF::SHF_TLS);
- return flags;
-}
-
-template <class ELFT> void TargetLayout<ELFT>::assignSectionsToSegments() {
- ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
- // sort the sections by their order as defined by the layout
- sortInputSections();
-
- // Create output sections.
- createOutputSections();
-
- // Finalize output section layout.
- finalizeOutputSectionLayout();
-
- // Set the ordinal after sorting the sections
- int ordinal = 1;
- for (auto osi : _outputSections) {
- osi->setOrdinal(ordinal);
- for (auto ai : osi->sections()) {
- ai->setOrdinal(ordinal);
- }
- ++ordinal;
- }
- for (auto osi : _outputSections) {
- for (auto section : osi->sections()) {
- if (!hasOutputSegment(section))
- continue;
-
- osi->setLoadableSection(section->isLoadableSection());
- osi->setHasSegment();
-
- auto segKeys = getSegmentsForSection(osi, section);
- assert(!segKeys.empty() && "Must always be at least one segment");
- section->setSegmentType(segKeys[0]._type);
-
- for (auto key : segKeys) {
- // Try to find non-load (real) segment type if possible
- if (key._type != llvm::ELF::PT_LOAD)
- section->setSegmentType(key._type);
-
- const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key,
- nullptr);
- std::pair<typename SegmentMapT::iterator, bool> segmentInsert(
- _segmentMap.insert(currentSegment));
- Segment<ELFT> *segment;
- if (!segmentInsert.second) {
- segment = segmentInsert.first->second;
- } else {
- segment = new (_allocator) Segment<ELFT>(_ctx, key._name, key._type);
- if (key._segmentFlags)
- segment->setSegmentFlags(key._flags);
- segmentInsert.first->second = segment;
- _segments.push_back(segment);
- }
- if (key._type == llvm::ELF::PT_LOAD) {
- // Insert chunks with linker script expressions that occur at this
- // point, just before appending a new input section
- addExtraChunksToSegment(segment, section->archivePath(),
- section->memberPath(),
- section->inputSectionName());
- }
- segment->append(section);
- }
- }
- }
-
- // Default values if no linker script is available
- bool hasProgramSegment = _ctx.isDynamic() && !_ctx.isDynamicLibrary();
- bool hasElfHeader = true;
- bool hasProgramHeader = true;
- uint64_t segmentFlags = 0;
-
- // Check if linker script has PHDRS and program segment defined
- if (_linkerScriptSema.hasPHDRs()) {
- if (auto p = _linkerScriptSema.getProgramPHDR()) {
- hasProgramSegment = true;
- hasElfHeader = p->hasFileHdr();
- hasProgramHeader = p->hasPHDRs();
- segmentFlags = p->flags();
- } else {
- hasProgramSegment = false;
- hasElfHeader = false;
- hasProgramHeader = false;
- }
- }
-
- if (hasProgramSegment) {
- Segment<ELFT> *segment = new (_allocator) ProgramHeaderSegment<ELFT>(_ctx);
- _segments.push_back(segment);
- if (segmentFlags)
- segment->setSegmentFlags(segmentFlags);
- if (hasElfHeader)
- segment->append(_elfHeader);
- if (hasProgramHeader)
- segment->append(_programHeader);
- }
-}
-
-template <class ELFT> void TargetLayout<ELFT>::sortSegments() {
- std::sort(_segments.begin(), _segments.end(), Segment<ELFT>::compareSegments);
-}
-
-template <class ELFT> void TargetLayout<ELFT>::assignVirtualAddress() {
- if (_segments.empty())
- return;
-
- sortSegments();
-
- uint64_t baseAddress = _ctx.getBaseAddress();
-
- // HACK: This is a super dirty hack. The elf header and program header are
- // not part of a section, but we need them to be loaded at the base address
- // so that AT_PHDR is set correctly by the loader and so they are accessible
- // at runtime. To do this we simply prepend them to the first loadable Segment
- // and let the layout logic take care of it.
- Segment<ELFT> *firstLoadSegment = nullptr;
- for (auto si : _segments) {
- if (si->segmentType() == llvm::ELF::PT_LOAD) {
- firstLoadSegment = si;
- si->firstSection()->setAlign(si->alignment());
- break;
- }
- }
- assert(firstLoadSegment != nullptr && "No loadable segment!");
- firstLoadSegment->prepend(_programHeader);
- firstLoadSegment->prepend(_elfHeader);
- bool newSegmentHeaderAdded = true;
- bool virtualAddressAssigned = false;
- bool fileOffsetAssigned = false;
- while (true) {
- for (auto si : _segments) {
- si->finalize();
- // Don't add PT_NULL segments into the program header
- if (si->segmentType() != llvm::ELF::PT_NULL)
- newSegmentHeaderAdded = _programHeader->addSegment(si);
- }
- if (!newSegmentHeaderAdded && virtualAddressAssigned)
- break;
- uint64_t address = baseAddress;
- // start assigning virtual addresses
- for (auto &si : _segments) {
- if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
- (si->segmentType() != llvm::ELF::PT_NULL))
- continue;
-
- if (si->segmentType() == llvm::ELF::PT_NULL) {
- si->assignVirtualAddress(0 /*non loadable*/);
- } else {
- if (virtualAddressAssigned && (address != baseAddress) &&
- (address == si->virtualAddr()))
- break;
- si->assignVirtualAddress(address);
- }
- address = si->virtualAddr() + si->memSize();
- }
- uint64_t baseFileOffset = 0;
- uint64_t fileoffset = baseFileOffset;
- for (auto &si : _segments) {
- if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
- (si->segmentType() != llvm::ELF::PT_NULL))
- continue;
- if (fileOffsetAssigned && (fileoffset != baseFileOffset) &&
- (fileoffset == si->fileOffset()))
- break;
- si->assignFileOffsets(fileoffset);
- fileoffset = si->fileOffset() + si->fileSize();
- }
- virtualAddressAssigned = true;
- fileOffsetAssigned = true;
- _programHeader->resetProgramHeaders();
- }
- Section<ELFT> *section;
- // Fix the offsets of all the atoms within a section
- for (auto &si : _sections) {
- section = dyn_cast<Section<ELFT>>(si);
- if (section && TargetLayout<ELFT>::hasOutputSegment(section))
- section->assignFileOffsets(section->fileOffset());
- }
- // Set the size of the merged Sections
- for (auto osi : _outputSections) {
- uint64_t sectionfileoffset = 0;
- uint64_t startFileOffset = 0;
- uint64_t sectionsize = 0;
- bool isFirstSection = true;
- for (auto si : osi->sections()) {
- if (isFirstSection) {
- startFileOffset = si->fileOffset();
- isFirstSection = false;
- }
- sectionfileoffset = si->fileOffset();
- sectionsize = si->fileSize();
- }
- sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
- osi->setFileOffset(startFileOffset);
- osi->setSize(sectionsize);
- }
- // Set the virtual addr of the merged Sections
- for (auto osi : _outputSections) {
- uint64_t sectionstartaddr = 0;
- uint64_t startaddr = 0;
- uint64_t sectionsize = 0;
- bool isFirstSection = true;
- for (auto si : osi->sections()) {
- if (isFirstSection) {
- startaddr = si->virtualAddr();
- isFirstSection = false;
- }
- sectionstartaddr = si->virtualAddr();
- sectionsize = si->memSize();
- }
- sectionsize = (sectionstartaddr - startaddr) + sectionsize;
- osi->setMemSize(sectionsize);
- osi->setAddr(startaddr);
- }
-}
-
-template <class ELFT>
-void TargetLayout<ELFT>::assignFileOffsetsForMiscSections() {
- uint64_t fileoffset = 0;
- uint64_t size = 0;
- for (auto si : _segments) {
- // Don't calculate offsets from non loadable segments
- if ((si->segmentType() != llvm::ELF::PT_LOAD) &&
- (si->segmentType() != llvm::ELF::PT_NULL))
- continue;
- fileoffset = si->fileOffset();
- size = si->fileSize();
- }
- fileoffset = fileoffset + size;
- Section<ELFT> *section;
- for (auto si : _sections) {
- section = dyn_cast<Section<ELFT>>(si);
- if (section && TargetLayout<ELFT>::hasOutputSegment(section))
- continue;
- fileoffset = llvm::RoundUpToAlignment(fileoffset, si->alignment());
- si->setFileOffset(fileoffset);
- si->setVirtualAddr(0);
- fileoffset += si->fileSize();
- }
-}
-
-template <class ELFT> void TargetLayout<ELFT>::sortInputSections() {
- // First, sort according to default layout's order
- std::stable_sort(
- _sections.begin(), _sections.end(),
- [](Chunk<ELFT> *A, Chunk<ELFT> *B) { return A->order() < B->order(); });
-
- if (!_linkerScriptSema.hasLayoutCommands())
- return;
-
- // Sort the sections by their order as defined by the linker script
- std::stable_sort(
- this->_sections.begin(), this->_sections.end(),
- [this](Chunk<ELFT> *A, Chunk<ELFT> *B) {
- auto *a = dyn_cast<Section<ELFT>>(A);
- auto *b = dyn_cast<Section<ELFT>>(B);
-
- if (a == nullptr)
- return false;
- if (b == nullptr)
- return true;
-
- return _linkerScriptSema.less(
- {a->archivePath(), a->memberPath(), a->inputSectionName()},
- {b->archivePath(), b->memberPath(), b->inputSectionName()});
- });
- // Now try to arrange sections with no mapping rules to sections with
- // similar content
- auto p = this->_sections.begin();
- // Find first section that has no assigned rule id
- while (p != this->_sections.end()) {
- auto *sect = dyn_cast<AtomSection<ELFT>>(*p);
- if (!sect)
- break;
-
- if (!_linkerScriptSema.hasMapping({sect->archivePath(), sect->memberPath(),
- sect->inputSectionName()}))
- break;
-
- ++p;
- }
- // For all sections that have no assigned rule id, try to move them near a
- // section with similar contents
- if (p != this->_sections.begin()) {
- for (; p != this->_sections.end(); ++p) {
- auto q = p;
- --q;
- while (q != this->_sections.begin() &&
- (*q)->getContentType() != (*p)->getContentType())
- --q;
- if ((*q)->getContentType() != (*p)->getContentType())
- continue;
- ++q;
- for (auto i = p; i != q;) {
- auto next = i--;
- std::iter_swap(i, next);
- }
- }
- }
-}
-
-template <class ELFT>
-const AtomLayout *
-TargetLayout<ELFT>::findAtomLayoutByName(StringRef name) const {
- for (auto sec : _sections)
- if (auto section = dyn_cast<Section<ELFT>>(sec))
- if (auto *al = section->findAtomLayoutByName(name))
- return al;
- return nullptr;
-}
-
-template <class ELFT>
-void TargetLayout<ELFT>::addExtraChunksToSegment(Segment<ELFT> *segment,
- StringRef archivePath,
- StringRef memberPath,
- StringRef sectionName) {
- if (!_linkerScriptSema.hasLayoutCommands())
- return;
- std::vector<const script::SymbolAssignment *> exprs =
- _linkerScriptSema.getExprs({archivePath, memberPath, sectionName});
- for (auto expr : exprs) {
- auto expChunk =
- new (this->_allocator) ExpressionChunk<ELFT>(this->_ctx, expr);
- segment->append(expChunk);
- }
-}
-
-template <class ELFT>
-RelocationTable<ELFT> *TargetLayout<ELFT>::getDynamicRelocationTable() {
- if (!_dynamicRelocationTable) {
- _dynamicRelocationTable = createRelocationTable(
- _ctx.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn",
- ORDER_DYNAMIC_RELOCS);
- addSection(_dynamicRelocationTable.get());
- }
- return _dynamicRelocationTable.get();
-}
-
-template <class ELFT>
-RelocationTable<ELFT> *TargetLayout<ELFT>::getPLTRelocationTable() {
- if (!_pltRelocationTable) {
- _pltRelocationTable = createRelocationTable(
- _ctx.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt",
- ORDER_DYNAMIC_PLT_RELOCS);
- addSection(_pltRelocationTable.get());
- }
- return _pltRelocationTable.get();
-}
-
-template <class ELFT> uint64_t TargetLayout<ELFT>::getTLSSize() const {
- for (const auto &phdr : *_programHeader)
- if (phdr->p_type == llvm::ELF::PT_TLS)
- return phdr->p_memsz;
- return 0;
-}
-
-template class TargetLayout<ELF32LE>;
-template class TargetLayout<ELF32BE>;
-template class TargetLayout<ELF64LE>;
-template class TargetLayout<ELF64BE>;
-
-} // end namespace elf
-} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/TargetLayout.h b/lib/ReaderWriter/ELF/TargetLayout.h
deleted file mode 100644
index 52512f8e279e..000000000000
--- a/lib/ReaderWriter/ELF/TargetLayout.h
+++ /dev/null
@@ -1,327 +0,0 @@
-//===- lib/ReaderWriter/ELF/TargetLayout.h --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_DEFAULT_LAYOUT_H
-#define LLD_READER_WRITER_ELF_DEFAULT_LAYOUT_H
-
-#include "Atoms.h"
-#include "HeaderChunks.h"
-#include "SectionChunks.h"
-#include "SegmentChunks.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include <unordered_map>
-
-namespace lld {
-namespace elf {
-
-/// \brief The TargetLayout class is used by the Writer to arrange
-/// sections and segments in the order determined by the target ELF
-/// format. The writer creates a single instance of the TargetLayout
-/// class
-template <class ELFT> class TargetLayout {
-public:
- typedef uint32_t SectionOrder;
- typedef uint32_t SegmentType;
-
- // The order in which the sections appear in the output file
- // If its determined, that the layout needs to change
- // just changing the order of enumerations would essentially
- // change the layout in the output file
- // Change the enumerations so that Target can override and stick
- // a section anywhere it wants to
- enum DefaultSectionOrder {
- ORDER_NOT_DEFINED = 0,
- ORDER_INTERP = 10,
- ORDER_RO_NOTE = 15,
- ORDER_HASH = 30,
- ORDER_DYNAMIC_SYMBOLS = 40,
- ORDER_DYNAMIC_STRINGS = 50,
- ORDER_DYNAMIC_RELOCS = 52,
- ORDER_DYNAMIC_PLT_RELOCS = 54,
- ORDER_INIT = 60,
- ORDER_PLT = 70,
- ORDER_TEXT = 80,
- ORDER_FINI = 90,
- ORDER_REL = 95,
- ORDER_RODATA = 100,
- ORDER_EH_FRAME = 110,
- ORDER_EH_FRAMEHDR = 120,
- ORDER_TDATA = 124,
- ORDER_TBSS = 128,
- ORDER_CTORS = 130,
- ORDER_DTORS = 140,
- ORDER_INIT_ARRAY = 150,
- ORDER_FINI_ARRAY = 160,
- ORDER_DYNAMIC = 170,
- ORDER_GOT = 180,
- ORDER_GOT_PLT = 190,
- ORDER_DATA = 200,
- ORDER_RW_NOTE = 205,
- ORDER_BSS = 210,
- ORDER_NOALLOC = 215,
- ORDER_OTHER = 220,
- ORDER_SECTION_STRINGS = 230,
- ORDER_SYMBOL_TABLE = 240,
- ORDER_STRING_TABLE = 250,
- ORDER_SECTION_HEADERS = 260
- };
-
-public:
-
- // The Key used for creating Sections
- // The sections are created using
- // SectionName, contentPermissions
- struct SectionKey {
- SectionKey(StringRef name, DefinedAtom::ContentPermissions perm,
- StringRef path)
- : _name(name), _perm(perm), _path(path) {}
-
- // Data members
- StringRef _name;
- DefinedAtom::ContentPermissions _perm;
- StringRef _path;
- };
-
- struct SectionKeyHash {
- int64_t operator()(const SectionKey &k) const {
- return llvm::hash_combine(k._name, k._perm, k._path);
- }
- };
-
- struct SectionKeyEq {
- bool operator()(const SectionKey &lhs, const SectionKey &rhs) const {
- return ((lhs._name == rhs._name) && (lhs._perm == rhs._perm) &&
- (lhs._path == rhs._path));
- }
- };
-
- typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
- typedef typename std::vector<Segment<ELFT> *>::iterator SegmentIter;
-
- // Properties used during segment creation
- struct SegmentKey {
- SegmentKey(StringRef name, int64_t type, uint64_t flags, bool segFlags)
- : _name(name), _type(type), _flags(flags),
- _segmentFlags(segFlags && flags != 0) {}
- StringRef _name = "";
- int64_t _type = 0;
- uint64_t _flags = 0;
- bool _segmentFlags = false;
- };
-
- struct SegmentKeyHash {
- int64_t operator()(const SegmentKey &k) const {
- return llvm::hash_combine(k._name, k._type, k._flags);
- }
- };
-
- struct SegmentKeyEq {
- bool operator()(const SegmentKey &lhs, const SegmentKey &rhs) const {
- return ((lhs._name == rhs._name) && (lhs._type == rhs._type) &&
- (lhs._flags == rhs._flags));
- }
- };
-
- // Output Sections contain the map of Section names to a vector of sections,
- // that have been merged to form a single section
- typedef llvm::StringMap<OutputSection<ELFT> *> OutputSectionMapT;
- typedef
- typename std::vector<OutputSection<ELFT> *>::iterator OutputSectionIter;
-
- typedef std::unordered_map<SectionKey, AtomSection<ELFT> *, SectionKeyHash,
- SectionKeyEq> SectionMapT;
- typedef std::unordered_map<SegmentKey, Segment<ELFT> *, SegmentKeyHash,
- SegmentKeyEq> SegmentMapT;
-
- typedef typename std::vector<AtomLayout *>::iterator AbsoluteAtomIterT;
-
- typedef llvm::DenseSet<const Atom *> AtomSetT;
-
- TargetLayout(ELFLinkingContext &ctx)
- : _ctx(ctx), _linkerScriptSema(ctx.linkerScriptSema()) {}
-
- virtual ~TargetLayout() = default;
-
- /// \brief Return the section order for a input section
- virtual SectionOrder getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPermissions);
-
- /// \brief Return the name of the input section by decoding the input
- /// sectionChoice.
- virtual StringRef getInputSectionName(const DefinedAtom *da) const;
-
- /// \brief Return the name of the output section from the input section.
- virtual StringRef getOutputSectionName(StringRef archivePath,
- StringRef memberPath,
- StringRef inputSectionName) const;
-
- /// \brief Gets or creates a section.
- AtomSection<ELFT> *
- getSection(StringRef name, int32_t contentType,
- DefinedAtom::ContentPermissions contentPermissions,
- const DefinedAtom *da);
-
- /// \brief Gets the segment for a output section
- virtual SegmentType getSegmentType(const Section<ELFT> *section) const;
-
- /// \brief Returns true/false depending on whether the section has a Output
- // segment or not
- static bool hasOutputSegment(Section<ELFT> *section);
-
- /// \brief Append the Atom to the layout and create appropriate sections.
- /// \returns A reference to the atom layout or an error. The atom layout will
- /// be updated as linking progresses.
- virtual ErrorOr<const AtomLayout *> addAtom(const Atom *atom);
-
- /// \brief Find an output Section given a section name.
- OutputSection<ELFT> *findOutputSection(StringRef name) {
- auto iter = _outputSectionMap.find(name);
- if (iter == _outputSectionMap.end())
- return nullptr;
- return iter->second;
- }
-
- /// \brief find a absolute atom given a name
- AtomLayout *findAbsoluteAtom(StringRef name) {
- auto iter = std::find_if(
- _absoluteAtoms.begin(), _absoluteAtoms.end(),
- [=](const AtomLayout *a) { return a->_atom->name() == name; });
- if (iter == _absoluteAtoms.end())
- return nullptr;
- return *iter;
- }
-
- // Output sections with the same name into a OutputSection
- void createOutputSections();
-
- // Query for segments based on output and input sections
- std::vector<SegmentKey> getSegmentsForSection(const OutputSection<ELFT> *os,
- const Section<ELFT> *sec) const;
-
- /// \brief Sort the sections by their order as defined by the layout,
- /// preparing all sections to be assigned to a segment.
- virtual void sortInputSections();
-
- /// \brief Add extra chunks to a segment just before including the input
- /// section given by <archivePath, memberPath, sectionName>. This
- /// is used to add linker script expressions before each section.
- virtual void addExtraChunksToSegment(Segment<ELFT> *segment,
- StringRef archivePath,
- StringRef memberPath,
- StringRef sectionName);
-
- /// \brief associates a section to a segment
- virtual void assignSectionsToSegments();
-
- /// \brief associates a virtual address to the segment, section, and the atom
- virtual void assignVirtualAddress();
-
- void assignFileOffsetsForMiscSections();
-
- range<AbsoluteAtomIterT> absoluteAtoms() { return _absoluteAtoms; }
-
- void addSection(Chunk<ELFT> *c) { _sections.push_back(c); }
-
- void finalize() {
- ScopedTask task(getDefaultDomain(), "Finalize layout");
- for (auto &si : _sections)
- si->finalize();
- }
-
- void doPreFlight() {
- for (auto &si : _sections)
- si->doPreFlight();
- }
-
- /// \brief find the Atom in the current layout
- virtual const AtomLayout *findAtomLayoutByName(StringRef name) const;
-
- void setHeader(ELFHeader<ELFT> *elfHeader) { _elfHeader = elfHeader; }
-
- void setProgramHeader(ProgramHeader<ELFT> *p) {
- _programHeader = p;
- }
-
- range<OutputSectionIter> outputSections() { return _outputSections; }
-
- range<ChunkIter> sections() { return _sections; }
-
- range<SegmentIter> segments() { return _segments; }
-
- ELFHeader<ELFT> *getHeader() { return _elfHeader; }
-
- bool hasDynamicRelocationTable() const { return !!_dynamicRelocationTable; }
-
- bool hasPLTRelocationTable() const { return !!_pltRelocationTable; }
-
- /// \brief Get or create the dynamic relocation table. All relocations in this
- /// table are processed at startup.
- RelocationTable<ELFT> *getDynamicRelocationTable();
-
- /// \brief Get or create the PLT relocation table. Referenced by DT_JMPREL.
- RelocationTable<ELFT> *getPLTRelocationTable();
-
- uint64_t getTLSSize() const;
-
- bool isReferencedByDefinedAtom(const Atom *a) const {
- return _referencedDynAtoms.count(a);
- }
-
- bool isCopied(const SharedLibraryAtom *sla) const {
- return _copiedDynSymNames.count(sla->name());
- }
-
-protected:
- /// \brief TargetLayouts may use these functions to reorder the input sections
- /// in a order defined by their ABI.
- virtual void finalizeOutputSectionLayout() {}
-
- /// \brief Allocate a new section.
- virtual AtomSection<ELFT> *createSection(
- StringRef name, int32_t contentType,
- DefinedAtom::ContentPermissions contentPermissions,
- SectionOrder sectionOrder);
-
- /// \brief Create a new relocation table.
- virtual unique_bump_ptr<RelocationTable<ELFT>>
- createRelocationTable(StringRef name, int32_t order) {
- return unique_bump_ptr<RelocationTable<ELFT>>(
- new (_allocator) RelocationTable<ELFT>(_ctx, name, order));
- }
-
- virtual uint64_t getLookupSectionFlags(const OutputSection<ELFT> *os) const;
-
- /// \brief Sort segements stored in the _segments
- virtual void sortSegments();
-
-protected:
- llvm::BumpPtrAllocator _allocator;
- SectionMapT _sectionMap;
- OutputSectionMapT _outputSectionMap;
- SegmentMapT _segmentMap;
- std::vector<Chunk<ELFT> *> _sections;
- std::vector<Segment<ELFT> *> _segments;
- std::vector<OutputSection<ELFT> *> _outputSections;
- ELFHeader<ELFT> *_elfHeader;
- ProgramHeader<ELFT> *_programHeader;
- unique_bump_ptr<RelocationTable<ELFT>> _dynamicRelocationTable;
- unique_bump_ptr<RelocationTable<ELFT>> _pltRelocationTable;
- std::vector<AtomLayout *> _absoluteAtoms;
- AtomSetT _referencedDynAtoms;
- llvm::StringSet<> _copiedDynSymNames;
- ELFLinkingContext &_ctx;
- script::Sema &_linkerScriptSema;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Writer.cpp b/lib/ReaderWriter/ELF/Writer.cpp
deleted file mode 100644
index 1c5d9766e9c5..000000000000
--- a/lib/ReaderWriter/ELF/Writer.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Writer.h"
-#include "DynamicLibraryWriter.h"
-#include "ExecutableWriter.h"
-
-using namespace llvm;
-using namespace llvm::object;
-
-namespace lld {
-
-std::unique_ptr<Writer> createWriterELF(const ELFLinkingContext &ctx) {
- return ctx.getTargetHandler().getWriter();
-}
-
-} // namespace lld
diff --git a/lib/ReaderWriter/ELF/Writer.h b/lib/ReaderWriter/ELF/Writer.h
deleted file mode 100644
index 8b3e8f90638a..000000000000
--- a/lib/ReaderWriter/ELF/Writer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- lib/ReaderWriter/ELF/Writer.h --------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_WRITER_H
-#define LLD_READER_WRITER_ELF_WRITER_H
-
-#include "lld/Core/File.h"
-#include "lld/Core/Writer.h"
-
-namespace lld {
-namespace elf {
-/// \brief The Writer class is a base class for the linker to write
-/// various kinds of ELF files.
-class ELFWriter : public Writer {
-public:
- /// \brief builds the chunks that needs to be written to the output
- /// ELF file
- virtual void buildChunks(const File &file) = 0;
-
- /// \brief Writes the chunks into the output file specified by path
- std::error_code writeFile(const File &file, StringRef path) override = 0;
-
- /// \brief Get the virtual address of \p atom after layout.
- virtual uint64_t addressOfAtom(const Atom *atom) = 0;
-};
-} // end namespace elf
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_ELF_WRITER_H
diff --git a/lib/ReaderWriter/ELF/X86/CMakeLists.txt b/lib/ReaderWriter/ELF/X86/CMakeLists.txt
deleted file mode 100644
index 5e3fe64dc15d..000000000000
--- a/lib/ReaderWriter/ELF/X86/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-add_lld_library(lldX86ELFTarget
- X86LinkingContext.cpp
- X86TargetHandler.cpp
- X86RelocationHandler.cpp
- LINK_LIBS
- lldELF
- lldReaderWriter
- lldCore
- LLVMObject
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h
deleted file mode 100644
index dd2184d7201e..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h -----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef X86_X86_DYNAMIC_LIBRARY_WRITER_H
-#define X86_X86_DYNAMIC_LIBRARY_WRITER_H
-
-#include "DynamicLibraryWriter.h"
-#include "X86LinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-class X86DynamicLibraryWriter : public DynamicLibraryWriter<ELF32LE> {
-public:
- X86DynamicLibraryWriter(X86LinkingContext &ctx,
- TargetLayout<ELF32LE> &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-};
-
-X86DynamicLibraryWriter::X86DynamicLibraryWriter(X86LinkingContext &ctx,
- TargetLayout<ELF32LE> &layout)
- : DynamicLibraryWriter(ctx, layout) {}
-
-void X86DynamicLibraryWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter::createImplicitFiles(result);
- auto gotFile = llvm::make_unique<SimpleFile>("GOTFile");
- gotFile->addAtom(*new (gotFile->allocator()) GlobalOffsetTableAtom(*gotFile));
- gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile));
- result.push_back(std::move(gotFile));
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h b/lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h
deleted file mode 100644
index 70aabde3ad2c..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h ---------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef X86_X86_EXECUTABLE_WRITER_H
-#define X86_X86_EXECUTABLE_WRITER_H
-
-#include "ExecutableWriter.h"
-#include "X86LinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-class X86ExecutableWriter : public ExecutableWriter<ELF32LE> {
-public:
- X86ExecutableWriter(X86LinkingContext &ctx, TargetLayout<ELF32LE> &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-};
-
-X86ExecutableWriter::X86ExecutableWriter(X86LinkingContext &ctx,
- TargetLayout<ELF32LE> &layout)
- : ExecutableWriter(ctx, layout) {}
-
-void X86ExecutableWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter::createImplicitFiles(result);
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp b/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp
deleted file mode 100644
index dc45efc390fd..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp ---------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86LinkingContext.h"
-#include "X86TargetHandler.h"
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/ErrorOr.h"
-
-using namespace lld;
-using namespace lld::elf;
-
-std::unique_ptr<ELFLinkingContext>
-elf::createX86LinkingContext(llvm::Triple triple) {
- if (triple.getArch() == llvm::Triple::x86)
- return llvm::make_unique<X86LinkingContext>(triple);
- return nullptr;
-}
-
-X86LinkingContext::X86LinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, llvm::make_unique<X86TargetHandler>(*this)) {}
-
-static const Registry::KindStrings kindStrings[] = {
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-#include "llvm/Support/ELFRelocs/i386.def"
-#undef ELF_RELOC
- LLD_KIND_STRING_END
-};
-
-void X86LinkingContext::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF, Reference::KindArch::x86,
- kindStrings);
-}
diff --git a/lib/ReaderWriter/ELF/X86/X86LinkingContext.h b/lib/ReaderWriter/ELF/X86/X86LinkingContext.h
deleted file mode 100644
index f6ab3e980d7d..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86LinkingContext.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86LinkingContext.h -----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_X86_TARGETINFO_H
-#define LLD_READER_WRITER_ELF_X86_TARGETINFO_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-class X86LinkingContext final : public ELFLinkingContext {
-public:
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
- int getMachineType() const override { return llvm::ELF::EM_386; }
- X86LinkingContext(llvm::Triple);
- void registerRelocationNames(Registry &r) override;
-
- /// \brief X86 has only two relative relocation
- /// a) for supporting IFUNC relocs - R_386_IRELATIVE
- /// b) for supporting relative relocs - R_386_RELATIVE
- bool isRelativeReloc(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::x86);
- switch (r.kindValue()) {
- case llvm::ELF::R_386_IRELATIVE:
- case llvm::ELF::R_386_RELATIVE:
- return true;
- default:
- return false;
- }
- }
-};
-} // end namespace elf
-} // end namespace lld
-#endif
diff --git a/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp b/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp
deleted file mode 100644
index 15774bc33123..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp ------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86LinkingContext.h"
-#include "X86TargetHandler.h"
-#include "llvm/Support/Endian.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::support::endian;
-
-/// \brief R_386_32 - word32: S + A
-static int reloc32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- int32_t result = (uint32_t)(S + A);
- write32le(location, result | read32le(location));
- return 0;
-}
-
-/// \brief R_386_PC32 - word32: S + A - P
-static int relocPC32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (uint32_t)(S + A - P);
- write32le(location, result + read32le(location));
- return 0;
-}
-
-std::error_code X86TargetRelocationHandler::applyRelocation(
- ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
- const Reference &ref) const {
- uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *loc = atomContent + ref.offsetInAtom();
- uint64_t target = writer.addressOfAtom(ref.target());
- uint64_t reloc = atom._virtualAddr + ref.offsetInAtom();
-
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return std::error_code();
- assert(ref.kindArch() == Reference::KindArch::x86);
- switch (ref.kindValue()) {
- case R_386_32:
- reloc32(loc, reloc, target, ref.addend());
- break;
- case R_386_PC32:
- relocPC32(loc, reloc, target, ref.addend());
- break;
- default:
- return make_unhandled_reloc_error();
- }
- return std::error_code();
-}
diff --git a/lib/ReaderWriter/ELF/X86/X86RelocationHandler.h b/lib/ReaderWriter/ELF/X86/X86RelocationHandler.h
deleted file mode 100644
index 1131635c6735..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86RelocationHandler.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86RelocationHandler.h --------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef X86_X86_RELOCATION_HANDLER_H
-#define X86_X86_RELOCATION_HANDLER_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-class X86TargetRelocationHandler final : public TargetRelocationHandler {
-public:
- std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const AtomLayout &,
- const Reference &) const override;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // X86_X86_RELOCATION_HANDLER_H
diff --git a/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp b/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp
deleted file mode 100644
index c01ed7258f1c..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp ----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86TargetHandler.h"
-#include "X86DynamicLibraryWriter.h"
-#include "X86ExecutableWriter.h"
-#include "X86LinkingContext.h"
-#include "X86RelocationHandler.h"
-
-using namespace lld;
-using namespace elf;
-
-using namespace llvm::ELF;
-
-std::unique_ptr<Writer> X86TargetHandler::getWriter() {
- switch (_ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- return llvm::make_unique<X86ExecutableWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<X86DynamicLibraryWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_REL:
- llvm_unreachable("TODO: support -r mode");
- default:
- llvm_unreachable("unsupported output type");
- }
-}
-
-X86TargetHandler::X86TargetHandler(X86LinkingContext &ctx)
- : _ctx(ctx), _targetLayout(new TargetLayout<ELF32LE>(ctx)),
- _relocationHandler(new X86TargetRelocationHandler()) {}
diff --git a/lib/ReaderWriter/ELF/X86/X86TargetHandler.h b/lib/ReaderWriter/ELF/X86/X86TargetHandler.h
deleted file mode 100644
index fecf9abfc678..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86TargetHandler.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86TargetHandler.h ------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_X86_TARGET_HANDLER_H
-#define LLD_READER_WRITER_ELF_X86_TARGET_HANDLER_H
-
-#include "TargetLayout.h"
-#include "ELFReader.h"
-#include "X86RelocationHandler.h"
-
-namespace lld {
-namespace elf {
-
-class X86LinkingContext;
-
-class X86TargetHandler final : public TargetHandler {
-public:
- X86TargetHandler(X86LinkingContext &ctx);
-
- const TargetRelocationHandler &getRelocationHandler() const override {
- return *_relocationHandler;
- }
-
- std::unique_ptr<Reader> getObjReader() override {
- return llvm::make_unique<ELFReader<ELFFile<ELF32LE>>>(_ctx);
- }
-
- std::unique_ptr<Reader> getDSOReader() override {
- return llvm::make_unique<ELFReader<DynamicFile<ELF32LE>>>(_ctx);
- }
-
- std::unique_ptr<Writer> getWriter() override;
-
-protected:
- X86LinkingContext &_ctx;
- std::unique_ptr<TargetLayout<ELF32LE>> _targetLayout;
- std::unique_ptr<X86TargetRelocationHandler> _relocationHandler;
-};
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt b/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
deleted file mode 100644
index 61f4b4b524e8..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-add_lld_library(lldX86_64ELFTarget
- X86_64LinkingContext.cpp
- X86_64TargetHandler.cpp
- X86_64RelocationHandler.cpp
- X86_64RelocationPass.cpp
- X86_64SectionChunks.cpp
- LINK_LIBS
- lldELF
- lldReaderWriter
- lldCore
- LLVMObject
- LLVMSupport
- )
-
-include_directories(.)
-
-add_subdirectory(ExampleSubTarget)
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt
deleted file mode 100644
index 700b2550b119..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-add_lld_library(lldExampleSubTarget
- ExampleLinkingContext.cpp
- ExampleTargetHandler.cpp
- LINK_LIBS
- lldX86_64ELFTarget
- lldELF
- lldReaderWriter
- lldCore
- LLVMObject
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp
deleted file mode 100644
index cb3e819aff6b..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/ExampleTarget/ExampleLinkingContext.cpp ----===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ExampleLinkingContext.h"
-#include "ExampleTargetHandler.h"
-
-using namespace lld;
-using namespace elf;
-
-std::unique_ptr<ELFLinkingContext>
-elf::createExampleLinkingContext(llvm::Triple triple) {
- if (triple.getVendorName() == "example")
- return llvm::make_unique<ExampleLinkingContext>(triple);
- return nullptr;
-}
-
-ExampleLinkingContext::ExampleLinkingContext(llvm::Triple triple)
- : X86_64LinkingContext(triple, std::unique_ptr<TargetHandler>(
- new ExampleTargetHandler(*this))) {
- _outputELFType = llvm::ELF::ET_LOPROC;
-}
-
-StringRef ExampleLinkingContext::entrySymbolName() const {
- return "_start";
-}
-
-void ExampleLinkingContext::addPasses(PassManager &p) {
- ELFLinkingContext::addPasses(p);
-}
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.h b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.h
deleted file mode 100644
index 5bb11cd35b41..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/ExampleTarget/ExampleLinkingContext.h --===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_X86_64_EXAMPLE_TARGET_EXAMPLE_LINKING_CONTEXT
-#define LLD_READER_WRITER_ELF_X86_64_EXAMPLE_TARGET_EXAMPLE_LINKING_CONTEXT
-
-#include "X86_64LinkingContext.h"
-#include "X86_64TargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-class ExampleLinkingContext final : public X86_64LinkingContext {
-public:
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
- ExampleLinkingContext(llvm::Triple triple);
-
- StringRef entrySymbolName() const override;
- void addPasses(PassManager &) override;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp
deleted file mode 100644
index 89ec6671f3a0..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/ExampleTarget/ExampleTargetHandler.cpp -===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ExampleTargetHandler.h"
-#include "X86_64ExecutableWriter.h"
-#include "ExampleLinkingContext.h"
-
-using namespace lld;
-using namespace elf;
-
-ExampleTargetHandler::ExampleTargetHandler(ExampleLinkingContext &c)
- : X86_64TargetHandler(c), _ctx(c) {}
-
-std::unique_ptr<Writer> ExampleTargetHandler::getWriter() {
- return llvm::make_unique<X86_64ExecutableWriter>(_ctx, *_targetLayout);
-}
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h
deleted file mode 100644
index 46eade5864f9..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/ExampleTarget/ExampleTargetHandler.h ---===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_X86_64_EXAMPLE_TARGET_EXAMPLE_TARGET_HANDLER_H
-#define LLD_READER_WRITER_ELF_X86_64_EXAMPLE_TARGET_EXAMPLE_TARGET_HANDLER_H
-
-#include "X86_64TargetHandler.h"
-
-namespace lld {
-namespace elf {
-class ExampleLinkingContext;
-
-class ExampleTargetHandler final : public X86_64TargetHandler {
-public:
- ExampleTargetHandler(ExampleLinkingContext &c);
-
- std::unique_ptr<Writer> getWriter() override;
-
-private:
- ExampleLinkingContext &_ctx;
-};
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/TODO.rst b/lib/ReaderWriter/ELF/X86_64/TODO.rst
deleted file mode 100644
index a2411a00d1ea..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/TODO.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-ELF x86-64
-~~~~~~~~~~
-
-Unimplemented Features
-######################
-
-* Code models other than the small code model
-* TLS strength reduction
-
-Unimplemented Relocations
-#########################
-
-All of these relocations are defined in:
-http://www.x86-64.org/documentation/abi.pdf
-
-Trivial Relocs
-<<<<<<<<<<<<<<
-
-These are very simple relocation calculations to implement.
-See lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
-
-* R_X86_64_8
-* R_X86_64_PC8
-* R_X86_64_SIZE32
-* R_X86_64_SIZE64
-* R_X86_64_GOTPC32 (this relocation requires there to be a __GLOBAL_OFFSET_TABLE__)
-
-Global Offset Table Relocs
-<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-* R_X86_64_GOTOFF32
-* R_X86_64_GOTOFF64
-
-Global Dynamic Thread Local Storage Relocs
-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-These relocations take more effort to implement, but some of them are done.
-Their implementation lives in lib/ReaderWriter/ELF/X86_64/{X86_64RelocationPass.cpp,X86_64RelocationHandler.cpp}.
-
-Documentation on these relocations can be found in:
-http://www.akkadia.org/drepper/tls.pdf
-http://www.fsfla.org/~lxoliva/writeups/TLS/RFC-TLSDESC-x86.txt
-
-* R_X86_64_GOTPC32_TLSDESC
-* R_X86_64_TLSDESC_CALL
-* R_X86_64_TLSDESC
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h
deleted file mode 100644
index f84f85223bfb..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86_64DynamicLibraryWriter.h ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef X86_64_DYNAMIC_LIBRARY_WRITER_H
-#define X86_64_DYNAMIC_LIBRARY_WRITER_H
-
-#include "DynamicLibraryWriter.h"
-#include "X86_64LinkingContext.h"
-#include "X86_64TargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-class X86_64DynamicLibraryWriter : public DynamicLibraryWriter<ELF64LE> {
-public:
- X86_64DynamicLibraryWriter(X86_64LinkingContext &ctx,
- X86_64TargetLayout &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-};
-
-X86_64DynamicLibraryWriter::X86_64DynamicLibraryWriter(
- X86_64LinkingContext &ctx, X86_64TargetLayout &layout)
- : DynamicLibraryWriter(ctx, layout) {}
-
-void X86_64DynamicLibraryWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter::createImplicitFiles(result);
- auto gotFile = llvm::make_unique<SimpleFile>("GOTFile");
- gotFile->addAtom(*new (gotFile->allocator()) GlobalOffsetTableAtom(*gotFile));
- gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile));
- result.push_back(std::move(gotFile));
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h b/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
deleted file mode 100644
index 930a2de2a9e8..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86_64ExecutableWriter.h ------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef X86_64_EXECUTABLE_WRITER_H
-#define X86_64_EXECUTABLE_WRITER_H
-
-#include "ExecutableWriter.h"
-#include "X86_64LinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-class X86_64ExecutableWriter : public ExecutableWriter<ELF64LE> {
-public:
- X86_64ExecutableWriter(X86_64LinkingContext &ctx, X86_64TargetLayout &layout)
- : ExecutableWriter(ctx, layout), _targetLayout(layout) {}
-
-protected:
- // Add any runtime files and their atoms to the output
- void
- createImplicitFiles(std::vector<std::unique_ptr<File>> &result) override {
- ExecutableWriter::createImplicitFiles(result);
- auto gotFile = llvm::make_unique<SimpleFile>("GOTFile");
- gotFile->addAtom(*new (gotFile->allocator())
- GlobalOffsetTableAtom(*gotFile));
- if (this->_ctx.isDynamic())
- gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile));
- result.push_back(std::move(gotFile));
- }
-
- void buildDynamicSymbolTable(const File &file) override {
- for (auto sec : this->_layout.sections()) {
- if (auto section = dyn_cast<AtomSection<ELF64LE>>(sec)) {
- for (const auto &atom : section->atoms()) {
- if (_targetLayout.getGOTSection().hasGlobalGOTEntry(atom->_atom)) {
- this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
- atom->_virtualAddr, atom);
- }
- }
- }
- }
-
- ExecutableWriter<ELF64LE>::buildDynamicSymbolTable(file);
- }
-
- X86_64TargetLayout &_targetLayout;
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp
deleted file mode 100644
index 0dcd6ac6fbed..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86_64LinkingContext.h"
-#include "X86_64RelocationPass.h"
-#include "X86_64TargetHandler.h"
-
-using namespace lld;
-using namespace lld::elf;
-
-X86_64LinkingContext::X86_64LinkingContext(
- llvm::Triple triple, std::unique_ptr<TargetHandler> handler)
- : ELFLinkingContext(triple, std::move(handler)) {}
-
-X86_64LinkingContext::X86_64LinkingContext(llvm::Triple triple)
- : X86_64LinkingContext(triple,
- llvm::make_unique<X86_64TargetHandler>(*this)) {}
-
-void X86_64LinkingContext::addPasses(PassManager &pm) {
- auto pass = createX86_64RelocationPass(*this);
- if (pass)
- pm.add(std::move(pass));
- ELFLinkingContext::addPasses(pm);
-}
-
-std::unique_ptr<ELFLinkingContext>
-elf::createX86_64LinkingContext(llvm::Triple triple) {
- if (triple.getArch() == llvm::Triple::x86_64)
- return llvm::make_unique<X86_64LinkingContext>(triple);
- return nullptr;
-}
-
-static const Registry::KindStrings kindStrings[] = {
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-#include "llvm/Support/ELFRelocs/x86_64.def"
-#undef ELF_RELOC
- LLD_KIND_STRING_ENTRY(LLD_R_X86_64_GOTRELINDEX),
- LLD_KIND_STRING_END
-};
-
-void X86_64LinkingContext::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::x86_64, kindStrings);
-}
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h
deleted file mode 100644
index a5a7b3d21f4e..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h
+++ /dev/null
@@ -1,103 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h -----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_ELF_X86_64_X86_64_LINKING_CONTEXT_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-
-/// \brief x86-64 internal references.
-enum {
- /// \brief The 32 bit index of the relocation in the got this reference refers
- /// to.
- LLD_R_X86_64_GOTRELINDEX = 1024,
-};
-
-class X86_64LinkingContext : public ELFLinkingContext {
-protected:
- X86_64LinkingContext(llvm::Triple, std::unique_ptr<TargetHandler>);
-
-public:
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
- int getMachineType() const override { return llvm::ELF::EM_X86_64; }
- X86_64LinkingContext(llvm::Triple);
-
- void addPasses(PassManager &) override;
- void registerRelocationNames(Registry &r) override;
-
- uint64_t getBaseAddress() const override {
- if (_baseAddress == 0)
- return 0x400000;
- return _baseAddress;
- }
-
- bool isDynamicRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::x86_64);
- switch (r.kindValue()) {
- case llvm::ELF::R_X86_64_RELATIVE:
- case llvm::ELF::R_X86_64_GLOB_DAT:
- case llvm::ELF::R_X86_64_COPY:
- case llvm::ELF::R_X86_64_DTPMOD64:
- case llvm::ELF::R_X86_64_DTPOFF64:
- case llvm::ELF::R_X86_64_TPOFF64:
- return true;
- default:
- return false;
- }
- }
-
- bool isCopyRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::x86_64);
- if (r.kindValue() == llvm::ELF::R_X86_64_COPY)
- return true;
- return false;
- }
-
- bool isPLTRelocation(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::x86_64);
- switch (r.kindValue()) {
- case llvm::ELF::R_X86_64_JUMP_SLOT:
- case llvm::ELF::R_X86_64_IRELATIVE:
- return true;
- default:
- return false;
- }
- }
-
- /// \brief X86_64 has two relative relocations
- /// a) for supporting IFUNC - R_X86_64_IRELATIVE
- /// b) for supporting relative relocs - R_X86_64_RELATIVE
- bool isRelativeReloc(const Reference &r) const override {
- if (r.kindNamespace() != Reference::KindNamespace::ELF)
- return false;
- assert(r.kindArch() == Reference::KindArch::x86_64);
- switch (r.kindValue()) {
- case llvm::ELF::R_X86_64_IRELATIVE:
- case llvm::ELF::R_X86_64_RELATIVE:
- return true;
- default:
- return false;
- }
- }
-};
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
deleted file mode 100644
index d56983d1e382..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp ------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86_64LinkingContext.h"
-#include "X86_64TargetHandler.h"
-#include "llvm/Support/Endian.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::support::endian;
-
-/// \brief R_X86_64_64 - word64: S + A
-static void reloc64(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
- uint64_t result = S + A;
- write64le(location, result | read64le(location));
-}
-
-/// \brief R_X86_64_PC32 - word32: S + A - P
-static void relocPC32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
- uint32_t result = (uint32_t)(S + A - P);
- write32le(location, result + read32le(location));
-}
-
-/// \brief R_X86_64_32 - word32: S + A
-static void reloc32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
- int32_t result = (uint32_t)(S + A);
- write32le(location, result | read32le(location));
- // TODO: Make sure that the result zero extends to the 64bit value.
-}
-
-/// \brief R_X86_64_32S - word32: S + A
-static void reloc32S(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
- int32_t result = (int32_t)(S + A);
- write32le(location, result | read32le(location));
- // TODO: Make sure that the result sign extends to the 64bit value.
-}
-
-/// \brief R_X86_64_16 - word16: S + A
-static void reloc16(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
- uint16_t result = (uint16_t)(S + A);
- write16le(location, result | read16le(location));
- // TODO: Check for overflow.
-}
-
-/// \brief R_X86_64_PC16 - word16: S + A - P
-static void relocPC16(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
- uint16_t result = (uint16_t)(S + A - P);
- write16le(location, result | read16le(location));
- // TODO: Check for overflow.
-}
-
-/// \brief R_X86_64_PC64 - word64: S + A - P
-static void relocPC64(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- int64_t result = (uint64_t)(S + A - P);
- write64le(location, result | read64le(location));
-}
-
-std::error_code X86_64TargetRelocationHandler::applyRelocation(
- ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
- const Reference &ref) const {
- uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *loc = atomContent + ref.offsetInAtom();
- uint64_t target = writer.addressOfAtom(ref.target());
- uint64_t reloc = atom._virtualAddr + ref.offsetInAtom();
-
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return std::error_code();
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- switch (ref.kindValue()) {
- case R_X86_64_NONE:
- break;
- case R_X86_64_64:
- reloc64(loc, reloc, target, ref.addend());
- break;
- case R_X86_64_PC32:
- case R_X86_64_GOTPCREL:
- relocPC32(loc, reloc, target, ref.addend());
- break;
- case R_X86_64_32:
- reloc32(loc, reloc, target, ref.addend());
- break;
- case R_X86_64_32S:
- reloc32S(loc, reloc, target, ref.addend());
- break;
- case R_X86_64_16:
- reloc16(loc, reloc, target, ref.addend());
- break;
- case R_X86_64_PC16:
- relocPC16(loc, reloc, target, ref.addend());
- break;
- case R_X86_64_DTPOFF32:
- case R_X86_64_TPOFF32:
- _tlsSize = _layout.getTLSSize();
- write32le(loc, target - _tlsSize);
- break;
- case R_X86_64_GOTTPOFF:
- relocPC32(loc, reloc, target, ref.addend());
- break;
- case R_X86_64_TLSGD: {
- relocPC32(loc, reloc, target, ref.addend());
- break;
- }
- case R_X86_64_TLSLD: {
- // Rewrite to move %fs:0 into %rax. Technically we should verify that the
- // next relocation is a PC32 to __tls_get_addr...
- static uint8_t instr[] = { 0x66, 0x66, 0x66, 0x64, 0x48, 0x8b, 0x04, 0x25,
- 0x00, 0x00, 0x00, 0x00 };
- std::memcpy(loc - 3, instr, sizeof(instr));
- break;
- }
- case R_X86_64_PC64:
- relocPC64(loc, reloc, target, ref.addend());
- break;
- case LLD_R_X86_64_GOTRELINDEX: {
- const DefinedAtom *target = cast<const DefinedAtom>(ref.target());
- for (const Reference *r : *target) {
- if (r->kindValue() == R_X86_64_JUMP_SLOT) {
- uint32_t index;
- if (!_layout.getPLTRelocationTable()->getRelocationIndex(*r, index))
- llvm_unreachable("Relocation doesn't exist");
- reloc32(loc, 0, index, 0);
- break;
- }
- }
- break;
- }
- // Runtime only relocations. Ignore here.
- case R_X86_64_RELATIVE:
- case R_X86_64_IRELATIVE:
- case R_X86_64_JUMP_SLOT:
- case R_X86_64_GLOB_DAT:
- case R_X86_64_DTPMOD64:
- case R_X86_64_DTPOFF64:
- case R_X86_64_TPOFF64:
- break;
- default:
- return make_unhandled_reloc_error();
- }
-
- return std::error_code();
-}
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h
deleted file mode 100644
index 26382804549b..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h --------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef X86_64_RELOCATION_HANDLER_H
-#define X86_64_RELOCATION_HANDLER_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-
-namespace lld {
-namespace elf {
-class X86_64TargetLayout;
-
-class X86_64TargetRelocationHandler final : public TargetRelocationHandler {
-public:
- X86_64TargetRelocationHandler(X86_64TargetLayout &layout)
- : _tlsSize(0), _layout(layout) {}
-
- std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const AtomLayout &,
- const Reference &) const override;
-
-private:
- // Cached size of the TLS segment.
- mutable uint64_t _tlsSize;
- X86_64TargetLayout &_layout;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif // X86_64_RELOCATION_HANDLER_H
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
deleted file mode 100644
index a2f10dc08a4e..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
+++ /dev/null
@@ -1,513 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Defines the relocation processing pass for x86-64. This includes
-/// GOT and PLT entries, TLS, COPY, and ifunc.
-///
-/// This is based on section 4.4.1 of the AMD64 ABI (no stable URL as of Oct,
-/// 2013).
-///
-/// This also includes aditional behaivor that gnu-ld and gold implement but
-/// which is not specified anywhere.
-///
-//===----------------------------------------------------------------------===//
-
-#include "X86_64RelocationPass.h"
-#include "Atoms.h"
-#include "X86_64LinkingContext.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::ELF;
-
-// .got values
-static const uint8_t x86_64GotAtomContent[8] = {0};
-
-// .plt value (entry 0)
-static const uint8_t x86_64Plt0AtomContent[16] = {
- 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip)
- 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip)
- 0x90, 0x90, 0x90, 0x90 // nopnopnop
-};
-
-// .plt values (other entries)
-static const uint8_t x86_64PltAtomContent[16] = {
- 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *gotatom(%rip)
- 0x68, 0x00, 0x00, 0x00, 0x00, // pushq reloc-index
- 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[-1]
-};
-
-// TLS GD Entry
-static const uint8_t x86_64GotTlsGdAtomContent[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-namespace {
-/// \brief Atoms that are used by X86_64 dynamic linking
-class X86_64GOTAtom : public GOTAtom {
-public:
- X86_64GOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return ArrayRef<uint8_t>(x86_64GotAtomContent, 8);
- }
-};
-
-/// \brief X86_64 GOT TLS GD entry.
-class GOTTLSGdAtom : public X86_64GOTAtom {
-public:
- GOTTLSGdAtom(const File &f, StringRef secName) : X86_64GOTAtom(f, secName) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(x86_64GotTlsGdAtomContent);
- }
-};
-
-class X86_64PLT0Atom : public PLT0Atom {
-public:
- X86_64PLT0Atom(const File &f) : PLT0Atom(f) {}
- ArrayRef<uint8_t> rawContent() const override {
- return ArrayRef<uint8_t>(x86_64Plt0AtomContent, 16);
- }
-};
-
-class X86_64PLTAtom : public PLTAtom {
-public:
- X86_64PLTAtom(const File &f, StringRef secName) : PLTAtom(f, secName) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- return ArrayRef<uint8_t>(x86_64PltAtomContent, 16);
- }
-};
-
-class ELFPassFile : public SimpleFile {
-public:
- ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
- setOrdinal(eti.getNextOrdinalAndIncrement());
- }
-
- llvm::BumpPtrAllocator _alloc;
-};
-
-/// \brief CRTP base for handling relocations.
-template <class Derived> class RelocationPass : public Pass {
- /// \brief Handle a specific reference.
- void handleReference(const DefinedAtom &atom, const Reference &ref) {
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return;
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- switch (ref.kindValue()) {
- case R_X86_64_16:
- case R_X86_64_32:
- case R_X86_64_32S:
- case R_X86_64_64:
- case R_X86_64_PC16:
- case R_X86_64_PC32:
- case R_X86_64_PC64:
- static_cast<Derived *>(this)->handlePlain(ref);
- break;
- case R_X86_64_PLT32:
- static_cast<Derived *>(this)->handlePLT32(ref);
- break;
- case R_X86_64_GOT32:
- case R_X86_64_GOTPC32:
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTOFF64:
- static_cast<Derived *>(this)->handleGOT(ref);
- break;
- case R_X86_64_GOTTPOFF: // GOT Thread Pointer Offset
- static_cast<Derived *>(this)->handleGOTTPOFF(ref);
- break;
- case R_X86_64_TLSGD:
- static_cast<Derived *>(this)->handleTLSGd(ref);
- break;
- }
- }
-
-protected:
- /// \brief get the PLT entry for a given IFUNC Atom.
- ///
- /// If the entry does not exist. Both the GOT and PLT entry is created.
- const PLTAtom *getIFUNCPLTEntry(const DefinedAtom *da) {
- auto plt = _pltMap.find(da);
- if (plt != _pltMap.end())
- return plt->second;
- auto ga = new (_file._alloc) X86_64GOTAtom(_file, ".got.plt");
- ga->addReferenceELF_x86_64(R_X86_64_IRELATIVE, 0, da, 0);
- auto pa = new (_file._alloc) X86_64PLTAtom(_file, ".plt");
- pa->addReferenceELF_x86_64(R_X86_64_PC32, 2, ga, -4);
-#ifndef NDEBUG
- ga->_name = "__got_ifunc_";
- ga->_name += da->name();
- pa->_name = "__plt_ifunc_";
- pa->_name += da->name();
-#endif
- _gotMap[da] = ga;
- _pltMap[da] = pa;
- _gotVector.push_back(ga);
- _pltVector.push_back(pa);
- return pa;
- }
-
- /// \brief Redirect the call to the PLT stub for the target IFUNC.
- ///
- /// This create a PLT and GOT entry for the IFUNC if one does not exist. The
- /// GOT entry and a IRELATIVE relocation to the original target resolver.
- std::error_code handleIFUNC(const Reference &ref) {
- auto target = dyn_cast_or_null<const DefinedAtom>(ref.target());
- if (target && target->contentType() == DefinedAtom::typeResolver)
- const_cast<Reference &>(ref).setTarget(getIFUNCPLTEntry(target));
- return std::error_code();
- }
-
- /// \brief Create a GOT entry for the TP offset of a TLS atom.
- const GOTAtom *getGOTTPOFF(const Atom *atom) {
- auto got = _gotMap.find(atom);
- if (got == _gotMap.end()) {
- auto g = new (_file._alloc) X86_64GOTAtom(_file, ".got");
- g->addReferenceELF_x86_64(R_X86_64_TPOFF64, 0, atom, 0);
-#ifndef NDEBUG
- g->_name = "__got_tls_";
- g->_name += atom->name();
-#endif
- _gotMap[atom] = g;
- _gotVector.push_back(g);
- return g;
- }
- return got->second;
- }
-
- /// \brief Create a TPOFF64 GOT entry.
- std::error_code handleGOTTPOFF(const Reference &ref) {
- if (isa<DefinedAtom>(ref.target())) {
- const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target()));
- }
- return std::error_code();
- }
-
- /// \brief Create a TLS GOT entry with DTPMOD64/DTPOFF64 dynamic relocations.
- void handleTLSGd(const Reference &ref) {
- const_cast<Reference &>(ref).setTarget(getTLSGdGOTEntry(ref.target()));
- }
-
- /// \brief Create a GOT entry containing 0.
- const GOTAtom *getNullGOT() {
- if (!_null) {
- _null = new (_file._alloc) X86_64GOTAtom(_file, ".got.plt");
-#ifndef NDEBUG
- _null->_name = "__got_null";
-#endif
- }
- return _null;
- }
-
- const GOTAtom *getGOT(const DefinedAtom *da) {
- auto got = _gotMap.find(da);
- if (got == _gotMap.end()) {
- auto g = new (_file._alloc) X86_64GOTAtom(_file, ".got");
- g->addReferenceELF_x86_64(R_X86_64_64, 0, da, 0);
-#ifndef NDEBUG
- g->_name = "__got_";
- g->_name += da->name();
-#endif
- _gotMap[da] = g;
- _gotVector.push_back(g);
- return g;
- }
- return got->second;
- }
-
- const GOTAtom *getTLSGdGOTEntry(const Atom *a) {
- auto got = _gotTLSGdMap.find(a);
- if (got != _gotTLSGdMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOTTLSGdAtom(_file, ".got");
- _gotTLSGdMap[a] = ga;
-
- _tlsGotVector.push_back(ga);
- ga->addReferenceELF_x86_64(R_X86_64_DTPMOD64, 0, a, 0);
- ga->addReferenceELF_x86_64(R_X86_64_DTPOFF64, 8, a, 0);
-
- return ga;
- }
-
-public:
- RelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {}
-
- /// \brief Do the pass.
- ///
- /// The goal here is to first process each reference individually. Each call
- /// to handleReference may modify the reference itself and/or create new
- /// atoms which must be stored in one of the maps below.
- ///
- /// After all references are handled, the atoms created during that are all
- /// added to mf.
- std::error_code perform(SimpleFile &mf) override {
- ScopedTask task(getDefaultDomain(), "X86-64 GOT/PLT Pass");
- // Process all references.
- for (const auto &atom : mf.defined())
- for (const auto &ref : *atom)
- handleReference(*atom, *ref);
-
- // Add all created atoms to the link.
- uint64_t ordinal = 0;
- if (_plt0) {
- _plt0->setOrdinal(ordinal++);
- mf.addAtom(*_plt0);
- }
- for (auto &plt : _pltVector) {
- plt->setOrdinal(ordinal++);
- mf.addAtom(*plt);
- }
- if (_null) {
- _null->setOrdinal(ordinal++);
- mf.addAtom(*_null);
- }
- if (_plt0) {
- _got0->setOrdinal(ordinal++);
- _got1->setOrdinal(ordinal++);
- mf.addAtom(*_got0);
- mf.addAtom(*_got1);
- }
- for (auto &got : _gotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
- for (auto &got : _tlsGotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
- for (auto obj : _objectVector) {
- obj->setOrdinal(ordinal++);
- mf.addAtom(*obj);
- }
- return std::error_code();
- }
-
-protected:
- /// \brief Owner of all the Atoms created by this pass.
- ELFPassFile _file;
- const ELFLinkingContext &_ctx;
-
- /// \brief Map Atoms to their GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
-
- /// \brief Map Atoms to their PLT entries.
- llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
-
- /// \brief Map Atoms to TLS GD GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotTLSGdMap;
-
- /// \brief Map Atoms to their Object entries.
- llvm::DenseMap<const Atom *, ObjectAtom *> _objectMap;
-
- /// \brief the list of GOT/PLT atoms
- std::vector<GOTAtom *> _gotVector;
- std::vector<PLTAtom *> _pltVector;
- std::vector<ObjectAtom *> _objectVector;
-
- /// \brief the list of TLS GOT atoms.
- std::vector<GOTAtom *> _tlsGotVector;
-
- /// \brief GOT entry that is always 0. Used for undefined weaks.
- GOTAtom *_null = nullptr;
-
- /// \brief The got and plt entries for .PLT0. This is used to call into the
- /// dynamic linker for symbol resolution.
- /// @{
- PLT0Atom *_plt0 = nullptr;
- GOTAtom *_got0 = nullptr;
- GOTAtom *_got1 = nullptr;
- /// @}
-};
-
-/// This implements the static relocation model. Meaning GOT and PLT entries are
-/// not created for references that can be directly resolved. These are
-/// converted to a direct relocation. For entries that do require a GOT or PLT
-/// entry, that entry is statically bound.
-///
-/// TLS always assumes module 1 and attempts to remove indirection.
-class StaticRelocationPass final
- : public RelocationPass<StaticRelocationPass> {
-public:
- StaticRelocationPass(const elf::X86_64LinkingContext &ctx)
- : RelocationPass(ctx) {}
-
- std::error_code handlePlain(const Reference &ref) { return handleIFUNC(ref); }
-
- std::error_code handlePLT32(const Reference &ref) {
- // __tls_get_addr is handled elsewhere.
- if (ref.target() && ref.target()->name() == "__tls_get_addr") {
- const_cast<Reference &>(ref).setKindValue(R_X86_64_NONE);
- return std::error_code();
- }
- // Static code doesn't need PLTs.
- const_cast<Reference &>(ref).setKindValue(R_X86_64_PC32);
- // Handle IFUNC.
- if (const DefinedAtom *da =
- dyn_cast_or_null<const DefinedAtom>(ref.target()))
- if (da->contentType() == DefinedAtom::typeResolver)
- return handleIFUNC(ref);
- return std::error_code();
- }
-
- std::error_code handleGOT(const Reference &ref) {
- if (isa<UndefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getNullGOT());
- else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getGOT(da));
- return std::error_code();
- }
-};
-
-class DynamicRelocationPass final
- : public RelocationPass<DynamicRelocationPass> {
-public:
- DynamicRelocationPass(const elf::X86_64LinkingContext &ctx)
- : RelocationPass(ctx) {}
-
- const PLT0Atom *getPLT0() {
- if (_plt0)
- return _plt0;
- // Fill in the null entry.
- getNullGOT();
- _plt0 = new (_file._alloc) X86_64PLT0Atom(_file);
- _got0 = new (_file._alloc) X86_64GOTAtom(_file, ".got.plt");
- _got1 = new (_file._alloc) X86_64GOTAtom(_file, ".got.plt");
- _plt0->addReferenceELF_x86_64(R_X86_64_PC32, 2, _got0, -4);
- _plt0->addReferenceELF_x86_64(R_X86_64_PC32, 8, _got1, -4);
-#ifndef NDEBUG
- _got0->_name = "__got0";
- _got1->_name = "__got1";
-#endif
- return _plt0;
- }
-
- const PLTAtom *getPLTEntry(const Atom *a) {
- auto plt = _pltMap.find(a);
- if (plt != _pltMap.end())
- return plt->second;
- auto ga = new (_file._alloc) X86_64GOTAtom(_file, ".got.plt");
- ga->addReferenceELF_x86_64(R_X86_64_JUMP_SLOT, 0, a, 0);
- auto pa = new (_file._alloc) X86_64PLTAtom(_file, ".plt");
- pa->addReferenceELF_x86_64(R_X86_64_PC32, 2, ga, -4);
- pa->addReferenceELF_x86_64(LLD_R_X86_64_GOTRELINDEX, 7, ga, 0);
- pa->addReferenceELF_x86_64(R_X86_64_PC32, 12, getPLT0(), -4);
- // Set the starting address of the got entry to the second instruction in
- // the plt entry.
- ga->addReferenceELF_x86_64(R_X86_64_64, 0, pa, 6);
-#ifndef NDEBUG
- ga->_name = "__got_";
- ga->_name += a->name();
- pa->_name = "__plt_";
- pa->_name += a->name();
-#endif
- _gotMap[a] = ga;
- _pltMap[a] = pa;
- _gotVector.push_back(ga);
- _pltVector.push_back(pa);
- return pa;
- }
-
- const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) {
- auto obj = _objectMap.find(a);
- if (obj != _objectMap.end())
- return obj->second;
-
- auto oa = new (_file._alloc) ObjectAtom(_file);
- // This needs to point to the atom that we just created.
- oa->addReferenceELF_x86_64(R_X86_64_COPY, 0, oa, 0);
-
- oa->_name = a->name();
- oa->_size = a->size();
-
- _objectMap[a] = oa;
- _objectVector.push_back(oa);
- return oa;
- }
-
- std::error_code handlePlain(const Reference &ref) {
- if (!ref.target())
- return std::error_code();
- if (auto sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
- if (sla->type() == SharedLibraryAtom::Type::Data)
- const_cast<Reference &>(ref).setTarget(getObjectEntry(sla));
- else if (sla->type() == SharedLibraryAtom::Type::Code)
- const_cast<Reference &>(ref).setTarget(getPLTEntry(sla));
- } else
- return handleIFUNC(ref);
- return std::error_code();
- }
-
- std::error_code handlePLT32(const Reference &ref) {
- // Turn this into a PC32 to the PLT entry.
- const_cast<Reference &>(ref).setKindValue(R_X86_64_PC32);
- // Handle IFUNC.
- if (const DefinedAtom *da =
- dyn_cast_or_null<const DefinedAtom>(ref.target()))
- if (da->contentType() == DefinedAtom::typeResolver)
- return handleIFUNC(ref);
- // If it is undefined at link time, push the work to the dynamic linker by
- // creating a PLT entry
- if (isa<SharedLibraryAtom>(ref.target()) ||
- isa<UndefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
- return std::error_code();
- }
-
- const GOTAtom *getSharedGOT(const Atom *a) {
- auto got = _gotMap.find(a);
- if (got == _gotMap.end()) {
- auto g = new (_file._alloc) X86_64GOTAtom(_file, ".got");
- g->addReferenceELF_x86_64(R_X86_64_GLOB_DAT, 0, a, 0);
-#ifndef NDEBUG
- g->_name = "__got_";
- g->_name += a->name();
-#endif
- _gotMap[a] = g;
- _gotVector.push_back(g);
- return g;
- }
- return got->second;
- }
-
- std::error_code handleGOT(const Reference &ref) {
- if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getGOT(da));
- // Handle undefined atoms in the same way as shared lib atoms: to be
- // resolved at run time.
- else if (isa<SharedLibraryAtom>(ref.target()) ||
- isa<UndefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getSharedGOT(ref.target()));
- return std::error_code();
- }
-};
-} // end anon namespace
-
-std::unique_ptr<Pass>
-lld::elf::createX86_64RelocationPass(const X86_64LinkingContext &ctx) {
- switch (ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- if (ctx.isDynamic())
- return llvm::make_unique<DynamicRelocationPass>(ctx);
- return llvm::make_unique<StaticRelocationPass>(ctx);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<DynamicRelocationPass>(ctx);
- case llvm::ELF::ET_REL:
- return nullptr;
- default:
- llvm_unreachable("Unhandled output file type");
- }
-}
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.h b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.h
deleted file mode 100644
index 1635b5e5f57b..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.h -----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Declares the relocation processing pass for x86-64. This includes
-/// GOT and PLT entries, TLS, COPY, and ifunc.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_RELOCATION_PASS_H
-#define LLD_READER_WRITER_ELF_X86_64_X86_64_RELOCATION_PASS_H
-
-#include <memory>
-
-namespace lld {
-class Pass;
-namespace elf {
-class X86_64LinkingContext;
-
-/// \brief Create x86-64 relocation pass for the given linking context.
-std::unique_ptr<Pass>
-createX86_64RelocationPass(const X86_64LinkingContext &);
-}
-}
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp
deleted file mode 100644
index 28eb3e4244b6..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp --------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86_64SectionChunks.h"
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-X86_64GOTSection::X86_64GOTSection(const ELFLinkingContext &ctx)
- : AtomSection<ELF64LE>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_,
- TargetLayout<ELF64LE>::ORDER_GOT) {
- this->_alignment = 8;
-}
-
-const AtomLayout *X86_64GOTSection::appendAtom(const Atom *atom) {
- const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
-
- for (const auto &r : *da) {
- if (r->kindNamespace() != Reference::KindNamespace::ELF)
- continue;
- assert(r->kindArch() == Reference::KindArch::x86_64);
- if (r->kindValue() == R_X86_64_TPOFF64)
- _tlsMap[r->target()] = _tlsMap.size();
- }
-
- return AtomSection<ELF64LE>::appendAtom(atom);
-}
-
-} // elf
-} // lld
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h
deleted file mode 100644
index 5208491eee55..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_SECTION_CHUNKS_H
-#define LLD_READER_WRITER_ELF_X86_64_X86_64_SECTION_CHUNKS_H
-
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-class X86_64GOTSection : public AtomSection<ELF64LE> {
-public:
- X86_64GOTSection(const ELFLinkingContext &ctx);
-
- bool hasGlobalGOTEntry(const Atom *a) const {
- return _tlsMap.count(a);
- }
-
- const AtomLayout *appendAtom(const Atom *atom) override;
-
-private:
- /// \brief Map TLS Atoms to their GOT entry index.
- llvm::DenseMap<const Atom *, std::size_t> _tlsMap;
-};
-
-} // elf
-} // lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
deleted file mode 100644
index 599077ac33c5..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Atoms.h"
-#include "X86_64DynamicLibraryWriter.h"
-#include "X86_64ExecutableWriter.h"
-#include "X86_64LinkingContext.h"
-#include "X86_64TargetHandler.h"
-
-using namespace lld;
-using namespace elf;
-
-X86_64TargetHandler::X86_64TargetHandler(X86_64LinkingContext &ctx)
- : _ctx(ctx), _targetLayout(new X86_64TargetLayout(ctx)),
- _relocationHandler(new X86_64TargetRelocationHandler(*_targetLayout)) {}
-
-std::unique_ptr<Writer> X86_64TargetHandler::getWriter() {
- switch (this->_ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- return llvm::make_unique<X86_64ExecutableWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_DYN:
- return llvm::make_unique<X86_64DynamicLibraryWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_REL:
- llvm_unreachable("TODO: support -r mode");
- default:
- llvm_unreachable("unsupported output type");
- }
-}
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
deleted file mode 100644
index 6e3e58f8aed6..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h ------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_TARGET_HANDLER_H
-#define LLD_READER_WRITER_ELF_X86_64_X86_64_TARGET_HANDLER_H
-
-#include "ELFReader.h"
-#include "TargetLayout.h"
-#include "X86_64LinkingContext.h"
-#include "X86_64RelocationHandler.h"
-#include "X86_64SectionChunks.h"
-#include "lld/Core/Simple.h"
-
-namespace lld {
-namespace elf {
-
-
-class X86_64TargetLayout : public TargetLayout<ELF64LE> {
-public:
- X86_64TargetLayout(X86_64LinkingContext &ctx) : TargetLayout(ctx),
- _gotSection(new (this->_allocator) X86_64GOTSection(ctx)) {}
-
- AtomSection<ELF64LE> *
- createSection(StringRef name, int32_t type,
- DefinedAtom::ContentPermissions permissions,
- TargetLayout<ELF64LE>::SectionOrder order) override {
- if (type == DefinedAtom::typeGOT && name == ".got")
- return _gotSection;
- return TargetLayout<ELF64LE>::createSection(name, type, permissions, order);
- }
-
- void finalizeOutputSectionLayout() override {
- sortOutputSectionByPriority<ELF64LE>(".init_array");
- sortOutputSectionByPriority<ELF64LE>(".fini_array");
- }
-
- const X86_64GOTSection &getGOTSection() const { return *_gotSection; }
-
-private:
- uint32_t getPriority(StringRef sectionName) const {
- StringRef priority = sectionName.drop_front().rsplit('.').second;
- uint32_t prio;
- if (priority.getAsInteger(10, prio))
- return std::numeric_limits<uint32_t>::max();
- return prio;
- }
-
- template <typename T> void sortOutputSectionByPriority(StringRef prefix) {
- OutputSection<T> *section = findOutputSection(prefix);
- if (!section)
- return;
- auto sections = section->sections();
- std::sort(sections.begin(), sections.end(),
- [&](Chunk<T> *lhs, Chunk<T> *rhs) {
- Section<T> *lhsSection = dyn_cast<Section<T>>(lhs);
- Section<T> *rhsSection = dyn_cast<Section<T>>(rhs);
- if (!lhsSection || !rhsSection)
- return false;
- StringRef lhsName = lhsSection->inputSectionName();
- StringRef rhsName = rhsSection->inputSectionName();
- if (!lhsName.startswith(prefix) || !rhsName.startswith(prefix))
- return false;
- return getPriority(lhsName) < getPriority(rhsName);
- });
- }
-
-private:
- X86_64GOTSection *_gotSection;
-};
-
-class X86_64TargetHandler : public TargetHandler {
-public:
- X86_64TargetHandler(X86_64LinkingContext &ctx);
-
- const TargetRelocationHandler &getRelocationHandler() const override {
- return *_relocationHandler;
- }
-
- std::unique_ptr<Reader> getObjReader() override {
- return llvm::make_unique<ELFReader<ELFFile<ELF64LE>>>(_ctx);
- }
-
- std::unique_ptr<Reader> getDSOReader() override {
- return llvm::make_unique<ELFReader<DynamicFile<ELF64LE>>>(_ctx);
- }
-
- std::unique_ptr<Writer> getWriter() override;
-
-protected:
- X86_64LinkingContext &_ctx;
- std::unique_ptr<X86_64TargetLayout> _targetLayout;
- std::unique_ptr<X86_64TargetRelocationHandler> _relocationHandler;
-};
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/FileArchive.cpp b/lib/ReaderWriter/FileArchive.cpp
index a09923f57d07..eb7e7fb1837b 100644
--- a/lib/ReaderWriter/FileArchive.cpp
+++ b/lib/ReaderWriter/FileArchive.cpp
@@ -8,27 +8,28 @@
//===----------------------------------------------------------------------===//
#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/File.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Parallel.h"
-#include "lld/Driver/Driver.h"
-#include "llvm/ADT/Hashing.h"
+#include "lld/Core/Reader.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Archive.h"
-#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
#include <memory>
-#include <mutex>
#include <set>
+#include <string>
+#include <system_error>
#include <unordered_map>
+#include <utility>
+#include <vector>
using llvm::object::Archive;
-using llvm::object::ObjectFile;
-using llvm::object::SymbolRef;
-using llvm::object::symbol_iterator;
-using llvm::object::object_error;
namespace lld {
@@ -44,39 +45,23 @@ public:
/// \brief Check if any member of the archive contains an Atom with the
/// specified name and return the File object for that member, or nullptr.
- File *find(StringRef name, bool dataSymbolOnly) override {
+ File *find(StringRef name) override {
auto member = _symbolMemberMap.find(name);
if (member == _symbolMemberMap.end())
return nullptr;
- Archive::child_iterator ci = member->second;
- if (ci->getError())
- return nullptr;
+ Archive::Child c = member->second;
// Don't return a member already returned
- ErrorOr<StringRef> buf = (*ci)->getBuffer();
+ ErrorOr<StringRef> buf = c.getBuffer();
if (!buf)
return nullptr;
const char *memberStart = buf->data();
if (_membersInstantiated.count(memberStart))
return nullptr;
- if (dataSymbolOnly && !isDataSymbol(ci, name))
- return nullptr;
-
_membersInstantiated.insert(memberStart);
- // Check if a file is preloaded.
- {
- std::lock_guard<std::mutex> lock(_mutex);
- auto it = _preloaded.find(memberStart);
- if (it != _preloaded.end()) {
- std::unique_ptr<Future<File *>> &p = it->second;
- Future<File *> *future = p.get();
- return future->get();
- }
- }
-
std::unique_ptr<File> result;
- if (instantiateMember(ci, result))
+ if (instantiateMember(c, result))
return nullptr;
File *file = result.get();
@@ -86,97 +71,68 @@ public:
return file;
}
- // Instantiate a member file containing a given symbol name.
- void preload(TaskGroup &group, StringRef name) override {
- auto member = _symbolMemberMap.find(name);
- if (member == _symbolMemberMap.end())
- return;
- Archive::child_iterator ci = member->second;
- if (ci->getError())
- return;
-
- // Do nothing if a member is already instantiated.
- ErrorOr<StringRef> buf = (*ci)->getBuffer();
- if (!buf)
- return;
- const char *memberStart = buf->data();
- if (_membersInstantiated.count(memberStart))
- return;
-
- std::lock_guard<std::mutex> lock(_mutex);
- if (_preloaded.find(memberStart) != _preloaded.end())
- return;
-
- // Instantiate the member
- auto *future = new Future<File *>();
- _preloaded[memberStart] = std::unique_ptr<Future<File *>>(future);
-
- group.spawn([=] {
- std::unique_ptr<File> result;
- std::error_code ec = instantiateMember(ci, result);
- future->set(ec ? nullptr : result.release());
- });
- }
-
/// \brief parse each member
std::error_code
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
if (std::error_code ec = parse())
return ec;
- for (auto mf = _archive->child_begin(), me = _archive->child_end();
+ llvm::Error err;
+ for (auto mf = _archive->child_begin(err), me = _archive->child_end();
mf != me; ++mf) {
std::unique_ptr<File> file;
- if (std::error_code ec = instantiateMember(mf, file))
+ if (std::error_code ec = instantiateMember(*mf, file)) {
+ // err is Success (or we wouldn't be in the loop body) but we can't
+ // return without testing or consuming it.
+ consumeError(std::move(err));
return ec;
+ }
result.push_back(std::move(file));
}
+ if (err)
+ return errorToErrorCode(std::move(err));
return std::error_code();
}
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _noDefinedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
- /// Returns a set of all defined symbols in the archive.
- std::set<StringRef> getDefinedSymbols() override {
- parse();
- std::set<StringRef> ret;
- for (const auto &e : _symbolMemberMap)
- ret.insert(e.first);
- return ret;
+ void clearAtoms() override {
+ _noDefinedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
}
protected:
std::error_code doParse() override {
// Make Archive object which will be owned by FileArchive object.
+ llvm::Error Err;
+ _archive.reset(new Archive(_mb->getMemBufferRef(), Err));
+ if (Err)
+ return errorToErrorCode(std::move(Err));
std::error_code ec;
- _archive.reset(new Archive(_mb->getMemBufferRef(), ec));
- if (ec)
- return ec;
if ((ec = buildTableOfContents()))
return ec;
return std::error_code();
}
private:
- std::error_code instantiateMember(Archive::child_iterator cOrErr,
+ std::error_code instantiateMember(Archive::Child member,
std::unique_ptr<File> &result) const {
- if (std::error_code ec = cOrErr->getError())
- return ec;
- Archive::child_iterator member = cOrErr->get();
- ErrorOr<llvm::MemoryBufferRef> mbOrErr = (*member)->getMemoryBufferRef();
+ ErrorOr<llvm::MemoryBufferRef> mbOrErr = member.getMemoryBufferRef();
if (std::error_code ec = mbOrErr.getError())
return ec;
llvm::MemoryBufferRef mb = mbOrErr.get();
@@ -204,64 +160,27 @@ private:
return std::error_code();
}
- // Parses the given memory buffer as an object file, and returns true
- // code if the given symbol is a data symbol. If the symbol is not a data
- // symbol or does not exist, returns false.
- bool isDataSymbol(Archive::child_iterator cOrErr, StringRef symbol) const {
- if (cOrErr->getError())
- return false;
- Archive::child_iterator member = cOrErr->get();
- ErrorOr<llvm::MemoryBufferRef> buf = (*member)->getMemoryBufferRef();
- if (buf.getError())
- return false;
- std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(
- buf.get().getBuffer(), buf.get().getBufferIdentifier(), false));
-
- auto objOrErr(ObjectFile::createObjectFile(mb->getMemBufferRef()));
- if (objOrErr.getError())
- return false;
- std::unique_ptr<ObjectFile> obj = std::move(objOrErr.get());
-
- for (SymbolRef sym : obj->symbols()) {
- // Skip until we find the symbol.
- ErrorOr<StringRef> name = sym.getName();
- if (!name)
- return false;
- if (*name != symbol)
- continue;
- uint32_t flags = sym.getFlags();
- if (flags <= SymbolRef::SF_Undefined)
- continue;
-
- // Returns true if it's a data symbol.
- SymbolRef::Type type = sym.getType();
- if (type == SymbolRef::ST_Data)
- return true;
- }
- return false;
- }
-
std::error_code buildTableOfContents() {
DEBUG_WITH_TYPE("FileArchive", llvm::dbgs()
<< "Table of contents for archive '"
<< _archive->getFileName() << "':\n");
for (const Archive::Symbol &sym : _archive->symbols()) {
StringRef name = sym.getName();
- ErrorOr<Archive::child_iterator> memberOrErr = sym.getMember();
+ ErrorOr<Archive::Child> memberOrErr = sym.getMember();
if (std::error_code ec = memberOrErr.getError())
return ec;
- Archive::child_iterator member = memberOrErr.get();
+ Archive::Child member = memberOrErr.get();
DEBUG_WITH_TYPE("FileArchive",
llvm::dbgs()
<< llvm::format("0x%08llX ",
- (*member)->getBuffer()->data())
+ member.getBuffer()->data())
<< "'" << name << "'\n");
_symbolMemberMap.insert(std::make_pair(name, member));
}
return std::error_code();
}
- typedef std::unordered_map<StringRef, Archive::child_iterator> MemberMap;
+ typedef std::unordered_map<StringRef, Archive::Child> MemberMap;
typedef std::set<const char *> InstantiatedSet;
std::shared_ptr<MemoryBuffer> _mb;
@@ -271,9 +190,7 @@ private:
InstantiatedSet _membersInstantiated;
bool _logLoading;
std::vector<std::unique_ptr<MemoryBuffer>> _memberBuffers;
- std::map<const char *, std::unique_ptr<Future<File *>>> _preloaded;
- std::mutex _mutex;
- FileVector _filesReturned;
+ std::vector<std::unique_ptr<File>> _filesReturned;
};
class ArchiveReader : public Reader {
@@ -302,4 +219,4 @@ void Registry::addSupportArchives(bool logLoading) {
add(std::unique_ptr<Reader>(new ArchiveReader(logLoading)));
}
-} // end namespace lld
+} // namespace lld
diff --git a/lib/ReaderWriter/LinkerScript.cpp b/lib/ReaderWriter/LinkerScript.cpp
deleted file mode 100644
index 67822dc48fe6..000000000000
--- a/lib/ReaderWriter/LinkerScript.cpp
+++ /dev/null
@@ -1,2895 +0,0 @@
-//===- ReaderWriter/LinkerScript.cpp ----------------------------*- C++ -*-===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Linker script parser.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/ReaderWriter/LinkerScript.h"
-
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace script {
-void Token::dump(raw_ostream &os) const {
- switch (_kind) {
-#define CASE(name) \
- case Token::name: \
- os << #name ": "; \
- break;
- CASE(unknown)
- CASE(eof)
- CASE(exclaim)
- CASE(exclaimequal)
- CASE(amp)
- CASE(ampequal)
- CASE(l_paren)
- CASE(r_paren)
- CASE(star)
- CASE(starequal)
- CASE(plus)
- CASE(plusequal)
- CASE(comma)
- CASE(minus)
- CASE(minusequal)
- CASE(slash)
- CASE(slashequal)
- CASE(number)
- CASE(colon)
- CASE(semicolon)
- CASE(less)
- CASE(lessequal)
- CASE(lessless)
- CASE(lesslessequal)
- CASE(equal)
- CASE(equalequal)
- CASE(greater)
- CASE(greaterequal)
- CASE(greatergreater)
- CASE(greatergreaterequal)
- CASE(question)
- CASE(identifier)
- CASE(libname)
- CASE(kw_align)
- CASE(kw_align_with_input)
- CASE(kw_as_needed)
- CASE(kw_at)
- CASE(kw_discard)
- CASE(kw_entry)
- CASE(kw_exclude_file)
- CASE(kw_extern)
- CASE(kw_filehdr)
- CASE(kw_fill)
- CASE(kw_flags)
- CASE(kw_group)
- CASE(kw_hidden)
- CASE(kw_input)
- CASE(kw_keep)
- CASE(kw_length)
- CASE(kw_memory)
- CASE(kw_origin)
- CASE(kw_phdrs)
- CASE(kw_provide)
- CASE(kw_provide_hidden)
- CASE(kw_only_if_ro)
- CASE(kw_only_if_rw)
- CASE(kw_output)
- CASE(kw_output_arch)
- CASE(kw_output_format)
- CASE(kw_overlay)
- CASE(kw_search_dir)
- CASE(kw_sections)
- CASE(kw_sort_by_alignment)
- CASE(kw_sort_by_init_priority)
- CASE(kw_sort_by_name)
- CASE(kw_sort_none)
- CASE(kw_subalign)
- CASE(l_brace)
- CASE(pipe)
- CASE(pipeequal)
- CASE(r_brace)
- CASE(tilde)
-#undef CASE
- }
- os << _range << "\n";
-}
-
-static llvm::ErrorOr<uint64_t> parseDecimal(StringRef str) {
- uint64_t res = 0;
- for (auto &c : str) {
- res *= 10;
- if (c < '0' || c > '9')
- return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
- res += c - '0';
- }
- return res;
-}
-
-static llvm::ErrorOr<uint64_t> parseOctal(StringRef str) {
- uint64_t res = 0;
- for (auto &c : str) {
- res <<= 3;
- if (c < '0' || c > '7')
- return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
- res += c - '0';
- }
- return res;
-}
-
-static llvm::ErrorOr<uint64_t> parseBinary(StringRef str) {
- uint64_t res = 0;
- for (auto &c : str) {
- res <<= 1;
- if (c != '0' && c != '1')
- return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
- res += c - '0';
- }
- return res;
-}
-
-static llvm::ErrorOr<uint64_t> parseHex(StringRef str) {
- uint64_t res = 0;
- for (auto &c : str) {
- res <<= 4;
- if (c >= '0' && c <= '9')
- res += c - '0';
- else if (c >= 'a' && c <= 'f')
- res += c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- res += c - 'A' + 10;
- else
- return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
- }
- return res;
-}
-
-static bool parseHexToByteStream(StringRef str, std::string &buf) {
- unsigned char byte = 0;
- bool dumpByte = str.size() % 2;
- for (auto &c : str) {
- byte <<= 4;
- if (c >= '0' && c <= '9')
- byte += c - '0';
- else if (c >= 'a' && c <= 'f')
- byte += c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- byte += c - 'A' + 10;
- else
- return false;
- if (!dumpByte) {
- dumpByte = true;
- continue;
- }
- buf.push_back(byte);
- byte = 0;
- dumpByte = false;
- }
- return !dumpByte;
-}
-
-static void dumpByteStream(raw_ostream &os, StringRef stream) {
- os << "0x";
- for (auto &c : stream) {
- unsigned char firstNibble = c >> 4 & 0xF;
- if (firstNibble > 9)
- os << (char) ('A' + firstNibble - 10);
- else
- os << (char) ('0' + firstNibble);
- unsigned char secondNibble = c & 0xF;
- if (secondNibble > 9)
- os << (char) ('A' + secondNibble - 10);
- else
- os << (char) ('0' + secondNibble);
- }
-}
-
-static llvm::ErrorOr<uint64_t> parseNum(StringRef str) {
- unsigned multiplier = 1;
- enum NumKind { decimal, hex, octal, binary };
- NumKind kind = llvm::StringSwitch<NumKind>(str)
- .StartsWith("0x", hex)
- .StartsWith("0X", hex)
- .StartsWith("0", octal)
- .Default(decimal);
-
- // Parse scale
- if (str.endswith("K")) {
- multiplier = 1 << 10;
- str = str.drop_back();
- } else if (str.endswith("M")) {
- multiplier = 1 << 20;
- str = str.drop_back();
- }
-
- // Parse type
- if (str.endswith_lower("o")) {
- kind = octal;
- str = str.drop_back();
- } else if (str.endswith_lower("h")) {
- kind = hex;
- str = str.drop_back();
- } else if (str.endswith_lower("d")) {
- kind = decimal;
- str = str.drop_back();
- } else if (str.endswith_lower("b")) {
- kind = binary;
- str = str.drop_back();
- }
-
- llvm::ErrorOr<uint64_t> res(0);
- switch (kind) {
- case hex:
- if (str.startswith_lower("0x"))
- str = str.drop_front(2);
- res = parseHex(str);
- break;
- case octal:
- res = parseOctal(str);
- break;
- case decimal:
- res = parseDecimal(str);
- break;
- case binary:
- res = parseBinary(str);
- break;
- }
- if (res.getError())
- return res;
-
- *res = *res * multiplier;
- return res;
-}
-
-bool Lexer::canStartNumber(char c) const {
- return '0' <= c && c <= '9';
-}
-
-bool Lexer::canContinueNumber(char c) const {
- // [xX] = hex marker, [hHoO] = type suffix, [MK] = scale suffix.
- return strchr("0123456789ABCDEFabcdefxXhHoOMK", c);
-}
-
-bool Lexer::canStartName(char c) const {
- return strchr(
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_.$/\\*", c);
-}
-
-bool Lexer::canContinueName(char c) const {
- return strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789_.$/\\~=+[]*?-:", c);
-}
-
-/// Helper function to split a StringRef in two at the nth character.
-/// The StringRef s is updated, while the function returns the n first
-/// characters.
-static StringRef drop(StringRef &s, int n) {
- StringRef res = s.substr(0, n);
- s = s.drop_front(n);
- return res;
-}
-
-void Lexer::lex(Token &tok) {
- skipWhitespace();
- if (_buffer.empty()) {
- tok = Token(_buffer, Token::eof);
- return;
- }
- switch (_buffer[0]) {
- case 0:
- tok = Token(drop(_buffer, 1), Token::eof);
- return;
- case '(':
- tok = Token(drop(_buffer, 1), Token::l_paren);
- return;
- case ')':
- tok = Token(drop(_buffer, 1), Token::r_paren);
- return;
- case '{':
- tok = Token(drop(_buffer, 1), Token::l_brace);
- return;
- case '}':
- tok = Token(drop(_buffer, 1), Token::r_brace);
- return;
- case '=':
- if (_buffer.startswith("==")) {
- tok = Token(drop(_buffer, 2), Token::equalequal);
- return;
- }
- tok = Token(drop(_buffer, 1), Token::equal);
- return;
- case '!':
- if (_buffer.startswith("!=")) {
- tok = Token(drop(_buffer, 2), Token::exclaimequal);
- return;
- }
- tok = Token(drop(_buffer, 1), Token::exclaim);
- return;
- case ',':
- tok = Token(drop(_buffer, 1), Token::comma);
- return;
- case ';':
- tok = Token(drop(_buffer, 1), Token::semicolon);
- return;
- case ':':
- tok = Token(drop(_buffer, 1), Token::colon);
- return;
- case '&':
- if (_buffer.startswith("&=")) {
- tok = Token(drop(_buffer, 2), Token::ampequal);
- return;
- }
- tok = Token(drop(_buffer, 1), Token::amp);
- return;
- case '|':
- if (_buffer.startswith("|=")) {
- tok = Token(drop(_buffer, 2), Token::pipeequal);
- return;
- }
- tok = Token(drop(_buffer, 1), Token::pipe);
- return;
- case '+':
- if (_buffer.startswith("+=")) {
- tok = Token(drop(_buffer, 2), Token::plusequal);
- return;
- }
- tok = Token(drop(_buffer, 1), Token::plus);
- return;
- case '-': {
- if (_buffer.startswith("-=")) {
- tok = Token(drop(_buffer, 2), Token::minusequal);
- return;
- }
- if (!_buffer.startswith("-l")) {
- tok = Token(drop(_buffer, 1), Token::minus);
- return;
- }
- // -l<lib name>
- _buffer = _buffer.drop_front(2);
- StringRef::size_type start = 0;
- if (_buffer[start] == ':')
- ++start;
- if (!canStartName(_buffer[start]))
- // Create 'unknown' token.
- break;
- auto libNameEnd = std::find_if(_buffer.begin() + start + 1, _buffer.end(),
- [=](char c) { return !canContinueName(c); });
- StringRef::size_type libNameLen =
- std::distance(_buffer.begin(), libNameEnd);
- tok = Token(_buffer.substr(0, libNameLen), Token::libname);
- _buffer = _buffer.drop_front(libNameLen);
- return;
- }
- case '<':
- if (_buffer.startswith("<<=")) {
- tok = Token(drop(_buffer, 3), Token::lesslessequal);
- return;
- }
- if (_buffer.startswith("<<")) {
- tok = Token(drop(_buffer, 2), Token::lessless);
- return;
- }
- if (_buffer.startswith("<=")) {
- tok = Token(drop(_buffer, 2), Token::lessequal);
- return;
- }
- tok = Token(drop(_buffer, 1), Token::less);
- return;
- case '>':
- if (_buffer.startswith(">>=")) {
- tok = Token(drop(_buffer, 3), Token::greatergreaterequal);
- return;
- }
- if (_buffer.startswith(">>")) {
- tok = Token(drop(_buffer, 2), Token::greatergreater);
- return;
- }
- if (_buffer.startswith(">=")) {
- tok = Token(drop(_buffer, 2), Token::greaterequal);
- return;
- }
- tok = Token(drop(_buffer, 1), Token::greater);
- return;
- case '~':
- tok = Token(drop(_buffer, 1), Token::tilde);
- return;
- case '\"': case '\'': {
- // Handle quoted strings. They are treated as identifiers for
- // simplicity.
- char c = _buffer[0];
- _buffer = _buffer.drop_front();
- auto quotedStringEnd = _buffer.find(c);
- if (quotedStringEnd == StringRef::npos || quotedStringEnd == 0)
- break;
- StringRef word = _buffer.substr(0, quotedStringEnd);
- tok = Token(word, Token::identifier);
- _buffer = _buffer.drop_front(quotedStringEnd + 1);
- return;
- }
- default:
- // Handle literal numbers
- if (canStartNumber(_buffer[0])) {
- auto endIter = std::find_if(_buffer.begin(), _buffer.end(), [=](char c) {
- return !canContinueNumber(c);
- });
- StringRef::size_type end = endIter == _buffer.end()
- ? StringRef::npos
- : std::distance(_buffer.begin(), endIter);
- if (end == StringRef::npos || end == 0)
- break;
- StringRef word = _buffer.substr(0, end);
- tok = Token(word, Token::number);
- _buffer = _buffer.drop_front(end);
- return;
- }
- // Handle slashes '/', which can be either an operator inside an expression
- // or the beginning of an identifier
- if (_buffer.startswith("/=")) {
- tok = Token(drop(_buffer, 2), Token::slashequal);
- return;
- }
- if (_buffer[0] == '/' && _buffer.size() > 1 &&
- !canContinueName(_buffer[1])) {
- tok = Token(drop(_buffer, 1), Token::slash);
- return;
- }
- // Handle stars '*'
- if (_buffer.startswith("*=")) {
- tok = Token(drop(_buffer, 2), Token::starequal);
- return;
- }
- if (_buffer[0] == '*' && _buffer.size() > 1 &&
- !canContinueName(_buffer[1])) {
- tok = Token(drop(_buffer, 1), Token::star);
- return;
- }
- // Handle questions '?'
- if (_buffer[0] == '?' && _buffer.size() > 1 &&
- !canContinueName(_buffer[1])) {
- tok = Token(drop(_buffer, 1), Token::question);
- return;
- }
- // keyword or identifier.
- if (!canStartName(_buffer[0]))
- break;
- auto endIter = std::find_if(_buffer.begin() + 1, _buffer.end(),
- [=](char c) { return !canContinueName(c); });
- StringRef::size_type end = endIter == _buffer.end()
- ? StringRef::npos
- : std::distance(_buffer.begin(), endIter);
- if (end == StringRef::npos || end == 0)
- break;
- StringRef word = _buffer.substr(0, end);
- Token::Kind kind =
- llvm::StringSwitch<Token::Kind>(word)
- .Case("ALIGN", Token::kw_align)
- .Case("ALIGN_WITH_INPUT", Token::kw_align_with_input)
- .Case("AS_NEEDED", Token::kw_as_needed)
- .Case("AT", Token::kw_at)
- .Case("ENTRY", Token::kw_entry)
- .Case("EXCLUDE_FILE", Token::kw_exclude_file)
- .Case("EXTERN", Token::kw_extern)
- .Case("FILEHDR", Token::kw_filehdr)
- .Case("FILL", Token::kw_fill)
- .Case("FLAGS", Token::kw_flags)
- .Case("GROUP", Token::kw_group)
- .Case("HIDDEN", Token::kw_hidden)
- .Case("INPUT", Token::kw_input)
- .Case("KEEP", Token::kw_keep)
- .Case("LENGTH", Token::kw_length)
- .Case("l", Token::kw_length)
- .Case("len", Token::kw_length)
- .Case("MEMORY", Token::kw_memory)
- .Case("ONLY_IF_RO", Token::kw_only_if_ro)
- .Case("ONLY_IF_RW", Token::kw_only_if_rw)
- .Case("ORIGIN", Token::kw_origin)
- .Case("o", Token::kw_origin)
- .Case("org", Token::kw_origin)
- .Case("OUTPUT", Token::kw_output)
- .Case("OUTPUT_ARCH", Token::kw_output_arch)
- .Case("OUTPUT_FORMAT", Token::kw_output_format)
- .Case("OVERLAY", Token::kw_overlay)
- .Case("PHDRS", Token::kw_phdrs)
- .Case("PROVIDE", Token::kw_provide)
- .Case("PROVIDE_HIDDEN", Token::kw_provide_hidden)
- .Case("SEARCH_DIR", Token::kw_search_dir)
- .Case("SECTIONS", Token::kw_sections)
- .Case("SORT", Token::kw_sort_by_name)
- .Case("SORT_BY_ALIGNMENT", Token::kw_sort_by_alignment)
- .Case("SORT_BY_INIT_PRIORITY", Token::kw_sort_by_init_priority)
- .Case("SORT_BY_NAME", Token::kw_sort_by_name)
- .Case("SORT_NONE", Token::kw_sort_none)
- .Case("SUBALIGN", Token::kw_subalign)
- .Case("/DISCARD/", Token::kw_discard)
- .Default(Token::identifier);
- tok = Token(word, kind);
- _buffer = _buffer.drop_front(end);
- return;
- }
- tok = Token(drop(_buffer, 1), Token::unknown);
-}
-
-void Lexer::skipWhitespace() {
- while (true) {
- if (_buffer.empty())
- return;
- switch (_buffer[0]) {
- case ' ':
- case '\r':
- case '\n':
- case '\t':
- _buffer = _buffer.drop_front();
- break;
- // Potential comment.
- case '/':
- if (_buffer.size() <= 1 || _buffer[1] != '*')
- return;
- // Skip starting /*
- _buffer = _buffer.drop_front(2);
- // If the next char is also a /, it's not the end.
- if (!_buffer.empty() && _buffer[0] == '/')
- _buffer = _buffer.drop_front();
-
- // Scan for /'s. We're done if it is preceded by a *.
- while (true) {
- if (_buffer.empty())
- break;
- _buffer = _buffer.drop_front();
- if (_buffer.data()[-1] == '/' && _buffer.data()[-2] == '*')
- break;
- }
- break;
- default:
- return;
- }
- }
-}
-
-// Constant functions
-void Constant::dump(raw_ostream &os) const { os << _num; }
-
-ErrorOr<int64_t> Constant::evalExpr(const SymbolTableTy &symbolTable) const {
- return _num;
-}
-
-// Symbol functions
-void Symbol::dump(raw_ostream &os) const { os << _name; }
-
-ErrorOr<int64_t> Symbol::evalExpr(const SymbolTableTy &symbolTable) const {
- auto it = symbolTable.find(_name);
- if (it == symbolTable.end())
- return LinkerScriptReaderError::unknown_symbol_in_expr;
- return it->second;
-}
-
-// FunctionCall functions
-void FunctionCall::dump(raw_ostream &os) const {
- os << _name << "(";
- for (unsigned i = 0, e = _args.size(); i != e; ++i) {
- if (i)
- os << ", ";
- _args[i]->dump(os);
- }
- os << ")";
-}
-
-ErrorOr<int64_t>
-FunctionCall::evalExpr(const SymbolTableTy &symbolTable) const {
- return LinkerScriptReaderError::unrecognized_function_in_expr;
-}
-
-// Unary functions
-void Unary::dump(raw_ostream &os) const {
- os << "(";
- if (_op == Unary::Minus)
- os << "-";
- else
- os << "~";
- _child->dump(os);
- os << ")";
-}
-
-ErrorOr<int64_t> Unary::evalExpr(const SymbolTableTy &symbolTable) const {
- auto child = _child->evalExpr(symbolTable);
- if (child.getError())
- return child.getError();
-
- int64_t childRes = *child;
- switch (_op) {
- case Unary::Minus:
- return -childRes;
- case Unary::Not:
- return ~childRes;
- }
-
- llvm_unreachable("");
-}
-
-// BinOp functions
-void BinOp::dump(raw_ostream &os) const {
- os << "(";
- _lhs->dump(os);
- os << " ";
- switch (_op) {
- case Sum:
- os << "+";
- break;
- case Sub:
- os << "-";
- break;
- case Mul:
- os << "*";
- break;
- case Div:
- os << "/";
- break;
- case Shl:
- os << "<<";
- break;
- case Shr:
- os << ">>";
- break;
- case And:
- os << "&";
- break;
- case Or:
- os << "|";
- break;
- case CompareEqual:
- os << "==";
- break;
- case CompareDifferent:
- os << "!=";
- break;
- case CompareLess:
- os << "<";
- break;
- case CompareGreater:
- os << ">";
- break;
- case CompareLessEqual:
- os << "<=";
- break;
- case CompareGreaterEqual:
- os << ">=";
- break;
- }
- os << " ";
- _rhs->dump(os);
- os << ")";
-}
-
-ErrorOr<int64_t> BinOp::evalExpr(const SymbolTableTy &symbolTable) const {
- auto lhs = _lhs->evalExpr(symbolTable);
- if (lhs.getError())
- return lhs.getError();
- auto rhs = _rhs->evalExpr(symbolTable);
- if (rhs.getError())
- return rhs.getError();
-
- int64_t lhsRes = *lhs;
- int64_t rhsRes = *rhs;
-
- switch(_op) {
- case And: return lhsRes & rhsRes;
- case CompareDifferent: return lhsRes != rhsRes;
- case CompareEqual: return lhsRes == rhsRes;
- case CompareGreater: return lhsRes > rhsRes;
- case CompareGreaterEqual: return lhsRes >= rhsRes;
- case CompareLess: return lhsRes < rhsRes;
- case CompareLessEqual: return lhsRes <= rhsRes;
- case Div: return lhsRes / rhsRes;
- case Mul: return lhsRes * rhsRes;
- case Or: return lhsRes | rhsRes;
- case Shl: return lhsRes << rhsRes;
- case Shr: return lhsRes >> rhsRes;
- case Sub: return lhsRes - rhsRes;
- case Sum: return lhsRes + rhsRes;
- }
-
- llvm_unreachable("");
-}
-
-// TernaryConditional functions
-void TernaryConditional::dump(raw_ostream &os) const {
- _conditional->dump(os);
- os << " ? ";
- _trueExpr->dump(os);
- os << " : ";
- _falseExpr->dump(os);
-}
-
-ErrorOr<int64_t>
-TernaryConditional::evalExpr(const SymbolTableTy &symbolTable) const {
- auto conditional = _conditional->evalExpr(symbolTable);
- if (conditional.getError())
- return conditional.getError();
- if (*conditional)
- return _trueExpr->evalExpr(symbolTable);
- return _falseExpr->evalExpr(symbolTable);
-}
-
-// SymbolAssignment functions
-void SymbolAssignment::dump(raw_ostream &os) const {
- int numParen = 0;
-
- if (_assignmentVisibility != Default) {
- switch (_assignmentVisibility) {
- case Hidden:
- os << "HIDDEN(";
- break;
- case Provide:
- os << "PROVIDE(";
- break;
- case ProvideHidden:
- os << "PROVIDE_HIDDEN(";
- break;
- default:
- llvm_unreachable("Unknown visibility");
- }
- ++numParen;
- }
-
- os << _symbol << " ";
- switch (_assignmentKind) {
- case Simple:
- os << "=";
- break;
- case Sum:
- os << "+=";
- break;
- case Sub:
- os << "-=";
- break;
- case Mul:
- os << "*=";
- break;
- case Div:
- os << "/=";
- break;
- case Shl:
- os << "<<=";
- break;
- case Shr:
- os << ">>=";
- break;
- case And:
- os << "&=";
- break;
- case Or:
- os << "|=";
- break;
- }
-
- os << " ";
- _expression->dump(os);
- if (numParen)
- os << ")";
- os << ";";
-}
-
-static int dumpSortDirectives(raw_ostream &os, WildcardSortMode sortMode) {
- switch (sortMode) {
- case WildcardSortMode::NA:
- return 0;
- case WildcardSortMode::ByName:
- os << "SORT_BY_NAME(";
- return 1;
- case WildcardSortMode::ByAlignment:
- os << "SORT_BY_ALIGNMENT(";
- return 1;
- case WildcardSortMode::ByInitPriority:
- os << "SORT_BY_INIT_PRIORITY(";
- return 1;
- case WildcardSortMode::ByNameAndAlignment:
- os << "SORT_BY_NAME(SORT_BY_ALIGNMENT(";
- return 2;
- case WildcardSortMode::ByAlignmentAndName:
- os << "SORT_BY_ALIGNMENT(SORT_BY_NAME(";
- return 2;
- case WildcardSortMode::None:
- os << "SORT_NONE(";
- return 1;
- }
- return 0;
-}
-
-// InputSectionName functions
-void InputSectionName::dump(raw_ostream &os) const {
- os << _name;
-}
-
-// InputSectionSortedGroup functions
-static void dumpInputSections(raw_ostream &os,
- llvm::ArrayRef<const InputSection *> secs) {
- bool excludeFile = false;
- bool first = true;
-
- for (auto &secName : secs) {
- if (!first)
- os << " ";
- first = false;
- // Coalesce multiple input sections marked with EXCLUDE_FILE in the same
- // EXCLUDE_FILE() group
- if (auto inputSec = dyn_cast<InputSectionName>(secName)) {
- if (!excludeFile && inputSec->hasExcludeFile()) {
- excludeFile = true;
- os << "EXCLUDE_FILE(";
- } else if (excludeFile && !inputSec->hasExcludeFile()) {
- excludeFile = false;
- os << ") ";
- }
- }
- secName->dump(os);
- }
-
- if (excludeFile)
- os << ")";
-}
-
-void InputSectionSortedGroup::dump(raw_ostream &os) const {
- int numParen = dumpSortDirectives(os, _sortMode);
- dumpInputSections(os, _sections);
- for (int i = 0; i < numParen; ++i)
- os << ")";
-}
-
-// InputSectionsCmd functions
-void InputSectionsCmd::dump(raw_ostream &os) const {
- if (_keep)
- os << "KEEP(";
-
- int numParen = dumpSortDirectives(os, _fileSortMode);
- os << _memberName;
- for (int i = 0; i < numParen; ++i)
- os << ")";
-
- if (_archiveName.size() > 0) {
- os << ":";
- numParen = dumpSortDirectives(os, _archiveSortMode);
- os << _archiveName;
- for (int i = 0; i < numParen; ++i)
- os << ")";
- }
-
- if (_sections.size() > 0) {
- os << "(";
- dumpInputSections(os, _sections);
- os << ")";
- }
-
- if (_keep)
- os << ")";
-}
-
-void FillCmd::dump(raw_ostream &os) const {
- os << "FILL(";
- dumpByteStream(os, StringRef((const char *)_bytes.begin(), _bytes.size()));
- os << ")";
-}
-
-// OutputSectionDescription functions
-void OutputSectionDescription::dump(raw_ostream &os) const {
- if (_discard)
- os << "/DISCARD/";
- else
- os << _sectionName;
-
- if (_address) {
- os << " ";
- _address->dump(os);
- }
- os << " :\n";
-
- if (_at) {
- os << " AT(";
- _at->dump(os);
- os << ")\n";
- }
-
- if (_align) {
- os << " ALIGN(";
- _align->dump(os);
- os << ")\n";
- } else if (_alignWithInput) {
- os << " ALIGN_WITH_INPUT\n";
- }
-
- if (_subAlign) {
- os << " SUBALIGN(";
- _subAlign->dump(os);
- os << ")\n";
- }
-
- switch (_constraint) {
- case C_None:
- break;
- case C_OnlyIfRO:
- os << "ONLY_IF_RO";
- break;
- case C_OnlyIfRW:
- os << "ONLY_IF_RW";
- break;
- }
-
- os << " {\n";
- for (auto &command : _outputSectionCommands) {
- os << " ";
- command->dump(os);
- os << "\n";
- }
- os << " }";
-
- for (auto && phdr : _phdrs)
- os << " : " << phdr;
-
- if (_fillStream.size() > 0) {
- os << " =";
- dumpByteStream(os, _fillStream);
- } else if (_fillExpr) {
- os << " =";
- _fillExpr->dump(os);
- }
-}
-
-// Special header that discards output sections assigned to it.
-static const PHDR PHDR_NONE("NONE", 0, false, false, nullptr, 0);
-
-bool PHDR::isNone() const {
- return this == &PHDR_NONE;
-}
-
-void PHDR::dump(raw_ostream &os) const {
- os << _name << " " << _type;
- if (_includeFileHdr)
- os << " FILEHDR";
- if (_includePHDRs)
- os << " PHDRS";
- if (_at) {
- os << " AT (";
- _at->dump(os);
- os << ")";
- }
- if (_flags)
- os << " FLAGS (" << _flags << ")";
- os << ";\n";
-}
-
-void PHDRS::dump(raw_ostream &os) const {
- os << "PHDRS\n{\n";
- for (auto &&phdr : _phdrs) {
- phdr->dump(os);
- }
- os << "}\n";
-}
-
-// Sections functions
-void Sections::dump(raw_ostream &os) const {
- os << "SECTIONS\n{\n";
- for (auto &command : _sectionsCommands) {
- command->dump(os);
- os << "\n";
- }
- os << "}\n";
-}
-
-// Memory functions
-void MemoryBlock::dump(raw_ostream &os) const {
- os << _name;
-
- if (!_attr.empty())
- os << " (" << _attr << ")";
-
- os << " : ";
-
- os << "ORIGIN = ";
- _origin->dump(os);
- os << ", ";
-
- os << "LENGTH = ";
- _length->dump(os);
-}
-
-void Memory::dump(raw_ostream &os) const {
- os << "MEMORY\n{\n";
- for (auto &block : _blocks) {
- block->dump(os);
- os << "\n";
- }
- os << "}\n";
-}
-
-// Extern functions
-void Extern::dump(raw_ostream &os) const {
- os << "EXTERN(";
- for (unsigned i = 0, e = _symbols.size(); i != e; ++i) {
- if (i)
- os << " ";
- os << _symbols[i];
- }
- os << ")\n";
-}
-
-// Parser functions
-std::error_code Parser::parse() {
- // Get the first token.
- _lex.lex(_tok);
- // Parse top level commands.
- while (true) {
- switch (_tok._kind) {
- case Token::eof:
- return std::error_code();
- case Token::semicolon:
- consumeToken();
- break;
- case Token::kw_output: {
- auto output = parseOutput();
- if (!output)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(output);
- break;
- }
- case Token::kw_output_format: {
- auto outputFormat = parseOutputFormat();
- if (!outputFormat)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(outputFormat);
- break;
- }
- case Token::kw_output_arch: {
- auto outputArch = parseOutputArch();
- if (!outputArch)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(outputArch);
- break;
- }
- case Token::kw_input: {
- Input *input = parsePathList<Input>();
- if (!input)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(input);
- break;
- }
- case Token::kw_group: {
- Group *group = parsePathList<Group>();
- if (!group)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(group);
- break;
- }
- case Token::kw_as_needed:
- // Not allowed at top level.
- error(_tok, "AS_NEEDED not allowed at top level.");
- return LinkerScriptReaderError::parse_error;
- case Token::kw_entry: {
- Entry *entry = parseEntry();
- if (!entry)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(entry);
- break;
- }
- case Token::kw_phdrs: {
- PHDRS *phdrs = parsePHDRS();
- if (!phdrs)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(phdrs);
- break;
- }
- case Token::kw_search_dir: {
- SearchDir *searchDir = parseSearchDir();
- if (!searchDir)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(searchDir);
- break;
- }
- case Token::kw_sections: {
- Sections *sections = parseSections();
- if (!sections)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(sections);
- break;
- }
- case Token::identifier:
- case Token::kw_hidden:
- case Token::kw_provide:
- case Token::kw_provide_hidden: {
- const Command *cmd = parseSymbolAssignment();
- if (!cmd)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(cmd);
- break;
- }
- case Token::kw_memory: {
- const Command *cmd = parseMemory();
- if (!cmd)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(cmd);
- break;
- }
- case Token::kw_extern: {
- const Command *cmd = parseExtern();
- if (!cmd)
- return LinkerScriptReaderError::parse_error;
- _script._commands.push_back(cmd);
- break;
- }
- default:
- // Unexpected.
- error(_tok, "expected linker script command");
- return LinkerScriptReaderError::parse_error;
- }
- }
- return LinkerScriptReaderError::parse_error;
-}
-
-const Expression *Parser::parseFunctionCall() {
- assert((_tok._kind == Token::identifier || _tok._kind == Token::kw_align) &&
- "expected function call first tokens");
- SmallVector<const Expression *, 8> params;
- StringRef name = _tok._range;
-
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
-
- if (_tok._kind == Token::r_paren) {
- consumeToken();
- return new (_alloc) FunctionCall(*this, _tok._range, params);
- }
-
- if (const Expression *firstParam = parseExpression())
- params.push_back(firstParam);
- else
- return nullptr;
-
- while (_tok._kind == Token::comma) {
- consumeToken();
- if (const Expression *param = parseExpression())
- params.push_back(param);
- else
- return nullptr;
- }
-
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- return new (_alloc) FunctionCall(*this, name, params);
-}
-
-bool Parser::expectExprOperand() {
- if (!(_tok._kind == Token::identifier || _tok._kind == Token::number ||
- _tok._kind == Token::kw_align || _tok._kind == Token::l_paren ||
- _tok._kind == Token::minus || _tok._kind == Token::tilde)) {
- error(_tok, "expected symbol, number, minus, tilde or left parenthesis.");
- return false;
- }
- return true;
-}
-
-const Expression *Parser::parseExprOperand() {
- if (!expectExprOperand())
- return nullptr;
-
- switch (_tok._kind) {
- case Token::identifier: {
- if (peek()._kind== Token::l_paren)
- return parseFunctionCall();
- auto *sym = new (_alloc) Symbol(*this, _tok._range);
- consumeToken();
- return sym;
- }
- case Token::kw_align:
- return parseFunctionCall();
- case Token::minus:
- consumeToken();
- return new (_alloc) Unary(*this, Unary::Minus, parseExprOperand());
- case Token::tilde:
- consumeToken();
- return new (_alloc) Unary(*this, Unary::Not, parseExprOperand());
- case Token::number: {
- auto val = parseNum(_tok._range);
- if (val.getError()) {
- error(_tok, "Unrecognized number constant");
- return nullptr;
- }
- auto *c = new (_alloc) Constant(*this, *val);
- consumeToken();
- return c;
- }
- case Token::l_paren: {
- consumeToken();
- const Expression *expr = parseExpression();
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- return expr;
- }
- default:
- llvm_unreachable("Unknown token");
- }
-}
-
-static bool TokenToBinOp(const Token &tok, BinOp::Operation &op,
- unsigned &precedence) {
- switch (tok._kind) {
- case Token::star:
- op = BinOp::Mul;
- precedence = 3;
- return true;
- case Token::slash:
- op = BinOp::Div;
- precedence = 3;
- return true;
- case Token::plus:
- op = BinOp::Sum;
- precedence = 4;
- return true;
- case Token::minus:
- op = BinOp::Sub;
- precedence = 4;
- return true;
- case Token::lessless:
- op = BinOp::Shl;
- precedence = 5;
- return true;
- case Token::greatergreater:
- op = BinOp::Shr;
- precedence = 5;
- return true;
- case Token::less:
- op = BinOp::CompareLess;
- precedence = 6;
- return true;
- case Token::greater:
- op = BinOp::CompareGreater;
- precedence = 6;
- return true;
- case Token::lessequal:
- op = BinOp::CompareLessEqual;
- precedence = 6;
- return true;
- case Token::greaterequal:
- op = BinOp::CompareGreaterEqual;
- precedence = 6;
- return true;
- case Token::equalequal:
- op = BinOp::CompareEqual;
- precedence = 7;
- return true;
- case Token::exclaimequal:
- op = BinOp::CompareDifferent;
- precedence = 7;
- return true;
- case Token::amp:
- op = BinOp::And;
- precedence = 8;
- return true;
- case Token::pipe:
- op = BinOp::Or;
- precedence = 10;
- return true;
- default:
- break;
- }
- return false;
-}
-
-static bool isExpressionOperator(Token tok) {
- switch (tok._kind) {
- case Token::star:
- case Token::slash:
- case Token::plus:
- case Token::minus:
- case Token::lessless:
- case Token::greatergreater:
- case Token::less:
- case Token::greater:
- case Token::lessequal:
- case Token::greaterequal:
- case Token::equalequal:
- case Token::exclaimequal:
- case Token::amp:
- case Token::pipe:
- case Token::question:
- return true;
- default:
- return false;
- }
-}
-
-const Expression *Parser::parseExpression(unsigned precedence) {
- assert(precedence <= 13 && "Invalid precedence value");
- if (!expectExprOperand())
- return nullptr;
-
- const Expression *expr = parseExprOperand();
- if (!expr)
- return nullptr;
-
- BinOp::Operation op;
- unsigned binOpPrecedence = 0;
- if (TokenToBinOp(_tok, op, binOpPrecedence)) {
- if (precedence >= binOpPrecedence)
- return parseOperatorOperandLoop(expr, precedence);
- return expr;
- }
-
- // Non-binary operators
- if (_tok._kind == Token::question && precedence >= 13)
- return parseOperatorOperandLoop(expr, precedence);
- return expr;
-}
-
-const Expression *Parser::parseOperatorOperandLoop(const Expression *lhs,
- unsigned highestPrecedence) {
- assert(highestPrecedence <= 13 && "Invalid precedence value");
- unsigned precedence = 0;
- const Expression *binOp = nullptr;
-
- while (1) {
- BinOp::Operation op;
- if (!TokenToBinOp(_tok, op, precedence)) {
- if (_tok._kind == Token::question && highestPrecedence >= 13)
- return parseTernaryCondOp(lhs);
- return binOp;
- }
-
- if (precedence > highestPrecedence)
- return binOp;
-
- consumeToken();
- const Expression *rhs = parseExpression(precedence - 1);
- if (!rhs)
- return nullptr;
- binOp = new (_alloc) BinOp(*this, lhs, op, rhs);
- lhs = binOp;
- }
-}
-
-const Expression *Parser::parseTernaryCondOp(const Expression *lhs) {
- assert(_tok._kind == Token::question && "Expected question mark");
-
- consumeToken();
-
- // The ternary conditional operator has right-to-left associativity.
- // To implement this, we allow our children to contain ternary conditional
- // operators themselves (precedence 13).
- const Expression *trueExpr = parseExpression(13);
- if (!trueExpr)
- return nullptr;
-
- if (!expectAndConsume(Token::colon, "expected :"))
- return nullptr;
-
- const Expression *falseExpr = parseExpression(13);
- if (!falseExpr)
- return nullptr;
-
- return new (_alloc) TernaryConditional(*this, lhs, trueExpr, falseExpr);
-}
-
-// Parse OUTPUT(ident)
-Output *Parser::parseOutput() {
- assert(_tok._kind == Token::kw_output && "Expected OUTPUT");
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
-
- if (_tok._kind != Token::identifier) {
- error(_tok, "Expected identifier in OUTPUT.");
- return nullptr;
- }
-
- auto ret = new (_alloc) Output(*this, _tok._range);
- consumeToken();
-
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
-
- return ret;
-}
-
-// Parse OUTPUT_FORMAT(ident)
-OutputFormat *Parser::parseOutputFormat() {
- assert(_tok._kind == Token::kw_output_format && "Expected OUTPUT_FORMAT!");
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
-
- if (_tok._kind != Token::identifier) {
- error(_tok, "Expected identifier in OUTPUT_FORMAT.");
- return nullptr;
- }
-
- SmallVector<StringRef, 8> formats;
- formats.push_back(_tok._range);
-
- consumeToken();
-
- do {
- if (isNextToken(Token::comma))
- consumeToken();
- else
- break;
- if (_tok._kind != Token::identifier) {
- error(_tok, "Expected identifier in OUTPUT_FORMAT.");
- return nullptr;
- }
- formats.push_back(_tok._range);
- consumeToken();
- } while (isNextToken(Token::comma));
-
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
-
- return new (_alloc) OutputFormat(*this, formats);
-}
-
-// Parse OUTPUT_ARCH(ident)
-OutputArch *Parser::parseOutputArch() {
- assert(_tok._kind == Token::kw_output_arch && "Expected OUTPUT_ARCH!");
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
-
- if (_tok._kind != Token::identifier) {
- error(_tok, "Expected identifier in OUTPUT_ARCH.");
- return nullptr;
- }
-
- auto ret = new (_alloc) OutputArch(*this, _tok._range);
- consumeToken();
-
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
-
- return ret;
-}
-
-// Parse file list for INPUT or GROUP
-template<class T> T *Parser::parsePathList() {
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
-
- SmallVector<Path, 8> paths;
- while (_tok._kind == Token::identifier || _tok._kind == Token::libname ||
- _tok._kind == Token::kw_as_needed) {
- switch (_tok._kind) {
- case Token::identifier:
- paths.push_back(Path(_tok._range));
- consumeToken();
- break;
- case Token::libname:
- paths.push_back(Path(_tok._range, false, true));
- consumeToken();
- break;
- case Token::kw_as_needed:
- if (!parseAsNeeded(paths))
- return nullptr;
- break;
- default:
- llvm_unreachable("Invalid token.");
- }
- }
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- return new (_alloc) T(*this, paths);
-}
-
-// Parse AS_NEEDED(file ...)
-bool Parser::parseAsNeeded(SmallVectorImpl<Path> &paths) {
- assert(_tok._kind == Token::kw_as_needed && "Expected AS_NEEDED!");
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return false;
-
- while (_tok._kind == Token::identifier || _tok._kind == Token::libname) {
- switch (_tok._kind) {
- case Token::identifier:
- paths.push_back(Path(_tok._range, true, false));
- consumeToken();
- break;
- case Token::libname:
- paths.push_back(Path(_tok._range, true, true));
- consumeToken();
- break;
- default:
- llvm_unreachable("Invalid token.");
- }
- }
-
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return false;
- return true;
-}
-
-// Parse ENTRY(ident)
-Entry *Parser::parseEntry() {
- assert(_tok._kind == Token::kw_entry && "Expected ENTRY!");
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
- if (_tok._kind != Token::identifier) {
- error(_tok, "expected identifier in ENTRY");
- return nullptr;
- }
- StringRef entryName(_tok._range);
- consumeToken();
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- return new (_alloc) Entry(*this, entryName);
-}
-
-// Parse SEARCH_DIR(ident)
-SearchDir *Parser::parseSearchDir() {
- assert(_tok._kind == Token::kw_search_dir && "Expected SEARCH_DIR!");
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
- if (_tok._kind != Token::identifier) {
- error(_tok, "expected identifier in SEARCH_DIR");
- return nullptr;
- }
- StringRef searchPath(_tok._range);
- consumeToken();
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- return new (_alloc) SearchDir(*this, searchPath);
-}
-
-const SymbolAssignment *Parser::parseSymbolAssignment() {
- assert((_tok._kind == Token::identifier || _tok._kind == Token::kw_hidden ||
- _tok._kind == Token::kw_provide ||
- _tok._kind == Token::kw_provide_hidden) &&
- "Expected identifier!");
- SymbolAssignment::AssignmentVisibility visibility = SymbolAssignment::Default;
- SymbolAssignment::AssignmentKind kind;
- int numParen = 0;
-
- switch (_tok._kind) {
- case Token::kw_hidden:
- visibility = SymbolAssignment::Hidden;
- ++numParen;
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
- break;
- case Token::kw_provide:
- visibility = SymbolAssignment::Provide;
- ++numParen;
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
- break;
- case Token::kw_provide_hidden:
- visibility = SymbolAssignment::ProvideHidden;
- ++numParen;
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
- break;
- default:
- break;
- }
-
- StringRef name = _tok._range;
- consumeToken();
-
- // Parse assignment operator (=, +=, -= etc.)
- switch (_tok._kind) {
- case Token::equal:
- kind = SymbolAssignment::Simple;
- break;
- case Token::plusequal:
- kind = SymbolAssignment::Sum;
- break;
- case Token::minusequal:
- kind = SymbolAssignment::Sub;
- break;
- case Token::starequal:
- kind = SymbolAssignment::Mul;
- break;
- case Token::slashequal:
- kind = SymbolAssignment::Div;
- break;
- case Token::ampequal:
- kind = SymbolAssignment::And;
- break;
- case Token::pipeequal:
- kind = SymbolAssignment::Or;
- break;
- case Token::lesslessequal:
- kind = SymbolAssignment::Shl;
- break;
- case Token::greatergreaterequal:
- kind = SymbolAssignment::Shr;
- break;
- default:
- error(_tok, "unexpected token");
- return nullptr;
- }
-
- consumeToken();
-
- const Expression *expr = nullptr;
- switch (_tok._kind) {
- case Token::number:
- case Token::kw_align:
- case Token::identifier:
- case Token::l_paren:
- expr = parseExpression();
- if (!expr)
- return nullptr;
- break;
- default:
- error(_tok, "unexpected token while parsing assignment value.");
- return nullptr;
- }
-
- for (int i = 0; i < numParen; ++i)
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
-
- return new (_alloc) SymbolAssignment(*this, name, expr, kind, visibility);
-}
-
-llvm::ErrorOr<InputSectionsCmd::VectorTy> Parser::parseExcludeFile() {
- assert(_tok._kind == Token::kw_exclude_file && "Expected EXCLUDE_FILE!");
- InputSectionsCmd::VectorTy res;
- consumeToken();
-
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return llvm::ErrorOr<InputSectionsCmd::VectorTy>(
- make_error_code(llvm::errc::io_error));
-
- while (_tok._kind == Token::identifier) {
- res.push_back(new (_alloc) InputSectionName(*this, _tok._range, true));
- consumeToken();
- }
-
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return llvm::ErrorOr<InputSectionsCmd::VectorTy>(
- make_error_code(llvm::errc::io_error));
- return llvm::ErrorOr<InputSectionsCmd::VectorTy>(std::move(res));
-}
-
-int Parser::parseSortDirectives(WildcardSortMode &sortMode) {
- int numParsedDirectives = 0;
- sortMode = WildcardSortMode::NA;
-
- if (_tok._kind == Token::kw_sort_by_name) {
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return -1;
- ++numParsedDirectives;
- sortMode = WildcardSortMode::ByName;
- }
-
- if (_tok._kind == Token::kw_sort_by_init_priority) {
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return -1;
- ++numParsedDirectives;
- sortMode = WildcardSortMode::ByInitPriority;
- }
-
- if (_tok._kind == Token::kw_sort_by_alignment) {
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return -1;
- ++numParsedDirectives;
- if (sortMode != WildcardSortMode::ByName)
- sortMode = WildcardSortMode::ByAlignment;
- else
- sortMode = WildcardSortMode::ByNameAndAlignment;
- }
-
- if (numParsedDirectives < 2 && _tok._kind == Token::kw_sort_by_name) {
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return -1;
- ++numParsedDirectives;
- if (sortMode == WildcardSortMode::ByAlignment)
- sortMode = WildcardSortMode::ByAlignmentAndName;
- }
-
- if (numParsedDirectives < 2 && _tok._kind == Token::kw_sort_by_alignment) {
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return -1;
- ++numParsedDirectives;
- }
-
- if (numParsedDirectives == 0 && _tok._kind == Token::kw_sort_none) {
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return -1;
- ++numParsedDirectives;
- sortMode = WildcardSortMode::None;
- }
-
- return numParsedDirectives;
-}
-
-const InputSection *Parser::parseSortedInputSections() {
- assert((_tok._kind == Token::kw_sort_by_name ||
- _tok._kind == Token::kw_sort_by_alignment ||
- _tok._kind == Token::kw_sort_by_init_priority ||
- _tok._kind == Token::kw_sort_none) &&
- "Expected SORT directives!");
-
- WildcardSortMode sortMode = WildcardSortMode::NA;
- int numParen = parseSortDirectives(sortMode);
- if (numParen == -1)
- return nullptr;
-
- SmallVector<const InputSection *, 8> inputSections;
-
- while (_tok._kind == Token::identifier) {
- inputSections.push_back(new (_alloc)
- InputSectionName(*this, _tok._range, false));
- consumeToken();
- }
-
- // Eat "numParen" rparens
- for (int i = 0, e = numParen; i != e; ++i)
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
-
- return new (_alloc) InputSectionSortedGroup(*this, sortMode, inputSections);
-}
-
-const InputSectionsCmd *Parser::parseInputSectionsCmd() {
- assert((_tok._kind == Token::identifier || _tok._kind == Token::colon ||
- _tok._kind == Token::star || _tok._kind == Token::kw_keep ||
- _tok._kind == Token::kw_sort_by_name ||
- _tok._kind == Token::kw_sort_by_alignment ||
- _tok._kind == Token::kw_sort_by_init_priority ||
- _tok._kind == Token::kw_sort_none) &&
- "Expected input section first tokens!");
- int numParen = 1;
- bool keep = false;
- WildcardSortMode fileSortMode = WildcardSortMode::NA;
- WildcardSortMode archiveSortMode = WildcardSortMode::NA;
- StringRef memberName;
- StringRef archiveName;
-
- if (_tok._kind == Token::kw_keep) {
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
- ++numParen;
- keep = true;
- }
-
- // Input name
- if (_tok._kind != Token::colon) {
- int numParen = parseSortDirectives(fileSortMode);
- if (numParen == -1)
- return nullptr;
- memberName = _tok._range;
- consumeToken();
- if (numParen) {
- while (numParen--)
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- }
- }
- if (_tok._kind == Token::colon) {
- consumeToken();
- if (_tok._kind == Token::identifier ||
- _tok._kind == Token::kw_sort_by_name ||
- _tok._kind == Token::kw_sort_by_alignment ||
- _tok._kind == Token::kw_sort_by_init_priority ||
- _tok._kind == Token::kw_sort_none) {
- int numParen = parseSortDirectives(archiveSortMode);
- if (numParen == -1)
- return nullptr;
- archiveName = _tok._range;
- consumeToken();
- for (int i = 0; i != numParen; ++i)
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- }
- }
-
- SmallVector<const InputSection *, 8> inputSections;
-
- if (_tok._kind != Token::l_paren)
- return new (_alloc)
- InputSectionsCmd(*this, memberName, archiveName, keep, fileSortMode,
- archiveSortMode, inputSections);
- consumeToken();
-
- while (_tok._kind == Token::identifier ||
- _tok._kind == Token::kw_exclude_file ||
- _tok._kind == Token::kw_sort_by_name ||
- _tok._kind == Token::kw_sort_by_alignment ||
- _tok._kind == Token::kw_sort_by_init_priority ||
- _tok._kind == Token::kw_sort_none) {
- switch (_tok._kind) {
- case Token::kw_exclude_file: {
- auto vec = parseExcludeFile();
- if (vec.getError())
- return nullptr;
- inputSections.insert(inputSections.end(), vec->begin(), vec->end());
- break;
- }
- case Token::star:
- case Token::identifier: {
- inputSections.push_back(new (_alloc)
- InputSectionName(*this, _tok._range, false));
- consumeToken();
- break;
- }
- case Token::kw_sort_by_name:
- case Token::kw_sort_by_alignment:
- case Token::kw_sort_by_init_priority:
- case Token::kw_sort_none: {
- const InputSection *group = parseSortedInputSections();
- if (!group)
- return nullptr;
- inputSections.push_back(group);
- break;
- }
- default:
- llvm_unreachable("Unknown token");
- }
- }
-
- for (int i = 0; i < numParen; ++i)
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- return new (_alloc)
- InputSectionsCmd(*this, memberName, archiveName, keep, fileSortMode,
- archiveSortMode, inputSections);
-}
-
-const FillCmd *Parser::parseFillCmd() {
- assert(_tok._kind == Token::kw_fill && "Expected FILL!");
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
-
- SmallVector<uint8_t, 8> storage;
-
- // If the expression is just a number, it's arbitrary length.
- if (_tok._kind == Token::number && peek()._kind == Token::r_paren) {
- if (_tok._range.size() > 2 && _tok._range.startswith("0x")) {
- StringRef num = _tok._range.substr(2);
- for (char c : num) {
- unsigned nibble = llvm::hexDigitValue(c);
- if (nibble == -1u)
- goto not_simple_hex;
- storage.push_back(nibble);
- }
-
- if (storage.size() % 2 != 0)
- storage.insert(storage.begin(), 0);
-
- // Collapse nibbles.
- for (std::size_t i = 0, e = storage.size() / 2; i != e; ++i)
- storage[i] = (storage[i * 2] << 4) + storage[(i * 2) + 1];
-
- storage.resize(storage.size() / 2);
- }
- }
-not_simple_hex:
-
- const Expression *expr = parseExpression();
- if (!expr)
- return nullptr;
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
-
- return new(getAllocator()) FillCmd(*this, storage);
-}
-
-const OutputSectionDescription *Parser::parseOutputSectionDescription() {
- assert((_tok._kind == Token::kw_discard || _tok._kind == Token::identifier) &&
- "Expected /DISCARD/ or identifier!");
- StringRef sectionName;
- const Expression *address = nullptr;
- const Expression *align = nullptr;
- const Expression *subAlign = nullptr;
- const Expression *at = nullptr;
- const Expression *fillExpr = nullptr;
- StringRef fillStream;
- bool alignWithInput = false;
- bool discard = false;
- OutputSectionDescription::Constraint constraint =
- OutputSectionDescription::C_None;
- SmallVector<const Command *, 8> outputSectionCommands;
-
- if (_tok._kind == Token::kw_discard)
- discard = true;
- else
- sectionName = _tok._range;
- consumeToken();
-
- if (_tok._kind == Token::number || _tok._kind == Token::identifier ||
- _tok._kind == Token::kw_align || _tok._kind == Token::l_paren) {
- address = parseExpression();
- if (!address)
- return nullptr;
- }
-
- if (!expectAndConsume(Token::colon, "expected :"))
- return nullptr;
-
- if (_tok._kind == Token::kw_at) {
- consumeToken();
- at = parseExpression();
- if (!at)
- return nullptr;
- }
-
- if (_tok._kind == Token::kw_align) {
- consumeToken();
- align = parseExpression();
- if (!align)
- return nullptr;
- }
-
- if (_tok._kind == Token::kw_align_with_input) {
- consumeToken();
- alignWithInput = true;
- }
-
- if (_tok._kind == Token::kw_subalign) {
- consumeToken();
- subAlign = parseExpression();
- if (!subAlign)
- return nullptr;
- }
-
- if (_tok._kind == Token::kw_only_if_ro) {
- consumeToken();
- constraint = OutputSectionDescription::C_OnlyIfRO;
- } else if (_tok._kind == Token::kw_only_if_rw) {
- consumeToken();
- constraint = OutputSectionDescription::C_OnlyIfRW;
- }
-
- if (!expectAndConsume(Token::l_brace, "expected {"))
- return nullptr;
-
- // Parse zero or more output-section-commands
- while (_tok._kind != Token::r_brace) {
- switch (_tok._kind) {
- case Token::semicolon:
- consumeToken();
- break;
- case Token::identifier:
- switch (peek()._kind) {
- case Token::equal:
- case Token::plusequal:
- case Token::minusequal:
- case Token::starequal:
- case Token::slashequal:
- case Token::ampequal:
- case Token::pipeequal:
- case Token::lesslessequal:
- case Token::greatergreaterequal:
- if (const Command *cmd = parseSymbolAssignment())
- outputSectionCommands.push_back(cmd);
- else
- return nullptr;
- break;
- default:
- if (const Command *cmd = parseInputSectionsCmd())
- outputSectionCommands.push_back(cmd);
- else
- return nullptr;
- break;
- }
- break;
- case Token::kw_fill:
- if (const Command *cmd = parseFillCmd())
- outputSectionCommands.push_back(cmd);
- else
- return nullptr;
- break;
- case Token::kw_keep:
- case Token::star:
- case Token::colon:
- case Token::kw_sort_by_name:
- case Token::kw_sort_by_alignment:
- case Token::kw_sort_by_init_priority:
- case Token::kw_sort_none:
- if (const Command *cmd = parseInputSectionsCmd())
- outputSectionCommands.push_back(cmd);
- else
- return nullptr;
- break;
- case Token::kw_hidden:
- case Token::kw_provide:
- case Token::kw_provide_hidden:
- if (const Command *cmd = parseSymbolAssignment())
- outputSectionCommands.push_back(cmd);
- else
- return nullptr;
- break;
- default:
- error(_tok, "expected symbol assignment or input file name.");
- return nullptr;
- }
- }
-
- if (!expectAndConsume(Token::r_brace, "expected }"))
- return nullptr;
-
- SmallVector<StringRef, 2> phdrs;
- while (_tok._kind == Token::colon) {
- consumeToken();
- if (_tok._kind != Token::identifier) {
- error(_tok, "expected program header name");
- return nullptr;
- }
- phdrs.push_back(_tok._range);
- consumeToken();
- }
-
- if (_tok._kind == Token::equal) {
- consumeToken();
- if (_tok._kind != Token::number || !_tok._range.startswith_lower("0x")) {
- fillExpr = parseExpression();
- if (!fillExpr)
- return nullptr;
- } else {
- std::string strBuf;
- if (isExpressionOperator(peek()) ||
- !parseHexToByteStream(_tok._range.drop_front(2), strBuf)) {
- fillExpr = parseExpression();
- if(!fillExpr)
- return nullptr;
- } else {
- char *rawBuf = (char *) _alloc.Allocate(strBuf.size(), 1);
- memcpy(rawBuf, strBuf.c_str(), strBuf.size());
- fillStream = StringRef(rawBuf, strBuf.size());
- consumeToken();
- }
- }
- }
-
- return new (_alloc) OutputSectionDescription(
- *this, sectionName, address, align, subAlign, at, fillExpr, fillStream,
- alignWithInput, discard, constraint, outputSectionCommands, phdrs);
-}
-
-const Overlay *Parser::parseOverlay() {
- assert(_tok._kind == Token::kw_overlay && "Expected OVERLAY!");
- error(_tok, "Overlay description is not yet supported.");
- return nullptr;
-}
-
-const PHDR *Parser::parsePHDR() {
- assert(_tok._kind == Token::identifier && "Expected identifier!");
-
- StringRef name = _tok._range;
- consumeToken();
-
- uint64_t type;
-
- switch (_tok._kind) {
- case Token::identifier:
- case Token::number:
- case Token::l_paren: {
- const Expression *expr = parseExpression();
- if (!expr)
- return nullptr;
- Expression::SymbolTableTy PHDRTypes;
-#define PHDR_INSERT(x) PHDRTypes.insert(std::make_pair(#x, llvm::ELF::x))
- PHDR_INSERT(PT_NULL);
- PHDR_INSERT(PT_LOAD);
- PHDR_INSERT(PT_DYNAMIC);
- PHDR_INSERT(PT_INTERP);
- PHDR_INSERT(PT_NOTE);
- PHDR_INSERT(PT_SHLIB);
- PHDR_INSERT(PT_PHDR);
- PHDR_INSERT(PT_TLS);
- PHDR_INSERT(PT_LOOS);
- PHDR_INSERT(PT_GNU_EH_FRAME);
- PHDR_INSERT(PT_GNU_STACK);
- PHDR_INSERT(PT_GNU_RELRO);
- PHDR_INSERT(PT_SUNW_EH_FRAME);
- PHDR_INSERT(PT_SUNW_UNWIND);
- PHDR_INSERT(PT_HIOS);
- PHDR_INSERT(PT_LOPROC);
- PHDR_INSERT(PT_ARM_ARCHEXT);
- PHDR_INSERT(PT_ARM_EXIDX);
- PHDR_INSERT(PT_ARM_UNWIND);
- PHDR_INSERT(PT_MIPS_REGINFO);
- PHDR_INSERT(PT_MIPS_RTPROC);
- PHDR_INSERT(PT_MIPS_OPTIONS);
- PHDR_INSERT(PT_MIPS_ABIFLAGS);
- PHDR_INSERT(PT_HIPROC);
-#undef PHDR_INSERT
- auto t = expr->evalExpr(PHDRTypes);
- if (t == LinkerScriptReaderError::unknown_symbol_in_expr) {
- error(_tok, "Unknown type");
- return nullptr;
- }
- if (!t)
- return nullptr;
- type = *t;
- break;
- }
- default:
- error(_tok, "expected identifier or expression");
- return nullptr;
- }
-
- uint64_t flags = 0;
- const Expression *flagsExpr = nullptr;
- bool includeFileHdr = false;
- bool includePHDRs = false;
-
- while (_tok._kind != Token::semicolon) {
- switch (_tok._kind) {
- case Token::kw_filehdr:
- if (includeFileHdr) {
- error(_tok, "Duplicate FILEHDR attribute");
- return nullptr;
- }
- includeFileHdr = true;
- consumeToken();
- break;
- case Token::kw_phdrs:
- if (includePHDRs) {
- error(_tok, "Duplicate PHDRS attribute");
- return nullptr;
- }
- includePHDRs = true;
- consumeToken();
- break;
- case Token::kw_flags: {
- if (flagsExpr) {
- error(_tok, "Duplicate FLAGS attribute");
- return nullptr;
- }
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "Expected ("))
- return nullptr;
- flagsExpr = parseExpression();
- if (!flagsExpr)
- return nullptr;
- auto f = flagsExpr->evalExpr();
- if (!f)
- return nullptr;
- flags = *f;
- if (!expectAndConsume(Token::r_paren, "Expected )"))
- return nullptr;
- } break;
- default:
- error(_tok, "Unexpected token");
- return nullptr;
- }
- }
-
- if (!expectAndConsume(Token::semicolon, "Expected ;"))
- return nullptr;
-
- return new (getAllocator())
- PHDR(name, type, includeFileHdr, includePHDRs, nullptr, flags);
-}
-
-PHDRS *Parser::parsePHDRS() {
- assert(_tok._kind == Token::kw_phdrs && "Expected PHDRS!");
- consumeToken();
- if (!expectAndConsume(Token::l_brace, "expected {"))
- return nullptr;
-
- SmallVector<const PHDR *, 8> phdrs;
-
- while (true) {
- if (_tok._kind == Token::identifier) {
- const PHDR *phdr = parsePHDR();
- if (!phdr)
- return nullptr;
- phdrs.push_back(phdr);
- } else
- break;
- }
-
- if (!expectAndConsume(Token::r_brace, "expected }"))
- return nullptr;
-
- return new (getAllocator()) PHDRS(*this, phdrs);
-}
-
-Sections *Parser::parseSections() {
- assert(_tok._kind == Token::kw_sections && "Expected SECTIONS!");
- consumeToken();
- if (!expectAndConsume(Token::l_brace, "expected {"))
- return nullptr;
- SmallVector<const Command *, 8> sectionsCommands;
-
- bool unrecognizedToken = false;
- // Parse zero or more sections-commands
- while (!unrecognizedToken) {
- switch (_tok._kind) {
- case Token::semicolon:
- consumeToken();
- break;
-
- case Token::identifier:
- switch (peek()._kind) {
- case Token::equal:
- case Token::plusequal:
- case Token::minusequal:
- case Token::starequal:
- case Token::slashequal:
- case Token::ampequal:
- case Token::pipeequal:
- case Token::lesslessequal:
- case Token::greatergreaterequal:
- if (const Command *cmd = parseSymbolAssignment())
- sectionsCommands.push_back(cmd);
- else
- return nullptr;
- break;
- default:
- if (const Command *cmd = parseOutputSectionDescription())
- sectionsCommands.push_back(cmd);
- else
- return nullptr;
- break;
- }
- break;
-
- case Token::kw_discard:
- case Token::star:
- if (const Command *cmd = parseOutputSectionDescription())
- sectionsCommands.push_back(cmd);
- else
- return nullptr;
- break;
-
- case Token::kw_entry:
- if (const Command *cmd = parseEntry())
- sectionsCommands.push_back(cmd);
- else
- return nullptr;
- break;
-
- case Token::kw_hidden:
- case Token::kw_provide:
- case Token::kw_provide_hidden:
- if (const Command *cmd = parseSymbolAssignment())
- sectionsCommands.push_back(cmd);
- else
- return nullptr;
- break;
-
- case Token::kw_overlay:
- if (const Command *cmd = parseOverlay())
- sectionsCommands.push_back(cmd);
- else
- return nullptr;
- break;
-
- default:
- unrecognizedToken = true;
- break;
- }
- }
-
- if (!expectAndConsume(
- Token::r_brace,
- "expected symbol assignment, entry, overlay or output section name."))
- return nullptr;
-
- return new (_alloc) Sections(*this, sectionsCommands);
-}
-
-Memory *Parser::parseMemory() {
- assert(_tok._kind == Token::kw_memory && "Expected MEMORY!");
- consumeToken();
- if (!expectAndConsume(Token::l_brace, "expected {"))
- return nullptr;
- SmallVector<const MemoryBlock *, 8> blocks;
-
- bool unrecognizedToken = false;
- // Parse zero or more memory block descriptors.
- while (!unrecognizedToken) {
- if (_tok._kind == Token::identifier) {
- StringRef name;
- StringRef attrs;
- const Expression *origin = nullptr;
- const Expression *length = nullptr;
-
- name = _tok._range;
- consumeToken();
-
- // Parse optional memory region attributes.
- if (_tok._kind == Token::l_paren) {
- consumeToken();
-
- if (_tok._kind != Token::identifier) {
- error(_tok, "Expected memory attribute string.");
- return nullptr;
- }
- attrs = _tok._range;
- consumeToken();
-
- if (!expectAndConsume(Token::r_paren, "expected )"))
- return nullptr;
- }
-
- if (!expectAndConsume(Token::colon, "expected :"))
- return nullptr;
-
- // Parse the ORIGIN (base address of memory block).
- if (!expectAndConsume(Token::kw_origin, "expected ORIGIN"))
- return nullptr;
-
- if (!expectAndConsume(Token::equal, "expected ="))
- return nullptr;
-
- origin = parseExpression();
- if (!origin)
- return nullptr;
-
- if (!expectAndConsume(Token::comma, "expected ,"))
- return nullptr;
-
- // Parse the LENGTH (length of memory block).
- if (!expectAndConsume(Token::kw_length, "expected LENGTH"))
- return nullptr;
-
- if (!expectAndConsume(Token::equal, "expected ="))
- return nullptr;
-
- length = parseExpression();
- if (!length)
- return nullptr;
-
- auto *block = new (_alloc) MemoryBlock(name, attrs, origin, length);
- blocks.push_back(block);
- } else {
- unrecognizedToken = true;
- }
- }
- if (!expectAndConsume(
- Token::r_brace,
- "expected memory block definition."))
- return nullptr;
-
- return new (_alloc) Memory(*this, blocks);
-}
-
-Extern *Parser::parseExtern() {
- assert(_tok._kind == Token::kw_extern && "Expected EXTERN!");
- consumeToken();
- if (!expectAndConsume(Token::l_paren, "expected ("))
- return nullptr;
-
- // Parse one or more symbols.
- SmallVector<StringRef, 8> symbols;
- if (_tok._kind != Token::identifier) {
- error(_tok, "expected one or more symbols in EXTERN.");
- return nullptr;
- }
- symbols.push_back(_tok._range);
- consumeToken();
- while (_tok._kind == Token::identifier) {
- symbols.push_back(_tok._range);
- consumeToken();
- }
-
- if (!expectAndConsume(Token::r_paren, "expected symbol in EXTERN."))
- return nullptr;
-
- return new (_alloc) Extern(*this, symbols);
-}
-
-// Sema member functions
-Sema::Sema() : _programPHDR(nullptr) {}
-
-std::error_code Sema::perform() {
- llvm::StringMap<const PHDR *> phdrs;
-
- for (auto &parser : _scripts) {
- for (const Command *c : parser->get()->_commands) {
- if (const auto *sec = dyn_cast<Sections>(c)) {
- linearizeAST(sec);
- } else if (const auto *ph = dyn_cast<PHDRS>(c)) {
- if (auto ec = collectPHDRs(ph, phdrs))
- return ec;
- }
- }
- }
- return buildSectionToPHDR(phdrs);
-}
-
-bool Sema::less(const SectionKey &lhs, const SectionKey &rhs) const {
- int a = getLayoutOrder(lhs, true);
- int b = getLayoutOrder(rhs, true);
-
- if (a != b) {
- if (a < 0)
- return false;
- if (b < 0)
- return true;
- return a < b;
- }
-
- // If both sections are not mapped anywhere, they have the same order
- if (a < 0)
- return false;
-
- // If both sections fall into the same layout order, we need to find their
- // relative position as written in the (InputSectionsCmd).
- return localCompare(a, lhs, rhs);
-}
-
-StringRef Sema::getOutputSection(const SectionKey &key) const {
- int layoutOrder = getLayoutOrder(key, true);
- if (layoutOrder < 0)
- return StringRef();
-
- for (int i = layoutOrder - 1; i >= 0; --i) {
- if (!isa<OutputSectionDescription>(_layoutCommands[i]))
- continue;
-
- const OutputSectionDescription *out =
- dyn_cast<OutputSectionDescription>(_layoutCommands[i]);
- return out->name();
- }
-
- return StringRef();
-}
-
-std::vector<const SymbolAssignment *>
-Sema::getExprs(const SectionKey &key) {
- int layoutOrder = getLayoutOrder(key, false);
- auto ans = std::vector<const SymbolAssignment *>();
-
- if (layoutOrder < 0 || _deliveredExprs.count(layoutOrder) > 0)
- return ans;
-
- for (int i = layoutOrder - 1; i >= 0; --i) {
- if (isa<InputSection>(_layoutCommands[i]))
- break;
- if (auto assgn = dyn_cast<SymbolAssignment>(_layoutCommands[i]))
- ans.push_back(assgn);
- }
-
- // Reverse this order so we evaluate the expressions in the original order
- // of the linker script
- std::reverse(ans.begin(), ans.end());
-
- // Mark this layout number as delivered
- _deliveredExprs.insert(layoutOrder);
- return ans;
-}
-
-std::error_code Sema::evalExpr(const SymbolAssignment *assgn,
- uint64_t &curPos) {
- _symbolTable[StringRef(".")] = curPos;
-
- auto ans = assgn->expr()->evalExpr(_symbolTable);
- if (ans.getError())
- return ans.getError();
- uint64_t result = *ans;
-
- if (assgn->symbol() == ".") {
- curPos = result;
- return std::error_code();
- }
-
- _symbolTable[assgn->symbol()] = result;
- return std::error_code();
-}
-
-const llvm::StringSet<> &Sema::getScriptDefinedSymbols() const {
- // Do we have cached results?
- if (!_definedSymbols.empty())
- return _definedSymbols;
-
- // Populate our defined set and return it
- for (auto cmd : _layoutCommands)
- if (auto sa = dyn_cast<SymbolAssignment>(cmd)) {
- StringRef symbol = sa->symbol();
- if (!symbol.empty() && symbol != ".")
- _definedSymbols.insert(symbol);
- }
-
- return _definedSymbols;
-}
-
-uint64_t Sema::getLinkerScriptExprValue(StringRef name) const {
- auto it = _symbolTable.find(name);
- assert (it != _symbolTable.end() && "Invalid symbol name!");
- return it->second;
-}
-
-bool Sema::hasPHDRs() const { return !_sectionToPHDR.empty(); }
-
-std::vector<const PHDR *> Sema::getPHDRsForOutputSection(StringRef name) const {
- auto vec = _sectionToPHDR.lookup(name);
- return std::vector<const PHDR *>(std::begin(vec), std::end(vec));
-}
-
-const PHDR *Sema::getProgramPHDR() const { return _programPHDR; }
-
-void Sema::dump() const {
- raw_ostream &os = llvm::outs();
- os << "Linker script semantics dump\n";
- int num = 0;
- for (auto &parser : _scripts) {
- os << "Dumping script #" << ++num << ":\n";
- parser->get()->dump(os);
- os << "\n";
- }
- os << "Dumping rule ids:\n";
- for (unsigned i = 0; i < _layoutCommands.size(); ++i) {
- os << "LayoutOrder " << i << ":\n";
- _layoutCommands[i]->dump(os);
- os << "\n\n";
- }
-}
-
-/// Given a string "pattern" with wildcard characters, return true if it
-/// matches "name". This function is useful when checking if a given name
-/// pattern written in the linker script, i.e. ".text*", should match
-/// ".text.anytext".
-static bool wildcardMatch(StringRef pattern, StringRef name) {
- auto i = name.begin();
-
- // Check if each char in pattern also appears in our input name, handling
- // special wildcard characters.
- for (auto j = pattern.begin(), e = pattern.end(); j != e; ++j) {
- if (i == name.end())
- return false;
-
- switch (*j) {
- case '*':
- while (!wildcardMatch(pattern.drop_front(j - pattern.begin() + 1),
- name.drop_front(i - name.begin()))) {
- if (i == name.end())
- return false;
- ++i;
- }
- break;
- case '?':
- // Matches any character
- ++i;
- break;
- case '[': {
- // Matches a range of characters specified between brackets
- size_t end = pattern.find(']', j - pattern.begin());
- if (end == pattern.size())
- return false;
-
- StringRef chars = pattern.slice(j - pattern.begin(), end);
- if (chars.find(i) == StringRef::npos)
- return false;
-
- j = pattern.begin() + end;
- ++i;
- break;
- }
- case '\\':
- ++j;
- if (*j != *i)
- return false;
- ++i;
- break;
- default:
- // No wildcard character means we must match exactly the same char
- if (*j != *i)
- return false;
- ++i;
- break;
- }
- }
-
- // If our pattern has't consumed the entire string, it is not a match
- return i == name.end();
-}
-
-int Sema::matchSectionName(int id, const SectionKey &key) const {
- const InputSectionsCmd *cmd = dyn_cast<InputSectionsCmd>(_layoutCommands[id]);
-
- if (!cmd || !wildcardMatch(cmd->archiveName(), key.archivePath))
- return -1;
-
- while ((size_t)++id < _layoutCommands.size() &&
- (isa<InputSection>(_layoutCommands[id]))) {
- if (isa<InputSectionSortedGroup>(_layoutCommands[id]))
- continue;
-
- const InputSectionName *in =
- dyn_cast<InputSectionName>(_layoutCommands[id]);
- if (wildcardMatch(in->name(), key.sectionName))
- return id;
- }
- return -1;
-}
-
-int Sema::getLayoutOrder(const SectionKey &key, bool coarse) const {
- // First check if we already answered this layout question
- if (coarse) {
- auto entry = _cacheSectionOrder.find(key);
- if (entry != _cacheSectionOrder.end())
- return entry->second;
- } else {
- auto entry = _cacheExpressionOrder.find(key);
- if (entry != _cacheExpressionOrder.end())
- return entry->second;
- }
-
- // Try to match exact file name
- auto range = _memberToLayoutOrder.equal_range(key.memberPath);
- for (auto I = range.first, E = range.second; I != E; ++I) {
- int order = I->second;
- int exprOrder = -1;
-
- if ((exprOrder = matchSectionName(order, key)) >= 0) {
- if (coarse) {
- _cacheSectionOrder.insert(std::make_pair(key, order));
- return order;
- }
- _cacheExpressionOrder.insert(std::make_pair(key, exprOrder));
- return exprOrder;
- }
- }
-
- // If we still couldn't find a rule for this input section, try to match
- // wildcards
- for (const auto &I : _memberNameWildcards) {
- if (!wildcardMatch(I.first, key.memberPath))
- continue;
- int order = I.second;
- int exprOrder = -1;
-
- if ((exprOrder = matchSectionName(order, key)) >= 0) {
- if (coarse) {
- _cacheSectionOrder.insert(std::make_pair(key, order));
- return order;
- }
- _cacheExpressionOrder.insert(std::make_pair(key, exprOrder));
- return exprOrder;
- }
- }
-
- _cacheSectionOrder.insert(std::make_pair(key, -1));
- _cacheExpressionOrder.insert(std::make_pair(key, -1));
- return -1;
-}
-
-static bool compareSortedNames(WildcardSortMode sortMode, StringRef lhs,
- StringRef rhs) {
- switch (sortMode) {
- case WildcardSortMode::None:
- case WildcardSortMode::NA:
- return false;
- case WildcardSortMode::ByAlignment:
- case WildcardSortMode::ByInitPriority:
- case WildcardSortMode::ByAlignmentAndName:
- assert(false && "Unimplemented sort order");
- break;
- case WildcardSortMode::ByName:
- return lhs.compare(rhs) < 0;
- case WildcardSortMode::ByNameAndAlignment:
- int compare = lhs.compare(rhs);
- if (compare != 0)
- return compare < 0;
- return compareSortedNames(WildcardSortMode::ByAlignment, lhs, rhs);
- }
- return false;
-}
-
-static bool sortedGroupContains(const InputSectionSortedGroup *cmd,
- const Sema::SectionKey &key) {
- for (const InputSection *child : *cmd) {
- if (auto i = dyn_cast<InputSectionName>(child)) {
- if (wildcardMatch(i->name(), key.sectionName))
- return true;
- continue;
- }
-
- auto *sortedGroup = dyn_cast<InputSectionSortedGroup>(child);
- assert(sortedGroup && "Expected InputSectionSortedGroup object");
-
- if (sortedGroupContains(sortedGroup, key))
- return true;
- }
-
- return false;
-}
-
-bool Sema::localCompare(int order, const SectionKey &lhs,
- const SectionKey &rhs) const {
- const InputSectionsCmd *cmd =
- dyn_cast<InputSectionsCmd>(_layoutCommands[order]);
-
- assert(cmd && "Invalid InputSectionsCmd index");
-
- if (lhs.archivePath != rhs.archivePath)
- return compareSortedNames(cmd->archiveSortMode(), lhs.archivePath,
- rhs.archivePath);
-
- if (lhs.memberPath != rhs.memberPath)
- return compareSortedNames(cmd->fileSortMode(), lhs.memberPath,
- rhs.memberPath);
-
- // Both sections come from the same exact same file and rule. Start walking
- // through input section names as written in the linker script and the
- // first one to match will have higher priority.
- for (const InputSection *inputSection : *cmd) {
- if (auto i = dyn_cast<InputSectionName>(inputSection)) {
- // If both match, return false (both have equal priority)
- // If rhs match, return false (rhs has higher priority)
- if (wildcardMatch(i->name(), rhs.sectionName))
- return false;
- // If lhs matches first, it has priority over rhs
- if (wildcardMatch(i->name(), lhs.sectionName))
- return true;
- continue;
- }
-
- // Handle sorted subgroups specially
- auto *sortedGroup = dyn_cast<InputSectionSortedGroup>(inputSection);
- assert(sortedGroup && "Expected InputSectionSortedGroup object");
-
- bool a = sortedGroupContains(sortedGroup, lhs);
- bool b = sortedGroupContains(sortedGroup, rhs);
- if (a && !b)
- return false;
- if (b && !a)
- return true;
- if (!a && !a)
- continue;
-
- return compareSortedNames(sortedGroup->sortMode(), lhs.sectionName,
- rhs.sectionName);
- }
-
- llvm_unreachable("");
- return false;
-}
-
-std::error_code Sema::collectPHDRs(const PHDRS *ph,
- llvm::StringMap<const PHDR *> &phdrs) {
- bool loadFound = false;
- for (auto *p : *ph) {
- phdrs[p->name()] = p;
-
- switch (p->type()) {
- case llvm::ELF::PT_PHDR:
- if (_programPHDR != nullptr)
- return LinkerScriptReaderError::extra_program_phdr;
- if (loadFound)
- return LinkerScriptReaderError::misplaced_program_phdr;
- if (!p->hasPHDRs())
- return LinkerScriptReaderError::program_phdr_wrong_phdrs;
- _programPHDR = p;
- break;
- case llvm::ELF::PT_LOAD:
- // Program header, if available, should have program header table
- // mapped in the first loadable segment.
- if (!loadFound && _programPHDR && !p->hasPHDRs())
- return LinkerScriptReaderError::program_phdr_wrong_phdrs;
- loadFound = true;
- break;
- }
- }
- return std::error_code();
-}
-
-std::error_code Sema::buildSectionToPHDR(llvm::StringMap<const PHDR *> &phdrs) {
- const bool noPhdrs = phdrs.empty();
-
- // Add NONE header to the map provided there's no user-defined
- // header with the same name.
- if (!phdrs.count(PHDR_NONE.name()))
- phdrs[PHDR_NONE.name()] = &PHDR_NONE;
-
- // Match output sections to available headers.
- llvm::SmallVector<const PHDR *, 2> phdrsCur, phdrsLast { &PHDR_NONE };
- for (const Command *cmd : _layoutCommands) {
- auto osd = dyn_cast<OutputSectionDescription>(cmd);
- if (!osd || osd->isDiscarded())
- continue;
-
- phdrsCur.clear();
- for (StringRef name : osd->PHDRs()) {
- auto it = phdrs.find(name);
- if (it == phdrs.end()) {
- return LinkerScriptReaderError::unknown_phdr_ids;
- }
- phdrsCur.push_back(it->second);
- }
-
- // If no headers and no errors - insert empty headers set.
- // If the current set of headers is empty, then use the last non-empty
- // set. Otherwise mark the current set to be the last non-empty set for
- // successors.
- if (noPhdrs)
- phdrsCur.clear();
- else if (phdrsCur.empty())
- phdrsCur = phdrsLast;
- else
- phdrsLast = phdrsCur;
-
- _sectionToPHDR[osd->name()] = phdrsCur;
- }
- return std::error_code();
-}
-
-static bool hasWildcard(StringRef name) {
- for (auto ch : name)
- if (ch == '*' || ch == '?' || ch == '[' || ch == '\\')
- return true;
- return false;
-}
-
-void Sema::linearizeAST(const InputSection *inputSection) {
- if (isa<InputSectionName>(inputSection)) {
- _layoutCommands.push_back(inputSection);
- return;
- }
-
- auto *sortedGroup = dyn_cast<InputSectionSortedGroup>(inputSection);
- assert(sortedGroup && "Expected InputSectionSortedGroup object");
-
- for (const InputSection *child : *sortedGroup) {
- linearizeAST(child);
- }
-}
-
-void Sema::linearizeAST(const InputSectionsCmd *inputSections) {
- StringRef memberName = inputSections->memberName();
- // Populate our maps for fast lookup of InputSectionsCmd
- if (hasWildcard(memberName))
- _memberNameWildcards.push_back(
- std::make_pair(memberName, (int)_layoutCommands.size()));
- else if (!memberName.empty())
- _memberToLayoutOrder.insert(
- std::make_pair(memberName.str(), (int)_layoutCommands.size()));
-
- _layoutCommands.push_back(inputSections);
- for (const InputSection *inputSection : *inputSections)
- linearizeAST(inputSection);
-}
-
-void Sema::linearizeAST(const Sections *sections) {
- for (const Command *sectionCommand : *sections) {
- if (isa<SymbolAssignment>(sectionCommand)) {
- _layoutCommands.push_back(sectionCommand);
- continue;
- }
-
- if (!isa<OutputSectionDescription>(sectionCommand))
- continue;
-
- _layoutCommands.push_back(sectionCommand);
- auto *outSection = dyn_cast<OutputSectionDescription>(sectionCommand);
-
- for (const Command *outSecCommand : *outSection) {
- if (isa<SymbolAssignment>(outSecCommand)) {
- _layoutCommands.push_back(outSecCommand);
- continue;
- }
-
- if (!isa<InputSectionsCmd>(outSecCommand))
- continue;
-
- linearizeAST(dyn_cast<InputSectionsCmd>(outSecCommand));
- }
- }
-}
-
-} // end namespace script
-} // end namespace lld
diff --git a/lib/ReaderWriter/MachO/ArchHandler.h b/lib/ReaderWriter/MachO/ArchHandler.h
index 120f5dfd4cd2..70a63bd1004b 100644
--- a/lib/ReaderWriter/MachO/ArchHandler.h
+++ b/lib/ReaderWriter/MachO/ArchHandler.h
@@ -7,18 +7,19 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
+#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
+
#include "Atoms.h"
#include "File.h"
#include "MachONormalizedFile.h"
#include "lld/Core/LLVM.h"
+#include "lld/Core/Error.h"
#include "lld/Core/Reference.h"
#include "lld/Core/Simple.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"
#include "llvm/ADT/Triple.h"
-#ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
-#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
-
namespace lld {
namespace mach_o {
@@ -78,6 +79,11 @@ public:
/// actually be used.
virtual uint32_t dwarfCompactUnwindType() = 0;
+ /// Reference from an __eh_frame CIE atom to its personality function it's
+ /// describing. Usually pointer-sized and PC-relative, but differs in whether
+ /// it needs to be in relocatable objects.
+ virtual Reference::KindValue unwindRefToPersonalityFunctionKind() = 0;
+
/// Reference from an __eh_frame FDE to the CIE it's based on.
virtual Reference::KindValue unwindRefToCIEKind() = 0;
@@ -92,6 +98,10 @@ public:
/// __eh_frame.
virtual Reference::KindValue unwindRefToEhFrameKind() = 0;
+ /// Returns a pointer sized reference kind. On 64-bit targets this will
+ /// likely be something like pointer64, and pointer32 on 32-bit targets.
+ virtual Reference::KindValue pointerKind() = 0;
+
virtual const Atom *fdeTargetFunction(const DefinedAtom *fde);
/// Used by normalizedFromAtoms() to know where to generated rebasing and
@@ -107,20 +117,20 @@ public:
/// Prototype for a helper function. Given a sectionIndex and address,
/// finds the atom and offset with that atom of that address.
- typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr,
+ typedef std::function<llvm::Error (uint32_t sectionIndex, uint64_t addr,
const lld::Atom **, Reference::Addend *)>
FindAtomBySectionAndAddress;
/// Prototype for a helper function. Given a symbolIndex, finds the atom
/// representing that symbol.
- typedef std::function<std::error_code (uint32_t symbolIndex,
+ typedef std::function<llvm::Error (uint32_t symbolIndex,
const lld::Atom **)> FindAtomBySymbolIndex;
/// Analyzes a relocation from a .o file and returns the info
/// (kind, target, addend) needed to instantiate a Reference.
/// Two helper functions are passed as parameters to find the target atom
/// given a symbol index or address.
- virtual std::error_code
+ virtual llvm::Error
getReferenceInfo(const normalized::Relocation &reloc,
const DefinedAtom *inAtom,
uint32_t offsetInAtom,
@@ -135,7 +145,7 @@ public:
/// (kind, target, addend) needed to instantiate a Reference.
/// Two helper functions are passed as parameters to find the target atom
/// given a symbol index or address.
- virtual std::error_code
+ virtual llvm::Error
getPairReferenceInfo(const normalized::Relocation &reloc1,
const normalized::Relocation &reloc2,
const DefinedAtom *inAtom,
@@ -169,7 +179,7 @@ public:
FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress,
uint64_t imageBaseAddress,
- uint8_t *atomContentBuffer) = 0;
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) = 0;
/// Used in -r mode to convert a Reference to a mach-o relocation.
virtual void appendSectionRelocations(const DefinedAtom &atom,
@@ -251,7 +261,10 @@ public:
ReferenceInfo stubHelperReferenceToImm;
ReferenceInfo stubHelperReferenceToHelperCommon;
+ DefinedAtom::ContentType stubHelperImageCacheContentType;
+
uint32_t stubHelperCommonSize;
+ uint8_t stubHelperCommonAlignment;
uint8_t stubHelperCommonBytes[36];
ReferenceInfo stubHelperCommonReferenceToCache;
OptionalRefInfo optStubHelperCommonReferenceToCache;
diff --git a/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
index 4e15a2d434c6..3286fe064535 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
@@ -51,6 +51,10 @@ public:
return invalid;
}
+ Reference::KindValue unwindRefToPersonalityFunctionKind() override {
+ return invalid;
+ }
+
Reference::KindValue unwindRefToCIEKind() override {
return invalid;
}
@@ -63,21 +67,25 @@ public:
return invalid;
}
+ Reference::KindValue pointerKind() override {
+ return invalid;
+ }
+
uint32_t dwarfCompactUnwindType() override {
// FIXME
return -1;
}
- std::error_code getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
- std::error_code
+ llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
+ const DefinedAtom *inAtom,
+ uint32_t offsetInAtom,
+ uint64_t fixupAddress, bool swap,
+ FindAtomBySectionAndAddress atomFromAddress,
+ FindAtomBySymbolIndex atomFromSymbolIndex,
+ Reference::KindValue *kind,
+ const lld::Atom **target,
+ Reference::Addend *addend) override;
+ llvm::Error
getPairReferenceInfo(const normalized::Relocation &reloc1,
const normalized::Relocation &reloc2,
const DefinedAtom *inAtom,
@@ -93,7 +101,7 @@ public:
FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress,
uint64_t imageBaseAddress,
- uint8_t *atomContentBuffer) override;
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
void appendSectionRelocations(const DefinedAtom &atom,
uint64_t atomSectionOffset,
@@ -256,8 +264,13 @@ const ArchHandler::StubInfo ArchHandler_arm::_sStubInfoArmPIC = {
{ Reference::KindArch::ARM, lazyImmediateLocation, 8, 0 },
{ Reference::KindArch::ARM, arm_b24, 4, 0 },
+ // Stub helper image cache content type
+ DefinedAtom::typeGOT,
+
// Stub Helper-Common size and code
36,
+ // Stub helper alignment
+ 2,
{ // push lazy-info-offset
0x04, 0xC0, 0x2D, 0xE5, // str ip, [sp, #-4]!
// push address of dyld_mageLoaderCache
@@ -505,13 +518,12 @@ uint32_t ArchHandler_arm::clearThumbBit(uint32_t value, const Atom *target) {
return value;
}
-std::error_code ArchHandler_arm::getReferenceInfo(
+llvm::Error ArchHandler_arm::getReferenceInfo(
const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
uint64_t fixupAddress, bool isBig,
FindAtomBySectionAndAddress atomFromAddress,
FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
const lld::Atom **target, Reference::Addend *addend) {
- typedef std::error_code E;
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
uint64_t targetAddress;
uint32_t instruction = *(const ulittle32_t *)fixupContent;
@@ -523,12 +535,12 @@ std::error_code ArchHandler_arm::getReferenceInfo(
*kind = thumb_b22;
else
*kind = thumb_bl22;
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
// Instruction contains branch to addend.
displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
*addend = fixupAddress + 4 + displacement;
- return std::error_code();
+ return llvm::Error();
case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
// ex: bl _foo (and _foo is defined)
if ((instruction & 0xD000F800) == 0x9000F000)
@@ -546,12 +558,12 @@ std::error_code ArchHandler_arm::getReferenceInfo(
*kind = thumb_bl22;
displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
targetAddress = fixupAddress + 4 + displacement;
- if (E ec = atomFromAddress(0, reloc.value, target, addend))
+ if (auto ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
// reloc.value is target atom's address. Instruction contains branch
// to atom+addend.
*addend += (targetAddress - reloc.value);
- return std::error_code();
+ return llvm::Error();
case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
// ex: bl _foo (and _foo is undefined)
if (((instruction & 0x0F000000) == 0x0A000000)
@@ -559,12 +571,12 @@ std::error_code ArchHandler_arm::getReferenceInfo(
*kind = arm_b24;
else
*kind = arm_bl24;
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
// Instruction contains branch to addend.
displacement = getDisplacementFromArmBranch(instruction);
*addend = fixupAddress + 8 + displacement;
- return std::error_code();
+ return llvm::Error();
case ARM_RELOC_BR24 | rPcRel | rLength4:
// ex: bl _foo (and _foo is defined)
if (((instruction & 0x0F000000) == 0x0A000000)
@@ -584,40 +596,40 @@ std::error_code ArchHandler_arm::getReferenceInfo(
*kind = arm_bl24;
displacement = getDisplacementFromArmBranch(instruction);
targetAddress = fixupAddress + 8 + displacement;
- if (E ec = atomFromAddress(0, reloc.value, target, addend))
+ if (auto ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
// reloc.value is target atom's address. Instruction contains branch
// to atom+addend.
*addend += (targetAddress - reloc.value);
- return std::error_code();
+ return llvm::Error();
case ARM_RELOC_VANILLA | rExtern | rLength4:
// ex: .long _foo (and _foo is undefined)
*kind = pointer32;
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = instruction;
- return std::error_code();
+ return llvm::Error();
case ARM_RELOC_VANILLA | rLength4:
// ex: .long _foo (and _foo is defined)
*kind = pointer32;
- if (E ec = atomFromAddress(reloc.symbol, instruction, target, addend))
+ if (auto ec = atomFromAddress(reloc.symbol, instruction, target, addend))
return ec;
*addend = clearThumbBit((uint32_t) * addend, *target);
- return std::error_code();
+ return llvm::Error();
case ARM_RELOC_VANILLA | rScattered | rLength4:
// ex: .long _foo+a (and _foo is defined)
*kind = pointer32;
- if (E ec = atomFromAddress(0, reloc.value, target, addend))
+ if (auto ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
*addend += (clearThumbBit(instruction, *target) - reloc.value);
- return std::error_code();
+ return llvm::Error();
default:
- return make_dynamic_error_code("unsupported arm relocation type");
+ return llvm::make_error<GenericError>("unsupported arm relocation type");
}
- return std::error_code();
+ return llvm::Error();
}
-std::error_code
+llvm::Error
ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
const normalized::Relocation &reloc2,
const DefinedAtom *inAtom,
@@ -770,10 +782,9 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
pointerDiff = true;
break;
default:
- return make_dynamic_error_code("unsupported arm relocation pair");
+ return llvm::make_error<GenericError>("unsupported arm relocation pair");
}
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- std::error_code ec;
uint32_t instruction = *(const ulittle32_t *)fixupContent;
uint32_t value;
uint32_t fromAddress;
@@ -786,14 +797,12 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
if (pointerDiff) {
toAddress = reloc1.value;
fromAddress = reloc2.value;
- ec = atomFromAddr(0, toAddress, target, &offsetInTo);
- if (ec)
+ if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
return ec;
- ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
- if (ec)
+ if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
return ec;
if (scatterable && (fromTarget != inAtom))
- return make_dynamic_error_code(
+ return llvm::make_error<GenericError>(
"SECTDIFF relocation where subtrahend label is not in atom");
*kind = delta32;
value = clearThumbBit(instruction, *target);
@@ -801,35 +810,33 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
} else if (funcRel) {
toAddress = reloc1.value;
fromAddress = reloc2.value;
- ec = atomFromAddr(0, toAddress, target, &offsetInTo);
- if (ec)
+ if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
return ec;
- ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
- if (ec)
+ if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
return ec;
if (fromTarget != inAtom)
- return make_dynamic_error_code("ARM_RELOC_HALF_SECTDIFF relocation "
- "where subtrahend label is not in atom");
+ return llvm::make_error<GenericError>("ARM_RELOC_HALF_SECTDIFF relocation"
+ " where subtrahend label is not in atom");
other16 = (reloc2.offset & 0xFFFF);
if (thumbReloc) {
if (top) {
if (!isThumbMovt(instruction))
- return make_dynamic_error_code("expected movt instruction");
+ return llvm::make_error<GenericError>("expected movt instruction");
}
else {
if (!isThumbMovw(instruction))
- return make_dynamic_error_code("expected movw instruction");
+ return llvm::make_error<GenericError>("expected movw instruction");
}
instruction16 = getWordFromThumbMov(instruction);
}
else {
if (top) {
if (!isArmMovt(instruction))
- return make_dynamic_error_code("expected movt instruction");
+ return llvm::make_error<GenericError>("expected movt instruction");
}
else {
if (!isArmMovw(instruction))
- return make_dynamic_error_code("expected movw instruction");
+ return llvm::make_error<GenericError>("expected movw instruction");
}
instruction16 = getWordFromArmMov(instruction);
}
@@ -840,28 +847,28 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
value = clearThumbBit(value, *target);
int64_t ta = (int64_t) value - (toAddress - fromAddress);
*addend = ta - offsetInFrom;
- return std::error_code();
+ return llvm::Error();
} else {
uint32_t sectIndex;
if (thumbReloc) {
if (top) {
if (!isThumbMovt(instruction))
- return make_dynamic_error_code("expected movt instruction");
+ return llvm::make_error<GenericError>("expected movt instruction");
}
else {
if (!isThumbMovw(instruction))
- return make_dynamic_error_code("expected movw instruction");
+ return llvm::make_error<GenericError>("expected movw instruction");
}
instruction16 = getWordFromThumbMov(instruction);
}
else {
if (top) {
if (!isArmMovt(instruction))
- return make_dynamic_error_code("expected movt instruction");
+ return llvm::make_error<GenericError>("expected movt instruction");
}
else {
if (!isArmMovw(instruction))
- return make_dynamic_error_code("expected movw instruction");
+ return llvm::make_error<GenericError>("expected movw instruction");
}
instruction16 = getWordFromArmMov(instruction);
}
@@ -871,8 +878,7 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
else
value = (other16 << 16) | instruction16;
if (reloc1.isExtern) {
- ec = atomFromSymbolIndex(reloc1.symbol, target);
- if (ec)
+ if (auto ec = atomFromSymbolIndex(reloc1.symbol, target))
return ec;
*addend = value;
} else {
@@ -883,14 +889,13 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
toAddress = value;
sectIndex = reloc1.symbol;
}
- ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo);
- if (ec)
+ if (auto ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo))
return ec;
*addend = value - toAddress;
}
}
- return std::error_code();
+ return llvm::Error();
}
void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *loc,
@@ -1006,9 +1011,10 @@ void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress,
uint64_t imageBaseAddress,
- uint8_t *atomContentBuffer) {
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
// Copy raw bytes.
- memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
+ std::copy(atom.rawContent().begin(), atom.rawContent().end(),
+ atomContentBuffer.begin());
// Apply fix-ups.
bool thumbMode = false;
for (const Reference *ref : atom) {
@@ -1384,7 +1390,8 @@ void ArchHandler_arm::appendSectionRelocations(
void ArchHandler_arm::addAdditionalReferences(MachODefinedAtom &atom) {
if (atom.isThumb()) {
- atom.addReference(0, modeThumbCode, &atom, 0, Reference::KindArch::ARM);
+ atom.addReference(Reference::KindNamespace::mach_o,
+ Reference::KindArch::ARM, modeThumbCode, 0, &atom, 0);
}
}
@@ -1415,6 +1422,8 @@ public:
_name = tmp.copy(file.allocator());
}
+ ~Thumb2ToArmShimAtom() override = default;
+
StringRef name() const override {
return _name;
}
@@ -1458,6 +1467,8 @@ public:
_name = tmp.copy(file.allocator());
}
+ ~ArmToThumbShimAtom() override = default;
+
StringRef name() const override {
return _name;
}
diff --git a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
index 778f6f4add74..a61f6aac05e1 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
@@ -53,6 +53,9 @@ public:
case delta32ToGOT:
canBypassGOT = false;
return true;
+ case unwindCIEToPersonalityFunction:
+ canBypassGOT = false;
+ return true;
case imageOffsetGot:
canBypassGOT = false;
return true;
@@ -108,6 +111,10 @@ public:
return imageOffsetGot;
}
+ Reference::KindValue unwindRefToPersonalityFunctionKind() override {
+ return unwindCIEToPersonalityFunction;
+ }
+
Reference::KindValue unwindRefToCIEKind() override {
return negDelta32;
}
@@ -120,20 +127,24 @@ public:
return unwindInfoToEhFrame;
}
+ Reference::KindValue pointerKind() override {
+ return pointer64;
+ }
+
uint32_t dwarfCompactUnwindType() override {
return 0x03000000;
}
- std::error_code getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool isBig,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
- std::error_code
+ llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
+ const DefinedAtom *inAtom,
+ uint32_t offsetInAtom,
+ uint64_t fixupAddress, bool isBig,
+ FindAtomBySectionAndAddress atomFromAddress,
+ FindAtomBySymbolIndex atomFromSymbolIndex,
+ Reference::KindValue *kind,
+ const lld::Atom **target,
+ Reference::Addend *addend) override;
+ llvm::Error
getPairReferenceInfo(const normalized::Relocation &reloc1,
const normalized::Relocation &reloc2,
const DefinedAtom *inAtom,
@@ -153,7 +164,7 @@ public:
FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress,
uint64_t imageBaseAddress,
- uint8_t *atomContentBuffer) override;
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
void appendSectionRelocations(const DefinedAtom &atom,
uint64_t atomSectionOffset,
@@ -197,6 +208,9 @@ private:
imageOffset, /// Location contains offset of atom in final image
imageOffsetGot, /// Location contains offset of GOT entry for atom in
/// final image (typically personality function).
+ unwindCIEToPersonalityFunction, /// Nearly delta32ToGOT, but cannot be
+ /// rematerialized in relocatable object
+ /// (yay for implicit contracts!).
unwindFDEToFunction, /// Nearly delta64, but cannot be rematerialized in
/// relocatable object (yay for implicit contracts!).
unwindInfoToEhFrame, /// Fix low 24 bits of compact unwind encoding to
@@ -244,6 +258,7 @@ const Registry::KindStrings ArchHandler_arm64::_sKindStrings[] = {
LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
LLD_KIND_STRING_ENTRY(imageOffset),
LLD_KIND_STRING_ENTRY(imageOffsetGot),
+ LLD_KIND_STRING_ENTRY(unwindCIEToPersonalityFunction),
LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
@@ -279,8 +294,13 @@ const ArchHandler::StubInfo ArchHandler_arm64::_sStubInfo = {
{ Reference::KindArch::AArch64, lazyImmediateLocation, 8, 0 },
{ Reference::KindArch::AArch64, branch26, 4, 0 },
+ // Stub helper image cache content type
+ DefinedAtom::typeGOT,
+
// Stub Helper-Common size and code
24,
+ // Stub helper alignment
+ 2,
{ 0x11, 0x00, 0x00, 0x90, // ADRP X17, dyld_ImageLoaderCache@page
0x31, 0x02, 0x00, 0x91, // ADD X17, X17, dyld_ImageLoaderCache@pageoff
0xF0, 0x47, 0xBF, 0xA9, // STP X16/X17, [SP, #-16]!
@@ -355,7 +375,7 @@ uint32_t ArchHandler_arm64::setImm12(uint32_t instruction, uint32_t offset) {
return (instruction & 0xFFC003FF) | imm12;
}
-std::error_code ArchHandler_arm64::getReferenceInfo(
+llvm::Error ArchHandler_arm64::getReferenceInfo(
const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
uint64_t fixupAddress, bool isBig,
FindAtomBySectionAndAddress atomFromAddress,
@@ -369,56 +389,56 @@ std::error_code ArchHandler_arm64::getReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4:
// ex: adrp x1, _foo@PAGE
*kind = page21;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_PAGEOFF12 | rExtern | rLength4:
// ex: ldr x0, [x1, _foo@PAGEOFF]
*kind = offset12KindFromInstruction(*(const little32_t *)fixupContent);
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4:
// ex: adrp x1, _foo@GOTPAGE
*kind = gotPage21;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4:
// ex: ldr x0, [x1, _foo@GOTPAGEOFF]
*kind = gotOffset12;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4:
// ex: adrp x1, _foo@TLVPAGE
*kind = tlvPage21;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4:
// ex: ldr x0, [x1, _foo@TLVPAGEOFF]
*kind = tlvOffset12;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_UNSIGNED | rExtern | rLength8:
// ex: .quad _foo + N
*kind = pointer64;
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = *(const little64_t *)fixupContent;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_UNSIGNED | rLength8:
// ex: .quad Lfoo + N
*kind = pointer64;
@@ -430,27 +450,33 @@ std::error_code ArchHandler_arm64::getReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
case ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4:
// ex: .long _foo@GOT - .
- *kind = delta32ToGOT;
+
+ // If we are in an .eh_frame section, then the kind of the relocation should
+ // not be delta32ToGOT. It may instead be unwindCIEToPersonalityFunction.
+ if (inAtom->contentType() == DefinedAtom::typeCFI)
+ *kind = unwindCIEToPersonalityFunction;
+ else
+ *kind = delta32ToGOT;
+
if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = 0;
- return std::error_code();
+ return llvm::Error();
default:
- return make_dynamic_error_code("unsupported arm64 relocation type");
+ return llvm::make_error<GenericError>("unsupported arm64 relocation type");
}
}
-std::error_code ArchHandler_arm64::getPairReferenceInfo(
+llvm::Error ArchHandler_arm64::getPairReferenceInfo(
const normalized::Relocation &reloc1, const normalized::Relocation &reloc2,
const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress,
bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress,
FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
const lld::Atom **target, Reference::Addend *addend) {
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- const uint32_t *cont32 = reinterpret_cast<const uint32_t *>(fixupContent);
switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
case ((ARM64_RELOC_ADDEND | rLength4) << 16 |
ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4):
@@ -459,7 +485,7 @@ std::error_code ArchHandler_arm64::getPairReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
*addend = reloc1.symbol;
- return std::error_code();
+ return llvm::Error();
case ((ARM64_RELOC_ADDEND | rLength4) << 16 |
ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4):
// ex: adrp x1, _foo@PAGE
@@ -467,26 +493,36 @@ std::error_code ArchHandler_arm64::getPairReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
*addend = reloc1.symbol;
- return std::error_code();
+ return llvm::Error();
case ((ARM64_RELOC_ADDEND | rLength4) << 16 |
- ARM64_RELOC_PAGEOFF12 | rExtern | rLength4):
+ ARM64_RELOC_PAGEOFF12 | rExtern | rLength4): {
// ex: ldr w0, [x1, _foo@PAGEOFF]
- *kind = offset12KindFromInstruction(*cont32);
+ uint32_t cont32 = (int32_t)*(const little32_t *)fixupContent;
+ *kind = offset12KindFromInstruction(cont32);
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
*addend = reloc1.symbol;
- return std::error_code();
+ return llvm::Error();
+ }
case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
ARM64_RELOC_UNSIGNED | rExtern | rLength8):
// ex: .quad _foo - .
- *kind = delta64;
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
+
+ // If we are in an .eh_frame section, then the kind of the relocation should
+ // not be delta64. It may instead be unwindFDEToFunction.
+ if (inAtom->contentType() == DefinedAtom::typeCFI)
+ *kind = unwindFDEToFunction;
+ else
+ *kind = delta64;
+
// The offsets of the 2 relocations must match
if (reloc1.offset != reloc2.offset)
- return make_dynamic_error_code("paired relocs must have the same offset");
+ return llvm::make_error<GenericError>(
+ "paired relocs must have the same offset");
*addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom;
- return std::error_code();
+ return llvm::Error();
case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
ARM64_RELOC_UNSIGNED | rExtern | rLength4):
// ex: .quad _foo - .
@@ -494,18 +530,19 @@ std::error_code ArchHandler_arm64::getPairReferenceInfo(
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
*addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom;
- return std::error_code();
+ return llvm::Error();
default:
- return make_dynamic_error_code("unsupported arm64 relocation pair");
+ return llvm::make_error<GenericError>("unsupported arm64 relocation pair");
}
}
void ArchHandler_arm64::generateAtomContent(
const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
- uint8_t *atomContentBuffer) {
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
// Copy raw bytes.
- memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
+ std::copy(atom.rawContent().begin(), atom.rawContent().end(),
+ atomContentBuffer.begin());
// Apply fix-ups.
#ifndef NDEBUG
if (atom.begin() != atom.end()) {
@@ -620,6 +657,7 @@ void ArchHandler_arm64::applyFixupFinal(const Reference &ref, uint8_t *loc,
return;
case delta32:
case delta32ToGOT:
+ case unwindCIEToPersonalityFunction:
*loc32 = (targetAddress - fixupAddress) + ref.addend();
return;
case negDelta32:
@@ -710,6 +748,13 @@ void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
case delta32ToGOT:
*loc32 = inAtomAddress - fixupAddress;
return;
+ case unwindCIEToPersonalityFunction:
+ // We don't emit unwindCIEToPersonalityFunction in -r mode as they are
+ // implicitly generated from the data in the __eh_frame section. So here we
+ // need to use the targetAddress so that we can generate the full relocation
+ // when we parse again later.
+ *loc32 = targetAddress - fixupAddress;
+ return;
case addOffset12:
llvm_unreachable("lazy reference kind implies GOT pass was run");
case lazyPointer:
@@ -832,6 +877,7 @@ void ArchHandler_arm64::appendSectionRelocations(
case imageOffset:
case imageOffsetGot:
llvm_unreachable("deltas from mach_header can only be in final images");
+ case unwindCIEToPersonalityFunction:
case unwindFDEToFunction:
case unwindInfoToEhFrame:
case negDelta32:
diff --git a/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
index 7aac2584d078..15f1f793b5d7 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
@@ -58,6 +58,10 @@ public:
return invalid;
}
+ Reference::KindValue unwindRefToPersonalityFunctionKind() override {
+ return invalid;
+ }
+
Reference::KindValue unwindRefToCIEKind() override {
return negDelta32;
}
@@ -70,20 +74,24 @@ public:
return invalid;
}
+ Reference::KindValue pointerKind() override {
+ return invalid;
+ }
+
uint32_t dwarfCompactUnwindType() override {
return 0x04000000U;
}
- std::error_code getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
- std::error_code
+ llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
+ const DefinedAtom *inAtom,
+ uint32_t offsetInAtom,
+ uint64_t fixupAddress, bool swap,
+ FindAtomBySectionAndAddress atomFromAddress,
+ FindAtomBySymbolIndex atomFromSymbolIndex,
+ Reference::KindValue *kind,
+ const lld::Atom **target,
+ Reference::Addend *addend) override;
+ llvm::Error
getPairReferenceInfo(const normalized::Relocation &reloc1,
const normalized::Relocation &reloc2,
const DefinedAtom *inAtom,
@@ -99,7 +107,7 @@ public:
FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress,
uint64_t imageBaseAddress,
- uint8_t *atomContentBuffer) override;
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
void appendSectionRelocations(const DefinedAtom &atom,
uint64_t atomSectionOffset,
@@ -212,8 +220,13 @@ const ArchHandler::StubInfo ArchHandler_x86::_sStubInfo = {
{ Reference::KindArch::x86, lazyImmediateLocation, 1, 0 },
{ Reference::KindArch::x86, branch32, 6, 0 },
+ // Stub helper image cache content type
+ DefinedAtom::typeNonLazyPointer,
+
// Stub Helper-Common size and code
12,
+ // Stub helper alignment
+ 2,
{ 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $dyld_ImageLoaderCache
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *_fast_lazy_bind
0x90 }, // nop
@@ -238,7 +251,7 @@ bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) {
(reloc.type == GENERIC_RELOC_SECTDIFF);
}
-std::error_code
+llvm::Error
ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
const DefinedAtom *inAtom,
uint32_t offsetInAtom,
@@ -248,7 +261,6 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
Reference::KindValue *kind,
const lld::Atom **target,
Reference::Addend *addend) {
- typedef std::error_code E;
DefinedAtom::ContentPermissions perms;
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
uint64_t targetAddress;
@@ -256,7 +268,7 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4:
// ex: call _foo (and _foo undefined)
*kind = branch32;
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = fixupAddress + 4 + (int32_t)*(const little32_t *)fixupContent;
break;
@@ -272,14 +284,14 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
*kind = branch32;
targetAddress =
fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
- if (E ec = atomFromAddress(0, reloc.value, target, addend))
+ if (auto ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
*addend = targetAddress - reloc.value;
break;
case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
// ex: callw _foo (and _foo undefined)
*kind = branch16;
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = fixupAddress + 2 + (int16_t)*(const little16_t *)fixupContent;
break;
@@ -295,7 +307,7 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
*kind = branch16;
targetAddress =
fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
- if (E ec = atomFromAddress(0, reloc.value, target, addend))
+ if (auto ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
*addend = targetAddress - reloc.value;
break;
@@ -306,7 +318,7 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
*kind =
((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
: pointer32;
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = *(const ulittle32_t *)fixupContent;
break;
@@ -326,17 +338,17 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
*kind =
((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
: pointer32;
- if (E ec = atomFromAddress(0, reloc.value, target, addend))
+ if (auto ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
*addend = *(const ulittle32_t *)fixupContent - reloc.value;
break;
default:
- return make_dynamic_error_code("unsupported i386 relocation type");
+ return llvm::make_error<GenericError>("unsupported i386 relocation type");
}
- return std::error_code();
+ return llvm::Error();
}
-std::error_code
+llvm::Error
ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
const normalized::Relocation &reloc2,
const DefinedAtom *inAtom,
@@ -349,7 +361,6 @@ ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
const lld::Atom **target,
Reference::Addend *addend) {
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- std::error_code ec;
DefinedAtom::ContentPermissions perms = inAtom->permissions();
uint32_t fromAddress;
uint32_t toAddress;
@@ -365,15 +376,13 @@ ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
toAddress = reloc1.value;
fromAddress = reloc2.value;
value = *(const little32_t *)fixupContent;
- ec = atomFromAddr(0, toAddress, target, &offsetInTo);
- if (ec)
+ if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
return ec;
- ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
- if (ec)
+ if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
return ec;
if (fromTarget != inAtom) {
if (*target != inAtom)
- return make_dynamic_error_code(
+ return llvm::make_error<GenericError>(
"SECTDIFF relocation where neither target is in atom");
*kind = negDelta32;
*addend = toAddress - value - fromAddress;
@@ -394,10 +403,10 @@ ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
*addend = fromAddress + value - toAddress;
}
}
- return std::error_code();
+ return llvm::Error();
break;
default:
- return make_dynamic_error_code("unsupported i386 relocation type");
+ return llvm::make_error<GenericError>("unsupported i386 relocation type");
}
}
@@ -406,9 +415,10 @@ void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress,
uint64_t imageBaseAddress,
- uint8_t *atomContentBuffer) {
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
// Copy raw bytes.
- memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
+ std::copy(atom.rawContent().begin(), atom.rawContent().end(),
+ atomContentBuffer.begin());
// Apply fix-ups.
for (const Reference *ref : atom) {
uint32_t offset = ref->offsetInAtom();
diff --git a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
index 8b4d1cf38cba..c36982a77b13 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
@@ -104,6 +104,10 @@ public:
return imageOffsetGot;
}
+ Reference::KindValue unwindRefToPersonalityFunctionKind() override {
+ return ripRel32Got;
+ }
+
Reference::KindValue unwindRefToCIEKind() override {
return negDelta32;
}
@@ -116,6 +120,10 @@ public:
return unwindInfoToEhFrame;
}
+ Reference::KindValue pointerKind() override {
+ return pointer64;
+ }
+
uint32_t dwarfCompactUnwindType() override {
return 0x04000000U;
}
@@ -130,16 +138,16 @@ public:
bool isPointer(const Reference &) override;
bool isPairedReloc(const normalized::Relocation &) override;
- std::error_code getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
- std::error_code
+ llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
+ const DefinedAtom *inAtom,
+ uint32_t offsetInAtom,
+ uint64_t fixupAddress, bool swap,
+ FindAtomBySectionAndAddress atomFromAddress,
+ FindAtomBySymbolIndex atomFromSymbolIndex,
+ Reference::KindValue *kind,
+ const lld::Atom **target,
+ Reference::Addend *addend) override;
+ llvm::Error
getPairReferenceInfo(const normalized::Relocation &reloc1,
const normalized::Relocation &reloc2,
const DefinedAtom *inAtom,
@@ -159,7 +167,7 @@ public:
FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress,
uint64_t imageBase,
- uint8_t *atomContentBuffer) override;
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
void appendSectionRelocations(const DefinedAtom &atom,
uint64_t atomSectionOffset,
@@ -195,6 +203,7 @@ private:
delta32, /// ex: .long _foo - .
delta64Anon, /// ex: .quad L1 - .
delta32Anon, /// ex: .long L1 - .
+ negDelta64, /// ex: .quad . - _foo
negDelta32, /// ex: .long . - _foo
// Kinds introduced by Passes:
@@ -216,8 +225,6 @@ private:
};
Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);
- Reference::KindValue kindFromRelocPair(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2);
void applyFixupFinal(const Reference &ref, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress,
@@ -246,6 +253,7 @@ const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = {
LLD_KIND_STRING_ENTRY(pointer64), LLD_KIND_STRING_ENTRY(pointer64Anon),
LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(delta64),
LLD_KIND_STRING_ENTRY(delta32Anon), LLD_KIND_STRING_ENTRY(delta64Anon),
+ LLD_KIND_STRING_ENTRY(negDelta64),
LLD_KIND_STRING_ENTRY(negDelta32),
LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot),
LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
@@ -280,8 +288,13 @@ const ArchHandler::StubInfo ArchHandler_x86_64::_sStubInfo = {
{ Reference::KindArch::x86_64, lazyImmediateLocation, 1, 0 },
{ Reference::KindArch::x86_64, branch32, 6, 0 },
+ // Stub helper image cache content type
+ DefinedAtom::typeNonLazyPointer,
+
// Stub Helper-Common size and code
16,
+ // Stub helper alignment
+ 2,
{ 0x4C, 0x8D, 0x1D, 0x00, 0x00, 0x00, 0x00, // leaq cache(%rip),%r11
0x41, 0x53, // push %r11
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *binder(%rip)
@@ -348,7 +361,7 @@ ArchHandler_x86_64::kindFromReloc(const Relocation &reloc) {
}
}
-std::error_code
+llvm::Error
ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
const DefinedAtom *inAtom,
uint32_t offsetInAtom,
@@ -358,34 +371,33 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
Reference::KindValue *kind,
const lld::Atom **target,
Reference::Addend *addend) {
- typedef std::error_code E;
*kind = kindFromReloc(reloc);
if (*kind == invalid)
- return make_dynamic_error_code("unknown type");
+ return llvm::make_error<GenericError>("unknown type");
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
uint64_t targetAddress;
switch (*kind) {
case branch32:
case ripRel32:
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = *(const little32_t *)fixupContent;
- return std::error_code();
+ return llvm::Error();
case ripRel32Minus1:
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = (int32_t)*(const little32_t *)fixupContent + 1;
- return std::error_code();
+ return llvm::Error();
case ripRel32Minus2:
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = (int32_t)*(const little32_t *)fixupContent + 2;
- return std::error_code();
+ return llvm::Error();
case ripRel32Minus4:
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = (int32_t)*(const little32_t *)fixupContent + 4;
- return std::error_code();
+ return llvm::Error();
case ripRel32Anon:
targetAddress = fixupAddress + 4 + *(const little32_t *)fixupContent;
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
@@ -401,13 +413,13 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
case ripRel32GotLoad:
case ripRel32Got:
case ripRel32Tlv:
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = *(const little32_t *)fixupContent;
- return std::error_code();
+ return llvm::Error();
case tlvInitSectionOffset:
case pointer64:
- if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+ if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
// If this is the 3rd pointer of a tlv-thunk (i.e. the pointer to the TLV's
// initial value) we need to handle it specially.
@@ -417,7 +429,7 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
assert(*addend == 0 && "TLV-init has non-zero addend?");
} else
*addend = *(const little64_t *)fixupContent;
- return std::error_code();
+ return llvm::Error();
case pointer64Anon:
targetAddress = *(const little64_t *)fixupContent;
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
@@ -426,28 +438,7 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
}
}
-Reference::KindValue
-ArchHandler_x86_64::kindFromRelocPair(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2) {
- switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
- case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
- X86_64_RELOC_UNSIGNED | rExtern | rLength8):
- return delta64;
- case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
- X86_64_RELOC_UNSIGNED | rExtern | rLength4):
- return delta32;
- case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
- X86_64_RELOC_UNSIGNED | rLength8):
- return delta64Anon;
- case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
- X86_64_RELOC_UNSIGNED | rLength4):
- return delta32Anon;
- default:
- llvm_unreachable("bad reloc pairs");
- }
-}
-
-std::error_code
+llvm::Error
ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
const normalized::Relocation &reloc2,
const DefinedAtom *inAtom,
@@ -459,45 +450,71 @@ ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
Reference::KindValue *kind,
const lld::Atom **target,
Reference::Addend *addend) {
- *kind = kindFromRelocPair(reloc1, reloc2);
- if (*kind == invalid)
- return make_dynamic_error_code("unknown pair");
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- typedef std::error_code E;
uint64_t targetAddress;
const lld::Atom *fromTarget;
- if (E ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget))
+ if (auto ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget))
return ec;
- if (fromTarget != inAtom)
- return make_dynamic_error_code("pointer diff not in base atom");
- switch (*kind) {
- case delta64:
- if (E ec = atomFromSymbolIndex(reloc2.symbol, target))
+
+ switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
+ case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
+ X86_64_RELOC_UNSIGNED | rExtern | rLength8): {
+ if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
- *addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom;
- return std::error_code();
- case delta32:
- if (E ec = atomFromSymbolIndex(reloc2.symbol, target))
+ uint64_t encodedAddend = (int64_t)*(const little64_t *)fixupContent;
+ if (inAtom == fromTarget) {
+ *kind = delta64;
+ *addend = encodedAddend + offsetInAtom;
+ } else if (inAtom == *target) {
+ *kind = negDelta64;
+ *addend = encodedAddend - offsetInAtom;
+ *target = fromTarget;
+ } else
+ return llvm::make_error<GenericError>("Invalid pointer diff");
+ return llvm::Error();
+ }
+ case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
+ X86_64_RELOC_UNSIGNED | rExtern | rLength4): {
+ if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
- *addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom;
- return std::error_code();
- case delta64Anon:
+ uint32_t encodedAddend = (int32_t)*(const little32_t *)fixupContent;
+ if (inAtom == fromTarget) {
+ *kind = delta32;
+ *addend = encodedAddend + offsetInAtom;
+ } else if (inAtom == *target) {
+ *kind = negDelta32;
+ *addend = encodedAddend - offsetInAtom;
+ *target = fromTarget;
+ } else
+ return llvm::make_error<GenericError>("Invalid pointer diff");
+ return llvm::Error();
+ }
+ case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
+ X86_64_RELOC_UNSIGNED | rLength8):
+ if (fromTarget != inAtom)
+ return llvm::make_error<GenericError>("pointer diff not in base atom");
+ *kind = delta64Anon;
targetAddress = offsetInAtom + (int64_t)*(const little64_t *)fixupContent;
return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
- case delta32Anon:
+ case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
+ X86_64_RELOC_UNSIGNED | rLength4):
+ if (fromTarget != inAtom)
+ return llvm::make_error<GenericError>("pointer diff not in base atom");
+ *kind = delta32Anon;
targetAddress = offsetInAtom + (int32_t)*(const little32_t *)fixupContent;
return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
default:
- llvm_unreachable("bad reloc pair kind");
+ return llvm::make_error<GenericError>("unknown pair");
}
}
void ArchHandler_x86_64::generateAtomContent(
const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
- uint8_t *atomContentBuffer) {
+ llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
// Copy raw bytes.
- memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
+ std::copy(atom.rawContent().begin(), atom.rawContent().end(),
+ atomContentBuffer.begin());
// Apply fix-ups.
for (const Reference *ref : atom) {
uint32_t offset = ref->offsetInAtom();
@@ -571,6 +588,9 @@ void ArchHandler_x86_64::applyFixupFinal(
loc[-2] = 0x8D;
*loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
return;
+ case negDelta64:
+ *loc64 = fixupAddress - targetAddress + ref.addend();
+ return;
case negDelta32:
*loc32 = fixupAddress - targetAddress + ref.addend();
return;
@@ -675,8 +695,11 @@ void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
// Then we want to encode the value (Ltarget + addend) - (LFixup - _base)
*loc64 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress);
return;
+ case negDelta64:
+ *loc64 = ref.addend() + fixupAddress - inAtomAddress;
+ return;
case negDelta32:
- *loc32 = fixupAddress - targetAddress + ref.addend();
+ *loc32 = ref.addend() + fixupAddress - inAtomAddress;
return;
case ripRel32GotLoadNowLea:
llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
@@ -796,7 +819,18 @@ void ArchHandler_x86_64::appendSectionRelocations(
return;
case unwindFDEToFunction:
case unwindInfoToEhFrame:
+ return;
case negDelta32:
+ appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+ X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
+ appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+ X86_64_RELOC_UNSIGNED | rExtern | rLength4 );
+ return;
+ case negDelta64:
+ appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+ X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
+ appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+ X86_64_RELOC_UNSIGNED | rExtern | rLength8 );
return;
case ripRel32GotLoadNowLea:
llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
diff --git a/lib/ReaderWriter/MachO/Atoms.h b/lib/ReaderWriter/MachO/Atoms.h
index 9f2e5acad99a..573efca9f6f9 100644
--- a/lib/ReaderWriter/MachO/Atoms.h
+++ b/lib/ReaderWriter/MachO/Atoms.h
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/MachO/Atoms.h -------------------------------------===//
+//===- lib/ReaderWriter/MachO/Atoms.h ---------------------------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -10,10 +10,21 @@
#ifndef LLD_READER_WRITER_MACHO_ATOMS_H
#define LLD_READER_WRITER_MACHO_ATOMS_H
+#include "lld/Core/Atom.h"
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/Simple.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstdint>
+#include <string>
namespace lld {
+
+class File;
+
namespace mach_o {
+
class MachODefinedAtom : public SimpleDefinedAtom {
public:
MachODefinedAtom(const File &f, const StringRef name, Scope scope,
@@ -32,6 +43,8 @@ public:
_contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
_noDeadStrip(noDeadStrip) {}
+ ~MachODefinedAtom() override = default;
+
uint64_t size() const override { return _content.size(); }
ContentType contentType() const override { return _contentType; }
@@ -61,15 +74,6 @@ public:
bool isThumb() const { return _thumb; }
- void addReference(uint32_t offsetInAtom, uint16_t relocType,
- const Atom *target, Reference::Addend addend,
- Reference::KindArch arch = Reference::KindArch::x86_64,
- Reference::KindNamespace ns
- = Reference::KindNamespace::mach_o) {
- SimpleDefinedAtom::addReference(ns, arch, relocType, offsetInAtom, target,
- addend);
- }
-
private:
const StringRef _name;
const ArrayRef<uint8_t> _content;
@@ -92,6 +96,8 @@ public:
content, align),
_sectionName(sectionName) {}
+ ~MachODefinedCustomSectionAtom() override = default;
+
SectionChoice sectionChoice() const override {
return DefinedAtom::sectionCustomRequired;
}
@@ -110,6 +116,8 @@ public:
: SimpleDefinedAtom(f), _name(name), _scope(scope), _size(size),
_align(align) {}
+ ~MachOTentativeDefAtom() override = default;
+
uint64_t size() const override { return _size; }
Merge merge() const override { return DefinedAtom::mergeAsTentative; }
@@ -167,7 +175,7 @@ private:
StringRef _dylibInstallName;
};
-} // namespace mach_o
-} // namespace lld
+} // end namespace mach_o
+} // end namespace lld
#endif // LLD_READER_WRITER_MACHO_ATOMS_H
diff --git a/lib/ReaderWriter/MachO/CMakeLists.txt b/lib/ReaderWriter/MachO/CMakeLists.txt
index a389ca51ddfd..70f451c997b3 100644
--- a/lib/ReaderWriter/MachO/CMakeLists.txt
+++ b/lib/ReaderWriter/MachO/CMakeLists.txt
@@ -13,6 +13,7 @@ add_lld_library(lldMachO
MachONormalizedFileFromAtoms.cpp
MachONormalizedFileToAtoms.cpp
MachONormalizedFileYAML.cpp
+ ObjCPass.cpp
ShimPass.cpp
StubsPass.cpp
TLVPass.cpp
@@ -22,6 +23,7 @@ add_lld_library(lldMachO
lldYAML
LLVMObject
LLVMSupport
+ ${PTHREAD_LIB}
)
include_directories(.)
diff --git a/lib/ReaderWriter/MachO/CompactUnwindPass.cpp b/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
index 4b8644a67e70..6f5ab83dbda6 100644
--- a/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
+++ b/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
@@ -59,7 +59,7 @@ struct CompactUnwindEntry {
};
struct UnwindInfoPage {
- std::vector<CompactUnwindEntry> entries;
+ ArrayRef<CompactUnwindEntry> entries;
};
}
@@ -88,6 +88,8 @@ public:
addSecondLevelPages(pages);
}
+ ~UnwindInfoAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeProcessedUnwindInfo;
}
@@ -179,7 +181,7 @@ public:
}
// Finally, write out the final sentinel index
- CompactUnwindEntry &finalEntry = pages[pages.size() - 1].entries.back();
+ auto &finalEntry = pages[pages.size() - 1].entries.back();
addImageReference(_topLevelIndexOffset +
3 * pages.size() * sizeof(uint32_t),
finalEntry.rangeStart, finalEntry.rangeLength);
@@ -273,11 +275,13 @@ class CompactUnwindPass : public Pass {
public:
CompactUnwindPass(const MachOLinkingContext &context)
: _ctx(context), _archHandler(_ctx.archHandler()),
- _file("<mach-o Compact Unwind Pass>"),
- _isBig(MachOLinkingContext::isBigEndian(_ctx.arch())) {}
+ _file(*_ctx.make_file<MachOFile>("<mach-o Compact Unwind Pass>")),
+ _isBig(MachOLinkingContext::isBigEndian(_ctx.arch())) {
+ _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
+ }
private:
- std::error_code perform(SimpleFile &mergedFile) override {
+ llvm::Error perform(SimpleFile &mergedFile) override {
DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");
std::map<const Atom *, CompactUnwindEntry> unwindLocs;
@@ -294,7 +298,7 @@ private:
// Skip rest of pass if no unwind info.
if (unwindLocs.empty() && dwarfFrames.empty())
- return std::error_code();
+ return llvm::Error();
// FIXME: if there are more than 4 personality functions then we need to
// defer to DWARF info for the ones we don't put in the list. They should
@@ -321,26 +325,23 @@ private:
// boundaries. That might be worth doing, or perhaps we could perform some
// minor balancing for expected number of lookups.
std::vector<UnwindInfoPage> pages;
- unsigned pageStart = 0;
+ auto remainingInfos = llvm::makeArrayRef(unwindInfos);
do {
pages.push_back(UnwindInfoPage());
// FIXME: we only create regular pages at the moment. These can hold up to
// 1021 entries according to the documentation.
- unsigned entriesInPage =
- std::min(1021U, (unsigned)unwindInfos.size() - pageStart);
+ unsigned entriesInPage = std::min(1021U, (unsigned)remainingInfos.size());
- std::copy(unwindInfos.begin() + pageStart,
- unwindInfos.begin() + pageStart + entriesInPage,
- std::back_inserter(pages.back().entries));
- pageStart += entriesInPage;
+ pages.back().entries = remainingInfos.slice(0, entriesInPage);
+ remainingInfos = remainingInfos.slice(entriesInPage);
DEBUG(llvm::dbgs()
<< " Page from " << pages.back().entries[0].rangeStart->name()
<< " to " << pages.back().entries.back().rangeStart->name() << " + "
<< llvm::format("0x%x", pages.back().entries.back().rangeLength)
<< " has " << entriesInPage << " entries\n");
- } while (pageStart < unwindInfos.size());
+ } while (!remainingInfos.empty());
auto *unwind = new (_file.allocator())
UnwindInfoAtom(_archHandler, _file, _isBig, personalities,
@@ -352,7 +353,7 @@ private:
return atom->contentType() == DefinedAtom::typeCompactUnwindInfo;
});
- return std::error_code();
+ return llvm::Error();
}
void collectCompactUnwindEntries(
@@ -568,7 +569,7 @@ private:
const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
- MachOFile _file;
+ MachOFile &_file;
bool _isBig;
};
diff --git a/lib/ReaderWriter/MachO/ExecutableAtoms.h b/lib/ReaderWriter/MachO/ExecutableAtoms.h
index 2e99af903dbd..acced33b7e74 100644
--- a/lib/ReaderWriter/MachO/ExecutableAtoms.h
+++ b/lib/ReaderWriter/MachO/ExecutableAtoms.h
@@ -11,10 +11,10 @@
#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
#include "Atoms.h"
+#include "File.h"
#include "llvm/Support/MachO.h"
-#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/LinkingContext.h"
@@ -34,7 +34,7 @@ namespace mach_o {
class CEntryFile : public SimpleFile {
public:
CEntryFile(const MachOLinkingContext &context)
- : SimpleFile("C entry"),
+ : SimpleFile("C entry", kindCEntryObject),
_undefMain(*this, context.entrySymbolName()) {
this->addAtom(_undefMain);
}
@@ -51,7 +51,7 @@ private:
class StubHelperFile : public SimpleFile {
public:
StubHelperFile(const MachOLinkingContext &context)
- : SimpleFile("stub runtime"),
+ : SimpleFile("stub runtime", kindStubHelperObject),
_undefBinder(*this, context.binderSymbolName()) {
this->addAtom(_undefBinder);
}
@@ -65,66 +65,88 @@ private:
// MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
// of the mach_header for final linked images.
//
-class MachHeaderAliasFile : public ArchiveLibraryFile {
+class MachHeaderAliasFile : public SimpleFile {
public:
MachHeaderAliasFile(const MachOLinkingContext &context)
- : ArchiveLibraryFile("mach_header symbols") {
- switch (context.outputMachOType()) {
- case llvm::MachO::MH_EXECUTE:
- _machHeaderSymbolName = "__mh_execute_header";
- break;
- case llvm::MachO::MH_DYLIB:
- _machHeaderSymbolName = "__mh_dylib_header";
- break;
- case llvm::MachO::MH_BUNDLE:
- _machHeaderSymbolName = "__mh_bundle_header";
- break;
- case llvm::MachO::MH_DYLINKER:
- _machHeaderSymbolName = "__mh_dylinker_header";
- break;
- case llvm::MachO::MH_PRELOAD:
- _machHeaderSymbolName = "__mh_preload_header";
- break;
- default:
- llvm_unreachable("no mach_header symbol for file type");
- }
- }
-
- std::error_code
- parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
- return std::error_code();
- }
-
- File *find(StringRef sym, bool dataSymbolOnly) override {
- if (sym.equals("___dso_handle") || sym.equals(_machHeaderSymbolName)) {
+ : SimpleFile("mach_header symbols", kindHeaderObject) {
+ StringRef machHeaderSymbolName;
+ DefinedAtom::Scope symbolScope = DefinedAtom::scopeLinkageUnit;
+ StringRef dsoHandleName;
+ switch (context.outputMachOType()) {
+ case llvm::MachO::MH_OBJECT:
+ machHeaderSymbolName = "__mh_object_header";
+ break;
+ case llvm::MachO::MH_EXECUTE:
+ machHeaderSymbolName = "__mh_execute_header";
+ symbolScope = DefinedAtom::scopeGlobal;
+ dsoHandleName = "___dso_handle";
+ break;
+ case llvm::MachO::MH_FVMLIB:
+ llvm_unreachable("no mach_header symbol for file type");
+ case llvm::MachO::MH_CORE:
+ llvm_unreachable("no mach_header symbol for file type");
+ case llvm::MachO::MH_PRELOAD:
+ llvm_unreachable("no mach_header symbol for file type");
+ case llvm::MachO::MH_DYLIB:
+ machHeaderSymbolName = "__mh_dylib_header";
+ dsoHandleName = "___dso_handle";
+ break;
+ case llvm::MachO::MH_DYLINKER:
+ machHeaderSymbolName = "__mh_dylinker_header";
+ dsoHandleName = "___dso_handle";
+ break;
+ case llvm::MachO::MH_BUNDLE:
+ machHeaderSymbolName = "__mh_bundle_header";
+ dsoHandleName = "___dso_handle";
+ break;
+ case llvm::MachO::MH_DYLIB_STUB:
+ llvm_unreachable("no mach_header symbol for file type");
+ case llvm::MachO::MH_DSYM:
+ llvm_unreachable("no mach_header symbol for file type");
+ case llvm::MachO::MH_KEXT_BUNDLE:
+ dsoHandleName = "___dso_handle";
+ break;
+ }
+ if (!machHeaderSymbolName.empty())
_definedAtoms.push_back(new (allocator()) MachODefinedAtom(
- *this, sym, DefinedAtom::scopeLinkageUnit,
- DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false, false,
+ *this, machHeaderSymbolName, symbolScope,
+ DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false,
+ true /* noDeadStrip */,
ArrayRef<uint8_t>(), DefinedAtom::Alignment(4096)));
- return this;
- }
- return nullptr;
+
+ if (!dsoHandleName.empty())
+ _definedAtoms.push_back(new (allocator()) MachODefinedAtom(
+ *this, dsoHandleName, DefinedAtom::scopeLinkageUnit,
+ DefinedAtom::typeDSOHandle, DefinedAtom::mergeNo, false,
+ true /* noDeadStrip */,
+ ArrayRef<uint8_t>(), DefinedAtom::Alignment(1)));
}
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _definedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
+ void clearAtoms() override {
+ _definedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
+
private:
mutable AtomVector<DefinedAtom> _definedAtoms;
- StringRef _machHeaderSymbolName;
};
} // namespace mach_o
diff --git a/lib/ReaderWriter/MachO/File.h b/lib/ReaderWriter/MachO/File.h
index c97dfa142b8d..64a0fcf82844 100644
--- a/lib/ReaderWriter/MachO/File.h
+++ b/lib/ReaderWriter/MachO/File.h
@@ -14,6 +14,7 @@
#include "MachONormalizedFile.h"
#include "lld/Core/SharedLibraryFile.h"
#include "lld/Core/Simple.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include <unordered_map>
@@ -25,9 +26,10 @@ using lld::mach_o::normalized::Section;
class MachOFile : public SimpleFile {
public:
MachOFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
- : SimpleFile(mb->getBufferIdentifier()), _mb(std::move(mb)), _ctx(ctx) {}
+ : SimpleFile(mb->getBufferIdentifier(), File::kindMachObject),
+ _mb(std::move(mb)), _ctx(ctx) {}
- MachOFile(StringRef path) : SimpleFile(path) {}
+ MachOFile(StringRef path) : SimpleFile(path, File::kindMachObject) {}
void addDefinedAtom(StringRef name, Atom::Scope scope,
DefinedAtom::ContentType type, DefinedAtom::Merge merge,
@@ -187,16 +189,51 @@ public:
visitor(offAndAtom.atom, offAndAtom.offset);
}
+ MachOLinkingContext::Arch arch() const { return _arch; }
+ void setArch(MachOLinkingContext::Arch arch) { _arch = arch; }
+
+ MachOLinkingContext::OS OS() const { return _os; }
+ void setOS(MachOLinkingContext::OS os) { _os = os; }
+
+ MachOLinkingContext::ObjCConstraint objcConstraint() const {
+ return _objcConstraint;
+ }
+ void setObjcConstraint(MachOLinkingContext::ObjCConstraint v) {
+ _objcConstraint = v;
+ }
+
+ uint32_t minVersion() const { return _minVersion; }
+ void setMinVersion(uint32_t v) { _minVersion = v; }
+
+ LoadCommandType minVersionLoadCommandKind() const {
+ return _minVersionLoadCommandKind;
+ }
+ void setMinVersionLoadCommandKind(LoadCommandType v) {
+ _minVersionLoadCommandKind = v;
+ }
+
+ uint32_t swiftVersion() const { return _swiftVersion; }
+ void setSwiftVersion(uint32_t v) { _swiftVersion = v; }
+
+ bool subsectionsViaSymbols() const {
+ return _flags & llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
+ }
+ void setFlags(normalized::FileFlags v) { _flags = v; }
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const File *F) {
+ return F->kind() == File::kindMachObject;
+ }
+
protected:
std::error_code doParse() override {
// Convert binary file to normalized mach-o.
auto normFile = normalized::readBinary(_mb, _ctx->arch());
- if (std::error_code ec = normFile.getError())
- return ec;
+ if (auto ec = normFile.takeError())
+ return llvm::errorToErrorCode(std::move(ec));
// Convert normalized mach-o to atoms.
- if (std::error_code ec = normalized::normalizedObjectToAtoms(
- this, **normFile, false))
- return ec;
+ if (auto ec = normalized::normalizedObjectToAtoms(this, **normFile, false))
+ return llvm::errorToErrorCode(std::move(ec));
return std::error_code();
}
@@ -220,6 +257,14 @@ private:
MachOLinkingContext *_ctx;
SectionToAtoms _sectionAtoms;
NameToAtom _undefAtoms;
+ MachOLinkingContext::Arch _arch = MachOLinkingContext::arch_unknown;
+ MachOLinkingContext::OS _os = MachOLinkingContext::OS::unknown;
+ uint32_t _minVersion = 0;
+ LoadCommandType _minVersionLoadCommandKind = (LoadCommandType)0;
+ MachOLinkingContext::ObjCConstraint _objcConstraint =
+ MachOLinkingContext::objc_unknown;
+ uint32_t _swiftVersion = 0;
+ normalized::FileFlags _flags = llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
};
class MachODylibFile : public SharedLibraryFile {
@@ -230,7 +275,7 @@ public:
MachODylibFile(StringRef path) : SharedLibraryFile(path) {}
- const SharedLibraryAtom *exports(StringRef name, bool isData) const override {
+ OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const override {
// Pass down _installName so that if this requested symbol
// is re-exported through this dylib, the SharedLibraryAtom's loadName()
// is this dylib installName and not the implementation dylib's.
@@ -273,35 +318,39 @@ public:
std::error_code doParse() override {
// Convert binary file to normalized mach-o.
auto normFile = normalized::readBinary(_mb, _ctx->arch());
- if (std::error_code ec = normFile.getError())
- return ec;
+ if (auto ec = normFile.takeError())
+ return llvm::errorToErrorCode(std::move(ec));
// Convert normalized mach-o to atoms.
- if (std::error_code ec = normalized::normalizedDylibToAtoms(
- this, **normFile, false))
- return ec;
+ if (auto ec = normalized::normalizedDylibToAtoms(this, **normFile, false))
+ return llvm::errorToErrorCode(std::move(ec));
return std::error_code();
}
private:
- const SharedLibraryAtom *exports(StringRef name,
+ OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
StringRef installName) const {
// First, check if requested symbol is directly implemented by this dylib.
auto entry = _nameToAtom.find(name);
if (entry != _nameToAtom.end()) {
- if (!entry->second.atom) {
- // Lazily create SharedLibraryAtom.
- entry->second.atom =
- new (allocator()) MachOSharedLibraryAtom(*this, name, installName,
- entry->second.weakDef);
- }
- return entry->second.atom;
+ // FIXME: Make this map a set and only used in assert builds.
+ // Note, its safe to assert here as the resolver is the only client of
+ // this API and it only requests exports for undefined symbols.
+ // If we return from here we are no longer undefined so we should never
+ // get here again.
+ assert(!entry->second.atom && "Duplicate shared library export");
+ bool weakDef = entry->second.weakDef;
+ auto *atom = new (allocator()) MachOSharedLibraryAtom(*this, name,
+ installName,
+ weakDef);
+ entry->second.atom = atom;
+ return atom;
}
// Next, check if symbol is implemented in some re-exported dylib.
for (const ReExportedDylib &dylib : _reExportedDylibs) {
assert(dylib.file);
auto atom = dylib.file->exports(name, installName);
- if (atom)
+ if (atom.get())
return atom;
}
diff --git a/lib/ReaderWriter/MachO/FlatNamespaceFile.h b/lib/ReaderWriter/MachO/FlatNamespaceFile.h
index 6c6a9262ba2e..76d295841c9d 100644
--- a/lib/ReaderWriter/MachO/FlatNamespaceFile.h
+++ b/lib/ReaderWriter/MachO/FlatNamespaceFile.h
@@ -25,34 +25,34 @@ public:
FlatNamespaceFile(const MachOLinkingContext &context)
: SharedLibraryFile("flat namespace") { }
- const SharedLibraryAtom *exports(StringRef name,
- bool dataSymbolOnly) const override {
- _sharedLibraryAtoms.push_back(
- new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
- false));
-
- return _sharedLibraryAtoms.back();
+ OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const override {
+ return new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
+ false);
}
StringRef getDSOName() const override { return "flat-namespace"; }
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _noDefinedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
+ return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
-private:
- mutable AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
+ void clearAtoms() override {
+ _noDefinedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
};
} // namespace mach_o
diff --git a/lib/ReaderWriter/MachO/GOTPass.cpp b/lib/ReaderWriter/MachO/GOTPass.cpp
index a5816277dd71..6cdca0a9e055 100644
--- a/lib/ReaderWriter/MachO/GOTPass.cpp
+++ b/lib/ReaderWriter/MachO/GOTPass.cpp
@@ -54,6 +54,8 @@ public:
GOTEntryAtom(const File &file, bool is64, StringRef name)
: SimpleDefinedAtom(file), _is64(is64), _name(name) { }
+ ~GOTEntryAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeGOT;
}
@@ -91,10 +93,12 @@ class GOTPass : public Pass {
public:
GOTPass(const MachOLinkingContext &context)
: _ctx(context), _archHandler(_ctx.archHandler()),
- _file("<mach-o GOT Pass>") {}
+ _file(*_ctx.make_file<MachOFile>("<mach-o GOT Pass>")) {
+ _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
+ }
private:
- std::error_code perform(SimpleFile &mergedFile) override {
+ llvm::Error perform(SimpleFile &mergedFile) override {
// Scan all references in all atoms.
for (const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
@@ -130,7 +134,7 @@ private:
for (const GOTEntryAtom *slot : entries)
mergedFile.addAtom(*slot);
- return std::error_code();
+ return llvm::Error();
}
bool shouldReplaceTargetWithGOTAtom(const Atom *target, bool canBypassGOT) {
@@ -167,7 +171,7 @@ private:
const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
- MachOFile _file;
+ MachOFile &_file;
llvm::DenseMap<const Atom*, const GOTEntryAtom*> _targetToGOT;
};
diff --git a/lib/ReaderWriter/MachO/LayoutPass.cpp b/lib/ReaderWriter/MachO/LayoutPass.cpp
index 0c14ee9d39ab..dd2ee8567ec9 100644
--- a/lib/ReaderWriter/MachO/LayoutPass.cpp
+++ b/lib/ReaderWriter/MachO/LayoutPass.cpp
@@ -17,6 +17,7 @@
#include "llvm/Support/Debug.h"
#include <algorithm>
#include <set>
+#include <utility>
using namespace lld;
@@ -133,7 +134,7 @@ static void checkReachabilityFromRoot(AtomToAtomT &followOnRoots,
}
}
-static void printDefinedAtoms(const SimpleFile::DefinedAtomRange &atomRange) {
+static void printDefinedAtoms(const File::AtomRange<DefinedAtom> &atomRange) {
for (const DefinedAtom *atom : atomRange) {
llvm::dbgs() << " file=" << atom->file().path()
<< ", name=" << atom->name()
@@ -146,7 +147,7 @@ static void printDefinedAtoms(const SimpleFile::DefinedAtomRange &atomRange) {
/// Verify that the followon chain is sane. Should not be called in
/// release binary.
-void LayoutPass::checkFollowonChain(SimpleFile::DefinedAtomRange &range) {
+void LayoutPass::checkFollowonChain(const File::AtomRange<DefinedAtom> &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::checkFollowonChain");
// Verify that there's no cycle in follow-on chain.
@@ -176,8 +177,8 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
const LayoutPass::SortKey &rc,
LayoutPass::SortOverride customSorter,
std::string &reason) {
- const DefinedAtom *left = lc._atom;
- const DefinedAtom *right = rc._atom;
+ const DefinedAtom *left = lc._atom.get();
+ const DefinedAtom *right = rc._atom.get();
if (left == right) {
reason = "same";
return false;
@@ -252,14 +253,15 @@ static bool compareAtoms(const LayoutPass::SortKey &lc,
bool result = compareAtomsSub(lc, rc, customSorter, reason);
DEBUG({
StringRef comp = result ? "<" : ">=";
- llvm::dbgs() << "Layout: '" << lc._atom->name() << "' " << comp << " '"
- << rc._atom->name() << "' (" << reason << ")\n";
+ llvm::dbgs() << "Layout: '" << lc._atom.get()->name()
+ << "' " << comp << " '"
+ << rc._atom.get()->name() << "' (" << reason << ")\n";
});
return result;
}
LayoutPass::LayoutPass(const Registry &registry, SortOverride sorter)
- : _registry(registry), _customSorter(sorter) {}
+ : _registry(registry), _customSorter(std::move(sorter)) {}
// Returns the atom immediately followed by the given atom in the followon
// chain.
@@ -329,12 +331,12 @@ void LayoutPass::setChainRoot(const DefinedAtom *targetAtom,
/// d) If the targetAtom is part of a different chain and the root of the
/// targetAtom until the targetAtom has all atoms of size 0, then chain the
/// targetAtoms and its tree to the current chain
-void LayoutPass::buildFollowOnTable(SimpleFile::DefinedAtomRange &range) {
+void LayoutPass::buildFollowOnTable(const File::AtomRange<DefinedAtom> &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::buildFollowOnTable");
// Set the initial size of the followon and the followonNext hash to the
// number of atoms that we have.
- _followOnRoots.resize(range.size());
- _followOnNexts.resize(range.size());
+ _followOnRoots.reserve(range.size());
+ _followOnNexts.reserve(range.size());
for (const DefinedAtom *ai : range) {
for (const Reference *r : *ai) {
if (r->kindNamespace() != lld::Reference::KindNamespace::all ||
@@ -397,7 +399,8 @@ void LayoutPass::buildFollowOnTable(SimpleFile::DefinedAtomRange &range) {
/// assigning ordinals to each atom, if the atoms have their ordinals
/// already assigned skip the atom and move to the next. This is the
/// main map thats used to sort the atoms while comparing two atoms together
-void LayoutPass::buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range) {
+void
+LayoutPass::buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::buildOrdinalOverrideMap");
uint64_t index = 0;
for (const DefinedAtom *ai : range) {
@@ -417,31 +420,31 @@ void LayoutPass::buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range) {
}
std::vector<LayoutPass::SortKey>
-LayoutPass::decorate(SimpleFile::DefinedAtomRange &atomRange) const {
+LayoutPass::decorate(File::AtomRange<DefinedAtom> &atomRange) const {
std::vector<SortKey> ret;
- for (const DefinedAtom *atom : atomRange) {
- auto ri = _followOnRoots.find(atom);
- auto oi = _ordinalOverrideMap.find(atom);
- const DefinedAtom *root = (ri == _followOnRoots.end()) ? atom : ri->second;
+ for (OwningAtomPtr<DefinedAtom> &atom : atomRange.owning_ptrs()) {
+ auto ri = _followOnRoots.find(atom.get());
+ auto oi = _ordinalOverrideMap.find(atom.get());
+ const auto *root = (ri == _followOnRoots.end()) ? atom.get() : ri->second;
uint64_t override = (oi == _ordinalOverrideMap.end()) ? 0 : oi->second;
- ret.push_back(SortKey(atom, root, override));
+ ret.push_back(SortKey(std::move(atom), root, override));
}
return ret;
}
-void LayoutPass::undecorate(SimpleFile::DefinedAtomRange &atomRange,
+void LayoutPass::undecorate(File::AtomRange<DefinedAtom> &atomRange,
std::vector<SortKey> &keys) const {
size_t i = 0;
for (SortKey &k : keys)
- atomRange[i++] = k._atom;
+ atomRange[i++] = std::move(k._atom);
}
/// Perform the actual pass
-std::error_code LayoutPass::perform(SimpleFile &mergedFile) {
+llvm::Error LayoutPass::perform(SimpleFile &mergedFile) {
DEBUG(llvm::dbgs() << "******** Laying out atoms:\n");
// sort the atoms
ScopedTask task(getDefaultDomain(), "LayoutPass");
- SimpleFile::DefinedAtomRange atomRange = mergedFile.definedAtoms();
+ File::AtomRange<DefinedAtom> atomRange = mergedFile.defined();
// Build follow on tables
buildFollowOnTable(atomRange);
@@ -471,7 +474,7 @@ std::error_code LayoutPass::perform(SimpleFile &mergedFile) {
});
DEBUG(llvm::dbgs() << "******** Finished laying out atoms\n");
- return std::error_code();
+ return llvm::Error();
}
void addLayoutPass(PassManager &pm, const MachOLinkingContext &ctx) {
diff --git a/lib/ReaderWriter/MachO/LayoutPass.h b/lib/ReaderWriter/MachO/LayoutPass.h
index d6072b0ca4fb..c18777eded0a 100644
--- a/lib/ReaderWriter/MachO/LayoutPass.h
+++ b/lib/ReaderWriter/MachO/LayoutPass.h
@@ -33,11 +33,31 @@ namespace mach_o {
class LayoutPass : public Pass {
public:
struct SortKey {
- SortKey(const DefinedAtom *atom, const DefinedAtom *root, uint64_t override)
- : _atom(atom), _root(root), _override(override) {}
- const DefinedAtom *_atom;
+ SortKey(OwningAtomPtr<DefinedAtom> &&atom,
+ const DefinedAtom *root, uint64_t override)
+ : _atom(std::move(atom)), _root(root), _override(override) {}
+ OwningAtomPtr<DefinedAtom> _atom;
const DefinedAtom *_root;
uint64_t _override;
+
+ // Note, these are only here to appease MSVC bots which didn't like
+ // the same methods being implemented/deleted in OwningAtomPtr.
+ SortKey(SortKey &&key) : _atom(std::move(key._atom)), _root(key._root),
+ _override(key._override) {
+ key._root = nullptr;
+ }
+
+ SortKey &operator=(SortKey &&key) {
+ _atom = std::move(key._atom);
+ _root = key._root;
+ key._root = nullptr;
+ _override = key._override;
+ return *this;
+ }
+
+ private:
+ SortKey(const SortKey &) = delete;
+ void operator=(const SortKey&) = delete;
};
typedef std::function<bool (const DefinedAtom *left, const DefinedAtom *right,
@@ -46,17 +66,17 @@ public:
LayoutPass(const Registry &registry, SortOverride sorter);
/// Sorts atoms in mergedFile by content type then by command line order.
- std::error_code perform(SimpleFile &mergedFile) override;
+ llvm::Error perform(SimpleFile &mergedFile) override;
~LayoutPass() override = default;
private:
// Build the followOn atoms chain as specified by the kindLayoutAfter
// reference type
- void buildFollowOnTable(SimpleFile::DefinedAtomRange &range);
+ void buildFollowOnTable(const File::AtomRange<DefinedAtom> &range);
// Build a map of Atoms to ordinals for sorting the atoms
- void buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range);
+ void buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range);
const Registry &_registry;
SortOverride _customSorter;
@@ -84,12 +104,13 @@ private:
void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
- std::vector<SortKey> decorate(SimpleFile::DefinedAtomRange &atomRange) const;
- void undecorate(SimpleFile::DefinedAtomRange &atomRange,
+ std::vector<SortKey> decorate(File::AtomRange<DefinedAtom> &atomRange) const;
+
+ void undecorate(File::AtomRange<DefinedAtom> &atomRange,
std::vector<SortKey> &keys) const;
// Check if the follow-on graph is a correct structure. For debugging only.
- void checkFollowonChain(SimpleFile::DefinedAtomRange &range);
+ void checkFollowonChain(const File::AtomRange<DefinedAtom> &range);
};
} // namespace mach_o
diff --git a/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index 1c97c5a39d3f..05375f145d34 100644
--- a/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -35,6 +35,7 @@
#endif
using lld::mach_o::ArchHandler;
+using lld::mach_o::MachOFile;
using lld::mach_o::MachODylibFile;
using namespace llvm::MachO;
@@ -75,6 +76,35 @@ bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
return false;
}
+bool MachOLinkingContext::parsePackedVersion(StringRef str, uint64_t &result) {
+ result = 0;
+
+ if (str.empty())
+ return false;
+
+ SmallVector<StringRef, 5> parts;
+ llvm::SplitString(str, parts, ".");
+
+ unsigned long long num;
+ if (llvm::getAsUnsignedInteger(parts[0], 10, num))
+ return true;
+ if (num > 0xFFFFFF)
+ return true;
+ result = num << 40;
+
+ unsigned Shift = 30;
+ for (StringRef str : llvm::makeArrayRef(parts).slice(1)) {
+ if (llvm::getAsUnsignedInteger(str, 10, num))
+ return true;
+ if (num > 0x3FF)
+ return true;
+ result |= (num << Shift);
+ Shift -= 10;
+ }
+
+ return false;
+}
+
MachOLinkingContext::ArchInfo MachOLinkingContext::_s_archInfos[] = {
{ "x86_64", arch_x86_64, true, CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL },
{ "i386", arch_x86, true, CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL },
@@ -139,44 +169,52 @@ bool MachOLinkingContext::sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset,
return mach_o::normalized::sliceFromFatFile(mb, _arch, offset, size);
}
-MachOLinkingContext::MachOLinkingContext()
- : _outputMachOType(MH_EXECUTE), _outputMachOTypeStatic(false),
- _doNothing(false), _pie(false), _arch(arch_unknown), _os(OS::macOSX),
- _osMinVersion(0), _pageZeroSize(0), _pageSize(4096), _baseAddress(0),
- _stackSize(0), _compatibilityVersion(0), _currentVersion(0),
- _flatNamespace(false), _undefinedMode(UndefinedMode::error),
- _deadStrippableDylib(false), _printAtoms(false), _testingFileUsage(false),
- _keepPrivateExterns(false), _demangle(false), _archHandler(nullptr),
- _exportMode(ExportMode::globals),
- _debugInfoMode(DebugInfoMode::addDebugMap), _orderFileEntries(0),
- _flatNamespaceFile(nullptr) {}
-
-MachOLinkingContext::~MachOLinkingContext() {}
+MachOLinkingContext::MachOLinkingContext() {}
+
+MachOLinkingContext::~MachOLinkingContext() {
+ // Atoms are allocated on BumpPtrAllocator's on File's.
+ // As we transfer atoms from one file to another, we need to clear all of the
+ // atoms before we remove any of the BumpPtrAllocator's.
+ auto &nodes = getNodes();
+ for (unsigned i = 0, e = nodes.size(); i != e; ++i) {
+ FileNode *node = dyn_cast<FileNode>(nodes[i].get());
+ if (!node)
+ continue;
+ File *file = node->getFile();
+ file->clearAtoms();
+ }
+}
void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
- uint32_t minOSVersion) {
+ uint32_t minOSVersion,
+ bool exportDynamicSymbols) {
_outputMachOType = type;
_arch = arch;
_os = os;
_osMinVersion = minOSVersion;
// If min OS not specified on command line, use reasonable defaults.
- if (minOSVersion == 0) {
- switch (_arch) {
- case arch_x86_64:
- case arch_x86:
- parsePackedVersion("10.8", _osMinVersion);
- _os = MachOLinkingContext::OS::macOSX;
- break;
- case arch_armv6:
- case arch_armv7:
- case arch_armv7s:
- case arch_arm64:
- parsePackedVersion("7.0", _osMinVersion);
- _os = MachOLinkingContext::OS::iOS;
- break;
- default:
- break;
+ // Note that we only do sensible defaults when emitting something other than
+ // object and preload.
+ if (_outputMachOType != llvm::MachO::MH_OBJECT &&
+ _outputMachOType != llvm::MachO::MH_PRELOAD) {
+ if (minOSVersion == 0) {
+ switch (_arch) {
+ case arch_x86_64:
+ case arch_x86:
+ parsePackedVersion("10.8", _osMinVersion);
+ _os = MachOLinkingContext::OS::macOSX;
+ break;
+ case arch_armv6:
+ case arch_armv7:
+ case arch_armv7s:
+ case arch_arm64:
+ parsePackedVersion("7.0", _osMinVersion);
+ _os = MachOLinkingContext::OS::iOS;
+ break;
+ default:
+ break;
+ }
}
}
@@ -217,9 +255,10 @@ void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
case OS::unknown:
break;
}
+ setGlobalsAreDeadStripRoots(exportDynamicSymbols);
break;
case llvm::MachO::MH_DYLIB:
- setGlobalsAreDeadStripRoots(true);
+ setGlobalsAreDeadStripRoots(exportDynamicSymbols);
break;
case llvm::MachO::MH_BUNDLE:
break;
@@ -325,6 +364,11 @@ bool MachOLinkingContext::needsCompactUnwindPass() const {
}
}
+bool MachOLinkingContext::needsObjCPass() const {
+ // ObjC pass is only needed if any of the inputs were ObjC.
+ return _objcConstraint != objc_unknown;
+}
+
bool MachOLinkingContext::needsShimPass() const {
// Shim pass only used in final executables.
if (_outputMachOType == MH_OBJECT)
@@ -368,9 +412,11 @@ bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
return false;
return _osMinVersion >= parsedVersion;
case OS::unknown:
- break;
+ // If we don't know the target, then assume that we don't meet the min OS.
+ // This matches the ld64 behaviour
+ return false;
}
- llvm_unreachable("target not configured for iOS or MacOSX");
+ llvm_unreachable("invalid OS enum");
}
bool MachOLinkingContext::addEntryPointLoadCommand() const {
@@ -484,7 +530,7 @@ void MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath,
_frameworkDirs.push_back(fwPath);
}
-ErrorOr<StringRef>
+llvm::Optional<StringRef>
MachOLinkingContext::searchDirForLibrary(StringRef path,
StringRef libName) const {
SmallString<256> fullPath;
@@ -494,7 +540,7 @@ MachOLinkingContext::searchDirForLibrary(StringRef path,
llvm::sys::path::append(fullPath, libName);
if (fileExists(fullPath))
return fullPath.str().copy(_allocator);
- return make_error_code(llvm::errc::no_such_file_or_directory);
+ return llvm::None;
}
// Search for dynamic library
@@ -509,21 +555,23 @@ MachOLinkingContext::searchDirForLibrary(StringRef path,
if (fileExists(fullPath))
return fullPath.str().copy(_allocator);
- return make_error_code(llvm::errc::no_such_file_or_directory);
+ return llvm::None;
}
-ErrorOr<StringRef> MachOLinkingContext::searchLibrary(StringRef libName) const {
+llvm::Optional<StringRef>
+MachOLinkingContext::searchLibrary(StringRef libName) const {
SmallString<256> path;
for (StringRef dir : searchDirs()) {
- ErrorOr<StringRef> ec = searchDirForLibrary(dir, libName);
- if (ec)
- return ec;
+ llvm::Optional<StringRef> searchDir = searchDirForLibrary(dir, libName);
+ if (searchDir)
+ return searchDir;
}
- return make_error_code(llvm::errc::no_such_file_or_directory);
+ return llvm::None;
}
-ErrorOr<StringRef> MachOLinkingContext::findPathForFramework(StringRef fwName) const{
+llvm::Optional<StringRef>
+MachOLinkingContext::findPathForFramework(StringRef fwName) const{
SmallString<256> fullPath;
for (StringRef dir : frameworkDirs()) {
fullPath.assign(dir);
@@ -532,7 +580,7 @@ ErrorOr<StringRef> MachOLinkingContext::findPathForFramework(StringRef fwName) c
return fullPath.str().copy(_allocator);
}
- return make_error_code(llvm::errc::no_such_file_or_directory);
+ return llvm::None;
}
bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
@@ -589,6 +637,10 @@ bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
}
void MachOLinkingContext::addPasses(PassManager &pm) {
+ // objc pass should be before layout pass. Otherwise test cases may contain
+ // no atoms which confuses the layout pass.
+ if (needsObjCPass())
+ mach_o::addObjCPass(pm, *this);
mach_o::addLayoutPass(pm, *this);
if (needsStubsPass())
mach_o::addStubsPass(pm, *this);
@@ -656,9 +708,8 @@ MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) {
if (leafName.startswith("lib") && leafName.endswith(".dylib")) {
// FIXME: Need to enhance searchLibrary() to only look for .dylib
auto libPath = searchLibrary(leafName);
- if (!libPath.getError()) {
- return loadIndirectDylib(libPath.get());
- }
+ if (libPath)
+ return loadIndirectDylib(libPath.getValue());
}
// Try full path with sysroot.
@@ -990,4 +1041,77 @@ void MachOLinkingContext::finalizeInputFiles() {
elements.push_back(llvm::make_unique<GroupEnd>(numLibs));
}
+llvm::Error MachOLinkingContext::handleLoadedFile(File &file) {
+ auto *machoFile = dyn_cast<MachOFile>(&file);
+ if (!machoFile)
+ return llvm::Error();
+
+ // Check that the arch of the context matches that of the file.
+ // Also set the arch of the context if it didn't have one.
+ if (_arch == arch_unknown) {
+ _arch = machoFile->arch();
+ } else if (machoFile->arch() != arch_unknown && machoFile->arch() != _arch) {
+ // Archs are different.
+ return llvm::make_error<GenericError>(file.path() +
+ Twine(" cannot be linked due to incompatible architecture"));
+ }
+
+ // Check that the OS of the context matches that of the file.
+ // Also set the OS of the context if it didn't have one.
+ if (_os == OS::unknown) {
+ _os = machoFile->OS();
+ } else if (machoFile->OS() != OS::unknown && machoFile->OS() != _os) {
+ // OSes are different.
+ return llvm::make_error<GenericError>(file.path() +
+ Twine(" cannot be linked due to incompatible operating systems"));
+ }
+
+ // Check that if the objc info exists, that it is compatible with the target
+ // OS.
+ switch (machoFile->objcConstraint()) {
+ case objc_unknown:
+ // The file is not compiled with objc, so skip the checks.
+ break;
+ case objc_gc_only:
+ case objc_supports_gc:
+ llvm_unreachable("GC support should already have thrown an error");
+ case objc_retainReleaseForSimulator:
+ // The file is built with simulator objc, so make sure that the context
+ // is also building with simulator support.
+ if (_os != OS::iOS_simulator)
+ return llvm::make_error<GenericError>(file.path() +
+ Twine(" cannot be linked. It contains ObjC built for the simulator"
+ " while we are linking a non-simulator target"));
+ assert((_objcConstraint == objc_unknown ||
+ _objcConstraint == objc_retainReleaseForSimulator) &&
+ "Must be linking with retain/release for the simulator");
+ _objcConstraint = objc_retainReleaseForSimulator;
+ break;
+ case objc_retainRelease:
+ // The file is built without simulator objc, so make sure that the
+ // context is also building without simulator support.
+ if (_os == OS::iOS_simulator)
+ return llvm::make_error<GenericError>(file.path() +
+ Twine(" cannot be linked. It contains ObjC built for a non-simulator"
+ " target while we are linking a simulator target"));
+ assert((_objcConstraint == objc_unknown ||
+ _objcConstraint == objc_retainRelease) &&
+ "Must be linking with retain/release for a non-simulator target");
+ _objcConstraint = objc_retainRelease;
+ break;
+ }
+
+ // Check that the swift version of the context matches that of the file.
+ // Also set the swift version of the context if it didn't have one.
+ if (!_swiftVersion) {
+ _swiftVersion = machoFile->swiftVersion();
+ } else if (machoFile->swiftVersion() &&
+ machoFile->swiftVersion() != _swiftVersion) {
+ // Swift versions are different.
+ return llvm::make_error<GenericError>("different swift versions");
+ }
+
+ return llvm::Error();
+}
+
} // end namespace lld
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFile.h b/lib/ReaderWriter/MachO/MachONormalizedFile.h
index cccf180f1043..92a21f7ef83d 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFile.h
+++ b/lib/ReaderWriter/MachO/MachONormalizedFile.h
@@ -39,6 +39,9 @@
/// +-------+
///
+#ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
+#define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
+
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"
@@ -50,9 +53,6 @@
#include "llvm/Support/MachO.h"
#include "llvm/Support/YAMLTraits.h"
-#ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
-#define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
-
using llvm::BumpPtrAllocator;
using llvm::yaml::Hex64;
using llvm::yaml::Hex32;
@@ -105,6 +105,9 @@ typedef std::vector<uint32_t> IndirectSymbols;
/// A typedef so that YAML I/O can encode/decode section attributes.
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionAttr)
+/// A typedef so that YAML I/O can encode/decode section alignment.
+LLVM_YAML_STRONG_TYPEDEF(uint16_t, SectionAlignment)
+
/// Mach-O has a 32-bit and 64-bit section record. This normalized form
/// can support either kind.
struct Section {
@@ -115,7 +118,7 @@ struct Section {
StringRef sectionName;
SectionType type;
SectionAttr attributes;
- uint16_t alignment;
+ SectionAlignment alignment;
Hex64 address;
ArrayRef<uint8_t> content;
Relocations relocations;
@@ -172,7 +175,8 @@ struct Segment {
StringRef name;
Hex64 address;
Hex64 size;
- VMProtect access;
+ VMProtect init_access;
+ VMProtect max_access;
};
/// Only used in normalized final linked images to specify on which dylibs
@@ -245,6 +249,8 @@ struct NormalizedFile {
PackedVersion compatVersion = 0; // dylibs only
PackedVersion currentVersion = 0; // dylibs only
bool hasUUID = false;
+ bool hasMinVersionLoadCommand = false;
+ bool generateDataInCodeLoadCommand = false;
std::vector<StringRef> rpaths;
Hex64 entryAddress = 0;
Hex64 stackSize = 0;
@@ -252,6 +258,7 @@ struct NormalizedFile {
Hex64 sourceVersion = 0;
PackedVersion minOSverson = 0;
PackedVersion sdkVersion = 0;
+ LoadCommandType minOSVersionKind = (LoadCommandType)0;
// Maps to load commands with LINKEDIT content (final linked images only).
Hex32 pageSize = 0;
@@ -260,6 +267,7 @@ struct NormalizedFile {
std::vector<BindLocation> weakBindingInfo;
std::vector<BindLocation> lazyBindingInfo;
std::vector<Export> exportInfo;
+ std::vector<uint8_t> functionStarts;
std::vector<DataInCode> dataInCode;
// TODO:
@@ -281,40 +289,40 @@ bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
uint32_t &offset, uint32_t &size);
/// Reads a mach-o file and produces an in-memory normalized view.
-ErrorOr<std::unique_ptr<NormalizedFile>>
+llvm::Expected<std::unique_ptr<NormalizedFile>>
readBinary(std::unique_ptr<MemoryBuffer> &mb,
const MachOLinkingContext::Arch arch);
/// Takes in-memory normalized view and writes a mach-o object file.
-std::error_code writeBinary(const NormalizedFile &file, StringRef path);
+llvm::Error writeBinary(const NormalizedFile &file, StringRef path);
size_t headerAndLoadCommandsSize(const NormalizedFile &file);
/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
-ErrorOr<std::unique_ptr<NormalizedFile>>
+llvm::Expected<std::unique_ptr<NormalizedFile>>
readYaml(std::unique_ptr<MemoryBuffer> &mb);
/// Writes a yaml encoded mach-o files given an in-memory normalized view.
std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out);
-std::error_code
+llvm::Error
normalizedObjectToAtoms(MachOFile *file,
const NormalizedFile &normalizedFile,
bool copyRefs);
-std::error_code
+llvm::Error
normalizedDylibToAtoms(MachODylibFile *file,
const NormalizedFile &normalizedFile,
bool copyRefs);
/// Takes in-memory normalized dylib or object and parses it into lld::File
-ErrorOr<std::unique_ptr<lld::File>>
+llvm::Expected<std::unique_ptr<lld::File>>
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
bool copyRefs);
/// Takes atoms and generates a normalized macho-o view.
-ErrorOr<std::unique_ptr<NormalizedFile>>
+llvm::Expected<std::unique_ptr<NormalizedFile>>
normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &ctxt);
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
index 1013d3ddaef3..a17de5be1742 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
@@ -53,7 +53,7 @@ namespace mach_o {
namespace normalized {
// Utility to call a lambda expression on each load command.
-static std::error_code forEachLoadCommand(
+static llvm::Error forEachLoadCommand(
StringRef lcRange, unsigned lcCount, bool isBig, bool is64,
std::function<bool(uint32_t cmd, uint32_t size, const char *lc)> func) {
const char* p = lcRange.begin();
@@ -67,15 +67,15 @@ static std::error_code forEachLoadCommand(
slc = &lcCopy;
}
if ( (p + slc->cmdsize) > lcRange.end() )
- return make_error_code(llvm::errc::executable_format_error);
+ return llvm::make_error<GenericError>("Load command exceeds range");
if (func(slc->cmd, slc->cmdsize, p))
- return std::error_code();
+ return llvm::Error();
p += slc->cmdsize;
}
- return std::error_code();
+ return llvm::Error();
}
static std::error_code appendRelocations(Relocations &relocs, StringRef buffer,
@@ -199,7 +199,7 @@ bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
}
/// Reads a mach-o file and produces an in-memory normalized view.
-ErrorOr<std::unique_ptr<NormalizedFile>>
+llvm::Expected<std::unique_ptr<NormalizedFile>>
readBinary(std::unique_ptr<MemoryBuffer> &mb,
const MachOLinkingContext::Arch arch) {
// Make empty NormalizedFile.
@@ -220,7 +220,7 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
// Determine endianness and pointer size for mach-o file.
bool is64, isBig;
if (!isMachOHeader(mh, is64, isBig))
- return make_error_code(llvm::errc::executable_format_error);
+ return llvm::make_error<GenericError>("File is not a mach-o");
// Endian swap header, if needed.
mach_header headerCopy;
@@ -237,12 +237,13 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
start + (is64 ? sizeof(mach_header_64) : sizeof(mach_header));
StringRef lcRange(lcStart, smh->sizeofcmds);
if (lcRange.end() > (start + objSize))
- return make_error_code(llvm::errc::executable_format_error);
+ return llvm::make_error<GenericError>("Load commands exceed file size");
// Get architecture from mach_header.
f->arch = MachOLinkingContext::archFromCpuType(smh->cputype, smh->cpusubtype);
if (f->arch != arch) {
- return make_dynamic_error_code(Twine("file is wrong architecture. Expected "
+ return llvm::make_error<GenericError>(
+ Twine("file is wrong architecture. Expected "
"(" + MachOLinkingContext::nameFromArch(arch)
+ ") found ("
+ MachOLinkingContext::nameFromArch(f->arch)
@@ -256,9 +257,9 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
// Pre-scan load commands looking for indirect symbol table.
uint32_t indirectSymbolTableOffset = 0;
uint32_t indirectSymbolTableCount = 0;
- std::error_code ec = forEachLoadCommand(lcRange, lcCount, isBig, is64,
- [&](uint32_t cmd, uint32_t size,
- const char *lc) -> bool {
+ auto ec = forEachLoadCommand(lcRange, lcCount, isBig, is64,
+ [&](uint32_t cmd, uint32_t size,
+ const char *lc) -> bool {
if (cmd == LC_DYSYMTAB) {
const dysymtab_command *d = reinterpret_cast<const dysymtab_command*>(lc);
indirectSymbolTableOffset = read32(&d->indirectsymoff, isBig);
@@ -268,7 +269,7 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
return false;
});
if (ec)
- return ec;
+ return std::move(ec);
// Walk load commands looking for segments/sections and the symbol table.
const data_in_code_entry *dataInCode = nullptr;
@@ -380,11 +381,11 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
reinterpret_cast<const nlist_64 *>(start + symOffset);
// Convert each nlist_64 to a lld::mach_o::normalized::Symbol.
for(uint32_t i=0; i < symCount; ++i) {
- const nlist_64 *sin = &symbols[i];
nlist_64 tempSym;
- if (isBig != llvm::sys::IsBigEndianHost) {
- tempSym = *sin; swapStruct(tempSym); sin = &tempSym;
- }
+ memcpy(&tempSym, &symbols[i], sizeof(nlist_64));
+ const nlist_64 *sin = &tempSym;
+ if (isBig != llvm::sys::IsBigEndianHost)
+ swapStruct(tempSym);
Symbol sout;
if (sin->n_strx > strSize)
return true;
@@ -471,11 +472,20 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
case LC_DYLD_INFO_ONLY:
dyldInfo = reinterpret_cast<const dyld_info_command*>(lc);
break;
+ case LC_VERSION_MIN_MACOSX:
+ case LC_VERSION_MIN_IPHONEOS:
+ case LC_VERSION_MIN_WATCHOS:
+ case LC_VERSION_MIN_TVOS:
+ // If we are emitting an object file, then we may take the load command
+ // kind from these commands and pass it on to the output
+ // file.
+ f->minOSVersionKind = (LoadCommandType)cmd;
+ break;
}
return false;
});
if (ec)
- return ec;
+ return std::move(ec);
if (dataInCode) {
// Convert on-disk data_in_code_entry array to DataInCode vector.
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
index 1226860b021e..86823efa33c9 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
+#define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
#include "MachONormalizedFile.h"
#include "lld/Core/Error.h"
@@ -16,16 +18,54 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MachO.h"
#include <system_error>
-#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
-#define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
-
namespace lld {
namespace mach_o {
namespace normalized {
+class ByteBuffer {
+public:
+ ByteBuffer() : _ostream(_bytes) { }
+
+ void append_byte(uint8_t b) {
+ _ostream << b;
+ }
+ void append_uleb128(uint64_t value) {
+ llvm::encodeULEB128(value, _ostream);
+ }
+ void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
+ unsigned min = llvm::getULEB128Size(value);
+ assert(min <= byteCount);
+ unsigned pad = byteCount - min;
+ llvm::encodeULEB128(value, _ostream, pad);
+ }
+ void append_sleb128(int64_t value) {
+ llvm::encodeSLEB128(value, _ostream);
+ }
+ void append_string(StringRef str) {
+ _ostream << str;
+ append_byte(0);
+ }
+ void align(unsigned alignment) {
+ while ( (_ostream.tell() % alignment) != 0 )
+ append_byte(0);
+ }
+ size_t size() {
+ return _ostream.tell();
+ }
+ const uint8_t *bytes() {
+ return reinterpret_cast<const uint8_t*>(_ostream.str().data());
+ }
+
+private:
+ SmallVector<char, 128> _bytes;
+ // Stream ivar must be after SmallVector ivar to construct properly.
+ llvm::raw_svector_ostream _ostream;
+};
+
using namespace llvm::support::endian;
using llvm::sys::getSwappedBytes;
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
index 4ecfece0629e..f3e159684e15 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
@@ -25,6 +25,8 @@
#include "MachONormalizedFileBinaryUtils.h"
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -35,7 +37,6 @@
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/LEB128.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
@@ -50,6 +51,72 @@ namespace lld {
namespace mach_o {
namespace normalized {
+struct TrieNode; // Forward declaration.
+
+struct TrieEdge : public llvm::ilist_node<TrieEdge> {
+ TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
+
+ StringRef _subString;
+ struct TrieNode *_child;
+};
+
+} // namespace normalized
+} // namespace mach_o
+} // namespace lld
+
+
+namespace llvm {
+ using lld::mach_o::normalized::TrieEdge;
+ template <>
+ struct ilist_traits<TrieEdge>
+ : public ilist_default_traits<TrieEdge> {
+ private:
+ mutable ilist_half_node<TrieEdge> Sentinel;
+ public:
+ TrieEdge *createSentinel() const {
+ return static_cast<TrieEdge*>(&Sentinel);
+ }
+ void destroySentinel(TrieEdge *) const {}
+
+ TrieEdge *provideInitialHead() const { return createSentinel(); }
+ TrieEdge *ensureHead(TrieEdge*) const { return createSentinel(); }
+ static void noteHead(TrieEdge*, TrieEdge*) {}
+ void deleteNode(TrieEdge *N) {}
+
+ private:
+ void createNode(const TrieEdge &);
+ };
+} // namespace llvm
+
+
+namespace lld {
+namespace mach_o {
+namespace normalized {
+
+struct TrieNode {
+ typedef llvm::ilist<TrieEdge> TrieEdgeList;
+
+ TrieNode(StringRef s)
+ : _cummulativeString(s), _address(0), _flags(0), _other(0),
+ _trieOffset(0), _hasExportInfo(false) {}
+ ~TrieNode() = default;
+
+ void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
+ std::vector<TrieNode *> &allNodes);
+ bool updateOffset(uint32_t &offset);
+ void appendToByteBuffer(ByteBuffer &out);
+
+private:
+ StringRef _cummulativeString;
+ TrieEdgeList _children;
+ uint64_t _address;
+ uint64_t _flags;
+ uint64_t _other;
+ StringRef _importedName;
+ uint32_t _trieOffset;
+ bool _hasExportInfo;
+};
+
/// Utility class for writing a mach-o binary file given an in-memory
/// normalized file.
class MachOFileLayout {
@@ -66,13 +133,13 @@ public:
/// Writes the normalized file as a binary mach-o file to the specified
/// path. This does not have a stream interface because the generated
/// file may need the 'x' bit set.
- std::error_code writeBinary(StringRef path);
+ llvm::Error writeBinary(StringRef path);
private:
uint32_t loadCommandsSize(uint32_t &count);
void buildFileOffsets();
void writeMachHeader();
- std::error_code writeLoadCommands();
+ llvm::Error writeLoadCommands();
void writeSectionContent();
void writeRelocations();
void writeSymbolTable();
@@ -80,6 +147,7 @@ private:
void writeBindingInfo();
void writeLazyBindingInfo();
void writeExportInfo();
+ void writeFunctionStartsInfo();
void writeDataInCodeInfo();
void writeLinkEditContent();
void buildLinkEditInfo();
@@ -87,6 +155,7 @@ private:
void buildBindInfo();
void buildLazyBindInfo();
void buildExportTrie();
+ void computeFunctionStartsSize();
void computeDataInCodeSize();
void computeSymbolTableSizes();
void buildSectionRelocations();
@@ -110,83 +179,12 @@ private:
};
template <typename T>
- std::error_code writeSingleSegmentLoadCommand(uint8_t *&lc);
- template <typename T> std::error_code writeSegmentLoadCommands(uint8_t *&lc);
+ llvm::Error writeSingleSegmentLoadCommand(uint8_t *&lc);
+ template <typename T> llvm::Error writeSegmentLoadCommands(uint8_t *&lc);
uint32_t pointerAlign(uint32_t value);
static StringRef dyldPath();
- class ByteBuffer {
- public:
- ByteBuffer() : _ostream(_bytes) { }
-
- void append_byte(uint8_t b) {
- _ostream << b;
- }
- void append_uleb128(uint64_t value) {
- llvm::encodeULEB128(value, _ostream);
- }
- void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
- unsigned min = llvm::getULEB128Size(value);
- assert(min <= byteCount);
- unsigned pad = byteCount - min;
- llvm::encodeULEB128(value, _ostream, pad);
- }
- void append_sleb128(int64_t value) {
- llvm::encodeSLEB128(value, _ostream);
- }
- void append_string(StringRef str) {
- _ostream << str;
- append_byte(0);
- }
- void align(unsigned alignment) {
- while ( (_ostream.tell() % alignment) != 0 )
- append_byte(0);
- }
- size_t size() {
- return _ostream.tell();
- }
- const uint8_t *bytes() {
- return reinterpret_cast<const uint8_t*>(_ostream.str().data());
- }
-
- private:
- SmallVector<char, 128> _bytes;
- // Stream ivar must be after SmallVector ivar to construct properly.
- llvm::raw_svector_ostream _ostream;
- };
-
- struct TrieNode; // Forward declaration.
-
- struct TrieEdge {
- TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
-
- StringRef _subString;
- struct TrieNode *_child;
- };
-
- struct TrieNode {
- TrieNode(StringRef s)
- : _cummulativeString(s), _address(0), _flags(0), _other(0),
- _trieOffset(0), _hasExportInfo(false) {}
- ~TrieNode() = default;
-
- void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
- std::vector<TrieNode *> &allNodes);
- bool updateOffset(uint32_t &offset);
- void appendToByteBuffer(ByteBuffer &out);
-
- private:
- StringRef _cummulativeString;
- std::list<TrieEdge> _children;
- uint64_t _address;
- uint64_t _flags;
- uint64_t _other;
- StringRef _importedName;
- uint32_t _trieOffset;
- bool _hasExportInfo;
- };
-
struct SegExtraInfo {
uint32_t fileOffset;
uint32_t fileSize;
@@ -209,6 +207,7 @@ private:
uint32_t _countOfLoadCommands;
uint32_t _endOfLoadCommands;
uint32_t _startOfRelocations;
+ uint32_t _startOfFunctionStarts;
uint32_t _startOfDataInCode;
uint32_t _startOfSymbols;
uint32_t _startOfIndirectSymbols;
@@ -219,6 +218,7 @@ private:
uint32_t _symbolTableUndefinesStartIndex;
uint32_t _symbolStringPoolSize;
uint32_t _symbolTableSize;
+ uint32_t _functionStartsSize;
uint32_t _dataInCodeSize;
uint32_t _indirectSymbolTableCount;
// Used in object file creation only
@@ -255,7 +255,7 @@ StringRef MachOFileLayout::dyldPath() {
}
uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
- return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4);
+ return llvm::alignTo(value, _is64 ? 8 : 4);
}
@@ -280,7 +280,15 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
+ file.sections.size() * sectsSize
+ sizeof(symtab_command);
_countOfLoadCommands = 2;
- if (!_file.dataInCode.empty()) {
+ if (file.hasMinVersionLoadCommand) {
+ _endOfLoadCommands += sizeof(version_min_command);
+ _countOfLoadCommands++;
+ }
+ if (!_file.functionStarts.empty()) {
+ _endOfLoadCommands += sizeof(linkedit_data_command);
+ _countOfLoadCommands++;
+ }
+ if (_file.generateDataInCodeLoadCommand) {
_endOfLoadCommands += sizeof(linkedit_data_command);
_countOfLoadCommands++;
}
@@ -292,7 +300,7 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
if (isZeroFillSection(sect.type))
_sectInfo[&sect].fileOffset = 0;
else {
- offset = llvm::RoundUpToAlignment(offset, sect.alignment);
+ offset = llvm::alignTo(offset, sect.alignment);
_sectInfo[&sect].fileOffset = offset;
offset += sect.content.size();
}
@@ -301,11 +309,13 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
_endOfSectionsContent = offset;
computeSymbolTableSizes();
+ computeFunctionStartsSize();
computeDataInCodeSize();
// Align start of relocations.
_startOfRelocations = pointerAlign(_endOfSectionsContent);
- _startOfDataInCode = _startOfRelocations + relocCount * 8;
+ _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
+ _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
_startOfSymbols = _startOfDataInCode + _dataInCodeSize;
// Add Indirect symbol table.
_startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
@@ -346,7 +356,8 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
_endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
_startOfExportTrie = _endOfLazyBindingInfo;
_endOfExportTrie = _startOfExportTrie + _exportTrie.size();
- _startOfDataInCode = _endOfExportTrie;
+ _startOfFunctionStarts = _endOfExportTrie;
+ _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
_startOfSymbols = _startOfDataInCode + _dataInCodeSize;
_startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
_startOfSymbolStrings = _startOfIndirectSymbols
@@ -368,6 +379,7 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
<< " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
<< " startOfExportTrie=" << _startOfExportTrie << "\n"
<< " endOfExportTrie=" << _endOfExportTrie << "\n"
+ << " startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
<< " startOfDataInCode=" << _startOfDataInCode << "\n"
<< " startOfSymbols=" << _startOfSymbols << "\n"
<< " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
@@ -389,9 +401,6 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
count += _file.segments.size();
// Add section record for each section.
size += _file.sections.size() * sectionSize;
- // Add one LC_SEGMENT for implicit __LINKEDIT segment
- size += segCommandSize;
- ++count;
// If creating a dylib, add LC_ID_DYLIB.
if (_file.fileType == llvm::MachO::MH_DYLIB) {
@@ -413,10 +422,25 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
++count;
}
- // If main executable add LC_LOAD_DYLINKER and LC_MAIN
+ // If main executable add LC_LOAD_DYLINKER
if (_file.fileType == llvm::MachO::MH_EXECUTE) {
size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
++count;
+ }
+
+ // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
+ // LC_VERSION_MIN_TVOS
+ if (_file.hasMinVersionLoadCommand) {
+ size += sizeof(version_min_command);
+ ++count;
+ }
+
+ // Add LC_SOURCE_VERSION
+ size += sizeof(source_version_command);
+ ++count;
+
+ // If main executable add LC_MAIN
+ if (_file.fileType == llvm::MachO::MH_EXECUTE) {
size += sizeof(entry_point_command);
++count;
}
@@ -433,8 +457,15 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
++count;
}
- // Add LC_DATA_IN_CODE if needed
- if (!_file.dataInCode.empty()) {
+ // Add LC_FUNCTION_STARTS if needed
+ if (!_file.functionStarts.empty()) {
+ size += sizeof(linkedit_data_command);
+ ++count;
+ }
+
+ // Add LC_DATA_IN_CODE if requested. Note, we do encode zero length entries.
+ // FIXME: Zero length entries is only to match ld64. Should we change this?
+ if (_file.generateDataInCodeLoadCommand) {
size += sizeof(linkedit_data_command);
++count;
}
@@ -517,7 +548,7 @@ void MachOFileLayout::buildFileOffsets() {
llvm::dbgs() << "buildFileOffsets()\n");
for (const Segment &sg : _file.segments) {
_segInfo[&sg].fileOffset = fileOffset;
- if ((_seg1addr == INT64_MAX) && sg.access)
+ if ((_seg1addr == INT64_MAX) && sg.init_access)
_seg1addr = sg.address;
DEBUG_WITH_TYPE("MachOFileLayout",
llvm::dbgs() << " segment=" << sg.name
@@ -525,7 +556,7 @@ void MachOFileLayout::buildFileOffsets() {
uint32_t segFileSize = 0;
// A segment that is not zero-fill must use a least one page of disk space.
- if (sg.access)
+ if (sg.init_access)
segFileSize = _file.pageSize;
for (const Section *s : _segInfo[&sg].sections) {
uint32_t sectOffset = s->address - sg.address;
@@ -539,10 +570,11 @@ void MachOFileLayout::buildFileOffsets() {
<< ", fileOffset=" << fileOffset << "\n");
}
- _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize,
- _file.pageSize);
- fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize,
- _file.pageSize);
+ // round up all segments to page aligned, except __LINKEDIT
+ if (!sg.name.equals("__LINKEDIT")) {
+ _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
+ fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
+ }
_addressOfLinkEdit = sg.address + sg.size;
}
_startOfLinkEdit = fileOffset;
@@ -553,10 +585,23 @@ size_t MachOFileLayout::size() const {
}
void MachOFileLayout::writeMachHeader() {
+ auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
+ // dynamic x86 executables on newer OS version should also set the
+ // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
+ // FIXME: Check that this is a dynamic executable, not a static one.
+ if (_file.fileType == llvm::MachO::MH_EXECUTE &&
+ cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
+ _file.os == MachOLinkingContext::OS::macOSX) {
+ uint32_t version;
+ bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
+ if (!failed && _file.minOSverson >= version)
+ cpusubtype |= CPU_SUBTYPE_LIB64;
+ }
+
mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
- mh->cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
+ mh->cpusubtype = cpusubtype;
mh->filetype = _file.fileType;
mh->ncmds = _countOfLoadCommands;
mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
@@ -583,7 +628,7 @@ uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
}
template <typename T>
-std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
+llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
seg->cmd = T::LC;
seg->cmdsize = sizeof(typename T::command)
@@ -623,15 +668,37 @@ std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
++sout;
}
lc = next;
- return std::error_code();
+ return llvm::Error();
}
template <typename T>
-std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
+llvm::Error MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
uint32_t indirectSymRunningIndex = 0;
for (const Segment &seg : _file.segments) {
- // Write segment command with trailing sections.
+ // Link edit has no sections and a custom range of address, so handle it
+ // specially.
SegExtraInfo &segInfo = _segInfo[&seg];
+ if (seg.name.equals("__LINKEDIT")) {
+ size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
+ typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
+ cmd->cmd = T::LC;
+ cmd->cmdsize = sizeof(typename T::command);
+ uint8_t *next = lc + cmd->cmdsize;
+ setString16("__LINKEDIT", cmd->segname);
+ cmd->vmaddr = _addressOfLinkEdit;
+ cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
+ cmd->fileoff = _startOfLinkEdit;
+ cmd->filesize = linkeditSize;
+ cmd->initprot = seg.init_access;
+ cmd->maxprot = seg.max_access;
+ cmd->nsects = 0;
+ cmd->flags = 0;
+ if (_swap)
+ swapStruct(*cmd);
+ lc = next;
+ continue;
+ }
+ // Write segment command with trailing sections.
typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
cmd->cmd = T::LC;
cmd->cmdsize = sizeof(typename T::command)
@@ -642,8 +709,8 @@ std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
cmd->vmsize = seg.size;
cmd->fileoff = segInfo.fileOffset;
cmd->filesize = segInfo.fileSize;
- cmd->maxprot = seg.access;
- cmd->initprot = seg.access;
+ cmd->initprot = seg.init_access;
+ cmd->maxprot = seg.max_access;
cmd->nsects = segInfo.sections.size();
cmd->flags = 0;
if (_swap)
@@ -671,36 +738,52 @@ std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
}
lc = reinterpret_cast<uint8_t*>(next);
}
- // Add implicit __LINKEDIT segment
- size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
- typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
- cmd->cmd = T::LC;
- cmd->cmdsize = sizeof(typename T::command);
- uint8_t *next = lc + cmd->cmdsize;
- setString16("__LINKEDIT", cmd->segname);
- cmd->vmaddr = _addressOfLinkEdit;
- cmd->vmsize = llvm::RoundUpToAlignment(linkeditSize, _file.pageSize);
- cmd->fileoff = _startOfLinkEdit;
- cmd->filesize = linkeditSize;
- cmd->maxprot = VM_PROT_READ;
- cmd->initprot = VM_PROT_READ;
- cmd->nsects = 0;
- cmd->flags = 0;
+ return llvm::Error();
+}
+
+static void writeVersionMinLoadCommand(const NormalizedFile &_file,
+ bool _swap,
+ uint8_t *&lc) {
+ if (!_file.hasMinVersionLoadCommand)
+ return;
+ version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
+ switch (_file.os) {
+ case MachOLinkingContext::OS::unknown:
+ vm->cmd = _file.minOSVersionKind;
+ vm->cmdsize = sizeof(version_min_command);
+ vm->version = _file.minOSverson;
+ vm->sdk = 0;
+ break;
+ case MachOLinkingContext::OS::macOSX:
+ vm->cmd = LC_VERSION_MIN_MACOSX;
+ vm->cmdsize = sizeof(version_min_command);
+ vm->version = _file.minOSverson;
+ vm->sdk = _file.sdkVersion;
+ break;
+ case MachOLinkingContext::OS::iOS:
+ case MachOLinkingContext::OS::iOS_simulator:
+ vm->cmd = LC_VERSION_MIN_IPHONEOS;
+ vm->cmdsize = sizeof(version_min_command);
+ vm->version = _file.minOSverson;
+ vm->sdk = _file.sdkVersion;
+ break;
+ }
if (_swap)
- swapStruct(*cmd);
- lc = next;
- return std::error_code();
+ swapStruct(*vm);
+ lc += sizeof(version_min_command);
}
-std::error_code MachOFileLayout::writeLoadCommands() {
- std::error_code ec;
+llvm::Error MachOFileLayout::writeLoadCommands() {
uint8_t *lc = &_buffer[_startOfLoadCommands];
if (_file.fileType == llvm::MachO::MH_OBJECT) {
// Object files have one unnamed segment which holds all sections.
- if (_is64)
- ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc);
- else
- ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc);
+ if (_is64) {
+ if (auto ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc))
+ return ec;
+ } else {
+ if (auto ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc))
+ return ec;
+ }
// Add LC_SYMTAB with symbol table info
symtab_command* st = reinterpret_cast<symtab_command*>(lc);
st->cmd = LC_SYMTAB;
@@ -713,8 +796,25 @@ std::error_code MachOFileLayout::writeLoadCommands() {
if (_swap)
swapStruct(*st);
lc += sizeof(symtab_command);
- // Add LC_DATA_IN_CODE if needed.
- if (_dataInCodeSize != 0) {
+
+ // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
+ // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
+ writeVersionMinLoadCommand(_file, _swap, lc);
+
+ // Add LC_FUNCTION_STARTS if needed.
+ if (_functionStartsSize != 0) {
+ linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
+ dl->cmd = LC_FUNCTION_STARTS;
+ dl->cmdsize = sizeof(linkedit_data_command);
+ dl->dataoff = _startOfFunctionStarts;
+ dl->datasize = _functionStartsSize;
+ if (_swap)
+ swapStruct(*dl);
+ lc += sizeof(linkedit_data_command);
+ }
+
+ // Add LC_DATA_IN_CODE if requested.
+ if (_file.generateDataInCodeLoadCommand) {
linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
dl->cmd = LC_DATA_IN_CODE;
dl->cmdsize = sizeof(linkedit_data_command);
@@ -726,10 +826,13 @@ std::error_code MachOFileLayout::writeLoadCommands() {
}
} else {
// Final linked images have sections under segments.
- if (_is64)
- ec = writeSegmentLoadCommands<MachO64Trait>(lc);
- else
- ec = writeSegmentLoadCommands<MachO32Trait>(lc);
+ if (_is64) {
+ if (auto ec = writeSegmentLoadCommands<MachO64Trait>(lc))
+ return ec;
+ } else {
+ if (auto ec = writeSegmentLoadCommands<MachO32Trait>(lc))
+ return ec;
+ }
// Add LC_ID_DYLIB command for dynamic libraries.
if (_file.fileType == llvm::MachO::MH_DYLIB) {
@@ -809,7 +912,7 @@ std::error_code MachOFileLayout::writeLoadCommands() {
lc += sizeof(dysymtab_command);
}
- // If main executable, add LC_LOAD_DYLINKER and LC_MAIN.
+ // If main executable, add LC_LOAD_DYLINKER
if (_file.fileType == llvm::MachO::MH_EXECUTE) {
// Build LC_LOAD_DYLINKER load command.
uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
@@ -822,14 +925,39 @@ std::error_code MachOFileLayout::writeLoadCommands() {
memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
lc += size;
+ }
+
+ // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
+ // LC_VERSION_MIN_TVOS
+ writeVersionMinLoadCommand(_file, _swap, lc);
+
+ // Add LC_SOURCE_VERSION
+ {
+ // Note, using a temporary here to appease UB as we may not be aligned
+ // enough for a struct containing a uint64_t when emitting a 32-bit binary
+ source_version_command sv;
+ sv.cmd = LC_SOURCE_VERSION;
+ sv.cmdsize = sizeof(source_version_command);
+ sv.version = _file.sourceVersion;
+ if (_swap)
+ swapStruct(sv);
+ memcpy(lc, &sv, sizeof(source_version_command));
+ lc += sizeof(source_version_command);
+ }
+
+ // If main executable, add LC_MAIN.
+ if (_file.fileType == llvm::MachO::MH_EXECUTE) {
// Build LC_MAIN load command.
- entry_point_command* ep = reinterpret_cast<entry_point_command*>(lc);
- ep->cmd = LC_MAIN;
- ep->cmdsize = sizeof(entry_point_command);
- ep->entryoff = _file.entryAddress - _seg1addr;
- ep->stacksize = _file.stackSize;
+ // Note, using a temporary here to appease UB as we may not be aligned
+ // enough for a struct containing a uint64_t when emitting a 32-bit binary
+ entry_point_command ep;
+ ep.cmd = LC_MAIN;
+ ep.cmdsize = sizeof(entry_point_command);
+ ep.entryoff = _file.entryAddress - _seg1addr;
+ ep.stacksize = _file.stackSize;
if (_swap)
- swapStruct(*ep);
+ swapStruct(ep);
+ memcpy(lc, &ep, sizeof(entry_point_command));
lc += sizeof(entry_point_command);
}
@@ -865,8 +993,20 @@ std::error_code MachOFileLayout::writeLoadCommands() {
lc += size;
}
- // Add LC_DATA_IN_CODE if needed.
- if (_dataInCodeSize != 0) {
+ // Add LC_FUNCTION_STARTS if needed.
+ if (_functionStartsSize != 0) {
+ linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
+ dl->cmd = LC_FUNCTION_STARTS;
+ dl->cmdsize = sizeof(linkedit_data_command);
+ dl->dataoff = _startOfFunctionStarts;
+ dl->datasize = _functionStartsSize;
+ if (_swap)
+ swapStruct(*dl);
+ lc += sizeof(linkedit_data_command);
+ }
+
+ // Add LC_DATA_IN_CODE if requested.
+ if (_file.generateDataInCodeLoadCommand) {
linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
dl->cmd = LC_DATA_IN_CODE;
dl->cmdsize = sizeof(linkedit_data_command);
@@ -877,7 +1017,7 @@ std::error_code MachOFileLayout::writeLoadCommands() {
lc += sizeof(linkedit_data_command);
}
}
- return ec;
+ return llvm::Error();
}
void MachOFileLayout::writeSectionContent() {
@@ -936,6 +1076,13 @@ void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
}
}
+void MachOFileLayout::writeFunctionStartsInfo() {
+ if (!_functionStartsSize)
+ return;
+ memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
+ _functionStartsSize);
+}
+
void MachOFileLayout::writeDataInCodeInfo() {
uint32_t offset = _startOfDataInCode;
for (const DataInCode &entry : _file.dataInCode) {
@@ -1011,6 +1158,7 @@ void MachOFileLayout::buildLinkEditInfo() {
buildLazyBindInfo();
buildExportTrie();
computeSymbolTableSizes();
+ computeFunctionStartsSize();
computeDataInCodeSize();
}
@@ -1079,9 +1227,9 @@ void MachOFileLayout::buildLazyBindInfo() {
_lazyBindingInfo.align(_is64 ? 8 : 4);
}
-void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
- BumpPtrAllocator &allocator,
- std::vector<TrieNode*> &allNodes) {
+void TrieNode::addSymbol(const Export& entry,
+ BumpPtrAllocator &allocator,
+ std::vector<TrieNode*> &allNodes) {
StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
for (TrieEdge &edge : _children) {
StringRef edgeStr = edge._subString;
@@ -1110,7 +1258,7 @@ void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
abEdge._subString = abEdgeStr;
abEdge._child = bNode;
auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
- bNode->_children.push_back(std::move(*bcEdge));
+ bNode->_children.insert(bNode->_children.end(), bcEdge);
bNode->addSymbol(entry, allocator, allNodes);
return;
}
@@ -1125,7 +1273,7 @@ void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
// No commonality with any existing child, make a new edge.
auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
- _children.push_back(std::move(*newEdge));
+ _children.insert(_children.end(), newEdge);
DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
<< "new TrieNode('" << entry.name << "') with edge '"
<< partialStr << "' from node='"
@@ -1139,7 +1287,7 @@ void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
allNodes.push_back(newNode);
}
-bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) {
+bool TrieNode::updateOffset(uint32_t& offset) {
uint32_t nodeSize = 1; // Length when no export info
if (_hasExportInfo) {
if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
@@ -1171,7 +1319,7 @@ bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) {
return result;
}
-void MachOFileLayout::TrieNode::appendToByteBuffer(ByteBuffer &out) {
+void TrieNode::appendToByteBuffer(ByteBuffer &out) {
if (_hasExportInfo) {
if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
if (!_importedName.empty()) {
@@ -1290,6 +1438,10 @@ void MachOFileLayout::computeSymbolTableSizes() {
}
}
+void MachOFileLayout::computeFunctionStartsSize() {
+ _functionStartsSize = _file.functionStarts.size();
+}
+
void MachOFileLayout::computeDataInCodeSize() {
_dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
}
@@ -1297,6 +1449,7 @@ void MachOFileLayout::computeDataInCodeSize() {
void MachOFileLayout::writeLinkEditContent() {
if (_file.fileType == llvm::MachO::MH_OBJECT) {
writeRelocations();
+ writeFunctionStartsInfo();
writeDataInCodeInfo();
writeSymbolTable();
} else {
@@ -1305,15 +1458,16 @@ void MachOFileLayout::writeLinkEditContent() {
writeLazyBindingInfo();
// TODO: add weak binding info
writeExportInfo();
+ writeFunctionStartsInfo();
writeDataInCodeInfo();
writeSymbolTable();
}
}
-std::error_code MachOFileLayout::writeBinary(StringRef path) {
+llvm::Error MachOFileLayout::writeBinary(StringRef path) {
// Check for pending error from constructor.
if (_ec)
- return _ec;
+ return llvm::errorCodeToError(_ec);
// Create FileOutputBuffer with calculated size.
unsigned flags = 0;
if (_file.fileType != llvm::MachO::MH_OBJECT)
@@ -1321,23 +1475,22 @@ std::error_code MachOFileLayout::writeBinary(StringRef path) {
ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
llvm::FileOutputBuffer::create(path, size(), flags);
if (std::error_code ec = fobOrErr.getError())
- return ec;
+ return llvm::errorCodeToError(ec);
std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
// Write content.
_buffer = fob->getBufferStart();
writeMachHeader();
- std::error_code ec = writeLoadCommands();
- if (ec)
+ if (auto ec = writeLoadCommands())
return ec;
writeSectionContent();
writeLinkEditContent();
fob->commit();
- return std::error_code();
+ return llvm::Error();
}
/// Takes in-memory normalized view and writes a mach-o object file.
-std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
+llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
MachOFileLayout layout(file);
return layout.writeBinary(path);
}
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index 575bc1a2b3a9..4775c75f7211 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -92,23 +92,27 @@ struct SegmentInfo {
StringRef name;
uint64_t address;
uint64_t size;
- uint32_t access;
+ uint32_t init_access;
+ uint32_t max_access;
std::vector<SectionInfo*> sections;
uint32_t normalizedSegmentIndex;
};
SegmentInfo::SegmentInfo(StringRef n)
- : name(n), address(0), size(0), access(0), normalizedSegmentIndex(0) {
+ : name(n), address(0), size(0), init_access(0), max_access(0),
+ normalizedSegmentIndex(0) {
}
class Util {
public:
Util(const MachOLinkingContext &ctxt)
: _ctx(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr),
- _hasTLVDescriptors(false) {}
+ _hasTLVDescriptors(false), _subsectionsViaSymbols(true) {}
~Util();
- void assignAtomsToSections(const lld::File &atomFile);
+ void processDefinedAtoms(const lld::File &atomFile);
+ void processAtomAttributes(const DefinedAtom *atom);
+ void assignAtomToSection(const DefinedAtom *atom);
void organizeSections();
void assignAddressesToSections(const NormalizedFile &file);
uint32_t fileFlags();
@@ -116,16 +120,29 @@ public:
void copySectionInfo(NormalizedFile &file);
void updateSectionInfo(NormalizedFile &file);
void buildAtomToAddressMap();
- std::error_code addSymbols(const lld::File &atomFile, NormalizedFile &file);
+ llvm::Error addSymbols(const lld::File &atomFile, NormalizedFile &file);
void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
void addExportInfo(const lld::File &, NormalizedFile &file);
void addSectionRelocs(const lld::File &, NormalizedFile &file);
+ void addFunctionStarts(const lld::File &, NormalizedFile &file);
void buildDataInCodeArray(const lld::File &, NormalizedFile &file);
void addDependentDylibs(const lld::File &, NormalizedFile &file);
void copyEntryPointAddress(NormalizedFile &file);
void copySectionContent(NormalizedFile &file);
+ bool allSourceFilesHaveMinVersions() const {
+ return _allSourceFilesHaveMinVersions;
+ }
+
+ uint32_t minVersion() const {
+ return _minVersion;
+ }
+
+ LoadCommandType minVersionCommandType() const {
+ return _minVersionCommandType;
+ }
+
private:
typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection;
typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
@@ -147,9 +164,9 @@ private:
uint8_t &segmentIndex, uint64_t &segmentStartAddr);
const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom);
const Atom *targetOfStub(const DefinedAtom *stubAtom);
- std::error_code getSymbolTableRegion(const DefinedAtom* atom,
- bool &inGlobalsRegion,
- SymbolScope &symbolScope);
+ llvm::Error getSymbolTableRegion(const DefinedAtom* atom,
+ bool &inGlobalsRegion,
+ SymbolScope &symbolScope);
void appendSection(SectionInfo *si, NormalizedFile &file);
uint32_t sectionIndexForAtom(const Atom *atom);
@@ -180,6 +197,10 @@ private:
AtomToIndex _atomToSymbolIndex;
std::vector<const Atom *> _machHeaderAliasAtoms;
bool _hasTLVDescriptors;
+ bool _subsectionsViaSymbols;
+ bool _allSourceFilesHaveMinVersions = true;
+ LoadCommandType _minVersionCommandType = (LoadCommandType)0;
+ uint32_t _minVersion = 0;
};
Util::~Util() {
@@ -239,6 +260,7 @@ struct MachOFinalSectionFromAtomType {
const MachOFinalSectionFromAtomType sectsToAtomType[] = {
ENTRY("__TEXT", "__text", S_REGULAR, typeCode),
+ ENTRY("__TEXT", "__text", S_REGULAR, typeMachHeader),
ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString),
ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String),
ENTRY("__TEXT", "__const", S_REGULAR, typeConstant),
@@ -261,6 +283,8 @@ const MachOFinalSectionFromAtomType sectsToAtomType[] = {
typeTerminatorPtr),
ENTRY("__DATA", "__got", S_NON_LAZY_SYMBOL_POINTERS,
typeGOT),
+ ENTRY("__DATA", "__nl_symbol_ptr", S_NON_LAZY_SYMBOL_POINTERS,
+ typeNonLazyPointer),
ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES,
typeThunkTLV),
ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR,
@@ -280,10 +304,11 @@ SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
continue;
SectionAttr sectionAttrs = 0;
switch (atomType) {
+ case DefinedAtom::typeMachHeader:
case DefinedAtom::typeCode:
case DefinedAtom::typeStub:
case DefinedAtom::typeStubHelper:
- sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
+ sectionAttrs = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS;
break;
case DefinedAtom::typeThunkTLV:
_hasTLVDescriptors = true;
@@ -366,27 +391,85 @@ void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) {
sect->size = offset + atom->size();
}
-void Util::assignAtomsToSections(const lld::File &atomFile) {
+void Util::processDefinedAtoms(const lld::File &atomFile) {
for (const DefinedAtom *atom : atomFile.defined()) {
- if (atom->contentType() == DefinedAtom::typeMachHeader)
- _machHeaderAliasAtoms.push_back(atom);
+ processAtomAttributes(atom);
+ assignAtomToSection(atom);
+ }
+}
+
+void Util::processAtomAttributes(const DefinedAtom *atom) {
+ if (auto *machoFile = dyn_cast<mach_o::MachOFile>(&atom->file())) {
+ // If the file doesn't use subsections via symbols, then make sure we don't
+ // add that flag to the final output file if we have a relocatable file.
+ if (!machoFile->subsectionsViaSymbols())
+ _subsectionsViaSymbols = false;
+
+ // All the source files must have min versions for us to output an object
+ // file with a min version.
+ if (auto v = machoFile->minVersion())
+ _minVersion = std::max(_minVersion, v);
else
- appendAtom(sectionForAtom(atom), atom);
+ _allSourceFilesHaveMinVersions = false;
+
+ // If we don't have a platform load command, but one of the source files
+ // does, then take the one from the file.
+ if (!_minVersionCommandType)
+ if (auto v = machoFile->minVersionLoadCommandKind())
+ _minVersionCommandType = v;
}
}
+void Util::assignAtomToSection(const DefinedAtom *atom) {
+ if (atom->contentType() == DefinedAtom::typeMachHeader) {
+ _machHeaderAliasAtoms.push_back(atom);
+ // Assign atom to this section with this offset.
+ AtomInfo ai = {atom, 0};
+ sectionForAtom(atom)->atomsAndOffsets.push_back(ai);
+ } else if (atom->contentType() == DefinedAtom::typeDSOHandle)
+ _machHeaderAliasAtoms.push_back(atom);
+ else
+ appendAtom(sectionForAtom(atom), atom);
+}
+
SegmentInfo *Util::segmentForName(StringRef segName) {
for (SegmentInfo *si : _segmentInfos) {
if ( si->name.equals(segName) )
return si;
}
auto *info = new (_allocator) SegmentInfo(segName);
+
+ // Set the initial segment protection.
if (segName.equals("__TEXT"))
- info->access = VM_PROT_READ | VM_PROT_EXECUTE;
- else if (segName.equals("__DATA"))
- info->access = VM_PROT_READ | VM_PROT_WRITE;
+ info->init_access = VM_PROT_READ | VM_PROT_EXECUTE;
else if (segName.equals("__PAGEZERO"))
- info->access = 0;
+ info->init_access = 0;
+ else if (segName.equals("__LINKEDIT"))
+ info->init_access = VM_PROT_READ;
+ else {
+ // All others default to read-write
+ info->init_access = VM_PROT_READ | VM_PROT_WRITE;
+ }
+
+ // Set max segment protection
+ // Note, its overkill to use a switch statement here, but makes it so much
+ // easier to use switch coverage to catch new cases.
+ switch (_ctx.os()) {
+ case lld::MachOLinkingContext::OS::unknown:
+ case lld::MachOLinkingContext::OS::macOSX:
+ case lld::MachOLinkingContext::OS::iOS_simulator:
+ if (segName.equals("__PAGEZERO")) {
+ info->max_access = 0;
+ break;
+ }
+ // All others default to all
+ info->max_access = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
+ break;
+ case lld::MachOLinkingContext::OS::iOS:
+ // iPhoneOS always uses same protection for max and initial
+ info->max_access = info->init_access;
+ break;
+ }
_segmentInfos.push_back(info);
return info;
}
@@ -436,6 +519,8 @@ void Util::organizeSections() {
default:
break;
}
+ segmentForName("__LINKEDIT");
+
// Group sections into segments.
for (SectionInfo *si : _sectionInfos) {
SegmentInfo *seg = segmentForName(si->segmentName);
@@ -465,10 +550,10 @@ void Util::organizeSections() {
void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) {
seg->address = addr;
for (SectionInfo *sect : seg->sections) {
- sect->address = llvm::RoundUpToAlignment(addr, sect->alignment);
+ sect->address = llvm::alignTo(addr, sect->alignment);
addr = sect->address + sect->size;
}
- seg->size = llvm::RoundUpToAlignment(addr - seg->address, _ctx.pageSize());
+ seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize());
}
// __TEXT segment lays out backwards so padding is at front after load commands.
@@ -488,10 +573,10 @@ void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
// Start assigning section address starting at padded offset.
addr += (padding + hlcSize);
for (SectionInfo *sect : seg->sections) {
- sect->address = llvm::RoundUpToAlignment(addr, sect->alignment);
+ sect->address = llvm::alignTo(addr, sect->alignment);
addr = sect->address + sect->size;
}
- seg->size = llvm::RoundUpToAlignment(addr - seg->address, _ctx.pageSize());
+ seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize());
}
void Util::assignAddressesToSections(const NormalizedFile &file) {
@@ -511,7 +596,7 @@ void Util::assignAddressesToSections(const NormalizedFile &file) {
} else
layoutSectionsInSegment(seg, address);
- address = llvm::RoundUpToAlignment(address, _ctx.pageSize());
+ address = llvm::alignTo(address, _ctx.pageSize());
}
DEBUG_WITH_TYPE("WriterMachO-norm",
llvm::dbgs() << "assignAddressesToSections()\n";
@@ -536,7 +621,8 @@ void Util::copySegmentInfo(NormalizedFile &file) {
seg.name = sgi->name;
seg.address = sgi->address;
seg.size = sgi->size;
- seg.access = sgi->access;
+ seg.init_access = sgi->init_access;
+ seg.max_access = sgi->max_access;
file.segments.push_back(seg);
}
}
@@ -583,11 +669,20 @@ void Util::copySectionContent(NormalizedFile &file) {
continue;
}
// Copy content from atoms to content buffer for section.
- uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
- normSect->content = llvm::makeArrayRef(sectionContent, si->size);
+ llvm::MutableArrayRef<uint8_t> sectionContent;
+ if (si->size) {
+ uint8_t *sectContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
+ sectionContent = llvm::MutableArrayRef<uint8_t>(sectContent, si->size);
+ normSect->content = sectionContent;
+ }
for (AtomInfo &ai : si->atomsAndOffsets) {
- uint8_t *atomContent = reinterpret_cast<uint8_t*>
- (&sectionContent[ai.offsetInSection]);
+ if (!ai.atom->size()) {
+ assert(ai.atom->begin() == ai.atom->end() &&
+ "Cannot have references without content");
+ continue;
+ }
+ auto atomContent = sectionContent.slice(ai.offsetInSection,
+ ai.atom->size());
_archHandler.generateAtomContent(*ai.atom, r, addrForAtom,
sectionAddrForAtom, _ctx.baseAddress(),
atomContent);
@@ -620,6 +715,11 @@ void Util::updateSectionInfo(NormalizedFile &file) {
}
void Util::copyEntryPointAddress(NormalizedFile &nFile) {
+ if (!_entryAtom) {
+ nFile.entryAddress = 0;
+ return;
+ }
+
if (_ctx.outputTypeHasEntry()) {
if (_archHandler.isThumbFunction(*_entryAtom))
nFile.entryAddress = (_atomToAddress[_entryAtom] | 1);
@@ -703,6 +803,8 @@ uint16_t Util::descBits(const DefinedAtom* atom) {
}
if (atom->contentType() == lld::DefinedAtom::typeResolver)
desc |= N_SYMBOL_RESOLVER;
+ if (atom->contentType() == lld::DefinedAtom::typeMachHeader)
+ desc |= REFERENCED_DYNAMICALLY;
if (_archHandler.isThumbFunction(*atom))
desc |= N_ARM_THUMB_DEF;
if (atom->deadStrip() == DefinedAtom::deadStripNever) {
@@ -718,56 +820,56 @@ bool Util::AtomSorter::operator()(const AtomAndIndex &left,
return (left.atom->name().compare(right.atom->name()) < 0);
}
-std::error_code Util::getSymbolTableRegion(const DefinedAtom* atom,
- bool &inGlobalsRegion,
- SymbolScope &scope) {
+llvm::Error Util::getSymbolTableRegion(const DefinedAtom* atom,
+ bool &inGlobalsRegion,
+ SymbolScope &scope) {
bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
switch (atom->scope()) {
case Atom::scopeTranslationUnit:
scope = 0;
inGlobalsRegion = false;
- return std::error_code();
+ return llvm::Error();
case Atom::scopeLinkageUnit:
if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) &&
_ctx.exportSymbolNamed(atom->name())) {
- return make_dynamic_error_code(Twine("cannot export hidden symbol ")
- + atom->name());
+ return llvm::make_error<GenericError>(
+ Twine("cannot export hidden symbol ") + atom->name());
}
if (rMode) {
if (_ctx.keepPrivateExterns()) {
// -keep_private_externs means keep in globals region as N_PEXT.
scope = N_PEXT | N_EXT;
inGlobalsRegion = true;
- return std::error_code();
+ return llvm::Error();
}
}
// scopeLinkageUnit symbols are no longer global once linked.
scope = N_PEXT;
inGlobalsRegion = false;
- return std::error_code();
+ return llvm::Error();
case Atom::scopeGlobal:
if (_ctx.exportRestrictMode()) {
if (_ctx.exportSymbolNamed(atom->name())) {
scope = N_EXT;
inGlobalsRegion = true;
- return std::error_code();
+ return llvm::Error();
} else {
scope = N_PEXT;
inGlobalsRegion = false;
- return std::error_code();
+ return llvm::Error();
}
} else {
scope = N_EXT;
inGlobalsRegion = true;
- return std::error_code();
+ return llvm::Error();
}
break;
}
llvm_unreachable("atom->scope() unknown enum value");
}
-std::error_code Util::addSymbols(const lld::File &atomFile,
- NormalizedFile &file) {
+llvm::Error Util::addSymbols(const lld::File &atomFile,
+ NormalizedFile &file) {
bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
// Mach-O symbol table has three regions: locals, globals, undefs.
@@ -863,7 +965,7 @@ std::error_code Util::addSymbols(const lld::File &atomFile,
file.undefinedSymbols.push_back(sym);
}
- return std::error_code();
+ return llvm::Error();
}
const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
@@ -1055,7 +1157,53 @@ void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
}
}
+void Util::addFunctionStarts(const lld::File &, NormalizedFile &file) {
+ if (!_ctx.generateFunctionStartsLoadCommand())
+ return;
+ file.functionStarts.reserve(8192);
+ // Delta compress function starts, starting with the mach header symbol.
+ const uint64_t badAddress = ~0ULL;
+ uint64_t addr = badAddress;
+ for (SectionInfo *si : _sectionInfos) {
+ for (const AtomInfo &info : si->atomsAndOffsets) {
+ auto type = info.atom->contentType();
+ if (type == DefinedAtom::typeMachHeader) {
+ addr = _atomToAddress[info.atom];
+ continue;
+ }
+ if (type != DefinedAtom::typeCode)
+ continue;
+ assert(addr != badAddress && "Missing mach header symbol");
+ // Skip atoms which have 0 size. This is so that LC_FUNCTION_STARTS
+ // can't spill in to the next section.
+ if (!info.atom->size())
+ continue;
+ uint64_t nextAddr = _atomToAddress[info.atom];
+ if (_archHandler.isThumbFunction(*info.atom))
+ nextAddr |= 1;
+ uint64_t delta = nextAddr - addr;
+ if (delta) {
+ ByteBuffer buffer;
+ buffer.append_uleb128(delta);
+ file.functionStarts.insert(file.functionStarts.end(), buffer.bytes(),
+ buffer.bytes() + buffer.size());
+ }
+ addr = nextAddr;
+ }
+ }
+
+ // Null terminate, and pad to pointer size for this arch.
+ file.functionStarts.push_back(0);
+
+ auto size = file.functionStarts.size();
+ for (unsigned i = size, e = llvm::alignTo(size, _ctx.is64Bit() ? 8 : 4);
+ i != e; ++i)
+ file.functionStarts.push_back(0);
+}
+
void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) {
+ if (!_ctx.generateDataInCodeLoadCommand())
+ return;
for (SectionInfo *si : _sectionInfos) {
for (const AtomInfo &info : si->atomsAndOffsets) {
// Atoms that contain data-in-code have "transition" references
@@ -1183,7 +1331,7 @@ void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) {
uint32_t Util::fileFlags() {
// FIXME: these need to determined at runtime.
if (_ctx.outputMachOType() == MH_OBJECT) {
- return MH_SUBSECTIONS_VIA_SYMBOLS;
+ return _subsectionsViaSymbols ? MH_SUBSECTIONS_VIA_SYMBOLS : 0;
} else {
uint32_t flags = MH_DYLDLINK;
if (!_ctx.useFlatNamespace())
@@ -1203,12 +1351,12 @@ namespace mach_o {
namespace normalized {
/// Convert a set of Atoms into a normalized mach-o file.
-ErrorOr<std::unique_ptr<NormalizedFile>>
+llvm::Expected<std::unique_ptr<NormalizedFile>>
normalizedFromAtoms(const lld::File &atomFile,
const MachOLinkingContext &context) {
// The util object buffers info until the normalized file can be made.
Util util(context);
- util.assignAtomsToSections(atomFile);
+ util.processDefinedAtoms(atomFile);
util.organizeSections();
std::unique_ptr<NormalizedFile> f(new NormalizedFile());
@@ -1220,6 +1368,35 @@ normalizedFromAtoms(const lld::File &atomFile,
normFile.installName = context.installName();
normFile.currentVersion = context.currentVersion();
normFile.compatVersion = context.compatibilityVersion();
+ normFile.os = context.os();
+
+ // If we are emitting an object file, then the min version is the maximum
+ // of the min's of all the source files and the cmdline.
+ if (normFile.fileType == llvm::MachO::MH_OBJECT)
+ normFile.minOSverson = std::max(context.osMinVersion(), util.minVersion());
+ else
+ normFile.minOSverson = context.osMinVersion();
+
+ normFile.minOSVersionKind = util.minVersionCommandType();
+
+ normFile.sdkVersion = context.sdkVersion();
+ normFile.sourceVersion = context.sourceVersion();
+
+ if (context.generateVersionLoadCommand() &&
+ context.os() != MachOLinkingContext::OS::unknown)
+ normFile.hasMinVersionLoadCommand = true;
+ else if (normFile.fileType == llvm::MachO::MH_OBJECT &&
+ util.allSourceFilesHaveMinVersions() &&
+ ((normFile.os != MachOLinkingContext::OS::unknown) ||
+ util.minVersionCommandType())) {
+ // If we emit an object file, then it should contain a min version load
+ // command if all of the source files also contained min version commands.
+ // Also, we either need to have a platform, or found a platform from the
+ // source object files.
+ normFile.hasMinVersionLoadCommand = true;
+ }
+ normFile.generateDataInCodeLoadCommand =
+ context.generateDataInCodeLoadCommand();
normFile.pageSize = context.pageSize();
normFile.rpaths = context.rpaths();
util.addDependentDylibs(atomFile, normFile);
@@ -1230,12 +1407,13 @@ normalizedFromAtoms(const lld::File &atomFile,
util.updateSectionInfo(normFile);
util.copySectionContent(normFile);
if (auto ec = util.addSymbols(atomFile, normFile)) {
- return ec;
+ return std::move(ec);
}
util.addIndirectSymbols(atomFile, normFile);
util.addRebaseAndBindingInfo(atomFile, normFile);
util.addExportInfo(atomFile, normFile);
util.addSectionRelocs(atomFile, normFile);
+ util.addFunctionStarts(atomFile, normFile);
util.buildDataInCodeArray(atomFile, normFile);
util.copyEntryPointAddress(normFile);
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index f9499b603214..fc760a3eddd0 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -88,6 +88,8 @@ const MachORelocatableSectionToAtomType sectsToAtomType[] = {
ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData),
ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL,
typeTLVInitialZeroFill),
+ ENTRY("__DATA", "__objc_imageinfo", S_REGULAR, typeObjCImageInfo),
+ ENTRY("__DATA", "__objc_catlist", S_REGULAR, typeObjC2CategoryList),
ENTRY("", "", S_INTERPOSING, typeInterposingTuples),
ENTRY("__LD", "__compact_unwind", S_REGULAR,
typeCompactUnwindInfo),
@@ -180,6 +182,8 @@ void sectionParseInfo(DefinedAtom::ContentType atomType,
atomizeCU),
ENTRY(typeGOT, 4, scopeLinkageUnit, mergeByContent,
atomizePointerSize),
+ ENTRY(typeObjC2CategoryList, 4, scopeTranslationUnit, mergeByContent,
+ atomizePointerSize),
ENTRY(typeUnknown, 1, scopeGlobal, mergeNo,
atomizeAtSymbols)
};
@@ -265,11 +269,11 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
}
}
-std::error_code processSymboledSection(DefinedAtom::ContentType atomType,
- const Section &section,
- const NormalizedFile &normalizedFile,
- MachOFile &file, bool scatterable,
- bool copyRefs) {
+llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
+ const Section &section,
+ const NormalizedFile &normalizedFile,
+ MachOFile &file, bool scatterable,
+ bool copyRefs) {
// Find section's index.
uint32_t sectIndex = 1;
for (auto &sect : normalizedFile.sections) {
@@ -316,7 +320,7 @@ std::error_code processSymboledSection(DefinedAtom::ContentType atomType,
// If section has no symbols and no content, there are no atoms.
if (symbols.empty() && section.content.empty())
- return std::error_code();
+ return llvm::Error();
if (symbols.empty()) {
// Section has no symbols, put all content in one anoymous atom.
@@ -360,22 +364,22 @@ std::error_code processSymboledSection(DefinedAtom::ContentType atomType,
file.eachAtomInSection(section,
[&](MachODefinedAtom *atom, uint64_t offset)->void {
if (prevAtom)
- prevAtom->addReference(0, Reference::kindLayoutAfter, atom, 0,
+ prevAtom->addReference(Reference::KindNamespace::all,
Reference::KindArch::all,
- Reference::KindNamespace::all);
+ Reference::kindLayoutAfter, 0, atom, 0);
prevAtom = atom;
});
}
- return std::error_code();
+ return llvm::Error();
}
-std::error_code processSection(DefinedAtom::ContentType atomType,
- const Section &section,
- bool customSectionName,
- const NormalizedFile &normalizedFile,
- MachOFile &file, bool scatterable,
- bool copyRefs) {
+llvm::Error processSection(DefinedAtom::ContentType atomType,
+ const Section &section,
+ bool customSectionName,
+ const NormalizedFile &normalizedFile,
+ MachOFile &file, bool scatterable,
+ bool copyRefs) {
const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
@@ -388,12 +392,13 @@ std::error_code processSection(DefinedAtom::ContentType atomType,
// Validate section size.
if ((section.content.size() % sizeMultiple) != 0)
- return make_dynamic_error_code(Twine("Section ") + section.segmentName
- + "/" + section.sectionName
- + " has size ("
- + Twine(section.content.size())
- + ") which is not a multiple of "
- + Twine(sizeMultiple) );
+ return llvm::make_error<GenericError>(Twine("Section ")
+ + section.segmentName
+ + "/" + section.sectionName
+ + " has size ("
+ + Twine(section.content.size())
+ + ") which is not a multiple of "
+ + Twine(sizeMultiple));
if (atomizeModel == atomizeAtSymbols) {
// Break section up into atoms each with a fixed size.
@@ -435,13 +440,13 @@ std::error_code processSection(DefinedAtom::ContentType atomType,
// Break section up into dwarf unwind CFIs (FDE or CIE).
size = read32(&section.content[offset], isBig) + 4;
if (offset+size > section.content.size()) {
- return make_dynamic_error_code(Twine(Twine("Section ")
- + section.segmentName
- + "/" + section.sectionName
- + " is malformed. Size of CFI "
- "starting at offset ("
- + Twine(offset)
- + ") is past end of section."));
+ return llvm::make_error<GenericError>(Twine("Section ")
+ + section.segmentName
+ + "/" + section.sectionName
+ + " is malformed. Size of CFI "
+ "starting at offset ("
+ + Twine(offset)
+ + ") is past end of section.");
}
break;
case atomizeCU:
@@ -456,10 +461,11 @@ std::error_code processSection(DefinedAtom::ContentType atomType,
break;
}
if (size == 0) {
- return make_dynamic_error_code(Twine("Section ") + section.segmentName
- + "/" + section.sectionName
- + " is malformed. The last atom is "
- "not zero terminated.");
+ return llvm::make_error<GenericError>(Twine("Section ")
+ + section.segmentName
+ + "/" + section.sectionName
+ + " is malformed. The last atom "
+ "is not zero terminated.");
}
if (customSectionName) {
// Mach-O needs a segment and section name. Concatentate those two
@@ -477,7 +483,7 @@ std::error_code processSection(DefinedAtom::ContentType atomType,
offset += size;
}
}
- return std::error_code();
+ return llvm::Error();
}
const Section* findSectionCoveringAddress(const NormalizedFile &normalizedFile,
@@ -509,23 +515,23 @@ findAtomCoveringAddress(const NormalizedFile &normalizedFile, MachOFile &file,
// Walks all relocations for a section in a normalized .o file and
// creates corresponding lld::Reference objects.
-std::error_code convertRelocs(const Section &section,
- const NormalizedFile &normalizedFile,
- bool scatterable,
- MachOFile &file,
- ArchHandler &handler) {
+llvm::Error convertRelocs(const Section &section,
+ const NormalizedFile &normalizedFile,
+ bool scatterable,
+ MachOFile &file,
+ ArchHandler &handler) {
// Utility function for ArchHandler to find atom by its address.
auto atomByAddr = [&] (uint32_t sectIndex, uint64_t addr,
const lld::Atom **atom, Reference::Addend *addend)
- -> std::error_code {
+ -> llvm::Error {
if (sectIndex > normalizedFile.sections.size())
- return make_dynamic_error_code(Twine("out of range section "
+ return llvm::make_error<GenericError>(Twine("out of range section "
"index (") + Twine(sectIndex) + ")");
const Section *sect = nullptr;
if (sectIndex == 0) {
sect = findSectionCoveringAddress(normalizedFile, addr);
if (!sect)
- return make_dynamic_error_code(Twine("address (" + Twine(addr)
+ return llvm::make_error<GenericError>(Twine("address (" + Twine(addr)
+ ") is not in any section"));
} else {
sect = &normalizedFile.sections[sectIndex-1];
@@ -534,12 +540,12 @@ std::error_code convertRelocs(const Section &section,
uint64_t offsetInSect = addr - sect->address;
*atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
*addend = offsetInTarget;
- return std::error_code();
+ return llvm::Error();
};
// Utility function for ArchHandler to find atom by its symbol index.
auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
- -> std::error_code {
+ -> llvm::Error {
// Find symbol from index.
const Symbol *sym = nullptr;
uint32_t numLocal = normalizedFile.localSymbols.size();
@@ -552,13 +558,13 @@ std::error_code convertRelocs(const Section &section,
} else if (symbolIndex < numLocal+numGlobal+numUndef) {
sym = &normalizedFile.undefinedSymbols[symbolIndex-numLocal-numGlobal];
} else {
- return make_dynamic_error_code(Twine("symbol index (")
+ return llvm::make_error<GenericError>(Twine("symbol index (")
+ Twine(symbolIndex) + ") out of range");
}
// Find atom from symbol.
if ((sym->type & N_TYPE) == N_SECT) {
if (sym->sect > normalizedFile.sections.size())
- return make_dynamic_error_code(Twine("symbol section index (")
+ return llvm::make_error<GenericError>(Twine("symbol section index (")
+ Twine(sym->sect) + ") out of range ");
const Section &symSection = normalizedFile.sections[sym->sect-1];
uint64_t targetOffsetInSect = sym->value - symSection.address;
@@ -566,19 +572,19 @@ std::error_code convertRelocs(const Section &section,
targetOffsetInSect);
if (target) {
*result = target;
- return std::error_code();
+ return llvm::Error();
}
- return make_dynamic_error_code("no atom found for defined symbol");
+ return llvm::make_error<GenericError>("no atom found for defined symbol");
} else if ((sym->type & N_TYPE) == N_UNDF) {
const lld::Atom *target = file.findUndefAtom(sym->name);
if (target) {
*result = target;
- return std::error_code();
+ return llvm::Error();
}
- return make_dynamic_error_code("no undefined atom found for sym");
+ return llvm::make_error<GenericError>("no undefined atom found for sym");
} else {
// Search undefs
- return make_dynamic_error_code("no atom found for symbol");
+ return llvm::make_error<GenericError>("no atom found for symbol");
}
};
@@ -589,7 +595,8 @@ std::error_code convertRelocs(const Section &section,
const Relocation &reloc = *it;
// Find atom this relocation is in.
if (reloc.offset > section.content.size())
- return make_dynamic_error_code(Twine("r_address (") + Twine(reloc.offset)
+ return llvm::make_error<GenericError>(
+ Twine("r_address (") + Twine(reloc.offset)
+ ") is larger than section size ("
+ Twine(section.content.size()) + ")");
uint32_t offsetInAtom;
@@ -602,68 +609,74 @@ std::error_code convertRelocs(const Section &section,
const lld::Atom *target = nullptr;
Reference::Addend addend = 0;
Reference::KindValue kind;
- std::error_code relocErr;
if (handler.isPairedReloc(reloc)) {
// Handle paired relocations together.
const Relocation &reloc2 = *++it;
- relocErr = handler.getPairReferenceInfo(
+ auto relocErr = handler.getPairReferenceInfo(
reloc, reloc2, inAtom, offsetInAtom, fixupAddress, isBig, scatterable,
atomByAddr, atomBySymbol, &kind, &target, &addend);
if (relocErr) {
- return make_dynamic_error_code(
- Twine("bad relocation (") + relocErr.message()
- + ") in section "
- + section.segmentName + "/" + section.sectionName
- + " (r1_address=" + Twine::utohexstr(reloc.offset)
- + ", r1_type=" + Twine(reloc.type)
- + ", r1_extern=" + Twine(reloc.isExtern)
- + ", r1_length=" + Twine((int)reloc.length)
- + ", r1_pcrel=" + Twine(reloc.pcRel)
- + (!reloc.scattered ? (Twine(", r1_symbolnum=")
- + Twine(reloc.symbol))
- : (Twine(", r1_scattered=1, r1_value=")
- + Twine(reloc.value)))
- + ")"
- + ", (r2_address=" + Twine::utohexstr(reloc2.offset)
- + ", r2_type=" + Twine(reloc2.type)
- + ", r2_extern=" + Twine(reloc2.isExtern)
- + ", r2_length=" + Twine((int)reloc2.length)
- + ", r2_pcrel=" + Twine(reloc2.pcRel)
- + (!reloc2.scattered ? (Twine(", r2_symbolnum=")
- + Twine(reloc2.symbol))
- : (Twine(", r2_scattered=1, r2_value=")
- + Twine(reloc2.value)))
- + ")" );
+ return handleErrors(std::move(relocErr),
+ [&](std::unique_ptr<GenericError> GE) {
+ return llvm::make_error<GenericError>(
+ Twine("bad relocation (") + GE->getMessage()
+ + ") in section "
+ + section.segmentName + "/" + section.sectionName
+ + " (r1_address=" + Twine::utohexstr(reloc.offset)
+ + ", r1_type=" + Twine(reloc.type)
+ + ", r1_extern=" + Twine(reloc.isExtern)
+ + ", r1_length=" + Twine((int)reloc.length)
+ + ", r1_pcrel=" + Twine(reloc.pcRel)
+ + (!reloc.scattered ? (Twine(", r1_symbolnum=")
+ + Twine(reloc.symbol))
+ : (Twine(", r1_scattered=1, r1_value=")
+ + Twine(reloc.value)))
+ + ")"
+ + ", (r2_address=" + Twine::utohexstr(reloc2.offset)
+ + ", r2_type=" + Twine(reloc2.type)
+ + ", r2_extern=" + Twine(reloc2.isExtern)
+ + ", r2_length=" + Twine((int)reloc2.length)
+ + ", r2_pcrel=" + Twine(reloc2.pcRel)
+ + (!reloc2.scattered ? (Twine(", r2_symbolnum=")
+ + Twine(reloc2.symbol))
+ : (Twine(", r2_scattered=1, r2_value=")
+ + Twine(reloc2.value)))
+ + ")" );
+ });
}
}
else {
// Use ArchHandler to convert relocation record into information
// needed to instantiate an lld::Reference object.
- relocErr = handler.getReferenceInfo(
+ auto relocErr = handler.getReferenceInfo(
reloc, inAtom, offsetInAtom, fixupAddress, isBig, atomByAddr,
atomBySymbol, &kind, &target, &addend);
if (relocErr) {
- return make_dynamic_error_code(
- Twine("bad relocation (") + relocErr.message()
- + ") in section "
- + section.segmentName + "/" + section.sectionName
- + " (r_address=" + Twine::utohexstr(reloc.offset)
- + ", r_type=" + Twine(reloc.type)
- + ", r_extern=" + Twine(reloc.isExtern)
- + ", r_length=" + Twine((int)reloc.length)
- + ", r_pcrel=" + Twine(reloc.pcRel)
- + (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
- : (Twine(", r_scattered=1, r_value=")
- + Twine(reloc.value)))
- + ")" );
+ return handleErrors(std::move(relocErr),
+ [&](std::unique_ptr<GenericError> GE) {
+ return llvm::make_error<GenericError>(
+ Twine("bad relocation (") + GE->getMessage()
+ + ") in section "
+ + section.segmentName + "/" + section.sectionName
+ + " (r_address=" + Twine::utohexstr(reloc.offset)
+ + ", r_type=" + Twine(reloc.type)
+ + ", r_extern=" + Twine(reloc.isExtern)
+ + ", r_length=" + Twine((int)reloc.length)
+ + ", r_pcrel=" + Twine(reloc.pcRel)
+ + (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
+ : (Twine(", r_scattered=1, r_value=")
+ + Twine(reloc.value)))
+ + ")" );
+ });
}
}
// Instantiate an lld::Reference object and add to its atom.
- inAtom->addReference(offsetInAtom, kind, target, addend,
- handler.kindArch());
+ inAtom->addReference(Reference::KindNamespace::mach_o,
+ handler.kindArch(),
+ kind, offsetInAtom, target, addend);
}
- return std::error_code();
+ return llvm::Error();
}
bool isDebugInfoSection(const Section &section) {
@@ -684,44 +697,81 @@ static int64_t readSPtr(bool is64, bool isBig, const uint8_t *addr) {
struct CIEInfo {
bool _augmentationDataPresent = false;
- bool _mayHaveLSDA = false;
+ bool _mayHaveEH = false;
+ uint32_t _offsetOfLSDA = ~0U;
+ uint32_t _offsetOfPersonality = ~0U;
+ uint32_t _offsetOfFDEPointerEncoding = ~0U;
+ uint32_t _augmentationDataLength = ~0U;
};
typedef llvm::DenseMap<const MachODefinedAtom*, CIEInfo> CIEInfoMap;
-static std::error_code processAugmentationString(const uint8_t *augStr,
- CIEInfo &cieInfo,
- unsigned *len = nullptr) {
+static llvm::Error processAugmentationString(const uint8_t *augStr,
+ CIEInfo &cieInfo,
+ unsigned &len) {
if (augStr[0] == '\0') {
- if (len)
- *len = 1;
- return std::error_code();
+ len = 1;
+ return llvm::Error();
}
if (augStr[0] != 'z')
- return make_dynamic_error_code("expected 'z' at start of augmentation "
- "string");
+ return llvm::make_error<GenericError>("expected 'z' at start of "
+ "augmentation string");
cieInfo._augmentationDataPresent = true;
uint64_t idx = 1;
+ uint32_t offsetInAugmentationData = 0;
while (augStr[idx] != '\0') {
if (augStr[idx] == 'L') {
- cieInfo._mayHaveLSDA = true;
+ cieInfo._offsetOfLSDA = offsetInAugmentationData;
+ // This adds a single byte to the augmentation data.
+ ++offsetInAugmentationData;
+ ++idx;
+ continue;
+ }
+ if (augStr[idx] == 'P') {
+ cieInfo._offsetOfPersonality = offsetInAugmentationData;
+ // This adds a single byte to the augmentation data for the encoding,
+ // then a number of bytes for the pointer data.
+ // FIXME: We are assuming 4 is correct here for the pointer size as we
+ // always currently use delta32ToGOT.
+ offsetInAugmentationData += 5;
++idx;
- } else
+ continue;
+ }
+ if (augStr[idx] == 'R') {
+ cieInfo._offsetOfFDEPointerEncoding = offsetInAugmentationData;
+ // This adds a single byte to the augmentation data.
+ ++offsetInAugmentationData;
++idx;
+ continue;
+ }
+ if (augStr[idx] == 'e') {
+ if (augStr[idx + 1] != 'h')
+ return llvm::make_error<GenericError>("expected 'eh' in "
+ "augmentation string");
+ cieInfo._mayHaveEH = true;
+ idx += 2;
+ continue;
+ }
+ ++idx;
}
- if (len)
- *len = idx + 1;
- return std::error_code();
+ cieInfo._augmentationDataLength = offsetInAugmentationData;
+
+ len = idx + 1;
+ return llvm::Error();
}
-static std::error_code processCIE(const NormalizedFile &normalizedFile,
- MachODefinedAtom *atom,
- CIEInfoMap &cieInfos) {
+static llvm::Error processCIE(const NormalizedFile &normalizedFile,
+ MachOFile &file,
+ mach_o::ArchHandler &handler,
+ const Section *ehFrameSection,
+ MachODefinedAtom *atom,
+ uint64_t offset,
+ CIEInfoMap &cieInfos) {
const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
const uint8_t *frameData = atom->rawContent().data();
@@ -734,31 +784,170 @@ static std::error_code processCIE(const NormalizedFile &normalizedFile,
uint64_t versionField = cieIDField + sizeof(uint32_t);
uint64_t augmentationStringField = versionField + sizeof(uint8_t);
+ unsigned augmentationStringLength = 0;
if (auto err = processAugmentationString(frameData + augmentationStringField,
- cieInfo))
+ cieInfo, augmentationStringLength))
return err;
+ if (cieInfo._offsetOfPersonality != ~0U) {
+ // If we have augmentation data for the personality function, then we may
+ // need to implicitly generate its relocation.
+
+ // Parse the EH Data field which is pointer sized.
+ uint64_t EHDataField = augmentationStringField + augmentationStringLength;
+ const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
+ unsigned EHDataFieldSize = (cieInfo._mayHaveEH ? (is64 ? 8 : 4) : 0);
+
+ // Parse Code Align Factor which is a ULEB128.
+ uint64_t CodeAlignField = EHDataField + EHDataFieldSize;
+ unsigned lengthFieldSize = 0;
+ llvm::decodeULEB128(frameData + CodeAlignField, &lengthFieldSize);
+
+ // Parse Data Align Factor which is a SLEB128.
+ uint64_t DataAlignField = CodeAlignField + lengthFieldSize;
+ llvm::decodeSLEB128(frameData + DataAlignField, &lengthFieldSize);
+
+ // Parse Return Address Register which is a byte.
+ uint64_t ReturnAddressField = DataAlignField + lengthFieldSize;
+
+ // Parse the augmentation length which is a ULEB128.
+ uint64_t AugmentationLengthField = ReturnAddressField + 1;
+ uint64_t AugmentationLength =
+ llvm::decodeULEB128(frameData + AugmentationLengthField,
+ &lengthFieldSize);
+
+ if (AugmentationLength != cieInfo._augmentationDataLength)
+ return llvm::make_error<GenericError>("CIE augmentation data length "
+ "mismatch");
+
+ // Get the start address of the augmentation data.
+ uint64_t AugmentationDataField = AugmentationLengthField + lengthFieldSize;
+
+ // Parse the personality function from the augmentation data.
+ uint64_t PersonalityField =
+ AugmentationDataField + cieInfo._offsetOfPersonality;
+
+ // Parse the personality encoding.
+ // FIXME: Verify that this is a 32-bit pcrel offset.
+ uint64_t PersonalityFunctionField = PersonalityField + 1;
+
+ if (atom->begin() != atom->end()) {
+ // If we have an explicit relocation, then make sure it matches this
+ // offset as this is where we'd expect it to be applied to.
+ DefinedAtom::reference_iterator CurrentRef = atom->begin();
+ if (CurrentRef->offsetInAtom() != PersonalityFunctionField)
+ return llvm::make_error<GenericError>("CIE personality reloc at "
+ "wrong offset");
+
+ if (++CurrentRef != atom->end())
+ return llvm::make_error<GenericError>("CIE contains too many relocs");
+ } else {
+ // Implicitly generate the personality function reloc. It's assumed to
+ // be a delta32 offset to a GOT entry.
+ // FIXME: Parse the encoding and check this.
+ int32_t funcDelta = read32(frameData + PersonalityFunctionField, isBig);
+ uint64_t funcAddress = ehFrameSection->address + offset +
+ PersonalityFunctionField;
+ funcAddress += funcDelta;
+
+ const MachODefinedAtom *func = nullptr;
+ Reference::Addend addend;
+ func = findAtomCoveringAddress(normalizedFile, file, funcAddress,
+ &addend);
+ atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
+ handler.unwindRefToPersonalityFunctionKind(),
+ PersonalityFunctionField, func, addend);
+ }
+ } else if (atom->begin() != atom->end()) {
+ // Otherwise, we expect there to be no relocations in this atom as the only
+ // relocation would have been to the personality function.
+ return llvm::make_error<GenericError>("unexpected relocation in CIE");
+ }
+
+
cieInfos[atom] = std::move(cieInfo);
- return std::error_code();
+ return llvm::Error();
}
-static std::error_code processFDE(const NormalizedFile &normalizedFile,
- MachOFile &file,
- mach_o::ArchHandler &handler,
- const Section *ehFrameSection,
- MachODefinedAtom *atom,
- uint64_t offset,
- const CIEInfoMap &cieInfos) {
+static llvm::Error processFDE(const NormalizedFile &normalizedFile,
+ MachOFile &file,
+ mach_o::ArchHandler &handler,
+ const Section *ehFrameSection,
+ MachODefinedAtom *atom,
+ uint64_t offset,
+ const CIEInfoMap &cieInfos) {
const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
// Compiler wasn't lazy and actually told us what it meant.
+ // Unfortunately, the compiler may not have generated references for all of
+ // [cie, func, lsda] and so we still need to parse the FDE and add references
+ // for any the compiler didn't generate.
if (atom->begin() != atom->end())
- return std::error_code();
+ atom->sortReferences();
+
+ DefinedAtom::reference_iterator CurrentRef = atom->begin();
+
+ // This helper returns the reference (if one exists) at the offset we are
+ // currently processing. It automatically increments the ref iterator if we
+ // do return a ref, and throws an error if we pass over a ref without
+ // comsuming it.
+ auto currentRefGetter = [&CurrentRef,
+ &atom](uint64_t Offset)->const Reference* {
+ // If there are no more refs found, then we are done.
+ if (CurrentRef == atom->end())
+ return nullptr;
+
+ const Reference *Ref = *CurrentRef;
+
+ // If we haven't reached the offset for this reference, then return that
+ // we don't yet have a reference to process.
+ if (Offset < Ref->offsetInAtom())
+ return nullptr;
+
+ // If the offset is equal, then we want to process this ref.
+ if (Offset == Ref->offsetInAtom()) {
+ ++CurrentRef;
+ return Ref;
+ }
+
+ // The current ref is at an offset which is earlier than the current
+ // offset, then we failed to consume it when we should have. In this case
+ // throw an error.
+ llvm::report_fatal_error("Skipped reference when processing FDE");
+ };
+
+ // Helper to either get the reference at this current location, and verify
+ // that it is of the expected type, or add a reference of that type.
+ // Returns the reference target.
+ auto verifyOrAddReference = [&](uint64_t targetAddress,
+ Reference::KindValue refKind,
+ uint64_t refAddress,
+ bool allowsAddend)->const Atom* {
+ if (auto *ref = currentRefGetter(refAddress)) {
+ // The compiler already emitted a relocation for the CIE ref. This should
+ // have been converted to the correct type of reference in
+ // get[Pair]ReferenceInfo().
+ assert(ref->kindValue() == refKind &&
+ "Incorrect EHFrame reference kind");
+ return ref->target();
+ }
+ Reference::Addend addend;
+ auto *target = findAtomCoveringAddress(normalizedFile, file,
+ targetAddress, &addend);
+ atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
+ refKind, refAddress, target, addend);
+
+ if (!allowsAddend)
+ assert(!addend && "EHFrame reference cannot have addend");
+ return target;
+ };
+
+ const uint8_t *startFrameData = atom->rawContent().data();
+ const uint8_t *frameData = startFrameData;
- const uint8_t *frameData = atom->rawContent().data();
uint32_t size = read32(frameData, isBig);
uint64_t cieFieldInFDE = size == 0xffffffffU
? sizeof(uint32_t) + sizeof(uint64_t)
@@ -770,13 +959,11 @@ static std::error_code processFDE(const NormalizedFile &normalizedFile,
uint64_t cieAddress = ehFrameSection->address + offset + cieFieldInFDE;
cieAddress -= cieDelta;
- Reference::Addend addend;
- const MachODefinedAtom *cie =
- findAtomCoveringAddress(normalizedFile, file, cieAddress, &addend);
- atom->addReference(cieFieldInFDE, handler.unwindRefToCIEKind(), cie,
- addend, handler.kindArch());
-
- assert(cie && cie->contentType() == DefinedAtom::typeCFI && !addend &&
+ auto *cieRefTarget = verifyOrAddReference(cieAddress,
+ handler.unwindRefToCIEKind(),
+ cieFieldInFDE, false);
+ const MachODefinedAtom *cie = dyn_cast<MachODefinedAtom>(cieRefTarget);
+ assert(cie && cie->contentType() == DefinedAtom::typeCFI &&
"FDE's CIE field does not point at the start of a CIE.");
const CIEInfo &cieInfo = cieInfos.find(cie)->second;
@@ -792,10 +979,9 @@ static std::error_code processFDE(const NormalizedFile &normalizedFile,
uint64_t rangeStart = ehFrameSection->address + offset + rangeFieldInFDE;
rangeStart += functionFromFDE;
- const Atom *func =
- findAtomCoveringAddress(normalizedFile, file, rangeStart, &addend);
- atom->addReference(rangeFieldInFDE, handler.unwindRefToFunctionKind(),
- func, addend, handler.kindArch());
+ verifyOrAddReference(rangeStart,
+ handler.unwindRefToFunctionKind(),
+ rangeFieldInFDE, true);
// Handle the augmentation data if there is any.
if (cieInfo._augmentationDataPresent) {
@@ -807,7 +993,7 @@ static std::error_code processFDE(const NormalizedFile &normalizedFile,
llvm::decodeULEB128(frameData + augmentationDataLengthFieldInFDE,
&lengthFieldSize);
- if (cieInfo._mayHaveLSDA && augmentationDataLength > 0) {
+ if (cieInfo._offsetOfLSDA != ~0U && augmentationDataLength > 0) {
// Look at the augmentation data field.
uint64_t augmentationDataFieldInFDE =
@@ -818,20 +1004,19 @@ static std::error_code processFDE(const NormalizedFile &normalizedFile,
uint64_t lsdaStart =
ehFrameSection->address + offset + augmentationDataFieldInFDE +
lsdaFromFDE;
- const Atom *lsda =
- findAtomCoveringAddress(normalizedFile, file, lsdaStart, &addend);
- atom->addReference(augmentationDataFieldInFDE,
- handler.unwindRefToFunctionKind(),
- lsda, addend, handler.kindArch());
+
+ verifyOrAddReference(lsdaStart,
+ handler.unwindRefToFunctionKind(),
+ augmentationDataFieldInFDE, true);
}
}
- return std::error_code();
+ return llvm::Error();
}
-std::error_code addEHFrameReferences(const NormalizedFile &normalizedFile,
- MachOFile &file,
- mach_o::ArchHandler &handler) {
+llvm::Error addEHFrameReferences(const NormalizedFile &normalizedFile,
+ MachOFile &file,
+ mach_o::ArchHandler &handler) {
const Section *ehFrameSection = nullptr;
for (auto &section : normalizedFile.sections)
@@ -843,9 +1028,9 @@ std::error_code addEHFrameReferences(const NormalizedFile &normalizedFile,
// No __eh_frame so nothing to do.
if (!ehFrameSection)
- return std::error_code();
+ return llvm::Error();
- std::error_code ehFrameErr;
+ llvm::Error ehFrameErr;
CIEInfoMap cieInfos;
file.eachAtomInSection(*ehFrameSection,
@@ -858,7 +1043,8 @@ std::error_code addEHFrameReferences(const NormalizedFile &normalizedFile,
const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
if (ArchHandler::isDwarfCIE(isBig, atom))
- ehFrameErr = processCIE(normalizedFile, atom, cieInfos);
+ ehFrameErr = processCIE(normalizedFile, file, handler, ehFrameSection,
+ atom, offset, cieInfos);
else
ehFrameErr = processFDE(normalizedFile, file, handler, ehFrameSection,
atom, offset, cieInfos);
@@ -867,24 +1053,66 @@ std::error_code addEHFrameReferences(const NormalizedFile &normalizedFile,
return ehFrameErr;
}
+llvm::Error parseObjCImageInfo(const Section &sect,
+ const NormalizedFile &normalizedFile,
+ MachOFile &file) {
+
+ // struct objc_image_info {
+ // uint32_t version; // initially 0
+ // uint32_t flags;
+ // };
+
+ ArrayRef<uint8_t> content = sect.content;
+ if (content.size() != 8)
+ return llvm::make_error<GenericError>(sect.segmentName + "/" +
+ sect.sectionName +
+ " in file " + file.path() +
+ " should be 8 bytes in size");
+
+ const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
+ uint32_t version = read32(content.data(), isBig);
+ if (version)
+ return llvm::make_error<GenericError>(sect.segmentName + "/" +
+ sect.sectionName +
+ " in file " + file.path() +
+ " should have version=0");
+
+ uint32_t flags = read32(content.data() + 4, isBig);
+ if (flags & (MachOLinkingContext::objc_supports_gc |
+ MachOLinkingContext::objc_gc_only))
+ return llvm::make_error<GenericError>(sect.segmentName + "/" +
+ sect.sectionName +
+ " in file " + file.path() +
+ " uses GC. This is not supported");
+
+ if (flags & MachOLinkingContext::objc_retainReleaseForSimulator)
+ file.setObjcConstraint(MachOLinkingContext::objc_retainReleaseForSimulator);
+ else
+ file.setObjcConstraint(MachOLinkingContext::objc_retainRelease);
+
+ file.setSwiftVersion((flags >> 8) & 0xFF);
+
+ return llvm::Error();
+}
+
/// Converts normalized mach-o file into an lld::File and lld::Atoms.
-ErrorOr<std::unique_ptr<lld::File>>
+llvm::Expected<std::unique_ptr<lld::File>>
objectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
bool copyRefs) {
std::unique_ptr<MachOFile> file(new MachOFile(path));
- if (std::error_code ec = normalizedObjectToAtoms(
- file.get(), normalizedFile, copyRefs))
- return ec;
+ if (auto ec = normalizedObjectToAtoms(file.get(), normalizedFile, copyRefs))
+ return std::move(ec);
return std::unique_ptr<File>(std::move(file));
}
-ErrorOr<std::unique_ptr<lld::File>>
+llvm::Expected<std::unique_ptr<lld::File>>
dylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
bool copyRefs) {
// Instantiate SharedLibraryFile object.
std::unique_ptr<MachODylibFile> file(new MachODylibFile(path));
- normalizedDylibToAtoms(file.get(), normalizedFile, copyRefs);
+ if (auto ec = normalizedDylibToAtoms(file.get(), normalizedFile, copyRefs))
+ return std::move(ec);
return std::unique_ptr<File>(std::move(file));
}
@@ -892,7 +1120,12 @@ dylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
namespace normalized {
-std::error_code
+static bool isObjCImageInfo(const Section &sect) {
+ return (sect.segmentName == "__OBJC" && sect.sectionName == "__image_info") ||
+ (sect.segmentName == "__DATA" && sect.sectionName == "__objc_imageinfo");
+}
+
+llvm::Error
normalizedObjectToAtoms(MachOFile *file,
const NormalizedFile &normalizedFile,
bool copyRefs) {
@@ -905,12 +1138,23 @@ normalizedObjectToAtoms(MachOFile *file,
DEBUG(llvm::dbgs() << "Creating atoms: "; sect.dump());
if (isDebugInfoSection(sect))
continue;
+
+
+ // If the file contains an objc_image_info struct, then we should parse the
+ // ObjC flags and Swift version.
+ if (isObjCImageInfo(sect)) {
+ if (auto ec = parseObjCImageInfo(sect, normalizedFile, *file))
+ return ec;
+ // We then skip adding atoms for this section as we use the ObjCPass to
+ // re-emit this data after it has been aggregated for all files.
+ continue;
+ }
+
bool customSectionName;
DefinedAtom::ContentType atomType = atomTypeFromSection(sect,
customSectionName);
- if (std::error_code ec =
- processSection(atomType, sect, customSectionName, normalizedFile,
- *file, scatterable, copyRefs))
+ if (auto ec = processSection(atomType, sect, customSectionName,
+ normalizedFile, *file, scatterable, copyRefs))
return ec;
}
// Create atoms from undefined symbols.
@@ -931,9 +1175,9 @@ normalizedObjectToAtoms(MachOFile *file,
for (auto &sect : normalizedFile.sections) {
if (isDebugInfoSection(sect))
continue;
- if (std::error_code ec = convertRelocs(sect, normalizedFile, scatterable,
- *file, *handler))
- return ec;
+ if (llvm::Error ec = convertRelocs(sect, normalizedFile, scatterable,
+ *file, *handler))
+ return ec;
}
// Add additional arch-specific References
@@ -945,7 +1189,7 @@ normalizedObjectToAtoms(MachOFile *file,
// providing unwind info for) and itself (FDE -> CIE). These aren't
// represented in the relocations on some architectures, so we have to add
// them back in manually there.
- if (std::error_code ec = addEHFrameReferences(normalizedFile, *file, *handler))
+ if (auto ec = addEHFrameReferences(normalizedFile, *file, *handler))
return ec;
// Process mach-o data-in-code regions array. That information is encoded in
@@ -955,25 +1199,26 @@ normalizedObjectToAtoms(MachOFile *file,
++nextIndex;
const Section* s = findSectionCoveringAddress(normalizedFile, entry.offset);
if (!s) {
- return make_dynamic_error_code(Twine("LC_DATA_IN_CODE address ("
- + Twine(entry.offset)
- + ") is not in any section"));
+ return llvm::make_error<GenericError>(Twine("LC_DATA_IN_CODE address ("
+ + Twine(entry.offset)
+ + ") is not in any section"));
}
uint64_t offsetInSect = entry.offset - s->address;
uint32_t offsetInAtom;
MachODefinedAtom *atom = file->findAtomCoveringAddress(*s, offsetInSect,
&offsetInAtom);
if (offsetInAtom + entry.length > atom->size()) {
- return make_dynamic_error_code(Twine("LC_DATA_IN_CODE entry (offset="
- + Twine(entry.offset)
- + ", length="
- + Twine(entry.length)
- + ") crosses atom boundary."));
+ return llvm::make_error<GenericError>(Twine("LC_DATA_IN_CODE entry "
+ "(offset="
+ + Twine(entry.offset)
+ + ", length="
+ + Twine(entry.length)
+ + ") crosses atom boundary."));
}
// Add reference that marks start of data-in-code.
- atom->addReference(offsetInAtom,
- handler->dataInCodeTransitionStart(*atom), atom,
- entry.kind, handler->kindArch());
+ atom->addReference(Reference::KindNamespace::mach_o, handler->kindArch(),
+ handler->dataInCodeTransitionStart(*atom),
+ offsetInAtom, atom, entry.kind);
// Peek at next entry, if it starts where this one ends, skip ending ref.
if (nextIndex < normalizedFile.dataInCode.size()) {
@@ -987,19 +1232,26 @@ normalizedObjectToAtoms(MachOFile *file,
continue;
// Add reference that marks end of data-in-code.
- atom->addReference(offsetInAtom+entry.length,
- handler->dataInCodeTransitionEnd(*atom), atom, 0,
- handler->kindArch());
+ atom->addReference(Reference::KindNamespace::mach_o, handler->kindArch(),
+ handler->dataInCodeTransitionEnd(*atom),
+ offsetInAtom+entry.length, atom, 0);
}
+ // Cache some attributes on the file for use later.
+ file->setFlags(normalizedFile.flags);
+ file->setArch(normalizedFile.arch);
+ file->setOS(normalizedFile.os);
+ file->setMinVersion(normalizedFile.minOSverson);
+ file->setMinVersionLoadCommandKind(normalizedFile.minOSVersionKind);
+
// Sort references in each atom to their canonical order.
for (const DefinedAtom* defAtom : file->defined()) {
reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
}
- return std::error_code();
+ return llvm::Error();
}
-std::error_code
+llvm::Error
normalizedDylibToAtoms(MachODylibFile *file,
const NormalizedFile &normalizedFile,
bool copyRefs) {
@@ -1027,7 +1279,7 @@ normalizedDylibToAtoms(MachODylibFile *file,
if (dep.kind == llvm::MachO::LC_REEXPORT_DYLIB)
file->addReExportedDylib(dep.path);
}
- return std::error_code();
+ return llvm::Error();
}
void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
@@ -1058,7 +1310,7 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
llvm_unreachable("content type not yet supported");
}
-ErrorOr<std::unique_ptr<lld::File>>
+llvm::Expected<std::unique_ptr<lld::File>>
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
bool copyRefs) {
switch (normalizedFile.fileType) {
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
index 0b92a68eeae8..66be77173983 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
@@ -237,6 +237,29 @@ struct ScalarBitSetTraits<SectionAttr> {
}
};
+/// This is a custom formatter for SectionAlignment. Values are
+/// the power to raise by, ie, the n in 2^n.
+template <> struct ScalarTraits<SectionAlignment> {
+ static void output(const SectionAlignment &value, void *ctxt,
+ raw_ostream &out) {
+ out << llvm::format("%d", (uint32_t)value);
+ }
+
+ static StringRef input(StringRef scalar, void *ctxt,
+ SectionAlignment &value) {
+ uint32_t alignment;
+ if (scalar.getAsInteger(0, alignment)) {
+ return "malformed alignment value";
+ }
+ if (!llvm::isPowerOf2_32(alignment))
+ return "alignment must be a power of 2";
+ value = alignment;
+ return StringRef(); // returning empty string means success
+ }
+
+ static bool mustQuote(StringRef) { return false; }
+};
+
template <>
struct ScalarEnumerationTraits<NListType> {
static void enumeration(IO &io, NListType &value) {
@@ -276,7 +299,7 @@ struct MappingTraits<Section> {
io.mapRequired("section", sect.sectionName);
io.mapRequired("type", sect.type);
io.mapOptional("attributes", sect.attributes);
- io.mapOptional("alignment", sect.alignment, (uint16_t)1);
+ io.mapOptional("alignment", sect.alignment, (SectionAlignment)1);
io.mapRequired("address", sect.address);
if (isZeroFillSection(sect.type)) {
// S_ZEROFILL sections use "size:" instead of "content:"
@@ -311,6 +334,8 @@ struct MappingTraits<Section> {
NormalizedFile *file = info->_normalizeMachOFile;
assert(file != nullptr);
size_t size = _normalizedContent.size();
+ if (!size)
+ return None;
uint8_t *bytes = file->ownedAllocations.Allocate<uint8_t>(size);
std::copy(_normalizedContent.begin(), _normalizedContent.end(), bytes);
return makeArrayRef(bytes, size);
@@ -504,10 +529,11 @@ struct ScalarTraits<VMProtect> {
template <>
struct MappingTraits<Segment> {
static void mapping(IO &io, Segment& seg) {
- io.mapRequired("name", seg.name);
- io.mapRequired("address", seg.address);
- io.mapRequired("size", seg.size);
- io.mapRequired("access", seg.access);
+ io.mapRequired("name", seg.name);
+ io.mapRequired("address", seg.address);
+ io.mapRequired("size", seg.size);
+ io.mapRequired("init-access", seg.init_access);
+ io.mapRequired("max-access", seg.max_access);
}
};
@@ -524,6 +550,14 @@ struct ScalarEnumerationTraits<LoadCommandType> {
llvm::MachO::LC_LOAD_UPWARD_DYLIB);
io.enumCase(value, "LC_LAZY_LOAD_DYLIB",
llvm::MachO::LC_LAZY_LOAD_DYLIB);
+ io.enumCase(value, "LC_VERSION_MIN_MACOSX",
+ llvm::MachO::LC_VERSION_MIN_MACOSX);
+ io.enumCase(value, "LC_VERSION_MIN_IPHONEOS",
+ llvm::MachO::LC_VERSION_MIN_IPHONEOS);
+ io.enumCase(value, "LC_VERSION_MIN_TVOS",
+ llvm::MachO::LC_VERSION_MIN_TVOS);
+ io.enumCase(value, "LC_VERSION_MIN_WATCHOS",
+ llvm::MachO::LC_VERSION_MIN_WATCHOS);
}
};
@@ -692,6 +726,7 @@ struct MappingTraits<NormalizedFile> {
io.mapOptional("source-version", file.sourceVersion, Hex64(0));
io.mapOptional("OS", file.os);
io.mapOptional("min-os-version", file.minOSverson, PackedVersion(0));
+ io.mapOptional("min-os-version-kind", file.minOSVersionKind, (LoadCommandType)0);
io.mapOptional("sdk-version", file.sdkVersion, PackedVersion(0));
io.mapOptional("segments", file.segments);
io.mapOptional("sections", file.sections);
@@ -731,8 +766,21 @@ bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io,
info->_normalizeMachOFile = &nf;
MappingTraits<NormalizedFile>::mapping(io, nf);
// Step 2: parse normalized mach-o struct into atoms.
- ErrorOr<std::unique_ptr<lld::File>> foe = normalizedToAtoms(nf, info->_path,
- true);
+ auto fileOrError = normalizedToAtoms(nf, info->_path, true);
+
+ // Check that we parsed successfully.
+ if (!fileOrError) {
+ std::string buffer;
+ llvm::raw_string_ostream stream(buffer);
+ handleAllErrors(fileOrError.takeError(),
+ [&](const llvm::ErrorInfoBase &EI) {
+ EI.log(stream);
+ stream << "\n";
+ });
+ io.setError(stream.str());
+ return false;
+ }
+
if (nf.arch != _arch) {
io.setError(Twine("file is wrong architecture. Expected ("
+ MachOLinkingContext::nameFromArch(_arch)
@@ -742,16 +790,8 @@ bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io,
return false;
}
info->_normalizeMachOFile = nullptr;
-
- if (foe) {
- // Transfer ownership to "out" File parameter.
- std::unique_ptr<lld::File> f = std::move(foe.get());
- file = f.release();
- return true;
- } else {
- io.setError(foe.getError().message());
- return false;
- }
+ file = fileOrError->release();
+ return true;
}
@@ -759,7 +799,7 @@ bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io,
namespace normalized {
/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
-ErrorOr<std::unique_ptr<NormalizedFile>>
+llvm::Expected<std::unique_ptr<NormalizedFile>>
readYaml(std::unique_ptr<MemoryBuffer> &mb) {
// Make empty NormalizedFile.
std::unique_ptr<NormalizedFile> f(new NormalizedFile());
@@ -773,8 +813,9 @@ readYaml(std::unique_ptr<MemoryBuffer> &mb) {
yin >> *f;
// Return error if there were parsing problems.
- if (yin.error())
- return make_error_code(lld::YamlReaderError::illegal_value);
+ if (auto ec = yin.error())
+ return llvm::make_error<GenericError>(Twine("YAML parsing error: ")
+ + ec.message());
// Hand ownership of instantiated NormalizedFile to caller.
return std::move(f);
diff --git a/lib/ReaderWriter/MachO/MachOPasses.h b/lib/ReaderWriter/MachO/MachOPasses.h
index a73785418d5f..cd01d4aa2c93 100644
--- a/lib/ReaderWriter/MachO/MachOPasses.h
+++ b/lib/ReaderWriter/MachO/MachOPasses.h
@@ -21,6 +21,7 @@ void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx);
void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx);
void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx);
void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx);
+void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx);
void addShimPass(PassManager &pm, const MachOLinkingContext &ctx);
} // namespace mach_o
diff --git a/lib/ReaderWriter/MachO/ObjCPass.cpp b/lib/ReaderWriter/MachO/ObjCPass.cpp
new file mode 100644
index 000000000000..ba24b3fecdf4
--- /dev/null
+++ b/lib/ReaderWriter/MachO/ObjCPass.cpp
@@ -0,0 +1,128 @@
+//===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#include "ArchHandler.h"
+#include "File.h"
+#include "MachOPasses.h"
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Simple.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace lld {
+namespace mach_o {
+
+///
+/// ObjC Image Info Atom created by the ObjC pass.
+///
+class ObjCImageInfoAtom : public SimpleDefinedAtom {
+public:
+ ObjCImageInfoAtom(const File &file,
+ MachOLinkingContext::ObjCConstraint objCConstraint,
+ uint32_t swiftVersion)
+ : SimpleDefinedAtom(file) {
+
+ Data.info.version = 0;
+
+ switch (objCConstraint) {
+ case MachOLinkingContext::objc_unknown:
+ llvm_unreachable("Shouldn't run the objc pass without a constraint");
+ case MachOLinkingContext::objc_supports_gc:
+ case MachOLinkingContext::objc_gc_only:
+ llvm_unreachable("GC is not supported");
+ case MachOLinkingContext::objc_retainReleaseForSimulator:
+ // The retain/release for simulator flag is already the correct
+ // encoded value for the data so just set it here.
+ Data.info.flags = (uint32_t)objCConstraint;
+ break;
+ case MachOLinkingContext::objc_retainRelease:
+ // We don't need to encode this flag, so just leave the flags as 0.
+ Data.info.flags = 0;
+ break;
+ }
+
+ Data.info.flags |= (swiftVersion << 8);
+ }
+
+ ~ObjCImageInfoAtom() override = default;
+
+ ContentType contentType() const override {
+ return DefinedAtom::typeObjCImageInfo;
+ }
+
+ Alignment alignment() const override {
+ return 4;
+ }
+
+ uint64_t size() const override {
+ return 8;
+ }
+
+ ContentPermissions permissions() const override {
+ return DefinedAtom::permR__;
+ }
+
+ ArrayRef<uint8_t> rawContent() const override {
+ return llvm::makeArrayRef(Data.bytes, size());
+ }
+
+private:
+
+ struct objc_image_info {
+ uint32_t version;
+ uint32_t flags;
+ };
+
+ union {
+ objc_image_info info;
+ uint8_t bytes[8];
+ } Data;
+};
+
+class ObjCPass : public Pass {
+public:
+ ObjCPass(const MachOLinkingContext &context)
+ : _ctx(context),
+ _file(*_ctx.make_file<MachOFile>("<mach-o objc pass>")) {
+ _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
+ }
+
+ llvm::Error perform(SimpleFile &mergedFile) override {
+ // Add the image info.
+ mergedFile.addAtom(*getImageInfo());
+
+ return llvm::Error();
+ }
+
+private:
+
+ const DefinedAtom* getImageInfo() {
+ return new (_file.allocator()) ObjCImageInfoAtom(_file,
+ _ctx.objcConstraint(),
+ _ctx.swiftVersion());
+ }
+
+ const MachOLinkingContext &_ctx;
+ MachOFile &_file;
+};
+
+
+
+void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx) {
+ pm.add(llvm::make_unique<ObjCPass>(ctx));
+}
+
+} // end namespace mach_o
+} // end namespace lld
diff --git a/lib/ReaderWriter/MachO/SectCreateFile.h b/lib/ReaderWriter/MachO/SectCreateFile.h
index 2e6e97c5433f..49e65f63151d 100644
--- a/lib/ReaderWriter/MachO/SectCreateFile.h
+++ b/lib/ReaderWriter/MachO/SectCreateFile.h
@@ -31,6 +31,8 @@ public:
_combinedName((segName + "/" + sectName).str()),
_content(std::move(content)) {}
+ ~SectCreateAtom() override = default;
+
uint64_t size() const override { return _content->getBufferSize(); }
Scope scope() const override { return scopeGlobal; }
@@ -59,7 +61,7 @@ public:
std::unique_ptr<MemoryBuffer> _content;
};
- SectCreateFile() : File("sectcreate", kindObject) {}
+ SectCreateFile() : File("sectcreate", kindSectCreateObject) {}
void addSection(StringRef seg, StringRef sect,
std::unique_ptr<MemoryBuffer> content) {
@@ -67,22 +69,29 @@ public:
new (allocator()) SectCreateAtom(*this, seg, sect, std::move(content)));
}
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _definedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
+ void clearAtoms() override {
+ _definedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
+
private:
AtomVector<DefinedAtom> _definedAtoms;
};
diff --git a/lib/ReaderWriter/MachO/ShimPass.cpp b/lib/ReaderWriter/MachO/ShimPass.cpp
index df29e37c183b..cd5367146658 100644
--- a/lib/ReaderWriter/MachO/ShimPass.cpp
+++ b/lib/ReaderWriter/MachO/ShimPass.cpp
@@ -42,9 +42,12 @@ class ShimPass : public Pass {
public:
ShimPass(const MachOLinkingContext &context)
: _ctx(context), _archHandler(_ctx.archHandler()),
- _stubInfo(_archHandler.stubInfo()), _file("<mach-o shim pass>") {}
+ _stubInfo(_archHandler.stubInfo()),
+ _file(*_ctx.make_file<MachOFile>("<mach-o shim pass>")) {
+ _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
+ }
- std::error_code perform(SimpleFile &mergedFile) override {
+ llvm::Error perform(SimpleFile &mergedFile) override {
// Scan all references in all atoms.
for (const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
@@ -63,7 +66,7 @@ public:
}
// Exit early if no shims needed.
if (_targetToShim.empty())
- return std::error_code();
+ return llvm::Error();
// Sort shim atoms so the layout order is stable.
std::vector<const DefinedAtom *> shims;
@@ -80,7 +83,7 @@ public:
for (const DefinedAtom *shim : shims)
mergedFile.addAtom(*shim);
- return std::error_code();
+ return llvm::Error();
}
private:
@@ -112,7 +115,7 @@ private:
const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
const ArchHandler::StubInfo &_stubInfo;
- MachOFile _file;
+ MachOFile &_file;
llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToShim;
};
diff --git a/lib/ReaderWriter/MachO/StubsPass.cpp b/lib/ReaderWriter/MachO/StubsPass.cpp
index 1f61256a5b79..d53b78b24d14 100644
--- a/lib/ReaderWriter/MachO/StubsPass.cpp
+++ b/lib/ReaderWriter/MachO/StubsPass.cpp
@@ -37,6 +37,8 @@ public:
LazyPointerAtom(const File &file, bool is64)
: SimpleDefinedAtom(file), _is64(is64) { }
+ ~LazyPointerAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeLazyPointer;
}
@@ -68,11 +70,13 @@ private:
//
class NonLazyPointerAtom : public SimpleDefinedAtom {
public:
- NonLazyPointerAtom(const File &file, bool is64)
- : SimpleDefinedAtom(file), _is64(is64) { }
+ NonLazyPointerAtom(const File &file, bool is64, ContentType contentType)
+ : SimpleDefinedAtom(file), _is64(is64), _contentType(contentType) { }
+
+ ~NonLazyPointerAtom() override = default;
ContentType contentType() const override {
- return DefinedAtom::typeGOT;
+ return _contentType;
}
Alignment alignment() const override {
@@ -95,6 +99,7 @@ public:
private:
const bool _is64;
+ const ContentType _contentType;
};
//
@@ -105,6 +110,8 @@ public:
StubAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
: SimpleDefinedAtom(file), _stubInfo(stubInfo){ }
+ ~StubAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeStub;
}
@@ -137,6 +144,8 @@ public:
StubHelperAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
: SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
+ ~StubHelperAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeStubHelper;
}
@@ -170,12 +179,14 @@ public:
StubHelperCommonAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
: SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
+ ~StubHelperCommonAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeStubHelper;
}
Alignment alignment() const override {
- return 1 << _stubInfo.codeAlignment;
+ return 1 << _stubInfo.stubHelperCommonAlignment;
}
uint64_t size() const override {
@@ -199,12 +210,15 @@ class StubsPass : public Pass {
public:
StubsPass(const MachOLinkingContext &context)
: _ctx(context), _archHandler(_ctx.archHandler()),
- _stubInfo(_archHandler.stubInfo()), _file("<mach-o Stubs pass>") {}
+ _stubInfo(_archHandler.stubInfo()),
+ _file(*_ctx.make_file<MachOFile>("<mach-o Stubs pass>")) {
+ _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
+ }
- std::error_code perform(SimpleFile &mergedFile) override {
+ llvm::Error perform(SimpleFile &mergedFile) override {
// Skip this pass if output format uses text relocations instead of stubs.
if (!this->noTextRelocs())
- return std::error_code();
+ return llvm::Error();
// Scan all references in all atoms.
for (const DefinedAtom *atom : mergedFile.defined()) {
@@ -231,15 +245,17 @@ public:
// Exit early if no stubs needed.
if (_targetToUses.empty())
- return std::error_code();
+ return llvm::Error();
// First add help-common and GOT slots used by lazy binding.
SimpleDefinedAtom *helperCommonAtom =
new (_file.allocator()) StubHelperCommonAtom(_file, _stubInfo);
SimpleDefinedAtom *helperCacheNLPAtom =
- new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit());
+ new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit(),
+ _stubInfo.stubHelperImageCacheContentType);
SimpleDefinedAtom *helperBinderNLPAtom =
- new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit());
+ new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit(),
+ _stubInfo.stubHelperImageCacheContentType);
addReference(helperCommonAtom, _stubInfo.stubHelperCommonReferenceToCache,
helperCacheNLPAtom);
addOptReference(
@@ -307,7 +323,7 @@ public:
lazyOffset += target->name().size() + 12;
}
- return std::error_code();
+ return llvm::Error();
}
private:
@@ -351,7 +367,7 @@ private:
const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
const ArchHandler::StubInfo &_stubInfo;
- MachOFile _file;
+ MachOFile &_file;
TargetToUses _targetToUses;
};
diff --git a/lib/ReaderWriter/MachO/TLVPass.cpp b/lib/ReaderWriter/MachO/TLVPass.cpp
index aba222edcd27..7a8496c20a4e 100644
--- a/lib/ReaderWriter/MachO/TLVPass.cpp
+++ b/lib/ReaderWriter/MachO/TLVPass.cpp
@@ -30,6 +30,8 @@ public:
TLVPEntryAtom(const File &file, bool is64, StringRef name)
: SimpleDefinedAtom(file), _is64(is64), _name(name) {}
+ ~TLVPEntryAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeTLVInitializerPtr;
}
@@ -65,10 +67,12 @@ class TLVPass : public Pass {
public:
TLVPass(const MachOLinkingContext &context)
: _ctx(context), _archHandler(_ctx.archHandler()),
- _file("<mach-o TLV Pass>") {}
+ _file(*_ctx.make_file<MachOFile>("<mach-o TLV pass>")) {
+ _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
+ }
private:
- std::error_code perform(SimpleFile &mergedFile) override {
+ llvm::Error perform(SimpleFile &mergedFile) override {
bool allowTLV = _ctx.minOS("10.7", "1.0");
for (const DefinedAtom *atom : mergedFile.defined()) {
@@ -77,7 +81,7 @@ private:
continue;
if (!allowTLV)
- return make_dynamic_error_code(
+ return llvm::make_error<GenericError>(
"targeted OS version does not support use of thread local "
"variables in " + atom->name() + " for architecture " +
_ctx.archName());
@@ -103,7 +107,7 @@ private:
for (const TLVPEntryAtom *slot : entries)
mergedFile.addAtom(*slot);
- return std::error_code();
+ return llvm::Error();
}
const DefinedAtom *makeTLVPEntry(const Atom *target) {
@@ -124,7 +128,7 @@ private:
const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
- MachOFile _file;
+ MachOFile &_file;
llvm::DenseMap<const Atom*, const TLVPEntryAtom*> _targetToTLVP;
};
diff --git a/lib/ReaderWriter/MachO/WriterMachO.cpp b/lib/ReaderWriter/MachO/WriterMachO.cpp
index cce0a179608c..f08487f21ac1 100644
--- a/lib/ReaderWriter/MachO/WriterMachO.cpp
+++ b/lib/ReaderWriter/MachO/WriterMachO.cpp
@@ -28,17 +28,18 @@ class MachOWriter : public Writer {
public:
MachOWriter(const MachOLinkingContext &ctxt) : _ctx(ctxt) {}
- std::error_code writeFile(const lld::File &file, StringRef path) override {
+ llvm::Error writeFile(const lld::File &file, StringRef path) override {
// Construct empty normalized file from atoms.
- ErrorOr<std::unique_ptr<NormalizedFile>> nFile =
+ llvm::Expected<std::unique_ptr<NormalizedFile>> nFile =
normalized::normalizedFromAtoms(file, _ctx);
- if (std::error_code ec = nFile.getError())
+ if (auto ec = nFile.takeError())
return ec;
// For testing, write out yaml form of normalized file.
if (_ctx.printAtoms()) {
std::unique_ptr<Writer> yamlWriter = createWriterYAML(_ctx);
- yamlWriter->writeFile(file, "-");
+ if (auto ec = yamlWriter->writeFile(file, "-"))
+ return ec;
}
// Write normalized file as mach-o binary.
diff --git a/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index 78c6797b713f..ee2a9ec10883 100644
--- a/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -7,30 +7,41 @@
//
//===----------------------------------------------------------------------===//
+#include "lld/Core/AbsoluteAtom.h"
#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/Atom.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/Error.h"
#include "lld/Core/File.h"
-#include "lld/Core/LLVM.h"
+#include "lld/Core/LinkingContext.h"
#include "lld/Core/Reader.h"
#include "lld/Core/Reference.h"
+#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/Simple.h"
+#include "lld/Core/UndefinedAtom.h"
#include "lld/Core/Writer.h"
#include "lld/ReaderWriter/YamlContext.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
+#include <cstring>
#include <memory>
#include <string>
#include <system_error>
+#include <vector>
using llvm::yaml::MappingTraits;
using llvm::yaml::ScalarEnumerationTraits;
@@ -178,31 +189,10 @@ public:
return nullptr;
}
- /// \brief Lookup a group parent when there is a reference of type
- /// kindGroupChild. If there was no group-parent produce an appropriate
- /// error.
- const lld::Atom *lookupGroupParent(StringRef name) const {
- NameToAtom::const_iterator pos = _groupMap.find(name);
- if (pos != _groupMap.end())
- return pos->second;
- _io.setError(Twine("no such group name: ") + name);
- return nullptr;
- }
-
private:
typedef llvm::StringMap<const lld::Atom *> NameToAtom;
void add(StringRef name, const lld::Atom *atom) {
- if (const lld::DefinedAtom *da = dyn_cast<DefinedAtom>(atom)) {
- if (da->isGroupParent()) {
- if (_groupMap.count(name)) {
- _io.setError(Twine("duplicate group name: ") + name);
- } else {
- _groupMap[name] = atom;
- }
- return;
- }
- }
if (_nameMap.count(name)) {
_io.setError(Twine("duplicate atom name: ") + name);
} else {
@@ -212,12 +202,11 @@ private:
IO &_io;
NameToAtom _nameMap;
- NameToAtom _groupMap;
};
/// Mapping of Atoms.
template <typename T> class AtomList {
- typedef lld::File::AtomVector<T> Ty;
+ using Ty = std::vector<OwningAtomPtr<T>>;
public:
typename Ty::iterator begin() { return _atoms.begin(); }
@@ -229,7 +218,6 @@ public:
enum FileKinds {
fileKindObjectAtoms, // atom based object file encoded in yaml
fileKindArchive, // static archive library encoded in yaml
- fileKindObjectELF, // ELF object files encoded in yaml
fileKindObjectMachO // mach-o object files encoded in yaml
};
@@ -255,7 +243,7 @@ struct RefKind {
Reference::KindValue value;
};
-} // anonymous namespace
+} // end anonymous namespace
LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember)
LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference *)
@@ -294,7 +282,8 @@ template <> struct ScalarTraits<RefKind> {
template <> struct ScalarEnumerationTraits<lld::File::Kind> {
static void enumeration(IO &io, lld::File::Kind &value) {
- io.enumCase(value, "object", lld::File::kindObject);
+ io.enumCase(value, "error-object", lld::File::kindErrorObject);
+ io.enumCase(value, "object", lld::File::kindMachObject);
io.enumCase(value, "shared-library", lld::File::kindSharedLibrary);
io.enumCase(value, "static-library", lld::File::kindArchiveLibrary);
}
@@ -417,6 +406,10 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
DefinedAtom::typeObjCClassPtr);
io.enumCase(value, "objc-category-list",
DefinedAtom::typeObjC2CategoryList);
+ io.enumCase(value, "objc-image-info",
+ DefinedAtom::typeObjCImageInfo);
+ io.enumCase(value, "objc-method-list",
+ DefinedAtom::typeObjCMethodList);
io.enumCase(value, "objc-class1", DefinedAtom::typeObjC1Class);
io.enumCase(value, "dtraceDOF", DefinedAtom::typeDTraceDOF);
io.enumCase(value, "interposing-tuples",
@@ -430,13 +423,7 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
io.enumCase(value, "tlv-initializer-ptr",
DefinedAtom::typeTLVInitializerPtr);
io.enumCase(value, "mach_header", DefinedAtom::typeMachHeader);
- io.enumCase(value, "thread-data", DefinedAtom::typeThreadData);
- io.enumCase(value, "thread-zero-fill",DefinedAtom::typeThreadZeroFill);
- io.enumCase(value, "ro-note", DefinedAtom::typeRONote);
- io.enumCase(value, "rw-note", DefinedAtom::typeRWNote);
- io.enumCase(value, "no-alloc", DefinedAtom::typeNoAlloc);
- io.enumCase(value, "group-comdat", DefinedAtom::typeGroupComdat);
- io.enumCase(value, "gnu-linkonce", DefinedAtom::typeGnuLinkOnce);
+ io.enumCase(value, "dso_handle", DefinedAtom::typeDSOHandle);
io.enumCase(value, "sectcreate", DefinedAtom::typeSectCreate);
}
};
@@ -512,7 +499,6 @@ template <> struct ScalarEnumerationTraits<FileKinds> {
static void enumeration(IO &io, FileKinds &value) {
io.enumCase(value, "object", fileKindObjectAtoms);
io.enumCase(value, "archive", fileKindArchive);
- io.enumCase(value, "object-elf", fileKindObjectELF);
io.enumCase(value, "object-mach-o", fileKindObjectMachO);
}
};
@@ -528,10 +514,20 @@ template <> struct MappingTraits<ArchMember> {
// Declare that an AtomList is a yaml sequence.
template <typename T> struct SequenceTraits<AtomList<T> > {
static size_t size(IO &io, AtomList<T> &seq) { return seq._atoms.size(); }
- static const T *&element(IO &io, AtomList<T> &seq, size_t index) {
+ static T *&element(IO &io, AtomList<T> &seq, size_t index) {
if (index >= seq._atoms.size())
seq._atoms.resize(index + 1);
- return seq._atoms[index];
+ return seq._atoms[index].get();
+ }
+};
+
+// Declare that an AtomRange is a yaml sequence.
+template <typename T> struct SequenceTraits<File::AtomRange<T> > {
+ static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
+ static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
+ assert(io.outputting() && "AtomRange only used when outputting");
+ assert(index < seq.size() && "Out of range access");
+ return seq[index].get();
}
};
@@ -583,39 +579,34 @@ template <> struct MappingTraits<const lld::File *> {
const lld::File *denormalize(IO &io) { return this; }
- const AtomVector<lld::DefinedAtom> &defined() const override {
+ const AtomRange<lld::DefinedAtom> defined() const override {
return _noDefinedAtoms;
}
- const AtomVector<lld::UndefinedAtom> &undefined() const override {
+ const AtomRange<lld::UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<lld::SharedLibraryAtom> &
- sharedLibrary() const override {
+ const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<lld::AbsoluteAtom> &absolute() const override {
+ const AtomRange<lld::AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
- File *find(StringRef name, bool dataSymbolOnly) override {
- for (const ArchMember &member : _members) {
- for (const lld::DefinedAtom *atom : member._content->defined()) {
- if (name == atom->name()) {
- if (!dataSymbolOnly)
- return const_cast<File *>(member._content);
- switch (atom->contentType()) {
- case lld::DefinedAtom::typeData:
- case lld::DefinedAtom::typeZeroFill:
- return const_cast<File *>(member._content);
- default:
- break;
- }
- }
- }
- }
+ void clearAtoms() override {
+ _noDefinedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
+
+ File *find(StringRef name) override {
+ for (const ArchMember &member : _members)
+ for (const lld::DefinedAtom *atom : member._content->defined())
+ if (name == atom->name())
+ return const_cast<File *>(member._content);
return nullptr;
}
@@ -630,36 +621,47 @@ template <> struct MappingTraits<const lld::File *> {
class NormalizedFile : public lld::File {
public:
- NormalizedFile(IO &io) : File("", kindObject), _io(io), _rnb(nullptr) {}
+ NormalizedFile(IO &io)
+ : File("", kindNormalizedObject), _io(io), _rnb(nullptr),
+ _definedAtomsRef(_definedAtoms._atoms),
+ _undefinedAtomsRef(_undefinedAtoms._atoms),
+ _sharedLibraryAtomsRef(_sharedLibraryAtoms._atoms),
+ _absoluteAtomsRef(_absoluteAtoms._atoms) {}
NormalizedFile(IO &io, const lld::File *file)
- : File(file->path(), kindObject), _io(io),
- _rnb(new RefNameBuilder(*file)), _path(file->path()) {
- for (const lld::DefinedAtom *a : file->defined())
- _definedAtoms._atoms.push_back(a);
- for (const lld::UndefinedAtom *a : file->undefined())
- _undefinedAtoms._atoms.push_back(a);
- for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
- _sharedLibraryAtoms._atoms.push_back(a);
- for (const lld::AbsoluteAtom *a : file->absolute())
- _absoluteAtoms._atoms.push_back(a);
+ : File(file->path(), kindNormalizedObject), _io(io),
+ _rnb(new RefNameBuilder(*file)), _path(file->path()),
+ _definedAtomsRef(file->defined()),
+ _undefinedAtomsRef(file->undefined()),
+ _sharedLibraryAtomsRef(file->sharedLibrary()),
+ _absoluteAtomsRef(file->absolute()) {
}
+
+ ~NormalizedFile() override {
+ }
+
const lld::File *denormalize(IO &io);
- const AtomVector<lld::DefinedAtom> &defined() const override {
- return _definedAtoms._atoms;
+ const AtomRange<lld::DefinedAtom> defined() const override {
+ return _definedAtomsRef;
+ }
+
+ const AtomRange<lld::UndefinedAtom> undefined() const override {
+ return _undefinedAtomsRef;
}
- const AtomVector<lld::UndefinedAtom> &undefined() const override {
- return _undefinedAtoms._atoms;
+ const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
+ return _sharedLibraryAtomsRef;
}
- const AtomVector<lld::SharedLibraryAtom> &
- sharedLibrary() const override {
- return _sharedLibraryAtoms._atoms;
+ const AtomRange<lld::AbsoluteAtom> absolute() const override {
+ return _absoluteAtomsRef;
}
- const AtomVector<lld::AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms._atoms;
+ void clearAtoms() override {
+ _definedAtoms._atoms.clear();
+ _undefinedAtoms._atoms.clear();
+ _sharedLibraryAtoms._atoms.clear();
+ _absoluteAtoms._atoms.clear();
}
// Allocate a new copy of this string in _storage, so the strings
@@ -677,6 +679,10 @@ template <> struct MappingTraits<const lld::File *> {
AtomList<lld::UndefinedAtom> _undefinedAtoms;
AtomList<lld::SharedLibraryAtom> _sharedLibraryAtoms;
AtomList<lld::AbsoluteAtom> _absoluteAtoms;
+ AtomRange<lld::DefinedAtom> _definedAtomsRef;
+ AtomRange<lld::UndefinedAtom> _undefinedAtomsRef;
+ AtomRange<lld::SharedLibraryAtom> _sharedLibraryAtomsRef;
+ AtomRange<lld::AbsoluteAtom> _absoluteAtomsRef;
llvm::BumpPtrAllocator _storage;
};
@@ -693,20 +699,31 @@ template <> struct MappingTraits<const lld::File *> {
}
static void mappingAtoms(IO &io, const lld::File *&file) {
- MappingNormalizationHeap<NormalizedFile, const lld::File *> keys(io, file);
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
+ MappingNormalizationHeap<NormalizedFile, const lld::File *>
+ keys(io, file, nullptr);
assert(info != nullptr);
info->_file = keys.operator->();
io.mapOptional("path", keys->_path);
- io.mapOptional("defined-atoms", keys->_definedAtoms);
- io.mapOptional("undefined-atoms", keys->_undefinedAtoms);
- io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
- io.mapOptional("absolute-atoms", keys->_absoluteAtoms);
+
+ if (io.outputting()) {
+ io.mapOptional("defined-atoms", keys->_definedAtomsRef);
+ io.mapOptional("undefined-atoms", keys->_undefinedAtomsRef);
+ io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
+ io.mapOptional("absolute-atoms", keys->_absoluteAtomsRef);
+ } else {
+ io.mapOptional("defined-atoms", keys->_definedAtoms);
+ io.mapOptional("undefined-atoms", keys->_undefinedAtoms);
+ io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
+ io.mapOptional("absolute-atoms", keys->_absoluteAtoms);
+ }
}
static void mappingArchive(IO &io, const lld::File *&file) {
- MappingNormalizationHeap<NormArchiveFile, const lld::File *> keys(io, file);
+ YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
+ MappingNormalizationHeap<NormArchiveFile, const lld::File *>
+ keys(io, file, &info->_file->allocator());
io.mapOptional("path", keys->_path);
io.mapOptional("members", keys->_members);
@@ -769,8 +786,9 @@ template <> struct MappingTraits<const lld::Reference *> {
};
static void mapping(IO &io, const lld::Reference *&ref) {
+ YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
MappingNormalizationHeap<NormalizedReference, const lld::Reference *> keys(
- io, ref);
+ io, ref, &info->_file->allocator());
io.mapRequired("kind", keys->_mappedKind);
io.mapOptional("offset", keys->_offset);
@@ -787,7 +805,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
public:
NormalizedAtom(IO &io)
: _file(fileFromContext(io)), _name(), _refName(), _contentType(),
- _alignment(1), _content(), _references(), _isGroupChild(false) {
+ _alignment(1), _content(), _references() {
static uint32_t ordinalCounter = 1;
_ordinal = ordinalCounter++;
}
@@ -810,6 +828,9 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
for (uint8_t x : cont)
_content.push_back(x);
}
+
+ ~NormalizedAtom() override = default;
+
const lld::DefinedAtom *denormalize(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
assert(info != nullptr);
@@ -827,7 +848,9 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
<< ", " << _name.size() << ")\n");
return this;
}
+
void bind(const RefNameResolver &);
+
// Extract current File object from YAML I/O parsing context
const lld::File &fileFromContext(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
@@ -851,8 +874,6 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
DynamicExport dynamicExport() const override { return _dynamicExport; }
CodeModel codeModel() const override { return _codeModel; }
ContentPermissions permissions() const override { return _permissions; }
- void setGroupChild(bool val) { _isGroupChild = val; }
- bool isGroupChild() const { return _isGroupChild; }
ArrayRef<uint8_t> rawContent() const override {
if (!occupiesDiskSpace())
return ArrayRef<uint8_t>();
@@ -883,6 +904,16 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
it = reinterpret_cast<const void *>(index);
}
+ void addReference(Reference::KindNamespace ns,
+ Reference::KindArch arch,
+ Reference::KindValue kindValue, uint64_t off,
+ const Atom *target, Reference::Addend a) override {
+ assert(target && "trying to create reference to nothing");
+ auto node = new (file().allocator()) SimpleReference(ns, arch, kindValue,
+ off, target, a);
+ _references.push_back(node);
+ }
+
const lld::File &_file;
StringRef _name;
StringRef _refName;
@@ -902,16 +933,15 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
StringRef _sectionName;
uint64_t _sectionSize;
std::vector<const lld::Reference *> _references;
- bool _isGroupChild;
};
static void mapping(IO &io, const lld::DefinedAtom *&atom) {
+ YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
MappingNormalizationHeap<NormalizedAtom, const lld::DefinedAtom *> keys(
- io, atom);
+ io, atom, &info->_file->allocator());
if (io.outputting()) {
// If writing YAML, check if atom needs a ref-name.
typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
assert(info != nullptr);
NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
assert(f);
@@ -951,18 +981,27 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
}
};
+template <> struct MappingTraits<lld::DefinedAtom *> {
+ static void mapping(IO &io, lld::DefinedAtom *&atom) {
+ const lld::DefinedAtom *atomPtr = atom;
+ MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
+ atom = const_cast<lld::DefinedAtom *>(atomPtr);
+ }
+};
+
// YAML conversion for const lld::UndefinedAtom*
template <> struct MappingTraits<const lld::UndefinedAtom *> {
class NormalizedAtom : public lld::UndefinedAtom {
public:
NormalizedAtom(IO &io)
- : _file(fileFromContext(io)), _name(), _canBeNull(canBeNullNever),
- _fallback(nullptr) {}
+ : _file(fileFromContext(io)), _name(), _canBeNull(canBeNullNever) {}
NormalizedAtom(IO &io, const lld::UndefinedAtom *atom)
: _file(fileFromContext(io)), _name(atom->name()),
- _canBeNull(atom->canBeNull()), _fallback(atom->fallback()) {}
+ _canBeNull(atom->canBeNull()) {}
+
+ ~NormalizedAtom() override = default;
const lld::UndefinedAtom *denormalize(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
@@ -990,29 +1029,33 @@ template <> struct MappingTraits<const lld::UndefinedAtom *> {
const lld::File &file() const override { return _file; }
StringRef name() const override { return _name; }
CanBeNull canBeNull() const override { return _canBeNull; }
- const UndefinedAtom *fallback() const override { return _fallback; }
const lld::File &_file;
StringRef _name;
CanBeNull _canBeNull;
- const UndefinedAtom *_fallback;
};
static void mapping(IO &io, const lld::UndefinedAtom *&atom) {
+ YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
MappingNormalizationHeap<NormalizedAtom, const lld::UndefinedAtom *> keys(
- io, atom);
+ io, atom, &info->_file->allocator());
io.mapRequired("name", keys->_name);
io.mapOptional("can-be-null", keys->_canBeNull,
lld::UndefinedAtom::canBeNullNever);
- io.mapOptional("fallback", keys->_fallback,
- (const lld::UndefinedAtom *)nullptr);
+ }
+};
+
+template <> struct MappingTraits<lld::UndefinedAtom *> {
+ static void mapping(IO &io, lld::UndefinedAtom *&atom) {
+ const lld::UndefinedAtom *atomPtr = atom;
+ MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
+ atom = const_cast<lld::UndefinedAtom *>(atomPtr);
}
};
// YAML conversion for const lld::SharedLibraryAtom*
template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
-
class NormalizedAtom : public lld::SharedLibraryAtom {
public:
NormalizedAtom(IO &io)
@@ -1023,6 +1066,8 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
_loadName(atom->loadName()), _canBeNull(atom->canBeNullAtRuntime()),
_type(atom->type()), _size(atom->size()) {}
+ ~NormalizedAtom() override = default;
+
const lld::SharedLibraryAtom *denormalize(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
assert(info != nullptr);
@@ -1066,8 +1111,9 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
static void mapping(IO &io, const lld::SharedLibraryAtom *&atom) {
+ YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
MappingNormalizationHeap<NormalizedAtom, const lld::SharedLibraryAtom *>
- keys(io, atom);
+ keys(io, atom, &info->_file->allocator());
io.mapRequired("name", keys->_name);
io.mapOptional("load-name", keys->_loadName);
@@ -1077,6 +1123,14 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
}
};
+template <> struct MappingTraits<lld::SharedLibraryAtom *> {
+ static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
+ const lld::SharedLibraryAtom *atomPtr = atom;
+ MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
+ atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
+ }
+};
+
// YAML conversion for const lld::AbsoluteAtom*
template <> struct MappingTraits<const lld::AbsoluteAtom *> {
@@ -1087,6 +1141,9 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> {
NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
: _file(fileFromContext(io)), _name(atom->name()),
_scope(atom->scope()), _value(atom->value()) {}
+
+ ~NormalizedAtom() override = default;
+
const lld::AbsoluteAtom *denormalize(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
assert(info != nullptr);
@@ -1122,8 +1179,9 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> {
};
static void mapping(IO &io, const lld::AbsoluteAtom *&atom) {
+ YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
MappingNormalizationHeap<NormalizedAtom, const lld::AbsoluteAtom *> keys(
- io, atom);
+ io, atom, &info->_file->allocator());
if (io.outputting()) {
typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
@@ -1144,8 +1202,16 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> {
}
};
-} // namespace llvm
-} // namespace yaml
+template <> struct MappingTraits<lld::AbsoluteAtom *> {
+ static void mapping(IO &io, lld::AbsoluteAtom *&atom) {
+ const lld::AbsoluteAtom *atomPtr = atom;
+ MappingTraits<const lld::AbsoluteAtom *>::mapping(io, atomPtr);
+ atom = const_cast<lld::AbsoluteAtom *>(atomPtr);
+ }
+};
+
+} // end namespace llvm
+} // end namespace yaml
RefNameResolver::RefNameResolver(const lld::File *file, IO &io) : _io(io) {
typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
@@ -1186,13 +1252,6 @@ MappingTraits<const lld::File *>::NormalizedFile::denormalize(IO &io) {
normAtom->bind(nameResolver);
}
- _definedAtoms._atoms.erase(
- std::remove_if(_definedAtoms._atoms.begin(), _definedAtoms._atoms.end(),
- [](const DefinedAtom *a) {
- return ((const NormalizedAtom *)a)->isGroupChild();
- }),
- _definedAtoms._atoms.end());
-
return this;
}
@@ -1208,14 +1267,7 @@ inline void MappingTraits<const lld::DefinedAtom *>::NormalizedAtom::bind(
inline void MappingTraits<const lld::Reference *>::NormalizedReference::bind(
const RefNameResolver &resolver) {
- typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom NormalizedAtom;
-
_target = resolver.lookup(_targetName);
-
- if (_mappedKind.ns == lld::Reference::KindNamespace::all &&
- _mappedKind.value == lld::Reference::kindGroupChild) {
- ((NormalizedAtom *)const_cast<Atom *>(_target))->setGroupChild(true);
- }
}
inline StringRef
@@ -1240,12 +1292,12 @@ class Writer : public lld::Writer {
public:
Writer(const LinkingContext &context) : _ctx(context) {}
- std::error_code writeFile(const lld::File &file, StringRef outPath) override {
+ llvm::Error writeFile(const lld::File &file, StringRef outPath) override {
// Create stream to path.
std::error_code ec;
llvm::raw_fd_ostream out(outPath, ec, llvm::sys::fs::F_Text);
if (ec)
- return ec;
+ return llvm::errorCodeToError(ec);
// Create yaml Output writer, using yaml options for context.
YamlContext yamlContext;
@@ -1257,7 +1309,7 @@ public:
const lld::File *fileRef = &file;
yout << fileRef;
- return std::error_code();
+ return llvm::Error();
}
private:
@@ -1330,7 +1382,7 @@ private:
const Registry &_registry;
};
-} // anonymous namespace
+} // end anonymous namespace
void Registry::addSupportYamlFiles() {
add(std::unique_ptr<Reader>(new YAMLReader(*this)));
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b92489e2cc8d..88cd128fc4c7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -20,9 +20,9 @@ configure_lit_site_cfg(
)
set(LLD_TEST_DEPS
- FileCheck not llvm-ar llvm-as llvm-nm llc
+ FileCheck not llvm-ar llvm-as llvm-dis llvm-nm llc
lld llvm-config llvm-objdump llvm-readobj yaml2obj obj2yaml
- linker-script-test llvm-mc llvm-nm llvm-lib
+ llvm-mc llvm-nm llvm-lib
)
if (LLVM_INCLUDE_TESTS)
set(LLD_TEST_DEPS ${LLD_TEST_DEPS} LLDUnitTests)
diff --git a/test/COFF/Inputs/armnt-executable.obj.yaml b/test/COFF/Inputs/armnt-executable.obj.yaml
index 33b2c886b860..5c42b9009dab 100644
--- a/test/COFF/Inputs/armnt-executable.obj.yaml
+++ b/test/COFF/Inputs/armnt-executable.obj.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_ARMNT
Characteristics: []
diff --git a/test/COFF/Inputs/export.yaml b/test/COFF/Inputs/export.yaml
index 25b57288a1bf..1ccf0909a953 100644
--- a/test/COFF/Inputs/export.yaml
+++ b/test/COFF/Inputs/export.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
@@ -9,7 +9,7 @@ sections:
SectionData: B800000000506800000000680000000050E80000000050E800000000
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
+ Alignment: 1
SectionData: 2f6578706f72743a6578706f7274666e3300 # /export:exportfn3
symbols:
- Name: .text
diff --git a/test/COFF/Inputs/export2.yaml b/test/COFF/Inputs/export2.yaml
index 592b76526ffa..37fa4c751b90 100644
--- a/test/COFF/Inputs/export2.yaml
+++ b/test/COFF/Inputs/export2.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/Inputs/hello32.yaml b/test/COFF/Inputs/hello32.yaml
index ea5a5c84c4f1..09e76f144532 100644
--- a/test/COFF/Inputs/hello32.yaml
+++ b/test/COFF/Inputs/hello32.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
diff --git a/test/COFF/Inputs/import.yaml b/test/COFF/Inputs/import.yaml
index 2c5fdc545b48..493400143d6c 100644
--- a/test/COFF/Inputs/import.yaml
+++ b/test/COFF/Inputs/import.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/Inputs/include1a.yaml b/test/COFF/Inputs/include1a.yaml
index 7fca9833cb7b..f61e0e0877ec 100644
--- a/test/COFF/Inputs/include1a.yaml
+++ b/test/COFF/Inputs/include1a.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
@@ -9,7 +9,7 @@ sections:
SectionData: B800000000506800000000680000000050E80000000050E800000000
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
+ Alignment: 1
SectionData: 2f696e636c7564653a666f6f00 # /include:foo
symbols:
- Name: .text
diff --git a/test/COFF/Inputs/include1b.yaml b/test/COFF/Inputs/include1b.yaml
index e4151be27cc3..78d1b92de8cc 100644
--- a/test/COFF/Inputs/include1b.yaml
+++ b/test/COFF/Inputs/include1b.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
@@ -9,7 +9,7 @@ sections:
SectionData: B800000000506800000000680000000050E80000000050E800000000
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
+ Alignment: 1
SectionData: 2f696e636c7564653a62617200 # /include:bar
symbols:
- Name: .text
diff --git a/test/COFF/Inputs/include1c.yaml b/test/COFF/Inputs/include1c.yaml
index 78dd29659e22..6cf9db6e3185 100644
--- a/test/COFF/Inputs/include1c.yaml
+++ b/test/COFF/Inputs/include1c.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/Inputs/machine-x64.yaml b/test/COFF/Inputs/machine-x64.yaml
index d70e0808a2e1..36bdfe6d14c3 100644
--- a/test/COFF/Inputs/machine-x64.yaml
+++ b/test/COFF/Inputs/machine-x64.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/Inputs/machine-x86.yaml b/test/COFF/Inputs/machine-x86.yaml
index 6b6cfae09c57..197143bde2e9 100644
--- a/test/COFF/Inputs/machine-x86.yaml
+++ b/test/COFF/Inputs/machine-x86.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
diff --git a/test/COFF/Inputs/manifestinput.test b/test/COFF/Inputs/manifestinput.test
new file mode 100644
index 000000000000..c65739225a59
--- /dev/null
+++ b/test/COFF/Inputs/manifestinput.test
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type='win32'
+ name='Microsoft.Windows.Common-Controls'
+ version='6.0.0.0'
+ processorArchitecture='*'
+ publicKeyToken='6595b64144ccf1df'
+ language='*' />
+ </dependentAssembly>
+ </dependency>
+</assembly>
diff --git a/test/COFF/Inputs/ret42.yaml b/test/COFF/Inputs/ret42.yaml
index 2b38cc7f0d6b..b98090166415 100644
--- a/test/COFF/Inputs/ret42.yaml
+++ b/test/COFF/Inputs/ret42.yaml
@@ -1,4 +1,4 @@
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/alternatename.test b/test/COFF/alternatename.test
index 5b9dc470af16..1be61adb1850 100644
--- a/test/COFF/alternatename.test
+++ b/test/COFF/alternatename.test
@@ -10,7 +10,7 @@
# RUN: yaml2obj < %s > %t.obj
# RUN: lld-link /entry:foo /subsystem:console /out:%t.exe %t.obj
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
@@ -25,7 +25,7 @@ sections:
SectionData: ''
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
+ Alignment: 1
SectionData: 2f616c7465726e6174656e616d653a666f6f3d6d61696e00 # /alternatename:foo=main
symbols:
- Name: '.text$mn'
diff --git a/test/COFF/ar-comdat.test b/test/COFF/ar-comdat.test
index af7d732ea3c0..5420b5be3dd5 100644
--- a/test/COFF/ar-comdat.test
+++ b/test/COFF/ar-comdat.test
@@ -6,7 +6,7 @@
# CHECK-NOT: .lib
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
diff --git a/test/COFF/armnt-blx23t.test b/test/COFF/armnt-blx23t.test
index fdc2bf51afb3..5caf6ebaa127 100644
--- a/test/COFF/armnt-blx23t.test
+++ b/test/COFF/armnt-blx23t.test
@@ -25,7 +25,7 @@
# AFTER: 1010: 01 30 adds r0, #1
# AFTER: 1012: bd e8 00 88 pop.w {r11, pc}
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_ARMNT
Characteristics: [ ]
diff --git a/test/COFF/armnt-branch24t.test b/test/COFF/armnt-branch24t.test
index 358b603303b3..6e1114c94a18 100644
--- a/test/COFF/armnt-branch24t.test
+++ b/test/COFF/armnt-branch24t.test
@@ -18,7 +18,7 @@
# AFTER: 1004: 20 20 movs r0, #32
# AFTER: 1006: ff f7 fb bf b.w #-10
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_ARMNT
Characteristics: []
diff --git a/test/COFF/armnt-imports.test b/test/COFF/armnt-imports.test
index 3842259a7a72..519886eb0c06 100644
--- a/test/COFF/armnt-imports.test
+++ b/test/COFF/armnt-imports.test
@@ -10,7 +10,7 @@
# CHECK: Symbol: function (0)
# CHECK: }
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_ARMNT
Characteristics: [ ]
diff --git a/test/COFF/armnt-mov32t-exec.test b/test/COFF/armnt-mov32t-exec.test
index 7fa9952e9547..629f0620730d 100644
--- a/test/COFF/armnt-mov32t-exec.test
+++ b/test/COFF/armnt-mov32t-exec.test
@@ -19,7 +19,7 @@
# AFTER: 1008: c0 f2 40 00 movt r0, #64
# AFTER: 100c: 70 47 bx lr
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_ARMNT
Characteristics: [ ]
diff --git a/test/COFF/armnt-movt32t.test b/test/COFF/armnt-movt32t.test
index be292cb39300..6a9bf256e335 100644
--- a/test/COFF/armnt-movt32t.test
+++ b/test/COFF/armnt-movt32t.test
@@ -15,7 +15,7 @@
# AFTER: 4: c0 f2 40 00 movt r0, #64
# AFTER: 8: 70 47 bx lr
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_ARMNT
Characteristics: [ ]
diff --git a/test/COFF/base.test b/test/COFF/base.test
index f03e321fc23a..662632bf9076 100644
--- a/test/COFF/base.test
+++ b/test/COFF/base.test
@@ -16,7 +16,7 @@
# BASE-TEXT: Contents of section .text:
# BASE-TEXT-NEXT: 1000 00000080 02000000
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/baserel.test b/test/COFF/baserel.test
index bac9c22cbc3d..ce0b27621caf 100644
--- a/test/COFF/baserel.test
+++ b/test/COFF/baserel.test
@@ -72,7 +72,7 @@
# BASEREL-HEADER-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
# BASEREL-HEADER-NEXT: ]
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/common.test b/test/COFF/common.test
index de25848674ed..d57ced457d10 100644
--- a/test/COFF/common.test
+++ b/test/COFF/common.test
@@ -9,7 +9,7 @@
# CHECK: 300f: b8 60 10 00 40
# CHECK: 3014: b8 80 10 00 40
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/conflict.test b/test/COFF/conflict.test
index 3d5725ab79ee..65dda51f498d 100644
--- a/test/COFF/conflict.test
+++ b/test/COFF/conflict.test
@@ -10,7 +10,7 @@
# CHECK: duplicate symbol: foo {{.+}}1.obj and foo {{.+}}2.obj
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/debug.test b/test/COFF/debug.test
index 52e0f60fe3f5..3921e0ccbb33 100644
--- a/test/COFF/debug.test
+++ b/test/COFF/debug.test
@@ -1,7 +1,7 @@
# RUN: yaml2obj %s > %t.obj
# RUN: lld-link /out:%t.exe /entry:main /subsystem:console %t.obj
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/dllorder.test b/test/COFF/dllorder.test
deleted file mode 100644
index 417483d33086..000000000000
--- a/test/COFF/dllorder.test
+++ /dev/null
@@ -1,65 +0,0 @@
-# REQUIRES: winlib
-
-# RUN: yaml2obj < %s > %t.obj
-# RUN: mkdir -p %tlib
-# RUN: rm -f %tlib/lib1.lib
-# RUN: rm -f %tlib/lib2.lib
-
-# RUN: echo EXPORTS sym1 > %t1.def
-# RUN: echo EXPORTS sym2 > %t2.def
-# RUN: lib /nologo /machine:amd64 /def:%t1.def /out:%tlib\lib1.lib
-# RUN: lib /nologo /machine:amd64 /def:%t2.def /out:%tlib\lib2.lib
-
-# RUN: lld-link /out:%t1.exe /entry:main /libpath:%tlib %t.obj /defaultlib:lib1 /defaultlib:lib2
-# RUN: lld-link /out:%t2.exe /entry:main /libpath:%tlib %t.obj /defaultlib:lib2 /defaultlib:lib1
-
-# RUN: llvm-readobj -coff-imports %t1.exe | FileCheck -check-prefix=CHECK1 %s
-# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=CHECK2 %s
-
-# CHECK1: Name: dllorder.test.tmp1.dll
-# CHECK1: Name: dllorder.test.tmp2.dll
-
-# CHECK2: Name: dllorder.test.tmp2.dll
-# CHECK2: Name: dllorder.test.tmp1.dll
-
----
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: []
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4096
- SectionData: 0000000000000000
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 8
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp_sym1
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp_sym2
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/COFF/entry-inference.test b/test/COFF/entry-inference.test
index 2063f28edc77..2eb9a6863983 100644
--- a/test/COFF/entry-inference.test
+++ b/test/COFF/entry-inference.test
@@ -19,7 +19,7 @@
# WINMAIN: <root>: undefined symbol: WinMainCRTStartup
# WWINMAIN: <root>: undefined symbol: wWinMainCRTStartup
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/entry-inference2.test b/test/COFF/entry-inference2.test
index afac80859d10..a66422fbabe2 100644
--- a/test/COFF/entry-inference2.test
+++ b/test/COFF/entry-inference2.test
@@ -4,7 +4,7 @@
# CHECK: Entry name inferred: WinMainCRTStartup
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
@@ -15,7 +15,7 @@ sections:
SectionData: B82A000000C3
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
+ Alignment: 1
SectionData: 2f616c7465726e6174656e616d653a6d61696e3d57696e4d61696e00 # /alternatename:main=WinMain
symbols:
- Name: .text
diff --git a/test/COFF/entry-inference32.test b/test/COFF/entry-inference32.test
index 6e1a5f925180..231b468b47f6 100644
--- a/test/COFF/entry-inference32.test
+++ b/test/COFF/entry-inference32.test
@@ -4,7 +4,7 @@
# CHECK: Entry name inferred: _WinMainCRTStartup
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
diff --git a/test/COFF/entry-mangled.test b/test/COFF/entry-mangled.test
index 41620336513e..acf54ba07973 100644
--- a/test/COFF/entry-mangled.test
+++ b/test/COFF/entry-mangled.test
@@ -3,7 +3,7 @@
# RUN: llvm-as -o %t.lto.obj %S/Inputs/entry-mangled.ll
# RUN: lld-link /out:%t.exe /entry:main %t.lto.obj
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/export32.test b/test/COFF/export32.test
index 5d7b2708dcba..86cd27bb9af6 100644
--- a/test/COFF/export32.test
+++ b/test/COFF/export32.test
@@ -74,7 +74,7 @@
# CHECK6: duplicate /export option: _exportfn2
# CHECK6-NOT: duplicate /export option: _exportfn1
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
@@ -85,7 +85,7 @@ sections:
SectionData: B800000000506800000000680000000050E80000000050E800000000
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
+ Alignment: 1
SectionData: 2f6578706f72743a5f6578706f7274666e3300 # /export:_exportfn3
symbols:
- Name: .text
diff --git a/test/COFF/force.test b/test/COFF/force.test
index 44e5722dab5d..80bd275558f6 100644
--- a/test/COFF/force.test
+++ b/test/COFF/force.test
@@ -6,7 +6,7 @@
# CHECK: .obj: undefined symbol: foo
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/icf-circular.test b/test/COFF/icf-circular.test
index 7319e135e2e6..c1135660a780 100644
--- a/test/COFF/icf-circular.test
+++ b/test/COFF/icf-circular.test
@@ -6,7 +6,7 @@
# CHECK: Selected foo
# CHECK: Removed bar
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/icf-circular2.test b/test/COFF/icf-circular2.test
index e7598c124365..3b8eb8f424ac 100644
--- a/test/COFF/icf-circular2.test
+++ b/test/COFF/icf-circular2.test
@@ -6,7 +6,7 @@
# CHECK: Selected foo
# CHECK: Removed bar
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/icf-different-align.test b/test/COFF/icf-different-align.test
index 6876048a5d40..3502ed3449a4 100644
--- a/test/COFF/icf-different-align.test
+++ b/test/COFF/icf-different-align.test
@@ -6,7 +6,7 @@
# CHECK-NOT: Selected foo
# CHECK-NOT: Removed bar
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/icf-local.test b/test/COFF/icf-local.test
index a0b4c91559a3..db690b8dc813 100644
--- a/test/COFF/icf-local.test
+++ b/test/COFF/icf-local.test
@@ -8,7 +8,7 @@
# CHECK-NOT: Removed bar
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/icf-simple.test b/test/COFF/icf-simple.test
index ae72fd9d9d73..c302c8796a95 100644
--- a/test/COFF/icf-simple.test
+++ b/test/COFF/icf-simple.test
@@ -16,7 +16,7 @@
# NOICF-NOT: Removed foo
# NOICF-NOT: Removed bar
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/imports-mangle.test b/test/COFF/imports-mangle.test
index 35b385559005..5d8ccae23009 100644
--- a/test/COFF/imports-mangle.test
+++ b/test/COFF/imports-mangle.test
@@ -10,7 +10,7 @@
# CHECK: Symbol: (2)
# CHECK: }
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/include.test b/test/COFF/include.test
index b9e5f49b4fb6..e7b0c58d5a19 100644
--- a/test/COFF/include.test
+++ b/test/COFF/include.test
@@ -14,7 +14,7 @@
# CHECK2-NOT: Discarded unused
# CHECK2-NOT: Discarded used
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
@@ -33,7 +33,7 @@ sections:
SectionData: B82A000000C3
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
+ Alignment: 1
SectionData: 2f696e636c7564653a7573656400 # /include:used
symbols:
- Name: '.text$mn'
diff --git a/test/COFF/internal.test b/test/COFF/internal.test
index 80a5332847de..bc958cb4bd19 100644
--- a/test/COFF/internal.test
+++ b/test/COFF/internal.test
@@ -5,7 +5,7 @@
# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t3.obj
# RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.obj %t3.obj
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/invalid-obj.test b/test/COFF/invalid-obj.test
index fd63f7874cc1..6f76c3702aa7 100644
--- a/test/COFF/invalid-obj.test
+++ b/test/COFF/invalid-obj.test
@@ -3,7 +3,7 @@
# CHECK: getSectionName failed: #1:
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/loadcfg.ll b/test/COFF/loadcfg.ll
index 3166881032b4..c49ae2f6ebd5 100644
--- a/test/COFF/loadcfg.ll
+++ b/test/COFF/loadcfg.ll
@@ -8,7 +8,7 @@
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
-@_load_config_used = constant i32 1
+@_load_config_used = constant [28 x i32] [i32 112, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]
define void @main() {
ret void
diff --git a/test/COFF/loadcfg.test b/test/COFF/loadcfg.test
index a84f864b4b53..b74917f15707 100644
--- a/test/COFF/loadcfg.test
+++ b/test/COFF/loadcfg.test
@@ -2,10 +2,10 @@
# RUN: lld-link /out:%t.exe %t.obj /entry:main /subsystem:console
# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-# CHECK: LoadConfigTableRVA: 0x1008
+# CHECK: LoadConfigTableRVA: 0x1000
# CHECK: LoadConfigTableSize: 0x70
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
@@ -18,6 +18,10 @@ sections:
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: B82A000000C3
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: '70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
symbols:
- Name: .text
Value: 0
@@ -50,9 +54,21 @@ symbols:
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 112
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
- Name: _load_config_used
Value: 0
- SectionNumber: 2
+ SectionNumber: 3
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
diff --git a/test/COFF/loadcfg32.test b/test/COFF/loadcfg32.test
index f7780e1d0373..03a066c1e552 100644
--- a/test/COFF/loadcfg32.test
+++ b/test/COFF/loadcfg32.test
@@ -5,7 +5,7 @@
# CHECK: LoadConfigTableRVA: 0x1000
# CHECK: LoadConfigTableSize: 0x40
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
@@ -14,6 +14,10 @@ sections:
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: B82A000000C3
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: '40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
symbols:
- Name: .text
Value: 0
@@ -33,9 +37,21 @@ symbols:
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 64
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
- Name: __load_config_used
Value: 0
- SectionNumber: 1
+ SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
diff --git a/test/COFF/locally-imported.test b/test/COFF/locally-imported.test
index 7c43666c8c1e..a10da4b11bcb 100644
--- a/test/COFF/locally-imported.test
+++ b/test/COFF/locally-imported.test
@@ -19,7 +19,7 @@
# BASEREL-NEXT: }
# BASEREL-NEXT: ]
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/locally-imported32.test b/test/COFF/locally-imported32.test
index 7f604d2a0495..789c8c8f8094 100644
--- a/test/COFF/locally-imported32.test
+++ b/test/COFF/locally-imported32.test
@@ -8,7 +8,7 @@
# CHECK: Contents of section .rdata:
# CHECK-NEXT: 2000 04104000
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
diff --git a/test/COFF/long-section-name.test b/test/COFF/long-section-name.test
index a3dad33ec2cf..1de329db0296 100644
--- a/test/COFF/long-section-name.test
+++ b/test/COFF/long-section-name.test
@@ -5,7 +5,7 @@
# CHECK: Name: .data_long_section_name
# CHECK: Name: .text_long_section_name
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
diff --git a/test/COFF/manifestinput.test b/test/COFF/manifestinput.test
new file mode 100644
index 000000000000..376d404d604c
--- /dev/null
+++ b/test/COFF/manifestinput.test
@@ -0,0 +1,10 @@
+# REQUIRES: winres
+
+# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main \
+# RUN: /manifestuac:"level='requireAdministrator'" \
+# RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj
+# RUN: FileCheck %s < %t.exe.manifest
+
+CHECK: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+CHECK: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency><trustInfo><security><requestedPrivileges><requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo></assembly>
diff --git a/test/COFF/merge.test b/test/COFF/merge.test
index 45ab4efe37a8..4b5c1007f9fb 100644
--- a/test/COFF/merge.test
+++ b/test/COFF/merge.test
@@ -6,7 +6,7 @@
# CHECK: Name: .def
# CHECK: Name: .abc
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/opt.test b/test/COFF/opt.test
index 652734b2f68a..a8b0e2eb97ba 100644
--- a/test/COFF/opt.test
+++ b/test/COFF/opt.test
@@ -14,7 +14,7 @@
# CHECK1: Discarded unused
# CHECK2-NOT: Discarded unused
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/out.test b/test/COFF/out.test
index a216fc9add8f..67b2ef01b711 100644
--- a/test/COFF/out.test
+++ b/test/COFF/out.test
@@ -1,3 +1,4 @@
+# REQUIRES: winres
# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
# RUN: mkdir -p %T/out/tmp
@@ -5,12 +6,13 @@
# RUN: cp %t.obj %T/out/tmp/out2
# RUN: cp %t.obj %T/out/tmp/out3.xyz
+# RUN: rm -f out1.exe out2.exe out3.exe out3.dll
# RUN: lld-link /entry:main %T/out/out1.obj
# RUN: lld-link /entry:main %T/out/tmp/out2
-# RUN: lld-link /entry:main %T/out/tmp/out3.xyz
+# RUN: lld-link /dll /entry:main %T/out/tmp/out3.xyz
# RUN: llvm-readobj out1.exe | FileCheck %s
# RUN: llvm-readobj out2.exe | FileCheck %s
-# RUN: llvm-readobj out3.exe | FileCheck %s
+# RUN: llvm-readobj out3.dll | FileCheck %s
CHECK: File:
diff --git a/test/COFF/reloc-arm.test b/test/COFF/reloc-arm.test
index b44c0822bb7f..11b863d4390b 100644
--- a/test/COFF/reloc-arm.test
+++ b/test/COFF/reloc-arm.test
@@ -11,7 +11,7 @@
# CHECK: 402050 fe07d62f 00000000 00000000 00000000
# CHECK: 402060 00000000 00000000 00000000 00000000
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_ARMNT
Characteristics: []
diff --git a/test/COFF/reloc-x64.test b/test/COFF/reloc-x64.test
index 5513f2eaa647..7af8fb24bd38 100644
--- a/test/COFF/reloc-x64.test
+++ b/test/COFF/reloc-x64.test
@@ -15,7 +15,7 @@
# CHECK: 1051: a1 02 00 00 00 00 00 00 00
# CHECK: 105a: a1 03 00 00 00 00 00 00 00
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/reloc-x86.test b/test/COFF/reloc-x86.test
index d189ca02f015..5e1406913756 100644
--- a/test/COFF/reloc-x86.test
+++ b/test/COFF/reloc-x86.test
@@ -10,7 +10,7 @@
# CHECK: 1014: a1 00 00 02 00
# CHECK: 1019: a1 03 00 00 00
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
diff --git a/test/COFF/safeseh.test b/test/COFF/safeseh.test
index f8308a6131b6..ed928a51350a 100644
--- a/test/COFF/safeseh.test
+++ b/test/COFF/safeseh.test
@@ -8,7 +8,7 @@
# CHECK: /safeseh: {{.*}} is not compatible with SEH
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: [ ]
diff --git a/test/COFF/section.test b/test/COFF/section.test
new file mode 100644
index 000000000000..591c04dde73f
--- /dev/null
+++ b/test/COFF/section.test
@@ -0,0 +1,62 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /section:.foo,r %t.obj
+# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=R %s
+
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /section:.foo,w %t.obj
+# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=W %s
+
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /section:.foo,e %t.obj
+# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=E %s
+
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /section:.foo,s %t.obj
+# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=S %s
+
+# R: Characteristics [
+# R-NEXT: IMAGE_SCN_MEM_READ
+# R-NEXT: ]
+
+# W: Characteristics [
+# W-NEXT: IMAGE_SCN_MEM_WRITE
+# W-NEXT: ]
+
+# E: Characteristics [
+# E-NEXT: IMAGE_SCN_MEM_EXECUTE
+# E-NEXT: ]
+
+# S: Characteristics [
+# S-NEXT: IMAGE_SCN_MEM_SHARED
+# S-NEXT: ]
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .foo
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: 000000000000
+symbols:
+ - Name: .foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 6
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/seh.test b/test/COFF/seh.test
index b3ff66cf09b8..f2d0af76a965 100644
--- a/test/COFF/seh.test
+++ b/test/COFF/seh.test
@@ -5,7 +5,7 @@
# CHECK: Contents of section .rdata:
# CHECK: 1000 00200000 02200000
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: [ ]
diff --git a/test/COFF/sort-debug.test b/test/COFF/sort-debug.test
index c099f2dc19b1..b04b41ad1c23 100644
--- a/test/COFF/sort-debug.test
+++ b/test/COFF/sort-debug.test
@@ -11,7 +11,7 @@
# CHECK: Name: .reloc
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: [ ]
diff --git a/test/COFF/subsystem-inference.test b/test/COFF/subsystem-inference.test
index da4f573c2e02..231fd5491120 100644
--- a/test/COFF/subsystem-inference.test
+++ b/test/COFF/subsystem-inference.test
@@ -19,7 +19,7 @@
# WINMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
# WWINMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/symtab.test b/test/COFF/symtab.test
index 14ae9a3e816c..51eb3a374c59 100644
--- a/test/COFF/symtab.test
+++ b/test/COFF/symtab.test
@@ -111,7 +111,7 @@
# NO: Symbols [
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/tls.test b/test/COFF/tls.test
index 395916dfdd67..a577fe832fb9 100644
--- a/test/COFF/tls.test
+++ b/test/COFF/tls.test
@@ -5,7 +5,7 @@
# CHECK: TLSTableRVA: 0x1000
# CHECK: TLSTableSize: 0x28
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
diff --git a/test/COFF/tls32.test b/test/COFF/tls32.test
index 4fe020eb9e10..fa39614f121e 100644
--- a/test/COFF/tls32.test
+++ b/test/COFF/tls32.test
@@ -3,9 +3,9 @@
# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
# CHECK: TLSTableRVA: 0x1000
-# CHECK: TLSTableSize: 0x28
+# CHECK: TLSTableSize: 0x18
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: []
diff --git a/test/COFF/unwind.test b/test/COFF/unwind.test
index 48e94165b9bd..2415b0542ca5 100644
--- a/test/COFF/unwind.test
+++ b/test/COFF/unwind.test
@@ -55,7 +55,7 @@
# UNWIND: 0x07: UOP_AllocLarge 8190
# UNWIND: 0x00: UOP_PushMachFrame w/o error code
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
diff --git a/test/COFF/weak-external.test b/test/COFF/weak-external.test
index 3997170b897a..e422b2e62761 100644
--- a/test/COFF/weak-external.test
+++ b/test/COFF/weak-external.test
@@ -8,7 +8,7 @@
# CHECK-NOT: :
# CHECK: {{ g$}}
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
diff --git a/test/COFF/weak-external2.test b/test/COFF/weak-external2.test
index 6afaac29219d..30101d73096b 100644
--- a/test/COFF/weak-external2.test
+++ b/test/COFF/weak-external2.test
@@ -2,7 +2,7 @@
# RUN: llvm-as -o %t.lto.obj %S/Inputs/weak-external2.ll
# RUN: lld-link /out:%t.exe /entry:g /subsystem:console %t.obj %t.lto.obj
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
diff --git a/test/COFF/weak-external3.test b/test/COFF/weak-external3.test
index 9ba32982d505..05ff859993a3 100644
--- a/test/COFF/weak-external3.test
+++ b/test/COFF/weak-external3.test
@@ -13,7 +13,7 @@
# CHECK2-NOT: :
# CHECK2: {{ f$}}
----
+--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
diff --git a/test/Driver/def-lib-search.test b/test/Driver/def-lib-search.test
deleted file mode 100644
index 15d5dbbea9ff..000000000000
--- a/test/Driver/def-lib-search.test
+++ /dev/null
@@ -1,8 +0,0 @@
-# Check that search paths explicitly provided by the -L option
-# are used in search before default paths.
-
-RUN: not lld -flavor old-gnu -target x86_64 -t -ltest \
-RUN: --sysroot=%p/Inputs -L%p/Inputs 2> %t
-RUN: FileCheck %s < %t
-
-CHECK: {{[^ ]+}}{{[\\/]}}Inputs{{[\\/]}}libtest.a
diff --git a/test/Driver/flavor-option.test b/test/Driver/flavor-option.test
deleted file mode 100644
index 2471bc09519b..000000000000
--- a/test/Driver/flavor-option.test
+++ /dev/null
@@ -1,8 +0,0 @@
-# a) the -flavor option is position independent and does not need to be the 1st
-# argument in the command line (bug 20975);
-# b) UniversalDriver correctly removes -flavor along with its value and the
-# underlying linker does not get a corrupted command line (bug 20977).
-RUN: lld --help -flavor old-gnu | FileCheck %s
-
-CHECK: --noinhibit-exec
-CHECK: --output-filetype
diff --git a/test/Driver/lib-search.test b/test/Driver/lib-search.test
deleted file mode 100644
index 255b17b1a55e..000000000000
--- a/test/Driver/lib-search.test
+++ /dev/null
@@ -1,24 +0,0 @@
-RUN: not lld -flavor old-gnu -t -ltest -L%p/Inputs 2> %t.err
-RUN: FileCheck %s < %t.err
-
-RUN: not lld -flavor old-gnu -target x86_64--netbsd -t -ltest \
-RUN: --sysroot=%p/Inputs 2> %t2
-RUN: FileCheck -check-prefix=NETBSD-AMD64 %s < %t2
-RUN: not lld -flavor old-gnu -target x86_64--netbsd -nostdlib -t -ltest \
-RUN: --sysroot=%p/Inputs 2> %t3
-RUN: FileCheck -check-prefix=NETBSD-AMD64-NS %s < %t3
-RUN: not lld -flavor old-gnu -target i386--netbsd -t -ltest \
-RUN: --sysroot=%p/Inputs 2> %t4
-RUN: FileCheck -check-prefix=NETBSD-I386 %s < %t4
-RUN: not lld -flavor old-gnu -target x86_64--netbsd -m elf_i386 -t -ltest \
-RUN: --sysroot=%p/Inputs 2> %t5
-RUN: FileCheck -check-prefix=NETBSD-AMD64_32 %s < %t5
-
-# run linker with -t mode to dump full paths to input files
-
-CHECK: {{[^ ]+[\\/]}}Inputs{{[\\/]}}libtest.a
-
-NETBSD-AMD64: {{[^ ]+}}{{[\\/]}}Inputs{{[\\/]}}usr{{[\\/]}}lib{{[\\/]}}libtest.a
-NETBSD-AMD64-NS-NOT: {{[^ ]+}}{{[\\/]}}Inputs{{[\\/]}}usr{{[\\/]}}lib{{[\\/]}}libtest.a
-NETBSD-I386: {{[^ ]+}}{{[\\/]}}Inputs{{[\\/]}}usr{{[\\/]}}lib{{[\\/]}}libtest.a
-NETBSD-AMD64_32: {{[^ ]+}}{{[\\/]}}Inputs{{[\\/]}}usr{{[\\/]}}lib{{[\\/]}}i386{{[\\/]}}libtest.a
diff --git a/test/Driver/so-whole-archive.test b/test/Driver/so-whole-archive.test
deleted file mode 100644
index 8ab879082bf1..000000000000
--- a/test/Driver/so-whole-archive.test
+++ /dev/null
@@ -1,63 +0,0 @@
-# Check that LLD does not show any error if the --whole-archive
-# is around non-archive.
-
-# RUN: yaml2obj -format=elf -docnum=1 %s > %t-so.o
-# RUN: yaml2obj -format=elf -docnum=2 %s > %t-exe.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -o %t.exe %t-exe.o --whole-archive %t.so
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x04
-Symbols:
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Size: 0x04
-
-# exe.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: foo
- Type: R_MIPS_26
-
-Symbols:
- Global:
- - Name: __start
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- - Name: foo
-...
diff --git a/test/Driver/trivial-driver.test b/test/Driver/trivial-driver.test
deleted file mode 100644
index 46de60c543f6..000000000000
--- a/test/Driver/trivial-driver.test
+++ /dev/null
@@ -1,5 +0,0 @@
-# This test, tests the Gnu lld option --help
-RUN: lld -flavor old-gnu --help | FileCheck %s
-
-CHECK: --noinhibit-exec
-CHECK: --output-filetype
diff --git a/test/Driver/undef-basic.objtxt b/test/Driver/undef-basic.objtxt
deleted file mode 100644
index 7b11a7e8c982..000000000000
--- a/test/Driver/undef-basic.objtxt
+++ /dev/null
@@ -1,22 +0,0 @@
-# RUN: lld -flavor old-gnu -u undefinedsymbol -e entrysymbol %s \
-# RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s
-
-#
-# Test that we are able to add undefined atoms from the command line
-#
-
----
-absolute-atoms:
- - name: putchar
- value: 0xFFFF0040
-
- - name: reset
- value: 0xFFFF0080
-
-...
-
-
-# CHECK: undefined-atoms:
-# CHECK: - name: entrysymbol
-# CHECK: - name: undefinedsymbol
-# CHECK: can-be-null: at-buildtime
diff --git a/test/ELF/Inputs/aarch64-copy2.s b/test/ELF/Inputs/aarch64-copy2.s
new file mode 100644
index 000000000000..8f3f748366be
--- /dev/null
+++ b/test/ELF/Inputs/aarch64-copy2.s
@@ -0,0 +1,5 @@
+ .global foo
+ .type foo, @function
+foo:
+ .global bar
+bar:
diff --git a/test/ELF/Inputs/aarch64-tls-gdie.s b/test/ELF/Inputs/aarch64-tls-gdie.s
new file mode 100644
index 000000000000..289cae523fe8
--- /dev/null
+++ b/test/ELF/Inputs/aarch64-tls-gdie.s
@@ -0,0 +1,4 @@
+ .section .tdata,"awT",@progbits
+ .globl a
+a:
+ .word 42
diff --git a/test/ELF/Inputs/abs-hidden.s b/test/ELF/Inputs/abs-hidden.s
new file mode 100644
index 000000000000..44bff383a8e0
--- /dev/null
+++ b/test/ELF/Inputs/abs-hidden.s
@@ -0,0 +1,3 @@
+.global foo
+.hidden foo
+foo = 0x42
diff --git a/test/ELF/Inputs/allow-shlib-undefined.s b/test/ELF/Inputs/allow-shlib-undefined.s
index e2fb7de2301a..5e3a46179027 100644
--- a/test/ELF/Inputs/allow-shlib-undefined.s
+++ b/test/ELF/Inputs/allow-shlib-undefined.s
@@ -1,3 +1,3 @@
.globl _shared
_shared:
- call _unresolved
+ callq _unresolved@PLT
diff --git a/test/ELF/Inputs/archive.s b/test/ELF/Inputs/archive.s
index 42ccfd47b48b..568bc1fc0a49 100644
--- a/test/ELF/Inputs/archive.s
+++ b/test/ELF/Inputs/archive.s
@@ -1,5 +1,5 @@
-.globl _start;
+.globl _start
_start:
-.globl end;
+.globl end
end:
diff --git a/test/ELF/Inputs/arm-plt-reloc.s b/test/ELF/Inputs/arm-plt-reloc.s
new file mode 100644
index 000000000000..29f133e6eb8f
--- /dev/null
+++ b/test/ELF/Inputs/arm-plt-reloc.s
@@ -0,0 +1,14 @@
+.text
+ .align 2
+ .globl func1
+ .type func1,%function
+func1:
+ bx lr
+ .globl func2
+ .type func2,%function
+func2:
+ bx lr
+ .globl func3
+ .type func3,%function
+func3:
+ bx lr
diff --git a/test/ELF/Inputs/arm-thumb-blx-targets.s b/test/ELF/Inputs/arm-thumb-blx-targets.s
new file mode 100644
index 000000000000..4585ac4399cb
--- /dev/null
+++ b/test/ELF/Inputs/arm-thumb-blx-targets.s
@@ -0,0 +1,36 @@
+ .syntax unified
+ .arm
+ .section .R_ARM_CALL24_callee_low, "ax",%progbits
+ .align 2
+ .globl callee_low
+ .type callee_low,%function
+callee_low:
+ bx lr
+
+ .section .R_ARM_CALL24_callee_thumb_low, "ax",%progbits
+ .balign 0x100
+ .thumb
+ .type callee_thumb_low,%function
+ .globl callee_thumb_low
+callee_thumb_low:
+ bx lr
+
+ .section .R_ARM_CALL24_callee_high, "ax",%progbits
+ .balign 0x100
+ .arm
+ .globl callee_high
+ .type callee_high,%function
+callee_high:
+ bx lr
+
+ .section .R_ARM_CALL24_callee_thumb_high, "ax",%progbits
+ .balign 0x100
+ .thumb
+ .type callee_thumb_high,%function
+ .globl callee_thumb_high
+callee_thumb_high:
+ bx lr
+
+ .globl blx_far
+ .type blx_far, %function
+blx_far = 0x1010018
diff --git a/test/ELF/Inputs/arm-thumb-narrow-branch.s b/test/ELF/Inputs/arm-thumb-narrow-branch.s
new file mode 100644
index 000000000000..473a8e64ef74
--- /dev/null
+++ b/test/ELF/Inputs/arm-thumb-narrow-branch.s
@@ -0,0 +1,18 @@
+// This input must be assembled by the GNU assembler, as llvm-mc does not emit
+// the R_ARM_JUMP11 relocation for a Thumb narrow branch. This is permissible
+// by the ABI for the ARM architecture as the range of the Thumb narrow branch
+// is short enough (+- 2048 bytes) that widespread use would be impractical.
+//
+// The test case will use a pre compiled object arm-thumb-narrow-branch.o
+ .syntax unified
+ .section .caller, "ax",%progbits
+ .thumb
+ .align 2
+ .type callers,%function
+ .globl callers
+callers:
+ b.n callee_low_far
+ b.n callee_low
+ b.n callee_high
+ b.n callee_high_far
+ bx lr
diff --git a/test/ELF/Inputs/conflict.s b/test/ELF/Inputs/conflict.s
new file mode 100644
index 000000000000..545ae99c845a
--- /dev/null
+++ b/test/ELF/Inputs/conflict.s
@@ -0,0 +1,7 @@
+.globl _Z3muldd, foo, baz
+_Z3muldd:
+foo:
+baz:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/Inputs/copy-in-shared.s b/test/ELF/Inputs/copy-in-shared.s
new file mode 100644
index 000000000000..52e99c6707a7
--- /dev/null
+++ b/test/ELF/Inputs/copy-in-shared.s
@@ -0,0 +1,4 @@
+.type foo, @object
+.global foo
+foo:
+.size foo, 4
diff --git a/test/ELF/Inputs/copy-rel-corrupted.s b/test/ELF/Inputs/copy-rel-corrupted.s
new file mode 100644
index 000000000000..b8d1b1aa04c4
--- /dev/null
+++ b/test/ELF/Inputs/copy-rel-corrupted.s
@@ -0,0 +1,4 @@
+.type x,@object
+.globl x
+x:
+.size x, 0
diff --git a/test/ELF/Inputs/copy-rel-pie.s b/test/ELF/Inputs/copy-rel-pie.s
new file mode 100644
index 000000000000..6cd681fcecb4
--- /dev/null
+++ b/test/ELF/Inputs/copy-rel-pie.s
@@ -0,0 +1,9 @@
+.global foo
+.type foo, @object
+.size foo, 4
+foo:
+.long 0
+
+.global bar
+.type bar, @function
+bar:
diff --git a/test/ELF/Inputs/ctors_dtors_priority1.s b/test/ELF/Inputs/ctors_dtors_priority1.s
new file mode 100644
index 000000000000..2eb19d7edad9
--- /dev/null
+++ b/test/ELF/Inputs/ctors_dtors_priority1.s
@@ -0,0 +1,5 @@
+.section .ctors, "aw", @progbits
+ .byte 0xA1
+
+.section .dtors, "aw", @progbits
+ .byte 0xA2
diff --git a/test/ELF/Inputs/ctors_dtors_priority2.s b/test/ELF/Inputs/ctors_dtors_priority2.s
new file mode 100644
index 000000000000..fb85ce87c5c5
--- /dev/null
+++ b/test/ELF/Inputs/ctors_dtors_priority2.s
@@ -0,0 +1,5 @@
+.section .ctors, "aw", @progbits
+ .byte 0xB1
+
+.section .dtors, "aw", @progbits
+ .byte 0xB2
diff --git a/test/ELF/Inputs/ctors_dtors_priority3.s b/test/ELF/Inputs/ctors_dtors_priority3.s
new file mode 100644
index 000000000000..96418d351a85
--- /dev/null
+++ b/test/ELF/Inputs/ctors_dtors_priority3.s
@@ -0,0 +1,5 @@
+.section .ctors, "aw", @progbits
+ .byte 0xC1
+
+.section .dtors, "aw", @progbits
+ .byte 0xC2
diff --git a/test/ELF/Inputs/duplicated-plt-entry.s b/test/ELF/Inputs/duplicated-plt-entry.s
new file mode 100644
index 000000000000..689f3af0ef4a
--- /dev/null
+++ b/test/ELF/Inputs/duplicated-plt-entry.s
@@ -0,0 +1,3 @@
+.global bar
+.type bar, @gnu_indirect_function
+bar:
diff --git a/test/ELF/Inputs/dynamic-reloc-weak.s b/test/ELF/Inputs/dynamic-reloc-weak.s
new file mode 100644
index 000000000000..2310749d9f85
--- /dev/null
+++ b/test/ELF/Inputs/dynamic-reloc-weak.s
@@ -0,0 +1,11 @@
+ .type sym1,@function
+ .global sym1
+sym1:
+
+ .type sym2,@function
+ .global sym2
+sym2:
+
+ .type sym3,@function
+ .global sym3
+sym3:
diff --git a/test/ELF/Inputs/ehframe-relocation.s b/test/ELF/Inputs/ehframe-relocation.s
new file mode 100644
index 000000000000..7ba6c0510cc8
--- /dev/null
+++ b/test/ELF/Inputs/ehframe-relocation.s
@@ -0,0 +1,2 @@
+ .cfi_startproc
+ .cfi_endproc
diff --git a/test/ELF/Inputs/empty-ver.ver b/test/ELF/Inputs/empty-ver.ver
new file mode 100644
index 000000000000..7d4b4ede7675
--- /dev/null
+++ b/test/ELF/Inputs/empty-ver.ver
@@ -0,0 +1,2 @@
+ver {
+};
diff --git a/test/ELF/Inputs/far-arm-abs.s b/test/ELF/Inputs/far-arm-abs.s
new file mode 100644
index 000000000000..68d6aabe00b8
--- /dev/null
+++ b/test/ELF/Inputs/far-arm-abs.s
@@ -0,0 +1,13 @@
+.global far
+.type far,%function
+far = 0x201001c
+
+.global too_far1
+.type too_far1,%function
+too_far1 = 0x2020008
+.global too_far2
+.type too_far2,%function
+too_far2 = 0x202000c
+.global too_far3
+.type too_far3,%function
+too_far3 = 0x2020010
diff --git a/test/ELF/Inputs/far-arm-thumb-abs.s b/test/ELF/Inputs/far-arm-thumb-abs.s
new file mode 100644
index 000000000000..0eb99b8e6ee9
--- /dev/null
+++ b/test/ELF/Inputs/far-arm-thumb-abs.s
@@ -0,0 +1,24 @@
+.global far_cond
+.type far_cond,%function
+far_cond = 0x110023
+.global far_uncond
+.type far_uncond,%function
+far_uncond = 0x101001b
+
+.global too_far1
+.type too_far1,%function
+too_far1 = 0x1020005
+.global too_far2
+.type too_far1,%function
+too_far2 = 0x1020009
+.global too_far3
+.type too_far3,%function
+too_far3 = 0x12000d
+
+.global blx_far
+.type blx_far, %function
+blx_far = 0x2010025
+
+.global blx_far2
+.type blx_far2, %function
+blx_far2 = 0x2010029
diff --git a/test/ELF/Inputs/gc-sections-weak.s b/test/ELF/Inputs/gc-sections-weak.s
new file mode 100644
index 000000000000..27baa6694e3d
--- /dev/null
+++ b/test/ELF/Inputs/gc-sections-weak.s
@@ -0,0 +1,8 @@
+.weak foo
+foo:
+ nop
+
+.data
+.global bar2
+bar2:
+.quad foo
diff --git a/test/ELF/Inputs/gnu-ifunc-gotpcrel.s b/test/ELF/Inputs/gnu-ifunc-gotpcrel.s
new file mode 100644
index 000000000000..83b06e05d461
--- /dev/null
+++ b/test/ELF/Inputs/gnu-ifunc-gotpcrel.s
@@ -0,0 +1,4 @@
+.type foo STT_GNU_IFUNC
+.globl foo
+foo:
+ret
diff --git a/test/ELF/Inputs/gotpc-relax-und-dso.s b/test/ELF/Inputs/gotpc-relax-und-dso.s
new file mode 100644
index 000000000000..cbe39f38ef0b
--- /dev/null
+++ b/test/ELF/Inputs/gotpc-relax-und-dso.s
@@ -0,0 +1,4 @@
+.globl dsofoo
+.type dsofoo, @function
+dsofoo:
+ nop
diff --git a/test/ELF/Inputs/icf2.s b/test/ELF/Inputs/icf2.s
new file mode 100644
index 000000000000..d332130bc935
--- /dev/null
+++ b/test/ELF/Inputs/icf2.s
@@ -0,0 +1,5 @@
+.globl f1, f2
+.section .text.f2, "ax"
+f2:
+ mov $60, %rdi
+ call f1
diff --git a/test/ELF/Inputs/invalid-cie-version2.elf b/test/ELF/Inputs/invalid-cie-version2.elf
new file mode 100644
index 000000000000..87f8a5be76f4
--- /dev/null
+++ b/test/ELF/Inputs/invalid-cie-version2.elf
Binary files differ
diff --git a/test/ELF/Inputs/libsearch-dyn.s b/test/ELF/Inputs/libsearch-dyn.s
index c0c33f92944d..091b3b9b6ece 100644
--- a/test/ELF/Inputs/libsearch-dyn.s
+++ b/test/ELF/Inputs/libsearch-dyn.s
@@ -1,3 +1,3 @@
-.globl _bar,_dynamic;
+.globl _bar,_dynamic
_bar:
_dynamic:
diff --git a/test/ELF/Inputs/libsearch-st.s b/test/ELF/Inputs/libsearch-st.s
index c02ee741c803..6da62f79d52f 100644
--- a/test/ELF/Inputs/libsearch-st.s
+++ b/test/ELF/Inputs/libsearch-st.s
@@ -1,3 +1,3 @@
-.globl _bar,_static;
+.globl _bar,_static
_bar:
_static:
diff --git a/test/ELF/Inputs/mips-align-err.s b/test/ELF/Inputs/mips-align-err.s
new file mode 100644
index 000000000000..2d813b754a45
--- /dev/null
+++ b/test/ELF/Inputs/mips-align-err.s
@@ -0,0 +1,2 @@
+ .global _foo
+_foo:
diff --git a/test/ELF/Inputs/mips-dynamic.s b/test/ELF/Inputs/mips-dynamic.s
index eba5b7f327b4..6f15cf334d9d 100644
--- a/test/ELF/Inputs/mips-dynamic.s
+++ b/test/ELF/Inputs/mips-dynamic.s
@@ -1,4 +1,28 @@
+ .option pic2
.text
.globl _foo
_foo:
nop
+
+ .globl foo0
+ .type foo0, @function
+foo0:
+ nop
+
+ .globl foo1
+ .type foo1, @function
+foo1:
+ nop
+
+ .data
+ .globl data0
+ .type data0, @object
+ .size data0, 4
+data0:
+ .word 0
+
+ .globl data1
+ .type data1, @object
+ .size data1, 4
+data1:
+ .word 0
diff --git a/test/ELF/Inputs/mips-gp-disp.so b/test/ELF/Inputs/mips-gp-disp.so
index 9cbb43720606..150de18fcca1 100644
--- a/test/ELF/Inputs/mips-gp-disp.so
+++ b/test/ELF/Inputs/mips-gp-disp.so
Binary files differ
diff --git a/test/ELF/Inputs/mips-nonalloc.s b/test/ELF/Inputs/mips-nonalloc.s
new file mode 100644
index 000000000000..72bfd274335c
--- /dev/null
+++ b/test/ELF/Inputs/mips-nonalloc.s
@@ -0,0 +1,2 @@
+ .section .debug_info
+ .word __start
diff --git a/test/ELF/Inputs/mips-pic.s b/test/ELF/Inputs/mips-pic.s
new file mode 100644
index 000000000000..880903241d3d
--- /dev/null
+++ b/test/ELF/Inputs/mips-pic.s
@@ -0,0 +1,19 @@
+ .option pic2
+
+ .section .text.1,"ax",@progbits
+ .align 4
+ .globl foo1a
+ .type foo1a, @function
+foo1a:
+ nop
+ .globl foo1b
+ .type foo1b, @function
+foo1b:
+ nop
+
+ .section .text.2,"ax",@progbits
+ .align 4
+ .globl foo2
+ .type foo2, @function
+foo2:
+ nop
diff --git a/test/ELF/Inputs/mips-tls.s b/test/ELF/Inputs/mips-tls.s
new file mode 100644
index 000000000000..9e0a0983e1cd
--- /dev/null
+++ b/test/ELF/Inputs/mips-tls.s
@@ -0,0 +1,5 @@
+ .globl foo
+ .section .tdata,"awT",%progbits
+ .type foo, %object
+foo:
+ .word 0
diff --git a/test/ELF/Inputs/plt-aarch64.s b/test/ELF/Inputs/plt-aarch64.s
new file mode 100644
index 000000000000..0f7a4eda7be1
--- /dev/null
+++ b/test/ELF/Inputs/plt-aarch64.s
@@ -0,0 +1,5 @@
+.global bar
+bar:
+
+.global weak
+weak:
diff --git a/test/ELF/Inputs/ppc64-addr16-error.s b/test/ELF/Inputs/ppc64-addr16-error.s
new file mode 100644
index 000000000000..d83a9f929c6e
--- /dev/null
+++ b/test/ELF/Inputs/ppc64-addr16-error.s
@@ -0,0 +1,3 @@
+.global sym
+.hidden sym
+sym = 0
diff --git a/test/ELF/Inputs/protected-shared.s b/test/ELF/Inputs/protected-shared.s
new file mode 100644
index 000000000000..5f4b1daf63cc
--- /dev/null
+++ b/test/ELF/Inputs/protected-shared.s
@@ -0,0 +1,10 @@
+ .global foo
+ .protected foo
+foo:
+
+ .global bar
+ .protected bar
+bar:
+
+ .global zed
+zed:
diff --git a/test/ELF/Inputs/relocatable-ehframe.s b/test/ELF/Inputs/relocatable-ehframe.s
new file mode 100644
index 000000000000..384aac6e7ced
--- /dev/null
+++ b/test/ELF/Inputs/relocatable-ehframe.s
@@ -0,0 +1,14 @@
+.section foo1,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.section bar1,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.section dah1,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
diff --git a/test/ELF/Inputs/relocatable.s b/test/ELF/Inputs/relocatable.s
new file mode 100644
index 000000000000..de34a6b3bf0e
--- /dev/null
+++ b/test/ELF/Inputs/relocatable.s
@@ -0,0 +1,22 @@
+.text
+.type xx,@object
+.bss
+.globl xx
+.align 4
+xx:
+.long 0
+.size xx, 4
+.type yy,@object
+.globl yy
+.align 4
+yy:
+.long 0
+.size yy, 4
+
+.text
+.globl foo
+.align 16, 0x90
+.type foo,@function
+foo:
+movl $1, xx
+movl $2, yy
diff --git a/test/ELF/Inputs/relocatable2.s b/test/ELF/Inputs/relocatable2.s
new file mode 100644
index 000000000000..93e23bc7ae69
--- /dev/null
+++ b/test/ELF/Inputs/relocatable2.s
@@ -0,0 +1,22 @@
+.text
+.type xxx,@object
+.bss
+.globl xxx
+.align 4
+xxx:
+.long 0
+.size xxx, 4
+.type yyy,@object
+.globl yyy
+.align 4
+yyy:
+.long 0
+.size yyy, 4
+
+.text
+.globl bar
+.align 16, 0x90
+.type bar,@function
+bar:
+movl $8, xxx
+movl $9, yyy
diff --git a/test/ELF/Inputs/relocation-copy-alias.s b/test/ELF/Inputs/relocation-copy-alias.s
new file mode 100644
index 000000000000..a9bc3d76a12c
--- /dev/null
+++ b/test/ELF/Inputs/relocation-copy-alias.s
@@ -0,0 +1,25 @@
+.data
+
+.globl a1
+.type a1, @object
+.size a1, 1
+a1:
+.weak a2
+.type a2, @object
+.size a2, 1
+a2:
+.byte 1
+
+.weak b1
+.type b1, @object
+.size b1, 1
+b1:
+.weak b2
+.type b2, @object
+.size b2, 1
+b2:
+.globl b3
+.type b3, @object
+.size b3, 1
+b3:
+.byte 1
diff --git a/test/ELF/Inputs/relocation-copy-arm.s b/test/ELF/Inputs/relocation-copy-arm.s
new file mode 100644
index 000000000000..ba5ab73043c9
--- /dev/null
+++ b/test/ELF/Inputs/relocation-copy-arm.s
@@ -0,0 +1,22 @@
+.bss
+
+.type x,%object
+.globl x
+.balign 16
+x:
+.long 0
+.size x, 4
+
+.type y,%object
+.globl y
+.balign 16
+y:
+.long 0
+.size y, 4
+
+.type z,%object
+.globl z
+.balign 4
+z:
+.long 0
+.size z, 4
diff --git a/test/ELF/Inputs/resolution-shared.s b/test/ELF/Inputs/resolution-shared.s
new file mode 100644
index 000000000000..2f0ccf81e395
--- /dev/null
+++ b/test/ELF/Inputs/resolution-shared.s
@@ -0,0 +1,2 @@
+ .global foo
+foo:
diff --git a/test/ELF/Inputs/shared.s b/test/ELF/Inputs/shared.s
index 1cfebbfaf373..c3c22fe4b4fb 100644
--- a/test/ELF/Inputs/shared.s
+++ b/test/ELF/Inputs/shared.s
@@ -2,5 +2,9 @@
.type bar, @function
bar:
+.global bar2
+.type bar2, @function
+bar2:
+
.global zed
zed:
diff --git a/test/ELF/Inputs/start-lib-comdat.s b/test/ELF/Inputs/start-lib-comdat.s
new file mode 100644
index 000000000000..dcbaaf443851
--- /dev/null
+++ b/test/ELF/Inputs/start-lib-comdat.s
@@ -0,0 +1,5 @@
+ .global bar
+bar:
+ .section .sec,"aG",@progbits,zed,comdat
+ .global zed
+zed:
diff --git a/test/ELF/Inputs/start-lib1.s b/test/ELF/Inputs/start-lib1.s
new file mode 100644
index 000000000000..d401b20e65dc
--- /dev/null
+++ b/test/ELF/Inputs/start-lib1.s
@@ -0,0 +1,3 @@
+.globl foo
+foo:
+ call bar
diff --git a/test/ELF/Inputs/start-lib2.s b/test/ELF/Inputs/start-lib2.s
new file mode 100644
index 000000000000..f500936565f7
--- /dev/null
+++ b/test/ELF/Inputs/start-lib2.s
@@ -0,0 +1,2 @@
+.globl bar
+bar:
diff --git a/test/ELF/Inputs/symbol-override.s b/test/ELF/Inputs/symbol-override.s
new file mode 100644
index 000000000000..21f3ae244c77
--- /dev/null
+++ b/test/ELF/Inputs/symbol-override.s
@@ -0,0 +1,16 @@
+.text
+.globl foo
+.type foo,@function
+foo:
+nop
+
+.globl bar
+.type bar,@function
+bar:
+nop
+
+.globl do
+.type do,@function
+do:
+callq foo@PLT
+callq bar@PLT
diff --git a/test/ELF/Inputs/tls-got-entry.s b/test/ELF/Inputs/tls-got-entry.s
new file mode 100644
index 000000000000..e1e09a3306a2
--- /dev/null
+++ b/test/ELF/Inputs/tls-got-entry.s
@@ -0,0 +1,13 @@
+.globl __tls_get_addr
+.align 16, 0x90
+.type __tls_get_addr,@function
+__tls_get_addr:
+
+.type tlsshared0,@object
+.section .tbss,"awT",@nobits
+.globl tlsshared0
+.align 4
+tlsshared0:
+ .long 0
+ .size tlsshared0, 4
+
diff --git a/test/ELF/Inputs/tls-in-archive.s b/test/ELF/Inputs/tls-in-archive.s
new file mode 100644
index 000000000000..0474a417659e
--- /dev/null
+++ b/test/ELF/Inputs/tls-in-archive.s
@@ -0,0 +1,3 @@
+ .type foo, @tls_object
+ .globl foo
+foo:
diff --git a/test/ELF/Inputs/trace-ar1.s b/test/ELF/Inputs/trace-ar1.s
new file mode 100644
index 000000000000..0292bae6b4d4
--- /dev/null
+++ b/test/ELF/Inputs/trace-ar1.s
@@ -0,0 +1,2 @@
+.globl _used
+_used:
diff --git a/test/ELF/Inputs/trace-ar2.s b/test/ELF/Inputs/trace-ar2.s
new file mode 100644
index 000000000000..d56f304c82f3
--- /dev/null
+++ b/test/ELF/Inputs/trace-ar2.s
@@ -0,0 +1,2 @@
+.globl _notused
+_notused:
diff --git a/test/ELF/Inputs/trace-symbols-foo-strong.s b/test/ELF/Inputs/trace-symbols-foo-strong.s
new file mode 100644
index 000000000000..874642978c9b
--- /dev/null
+++ b/test/ELF/Inputs/trace-symbols-foo-strong.s
@@ -0,0 +1,14 @@
+.text
+.globl foo
+.type foo, @function
+foo:
+nop
+
+.globl bar
+.type bar, @function
+bar:
+nop
+
+.global func2
+.type func2, @function
+func2:
diff --git a/test/ELF/Inputs/trace-symbols-foo-weak.s b/test/ELF/Inputs/trace-symbols-foo-weak.s
new file mode 100644
index 000000000000..d071ebecc4b5
--- /dev/null
+++ b/test/ELF/Inputs/trace-symbols-foo-weak.s
@@ -0,0 +1,12 @@
+.comm common,4,4
+.text
+.weak foo
+.type foo, @function
+foo:
+callq bar@PLT
+
+.globl func1
+.type func1, @function
+func1:
+call func2@PLT
+
diff --git a/test/ELF/Inputs/undef-with-plt-addr.s b/test/ELF/Inputs/undef-with-plt-addr.s
new file mode 100644
index 000000000000..b12737d9e098
--- /dev/null
+++ b/test/ELF/Inputs/undef-with-plt-addr.s
@@ -0,0 +1,7 @@
+ .globl set_data
+ .type set_data,@function
+set_data:
+
+ .globl foo
+ .type foo,@function
+foo:
diff --git a/test/ELF/Inputs/undef.s b/test/ELF/Inputs/undef.s
new file mode 100644
index 000000000000..01776bf3505e
--- /dev/null
+++ b/test/ELF/Inputs/undef.s
@@ -0,0 +1,3 @@
+ .global zed1
+zed1:
+ .quad zed2
diff --git a/test/ELF/Inputs/unresolved-symbols.s b/test/ELF/Inputs/unresolved-symbols.s
new file mode 100644
index 000000000000..b504708e43da
--- /dev/null
+++ b/test/ELF/Inputs/unresolved-symbols.s
@@ -0,0 +1,3 @@
+.globl _shared
+_shared:
+ callq undef@PLT
diff --git a/test/ELF/Inputs/verdef-defaultver.s b/test/ELF/Inputs/verdef-defaultver.s
new file mode 100644
index 000000000000..2e1d1c36fb92
--- /dev/null
+++ b/test/ELF/Inputs/verdef-defaultver.s
@@ -0,0 +1,22 @@
+b@LIBSAMPLE_1.0 = b_1
+b@@LIBSAMPLE_2.0 = b_2
+
+.globl a
+.type a,@function
+a:
+retq
+
+.globl b_1
+.type b_1,@function
+b_1:
+retq
+
+.globl b_2
+.type b_2,@function
+b_2:
+retq
+
+.globl c
+.type c,@function
+c:
+retq
diff --git a/test/ELF/Inputs/verdef.s b/test/ELF/Inputs/verdef.s
new file mode 100644
index 000000000000..349d5fd0c261
--- /dev/null
+++ b/test/ELF/Inputs/verdef.s
@@ -0,0 +1,6 @@
+.text
+.globl _start
+_start:
+ callq a
+ callq b
+ callq c
diff --git a/test/ELF/Inputs/verneed.so.sh b/test/ELF/Inputs/verneed.so.sh
new file mode 100755
index 000000000000..3423f678e47a
--- /dev/null
+++ b/test/ELF/Inputs/verneed.so.sh
@@ -0,0 +1,58 @@
+#!/bin/sh -eu
+
+# This script was used to produce the verneed{1,2}.so files.
+
+tmp=$(mktemp -d)
+
+echo "v1 {}; v2 {}; v3 {}; { local: *; };" > $tmp/verneed.script
+
+cat > $tmp/verneed1.s <<eof
+.globl f1_v1
+f1_v1:
+ret
+
+.globl f1_v2
+f1_v2:
+ret
+
+.globl f1_v3
+f1_v3:
+ret
+
+.symver f1_v1, f1@v1
+.symver f1_v2, f1@v2
+.symver f1_v3, f1@@v3
+
+.globl f2_v1
+f2_v1:
+ret
+
+.globl f2_v2
+f2_v2:
+ret
+
+.symver f2_v1, f2@v1
+.symver f2_v2, f2@@v2
+
+.globl f3_v1
+f3_v1:
+ret
+
+.symver f3_v1, f3@v1
+eof
+
+as -o $tmp/verneed1.o $tmp/verneed1.s
+ld.gold -shared -o verneed1.so $tmp/verneed1.o --version-script $tmp/verneed.script -soname verneed1.so.0
+
+cat > $tmp/verneed2.s <<eof
+.globl g1_v1
+g1_v1:
+ret
+
+.symver g1_v1, g1@@v1
+eof
+
+as -o $tmp/verneed2.o $tmp/verneed2.s
+ld.gold -shared -o verneed2.so $tmp/verneed2.o --version-script $tmp/verneed.script -soname verneed2.so.0
+
+rm -rf $tmp
diff --git a/test/ELF/Inputs/version-script-err.script b/test/ELF/Inputs/version-script-err.script
new file mode 100644
index 000000000000..37de5980466e
--- /dev/null
+++ b/test/ELF/Inputs/version-script-err.script
@@ -0,0 +1,4 @@
+{
+ global:
+ foo
+};
diff --git a/test/ELF/Inputs/version-use.script b/test/ELF/Inputs/version-use.script
new file mode 100644
index 000000000000..5b2721b05b61
--- /dev/null
+++ b/test/ELF/Inputs/version-use.script
@@ -0,0 +1,6 @@
+ABC {
+global:
+foo;
+local:
+*;
+};
diff --git a/test/ELF/Inputs/visibility.s b/test/ELF/Inputs/visibility.s
index 6ef027d315fa..fe7cd9a49e7e 100644
--- a/test/ELF/Inputs/visibility.s
+++ b/test/ELF/Inputs/visibility.s
@@ -1,3 +1,4 @@
+.data
.quad default
.protected protected
diff --git a/test/ELF/Inputs/warn-common.s b/test/ELF/Inputs/warn-common.s
new file mode 100644
index 000000000000..fc4509ba70c7
--- /dev/null
+++ b/test/ELF/Inputs/warn-common.s
@@ -0,0 +1,2 @@
+.type arr,@object
+.comm arr,8,4
diff --git a/test/ELF/Inputs/warn-common2.s b/test/ELF/Inputs/warn-common2.s
new file mode 100644
index 000000000000..976c5becb09f
--- /dev/null
+++ b/test/ELF/Inputs/warn-common2.s
@@ -0,0 +1,8 @@
+.type arr,@object
+.data
+.globl arr
+.p2align 2
+arr:
+ .long 1
+ .long 0
+ .size arr, 8
diff --git a/test/ELF/Inputs/whole-archive.s b/test/ELF/Inputs/whole-archive.s
index f9d56fc2fa21..816b24e2beca 100644
--- a/test/ELF/Inputs/whole-archive.s
+++ b/test/ELF/Inputs/whole-archive.s
@@ -1,2 +1,2 @@
-.globl _bar;
+.globl _bar
_bar:
diff --git a/test/ELF/Inputs/x86-64-relax-offset.s b/test/ELF/Inputs/x86-64-relax-offset.s
new file mode 100644
index 000000000000..780d1d0e64c1
--- /dev/null
+++ b/test/ELF/Inputs/x86-64-relax-offset.s
@@ -0,0 +1,7 @@
+.global foo
+.hidden foo
+foo:
+ nop
+ nop
+ nop
+ nop
diff --git a/test/ELF/Inputs/x86-64-reloc-error.s b/test/ELF/Inputs/x86-64-reloc-error.s
new file mode 100644
index 000000000000..bce6f8fafaaa
--- /dev/null
+++ b/test/ELF/Inputs/x86-64-reloc-error.s
@@ -0,0 +1,7 @@
+.global big
+.hidden big
+big = 0x1000000000
+
+.global foo
+.hidden foo
+foo = 0
diff --git a/test/ELF/Inputs/x86-64-tls-gd-got.s b/test/ELF/Inputs/x86-64-tls-gd-got.s
new file mode 100644
index 000000000000..67a021a44fce
--- /dev/null
+++ b/test/ELF/Inputs/x86-64-tls-gd-got.s
@@ -0,0 +1,6 @@
+ .globl bar
+ .section .tdata,"awT",@progbits
+ .align 4
+ .type bar, @object
+bar:
+ .long 42
diff --git a/test/ELF/aarch64-abs64-dyn.s b/test/ELF/aarch64-abs64-dyn.s
new file mode 100644
index 000000000000..2220225d5300
--- /dev/null
+++ b/test/ELF/aarch64-abs64-dyn.s
@@ -0,0 +1,27 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o
+
+// Creates a R_AARCH64_ABS64 relocation against foo and bar
+ .globl foo
+foo:
+
+ .global bar
+ .hidden bar
+bar:
+
+ .data
+ .xword foo
+ .xword bar
+
+// RUN: ld.lld -shared -o %t.so %t.o
+// RUN: llvm-readobj -symbols -dyn-relocations %t.so | FileCheck %s
+
+// CHECK: Dynamic Relocations {
+// CHECK-NEXT: {{.*}} R_AARCH64_RELATIVE - [[BAR_ADDR:.*]]
+// CHECK-NEXT: {{.*}} R_AARCH64_ABS64 foo 0x0
+// CHECK-NEXT: }
+
+// CHECK: Symbols [
+// CHECK: Symbol {
+// CHECK: Name: bar
+// CHECK-NEXT: Value: [[BAR_ADDR]]
diff --git a/test/ELF/aarch64-copy.s b/test/ELF/aarch64-copy.s
index 86d972057df0..6e0af27a0c6b 100644
--- a/test/ELF/aarch64-copy.s
+++ b/test/ELF/aarch64-copy.s
@@ -5,7 +5,7 @@
// RUN: ld.lld %t.o %t2.so -o %t3
// RUN: llvm-readobj -s -r --expand-relocs -symbols %t3 | FileCheck %s
// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
-// RUN: llvm-objdump -s -section=.data %t3 | FileCheck -check-prefix=DATA %s
+// RUN: llvm-objdump -s -section=.rodata %t3 | FileCheck -check-prefix=RODATA %s
.text
.globl _start
@@ -13,7 +13,7 @@ _start:
adr x1, x
adrp x2, y
add x2, x2, :lo12:y
-.data
+.rodata
.word z
// CHECK: Name: .bss
@@ -22,7 +22,7 @@ _start:
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x13010
+// CHECK-NEXT: Address: 0x13000
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 24
// CHECK-NEXT: Link:
@@ -32,19 +32,19 @@ _start:
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: Relocation {
-// CHECK-NEXT: Offset: 0x13010
+// CHECK-NEXT: Offset: 0x13000
// CHECK-NEXT: Type: R_AARCH64_COPY
// CHECK-NEXT: Symbol: x
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
-// CHECK-NEXT: Offset: 0x13020
+// CHECK-NEXT: Offset: 0x13010
// CHECK-NEXT: Type: R_AARCH64_COPY
// CHECK-NEXT: Symbol: y
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
-// CHECK-NEXT: Offset: 0x13024
+// CHECK-NEXT: Offset: 0x13014
// CHECK-NEXT: Type: R_AARCH64_COPY
// CHECK-NEXT: Symbol: z
// CHECK-NEXT: Addend: 0x0
@@ -54,21 +54,21 @@ _start:
// CHECK: Symbols [
// CHECK: Name: x
-// CHECK-NEXT: Value: 0x13010
+// CHECK-NEXT: Value: 0x13000
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other:
// CHECK-NEXT: Section: .bss
// CHECK: Name: y
-// CHECK-NEXT: Value: 0x13020
+// CHECK-NEXT: Value: 0x13010
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other:
// CHECK-NEXT: Section: .bss
// CHECK: Name: z
-// CHECK-NEXT: Value: 0x13024
+// CHECK-NEXT: Value: 0x13014
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
@@ -78,16 +78,16 @@ _start:
// CODE: Disassembly of section .text:
// CODE-NEXT: _start:
-// S(x) = 0x13010, A = 0, P = 0x11000
-// S + A - P = 0x10B0 = 8208
-// CODE-NEXT: 11000: {{.*}} adr x1, #8208
-// S(y) = 0x13020, A = 0, P = 0x11004
+// S(x) = 0x13000, A = 0, P = 0x11000
+// S + A - P = 0x2000 = 8208
+// CODE-NEXT: 11000: {{.*}} adr x1, #8192
+// S(y) = 0x13010, A = 0, P = 0x11004
// Page(S + A) - Page(P) = 0x13000 - 0x11000 = 0x2000 = 8192
// CODE-NEXT: 11004: {{.*}} adrp x2, #8192
-// S(y) = 0x13020, A = 0
-// (S + A) & 0xFFF = 0x20 = 32
-// CODE-NEXT: 11008: {{.*}} add x2, x2, #32
+// S(y) = 0x13010, A = 0
+// (S + A) & 0xFFF = 0x10 = 16
+// CODE-NEXT: 11008: {{.*}} add x2, x2, #16
-// DATA: Contents of section .data:
-// S(z) = 0x13024
-// DATA-NEXT: 13000 24300100
+// RODATA: Contents of section .rodata:
+// S(z) = 0x13014
+// RODATA-NEXT: 101c8 14300100
diff --git a/test/ELF/aarch64-copy2.s b/test/ELF/aarch64-copy2.s
new file mode 100644
index 000000000000..af99d8ec2aee
--- /dev/null
+++ b/test/ELF/aarch64-copy2.s
@@ -0,0 +1,27 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux
+// RUN: llvm-mc %p/Inputs/aarch64-copy2.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-readobj -t %t | FileCheck %s
+
+ .global _start
+_start:
+ adrp x8, foo
+ bl bar
+
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x11030
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Function
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
diff --git a/test/ELF/aarch64-fpic-abs16.s b/test/ELF/aarch64-fpic-abs16.s
index 02ac90d3a1f2..e123f57447a5 100644
--- a/test/ELF/aarch64-fpic-abs16.s
+++ b/test/ELF/aarch64-fpic-abs16.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_ABS16 cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: relocation R_AARCH64_ABS16 cannot be used against shared object; recompile with -fPIC.
.data
.hword foo
diff --git a/test/ELF/aarch64-fpic-add_abs_lo12_nc.s b/test/ELF/aarch64-fpic-add_abs_lo12_nc.s
index 9e3216b1e090..7e0b6b833006 100644
--- a/test/ELF/aarch64-fpic-add_abs_lo12_nc.s
+++ b/test/ELF/aarch64-fpic-add_abs_lo12_nc.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_ADD_ABS_LO12_NC cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: can't create dynamic relocation R_AARCH64_ADD_ABS_LO12_NC against readonly segment
add x0, x0, :lo12:dat
.data
diff --git a/test/ELF/aarch64-fpic-adr_prel_lo21.s b/test/ELF/aarch64-fpic-adr_prel_lo21.s
index 2246b64c6a71..501a724616e3 100644
--- a/test/ELF/aarch64-fpic-adr_prel_lo21.s
+++ b/test/ELF/aarch64-fpic-adr_prel_lo21.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_ADR_PREL_LO21 cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: can't create dynamic relocation R_AARCH64_ADR_PREL_LO21 against readonly segment
adr x0, dat
.data
diff --git a/test/ELF/aarch64-fpic-adr_prel_pg_hi21.s b/test/ELF/aarch64-fpic-adr_prel_pg_hi21.s
index af6ebfc3e879..572ecffa6d71 100644
--- a/test/ELF/aarch64-fpic-adr_prel_pg_hi21.s
+++ b/test/ELF/aarch64-fpic-adr_prel_pg_hi21.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_ADR_PREL_PG_HI21 cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: can't create dynamic relocation R_AARCH64_ADR_PREL_PG_HI21 against readonly segment
adrp x0, dat
.data
diff --git a/test/ELF/aarch64-fpic-got.s b/test/ELF/aarch64-fpic-got.s
new file mode 100644
index 000000000000..70b2a7a76f86
--- /dev/null
+++ b/test/ELF/aarch64-fpic-got.s
@@ -0,0 +1,18 @@
+# REQUIRES: aarch64
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %p/Inputs/shared.s -o %t-lib.o
+# RUN: ld.lld -shared %t-lib.o -o %t-lib.so
+# RUN: ld.lld %t-lib.so %t.o -o %t.exe
+# RUN: llvm-readobj -dyn-relocations %t.exe | FileCheck %s
+
+## Checks if got access to dynamic objects is done through a got relative
+## dynamic relocation and not using plt relative (R_AARCH64_JUMP_SLOT).
+# CHECK: Dynamic Relocations {
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_AARCH64_GLOB_DAT bar 0x0
+# CHECK-NEXT: }
+
+.globl _start
+_start:
+ adrp x0, :got:bar
+ ldr x0, [x0, :got_lo12:bar]
diff --git a/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s
index 2b1e6769e1a0..85772f10fcc7 100644
--- a/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s
+++ b/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_LDST32_ABS_LO12_NC cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: can't create dynamic relocation R_AARCH64_LDST32_ABS_LO12_NC against readonly segment
ldr s4, [x0, :lo12:dat]
.data
diff --git a/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s
index f2553879cf37..d9f7b0c9ad1b 100644
--- a/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s
+++ b/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_LDST64_ABS_LO12_NC cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: can't create dynamic relocation R_AARCH64_LDST64_ABS_LO12_NC against readonly segment
ldr x0, [x0, :lo12:dat]
.data
diff --git a/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s
index f7b465731b46..20e1bba49d1e 100644
--- a/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s
+++ b/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_LDST8_ABS_LO12_NC cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: can't create dynamic relocation R_AARCH64_LDST8_ABS_LO12_NC against readonly segment
ldrsb x0, [x1, :lo12:dat]
.data
diff --git a/test/ELF/aarch64-fpic-prel16.s b/test/ELF/aarch64-fpic-prel16.s
index d80b6e88a67a..52e2402a4831 100644
--- a/test/ELF/aarch64-fpic-prel16.s
+++ b/test/ELF/aarch64-fpic-prel16.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_PREL16 cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: relocation R_AARCH64_PREL16 cannot be used against shared object; recompile with -fPIC.
.data
.hword foo - .
diff --git a/test/ELF/aarch64-fpic-prel32.s b/test/ELF/aarch64-fpic-prel32.s
index af540ce734bb..72ba58f84d56 100644
--- a/test/ELF/aarch64-fpic-prel32.s
+++ b/test/ELF/aarch64-fpic-prel32.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_PREL32 cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: relocation R_AARCH64_PREL32 cannot be used against shared object; recompile with -fPIC.
.data
.word foo - .
diff --git a/test/ELF/aarch64-fpic-prel64.s b/test/ELF/aarch64-fpic-prel64.s
index 2cf4cc916b3e..53a4820962b6 100644
--- a/test/ELF/aarch64-fpic-prel64.s
+++ b/test/ELF/aarch64-fpic-prel64.s
@@ -1,7 +1,7 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
// RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: Relocation R_AARCH64_PREL64 cannot be used when making a shared object; recompile with -fPIC.
+// CHECK: relocation R_AARCH64_PREL64 cannot be used against shared object; recompile with -fPIC.
.data
.xword foo - .
diff --git a/test/ELF/aarch64-gnu-ifunc-nosym.s b/test/ELF/aarch64-gnu-ifunc-nosym.s
index d85bf1076601..bb3a0b8b5116 100644
--- a/test/ELF/aarch64-gnu-ifunc-nosym.s
+++ b/test/ELF/aarch64-gnu-ifunc-nosym.s
@@ -6,20 +6,18 @@
// Check that no __rela_iplt_end/__rela_iplt_start
// appear in symtab if there is no references to them.
// CHECK: Symbols [
-// CHECK-NEXT-NOT: __rela_iplt_end
-// CHECK-NEXT-NOT: __rela_iplt_start
+// CHECK-NOT: __rela_iplt_end
+// CHECK-NOT: __rela_iplt_start
// CHECK: ]
.text
.type foo STT_GNU_IFUNC
.globl foo
-.type foo, @function
foo:
ret
.type bar STT_GNU_IFUNC
.globl bar
-.type bar, @function
bar:
ret
diff --git a/test/ELF/aarch64-gnu-ifunc.s b/test/ELF/aarch64-gnu-ifunc.s
index 4cc94200789d..351d0ed0440a 100644
--- a/test/ELF/aarch64-gnu-ifunc.s
+++ b/test/ELF/aarch64-gnu-ifunc.s
@@ -1,7 +1,7 @@
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
// RUN: ld.lld -static %t.o -o %tout
// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
-// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
+// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s
// REQUIRES: aarch64
// CHECK: Sections [
@@ -51,8 +51,10 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rela.plt
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: __rela_iplt_start
@@ -60,8 +62,10 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rela.plt
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: _start
@@ -126,13 +130,11 @@
.text
.type foo STT_GNU_IFUNC
.globl foo
-.type foo, @function
foo:
ret
.type bar STT_GNU_IFUNC
.globl bar
-.type bar, @function
bar:
ret
diff --git a/test/ELF/aarch64-got-relocations.s b/test/ELF/aarch64-got-relocations.s
new file mode 100644
index 000000000000..13ee09a892e9
--- /dev/null
+++ b/test/ELF/aarch64-got-relocations.s
@@ -0,0 +1,21 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-cloudabi %s -o %t.o
+# RUN: ld.lld -pie %t.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s
+
+# If we're addressing a global relatively through the GOT, we still need to
+# emit a relocation for the entry in the GOT itself.
+# CHECK: Relocations [
+# CHECK: Section (4) .rela.dyn {
+# CHECK: 0x{{[0-9A-F]+}} R_AARCH64_RELATIVE - 0x{{[0-9A-F]+}}
+# CHECK: }
+# CHECK: ]
+
+ .globl _start
+ .type _start,@function
+_start:
+ adrp x8, :got:i
+ ldr x8, [x8, :got_lo12:i]
+
+ .type i,@object
+ .comm i,4,4
diff --git a/test/ELF/aarch64-got.s b/test/ELF/aarch64-got.s
new file mode 100644
index 000000000000..f56d8a734784
--- /dev/null
+++ b/test/ELF/aarch64-got.s
@@ -0,0 +1,18 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-readobj -s %t | FileCheck %s
+
+# CHECK-NOT: Name: .got
+
+.globl _start
+_start:
+ adrp x0, :gottprel:foo
+
+ .global foo
+ .section .tdata,"awT",%progbits
+ .align 2
+ .type foo, %object
+ .size foo, 4
+foo:
+ .word 5
diff --git a/test/ELF/aarch64-relative.s b/test/ELF/aarch64-relative.s
new file mode 100644
index 000000000000..b10dd80fae6c
--- /dev/null
+++ b/test/ELF/aarch64-relative.s
@@ -0,0 +1,26 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -r %t.so | FileCheck %s
+
+ adr x8, .Lfoo // R_AARCH64_ADR_PREL_LO21
+ adrp x8, .Lfoo // R_AARCH64_ADR_PREL_PG_HI21
+ strb w9, [x8, :lo12:.Lfoo] // R_AARCH64_LDST8_ABS_LO12_NC
+ ldr h17, [x19, :lo12:.Lfoo] // R_AARCH64_LDST16_ABS_LO12_NC
+ ldr w0, [x8, :lo12:.Lfoo] // R_AARCH64_LDST32_ABS_LO12_NC
+ ldr x0, [x8, :lo12:.Lfoo] // R_AARCH64_LDST64_ABS_LO12_NC
+ ldr q20, [x19, #:lo12:.Lfoo] // R_AARCH64_LDST128_ABS_LO12_NC
+ add x0, x0, :lo12:.Lfoo // R_AARCH64_ADD_ABS_LO12_NC
+ bl .Lfoo // R_AARCH64_CALL26
+ b .Lfoo // R_AARCH64_JUMP26
+ beq .Lfoo // R_AARCH64_CONDBR19
+.Lbranch:
+ tbz x1, 7, .Lbranch // R_AARCH64_TSTBR14
+.data
+.Lfoo:
+
+.rodata
+.long .Lfoo - .
+.xword .Lfoo - . // R_AARCH64_PREL64
+// CHECK: Relocations [
+// CHECK-NEXT: ]
diff --git a/test/ELF/aarch64-relocs.s b/test/ELF/aarch64-relocs.s
index 56b04a679111..90541329587a 100644
--- a/test/ELF/aarch64-relocs.s
+++ b/test/ELF/aarch64-relocs.s
@@ -120,3 +120,33 @@ foo8:
# CHECK: Disassembly of section .R_AARCH64_LDST8_ABS_LO12_NC:
# CHECK-NEXT: ldst8:
# CHECK-NEXT: 11044: ab 21 81 39 ldrsb x11, [x13, #72]
+
+.section .R_AARCH64_LDST128_ABS_LO12_NC,"ax",@progbits
+ldst128:
+ ldr q20, [x19, #:lo12:foo128]
+foo128:
+ .asciz "foo"
+ .size mystr, 3
+
+# S = 0x1104c, A = 0x4
+# R = ((S + A) & 0xFF8) << 6 = 0x00001400
+# 0x00001400 | 0x3dc00274 = 0x3dc01674
+# CHECK: Disassembly of section .R_AARCH64_LDST128_ABS_LO12_NC:
+# CHECK: ldst128:
+# CHECK: 1104c: 74 16 c0 3d ldr q20, [x19, #80]
+#foo128:
+# 11050: 66 6f 6f 00 .word
+
+.section .R_AARCH64_LDST16_ABS_LO12_NC,"ax",@progbits
+ldst16:
+ ldr h17, [x19, :lo12:foo16]
+foo16:
+ .asciz "foo"
+ .size mystr, 3
+
+# S = 0x11054, A = 0x4
+# R = ((S + A) & 0x0FFC) << 9 = 0xb000
+# 0xb000 | 0x7d400271 = 0x7d40b271
+# CHECK: Disassembly of section .R_AARCH64_LDST16_ABS_LO12_NC:
+# CHECK-NEXT: ldst16:
+# CHECK-NEXT: 11054: 71 b2 40 7d ldr h17, [x19, #88]
diff --git a/test/ELF/aarch64-tls-gdie.s b/test/ELF/aarch64-tls-gdie.s
new file mode 100644
index 000000000000..709cc53a8c47
--- /dev/null
+++ b/test/ELF/aarch64-tls-gdie.s
@@ -0,0 +1,34 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux
+// RUN: llvm-mc %p/Inputs/aarch64-tls-gdie.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-readobj -s %t | FileCheck --check-prefix=SEC %s
+// RUN: llvm-objdump -d %t | FileCheck %s
+
+ .globl _start
+_start:
+ nop
+ adrp x0, :tlsdesc:a
+ ldr x1, [x0, :tlsdesc_lo12:a]
+ add x0, x0, :tlsdesc_lo12:a
+ .tlsdesccall a
+ blr x1
+
+// SEC: Name: .got
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT: SHF_ALLOC
+// SEC-NEXT: SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x120B0
+
+// page(0x120B0) - page(0x11004) = 4096
+// 0x0B0 = 176
+
+// CHECK: _start:
+// CHECK-NEXT: 11000: {{.*}} nop
+// CHECK-NEXT: 11004: {{.*}} adrp x0, #4096
+// CHECK-NEXT: 11008: {{.*}} ldr x0, [x0, #176]
+// CHECK-NEXT: 1100c: {{.*}} nop
+// CHECK-NEXT: 11010: {{.*}} nop
diff --git a/test/ELF/aarch64-tls-gdle.s b/test/ELF/aarch64-tls-gdle.s
new file mode 100644
index 000000000000..dc0c02a31d1c
--- /dev/null
+++ b/test/ELF/aarch64-tls-gdle.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o
+# RUN: ld.lld %tmain.o %ttlsie.o -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck %s
+# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
+# REQUIRES: aarch64
+
+#Local-Dynamic to Initial-Exec relax creates no
+#RELOC: Relocations [
+#RELOC-NEXT: ]
+
+# TCB size = 0x16 and foo is first element from TLS register.
+# CHECK: Disassembly of section .text:
+# CHECK: _start:
+# CHECK: 11000: 00 00 a0 d2 movz x0, #0, lsl #16
+# CHECK: 11004: 00 02 80 f2 movk x0, #16
+# CHECK: 11008: 1f 20 03 d5 nop
+# CHECK: 1100c: 1f 20 03 d5 nop
+
+.globl _start
+_start:
+ adrp x0, :tlsdesc:foo
+ ldr x1, [x0, :tlsdesc_lo12:foo]
+ add x0, x0, :tlsdesc_lo12:foo
+ .tlsdesccall foo
+ blr x1
diff --git a/test/ELF/aarch64-tls-ie.s b/test/ELF/aarch64-tls-ie.s
index 0462addba22d..0cec402b294a 100644
--- a/test/ELF/aarch64-tls-ie.s
+++ b/test/ELF/aarch64-tls-ie.s
@@ -1,3 +1,4 @@
+// REQUIRES: aarch64
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tls-ie.s -o %tdso.o
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o
# RUN: ld.lld -shared %tdso.o -o %tdso.so
@@ -24,8 +25,8 @@
#RELOC-NEXT: }
#RELOC: Relocations [
#RELOC-NEXT: Section ({{.*}}) .rela.dyn {
-#RELOC-NEXT: 0x120B0 R_AARCH64_TLS_TPREL64 foo 0x0
#RELOC-NEXT: 0x120B8 R_AARCH64_TLS_TPREL64 bar 0x0
+#RELOC-NEXT: 0x120B0 R_AARCH64_TLS_TPREL64 foo 0x0
#RELOC-NEXT: }
#RELOC-NEXT:]
diff --git a/test/ELF/aarch64-tls-iele.s b/test/ELF/aarch64-tls-iele.s
new file mode 100644
index 000000000000..91efc092a2cf
--- /dev/null
+++ b/test/ELF/aarch64-tls-iele.s
@@ -0,0 +1,33 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o
+# RUN: ld.lld %tmain.o %ttlsie.o -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck %s
+# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
+# REQUIRES: aarch64
+
+# Initial-Exec to Local-Exec relax creates no dynamic relocations.
+# RELOC: Relocations [
+# RELOC-NEXT: ]
+
+# TCB size = 0x16 and foo is first element from TLS register.
+# CHECK: Disassembly of section .text:
+# CHECK: _start:
+# CHECK-NEXT: 11000: 00 00 a0 d2 movz x0, #0, lsl #16
+# CHECK-NEXT: 11004: 80 02 80 f2 movk x0, #20
+# CHECK-NEXT: 11008: 00 00 a0 d2 movz x0, #0, lsl #16
+# CHECK-NEXT: 1100c: 00 02 80 f2 movk x0, #16
+
+.section .tdata
+.align 2
+.type foo_local, %object
+.size foo_local, 4
+foo_local:
+.word 5
+.text
+
+.globl _start
+_start:
+ adrp x0, :gottprel:foo
+ ldr x0, [x0, :gottprel_lo12:foo]
+ adrp x0, :gottprel:foo_local
+ ldr x0, [x0, :gottprel_lo12:foo_local]
diff --git a/test/ELF/aarch64-tls-le.s b/test/ELF/aarch64-tls-le.s
new file mode 100644
index 000000000000..22bd0ef2dad7
--- /dev/null
+++ b/test/ELF/aarch64-tls-le.s
@@ -0,0 +1,31 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o
+# RUN: ld.lld %tmain.o -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck %s
+# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
+# REQUIRES: aarch64
+
+#Local-Dynamic to Initial-Exec relax creates no
+#RELOC: Relocations [
+#RELOC-NEXT: ]
+
+.globl _start
+_start:
+ mrs x0, TPIDR_EL0
+ add x0, x0, :tprel_hi12:v1
+ add x0, x0, :tprel_lo12_nc:v1
+
+# TCB size = 0x16 and foo is first element from TLS register.
+#CHECK: Disassembly of section .text:
+#CHECK: _start:
+#CHECK: 11000: 40 d0 3b d5 mrs x0, TPIDR_EL0
+#CHECK: 11004: 00 00 00 91 add x0, x0, #0
+#CHECK: 11008: 00 40 00 91 add x0, x0, #16
+
+.type v1,@object
+.section .tbss,"awT",@nobits
+.globl v1
+.p2align 2
+v1:
+.word 0
+.size v1, 4
+
diff --git a/test/ELF/aarch64-tls-pie.s b/test/ELF/aarch64-tls-pie.s
new file mode 100644
index 000000000000..466045d6765d
--- /dev/null
+++ b/test/ELF/aarch64-tls-pie.s
@@ -0,0 +1,28 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-cloudabi %s -o %t1.o
+# RUN: ld.lld -pie %t1.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s
+
+# Similar to bug 27174: R_AARCH64_TLSLE_*TPREL* relocations should be
+# eliminated when building a PIE executable, as the static TLS layout is
+# fixed.
+#
+# CHECK: Relocations [
+# CHECK-NEXT: ]
+
+ .globl _start
+_start:
+ # Accessing the variable directly.
+ add x11, x8, :tprel_hi12:i
+ add x11, x11, :tprel_lo12_nc:i
+
+ # Accessing the variable through the GOT.
+ adrp x10, :gottprel:i
+ mrs x8, TPIDR_EL0
+ ldr x10, [x10, :gottprel_lo12:i]
+
+ .section .tbss.i,"awT",@nobits
+ .globl i
+i:
+ .word 0
+ .size i, 4
diff --git a/test/ELF/aarch64-tls-static.s b/test/ELF/aarch64-tls-static.s
new file mode 100644
index 000000000000..c8508ee58b7f
--- /dev/null
+++ b/test/ELF/aarch64-tls-static.s
@@ -0,0 +1,37 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc %s -o %t.o -triple aarch64-pc-linux -filetype=obj
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -s %t.so | FileCheck --check-prefix=SEC %s
+// RUN: llvm-objdump -d %t.so | FileCheck %s
+
+foo:
+ adrp x0, :tlsdesc:bar
+ ldr x1, [x0, :tlsdesc_lo12:bar]
+ add x0, x0, :tlsdesc_lo12:bar
+ .tlsdesccall bar
+ blr x1
+
+
+ .section .tdata,"awT",@progbits
+bar:
+ .word 42
+
+
+// SEC: Name: .got
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT: SHF_ALLOC
+// SEC-NEXT: SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x2098
+// SEC-NEXT: Offset: 0x2098
+// SEC-NEXT: Size: 16
+
+// page(0x2098) - page(0x1000) = 4096
+// 0x98 = 152
+
+// CHECK: foo:
+// CHECK-NEXT: 1000: {{.*}} adrp x0, #4096
+// CHECK-NEXT: 1004: {{.*}} ldr x1, [x0, #152]
+// CHECK-NEXT: 1008: {{.*}} add x0, x0, #152
+// CHECK-NEXT: 100c: {{.*}} blr x1
diff --git a/test/ELF/aarch64-tlsdesc.s b/test/ELF/aarch64-tlsdesc.s
new file mode 100644
index 000000000000..f8c73aff243d
--- /dev/null
+++ b/test/ELF/aarch64-tlsdesc.s
@@ -0,0 +1,24 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-objdump -d %t.so | FileCheck %s
+// RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=REL %s
+
+ adrp x0, :tlsdesc:a
+ ldr x1, [x0, :tlsdesc_lo12:a]
+ add x0, x0, :tlsdesc_lo12:a
+ .tlsdesccall a
+ blr x1
+
+// CHECK: 1000: {{.*}} adrp x0, #4096
+// CHECK-NEXT: 1004: {{.*}} ldr x1, [x0, #144]
+// CHECK-NEXT: 1008: {{.*}} add x0, x0, #144
+// CHECK-NEXT: 100c: {{.*}} blr x1
+
+// 0x1000 + 4096 + 144 = 0x2090
+
+// REL: Relocations [
+// REL-NEXT: Section (4) .rela.dyn {
+// REL-NEXT: 0x2090 R_AARCH64_TLSDESC a 0x0
+// REL-NEXT: }
+// REL-NEXT: ]
diff --git a/test/ELF/abs-hidden.s b/test/ELF/abs-hidden.s
new file mode 100644
index 000000000000..b93c2c692919
--- /dev/null
+++ b/test/ELF/abs-hidden.s
@@ -0,0 +1,46 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/abs-hidden.s -o %t2.o
+// RUN: ld.lld %t.o %t2.o -o %t.so -shared
+// RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s
+
+ .quad foo
+ .long foo@gotpcrel
+
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1000
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 12
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 42000000 00000000 58100000
+// 0x2060 - (0x1000 + 8) = 1058
+// CHECK-NEXT: )
+
+// CHECK: Name: .got (38)
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2060
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 42000000 00000000
+// CHECK-NEXT: )
+
+// CHECK: Relocations [
+// CHECK-NEXT: ]
diff --git a/test/ELF/allow-shlib-undefined.s b/test/ELF/allow-shlib-undefined.s
index 541a7e12007b..2d068b0f60ed 100644
--- a/test/ELF/allow-shlib-undefined.s
+++ b/test/ELF/allow-shlib-undefined.s
@@ -22,4 +22,4 @@
.globl _start
_start:
- call _shared
+ callq _shared@PLT
diff --git a/test/ELF/amdgpu-entry.s b/test/ELF/amdgpu-entry.s
index a17d243214b7..2a47b1778de8 100644
--- a/test/ELF/amdgpu-entry.s
+++ b/test/ELF/amdgpu-entry.s
@@ -1,5 +1,5 @@
# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
-# RUN: not lld -e kernel0 -flavor gnu %t.o -o %t
+# RUN: not ld.lld -e kernel0 %t.o -o %t
# REQUIRES: amdgpu
diff --git a/test/ELF/amdgpu-globals.s b/test/ELF/amdgpu-globals.s
index ff0899f60a98..7f46b989b955 100644
--- a/test/ELF/amdgpu-globals.s
+++ b/test/ELF/amdgpu-globals.s
@@ -77,7 +77,7 @@ program_global_readonly:
# CHECK: Symbol {
# CHECK: Name: module_global_agent
-# CHECK: Value: 0x0
+# CHECK: Value:
# CHECK: Size: 4
# CHECK: Binding: Local
# CHECK: Section: .hsadata_global_agent
@@ -85,7 +85,7 @@ program_global_readonly:
# CHECK: Symbol {
# CHECK: Name: module_global_program
-# CHECK: Value: 0x0
+# CHECK: Value:
# CHECK: Size: 4
# CHECK: Binding: Local
# CHECK: Section: .hsadata_global_program
@@ -93,7 +93,7 @@ program_global_readonly:
# CHECK: Symbol {
# CHECK: Name: module_global_readonly
-# CHECK: Value: 0x0
+# CHECK: Value:
# CHECK: Size: 4
# CHECK: Binding: Local
# CHECK: Type: Object
@@ -102,7 +102,7 @@ program_global_readonly:
# CHECK: Symbol {
# CHECK: Name: program_global_agent
-# CHECK: Value: 0x4
+# CHECK: Value:
# CHECK: Size: 4
# CHECK: Binding: Global
# CHECK: Type: Object
@@ -111,7 +111,7 @@ program_global_readonly:
# CHECK: Symbol {
# CHECK: Name: program_global_program
-# CHECK: Value: 0x4
+# CHECK: Value:
# CHECK: Size: 4
# CHECK: Binding: Global
# CHECK: Type: Object
@@ -120,7 +120,7 @@ program_global_readonly:
# CHECK: Symbol {
# CHECK: Name: program_global_readonly
-# CHECK: Value: 0x4
+# CHECK: Value:
# CHECK: Size: 4
# CHECK: Binding: Global
# CHECK: Type: Object
@@ -128,11 +128,11 @@ program_global_readonly:
# CHECK: }
# CHECK: ProgramHeader {
-# CHECK: Type: PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM
-# CHECK: VirtualAddress: [[HSADATA_GLOBAL_PROGRAM_ADDR]]
+# CHECK: Type: PT_LOAD
+# CHECK: VirtualAddress:
# CHECK: }
# CHECK: ProgramHeader {
-# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT
-# CHECK: VirtualAddress: [[HSATEXT_ADDR]]
+# CHECK: Type: PT_LOAD
+# CHECK: VirtualAddress:
# CHECK: }
diff --git a/test/ELF/amdgpu-kernels.s b/test/ELF/amdgpu-kernels.s
index 3f43c71f65d7..62a8cb74a541 100644
--- a/test/ELF/amdgpu-kernels.s
+++ b/test/ELF/amdgpu-kernels.s
@@ -1,5 +1,5 @@
# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
-# RUN: lld -flavor gnu %t.o -o %t
+# RUN: ld.lld %t.o -o %t
# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s
# REQUIRES: amdgpu
@@ -41,7 +41,7 @@ kernel1:
# CHECK: Symbol {
# CHECK: Name: kernel0
-# CHECK: Value: 0x0
+# CHECK: Value:
# CHECK: Size: 4
# CHECK: Binding: Global
# CHECK: Type: AMDGPU_HSA_KERNEL
@@ -50,7 +50,7 @@ kernel1:
# CHECK: Symbol {
# CHECK: Name: kernel1
-# CHECK: Value: 0x100
+# CHECK: Value:
# CHECK: Size: 8
# CHECK: Binding: Global
# CHECK: Type: AMDGPU_HSA_KERNEL
@@ -58,6 +58,6 @@ kernel1:
# CHECK: }
# CHECK: ProgramHeader {
-# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT
-# CHECK: VirtualAddress: [[HSATEXT_ADDR]]
+# CHECK: Type: PT_LOAD
+# CHECK: VirtualAddress:
# CHECK: }
diff --git a/test/ELF/amdgpu-relocs.s b/test/ELF/amdgpu-relocs.s
new file mode 100644
index 000000000000..58c9582a84f1
--- /dev/null
+++ b/test/ELF/amdgpu-relocs.s
@@ -0,0 +1,33 @@
+# RUN: llvm-mc -filetype=obj -triple=amdgcn--amdhsa -mcpu=fiji %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t.so
+# RUN: llvm-readobj -r %t.so | FileCheck %s
+
+# REQUIRES: amdgpu
+
+ .text
+
+kernel0:
+ s_mov_b32 s0, common_var@GOTPCREL+4
+ s_mov_b32 s0, extern_var@GOTPCREL+4
+ s_mov_b32 s0, local_var+4
+ s_mov_b32 s0, global_var@GOTPCREL+4
+ s_mov_b32 s0, weak_var@GOTPCREL+4
+ s_mov_b32 s0, weakref_var@GOTPCREL+4
+ s_endpgm
+
+ .comm common_var,1024,4
+ .globl global_var
+ .local local_var
+ .weak weak_var
+ .weakref weakref_var, weakref_alias_var
+
+# The relocation for local_var should be resolved by the linker.
+# CHECK: Relocations [
+# CHECK: .rela.dyn {
+# CHECK-NEXT: R_AMDGPU_ABS64 common_var 0x0
+# CHECK-NEXT: R_AMDGPU_ABS64 extern_var 0x0
+# CHECK-NEXT: R_AMDGPU_ABS64 global_var 0x0
+# CHECK-NEXT: R_AMDGPU_ABS64 weak_var 0x0
+# CHECK-NEXT: R_AMDGPU_ABS64 weakref_alias_var 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
diff --git a/test/ELF/archive.s b/test/ELF/archive.s
index 41d74451cdd6..59c96a5fba9b 100644
--- a/test/ELF/archive.s
+++ b/test/ELF/archive.s
@@ -6,6 +6,10 @@
# RUN: llvm-ar rcs %tar %t2 %t3 %t4
# RUN: ld.lld %t %tar %t5 -o %tout
# RUN: llvm-nm %tout | FileCheck %s
+# RUN: rm -f %tarthin
+# RUN: llvm-ar --format=gnu rcsT %tarthin %t2 %t3 %t4
+# RUN: ld.lld %t %tarthin %t5 -o %tout
+# RUN: llvm-nm %tout | FileCheck %s
# REQUIRES: x86
# Nothing here. Just needed for the linker to create a undefined _start symbol.
diff --git a/test/ELF/arm-abs32-dyn.s b/test/ELF/arm-abs32-dyn.s
new file mode 100644
index 000000000000..68183fe6f198
--- /dev/null
+++ b/test/ELF/arm-abs32-dyn.s
@@ -0,0 +1,32 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux %s -o %t.o
+
+// Creates a R_ARM_ABS32 relocation against foo and bar, bar has hidden
+// visibility so we expect a R_ARM_RELATIVE
+ .syntax unified
+ .globl foo
+foo:
+ .globl bar
+ .hidden bar
+bar:
+
+ .data
+ .word foo
+ .word bar
+
+// RUN: ld.lld -shared -o %t.so %t.o
+// RUN: llvm-readobj -symbols -dyn-relocations %t.so | FileCheck %s
+
+// CHECK: Dynamic Relocations {
+// CHECK-NEXT: 0x2004 R_ARM_RELATIVE
+// CHECK-NEXT: 0x2000 R_ARM_ABS32 foo 0x0
+// CHECK-NEXT: }
+
+// CHECK: Symbols [
+// CHECK: Symbol {
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x1000
+
+// CHECK: Symbol {
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x1000
diff --git a/test/ELF/arm-attributes-remove.s b/test/ELF/arm-attributes-remove.s
new file mode 100644
index 000000000000..010f366cd7fb
--- /dev/null
+++ b/test/ELF/arm-attributes-remove.s
@@ -0,0 +1,45 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -s %t | FileCheck %s
+// RUN: ld.lld %t.o -shared -o %t2
+// RUN: llvm-readobj -s %t2 | FileCheck %s
+// RUN: ld.lld %t.o -r -o %t3
+// RUN: llvm-readobj -s %t3 | FileCheck %s
+
+// The .ARM.attributes section should be removed from executables and
+// shared objects.
+
+// At present we remove it from the -r object output as well which isn't ideal.
+// Unfortunately combining per-object attributes cannot be safely done by just
+// concatentation of input sections.
+
+// CHECK-NOT: Name: .ARM.attributes
+// REQUIRES: arm
+ .text
+ .syntax unified
+ .eabi_attribute 67, "2.09" @ Tag_conformance
+ .cpu cortex-a8
+ .eabi_attribute 6, 10 @ Tag_CPU_arch
+ .eabi_attribute 7, 65 @ Tag_CPU_arch_profile
+ .eabi_attribute 8, 1 @ Tag_ARM_ISA_use
+ .eabi_attribute 9, 2 @ Tag_THUMB_ISA_use
+ .fpu neon
+ .eabi_attribute 15, 1 @ Tag_ABI_PCS_RW_data
+ .eabi_attribute 16, 1 @ Tag_ABI_PCS_RO_data
+ .eabi_attribute 17, 2 @ Tag_ABI_PCS_GOT_use
+ .eabi_attribute 20, 1 @ Tag_ABI_FP_denormal
+ .eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions
+ .eabi_attribute 23, 3 @ Tag_ABI_FP_number_model
+ .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access
+ .eabi_attribute 24, 1 @ Tag_ABI_align_needed
+ .eabi_attribute 25, 1 @ Tag_ABI_align_preserved
+ .eabi_attribute 38, 1 @ Tag_ABI_FP_16bit_format
+ .eabi_attribute 18, 4 @ Tag_ABI_PCS_wchar_t
+ .eabi_attribute 26, 2 @ Tag_ABI_enum_size
+ .eabi_attribute 14, 0 @ Tag_ABI_PCS_R9_use
+ .eabi_attribute 68, 1 @ Tag_Virtualization_use
+ .globl _start
+ .p2align 2
+ .type _start,%function
+_start:
+ bx lr
diff --git a/test/ELF/arm-blx.s b/test/ELF/arm-blx.s
new file mode 100644
index 000000000000..cccb1324fc8b
--- /dev/null
+++ b/test/ELF/arm-blx.s
@@ -0,0 +1,113 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar
+// RUN: echo "SECTIONS { \
+// RUN: .callee1 : { *(.callee_low) } \
+// RUN: .callee2 : { *(.callee_arm_low) } \
+// RUN: .caller : { *(.text) } \
+// RUN: .callee3 : { *(.callee_high) } \
+// RUN: .callee4 : { *(.callee_arm_high) } } " > %t.script
+// RUN: ld.lld --script %t.script %t %tfar -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-ARM %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-THUMB %s
+// REQUIRES: arm
+
+// Test BLX instruction is chosen for ARM BL/BLX instruction and Thumb callee
+// Using two callees to ensure at least one has 2-byte alignment.
+ .syntax unified
+ .thumb
+ .section .callee_low, "ax",%progbits
+ .align 2
+ .type callee_low,%function
+callee_low:
+ bx lr
+ .type callee_low2, %function
+callee_low2:
+ bx lr
+
+ .section .callee_arm_low, "ax",%progbits
+ .arm
+ .balign 0x100
+ .type callee_arm_low,%function
+ .align 2
+callee_arm_low:
+ bx lr
+
+.section .text, "ax",%progbits
+ .arm
+ .globl _start
+ .balign 0x10000
+ .type _start,%function
+_start:
+ bl callee_low
+ blx callee_low
+ bl callee_low2
+ blx callee_low2
+ bl callee_high
+ blx callee_high
+ bl callee_high2
+ blx callee_high2
+ bl blx_far
+ blx blx_far2
+// blx to ARM instruction should be written as a BL
+ bl callee_arm_low
+ blx callee_arm_low
+ bl callee_arm_high
+ blx callee_arm_high
+ bx lr
+
+ .section .callee_high, "ax",%progbits
+ .balign 0x100
+ .thumb
+ .type callee_high,%function
+callee_high:
+ bx lr
+ .type callee_high2,%function
+callee_high2:
+ bx lr
+
+ .section .callee_arm_high, "ax",%progbits
+ .arm
+ .balign 0x100
+ .type callee_arm_high,%function
+callee_arm_high:
+ bx lr
+
+// CHECK-THUMB: Disassembly of section .callee1:
+// CHECK-THUMB-NEXT: callee_low:
+// CHECK-THUMB-NEXT: b4: 70 47 bx lr
+// CHECK-THUMB: callee_low2:
+// CHECK-THUMB-NEXT: b6: 70 47 bx lr
+
+// CHECK-ARM: Disassembly of section .callee2:
+// CHECK-ARM-NEXT: callee_arm_low:
+// CHECK-ARM-NEXT: 100: 1e ff 2f e1 bx lr
+
+// CHECK-ARM: Disassembly of section .caller:
+// CHECK-ARM-NEXT: _start:
+// CHECK-ARM-NEXT: 10000: 2b c0 ff fa blx #-65364 <callee_low>
+// CHECK-ARM-NEXT: 10004: 2a c0 ff fa blx #-65368 <callee_low>
+// CHECK-ARM-NEXT: 10008: 29 c0 ff fb blx #-65370 <callee_low2>
+// CHECK-ARM-NEXT: 1000c: 28 c0 ff fb blx #-65374 <callee_low2>
+// CHECK-ARM-NEXT: 10010: 3a 00 00 fa blx #232 <callee_high>
+// CHECK-ARM-NEXT: 10014: 39 00 00 fa blx #228 <callee_high>
+// CHECK-ARM-NEXT: 10018: 38 00 00 fb blx #226 <callee_high2>
+// CHECK-ARM-NEXT: 1001c: 37 00 00 fb blx #222 <callee_high2>
+// 10020 + 1FFFFFC + 8 = 0x2010024 = blx_far
+// CHECK-ARM-NEXT: 10020: ff ff 7f fa blx #33554428
+// 10024 + 1FFFFFC + 8 = 0x2010028 = blx_far2
+// CHECK-ARM-NEXT: 10024: ff ff 7f fa blx #33554428
+// CHECK-ARM-NEXT: 10028: 34 c0 ff eb bl #-65328 <callee_arm_low>
+// CHECK-ARM-NEXT: 1002c: 33 c0 ff eb bl #-65332 <callee_arm_low>
+// CHECK-ARM-NEXT: 10030: 72 00 00 eb bl #456 <callee_arm_high>
+// CHECK-ARM-NEXT: 10034: 71 00 00 eb bl #452 <callee_arm_high>
+// CHECK-ARM-NEXT: 10038: 1e ff 2f e1 bx lr
+
+// CHECK-THUMB: Disassembly of section .callee3:
+// CHECK-THUMB: callee_high:
+// CHECK-THUMB-NEXT: 10100: 70 47 bx lr
+// CHECK-THUMB: callee_high2:
+// CHECK-THUMB-NEXT: 10102: 70 47 bx lr
+
+// CHECK-ARM: Disassembly of section .callee4:
+// CHECK-NEXT-ARM: callee_arm_high:
+// CHECK-NEXT-ARM: 10200: 1e ff 2f e1 bx lr
diff --git a/test/ELF/arm-branch-error.s b/test/ELF/arm-branch-error.s
new file mode 100644
index 000000000000..f1a855d7373f
--- /dev/null
+++ b/test/ELF/arm-branch-error.s
@@ -0,0 +1,19 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar
+// RUN: not ld.lld %t %tfar -o %t2 2>&1 | FileCheck %s
+// REQUIRES: arm
+ .syntax unified
+ .section .text, "ax",%progbits
+ .globl _start
+ .balign 0x10000
+ .type _start,%function
+_start:
+ // address of too_far symbols are just out of range of ARM branch with
+ // 26-bit immediate field and an addend of -8
+ bl too_far1
+ b too_far2
+ beq too_far3
+
+// CHECK: R_ARM_CALL out of range
+// CHECK-NEXT: R_ARM_JUMP24 out of range
+// CHECK-NEXT: R_ARM_JUMP24 out of range
diff --git a/test/ELF/arm-branch.s b/test/ELF/arm-branch.s
new file mode 100644
index 000000000000..38266fabf852
--- /dev/null
+++ b/test/ELF/arm-branch.s
@@ -0,0 +1,59 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar
+// RUN: echo "SECTIONS { \
+// RUN: .callee1 : { *(.callee_low) } \
+// RUN: .caller : { *(.text) } \
+// RUN: .callee2 : { *(.callee_high) } } " > %t.script
+// RUN: ld.lld --script %t.script %t %tfar -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// REQUIRES: arm
+ .syntax unified
+ .section .callee_low, "ax",%progbits
+ .align 2
+ .type callee_low,%function
+callee_low:
+ bx lr
+
+ .section .text, "ax",%progbits
+ .globl _start
+ .balign 0x10000
+ .type _start,%function
+_start:
+ bl callee_low
+ b callee_low
+ beq callee_low
+ bl callee_high
+ b callee_high
+ bne callee_high
+ bl far
+ b far
+ bgt far
+ bx lr
+
+ .section .callee_high, "ax",%progbits
+ .align 2
+ .type callee_high,%function
+callee_high:
+ bx lr
+
+// CHECK: Disassembly of section .caller:
+// CHECK-NEXT: _start:
+// S(callee_low) = 0xb4 P = 0x10000 A = -8 = -0xff54 = -65364
+// CHECK-NEXT: 10000: 2b c0 ff eb bl #-65364 <callee_low>
+// S(callee_low) = 0xb4 P = 0x10004 A = -8 = -0xff58 = -65368
+// CHECK-NEXT: 10004: 2a c0 ff ea b #-65368 <callee_low>
+// S(callee_low) = 0xb4 P = 0x10008 A = -8 = -0xff5c -65372
+// CHECK-NEXT: 10008: 29 c0 ff 0a beq #-65372 <callee_low>
+// S(callee_high) = 0x10028 P = 0x1000c A = -8 = 0x14 = 20
+// CHECK-NEXT: 1000c: 05 00 00 eb bl #20 <callee_high>
+// S(callee_high) = 0x10028 P = 0x10010 A = -8 = 0x10 = 16
+// CHECK-NEXT: 10010: 04 00 00 ea b #16 <callee_high>
+// S(callee_high) = 0x10028 P = 0x10014 A = -8 = 0x0c =12
+// CHECK-NEXT: 10014: 03 00 00 1a bne #12 <callee_high>
+// S(far) = 0x201001c P = 0x10018 A = -8 = 0x1fffffc = 33554428
+// CHECK-NEXT: 10018: ff ff 7f eb bl #33554428
+// S(far) = 0x201001c P = 0x1001c A = -8 = 0x1fffff8 = 33554424
+// CHECK-NEXT: 1001c: fe ff 7f ea b #33554424
+// S(far) = 0x201001c P = 0x10020 A = -8 = 0x1fffff4 = 33554420
+// CHECK-NEXT: 10020: fd ff 7f ca bgt #33554420
+// CHECK-NEXT: 10024: 1e ff 2f e1 bx lr
diff --git a/test/ELF/arm-copy.s b/test/ELF/arm-copy.s
new file mode 100644
index 000000000000..e5ce1577babd
--- /dev/null
+++ b/test/ELF/arm-copy.s
@@ -0,0 +1,81 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/relocation-copy-arm.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t3
+// RUN: llvm-readobj -s -r --expand-relocs -symbols %t3 | FileCheck %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CODE %s
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi -section=.rodata %t3 | FileCheck -check-prefix=RODATA %s
+
+// Copy relocations R_ARM_COPY are required for y and z
+ .syntax unified
+ .text
+ .globl _start
+_start:
+ movw r2,:lower16: y
+ movt r2,:upper16: y
+ ldr r3,[pc,#4]
+ ldr r3,[r3,#0]
+ .rodata
+ .word z
+
+// CHECK: Name: .bss
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x13000
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment: 16
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section (5) .rel.dyn {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x13000
+// CHECK-NEXT: Type: R_ARM_COPY
+// CHECK-NEXT: Symbol: y
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x13004
+// CHECK-NEXT: Type: R_ARM_COPY
+// CHECK-NEXT: Symbol: z
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+
+// CHECK: Symbols [
+// CHECK: Name: y
+// CHECK-NEXT: Value: 0x13000
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other:
+// CHECK-NEXT: Section: .bss
+// CHECK: Name: z
+// CHECK-NEXT: Value: 0x13004
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+// CODE: Disassembly of section .text:
+// CODE-NEXT: _start:
+// S(y) = 0x13000, A = 0
+// (S + A) & 0x0000ffff = 0x3000 = #12288
+// CODE-NEXT: 11000: 00 20 03 e3 movw r2, #12288
+// S(y) = 0x13000, A = 0
+// ((S + A) & 0xffff0000) >> 16 = 0x1
+// CODE-NEXT: 11004: 01 20 40 e3 movt r2, #1
+// CODE-NEXT: 11008: 04 30 9f e5 ldr r3, [pc, #4]
+// CODE-NEXT: 1100c: 00 30 93 e5 ldr r3, [r3]
+
+
+// RODATA: Contents of section .rodata:
+// S(z) = 0x13004
+// RODATA-NEXT: 10114 04300100
diff --git a/test/ELF/arm-data-prel.s b/test/ELF/arm-data-prel.s
new file mode 100644
index 000000000000..590d8118ae6e
--- /dev/null
+++ b/test/ELF/arm-data-prel.s
@@ -0,0 +1,63 @@
+// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o
+// RUN: echo "SECTIONS { \
+// RUN: .text : { *(.text) } \
+// RUN: .ARM.exidx : { *(.ARM.exidx) } \
+// RUN: .ARM.exidx.TEST1 : { *(.ARM.exidx.TEST1) } \
+// RUN: .TEST1 : { *(.TEST1) } } " > %t.script
+// RUN: ld.lld --script %t.script %t.o -o %t
+// RUN: llvm-readobj -s -sd %t | FileCheck --check-prefix=CHECK %s
+// REQUIRES: arm
+
+// The R_ARM_PREL31 relocation is used in by the .ARM.exidx exception tables
+// bit31 of the place denotes whether the field is an inline table entry
+// (bit31=1) or relocation (bit31=0)
+// The linker must preserve the value of bit31
+
+// This test case is adapted from llvm/test/MC/ARM/eh-compact-pr0.s
+// We use a linker script to place the .ARM.exidx sections in between
+// the code sections so that we can test positive and negative offsets
+ .syntax unified
+
+ .section .TEST1, "ax",%progbits
+ .globl _start
+ .align 2
+ .type _start,%function
+_start:
+ .fnstart
+ .save {r11, lr}
+ push {r11, lr}
+ .setfp r11, sp
+ mov r11, sp
+ pop {r11, lr}
+ mov pc, lr
+ .fnend
+
+ .section .text, "ax",%progbits
+// The generated .ARM.exidx section will refer to the personality
+// routine __aeabi_unwind_cpp_pr0. Provide a dummy implementation
+// to stop an undefined symbol error
+ .globl __aeabi_unwind_cpp_pr0
+ .align 2
+ .type __aeabi_unwind_cpp_pr0,%function
+__aeabi_unwind_cpp_pr0:
+ .fnstart
+ bx lr
+ .fnend
+
+// The expected value of the exception table is
+// Word0 0 in bit 31, -4 encoded in 31-bit signed offset
+// Word1 Inline table entry EHT Inline Personality Routine #0
+// CHECK: Name: .ARM.exidx
+// CHECK: SectionData (
+// CHECK: 0000: FCFFFF7F B0B0B080
+// CHECK: )
+
+// The expected value of the exception table is
+// Word0 0 in bit 31, +8 encoded in 31-bit signed offset
+// Word1 Inline table entry EHT Inline Personality Routine #0
+// set vsp = r11
+// pop r11, r14
+// CHECK: Name: .ARM.exidx.TEST1
+// CHECK: SectionData (
+// CHECK: 0000: 08000000 80849B80
+// CHECK: )
diff --git a/test/ELF/arm-data-relocs.s b/test/ELF/arm-data-relocs.s
new file mode 100644
index 000000000000..ed237850c4c1
--- /dev/null
+++ b/test/ELF/arm-data-relocs.s
@@ -0,0 +1,20 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/abs256.s -o %t256.o
+// RUN: ld.lld %t %t256.o -o %t2
+// RUN: llvm-objdump -d %t2 | FileCheck %s
+// REQUIRES: arm
+ .syntax unified
+ .globl _start
+_start:
+ .section .R_ARM_ABS32POS, "ax",%progbits
+ .word foo + 0x24
+
+// S = 0x100, A = 0x24
+// S + A = 0x124
+// CHECK: Disassembly of section .R_ARM_ABS32POS:
+// CHECK: 11000: 24 01 00 00
+ .section .R_ARM_ABS32NEG, "ax",%progbits
+ .word foo - 0x24
+// S = 0x100, A = -0x24
+// CHECK: Disassembly of section .R_ARM_ABS32NEG:
+// CHECK: 11004: dc 00 00 00
diff --git a/test/ELF/arm-fpic-got.s b/test/ELF/arm-fpic-got.s
new file mode 100644
index 000000000000..4b6002d3c077
--- /dev/null
+++ b/test/ELF/arm-fpic-got.s
@@ -0,0 +1,63 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -s %t | FileCheck %s
+// RUN: llvm-readobj -s -symbols %t | FileCheck -check-prefix=SYMBOLS %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s
+
+// Test the R_ARM_GOT_PREL relocation
+ .syntax unified
+ .text
+ .globl _start
+ .align 2
+_start:
+ ldr r0, .LCPI0_0
+.LPC0_0:
+ ldr r0, [pc, r0]
+ ldr r0, [r0]
+ bx lr
+.LCPI0_0:
+.Ltmp0:
+ // Generate R_ARM_GOT_PREL
+ .long val(GOT_PREL)-((.LPC0_0+8)-.Ltmp0)
+
+ .data
+ .type val,%object
+ .globl val
+ .align 2
+val:
+ .long 10
+ .size val, 4
+
+// CHECK: Section {
+// CHECK: Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x12000
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize:
+
+// SYMBOLS: Name: val
+// SYMBOLS-NEXT: Value: 0x13000
+// SYMBOLS-NEXT: Size: 4
+// SYMBOLS-NEXT: Binding: Global
+// SYMBOLS-NEXT: Type: Object
+// SYMBOLS-NEXT: Other:
+// SYMBOLS-NEXT: Section: .data
+
+// CODE: Disassembly of section .text:
+// CODE-NEXT: _start:
+// CODE-NEXT: 11000: 08 00 9f e5 ldr r0, [pc, #8]
+// CODE-NEXT: 11004: 00 00 9f e7 ldr r0, [pc, r0]
+// CODE-NEXT: 11008: 00 00 90 e5 ldr r0, [r0]
+// CODE-NEXT: 1100c: 1e ff 2f e1 bx lr
+// CODE: $d.1:
+// 0x11004 + 0x0ff4 + 8 = 0x12000 = .got
+// CODE-NEXT: 11010: f4 0f 00 00
diff --git a/test/ELF/arm-gnu-ifunc-nosym.s b/test/ELF/arm-gnu-ifunc-nosym.s
new file mode 100644
index 000000000000..fa79aef7ced8
--- /dev/null
+++ b/test/ELF/arm-gnu-ifunc-nosym.s
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-readobj -symbols %tout | FileCheck %s
+// REQUIRES: arm
+
+// Check that no __rel_iplt_end/__rel_iplt_start
+// appear in symtab if there are no references to them.
+// CHECK: Symbols [
+// CHECK-NOT: __rel_iplt_end
+// CHECK-NOT: __rel_iplt_start
+// CHECK: ]
+ .syntax unified
+ .text
+ .type foo STT_GNU_IFUNC
+ .globl foo
+foo:
+ bx lr
+
+ .type bar STT_GNU_IFUNC
+ .globl bar
+bar:
+ bx lr
+
+ .globl _start
+_start:
+ bl foo
+ bl bar
diff --git a/test/ELF/arm-gnu-ifunc.s b/test/ELF/arm-gnu-ifunc.s
new file mode 100644
index 000000000000..c1e8a7183530
--- /dev/null
+++ b/test/ELF/arm-gnu-ifunc.s
@@ -0,0 +1,131 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-objdump -triple armv7a-none-linux-gnueabi -d %tout | FileCheck %s --check-prefix=DISASM
+// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s
+// REQUIRES: arm
+ .syntax unified
+ .text
+ .type foo STT_GNU_IFUNC
+ .globl foo
+foo:
+ bx lr
+
+ .type bar STT_GNU_IFUNC
+ .globl bar
+bar:
+ bx lr
+
+ .globl _start
+_start:
+ bl foo
+ bl bar
+ movw r0,:lower16:__rel_iplt_start
+ movt r0,:upper16:__rel_iplt_start
+ movw r0,:lower16:__rel_iplt_end
+ movt r0,:upper16:__rel_iplt_end
+
+// CHECK: Sections [
+// CHECK: Section {
+// CHECK: Index: 1
+// CHECK-NEXT: Name: .rel.plt
+// CHECK-NEXT: Type: SHT_REL
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[REL:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 8
+// CHECK-NEXT: }
+// CHECK: Relocations [
+// CHECK-NEXT: Section (1) .rel.plt {
+// CHECK-NEXT: 0x1200C R_ARM_IRELATIVE
+// CHECK-NEXT: 0x12010 R_ARM_IRELATIVE
+// CHECK-NEXT: }
+// CHECK-NEXT:]
+// CHECK: Symbols [
+// CHECK: Symbol {
+// CHECK: Name: __rel_iplt_end
+// CHECK-NEXT: Value: 0x100E4
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rel.plt
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __rel_iplt_start
+// CHECK-NEXT: Value: 0x100D4
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rel.plt
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _start (6)
+// CHECK-NEXT: Value: 0x11008
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other:
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: bar
+// CHECK-NEXT: Value: 0x11004
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: GNU_IFunc
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: foo
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: GNU_IFunc
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: foo:
+// DISASM-NEXT: 11000: 1e ff 2f e1 bx lr
+// DISASM: bar:
+// DISASM-NEXT: 11004: 1e ff 2f e1 bx lr
+// DISASM: _start:
+// DISASM-NEXT: 11008: 09 00 00 eb bl #36
+// DISASM-NEXT: 1100c: 0c 00 00 eb bl #48
+// DISASM-NEXT: 11010: d4 00 00 e3 movw r0, #212
+// DISASM-NEXT: 11014: 01 00 40 e3 movt r0, #1
+// r0 = 212 + 1 * 65536 = 100D4 = __rel_iplt_start
+// DISASM-NEXT: 11018: e4 00 00 e3 movw r0, #228
+// DISASM-NEXT: 1101c: 01 00 40 e3 movt r0, #1
+// r1 = 228 + 1 * 65536 = 100E4 = __rel_iplt_end
+// DISASM-NEXT: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT: 11020: 04 e0 2d e5 str lr, [sp, #-4]!
+// DISASM-NEXT: 11024: 04 e0 9f e5 ldr lr, [pc, #4]
+// DISASM-NEXT: 11028: 0e e0 8f e0 add lr, pc, lr
+// DISASM-NEXT: 1102c: 08 f0 be e5 ldr pc, [lr, #8]!
+// 0x0fd0 + 0x11028 + 0x8 = 0x12000
+// DISASM-NEXT: 11030: d0 0f 00 00
+// DISASM-NEXT: 11034: 04 c0 9f e5 ldr r12, [pc, #4]
+// DISASM-NEXT: 11038: 0f c0 8c e0 add r12, r12, pc
+// DISASM-NEXT: 1103c: 00 f0 9c e5 ldr pc, [r12]
+// 0x0fcc + 0x11038 + 0x8 = 0x1200C
+// DISASM-NEXT: 11040: cc 0f 00 00
+// DISASM-NEXT: 11044: 04 c0 9f e5 ldr r12, [pc, #4]
+// DISASM-NEXT: 11048: 0f c0 8c e0 add r12, r12, pc
+// DISASM-NEXT: 1104c: 00 f0 9c e5 ldr pc, [r12]
+// 0x0fc0 + 0x11048 + 0x8 = 0x12010
+// DISASM-NEXT: 11050: c0 0f 00 00
diff --git a/test/ELF/arm-got-relative.s b/test/ELF/arm-got-relative.s
new file mode 100644
index 000000000000..22ccb16a2a58
--- /dev/null
+++ b/test/ELF/arm-got-relative.s
@@ -0,0 +1,53 @@
+// REQUIRES: arm
+// RUN: llvm-mc -position-independent -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: ld.lld %t.o -shared -o %t
+// RUN: llvm-readobj -s -symbols -dyn-relocations %t | FileCheck %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s
+ .syntax unified
+ .text
+ .globl _start
+ .align 2
+_start:
+ .type _start, %function
+ ldr r3, .LGOT
+ ldr r2, .LGOT+4
+.LPIC:
+ add r0, pc, r3
+ bx lr
+ .align 2
+.LGOT:
+ // gas implicitly uses (GOT_PREL) for _GLOBAL_OFFSET_TABLE_ in PIC
+ // llvm-mc needs the (GOT_PREL) suffix or it generates R_ARM_REL32
+ .word _GLOBAL_OFFSET_TABLE_(GOT_PREL) - (.LPIC+8)
+ .word function(GOT)
+
+ .globl function
+ .align 2
+function:
+ .type function, %function
+ bx lr
+
+// CHECK: Dynamic Relocations {
+// CHECK-NEXT: 0x204C R_ARM_GLOB_DAT function 0x0
+
+// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (16)
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: Absolute
+
+// CODE: Disassembly of section .text:
+// CODE-NEXT: _start:
+// CODE-NEXT: 1000: 08 30 9f e5 ldr r3, [pc, #8]
+// CODE-NEXT: 1004: 08 20 9f e5 ldr r2, [pc, #8]
+// CODE-NEXT: 1008: 03 00 8f e0 add r0, pc, r3
+// CODE-NEXT: 100c: 1e ff 2f e1 bx lr
+// CODE:$d.1:
+// (_GLOBAL_OFFSET_TABLE_ = 0x2048) - (0x1008 + 8) 0x1038
+// CODE-NEXT: 1010: 38 10 00 00
+// (Got(function) - GotBase = 0x4
+// CODE-NEXT: 1014: 04 00 00 00
diff --git a/test/ELF/arm-gotoff.s b/test/ELF/arm-gotoff.s
new file mode 100644
index 000000000000..5169f84e6a01
--- /dev/null
+++ b/test/ELF/arm-gotoff.s
@@ -0,0 +1,74 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabi %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -s -r -t %t | FileCheck %s
+// RUN: llvm-objdump -triple=armv7a-linux-gnueabi -d %t | FileCheck --check-prefix=DISASM %s
+// REQUIRES: arm
+
+// Test the R_ARM_GOTOFF32 relocation
+
+// CHECK: Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x12000
+// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+
+// CHECK: Name: .bss
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x12000
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 20
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment: 1
+
+// CHECK-NEXT: EntrySize: 0
+
+// CHECK: Symbol {
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x12000
+// CHECK-NEXT: Size: 10
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: obj
+// CHECK-NEXT: Value: 0x1200A
+// CHECK-NEXT: Size: 10
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT :_start:
+// DISASM-NEXT 11000: 1e ff 2f e1 bx lr
+// Offset 0 from .got = bar
+// DISASM 11004: 00 00 00 00
+// Offset 10 from .got = obj
+// DISASM-NEXT 11008: 0a 00 00 00
+// Offset 15 from .got = obj +5
+// DISASM-NEXT 1100c: 0f 00 00 00
+ .syntax unified
+ .globl _start
+_start:
+ bx lr
+ .word bar(GOTOFF)
+ .word obj(GOTOFF)
+ .word obj(GOTOFF)+5
+ .type bar, %object
+ .comm bar, 10
+ .type obj, %object
+ .comm obj, 10
diff --git a/test/ELF/arm-mov-relocs.s b/test/ELF/arm-mov-relocs.s
new file mode 100644
index 000000000000..31ccba4cceaf
--- /dev/null
+++ b/test/ELF/arm-mov-relocs.s
@@ -0,0 +1,94 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-unknown-linux-gnueabi %s -o %t
+// RUN: ld.lld %t -o %t2
+// RUN: llvm-objdump -d %t2 -triple=armv7a-unknown-linux-gnueabi | FileCheck %s
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-unknown-linux-gnueabi %s -o %t3
+// RUN: ld.lld %t3 -o %t4
+// RUN: llvm-objdump -d %t4 -triple=thumbv7a-unknown-linux-gnueabi | FileCheck %s
+// REQUIRES: arm
+
+// Test the R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS relocations as well as
+// the R_ARM_THM_MOVW_ABS_NC and R_ARM_THM_MOVT_ABS relocations.
+ .syntax unified
+ .globl _start
+_start:
+ .section .R_ARM_MOVW_ABS_NC, "ax",%progbits
+ movw r0, :lower16:label
+ movw r1, :lower16:label1
+ movw r2, :lower16:label2 + 4
+ movw r3, :lower16:label3
+ movw r4, :lower16:label3 + 4
+// CHECK: Disassembly of section .R_ARM_MOVW_ABS_NC
+// CHECK: movw r0, #0
+// CHECK: movw r1, #4
+// CHECK: movw r2, #12
+// CHECK: movw r3, #65532
+// CHECK: movw r4, #0
+ .section .R_ARM_MOVT_ABS, "ax",%progbits
+ movt r0, :upper16:label
+ movt r1, :upper16:label1
+// FIXME: We shouldn't need to multiply by 65536.
+// arguably llvm-mc incorrectly assembles addends for
+// SHT_REL relocated movt instructions. When there is a relocation
+// the interpretation of the addend for SHT_REL is not shifted
+ movt r2, :upper16:label2 + (4 * 65536)
+ movt r3, :upper16:label3
+// FIXME: We shouldn't need to multiply by 65536 see comment above.
+ movt r4, :upper16:label3 + (4 * 65536)
+// CHECK: Disassembly of section .R_ARM_MOVT_ABS
+// CHECK: movt r0, #2
+// CHECK: movt r1, #2
+// CHECK: movt r2, #2
+// CHECK: movt r3, #2
+// CHECK: movt r4, #3
+
+.section .R_ARM_MOVW_PREL_NC, "ax",%progbits
+ movw r0, :lower16:label - .
+ movw r1, :lower16:label1 - .
+ movw r2, :lower16:label2 + 4 - .
+ movw r3, :lower16:label3 - .
+ movw r4, :lower16:label3 + 0x103c - .
+// 0x20000 - 0x11028 = :lower16:0xefd8 (61400)
+// CHECK: 11028: {{.*}} movw r0, #61400
+// 0x20004 = 0x1102c = :lower16:0xefd8 (61400)
+// CHECK: 1102c: {{.*}} movw r1, #61400
+// 0x20008 - 0x11030 + 4 = :lower16:0xefdc (61404)
+// CHECK: 11030: {{.*}} movw r2, #61404
+// 0x2fffc - 0x11034 = :lower16:0x1efc8 (61384)
+// CHECK: 11034: {{.*}} movw r3, #61384
+// 0x2fffc - 0x11038 +0x103c :lower16:0x20000 (0)
+// CHECK: 11038: {{.*}} movw r4, #0
+
+.section .R_ARM_MOVT_PREL, "ax",%progbits
+ movt r0, :upper16:label - .
+ movt r1, :upper16:label1 - .
+ movt r2, :upper16:label2 + 0x4 - .
+ movt r3, :upper16:label3 - .
+ movt r4, :upper16:label3 + 0x1050 - .
+// 0x20000 - 0x1103c = :upper16:0xefc4 = 0
+// CHECK: 1103c: {{.*}} movt r0, #0
+// 0x20004 - 0x11040 = :upper16:0xefc0 = 0
+// CHECK: 11040: {{.*}} movt r1, #0
+// 0x20008 - 0x11044 + 4 = :upper16:0xefc8 = 0
+// CHECK: 11044: {{.*}} movt r2, #0
+// 0x2fffc - 0x11048 = :upper16:0x1efb4 = 1
+// CHECK: 11048: {{.*}} movt r3, #1
+// 0x2fffc - 0x1104c + 0x1050 = :upper16:0x20000 = 2
+// CHECK: 1104c: {{.*}} movt r4, #2
+ .section .destination, "aw",%progbits
+ .balign 65536
+// 0x20000
+label:
+ .word 0
+// 0x20004
+label1:
+ .word 1
+// 0x20008
+label2:
+ .word 2
+// Test label3 is immediately below 2^16 alignment boundary
+ .space 65536 - 16
+// 0x2fffc
+label3:
+ .word 3
+// label3 + 4 is on a 2^16 alignment boundary
+ .word 4
diff --git a/test/ELF/arm-plt-reloc.s b/test/ELF/arm-plt-reloc.s
new file mode 100644
index 000000000000..0616aa7966a9
--- /dev/null
+++ b/test/ELF/arm-plt-reloc.s
@@ -0,0 +1,90 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/arm-plt-reloc.s -o %t1
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2
+// RUN: ld.lld %t1 %t2 -o %t
+// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t | FileCheck %s
+// RUN: ld.lld -shared %t1 %t2 -o %t3
+// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSO %s
+// RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s
+// REQUIRES: arm
+//
+// Test PLT entry generation
+ .syntax unified
+ .text
+ .align 2
+ .globl _start
+ .type _start,%function
+_start:
+ b func1
+ bl func2
+ beq func3
+
+// Executable, expect no PLT
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: func1:
+// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr
+// CHECK: func2:
+// CHECK-NEXT: 11004: 1e ff 2f e1 bx lr
+// CHECK: func3:
+// CHECK-NEXT: 11008: 1e ff 2f e1 bx lr
+// CHECK: _start:
+// CHECK-NEXT: 1100c: fb ff ff ea b #-20 <func1>
+// CHECK-NEXT: 11010: fb ff ff eb bl #-20 <func2>
+// CHECK-NEXT: 11014: fb ff ff 0a beq #-20 <func3>
+
+// Expect PLT entries as symbols can be preempted
+// DSO: Disassembly of section .text:
+// DSO-NEXT: func1:
+// DSO-NEXT: 1000: 1e ff 2f e1 bx lr
+// DSO: func2:
+// DSO-NEXT: 1004: 1e ff 2f e1 bx lr
+// DSO: func3:
+// DSO-NEXT: 1008: 1e ff 2f e1 bx lr
+// DSO: _start:
+// S(0x1034) - P(0x100c) + A(-8) = 0x20 = 32
+// DSO-NEXT: 100c: 08 00 00 ea b #32
+// S(0x1044) - P(0x1010) + A(-8) = 0x2c = 44
+// DSO-NEXT: 1010: 0b 00 00 eb bl #44
+// S(0x1054) - P(0x1014) + A(-8) = 0x38 = 56
+// DSO-NEXT: 1014: 0e 00 00 0a beq #56
+// DSO: Disassembly of section .plt:
+// DSO-NEXT:.plt:
+// DSO-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]!
+// DSO-NEXT: 1024: 04 e0 9f e5 ldr lr, [pc, #4]
+// DSO-NEXT: 1028: 0e e0 8f e0 add lr, pc, lr
+// DSO-NEXT: 102c: 08 f0 be e5 ldr pc, [lr, #8]!
+// 0x1028 + 8 + 1fd0 = 0x3000
+// DSO-NEXT: 1030: d0 1f 00 00
+// DSO-NEXT: 1034: 04 c0 9f e5 ldr r12, [pc, #4]
+// DSO-NEXT: 1038: 0f c0 8c e0 add r12, r12, pc
+// DSO-NEXT: 103c: 00 f0 9c e5 ldr pc, [r12]
+// 0x1038 + 8 + 1fcc = 0x300c
+// DSO-NEXT: 1040: cc 1f 00 00
+// DSO-NEXT: 1044: 04 c0 9f e5 ldr r12, [pc, #4]
+// DSO-NEXT: 1048: 0f c0 8c e0 add r12, r12, pc
+// DSO-NEXT: 104c: 00 f0 9c e5 ldr pc, [r12]
+// 0x1048 + 8 + 1fc0 = 0x3010
+// DSO-NEXT: 1050: c0 1f 00 00
+// DSO-NEXT: 1054: 04 c0 9f e5 ldr r12, [pc, #4]
+// DSO-NEXT: 1058: 0f c0 8c e0 add r12, r12, pc
+// DSO-NEXT: 105c: 00 f0 9c e5 ldr pc, [r12]
+// 0x1058 + 8 + 1fb4 = 0x3014
+// DSO-NEXT: 1060: b4 1f 00 00
+
+// DSOREL: Name: .got.plt
+// DSOREL-NEXT: Type: SHT_PROGBITS
+// DSOREL-NEXT: Flags [
+// DSOREL-NEXT: SHF_ALLOC
+// DSOREL-NEXT: SHF_WRITE
+// DSOREL-NEXT: ]
+// DSOREL-NEXT: Address: 0x3000
+// DSOREL-NEXT: Offset:
+// DSOREL-NEXT: Size: 24
+// DSOREL-NEXT: Link:
+// DSOREL-NEXT: Info:
+// DSOREL-NEXT: AddressAlignment: 4
+// DSOREL-NEXT: EntrySize:
+// DSOREL: Relocations [
+// DSOREL-NEXT: Section (4) .rel.plt {
+// DSOREL-NEXT: 0x300C R_ARM_JUMP_SLOT func1 0x0
+// DSOREL-NEXT: 0x3010 R_ARM_JUMP_SLOT func2 0x0
+// DSOREL-NEXT: 0x3014 R_ARM_JUMP_SLOT func3 0x0
diff --git a/test/ELF/arm-thumb-blx.s b/test/ELF/arm-thumb-blx.s
new file mode 100644
index 000000000000..b581d1dd3acd
--- /dev/null
+++ b/test/ELF/arm-thumb-blx.s
@@ -0,0 +1,85 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/arm-thumb-blx-targets.s -o %ttarget
+// RUN: echo "SECTIONS { \
+// RUN: .R_ARM_CALL24_callee1 : { *(.R_ARM_CALL24_callee_low) } \
+// RUN: .R_ARM_CALL24_callee2 : { *(.R_ARM_CALL24_callee_thumb_low) } \
+// RUN: .caller : { *(.text) } \
+// RUN: .R_ARM_CALL24_callee3 : { *(.R_ARM_CALL24_callee_high) } \
+// RUN: .R_ARM_CALL24_callee4 : { *(.R_ARM_CALL24_callee_thumb_high) } } " > %t.script
+// RUN: ld.lld --script %t.script %t %ttarget -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-THUMB %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-ARM %s
+// REQUIRES: arm
+// Test BLX instruction is chosen for Thumb BL/BLX instruction and ARM callee
+// 2 byte nops are used to test the pc-rounding behaviour. As a BLX from a
+// 2 byte aligned destination is defined as Align(PC,4) + immediate:00
+// FIXME: llvm-mc has problems assembling BLX unless the destination is
+// external. The targets of the BL and BLX instructions are in arm-thumb-blx-target.s
+ .syntax unified
+ .section .text, "ax",%progbits
+ .thumb
+ .globl _start
+ .balign 0x10000
+ .type _start,%function
+_start:
+ blx callee_low
+ nop
+ bl callee_low
+ nop
+ blx callee_high
+ nop
+ bl callee_high
+ nop
+ blx blx_far
+ nop
+ bl blx_far
+ nop
+// Expect BLX to thumb target to be written out as a BL
+ blx callee_thumb_low
+ nop
+ blx callee_thumb_high
+ bx lr
+
+// CHECK-ARM: Disassembly of section .R_ARM_CALL24_callee1:
+// CHECK-NEXT-ARM: callee_low:
+// CHECK-NEXT-ARM: b4: 1e ff 2f e1 bx lr
+
+// CHECK-THUMB: Disassembly of section .R_ARM_CALL24_callee2:
+// CHECK-NEXT-THUMB: callee_thumb_low:
+// CHECK-NEXT-THUMB: 100: 70 47 bx lr
+
+// CHECK-THUMB: Disassembly of section .caller:
+// CHECK-THUMB: _start:
+// Align(0x10000,4) - 0xff50 (65360) + 4 = 0xb4 = callee_low
+// CHECK-NEXT-THUMB: 10000: f0 f7 58 e8 blx #-65360
+// CHECK-NEXT-THUMB: 10004: 00 bf nop
+// Align(0x10006,4) - 0xff54 (65364) + 4 = 0xb4 = callee_low
+// CHECK-NEXT-THUMB: 10006: f0 f7 56 e8 blx #-65364
+// CHECK-NEXT-THUMB: 1000a: 00 bf nop
+// Align(0x1000c,4) + 0xf0 (240) + 4 = 0x10100 = callee_high
+// CHECK-NEXT-THUMB: 1000c: 00 f0 78 e8 blx #240
+// CHECK-NEXT-THUMB: 10010: 00 bf nop
+// Align(0x10012,4) + 0xec (236) + 4 = 0x10100 = callee_high
+// CHECK-NEXT-THUMB: 10012: 00 f0 76 e8 blx #236
+// CHECK-NEXT-THUMB: 10016: 00 bf nop
+// Align(0x10018,4) + 0xfffffc (16777212) = 0x1010018 = blx_far
+// CHECK-NEXT-THUMB: 10018: ff f3 fe c7 blx #16777212
+// CHECK-NEXT-THUMB: 1001c: 00 bf nop
+// Align(0x1001e,4) + 0xfffff8 (16777208) = 0x1010018 = blx_far
+// CHECK-NEXT-THUMB: 1001e: ff f3 fc c7 blx #16777208
+// CHECK-NEXT-THUMB: 10022: 00 bf nop
+// 10024 - 0xff28 (65320) + 4 = 0x100 = callee_thumb_low
+// CHECK-NEXT-THUMB: 10024: f0 f7 6c f8 bl #-65320
+// CHECK-NEXT-THUMB: 10028: 00 bf nop
+// 1002a + 0x1d2 (466) + 4 = 0x10200 = callee_thumb_high
+// CHECK-NEXT-THUMB: 1002a: 00 f0 e9 f8 bl #466
+// CHECK-NEXT-THUMB: 1002e: 70 47 bx lr
+
+
+// CHECK-ARM: Disassembly of section .R_ARM_CALL24_callee3:
+// CHECK-NEXT-ARM: callee_high:
+// CHECK-NEXT-ARM: 10100: 1e ff 2f e1 bx lr
+
+// CHECK: Disassembly of section .R_ARM_CALL24_callee4:
+// CHECK-NEXT-THUMB:callee_thumb_high:
+// CHECK-NEXT-THUMB: 10200: 70 47 bx lr
diff --git a/test/ELF/arm-thumb-branch-error.s b/test/ELF/arm-thumb-branch-error.s
new file mode 100644
index 000000000000..de6c1bc16c96
--- /dev/null
+++ b/test/ELF/arm-thumb-branch-error.s
@@ -0,0 +1,19 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar
+// RUN: not ld.lld %t %tfar -o %t2 2>&1 | FileCheck %s
+// REQUIRES: arm
+ .syntax unified
+ .section .text, "ax",%progbits
+ .globl _start
+ .balign 0x10000
+ .type _start,%function
+_start:
+ // address of too_far symbols are just out of range of ARM branch with
+ // 26-bit immediate field and an addend of -8
+ bl too_far1
+ b too_far2
+ beq.w too_far3
+
+// CHECK: R_ARM_THM_CALL out of range
+// CHECK-NEXT: R_ARM_THM_JUMP24 out of range
+// CHECK-NEXT: R_ARM_THM_JUMP19 out of range
diff --git a/test/ELF/arm-thumb-branch.s b/test/ELF/arm-thumb-branch.s
new file mode 100644
index 000000000000..94be9ecb6e53
--- /dev/null
+++ b/test/ELF/arm-thumb-branch.s
@@ -0,0 +1,59 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar
+// RUN: echo "SECTIONS { \
+// RUN: .callee1 : { *(.callee_low) } \
+// RUN: .caller : { *(.text) } \
+// RUN: .callee2 : { *(.callee_high) } } " > %t.script
+// RUN: ld.lld --script %t.script %t %tfar -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s
+// REQUIRES: arm
+
+ .syntax unified
+ .thumb
+ .section .callee_low, "ax",%progbits
+ .align 2
+ .type callee_low,%function
+callee_low:
+ bx lr
+
+ .section .text, "ax",%progbits
+ .globl _start
+ .balign 0x10000
+ .type _start,%function
+_start:
+ bl callee_low
+ b callee_low
+ beq callee_low
+ bl callee_high
+ b callee_high
+ bne callee_high
+ bl far_uncond
+ b far_uncond
+ bgt far_cond
+ bx lr
+
+ .section .callee_high, "ax",%progbits
+ .align 2
+ .type callee_high,%function
+callee_high:
+ bx lr
+
+// CHECK: Disassembly of section .callee1:
+// CHECK-NEXT: callee_low:
+// CHECK-NEXT: b4: 70 47 bx lr
+// CHECK-NEXT: Disassembly of section .caller:
+// CHECK-NEXT: _start:
+// CHECK-NEXT: 10000: f0 f7 58 f8 bl #-65360
+// CHECK-NEXT: 10004: f0 f7 56 b8 b.w #-65364
+// CHECK-NEXT: 10008: 30 f4 54 a8 beq.w #-65368
+// CHECK-NEXT: 1000c: 00 f0 0c f8 bl #24
+// CHECK-NEXT: 10010: 00 f0 0a b8 b.w #20
+// CHECK-NEXT: 10014: 40 f0 08 80 bne.w #16
+// CHECK-NEXT: 10018: ff f3 ff d7 bl #16777214
+// CHECK-NEXT: 1001c: ff f3 fd 97 b.w #16777210
+// CHECK-NEXT: 10020: 3f f3 ff af bgt.w #1048574
+// CHECK-NEXT: 10024: 70 47 bx lr
+// CHECK-NEXT: 10026: 00 00 movs r0, r0
+// CHECK-NEXT: Disassembly of section .callee2:
+// CHECK-NEXT: callee_high:
+// CHECK-NEXT: 10028: 70 47 bx lr
diff --git a/test/ELF/arm-thumb-interwork-thunk.s b/test/ELF/arm-thumb-interwork-thunk.s
new file mode 100644
index 000000000000..6173df3c066b
--- /dev/null
+++ b/test/ELF/arm-thumb-interwork-thunk.s
@@ -0,0 +1,375 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN: .R_ARM_JUMP24_callee_1 : { *(.R_ARM_JUMP24_callee_low) } \
+// RUN: .R_ARM_THM_JUMP_callee_1 : { *(.R_ARM_THM_JUMP_callee_low)} \
+// RUN: .text : { *(.text) } \
+// RUN: .arm_caller : { *(.arm_caller) } \
+// RUN: .thumb_caller : { *(.thumb_caller) } \
+// RUN: .R_ARM_JUMP24_callee_2 : { *(.R_ARM_JUMP24_callee_high) } \
+// RUN: .R_ARM_THM_JUMP_callee_2 : { *(.R_ARM_THM_JUMP_callee_high) } } " > %t.script
+// RUN: ld.lld --script %t.script %t -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-ABS-THUMB %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-ARM -check-prefix=CHECK-ABS-ARM %s
+// RUN: ld.lld --script %t.script %t -pie -o %t3 2>&1
+// RUN: ld.lld --script %t.script %t --shared -o %t4 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-PI-THUMB %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-ARM %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t4 | FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-PI-PLT-THUMB %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t4 | FileCheck -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-PLT-ARM %s
+// RUN: llvm-readobj -s -r %t4 | FileCheck -check-prefix=CHECK-DSO-REL %s
+// REQUIRES: arm
+
+// Test ARM Thumb Interworking
+// The file is linked and checked 3 times to check the following contexts
+// - Absolute executables, absolute Thunks are used.
+// - Position independent executables, position independent Thunks are used.
+// - Shared object, position independent Thunks to PLT entries are used.
+
+ .syntax unified
+
+// Target Sections for thunks at a lower address than the callers.
+.section .R_ARM_JUMP24_callee_low, "ax", %progbits
+ .thumb
+ .balign 0x1000
+ .globl thumb_callee1
+ .type thumb_callee1, %function
+thumb_callee1:
+ bx lr
+
+// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_1:
+// CHECK-THUMB: thumb_callee1:
+// CHECK-THUMB: 1000: 70 47 bx
+ .section .R_ARM_THM_JUMP_callee_low, "ax", %progbits
+ .arm
+ .balign 0x100
+ .globl arm_callee1
+ .type arm_callee1, %function
+arm_callee1:
+ bx lr
+// Disassembly of section .R_ARM_THM_JUMP_callee_1:
+// CHECK-ARM: arm_callee1:
+// CHECK-ARM-NEXT: 1100: 1e ff 2f e1 bx lr
+
+ // Calling sections
+ // At present ARM and Thumb interworking thunks are always added to the calling
+ // section.
+ .section .arm_caller, "ax", %progbits
+ .arm
+ .balign 0x100
+ .globl arm_caller
+ .type arm_caller, %function
+arm_caller:
+ // If target supports BLX and target is in range we don't need an
+ // interworking thunk for a BL or BLX instruction.
+ bl thumb_callee1
+ blx thumb_callee1
+ // A B instruction can't be transformed into a BLX and needs an interworking
+ // thunk
+ b thumb_callee1
+ // As long as the thunk is in range it can be reused
+ b thumb_callee1
+ // There can be more than one thunk associated with a section
+ b thumb_callee2
+ b thumb_callee3
+ // In range ARM targets do not require interworking thunks
+ b arm_callee1
+ beq arm_callee2
+ bne arm_callee3
+ bx lr
+// CHECK-ABS-ARM: Disassembly of section .arm_caller:
+// CHECK-ABS-ARM-NEXT: arm_caller:
+// CHECK-ABS-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>
+// CHECK-ABS-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>
+// CHECK-ABS-ARM-NEXT: 1308: 06 00 00 ea b #24 <arm_caller+0x28>
+// CHECK-ABS-ARM-NEXT: 130c: 05 00 00 ea b #20 <arm_caller+0x28>
+// CHECK-ABS-ARM-NEXT: 1310: 07 00 00 ea b #28 <arm_caller+0x34>
+// CHECK-ABS-ARM-NEXT: 1314: 09 00 00 ea b #36 <arm_caller+0x40>
+// CHECK-ABS-ARM-NEXT: 1318: 78 ff ff ea b #-544 <arm_callee1>
+// CHECK-ABS-ARM-NEXT: 131c: b7 00 00 0a beq #732 <arm_callee2>
+// CHECK-ABS-ARM-NEXT: 1320: b7 00 00 1a bne #732 <arm_callee3>
+// CHECK-ABS-ARM-NEXT: 1324: 1e ff 2f e1 bx lr
+// 0x1001 = thumb_callee1
+// CHECK-ABS-ARM-NEXT: 1328: 01 c0 01 e3 movw r12, #4097
+// CHECK-ABS-ARM-NEXT: 132c: 00 c0 40 e3 movt r12, #0
+// CHECK-ABS-ARM-NEXT: 1330: 1c ff 2f e1 bx r12
+// 0x1501 = thumb_callee2
+// CHECK-ABS-ARM-NEXT: 1334: 01 c5 01 e3 movw r12, #5377
+// CHECK-ABS-ARM-NEXT: 1338: 00 c0 40 e3 movt r12, #0
+// CHECK-ABS-ARM-NEXT: 133c: 1c ff 2f e1 bx r12
+// 0x1503 = thumb_callee3
+// CHECK-ABS-ARM-NEXT: 1340: 03 c5 01 e3 movw r12, #5379
+// CHECK-ABS-ARM-NEXT: 1344: 00 c0 40 e3 movt r12, #0
+// CHECK-ABS-ARM-NEXT: 1348: 1c ff 2f e1 bx r12
+
+// CHECK-PI-ARM: Disassembly of section .arm_caller:
+// CHECK-PI-ARM-NEXT: arm_caller:
+// CHECK-PI-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>
+// CHECK-PI-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>
+// 0x1308 + 8 + 0x18 = 0x1328
+// CHECK-PI-ARM-NEXT: 1308: 06 00 00 ea b #24 <arm_caller+0x28>
+// 0x130c + 8 + 0x14 = 0x1328
+// CHECK-PI-ARM-NEXT: 130c: 05 00 00 ea b #20 <arm_caller+0x28>
+// 0x1310 + 8 + 0x20 = 0x1338
+// CHECK-PI-ARM-NEXT: 1310: 08 00 00 ea b #32 <arm_caller+0x38>
+// 0x1314 + 8 + 0x2c = 0x1348
+// CHECK-PI-ARM-NEXT: 1314: 0b 00 00 ea b #44 <arm_caller+0x48>
+// CHECK-PI-ARM-NEXT: 1318: 78 ff ff ea b #-544 <arm_callee1>
+// CHECK-PI-ARM-NEXT: 131c: b7 00 00 0a beq #732 <arm_callee2>
+// CHECK-PI-ARM-NEXT: 1320: b7 00 00 1a bne #732 <arm_callee3>
+// CHECK-PI-ARM-NEXT: 1324: 1e ff 2f e1 bx lr
+// 0x1330 + 8 - 0x337 = 0x1001 = thumb_callee1
+// CHECK-PI-ARM-NEXT: 1328: c9 cc 0f e3 movw r12, #64713
+// CHECK-PI-ARM-NEXT: 132c: ff cf 4f e3 movt r12, #65535
+// CHECK-PI-ARM-NEXT: 1330: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-NEXT: 1334: 1c ff 2f e1 bx r12
+// 0x1340 + 8 + 0x1b9 = 0x1501
+// CHECK-PI-ARM-NEXT: 1338: b9 c1 00 e3 movw r12, #441
+// CHECK-PI-ARM-NEXT: 133c: 00 c0 40 e3 movt r12, #0
+// CHECK-PI-ARM-NEXT: 1340: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-NEXT: 1344: 1c ff 2f e1 bx r12
+// 1350 + 8 + 0x1ab = 0x1503
+// CHECK-PI-ARM-NEXT: 1348: ab c1 00 e3 movw r12, #427
+// CHECK-PI-ARM-NEXT: 134c: 00 c0 40 e3 movt r12, #0
+// CHECK-PI-ARM-NEXT: 1350: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-NEXT: 1354: 1c ff 2f e1 bx r12
+
+// All PLT entries are ARM, no need for interworking thunks
+// CHECK-PI-ARM-PLT: Disassembly of section .arm_caller:
+// CHECK-PI-ARM-PLT-NEXT: arm_caller:
+// 0x17e4 PLT(thumb_callee1)
+// CHECK-PI-ARM-PLT-NEXT: 1300: 37 01 00 eb bl #1244
+// 0x17e4 PLT(thumb_callee1)
+// CHECK-PI-ARM-PLT-NEXT: 1304: 36 01 00 eb bl #1240
+// 0x17e4 PLT(thumb_callee1)
+// CHECK-PI-ARM-PLT-NEXT: 1308: 35 01 00 ea b #1236
+// 0x17e4 PLT(thumb_callee1)
+// CHECK-PI-ARM-PLT-NEXT: 130c: 34 01 00 ea b #1232
+// 0x17f4 PLT(thumb_callee2)
+// CHECK-PI-ARM-PLT-NEXT: 1310: 37 01 00 ea b #1244
+// 0x1804 PLT(thumb_callee3)
+// CHECK-PI-ARM-PLT-NEXT: 1314: 3a 01 00 ea b #1256
+// 0x1814 PLT(arm_callee1)
+// CHECK-PI-ARM-PLT-NEXT: 1318: 3d 01 00 ea b #1268
+// 0x1824 PLT(arm_callee2)
+// CHECK-PI-ARM-PLT-NEXT: 131c: 40 01 00 0a beq #1280
+// 0x1834 PLT(arm_callee3)
+// CHECK-PI-ARM-PLT-NEXT: 1320: 43 01 00 1a bne #1292
+// CHECK-PI-ARM-PLT-NEXT: 1324: 1e ff 2f e1 bx lr
+
+ .section .thumb_caller, "ax", %progbits
+ .balign 0x100
+ .thumb
+ .globl thumb_caller
+ .type thumb_caller, %function
+thumb_caller:
+ // If target supports BLX and target is in range we don't need an
+ // interworking thunk for a BL or BLX instruction.
+ bl arm_callee1
+ blx arm_callee1
+ // A B instruction can't be transformed into a BLX and needs an interworking
+ // thunk
+ b.w arm_callee1
+ // As long as the thunk is in range it can be reused
+ b.w arm_callee2
+ // There can be more than one thunk associated with a section
+ b.w arm_callee3
+ // Conditional branches also require interworking thunks, they can use the
+ // same interworking thunks.
+ beq.w arm_callee1
+ beq.w arm_callee2
+ bne.w arm_callee3
+// CHECK-ABS-THUMB: Disassembly of section .thumb_caller:
+// CHECK-ABS-THUMB-NEXT: thumb_caller:
+// 0x1400 + 4 - 0x304 = 0x1100 = arm_callee1
+// CHECK-ABS-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
+// 0x1404 + 4 - 0x308 = 0x1100 = arm_callee1
+// CHECK-ABS-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
+// 0x1408 + 4 + 0x14 = 0x520
+// CHECK-ABS-THUMB-NEXT: 1408: 00 f0 0a b8 b.w #20
+// 0x140c + 4 + 0x1a = 0x52a
+// CHECK-ABS-THUMB-NEXT: 140c: 00 f0 0d b8 b.w #26
+// 0x1410 + 4 + 0x20 = 0x534
+// CHECK-ABS-THUMB-NEXT: 1410: 00 f0 10 b8 b.w #32
+// 0x1414 + 4 + 8 = 0x520
+// CHECK-ABS-THUMB-NEXT: 1414: 00 f0 04 80 beq.w #8
+// 0x1418 + 4 + 0xe = 0x52a
+// CHECK-ABS-THUMB-NEXT: 1418: 00 f0 07 80 beq.w #14
+// 0x141c + 4 + 0x14 = 0x534
+// CHECK-ABS-THUMB-NEXT: 141c: 40 f0 0a 80 bne.w #20
+// 0x1100 = arm_callee1
+// CHECK-ABS-THUMB-NEXT: 1420: 41 f2 00 1c movw r12, #4352
+// CHECK-ABS-THUMB-NEXT: 1424: c0 f2 00 0c movt r12, #0
+// CHECK-ABS-THUMB-NEXT: 1428: 60 47 bx r12
+// 0x1600 = arm_callee2
+// CHECK-ABS-THUMB-NEXT: 142a: 41 f2 00 6c movw r12, #5632
+// CHECK-ABS-THUMB-NEXT: 142e: c0 f2 00 0c movt r12, #0
+// CHECK-ABS-THUMB-NEXT: 1432: 60 47 bx r12
+// 0x1604 = arm_callee3
+// CHECK-ABS-THUMB-NEXT: 1434: 41 f2 04 6c movw r12, #5636
+// CHECK-ABS-THUMB-NEXT: 1438: c0 f2 00 0c movt r12, #0
+// CHECK-ABS-THUMB-NEXT: 143c: 60 47 bx r12
+
+// CHECK-PI-THUMB: Disassembly of section .thumb_caller:
+// CHECK-PI-THUMB-NEXT: thumb_caller:
+// CHECK-PI-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
+// CHECK-PI-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
+// CHECK-PI-THUMB-NEXT: 1408: 00 f0 0a b8 b.w #20
+// CHECK-PI-THUMB-NEXT: 140c: 00 f0 0e b8 b.w #28
+// CHECK-PI-THUMB-NEXT: 1410: 00 f0 12 b8 b.w #36
+// CHECK-PI-THUMB-NEXT: 1414: 00 f0 04 80 beq.w #8
+// CHECK-PI-THUMB-NEXT: 1418: 00 f0 08 80 beq.w #16
+// CHECK-PI-THUMB-NEXT: 141c: 40 f0 0c 80 bne.w #24
+// 0x1428 + 4 - 0x32c = 0x1100 = arm_callee1
+// CHECK-PI-THUMB-NEXT: 1420: 4f f6 d4 4c movw r12, #64724
+// CHECK-PI-THUMB-NEXT: 1424: cf f6 ff 7c movt r12, #65535
+// CHECK-PI-THUMB-NEXT: 1428: fc 44 add r12, pc
+// CHECK-PI-THUMB-NEXT: 142a: 60 47 bx r12
+// 0x1434 + 4 + 0x1c8 = 0x1600 = arm_callee2
+// CHECK-PI-THUMB-NEXT: 142c: 40 f2 c8 1c movw r12, #456
+// CHECK-PI-THUMB-NEXT: 1430: c0 f2 00 0c movt r12, #0
+// CHECK-PI-THUMB-NEXT: 1434: fc 44 add r12, pc
+// CHECK-PI-THUMB-NEXT: 1436: 60 47 bx r12
+// 0x1440 + 4 + 0x1c0 = 0x1604 = arm_callee3
+// CHECK-PI-THUMB-NEXT: 1438: 40 f2 c0 1c movw r12, #448
+// CHECK-PI-THUMB-NEXT: 143c: c0 f2 00 0c movt r12, #0
+// CHECK-PI-THUMB-NEXT: 1440: fc 44 add r12, pc
+// CHECK-PI-THUMB-NEXT: 1442: 60 47 bx r12
+
+// CHECK-PI-THUMB-PLT: Disassembly of section .arm_caller:
+// CHECK-PI-THUMB-PLT-NEXT: thumb_caller:
+// 0x1400 + 4 + 0x410 = 0x1814 = PLT(arm_callee1)
+// CHECK-PI-THUMB-PLT-NEXT: 1400: 00 f0 08 ea blx #1040
+// 0x1404 + 4 + 0x40c = 0x1814 = PLT(arm_callee1)
+// CHECK-PI-THUMB-PLT-NEXT: 1404: 00 f0 06 ea blx #1036
+// 0x1408 + 4 + 0x14 = 0x1420 = IWV(PLT(arm_callee1)
+// CHECK-PI-THUMB-PLT-NEXT: 1408: 00 f0 0a b8 b.w #20
+// 0x140c + 4 + 0x1c = 0x142c = IWV(PLT(arm_callee2)
+// CHECK-PI-THUMB-PLT-NEXT: 140c: 00 f0 0e b8 b.w #28
+// 0x1410 + 4 + 0x24 = 0x1438 = IWV(PLT(arm_callee3)
+// CHECK-PI-THUMB-PLT-NEXT: 1410: 00 f0 12 b8 b.w #36
+// 0x1414 + 4 + 8 = 0x1420 = IWV(PLT(arm_callee1)
+// CHECK-PI-THUMB-PLT-NEXT: 1414: 00 f0 04 80 beq.w #8
+// 0x1418 + 4 + 0x10 = 0x142c = IWV(PLT(arm_callee2)
+// CHECK-PI-THUMB-PLT-NEXT: 1418: 00 f0 08 80 beq.w #16
+// 0x141c + 4 + 0x18 = 0x1438 = IWV(PLT(arm_callee3)
+// CHECK-PI-THUMB-PLT-NEXT: 141c: 40 f0 0c 80 bne.w #24
+// 0x1428 + 4 + 0x3e8 = 0x1814 = PLT(arm_callee1)
+// CHECK-PI-THUMB-PLT-NEXT: 1420: 40 f2 e8 3c movw r12, #1000
+// CHECK-PI-THUMB-PLT-NEXT: 1424: c0 f2 00 0c movt r12, #0
+// CHECK-PI-THUMB-PLT-NEXT: 1428: fc 44 add r12, pc
+// CHECK-PI-THUMB-PLT-NEXT: 142a: 60 47 bx r12
+// 0x1434 + 4 + 0x3ec = 0x1824 = PLT(arm_callee2)
+// CHECK-PI-THUMB-PLT-NEXT: 142c: 40 f2 ec 3c movw r12, #1004
+// CHECK-PI-THUMB-PLT-NEXT: 1430: c0 f2 00 0c movt r12, #0
+// CHECK-PI-THUMB-PLT-NEXT: 1434: fc 44 add r12, pc
+// CHECK-PI-THUMB-PLT-NEXT: 1436: 60 47 bx r12
+// 0x1440 + 4 + 0x3f0 = 0x1834 = PLT(arm_callee3)
+// CHECK-PI-THUMB-PLT-NEXT: 1438: 40 f2 f0 3c movw r12, #1008
+// CHECK-PI-THUMB-PLT-NEXT: 143c: c0 f2 00 0c movt r12, #0
+// CHECK-PI-THUMB-PLT-NEXT: 1440: fc 44 add r12, pc
+// CHECK-PI-THUMB-PLT-NEXT: 1442: 60 47 bx r12
+
+// Target Sections for thunks at a higher address than the callers.
+.section .R_ARM_JUMP24_callee_high, "ax", %progbits
+ .thumb
+ .balign 0x100
+ .globl thumb_callee2
+ .type thumb_callee2, %function
+thumb_callee2:
+ bx lr
+
+ .globl thumb_callee3
+ .type thumb_callee3, %function
+thumb_callee3:
+ bx lr
+// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_2:
+// CHECK-THUMB-NEXT: thumb_callee2:
+// CHECK-THUMB-NEXT: 1500: 70 47 bx lr
+// CHECK-THUMB: thumb_callee3:
+// CHECK-THUMB-NEXT: 1502: 70 47 bx lr
+
+ .section .R_ARM_THM_JUMP_callee_high, "ax", %progbits
+ .arm
+ .balign 0x100
+ .globl arm_callee2
+ .type arm_callee2, %function
+arm_callee2:
+ bx lr
+ .globl arm_callee3
+ .type arm_callee3, %function
+arm_callee3:
+ bx lr
+// CHECK-ARM: Disassembly of section .R_ARM_THM_JUMP_callee_2:
+// CHECK-ARM-NEXT: arm_callee2:
+// CHECK-ARM-NEXT: 1600: 1e ff 2f e1 bx lr
+// CHECK-ARM: arm_callee3:
+// CHECK-ARM-NEXT: 1604: 1e ff 2f e1 bx lr
+
+// _start section just calls the arm and thumb calling sections
+ .text
+ .arm
+ .globl _start
+ .balign 0x100
+ .type _start, %function
+_start:
+ bl arm_caller
+ bl thumb_caller
+ bx lr
+
+
+// CHECK-PI-ARM-PLT: Disassembly of section .plt:
+// CHECK-PI-ARM-PLT-NEXT: .plt:
+// CHECK-PI-ARM-PLT-NEXT: 17b0: 04 e0 2d e5 str lr, [sp, #-4]!
+// CHECK-PI-ARM-PLT-NEXT: 17b4: 04 e0 9f e5 ldr lr, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 17b8: 0e e0 8f e0 add lr, pc, lr
+// CHECK-PI-ARM-PLT-NEXT: 17bc: 08 f0 be e5 ldr pc, [lr, #8]!
+// CHECK-PI-ARM-PLT-NEXT: 17c0: d4 00 00 00
+// 0x17c8 + 8 + 0xd0 = 0x18a0 arm_caller
+// CHECK-PI-ARM-PLT-NEXT: 17c4: 04 c0 9f e5 ldr r12, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 17c8: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-PLT-NEXT: 17cc: 00 f0 9c e5 ldr pc, [r12]
+// CHECK-PI-ARM-PLT-NEXT: 17d0: d0 00 00 00
+// 0x17d8 + 8 + 0xc4 = 0x18a4 thumb_caller
+// CHECK-PI-ARM-PLT-NEXT: 17d4: 04 c0 9f e5 ldr r12, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 17d8: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-PLT-NEXT: 17dc: 00 f0 9c e5 ldr pc, [r12]
+// CHECK-PI-ARM-PLT-NEXT: 17e0: c4 00 00 00
+// 0x17e8 + 8 + 0xb8 = 0x18a8 thumb_callee1
+// CHECK-PI-ARM-PLT-NEXT: 17e4: 04 c0 9f e5 ldr r12, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 17e8: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-PLT-NEXT: 17ec: 00 f0 9c e5 ldr pc, [r12]
+// CHECK-PI-ARM-PLT-NEXT: 17f0: b8 00 00 00
+// 0x17f8 + 8 + 0xac = 0x18ac thumb_callee2
+// CHECK-PI-ARM-PLT-NEXT: 17f4: 04 c0 9f e5 ldr r12, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 17f8: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-PLT-NEXT: 17fc: 00 f0 9c e5 ldr pc, [r12]
+// CHECK-PI-ARM-PLT-NEXT: 1800: ac 00 00 00
+// 0x1808 + 8 + 0xa0 = 0x18b0 thumb_callee3
+// CHECK-PI-ARM-PLT-NEXT: 1804: 04 c0 9f e5 ldr r12, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 1808: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-PLT-NEXT: 180c: 00 f0 9c e5 ldr pc, [r12]
+// CHECK-PI-ARM-PLT-NEXT: 1810: a0 00 00 00
+// 0x1818 + 8 + 0x94 = 0x18b4 arm_callee1
+// CHECK-PI-ARM-PLT-NEXT: 1814: 04 c0 9f e5 ldr r12, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 1818: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-PLT-NEXT: 181c: 00 f0 9c e5 ldr pc, [r12]
+// CHECK-PI-ARM-PLT-NEXT: 1820: 94 00 00 00
+// 0x1828 + 8 + 0x88 = 0x18b8 arm_callee2
+// CHECK-PI-ARM-PLT-NEXT: 1824: 04 c0 9f e5 ldr r12, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 1828: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-PLT-NEXT: 182c: 00 f0 9c e5 ldr pc, [r12]
+// CHECK-PI-ARM-PLT-NEXT: 1830: 88 00 00 00
+// 0x1838 + 8 + 0x7c = 0x18bc arm_callee3
+// CHECK-PI-ARM-PLT-NEXT: 1834: 04 c0 9f e5 ldr r12, [pc, #4]
+// CHECK-PI-ARM-PLT-NEXT: 1838: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-PLT-NEXT: 183c: 00 f0 9c e5 ldr pc, [r12]
+// CHECK-PI-ARM-PLT-NEXT: 1840: 7c 00 00 00
+
+// CHECK-DSO-REL: 0x18A0 R_ARM_JUMP_SLOT arm_caller
+// CHECK-DSO-REL-NEXT: 0x18A4 R_ARM_JUMP_SLOT thumb_caller
+// CHECK-DSO-REL-NEXT: 0x18A8 R_ARM_JUMP_SLOT thumb_callee1
+// CHECK-DSO-REL-NEXT: 0x18AC R_ARM_JUMP_SLOT thumb_callee2
+// CHECK-DSO-REL-NEXT: 0x18B0 R_ARM_JUMP_SLOT thumb_callee3
+// CHECK-DSO-REL-NEXT: 0x18B4 R_ARM_JUMP_SLOT arm_callee1
+// CHECK-DSO-REL-NEXT: 0x18B8 R_ARM_JUMP_SLOT arm_callee2
+// CHECK-DSO-REL-NEXT: 0x18BC R_ARM_JUMP_SLOT arm_callee3
diff --git a/test/ELF/arm-thumb-narrow-branch-check.s b/test/ELF/arm-thumb-narrow-branch-check.s
new file mode 100644
index 000000000000..b601b6d5dc26
--- /dev/null
+++ b/test/ELF/arm-thumb-narrow-branch-check.s
@@ -0,0 +1,72 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN: .R_ARM_PC11_1 : { *(.R_ARM_PC11_1) } \
+// RUN: .caller : { *(.caller) } \
+// RUN: .R_ARM_PC11_2 : { *(.R_ARM_PC11_2) } \
+// RUN: .text : { *(.text) } } " > %t.script
+// RUN: ld.lld --script %t.script %t %S/Inputs/arm-thumb-narrow-branch.o -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s
+// REQUIRES: arm
+
+// Test the R_ARM_PC11 relocation which is used with the narrow encoding of B.N
+// the source of these relocations is a binary file arm-thumb-narrow-branch.o
+// which has been assembled with the GNU assembler as llvm-mc doesn't emit it
+// as the range of +-2048 bytes is too small to be practically useful for out
+// of section branches.
+ .syntax unified
+
+.global callee_low_far
+.type callee_low_far,%function
+callee_low_far = 0x809
+
+ .section .R_ARM_PC11_1,"ax",%progbits
+ .thumb
+ .balign 0x1000
+ .type callee_low,%function
+ .globl callee_low
+callee_low:
+ bx lr
+
+ .text
+ .align 2
+ .thumb
+ .globl _start
+ .type _start, %function
+_start:
+ bl callers
+ bx lr
+
+ .section .R_ARM_PC11_2,"ax",%progbits
+ .thumb
+ .align 2
+ .type callee_high,%function
+ .globl callee_high
+callee_high:
+ bx lr
+
+.global callee_high_far
+.type callee_high_far,%function
+callee_high_far = 0x180d
+
+// CHECK: Disassembly of section .R_ARM_PC11_1:
+// CHECK-NEXT: callee_low:
+// CHECK-NEXT: 1000: 70 47 bx lr
+// CHECK-NEXT: Disassembly of section .caller:
+// CHECK-NEXT: callers:
+// 1004 - 0x800 (2048) + 4 = 0x808 = callee_low_far
+// CHECK-NEXT: 1004: 00 e4 b #-2048
+// 1006 - 0xa (10) + 4 = 0x1000 = callee_low
+// CHECK-NEXT: 1006: fb e7 b #-10
+// 1008 + 4 + 4 = 0x1010 = callee_high
+// CHECK-NEXT: 1008: 02 e0 b #4
+// 100a + 0x7fe (2046) + 4 = 0x180c = callee_high_far
+// CHECK-NEXT: 100a: ff e3 b #2046
+// CHECK-NEXT: 100c: 70 47 bx lr
+// CHECK-NEXT: 100e: 00 bf nop
+// CHECK-NEXT: Disassembly of section .R_ARM_PC11_2:
+// CHECK-NEXT: callee_high:
+// CHECK-NEXT: 1010: 70 47 bx lr
+// CHECK-NEXT: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// CHECK-NEXT: 1014: ff f7 f6 ff bl #-20
+// CHECK-NEXT: 1018: 70 47 bx lr
diff --git a/test/ELF/arm-thumb-plt-reloc.s b/test/ELF/arm-thumb-plt-reloc.s
new file mode 100644
index 000000000000..6294e909f078
--- /dev/null
+++ b/test/ELF/arm-thumb-plt-reloc.s
@@ -0,0 +1,101 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %p/Inputs/arm-plt-reloc.s -o %t1
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t2
+// RUN: ld.lld %t1 %t2 -o %t
+// RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t | FileCheck %s
+// RUN: ld.lld -shared %t1 %t2 -o %t3
+// RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOTHUMB %s
+// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOARM %s
+// RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s
+// REQUIRES: arm
+//
+// Test PLT entry generation
+ .syntax unified
+ .text
+ .align 2
+ .globl _start
+ .type _start,%function
+_start:
+// FIXME, interworking is only supported for BL via BLX at the moment, when
+// interworking thunks are available for b.w and b<cond>.w this can be altered
+// to test the different forms of interworking.
+ bl func1
+ bl func2
+ bl func3
+
+// Executable, expect no PLT
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: func1:
+// CHECK-NEXT: 11000: 70 47 bx lr
+// CHECK: func2:
+// CHECK-NEXT: 11002: 70 47 bx lr
+// CHECK: func3:
+// CHECK-NEXT: 11004: 70 47 bx lr
+// CHECK-NEXT: 11006: 00 00 movs r0, r0
+// CHECK: _start:
+// 11008 + 4 -12 = 0x11000 = func1
+// CHECK-NEXT: 11008: ff f7 fa ff bl #-12
+// 1100c + 4 -14 = 0x11002 = func2
+// CHECK-NEXT: 1100c: ff f7 f9 ff bl #-14
+// 11010 + 4 -16 = 0x11004 = func3
+// CHECK-NEXT: 11010: ff f7 f8 ff bl #-16
+
+// Expect PLT entries as symbols can be preempted
+// .text is Thumb and .plt is ARM, llvm-objdump can currently only disassemble
+// as ARM or Thumb. Work around by disassembling twice.
+// DSOTHUMB: Disassembly of section .text:
+// DSOTHUMB: func1:
+// DSOTHUMB-NEXT: 1000: 70 47 bx lr
+// DSOTHUMB: func2:
+// DSOTHUMB-NEXT: 1002: 70 47 bx lr
+// DSOTHUMB: func3:
+// DSOTHUMB-NEXT: 1004: 70 47 bx lr
+// DSOTHUMB-NEXT: 1006: 00 00 movs r0, r0
+// DSOTHUMB: _start:
+// 0x1008 + 0x28 + 4 = 0x1034 = PLT func1
+// DSOTHUMB-NEXT: 1008: 00 f0 14 e8 blx #40
+// 0x100c + 0x34 + 4 = 0x1044 = PLT func2
+// DSOTHUMB-NEXT: 100c: 00 f0 1a e8 blx #52
+// 0x1010 + 0x40 + 4 = 0x1054 = PLT func3
+// DSOTHUMB-NEXT: 1010: 00 f0 20 e8 blx #64
+// DSOARM: Disassembly of section .plt:
+// DSOARM: .plt:
+// DSOARM-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]!
+// DSOARM-NEXT: 1024: 04 e0 9f e5 ldr lr, [pc, #4]
+// DSOARM-NEXT: 1028: 0e e0 8f e0 add lr, pc, lr
+// DSOARM-NEXT: 102c: 08 f0 be e5 ldr pc, [lr, #8]!
+// DSOARM-NEXT: 1030: d0 1f 00 00
+// 0x1028 + 8 + 1fd0 = 0x3000
+// DSOARM-NEXT: 1034: 04 c0 9f e5 ldr r12, [pc, #4]
+// DSOARM-NEXT: 1038: 0f c0 8c e0 add r12, r12, pc
+// DSOARM-NEXT: 103c: 00 f0 9c e5 ldr pc, [r12]
+// DSOARM-NEXT: 1040: cc 1f 00 00
+// 0x1038 + 8 + 1fcc = 0x300c
+// DSOARM-NEXT: 1044: 04 c0 9f e5 ldr r12, [pc, #4]
+// DSOARM-NEXT: 1048: 0f c0 8c e0 add r12, r12, pc
+// DSOARM-NEXT: 104c: 00 f0 9c e5 ldr pc, [r12]
+// DSOARM-NEXT: 1050: c0 1f 00 00
+// 0x1048 + 8 + 1fc0 = 0x3010
+// DSOARM-NEXT: 1054: 04 c0 9f e5 ldr r12, [pc, #4]
+// DSOARM-NEXT: 1058: 0f c0 8c e0 add r12, r12, pc
+// DSOARM-NEXT: 105c: 00 f0 9c e5 ldr pc, [r12]
+// DSOARM-NEXT: 1060: b4 1f 00 00
+// 0x1058 + 8 + 1fb4 = 0x3014
+
+// DSOREL: Name: .got.plt
+// DSOREL-NEXT: Type: SHT_PROGBITS
+// DSOREL-NEXT: Flags [
+// DSOREL-NEXT: SHF_ALLOC
+// DSOREL-NEXT: SHF_WRITE
+// DSOREL-NEXT: ]
+// DSOREL-NEXT: Address: 0x3000
+// DSOREL-NEXT: Offset:
+// DSOREL-NEXT: Size: 24
+// DSOREL-NEXT: Link:
+// DSOREL-NEXT: Info:
+// DSOREL-NEXT: AddressAlignment: 4
+// DSOREL-NEXT: EntrySize:
+// DSOREL: Relocations [
+// DSOREL-NEXT: Section (4) .rel.plt {
+// DSOREL-NEXT: 0x300C R_ARM_JUMP_SLOT func1 0x0
+// DSOREL-NEXT: 0x3010 R_ARM_JUMP_SLOT func2 0x0
+// DSOREL-NEXT: 0x3014 R_ARM_JUMP_SLOT func3 0x0
diff --git a/test/ELF/as-needed-no-reloc.s b/test/ELF/as-needed-no-reloc.s
new file mode 100644
index 000000000000..0706ca0a932d
--- /dev/null
+++ b/test/ELF/as-needed-no-reloc.s
@@ -0,0 +1,23 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t2.so
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld -o %t %t.o --as-needed %t2.so
+# RUN: llvm-readobj --dynamic-table --dyn-symbols %t | FileCheck %s
+
+
+# There must be a NEEDED entry for each undefined
+
+# CHECK: Name: bar
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+
+# CHECK: NEEDED SharedLibrary ({{.*}}2.so)
+
+ .globl _start
+_start:
+ .global bar
diff --git a/test/ELF/as-needed.s b/test/ELF/as-needed.s
index 2c5174d54077..4f1a48abac36 100644
--- a/test/ELF/as-needed.s
+++ b/test/ELF/as-needed.s
@@ -20,11 +20,11 @@
/// GROUP directive is the same as --as-needed.
-// RUN: echo "GROUP(" %t2.so %t3.so %t4.so ")" > %t.script
+// RUN: echo "GROUP(\"%t2.so\" \"%t3.so\" \"%t4.so\")" > %t.script
// RUN: ld.lld %t.o %t.script -o %t2
// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
-// RUN: echo "GROUP(AS_NEEDED(" %t2.so %t3.so %t4.so "))" > %t.script
+// RUN: echo "GROUP(AS_NEEDED(\"%t2.so\" \"%t3.so\" \"%t4.so\"))" > %t.script
// RUN: ld.lld %t.o %t.script -o %t2
// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
@@ -38,6 +38,7 @@
.global _start
_start:
+.data
.long bar
.long zed
.weak baz
diff --git a/test/ELF/avoid-empty-program-headers.s b/test/ELF/avoid-empty-program-headers.s
new file mode 100644
index 000000000000..f7315677e1a3
--- /dev/null
+++ b/test/ELF/avoid-empty-program-headers.s
@@ -0,0 +1,78 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %tout
+// RUN: llvm-readobj -program-headers %tout | FileCheck %s
+
+.global _start
+_start:
+ retq
+
+.section .tbss,"awT",@nobits
+ .zero 4
+// FIXME: Test that we don't create unecessary empty PT_LOAD and PT_GNU_RELRO
+// for the .tbss section.
+
+// CHECK: ProgramHeaders [
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_PHDR (0x6)
+// CHECK-NEXT: Offset: 0x40
+// CHECK-NEXT: VirtualAddress: 0x10040
+// CHECK-NEXT: PhysicalAddress: 0x10040
+// CHECK-NEXT: FileSize: 280
+// CHECK-NEXT: MemSize: 280
+// CHECK-NEXT: Flags [ (0x4)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 8
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_LOAD (0x1)
+// CHECK-NEXT: Offset: 0x0
+// CHECK-NEXT: VirtualAddress: 0x10000
+// CHECK-NEXT: PhysicalAddress: 0x10000
+// CHECK-NEXT: FileSize: 344
+// CHECK-NEXT: MemSize: 344
+// CHECK-NEXT: Flags [ (0x4)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 4096
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_LOAD (0x1)
+// CHECK-NEXT: Offset: 0x1000
+// CHECK-NEXT: VirtualAddress: 0x11000
+// CHECK-NEXT: PhysicalAddress: 0x11000
+// CHECK-NEXT: FileSize: 1
+// CHECK-NEXT: MemSize: 1
+// CHECK-NEXT: Flags [ (0x5)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: PF_X (0x1)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 4096
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_TLS (0x7)
+// CHECK-NEXT: Offset: 0x1001
+// CHECK-NEXT: VirtualAddress: 0x11001
+// CHECK-NEXT: PhysicalAddress: 0x11001
+// CHECK-NEXT: FileSize: 0
+// CHECK-NEXT: MemSize: 4
+// CHECK-NEXT: Flags [ (0x4)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 1
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)
+// CHECK-NEXT: Offset: 0x0
+// CHECK-NEXT: VirtualAddress: 0x0
+// CHECK-NEXT: PhysicalAddress: 0x0
+// CHECK-NEXT: FileSize: 0
+// CHECK-NEXT: MemSize: 0
+// CHECK-NEXT: Flags [ (0x6)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: PF_W (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/basic-aarch64.s b/test/ELF/basic-aarch64.s
index 61b6707e49a4..84105f0acdb7 100644
--- a/test/ELF/basic-aarch64.s
+++ b/test/ELF/basic-aarch64.s
@@ -5,7 +5,7 @@
# REQUIRES: aarch64
# exits with return code 42 on FreeBSD/AArch64
-.globl _start;
+.globl _start
_start:
mov x0, 42
mov x8, 1
diff --git a/test/ELF/basic-mips.s b/test/ELF/basic-mips.s
index 7b2ef564f1ce..c598c7b5f2f7 100644
--- a/test/ELF/basic-mips.s
+++ b/test/ELF/basic-mips.s
@@ -27,7 +27,7 @@ __start:
# CHECK-NEXT: Version: 1
# CHECK-NEXT: Entry: 0x20000
# CHECK-NEXT: ProgramHeaderOffset: 0x34
-# CHECK-NEXT: SectionHeaderOffset: 0x20084
+# CHECK-NEXT: SectionHeaderOffset: 0x30088
# CHECK-NEXT: Flags [
# CHECK-NEXT: EF_MIPS_ABI_O32
# CHECK-NEXT: EF_MIPS_ARCH_32R2
@@ -35,10 +35,10 @@ __start:
# CHECK-NEXT: ]
# CHECK-NEXT: HeaderSize: 52
# CHECK-NEXT: ProgramHeaderEntrySize: 32
-# CHECK-NEXT: ProgramHeaderCount: 5
+# CHECK-NEXT: ProgramHeaderCount: 6
# CHECK-NEXT: SectionHeaderEntrySize: 40
-# CHECK-NEXT: SectionHeaderCount: 9
-# CHECK-NEXT: StringTableSectionIndex: 7
+# CHECK-NEXT: SectionHeaderCount: 10
+# CHECK-NEXT: StringTableSectionIndex: 8
# CHECK-NEXT: }
# CHECK-NEXT: Sections [
# CHECK-NEXT: Section {
@@ -62,8 +62,8 @@ __start:
# CHECK-NEXT: Flags [ (0x2)
# CHECK-NEXT: SHF_ALLOC (0x2)
# CHECK-NEXT: ]
-# CHECK-NEXT: Address: 0x100D4
-# CHECK-NEXT: Offset: 0xD4
+# CHECK-NEXT: Address: 0x100F4
+# CHECK-NEXT: Offset: 0xF4
# CHECK-NEXT: Size: 24
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
@@ -77,8 +77,8 @@ __start:
# CHECK-NEXT: Flags [ (0x2)
# CHECK-NEXT: SHF_ALLOC (0x2)
# CHECK-NEXT: ]
-# CHECK-NEXT: Address: 0x100F0
-# CHECK-NEXT: Offset: 0xF0
+# CHECK-NEXT: Address: 0x10110
+# CHECK-NEXT: Offset: 0x110
# CHECK-NEXT: Size: 24
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
@@ -103,14 +103,31 @@ __start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 4
-# CHECK-NEXT: Name: .data
+# CHECK-NEXT: Name: .got (31)
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
-# CHECK-NEXT: Flags [ (0x3)
+# CHECK-NEXT: Flags [ (0x10000003)
# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: SHF_MIPS_GPREL (0x10000000)
# CHECK-NEXT: SHF_WRITE (0x1)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x30000
# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: Size: 8
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 5
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+# CHECK-NEXT: Flags [ (0x3)
+# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: SHF_WRITE (0x1)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x40000
+# CHECK-NEXT: Offset: 0x30000
# CHECK-NEXT: Size: 0
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
@@ -118,15 +135,15 @@ __start:
# CHECK-NEXT: EntrySize: 0
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 5
-# CHECK-NEXT: Name: .bss (37)
+# CHECK-NEXT: Index: 6
+# CHECK-NEXT: Name: .bss
# CHECK-NEXT: Type: SHT_NOBITS (0x8)
# CHECK-NEXT: Flags [ (0x3)
# CHECK-NEXT: SHF_ALLOC (0x2)
# CHECK-NEXT: SHF_WRITE (0x1)
# CHECK-NEXT: ]
-# CHECK-NEXT: Address: 0x30000
-# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: Address: 0x40000
+# CHECK-NEXT: Offset: 0x30000
# CHECK-NEXT: Size: 0
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
@@ -134,41 +151,41 @@ __start:
# CHECK-NEXT: EntrySize: 0
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 6
+# CHECK-NEXT: Index: 7
# CHECK-NEXT: Name: .symtab
# CHECK-NEXT: Type: SHT_SYMTAB (0x2)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
-# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: Offset: 0x30000
# CHECK-NEXT: Size: 48
-# CHECK-NEXT: Link: 8
+# CHECK-NEXT: Link: 9
# CHECK-NEXT: Info: 1
# CHECK-NEXT: AddressAlignment: 4
# CHECK-NEXT: EntrySize: 16
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 7
+# CHECK-NEXT: Index: 8
# CHECK-NEXT: Name: .shstrtab
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
-# CHECK-NEXT: Offset: 0x20030
-# CHECK-NEXT: Size: 68
+# CHECK-NEXT: Offset: 0x30030
+# CHECK-NEXT: Size: 73
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 1
# CHECK-NEXT: EntrySize: 0
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 8
-# CHECK-NEXT: Name: .strtab (60)
+# CHECK-NEXT: Index: 9
+# CHECK-NEXT: Name: .strtab
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
-# CHECK-NEXT: Offset: 0x20074
+# CHECK-NEXT: Offset: 0x30079
# CHECK-NEXT: Size: 13
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
@@ -188,12 +205,14 @@ __start:
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: _gp
-# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Value: 0x37FF0
# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
+# CHECK-NEXT: Binding: Local
# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Absolute (0xFFF1)
+# CHECK-NEXT: Other [ (0x2)
+# CHECK-NEXT: STV_HIDDEN (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Section: .got
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: __start
@@ -211,20 +230,20 @@ __start:
# CHECK-NEXT: Offset: 0x34
# CHECK-NEXT: VirtualAddress: 0x10034
# CHECK-NEXT: PhysicalAddress: 0x10034
-# CHECK-NEXT: FileSize: 160
-# CHECK-NEXT: MemSize: 160
+# CHECK-NEXT: FileSize: 192
+# CHECK-NEXT: MemSize: 192
# CHECK-NEXT: Flags [ (0x4)
# CHECK-NEXT: PF_R (0x4)
# CHECK-NEXT: ]
-# CHECK-NEXT: Alignment: 8
+# CHECK-NEXT: Alignment: 4
# CHECK-NEXT: }
# CHECK-NEXT: ProgramHeader {
# CHECK-NEXT: Type: PT_LOAD (0x1)
# CHECK-NEXT: Offset: 0x0
# CHECK-NEXT: VirtualAddress: 0x10000
# CHECK-NEXT: PhysicalAddress: 0x10000
-# CHECK-NEXT: FileSize: 264
-# CHECK-NEXT: MemSize: 264
+# CHECK-NEXT: FileSize: 296
+# CHECK-NEXT: MemSize: 296
# CHECK-NEXT: Flags [ (0x4)
# CHECK-NEXT: PF_R (0x4)
# CHECK-NEXT: ]
@@ -248,8 +267,8 @@ __start:
# CHECK-NEXT: Offset: 0x20000
# CHECK-NEXT: VirtualAddress: 0x30000
# CHECK-NEXT: PhysicalAddress: 0x30000
-# CHECK-NEXT: FileSize: 0
-# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: FileSize: 65536
+# CHECK-NEXT: MemSize: 65536
# CHECK-NEXT: Flags [
# CHECK-NEXT: PF_R
# CHECK-NEXT: PF_W
@@ -257,6 +276,18 @@ __start:
# CHECK-NEXT: Alignment: 65536
# CHECK-NEXT: }
# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_GNU_RELRO (0x6474E552)
+# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: VirtualAddress: 0x30000
+# CHECK-NEXT: PhysicalAddress: 0x30000
+# CHECK-NEXT: FileSize: 8
+# CHECK-NEXT: MemSize: 8
+# CHECK-NEXT: Flags [ (0x4)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 1
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
# CHECK-NEXT: Type: PT_GNU_STACK
# CHECK-NEXT: Offset: 0x0
# CHECK-NEXT: VirtualAddress: 0x0
diff --git a/test/ELF/basic-ppc.s b/test/ELF/basic-ppc.s
index 90acd8d8ddac..83ace9a4983d 100644
--- a/test/ELF/basic-ppc.s
+++ b/test/ELF/basic-ppc.s
@@ -28,7 +28,7 @@
// CHECK-NEXT: Version: 1
// CHECK-NEXT: Entry: 0x0
// CHECK-NEXT: ProgramHeaderOffset: 0x34
-// CHECK-NEXT: SectionHeaderOffset: 0x2084
+// CHECK-NEXT: SectionHeaderOffset: 0x209C
// CHECK-NEXT: Flags [ (0x0)
// CHECK-NEXT: ]
// CHECK-NEXT: HeaderSize: 52
@@ -157,13 +157,14 @@
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x0
// CHECK-NEXT: Offset: 0x2030
-// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Size: 32
// CHECK-NEXT: Link: 8
// CHECK-NEXT: Info: 1
// CHECK-NEXT: AddressAlignment: 4
// CHECK-NEXT: EntrySize: 16
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
+// CHECK-NEXT: 0010: 00000001 00002000 00000000 00020005 |...... .........|
// CHECK-NEXT: )
// CHECK-NEXT: }
// CHECK-NEXT: Section {
@@ -173,7 +174,7 @@
// CHECK-NEXT: Flags [ (0x0)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x0
-// CHECK-NEXT: Offset: 0x2040
+// CHECK-NEXT: Offset: 0x2050
// CHECK-NEXT: Size: 64
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
@@ -193,14 +194,14 @@
// CHECK-NEXT: Flags [ (0x0)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x0
-// CHECK-NEXT: Offset: 0x2080
+// CHECK-NEXT: Offset: 0x2090
// CHECK-NEXT: Size: 1
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 1
// CHECK-NEXT: EntrySize: 0
// CHECK-NEXT: SectionData (
-// CHECK-NEXT: 0000: 00 |.|
+// CHECK-NEXT: 0000: 005F4459 4E414D49 4300 |._DYNAMIC.|
// CHECK-NEXT: )
// CHECK-NEXT: }
// CHECK-NEXT: ]
@@ -215,7 +216,7 @@
// CHECK-NEXT: Flags [ (0x4)
// CHECK-NEXT: PF_R (0x4)
// CHECK-NEXT: ]
-// CHECK-NEXT: Alignment: 8
+// CHECK-NEXT: Alignment: 4
// CHECK-NEXT: }
// CHECK-NEXT: ProgramHeader {
// CHECK-NEXT: Type: PT_LOAD (0x1)
diff --git a/test/ELF/basic.s b/test/ELF/basic.s
index bbc674ced2ed..28449331d3fa 100644
--- a/test/ELF/basic.s
+++ b/test/ELF/basic.s
@@ -6,7 +6,7 @@
# RUN: | FileCheck %s
# exits with return code 42 on linux
-.globl _start;
+.globl _start
_start:
mov $60, %rax
mov $42, %rdi
@@ -184,12 +184,23 @@ _start:
# CHECK-NEXT: }
# CHECK-NEXT: ]
-# Test for the response file
+# Test for the response file (POSIX quoting style)
# RUN: echo " -o %t2" > %t.responsefile
-# RUN: ld.lld %t @%t.responsefile
+# RUN: ld.lld %t --rsp-quoting=posix @%t.responsefile
# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \
# RUN: | FileCheck %s
+# Test for the response file (Windows quoting style)
+# RUN: echo " c:\blah\foo" > %t.responsefile
+# RUN: not ld.lld --rsp-quoting=windows %t @%t.responsefile 2>&1 | FileCheck \
+# RUN: %s --check-prefix=WINRSP
+# WINRSP: cannot open c:\blah\foo
+
+# Test for the response file (invalid quoting style)
+# RUN: not ld.lld --rsp-quoting=patatino %t 2>&1 | FileCheck %s \
+# RUN: --check-prefix=INVRSP
+# INVRSP: invalid response file quoting: patatino
+
# RUN: not ld.lld %t.foo -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=MISSING %s
# MISSING: cannot open {{.*}}.foo: {{[Nn]}}o such file or directory
@@ -213,4 +224,7 @@ _start:
# DUP: duplicate symbol: _start in {{.*}} and {{.*}}
# RUN: not ld.lld %t -o %t -m wrong_emul 2>&1 | FileCheck --check-prefix=UNKNOWN_EMUL %s
-# UNKNOWN_EMUL: Unknown emulation: wrong_emul
+# UNKNOWN_EMUL: unknown emulation: wrong_emul
+
+# RUN: not ld.lld %t --lto-jobs=0 2>&1 | FileCheck --check-prefix=NOTHREADS %s
+# NOTHREADS: number of threads must be > 0
diff --git a/test/ELF/basic32.s b/test/ELF/basic32.s
index f4f9c410a048..44ebe7a46225 100644
--- a/test/ELF/basic32.s
+++ b/test/ELF/basic32.s
@@ -4,7 +4,7 @@
# REQUIRES: x86
# exits with return code 42 on linux
-.globl _start;
+.globl _start
_start:
mov $1, %eax
mov $42, %ebx
@@ -120,7 +120,7 @@ _start:
# CHECK-NEXT: Flags [ (0x4)
# CHECK-NEXT: PF_R (0x4)
# CHECK-NEXT: ]
-# CHECK-NEXT: Alignment: 8
+# CHECK-NEXT: Alignment: 4
# CHECK-NEXT: }
# CHECK-NEXT: ProgramHeader {
# CHECK-NEXT: Type: PT_LOAD (0x1)
diff --git a/test/ELF/basic64be.s b/test/ELF/basic64be.s
index 32d8974dae01..fb0bf7bfdb80 100644
--- a/test/ELF/basic64be.s
+++ b/test/ELF/basic64be.s
@@ -43,10 +43,10 @@ _start:
# CHECK-NEXT: ]
# CHECK-NEXT: HeaderSize: 64
# CHECK-NEXT: ProgramHeaderEntrySize: 56
-# CHECK-NEXT: ProgramHeaderCount: 5
+# CHECK-NEXT: ProgramHeaderCount: 6
# CHECK-NEXT: SectionHeaderEntrySize: 64
-# CHECK-NEXT: SectionHeaderCount: 8
-# CHECK-NEXT: StringTableSectionIndex: 6
+# CHECK-NEXT: SectionHeaderCount: 9
+# CHECK-NEXT: StringTableSectionIndex: 7
# CHECK-NEXT: }
# CHECK-NEXT: Sections [
# CHECK-NEXT: Section {
@@ -85,6 +85,24 @@ _start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .got
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x10020000
+# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 8
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
# CHECK-NEXT: Name: .toc
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x3)
@@ -104,7 +122,7 @@ _start:
# CHECK-NEXT: )
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Index: 4
# CHECK-NEXT: Name: .toc1
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x3)
@@ -124,7 +142,7 @@ _start:
# CHECK-NEXT: )
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 4
+# CHECK-NEXT: Index: 5
# CHECK-NEXT: Name: .opd
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x3)
@@ -139,12 +157,12 @@ _start:
# CHECK-NEXT: AddressAlignment: 1
# CHECK-NEXT: EntrySize: 0
# CHECK-NEXT: SectionData (
-# CHECK-NEXT: 0000: 00000000 10010000 00000000 00008000 |................|
-# CHECK-NEXT: 0010: 00000000 00000000 |........|
+# CHECK-NEXT: 0000: 00000000 10010000 00000000 10028000 |................|
+# CHECK-NEXT: 0010: 00000000 00000000 |........|
# CHECK-NEXT: )
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 5
+# CHECK-NEXT: Index: 6
# CHECK-NEXT: Name: .symtab
# CHECK-NEXT: Type: SHT_SYMTAB (0x2)
# CHECK-NEXT: Flags [ (0x0)
@@ -152,7 +170,7 @@ _start:
# CHECK-NEXT: Address: 0x0
# CHECK-NEXT: Offset: 0x20058
# CHECK-NEXT: Size: 48
-# CHECK-NEXT: Link: 7
+# CHECK-NEXT: Link: 8
# CHECK-NEXT: Info: 1
# CHECK-NEXT: AddressAlignment: 8
# CHECK-NEXT: EntrySize: 24
@@ -160,14 +178,14 @@ _start:
# CHECK: )
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 6
+# CHECK-NEXT: Index: 7
# CHECK-NEXT: Name: .shstrtab
-# CHECK-NEXT: Type: SHT_STRTAB (0x3)
-# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: Type: SHT_STRTAB
+# CHECK-NEXT: Flags [
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
# CHECK-NEXT: Offset: 0x20088
-# CHECK-NEXT: Size: 49
+# CHECK-NEXT: Size: 54
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
# CHECK-NEXT: AddressAlignment: 1
@@ -176,13 +194,13 @@ _start:
# CHECK: )
# CHECK-NEXT: }
# CHECK-NEXT: Section {
-# CHECK-NEXT: Index: 7
-# CHECK-NEXT: Name: .strtab (41)
-# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Index: 8
+# CHECK-NEXT: Name: .strtab
+# CHECK-NEXT: Type: SHT_STRTAB
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
-# CHECK-NEXT: Offset: 0x200B9
+# CHECK-NEXT: Offset: 0x200BE
# CHECK-NEXT: Size: 8
# CHECK-NEXT: Link: 0
# CHECK-NEXT: Info: 0
@@ -199,10 +217,10 @@ _start:
# CHECK-NEXT: Offset: 0x40
# CHECK-NEXT: VirtualAddress: 0x10000040
# CHECK-NEXT: PhysicalAddress: 0x10000040
-# CHECK-NEXT: FileSize: 280
-# CHECK-NEXT: MemSize: 280
-# CHECK-NEXT: Flags [ (0x4)
-# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: FileSize: 336
+# CHECK-NEXT: MemSize: 336
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
# CHECK-NEXT: ]
# CHECK-NEXT: Alignment: 8
# CHECK-NEXT: }
@@ -211,8 +229,8 @@ _start:
# CHECK-NEXT: Offset: 0x0
# CHECK-NEXT: VirtualAddress: 0x10000000
# CHECK-NEXT: PhysicalAddress: 0x10000000
-# CHECK-NEXT: FileSize: 344
-# CHECK-NEXT: MemSize: 344
+# CHECK-NEXT: FileSize: 400
+# CHECK-NEXT: MemSize: 400
# CHECK-NEXT: Flags [
# CHECK-NEXT: PF_R
# CHECK-NEXT: ]
@@ -245,6 +263,18 @@ _start:
# CHECK-NEXT: Alignment: 65536
# CHECK-NEXT: }
# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_GNU_RELRO
+# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: VirtualAddress: 0x10020000
+# CHECK-NEXT: PhysicalAddress: 0x10020000
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [ (0x4)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 1
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
# CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)
# CHECK-NEXT: Offset: 0x0
# CHECK-NEXT: VirtualAddress: 0x0
diff --git a/test/ELF/bsymbolic-undef.s b/test/ELF/bsymbolic-undef.s
new file mode 100644
index 000000000000..6590bbcb50b7
--- /dev/null
+++ b/test/ELF/bsymbolic-undef.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared -Bsymbolic %t.o -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @ (0)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local (0x0)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: undef@ (1)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+call undef@PLT
diff --git a/test/ELF/bsymbolic.s b/test/ELF/bsymbolic.s
new file mode 100644
index 000000000000..d713588d5952
--- /dev/null
+++ b/test/ELF/bsymbolic.s
@@ -0,0 +1,34 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t0.so
+// RUN: ld.lld -shared -Bsymbolic %t.o -o %t1.so
+// RUN: ld.lld -shared -Bsymbolic-functions %t.o -o %t2.so
+// RUN: llvm-readobj -s %t0.so | FileCheck -check-prefix=NOOPTION %s
+// RUN: llvm-readobj -s %t1.so | FileCheck -check-prefix=SYMBOLIC %s
+// RUN: llvm-readobj -s %t2.so | FileCheck -check-prefix=SYMBOLIC %s
+
+// NOOPTION: Section {
+// NOOPTION: Name: .plt
+
+// SYMBOLIC: Section {
+// SYMBOLIC-NOT: Name: .plt
+
+.text
+.globl foo
+.type foo,@function
+foo:
+nop
+
+.globl bar
+.type bar,@function
+bar:
+nop
+
+.globl do
+.type do,@function
+do:
+callq foo@PLT
+callq bar@PLT
+
+.weak zed
+.protected zed
+.quad zed
diff --git a/test/ELF/build-id.s b/test/ELF/build-id.s
new file mode 100644
index 000000000000..f1eac42812b4
--- /dev/null
+++ b/test/ELF/build-id.s
@@ -0,0 +1,38 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld --build-id %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=DEFAULT %s
+# RUN: ld.lld --build-id=md5 %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=MD5 %s
+# RUN: ld.lld --build-id=sha1 %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SHA1 %s
+# RUN: ld.lld --build-id=0x12345678 %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=HEX %s
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=NONE %s
+# RUN: ld.lld --build-id=md5 --build-id=none %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=NONE %s
+
+.globl _start
+_start:
+ nop
+
+.section .note.test, "a", @note
+ .quad 42
+
+# DEFAULT: Contents of section .note.gnu.build-id:
+# DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU.
+# DEFAULT: Contents of section .note.test:
+
+# MD5: Contents of section .note.gnu.build-id:
+# MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU.
+
+# SHA1: Contents of section .note.gnu.build-id:
+# SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU.
+
+# HEX: Contents of section .note.gnu.build-id:
+# HEX-NEXT: 04000000 04000000 03000000 474e5500 ............GNU.
+# HEX-NEXT: 12345678
+
+# NONE-NOT: Contents of section .note.gnu.build-id:
diff --git a/test/ELF/combrelocs.s b/test/ELF/combrelocs.s
new file mode 100644
index 000000000000..5b876ee221a4
--- /dev/null
+++ b/test/ELF/combrelocs.s
@@ -0,0 +1,92 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t.out
+# RUN: llvm-readobj -r --expand-relocs --dynamic-table %t.out | FileCheck %s
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+# CHECK-NEXT: Relocation {
+# CHECK-NEXT: Offset: 0x2000
+# CHECK-NEXT: Type: R_X86_64_64
+# CHECK-NEXT: Symbol: aaa (1)
+# CHECK-NEXT: Addend: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Relocation {
+# CHECK-NEXT: Offset: 0x2018
+# CHECK-NEXT: Type: R_X86_64_64
+# CHECK-NEXT: Symbol: aaa (1)
+# CHECK-NEXT: Addend: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Relocation {
+# CHECK-NEXT: Offset: 0x2010
+# CHECK-NEXT: Type: R_X86_64_64
+# CHECK-NEXT: Symbol: bbb (2)
+# CHECK-NEXT: Addend: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Relocation {
+# CHECK-NEXT: Offset: 0x2008
+# CHECK-NEXT: Type: R_X86_64_64
+# CHECK-NEXT: Symbol: ccc (3)
+# CHECK-NEXT: Addend: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Relocation {
+# CHECK-NEXT: Offset: 0x2020
+# CHECK-NEXT: Type: R_X86_64_64
+# CHECK-NEXT: Symbol: ddd (4)
+# CHECK-NEXT: Addend: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK: DynamicSection [
+# CHECK-NEXT: Tag
+# CHECK-NOT: RELACOUNT
+
+# RUN: ld.lld -z nocombreloc -shared %t.o -o %t.out
+# RUN: llvm-readobj -r --expand-relocs --dynamic-table %t.out | \
+# RUN: FileCheck --check-prefix=NOCOMB %s
+
+# NOCOMB: Relocations [
+# NOCOMB-NEXT: Section ({{.*}}) .rela.dyn {
+# NOCOMB-NEXT: Relocation {
+# NOCOMB-NEXT: Offset: 0x2000
+# NOCOMB-NEXT: Type: R_X86_64_64
+# NOCOMB-NEXT: Symbol: aaa (1)
+# NOCOMB-NEXT: Addend: 0x0
+# NOCOMB-NEXT: }
+# NOCOMB-NEXT: Relocation {
+# NOCOMB-NEXT: Offset: 0x2008
+# NOCOMB-NEXT: Type: R_X86_64_64
+# NOCOMB-NEXT: Symbol: ccc (3)
+# NOCOMB-NEXT: Addend: 0x0
+# NOCOMB-NEXT: }
+# NOCOMB-NEXT: Relocation {
+# NOCOMB-NEXT: Offset: 0x2010
+# NOCOMB-NEXT: Type: R_X86_64_64
+# NOCOMB-NEXT: Symbol: bbb (2)
+# NOCOMB-NEXT: Addend: 0x0
+# NOCOMB-NEXT: }
+# NOCOMB-NEXT: Relocation {
+# NOCOMB-NEXT: Offset: 0x2018
+# NOCOMB-NEXT: Type: R_X86_64_64
+# NOCOMB-NEXT: Symbol: aaa (1)
+# NOCOMB-NEXT: Addend: 0x0
+# NOCOMB-NEXT: }
+# NOCOMB-NEXT: Relocation {
+# NOCOMB-NEXT: Offset: 0x2020
+# NOCOMB-NEXT: Type: R_X86_64_64
+# NOCOMB-NEXT: Symbol: ddd (4)
+# NOCOMB-NEXT: Addend: 0x0
+# NOCOMB-NEXT: }
+# NOCOMB-NEXT: }
+# NOCOMB-NEXT: ]
+# NOCOMB: DynamicSection [
+# NOCOMB-NEXT: Tag
+# NOCOMB-NOT: RELACOUNT
+
+.data
+ .quad aaa
+ .quad ccc
+ .quad bbb
+ .quad aaa
+ .quad ddd
diff --git a/test/ELF/comdat.s b/test/ELF/comdat.s
index 4f8955e289d5..d422ee8fba33 100644
--- a/test/ELF/comdat.s
+++ b/test/ELF/comdat.s
@@ -61,6 +61,17 @@ foo:
// READ-NEXT: Section: .text
// READ-NEXT: }
// READ-NEXT: Symbol {
+// READ-NEXT: Name: _DYNAMIC
+// READ-NEXT: Value: 0x2000
+// READ-NEXT: Size: 0
+// READ-NEXT: Binding: Local
+// READ-NEXT: Type: None
+// READ-NEXT: Other [ (0x2)
+// READ-NEXT: STV_HIDDEN
+// READ-NEXT: ]
+// READ-NEXT: Section: .dynamic
+// READ-NEXT: }
+// READ-NEXT: Symbol {
// READ-NEXT: Name: abc
// READ-NEXT: Value: 0x0
// READ-NEXT: Size: 0
diff --git a/test/ELF/common.s b/test/ELF/common.s
index 67cedbccb866..f16f948fe64e 100644
--- a/test/ELF/common.s
+++ b/test/ELF/common.s
@@ -13,6 +13,9 @@
// CHECK-NEXT: Address: 0x11000
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 22
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 16
// CHECK: Name: sym1
// CHECK-NEXT: Value: 0x11004
diff --git a/test/ELF/compressed-debug-input.s b/test/ELF/compressed-debug-input.s
new file mode 100644
index 000000000000..7339833dbb7f
--- /dev/null
+++ b/test/ELF/compressed-debug-input.s
@@ -0,0 +1,61 @@
+# REQUIRES: zlib
+
+# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: llvm-readobj -sections %t | FileCheck -check-prefix=COMPRESSED %s
+
+# COMPRESSED: Section {
+# COMPRESSED: Index: 2
+# COMPRESSED: Name: .debug_str
+# COMPRESSED-NEXT: Type: SHT_PROGBITS
+# COMPRESSED-NEXT: Flags [
+# COMPRESSED-NEXT: SHF_COMPRESSED (0x800)
+# COMPRESSED-NEXT: SHF_MERGE (0x10)
+# COMPRESSED-NEXT: SHF_STRINGS (0x20)
+# COMPRESSED-NEXT: ]
+# COMPRESSED-NEXT: Address:
+# COMPRESSED-NEXT: Offset:
+# COMPRESSED-NEXT: Size: 66
+# COMPRESSED-NEXT: Link:
+# COMPRESSED-NEXT: Info:
+# COMPRESSED-NEXT: AddressAlignment: 1
+# COMPRESSED-NEXT: EntrySize: 1
+# COMPRESSED-NEXT: }
+
+# RUN: ld.lld %t -o %t.so -shared
+# RUN: llvm-readobj -sections -section-data %t.so | FileCheck -check-prefix=UNCOMPRESSED %s
+
+# UNCOMPRESSED: Section {
+# UNCOMPRESSED: Index: 6
+# UNCOMPRESSED: Name: .debug_str
+# UNCOMPRESSED-NEXT: Type: SHT_PROGBITS
+# UNCOMPRESSED-NEXT: Flags [
+# UNCOMPRESSED-NEXT: SHF_MERGE (0x10)
+# UNCOMPRESSED-NEXT: SHF_STRINGS (0x20)
+# UNCOMPRESSED-NEXT: ]
+# UNCOMPRESSED-NEXT: Address: 0x0
+# UNCOMPRESSED-NEXT: Offset: 0x1060
+# UNCOMPRESSED-NEXT: Size: 69
+# UNCOMPRESSED-NEXT: Link: 0
+# UNCOMPRESSED-NEXT: Info: 0
+# UNCOMPRESSED-NEXT: AddressAlignment: 1
+# UNCOMPRESSED-NEXT: EntrySize: 1
+# UNCOMPRESSED-NEXT: SectionData (
+# UNCOMPRESSED-NEXT: 0000: 73686F72 7420756E 7369676E 65642069 |short unsigned i|
+# UNCOMPRESSED-NEXT: 0010: 6E740075 6E736967 6E656420 696E7400 |nt.unsigned int.|
+# UNCOMPRESSED-NEXT: 0020: 6C6F6E67 20756E73 69676E65 6420696E |long unsigned in|
+# UNCOMPRESSED-NEXT: 0030: 74006368 61720075 6E736967 6E656420 |t.char.unsigned |
+# UNCOMPRESSED-NEXT: 0040: 63686172 00 |char.|
+# UNCOMPRESSED-NEXT: )
+# UNCOMPRESSED-NEXT: }
+
+.section .debug_str,"MS",@progbits,1
+.LASF2:
+ .string "short unsigned int"
+.LASF3:
+ .string "unsigned int"
+.LASF0:
+ .string "long unsigned int"
+.LASF8:
+ .string "char"
+.LASF1:
+ .string "unsigned char"
diff --git a/test/ELF/conflict.s b/test/ELF/conflict.s
new file mode 100644
index 000000000000..7598eea3711c
--- /dev/null
+++ b/test/ELF/conflict.s
@@ -0,0 +1,26 @@
+# REQUIRES: x86, shell
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: not ld.lld %t1.o %t1.o -o %t2 2>&1 | FileCheck -check-prefix=DEMANGLE %s
+
+# DEMANGLE: duplicate symbol: mul(double, double) in
+# DEMANGLE: duplicate symbol: foo in
+
+# RUN: not ld.lld %t1.o %t1.o -o %t2 --no-demangle 2>&1 | \
+# RUN: FileCheck -check-prefix=NO_DEMANGLE %s
+
+# NO_DEMANGLE: duplicate symbol: _Z3muldd in
+# NO_DEMANGLE: duplicate symbol: foo in
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/conflict.s -o %t2.o
+# RUN: llvm-ar rcs %t3.a %t2.o
+# RUN: not ld.lld %t1.o %t3.a -u baz -o %t2 2>&1 | FileCheck -check-prefix=ARCHIVE %s
+
+# ARCHIVE: duplicate symbol: foo in {{.*}}1.o and {{.*}}3.a({{.*}}2.o)
+
+.globl _Z3muldd, foo
+_Z3muldd:
+foo:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/copy-errors.s b/test/ELF/copy-errors.s
new file mode 100644
index 000000000000..9d8b72ddb43b
--- /dev/null
+++ b/test/ELF/copy-errors.s
@@ -0,0 +1,15 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/protected-shared.s -o %t2.o
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s
+
+.global _start
+_start:
+
+
+call bar
+// CHECK: cannot preempt symbol
+
+call zed
+// CHECK: symbol is missing type
diff --git a/test/ELF/copy-in-shared.s b/test/ELF/copy-in-shared.s
new file mode 100644
index 000000000000..4114d95fb101
--- /dev/null
+++ b/test/ELF/copy-in-shared.s
@@ -0,0 +1,10 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/copy-in-shared.s -o %t1.o
+// RUN: ld.lld -shared %t1.o -o %t1.so
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
+// RUN: not ld.lld %t2.o %t1.so -o %t2.so -shared 2>&1 | FileCheck %s
+
+
+.quad foo
+
+// CHECK: can't create dynamic relocation R_X86_64_64 against readonly segment
diff --git a/test/ELF/copy-rel-corrupted.s b/test/ELF/copy-rel-corrupted.s
new file mode 100644
index 000000000000..a3f72f71c1da
--- /dev/null
+++ b/test/ELF/copy-rel-corrupted.s
@@ -0,0 +1,10 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: llvm-mc %p/Inputs/copy-rel-corrupted.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: not ld.lld %t.o %t2.so -o %t.exe 2>&1 | FileCheck %s
+
+// CHECK: cannot create a copy relocation for x
+
+.global _start
+_start:
+ call x
diff --git a/test/ELF/copy-rel-pie-error.s b/test/ELF/copy-rel-pie-error.s
new file mode 100644
index 000000000000..1f427023baa5
--- /dev/null
+++ b/test/ELF/copy-rel-pie-error.s
@@ -0,0 +1,12 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: not ld.lld %t.o %t2.so -o %t.exe -pie 2>&1 | FileCheck %s
+
+// CHECK: can't create dynamic relocation R_X86_64_64 against readonly segment
+// CHECK: can't create dynamic relocation R_X86_64_64 against readonly segment
+
+.global _start
+_start:
+ .quad bar
+ .quad foo
diff --git a/test/ELF/copy-rel-pie.s b/test/ELF/copy-rel-pie.s
new file mode 100644
index 000000000000..be7d5acaeba9
--- /dev/null
+++ b/test/ELF/copy-rel-pie.s
@@ -0,0 +1,44 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t.exe -pie
+// RUN: llvm-readobj -s -r %t.exe | FileCheck %s
+// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s
+
+.global _start
+_start:
+ call bar
+ call foo
+
+// CHECK: Name: .plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1010
+
+// CHECK: Name: .bss
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x3020
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section (4) .rela.dyn {
+// CHECK-NEXT: 0x3020 R_X86_64_COPY foo 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Section (5) .rela.plt {
+// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// (0x1010 + 0x10) - 0x1005 = 27
+// 0x3020 - 0x100a = 8214
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+// DISASM-NEXT: 1000: e8 1b 00 00 00 callq 27
+// DISASM-NEXT: 1005: e8 16 20 00 00 callq 8214 <foo>
diff --git a/test/ELF/ctors_dtors_priority.s b/test/ELF/ctors_dtors_priority.s
new file mode 100644
index 000000000000..10d6471f953a
--- /dev/null
+++ b/test/ELF/ctors_dtors_priority.s
@@ -0,0 +1,41 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN: %p/Inputs/ctors_dtors_priority1.s -o %t-crtbegin.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN: %p/Inputs/ctors_dtors_priority2.s -o %t2
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN: %p/Inputs/ctors_dtors_priority3.s -o %t-crtend.o
+// RUN: ld.lld %t1 %t2 %t-crtend.o %t-crtbegin.o -o %t.exe
+// RUN: llvm-objdump -s %t.exe | FileCheck %s
+// REQUIRES: x86
+
+.globl _start
+_start:
+ nop
+
+.section .ctors, "aw", @progbits
+ .byte 1
+.section .ctors.100, "aw", @progbits
+ .byte 2
+.section .ctors.005, "aw", @progbits
+ .byte 3
+.section .ctors, "aw", @progbits
+ .byte 4
+.section .ctors, "aw", @progbits
+ .byte 5
+
+.section .dtors, "aw", @progbits
+ .byte 0x11
+.section .dtors.100, "aw", @progbits
+ .byte 0x12
+.section .dtors.005, "aw", @progbits
+ .byte 0x13
+.section .dtors, "aw", @progbits
+ .byte 0x14
+.section .dtors, "aw", @progbits
+ .byte 0x15
+
+// CHECK: Contents of section .ctors:
+// CHECK-NEXT: a1010405 b10302c1
+// CHECK: Contents of section .dtors:
+// CHECK-NEXT: a2111415 b21312c2
diff --git a/test/ELF/default-output.s b/test/ELF/default-output.s
index 8da3bb40eac0..c0766acf6e55 100644
--- a/test/ELF/default-output.s
+++ b/test/ELF/default-output.s
@@ -9,7 +9,7 @@
# RUN: ld.lld %t
# RUN: llvm-readobj a.out > /dev/null 2>&1
-.globl _start;
+.globl _start
_start:
mov $60, %rax
mov $42, %rdi
diff --git a/test/ELF/discard-merge-locals.s b/test/ELF/discard-merge-locals.s
index 51676da192ca..01b4d337cb2d 100644
--- a/test/ELF/discard-merge-locals.s
+++ b/test/ELF/discard-merge-locals.s
@@ -21,4 +21,15 @@
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: Undefined
// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _DYNAMIC
+// CHECK-NEXT: Value: 0x2000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .dynamic
+// CHECK-NEXT: }
// CHECK-NEXT: ]
diff --git a/test/ELF/discard-merge-unnamed.s b/test/ELF/discard-merge-unnamed.s
index bd0058cbd7db..be174f27b50b 100644
--- a/test/ELF/discard-merge-unnamed.s
+++ b/test/ELF/discard-merge-unnamed.s
@@ -13,4 +13,15 @@
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: Undefined
// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _DYNAMIC
+// CHECK-NEXT: Value: 0x2000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .dynamic
+// CHECK-NEXT: }
// CHECK-NEXT: ]
diff --git a/test/ELF/discard-none.s b/test/ELF/discard-none.s
index c13b544f514d..e3a7a2032082 100644
--- a/test/ELF/discard-none.s
+++ b/test/ELF/discard-none.s
@@ -21,7 +21,7 @@
// CHECK-NEXT: EntrySize:
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 002E4C6D 796F7468 65727661 72002E4C |..Lmyothervar..L|
-// CHECK-NEXT: 0010: 6D797661 7200 |myvar.|
+// CHECK-NEXT: 0010: 6D797661 72005F44 594E414D 494300 |myvar._DYNAMIC.|
// CHECK-NEXT: )
// CHECK-NEXT: }
diff --git a/test/ELF/dont-export-hidden.s b/test/ELF/dont-export-hidden.s
new file mode 100644
index 000000000000..8819a6e99fdb
--- /dev/null
+++ b/test/ELF/dont-export-hidden.s
@@ -0,0 +1,39 @@
+// RUN: llvm-mc %p/Inputs/shared.s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: llvm-mc %s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: ld.lld %t2.o %t.so -o %t.exe
+// RUN: llvm-readobj --dyn-symbols %t.exe | FileCheck %s
+
+ .global _start
+_start:
+ .global bar
+ .hidden bar
+bar:
+
+ .global bar2
+bar2:
+
+ .global foo
+foo:
+
+// CHECK: DynamicSymbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: @ (0)
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: bar2
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
diff --git a/test/ELF/driver.test b/test/ELF/driver.test
new file mode 100644
index 000000000000..95e2100b4abf
--- /dev/null
+++ b/test/ELF/driver.test
@@ -0,0 +1,49 @@
+# REQUIRES: x86
+
+# RUN: not ld.lld --unknown1 --unknown2 -m foo /no/such/file -lnosuchlib \
+# RUN: 2>&1 | FileCheck -check-prefix=UNKNOWN %s
+
+# UNKNOWN: unknown argument: --unknown1
+# UNKNOWN: unknown argument: --unknown2
+# UNKNOWN: unknown emulation: foo
+# UNKNOWN: cannot open /no/such/file
+# UNKNOWN: unable to find library -lnosuchlib
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: not ld.lld %t -o /no/such/file 2>&1 | FileCheck -check-prefix=MISSING %s
+# MISSING: failed to open /no/such/file
+
+# RUN: ld.lld --help 2>&1 | FileCheck -check-prefix=HELP %s
+# HELP: USAGE:
+
+# RUN: ld.lld --version 2>&1 | FileCheck -check-prefix=VERSION %s
+# VERSION: LLD
+
+## Attempt to link DSO with -r
+# RUN: ld.lld -shared %t -o %t.so
+# RUN: not ld.lld -r %t.so %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR %s
+# ERR: attempted static link of dynamic object
+
+## Attempt to use -r and -shared together
+# RUN: not ld.lld -r -shared %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR2 %s
+# ERR2: -r and -shared may not be used together
+
+## Attempt to use -r and --gc-sections together
+# RUN: not ld.lld -r --gc-sections %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR3 %s
+# ERR3: -r and --gc-sections may not be used together
+
+## Attempt to use -r and --icf together
+# RUN: not ld.lld -r --icf=all %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR4 %s
+# ERR4: -r and --icf may not be used together
+
+## Attempt to use -r and -pie together
+# RUN: not ld.lld -r -pie %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR5 %s
+# ERR5: -r and -pie may not be used together
+
+## Attempt to use -shared and -pie together
+# RUN: not ld.lld -shared -pie %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR6 %s
+# ERR6: -shared and -pie may not be used together
+
+.globl _start
+_start:
+ nop
diff --git a/test/ELF/duplicate-internal.s b/test/ELF/duplicate-internal.s
index 2395a6cae0db..d1ccf5322127 100644
--- a/test/ELF/duplicate-internal.s
+++ b/test/ELF/duplicate-internal.s
@@ -3,7 +3,7 @@
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
# RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-# CHECK: duplicate symbol: _gp in (internal) and {{.*}}
+# CHECK: duplicate symbol: _gp in {{.*}} and (internal)
# REQUIRES: mips
diff --git a/test/ELF/duplicated-plt-entry.s b/test/ELF/duplicated-plt-entry.s
new file mode 100644
index 000000000000..4644bed0ca8b
--- /dev/null
+++ b/test/ELF/duplicated-plt-entry.s
@@ -0,0 +1,17 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/duplicated-plt-entry.s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o
+// RUN: ld.lld %t2.o %t.so -o %t2.so -shared
+
+// RUN: llvm-readobj -r %t2.so | FileCheck %s
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+callq bar@PLT
+callq bar@PLT
diff --git a/test/ELF/dynamic-list.s b/test/ELF/dynamic-list.s
new file mode 100644
index 000000000000..5e257b31d1f3
--- /dev/null
+++ b/test/ELF/dynamic-list.s
@@ -0,0 +1,110 @@
+## There is some bad quoting interaction between lit's internal shell, which is
+## implemented in Python, and the Cygwin implementations of the Unix utilities.
+## Avoid running these tests on Windows for now by requiring a real shell.
+
+# REQUIRES: shell
+
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
+# RUN: ld.lld -shared %t2.o -soname shared -o %t2.so
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## Check exporting only one symbol.
+# RUN: echo "{ foo1; };" > %t.list
+# RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe
+# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s
+
+## And now using quoted strings (the output is the same since it does
+## use any wildcard character).
+# RUN: echo "{ \"foo1\"; };" > %t.list
+# RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe
+# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s
+
+## And now using --export-dynamic-symbol.
+# RUN: ld.lld --export-dynamic-symbol foo1 %t %t2.so -o %t.exe
+# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s
+# RUN: ld.lld --export-dynamic-symbol=foo1 %t %t2.so -o %t.exe
+# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @ (0)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo1@ (1)
+# CHECK-NEXT: Value: 0x11000
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text (0x4)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+
+## Now export all the foo1, foo2, and foo31 symbols
+# RUN: echo "{ foo1; foo2; foo31; };" > %t.list
+# RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe
+# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK2 %s
+
+# CHECK2: DynamicSymbols [
+# CHECK2-NEXT: Symbol {
+# CHECK2-NEXT: Name: @ (0)
+# CHECK2-NEXT: Value: 0x0
+# CHECK2-NEXT: Size: 0
+# CHECK2-NEXT: Binding: Local
+# CHECK2-NEXT: Type: None
+# CHECK2-NEXT: Other: 0
+# CHECK2-NEXT: Section: Undefined
+# CHECK2-NEXT: }
+# CHECK2-NEXT: Symbol {
+# CHECK2-NEXT: Name: foo1@ (1)
+# CHECK2-NEXT: Value: 0x11000
+# CHECK2-NEXT: Size: 0
+# CHECK2-NEXT: Binding: Global (0x1)
+# CHECK2-NEXT: Type: None (0x0)
+# CHECK2-NEXT: Other: 0
+# CHECK2-NEXT: Section: .text (0x4)
+# CHECK2-NEXT: }
+# CHECK2-NEXT: Symbol {
+# CHECK2-NEXT: Name: foo2@ (6)
+# CHECK2-NEXT: Value: 0x11001
+# CHECK2-NEXT: Size: 0
+# CHECK2-NEXT: Binding: Global (0x1)
+# CHECK2-NEXT: Type: None (0x0)
+# CHECK2-NEXT: Other: 0
+# CHECK2-NEXT: Section: .text (0x4)
+# CHECK2-NEXT: }
+# CHECK2-NEXT: Symbol {
+# CHECK2-NEXT: Name: foo31@ (11)
+# CHECK2-NEXT: Value: 0x11002
+# CHECK2-NEXT: Size: 0
+# CHECK2-NEXT: Binding: Global (0x1)
+# CHECK2-NEXT: Type: None (0x0)
+# CHECK2-NEXT: Other: 0
+# CHECK2-NEXT: Section: .text (0x4)
+# CHECK2-NEXT: }
+# CHECK2-NEXT: ]
+
+.globl foo1
+foo1:
+ ret
+
+.globl foo2
+foo2:
+ ret
+
+.globl foo31
+foo31:
+ ret
+
+.globl _start
+_start:
+ retq
diff --git a/test/ELF/dynamic-reloc-in-ro.s b/test/ELF/dynamic-reloc-in-ro.s
new file mode 100644
index 000000000000..2ef36f695fb6
--- /dev/null
+++ b/test/ELF/dynamic-reloc-in-ro.s
@@ -0,0 +1,8 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s
+
+foo:
+.quad foo
+
+// CHECK: can't create dynamic relocation R_X86_64_64 against readonly segment
diff --git a/test/ELF/dynamic-reloc-weak.s b/test/ELF/dynamic-reloc-weak.s
index fe1b7eedb6d7..b4da2e552e11 100644
--- a/test/ELF/dynamic-reloc-weak.s
+++ b/test/ELF/dynamic-reloc-weak.s
@@ -1,5 +1,5 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dynamic-reloc-weak.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so -o %t
// RUN: llvm-readobj -r %t | FileCheck %s
@@ -19,9 +19,12 @@ _start:
.weak sym3
.quad sym3
-// Both gold and bfd ld will produce a relocation for sym1 and sym2 only. That
-// That seems odd. If the dynamic linker must get a chance to resolve sym1
-// and sym2, that should also be the case for sym3.
+ .type sym4,@function
+ .weak sym4
+ .quad sym4
+
+// Test that we produce dynamic relocation for every weak undefined symbol
+// we found.
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
@@ -29,5 +32,6 @@ _start:
// CHECK-NEXT: }
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
// CHECK-NEXT: 0x{{.*}} R_X86_64_JUMP_SLOT sym2 0x0
+// CHECK-NEXT: 0x{{.*}} R_X86_64_JUMP_SLOT sym3 0x0
// CHECK-NEXT: }
-// CHECK-NEXT: ] \ No newline at end of file
+// CHECK-NEXT: ]
diff --git a/test/ELF/dynamic-reloc.s b/test/ELF/dynamic-reloc.s
index 295396006543..5e23ba93d5a9 100644
--- a/test/ELF/dynamic-reloc.s
+++ b/test/ELF/dynamic-reloc.s
@@ -43,6 +43,7 @@
// CHECK: DynamicSection [
// CHECK-NEXT: Tag Type Name/Value
+// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x0000000000000017 JMPREL
// CHECK-NEXT: 0x0000000000000002 PLTRELSZ 24 (bytes)
// CHECK-NEXT: 0x0000000000000003 PLTGOT
@@ -52,7 +53,6 @@
// CHECK-NEXT: 0x0000000000000005 STRTAB
// CHECK-NEXT: 0x000000000000000A STRSZ
// CHECK-NEXT: 0x0000000000000004 HASH
-// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0
// CHECK-NEXT: 0x0000000000000000 NULL 0x0
// CHECK-NEXT: ]
diff --git a/test/ELF/dynamic.s b/test/ELF/dynamic.s
new file mode 100644
index 000000000000..2efd2990c52c
--- /dev/null
+++ b/test/ELF/dynamic.s
@@ -0,0 +1,44 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t.o
+
+## Check that _DYNAMIC symbol is created when creating dynamic output,
+## and has hidden visibility and address equal to .dynamic section.
+# RUN: ld.lld -shared %t.o -o %t.so
+# RUN: llvm-readobj -sections -symbols %t.so | FileCheck %s
+# CHECK: Section {
+# CHECK: Index: 5
+# CHECK: Name: .dynamic
+# CHECK-NEXT: Type: SHT_DYNAMIC
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x[[ADDR:.*]]
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK: Symbols [
+# CHECK: Symbol {
+# CHECK: Name: _DYNAMIC
+# CHECK-NEXT: Value: 0x[[ADDR]]
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other [ (0x2)
+# CHECK-NEXT: STV_HIDDEN
+# CHECK-NEXT: ]
+# CHECK-NEXT: Section: .dynamic
+# CHECK-NEXT: }
+
+# RUN: ld.lld %t.o -o %t.o
+# RUN: llvm-readobj -sections -symbols %t.o | FileCheck -check-prefix=NODYN %s
+# NODYN: Symbols [
+# NODYN-NOT: Name: _DYNAMIC
+# NODYN: ]
+
+.globl _start
+_start:
diff --git a/test/ELF/dynsym-pie.s b/test/ELF/dynsym-pie.s
new file mode 100644
index 000000000000..9d3a9ffe304f
--- /dev/null
+++ b/test/ELF/dynsym-pie.s
@@ -0,0 +1,36 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+# RUN: ld.lld -pie %t -o %t.out
+# RUN: llvm-readobj -t -dyn-symbols %t.out | FileCheck %s
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+.text
+.globl _start
+_start:
+
+.global default
+default:
+
+.global protected
+protected:
+
+.global hidden
+hidden:
+
+.global internal
+internal:
+
+.global protected_with_hidden
+.protected
+protected_with_hidden:
diff --git a/test/ELF/edata-etext.s b/test/ELF/edata-etext.s
new file mode 100644
index 000000000000..e0538d690d7c
--- /dev/null
+++ b/test/ELF/edata-etext.s
@@ -0,0 +1,117 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-readobj -sections -symbols %t | FileCheck %s
+
+## This checks that:
+## 1) Address of _etext is the first location after the last read-only loadable segment.
+## 2) Address of _edata points to the end of the last non SHT_NOBITS section.
+## That is how gold/bfd do. At the same time specs says: "If the address of _edata is
+## greater than the address of _etext, the address of _end is same as the address
+## of _edata." (https://docs.oracle.com/cd/E53394_01/html/E54766/u-etext-3c.html).
+## 3) Address of _end is different from _edata because of 2.
+# CHECK: Section {
+# CHECK: Index: 1
+# CHECK: Name: .text
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_EXECINSTR
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x11000
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: Size: 1
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x12000
+# CHECK-NEXT: Offset: 0x2000
+# CHECK-NEXT: Size: 2
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .bss
+# CHECK-NEXT: Type: SHT_NOBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x12004
+# CHECK-NEXT: Offset: 0x2002
+# CHECK-NEXT: Size: 6
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK: Symbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name:
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: _start
+# CHECK-NEXT: Value: 0x11000
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: _edata
+# CHECK-NEXT: Value: 0x12002
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Absolute
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: _end
+# CHECK-NEXT: Value: 0x1200A
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Absolute
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: _etext
+# CHECK-NEXT: Value: 0x11001
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Absolute
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+.global _start,_end,_etext,_edata
+.text
+_start:
+ nop
+.data
+ .word 1
+.bss
+ .align 4
+ .space 6
diff --git a/test/ELF/eh-frame-dyn-rel.s b/test/ELF/eh-frame-dyn-rel.s
new file mode 100644
index 000000000000..62d56951b2cf
--- /dev/null
+++ b/test/ELF/eh-frame-dyn-rel.s
@@ -0,0 +1,10 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: not ld.lld %t.o %t.o -o %t -shared 2>&1 | FileCheck %s
+
+ .section bar,"axG",@progbits,foo,comdat
+ .cfi_startproc
+ .cfi_personality 0x8c, foo
+ .cfi_endproc
+
+// CHECK: can't create dynamic relocation R_X86_64_64 against readonly segment
diff --git a/test/ELF/eh-frame-gc.s b/test/ELF/eh-frame-gc.s
new file mode 100644
index 000000000000..b2e21f497f41
--- /dev/null
+++ b/test/ELF/eh-frame-gc.s
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+# RUN: ld.lld -shared --gc-sections %t.o -o %t
+# RUN: llvm-readobj -s %t | FileCheck %s
+
+## Check that section containing personality is
+## not garbage collected.
+# CHECK: Sections [
+# CHECK: Name: .test_personality_section
+
+.text
+.globl foo
+.type foo,@function
+foo:
+ .cfi_startproc
+ .cfi_personality 155, DW.ref.__gxx_personality_v0
+ .cfi_endproc
+
+.section .test_personality_section
+DW.ref.__gxx_personality_v0:
diff --git a/test/ELF/eh-frame-hdr-abs-fde.s b/test/ELF/eh-frame-hdr-abs-fde.s
new file mode 100644
index 000000000000..37705d6ad818
--- /dev/null
+++ b/test/ELF/eh-frame-hdr-abs-fde.s
@@ -0,0 +1,33 @@
+# Check reading PC values of FDEs and writing lookup table in the .eh_frame_hdr
+# if CIE augmentation string has 'L' token and PC values are encoded using
+# absolute (not relative) format.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld --eh-frame-hdr %t.o -o %t
+# RUN: llvm-objdump -s -dwarf=frames %t | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Contents of section .eh_frame_hdr:
+# CHECK-NEXT: 10178 011b033b ffffffcc 00000001 0000fe88
+# ^-- 0x20000 - 0x10178
+# .text - .eh_frame_hdr
+# CHECK-NEXT: 10188 ffffffe8
+# CHECK-NEXT: Contents of section .text:
+# CHECK-NEXT: 20000 00000000
+
+# CHECK: Augmentation: "zLR"
+# CHECK: Augmentation data: 00 0B
+# ^-- DW_EH_PE_udata4 | DW_EH_PE_signed
+
+ .text
+ .globl __start
+__start:
+ .cfi_startproc
+ .cfi_lsda 0, _ex
+ nop
+ .cfi_endproc
+
+ .data
+_ex:
+ .word 0
diff --git a/test/ELF/eh-frame-hdr-augmentation.s b/test/ELF/eh-frame-hdr-augmentation.s
new file mode 100644
index 000000000000..91e6a9cc1ccb
--- /dev/null
+++ b/test/ELF/eh-frame-hdr-augmentation.s
@@ -0,0 +1,38 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld --eh-frame-hdr %t.o -o %t -shared
+// RUN: llvm-objdump --dwarf=frames %t | FileCheck %s
+
+// CHECK: .eh_frame contents:
+
+// CHECK: 00000000 0000001c ffffffff CIE
+// CHECK-NEXT: Version: 1
+// CHECK-NEXT: Augmentation: "zPLR"
+// CHECK-NEXT: Code alignment factor: 1
+// CHECK-NEXT: Data alignment factor: -8
+// CHECK-NEXT: Return address column: 16
+// CHECK-NEXT: Augmentation data:
+
+// CHECK: DW_CFA_def_cfa: reg7 +8
+// CHECK-NEXT: DW_CFA_offset: reg16 -8
+// CHECK-NEXT: DW_CFA_nop:
+// CHECK-NEXT: DW_CFA_nop:
+
+// CHECK: 00000020 00000014 00000024 FDE cie=00000024 pc=00000dd8...00000dd8
+// CHECK-NEXT: DW_CFA_nop:
+// CHECK-NEXT: DW_CFA_nop:
+// CHECK-NEXT: DW_CFA_nop:
+
+ .cfi_startproc
+ .cfi_personality 0x9b, g
+ .cfi_lsda 0x1b, h
+ .cfi_endproc
+
+ .global g
+ .hidden g
+g:
+
+ .global h
+ .hidden h
+h:
+
diff --git a/test/ELF/eh-frame-hdr-icf.s b/test/ELF/eh-frame-hdr-icf.s
new file mode 100644
index 000000000000..2e7b335fb46d
--- /dev/null
+++ b/test/ELF/eh-frame-hdr-icf.s
@@ -0,0 +1,27 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2 --icf=all --eh-frame-hdr
+# RUN: llvm-objdump -s %t2 | FileCheck %s
+
+# CHECK: Contents of section .eh_frame_hdr:
+# CHECK-NEXT: 101a0 011b033b b4ffffff 01000000 600e0000
+# ^ FDE count
+# CHECK-NEXT: 101b0 d0ffffff 00000000 00000000
+# ^ FDE for f2
+
+.globl _start, f1, f2
+_start:
+ ret
+
+.section .text.f1, "ax"
+f1:
+ .cfi_startproc
+ ret
+ .cfi_endproc
+
+.section .text.f2, "ax"
+f2:
+ .cfi_startproc
+ ret
+ .cfi_endproc
diff --git a/test/ELF/eh-frame-hdr-no-out.s b/test/ELF/eh-frame-hdr-no-out.s
new file mode 100644
index 000000000000..edbafad07247
--- /dev/null
+++ b/test/ELF/eh-frame-hdr-no-out.s
@@ -0,0 +1,6 @@
+// REQUIRES: x86
+// RUN: not ld.lld --eh-frame-hdr %p/Inputs/invalid-cie-version2.elf -o %t >& %t.log
+// RUN: FileCheck %s < %t.log
+
+// invalid-cie-version2.elf contains unsupported version of CIE = 2.
+// CHECK: FDE version 1 or 3 expected, but got 2
diff --git a/test/ELF/eh-frame-hdr-no-out2.s b/test/ELF/eh-frame-hdr-no-out2.s
new file mode 100644
index 000000000000..0eeb0ea5548d
--- /dev/null
+++ b/test/ELF/eh-frame-hdr-no-out2.s
@@ -0,0 +1,19 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld --eh-frame-hdr %t.o -o %t
+// RUN: llvm-readobj -s -program-headers %t | FileCheck %s --check-prefix=NOHDR
+
+.section foo,"ax",@progbits
+ nop
+
+.text
+.globl _start
+_start:
+
+// There is no .eh_frame section,
+// therefore .eh_frame_hdr also not created.
+// NOHDR: Sections [
+// NOHDR-NOT: Name: .eh_frame
+// NOHDR-NOT: Name: .eh_frame_hdr
+// NOHDR: ProgramHeaders [
+// NOHDR-NOT: PT_GNU_EH_FRAME
diff --git a/test/ELF/eh-frame-hdr.s b/test/ELF/eh-frame-hdr.s
new file mode 100644
index 000000000000..16fb49ac8e9f
--- /dev/null
+++ b/test/ELF/eh-frame-hdr.s
@@ -0,0 +1,127 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t | FileCheck %s --check-prefix=NOHDR
+// RUN: ld.lld --eh-frame-hdr %t.o -o %t
+// RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t | FileCheck %s --check-prefix=HDR
+// RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=HDRDISASM
+
+.section foo,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.section bar,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.section dah,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.text
+.globl _start
+_start:
+
+// NOHDR: Sections [
+// NOHDR-NOT: Name: .eh_frame_hdr
+// NOHDR: ProgramHeaders [
+// NOHDR-NOT: PT_GNU_EH_FRAME
+
+//HDRDISASM: Disassembly of section foo:
+//HDRDISASM-NEXT: foo:
+//HDRDISASM-NEXT: 11000: 90 nop
+//HDRDISASM-NEXT: Disassembly of section bar:
+//HDRDISASM-NEXT: bar:
+//HDRDISASM-NEXT: 11001: 90 nop
+//HDRDISASM-NEXT: Disassembly of section dah:
+//HDRDISASM-NEXT: dah:
+//HDRDISASM-NEXT: 11002: 90 nop
+
+// HDR: Sections [
+// HDR: Section {
+// HDR: Index: 1
+// HDR-NEXT: Name: .eh_frame
+// HDR-NEXT: Type: SHT_PROGBITS
+// HDR-NEXT: Flags [
+// HDR-NEXT: SHF_ALLOC
+// HDR-NEXT: ]
+// HDR-NEXT: Address: 0x10158
+// HDR-NEXT: Offset: 0x158
+// HDR-NEXT: Size: 96
+// HDR-NEXT: Link: 0
+// HDR-NEXT: Info: 0
+// HDR-NEXT: AddressAlignment: 8
+// HDR-NEXT: EntrySize: 0
+// HDR-NEXT: SectionData (
+// HDR-NEXT: 0000: 14000000 00000000 017A5200 01781001 |
+// HDR-NEXT: 0010: 1B0C0708 90010000 14000000 1C000000 |
+// HDR-NEXT: 0020: 880E0000 01000000 00000000 00000000 |
+// HDR-NEXT: 0030: 14000000 34000000 710E0000 01000000 |
+// HDR-NEXT: 0040: 00000000 00000000 14000000 4C000000 |
+// HDR-NEXT: 0050: 5A0E0000 01000000 00000000 00000000 |
+// CIE: 14000000 00000000 017A5200 01781001 1B0C0708 90010000
+// FDE(1): 14000000 1C000000 880E0000 01000000 00000000 00000000
+// address of data (starts with 0x880E0000) = 0x10158 + 0x0020 = 0x10178
+// The starting address to which this FDE applies = 0xE88 + 0x10178 = 0x11000
+// The number of bytes after the start address to which this FDE applies = 0x01000000 = 1
+// FDE(2): 14000000 34000000 710E0000 01000000 00000000 00000000
+// address of data (starts with 0x710E0000) = 0x10158 + 0x0038 = 0x10190
+// The starting address to which this FDE applies = 0xE71 + 0x10190 = 0x11001
+// The number of bytes after the start address to which this FDE applies = 0x01000000 = 1
+// FDE(3): 14000000 4C000000 5A0E0000 01000000 00000000 00000000
+// address of data (starts with 0x5A0E0000) = 0x10158 + 0x0050 = 0x101A8
+// The starting address to which this FDE applies = 0xE5A + 0x101A8 = 0x11002
+// The number of bytes after the start address to which this FDE applies = 0x01000000 = 1
+// HDR-NEXT: )
+// HDR-NEXT: }
+// HDR-NEXT: Section {
+// HDR-NEXT: Index: 2
+// HDR-NEXT: Name: .eh_frame_hdr
+// HDR-NEXT: Type: SHT_PROGBITS
+// HDR-NEXT: Flags [
+// HDR-NEXT: SHF_ALLOC
+// HDR-NEXT: ]
+// HDR-NEXT: Address: 0x101B8
+// HDR-NEXT: Offset: 0x1B8
+// HDR-NEXT: Size: 36
+// HDR-NEXT: Link: 0
+// HDR-NEXT: Info: 0
+// HDR-NEXT: AddressAlignment: 1
+// HDR-NEXT: EntrySize: 0
+// HDR-NEXT: SectionData (
+// HDR-NEXT: 0000: 011B033B 9CFFFFFF 03000000 480E0000 |
+// HDR-NEXT: 0010: B8FFFFFF 490E0000 D0FFFFFF 4A0E0000 |
+// HDR-NEXT: 0020: E8FFFFFF |
+// Header (always 4 bytes): 0x011B033B
+// 9CFFFFFF = .eh_frame(0x10158) - .eh_frame_hdr(0x101B8) - 4
+// 03000000 = 3 = the number of FDE pointers in the table.
+// Entry(1): 480E0000 B8FFFFFF
+// 480E0000 = 0x11000 - .eh_frame_hdr(0x101B8) = 0xE48
+// B8FFFFFF = address of FDE(1) - .eh_frame_hdr(0x101B8) =
+// = .eh_frame(0x10158) + 24 - 0x101B8 = 0xFFFFFFB8
+// Entry(2): 490E0000 D0FFFFFF
+// 490E0000 = 0x11001 - .eh_frame_hdr(0x101B8) = 0xE49
+// D0FFFFFF = address of FDE(2) - .eh_frame_hdr(0x101B8) =
+// = .eh_frame(0x10158) + 24 + 24 - 0x101B8 = 0xFFFFFFD0
+// Entry(3): 4A0E0000 E8FFFFFF
+// 4A0E0000 = 0x11002 - .eh_frame_hdr(0x101B8) = 0xE4A
+// E8FFFFFF = address of FDE(2) - .eh_frame_hdr(0x101B8) =
+// = .eh_frame(0x10158) + 24 + 24 - 0x101B8 = 0xFFFFFFE8
+// HDR-NEXT: )
+// HDR-NEXT: }
+// HDR: ProgramHeaders [
+// HDR: ProgramHeader {
+// HDR: Type: PT_GNU_EH_FRAME
+// HDR-NEXT: Offset: 0x1B8
+// HDR-NEXT: VirtualAddress: 0x101B8
+// HDR-NEXT: PhysicalAddress: 0x101B8
+// HDR-NEXT: FileSize: 36
+// HDR-NEXT: MemSize: 36
+// HDR-NEXT: Flags [
+// HDR-NEXT: PF_R
+// HDR-NEXT: ]
+// HDR-NEXT: Alignment: 1
+// HDR-NEXT: }
diff --git a/test/ELF/eh-frame-marker.s b/test/ELF/eh-frame-marker.s
new file mode 100644
index 000000000000..a5de2a7c3d40
--- /dev/null
+++ b/test/ELF/eh-frame-marker.s
@@ -0,0 +1,6 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld --eh-frame-hdr %t.o -o %t.so -shared
+// We used to crash on this.
+ .section .eh_frame
+foo:
+ .long 0
diff --git a/test/ELF/eh-frame-merge.s b/test/ELF/eh-frame-merge.s
index 2b0e4a52822d..2610d4d4d2de 100644
--- a/test/ELF/eh-frame-merge.s
+++ b/test/ELF/eh-frame-merge.s
@@ -21,7 +21,7 @@
// * There is only one copy of the second FDE
// CHECK: Name: .eh_frame
-// CHECK-NEXT: Type: SHT_X86_64_UNWIND
+// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: ]
diff --git a/test/ELF/eh-frame-multilpe-cie.s b/test/ELF/eh-frame-multilpe-cie.s
new file mode 100644
index 000000000000..12781ff5b6e9
--- /dev/null
+++ b/test/ELF/eh-frame-multilpe-cie.s
@@ -0,0 +1,12 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld --eh-frame-hdr %t.o -o %t.so -shared
+// We would fail to parse multiple cies in the same file.
+
+ .cfi_startproc
+ .cfi_personality 0x9b, foo
+ .cfi_endproc
+
+ .cfi_startproc
+ .cfi_endproc
+
+foo:
diff --git a/test/ELF/eh-frame-type.test b/test/ELF/eh-frame-type.test
index f59ab116d7dd..756299739e16 100644
--- a/test/ELF/eh-frame-type.test
+++ b/test/ELF/eh-frame-type.test
@@ -1,10 +1,11 @@
-# RUN: yaml2obj -format elf %s -o %t.o
+# RUN: yaml2obj %s -o %t.o
# RUN: ld.lld %t.o -o %t -shared
# RUN: llvm-readobj -s %t | FileCheck %s
# CHECK: Name: .eh_frame
-# CHECK-NEXT: Type: SHT_X86_64_UNWIND
+# CHECK-NEXT: Type: SHT_PROGBITS
+!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
diff --git a/test/ELF/ehframe-relocation.s b/test/ELF/ehframe-relocation.s
index f952ebc60865..8d5e14919e92 100644
--- a/test/ELF/ehframe-relocation.s
+++ b/test/ELF/ehframe-relocation.s
@@ -1,17 +1,19 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-// RUN: ld.lld %t.o -o %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/ehframe-relocation.s -o %t2.o
+// RUN: ld.lld %t.o %t2.o -o %t
// RUN: llvm-readobj -s %t | FileCheck %s
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
// CHECK: Name: .eh_frame
-// CHECK-NEXT: Type: SHT_X86_64_UNWIND
+// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x10120
// CHECK-NEXT: Offset:
-// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Size: 48
+// CHECK-NOT: .eh_frame
// 0x10120 = 65824
// 0x10120 + 5 = 65829
diff --git a/test/ELF/empty-ver.s b/test/ELF/empty-ver.s
new file mode 100644
index 000000000000..f200d2876e09
--- /dev/null
+++ b/test/ELF/empty-ver.s
@@ -0,0 +1,25 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared -version-script %p/Inputs/empty-ver.ver
+// RUN: llvm-readobj -version-info %t.so | FileCheck %s
+
+// CHECK: Version symbols {
+// CHECK-NEXT: Section Name:
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Symbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Version: 0
+// CHECK-NEXT: Name: @
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Version: 2
+// CHECK-NEXT: Name: foo@ver
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+
+
+.global foo@ver
+foo@ver:
diff --git a/test/ELF/emulation.s b/test/ELF/emulation.s
index a8a8f398c42c..7cc764fc6c18 100644
--- a/test/ELF/emulation.s
+++ b/test/ELF/emulation.s
@@ -29,6 +29,37 @@
# X86-64-NEXT: StringTableSectionIndex:
# X86-64-NEXT: }
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnux32 %s -o %tx32
+# RUN: ld.lld -m elf32_x86_64 %tx32 -o %t2x32
+# RUN: llvm-readobj -file-headers %t2x32 | FileCheck --check-prefix=X32 %s
+# RUN: ld.lld %tx32 -o %t3x32
+# RUN: llvm-readobj -file-headers %t3x32 | FileCheck --check-prefix=X32 %s
+# X32: ElfHeader {
+# X32-NEXT: Ident {
+# X32-NEXT: Magic: (7F 45 4C 46)
+# X32-NEXT: Class: 32-bit (0x1)
+# X32-NEXT: DataEncoding: LittleEndian (0x1)
+# X32-NEXT: FileVersion: 1
+# X32-NEXT: OS/ABI: SystemV (0x0)
+# X32-NEXT: ABIVersion: 0
+# X32-NEXT: Unused: (00 00 00 00 00 00 00)
+# X32-NEXT: }
+# X32-NEXT: Type: Executable (0x2)
+# X32-NEXT: Machine: EM_X86_64 (0x3E)
+# X32-NEXT: Version: 1
+# X32-NEXT: Entry:
+# X32-NEXT: ProgramHeaderOffset: 0x34
+# X32-NEXT: SectionHeaderOffset:
+# X32-NEXT: Flags [ (0x0)
+# X32-NEXT: ]
+# X32-NEXT: HeaderSize: 52
+# X32-NEXT: ProgramHeaderEntrySize: 32
+# X32-NEXT: ProgramHeaderCount:
+# X32-NEXT: SectionHeaderEntrySize: 40
+# X32-NEXT: SectionHeaderCount:
+# X32-NEXT: StringTableSectionIndex:
+# X32-NEXT: }
+
# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tx86
# RUN: ld.lld -m elf_i386 %tx86 -o %t2x86
# RUN: llvm-readobj -file-headers %t2x86 | FileCheck --check-prefix=X86 %s
@@ -60,6 +91,37 @@
# X86-NEXT: StringTableSectionIndex:
# X86-NEXT: }
+# RUN: llvm-mc -filetype=obj -triple=i686-unknown-freebsd %s -o %tx86fbsd
+# RUN: ld.lld -m elf_i386_fbsd %tx86fbsd -o %t2x86_fbsd
+# RUN: llvm-readobj -file-headers %t2x86_fbsd | FileCheck --check-prefix=X86FBSD %s
+# RUN: ld.lld %tx86fbsd -o %t3x86fbsd
+# RUN: llvm-readobj -file-headers %t3x86fbsd | FileCheck --check-prefix=X86FBSD %s
+# X86FBSD: ElfHeader {
+# X86FBSD-NEXT: Ident {
+# X86FBSD-NEXT: Magic: (7F 45 4C 46)
+# X86FBSD-NEXT: Class: 32-bit (0x1)
+# X86FBSD-NEXT: DataEncoding: LittleEndian (0x1)
+# X86FBSD-NEXT: FileVersion: 1
+# X86FBSD-NEXT: OS/ABI: FreeBSD (0x9)
+# X86FBSD-NEXT: ABIVersion: 0
+# X86FBSD-NEXT: Unused: (00 00 00 00 00 00 00)
+# X86FBSD-NEXT: }
+# X86FBSD-NEXT: Type: Executable (0x2)
+# X86FBSD-NEXT: Machine: EM_386 (0x3)
+# X86FBSD-NEXT: Version: 1
+# X86FBSD-NEXT: Entry:
+# X86FBSD-NEXT: ProgramHeaderOffset: 0x34
+# X86FBSD-NEXT: SectionHeaderOffset:
+# X86FBSD-NEXT: Flags [ (0x0)
+# X86FBSD-NEXT: ]
+# X86FBSD-NEXT: HeaderSize: 52
+# X86FBSD-NEXT: ProgramHeaderEntrySize: 32
+# X86FBSD-NEXT: ProgramHeaderCount:
+# X86FBSD-NEXT: SectionHeaderEntrySize: 40
+# X86FBSD-NEXT: SectionHeaderCount:
+# X86FBSD-NEXT: StringTableSectionIndex:
+# X86FBSD-NEXT: }
+
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %tppc64
# RUN: ld.lld -m elf64ppc %tppc64 -o %t2ppc64
# RUN: llvm-readobj -file-headers %t2ppc64 | FileCheck --check-prefix=PPC64 %s
@@ -147,6 +209,60 @@
# MIPSEL-NEXT: EF_MIPS_CPIC
# MIPSEL-NEXT: ]
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %tmips64
+# RUN: ld.lld -m elf64btsmip -e _start %tmips64 -o %t2mips64
+# RUN: llvm-readobj -file-headers %t2mips64 | FileCheck --check-prefix=MIPS64 %s
+# RUN: ld.lld %tmips64 -e _start -o %t3mips64
+# RUN: llvm-readobj -file-headers %t3mips64 | FileCheck --check-prefix=MIPS64 %s
+# MIPS64: ElfHeader {
+# MIPS64-NEXT: Ident {
+# MIPS64-NEXT: Magic: (7F 45 4C 46)
+# MIPS64-NEXT: Class: 64-bit (0x2)
+# MIPS64-NEXT: DataEncoding: BigEndian (0x2)
+# MIPS64-NEXT: FileVersion: 1
+# MIPS64-NEXT: OS/ABI: SystemV (0x0)
+# MIPS64-NEXT: ABIVersion: 0
+# MIPS64-NEXT: Unused: (00 00 00 00 00 00 00)
+# MIPS64-NEXT: }
+# MIPS64-NEXT: Type: Executable (0x2)
+# MIPS64-NEXT: Machine: EM_MIPS (0x8)
+# MIPS64-NEXT: Version: 1
+# MIPS64-NEXT: Entry:
+# MIPS64-NEXT: ProgramHeaderOffset: 0x40
+# MIPS64-NEXT: SectionHeaderOffset:
+# MIPS64-NEXT: Flags [
+# MIPS64-NEXT: EF_MIPS_ARCH_64R2
+# MIPS64-NEXT: EF_MIPS_CPIC
+# MIPS64-NEXT: EF_MIPS_PIC
+# MIPS64-NEXT: ]
+
+# RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux %s -o %tmips64el
+# RUN: ld.lld -m elf64ltsmip -e _start %tmips64el -o %t2mips64el
+# RUN: llvm-readobj -file-headers %t2mips64el | FileCheck --check-prefix=MIPS64EL %s
+# RUN: ld.lld %tmips64el -e _start -o %t3mips64el
+# RUN: llvm-readobj -file-headers %t3mips64el | FileCheck --check-prefix=MIPS64EL %s
+# MIPS64EL: ElfHeader {
+# MIPS64EL-NEXT: Ident {
+# MIPS64EL-NEXT: Magic: (7F 45 4C 46)
+# MIPS64EL-NEXT: Class: 64-bit (0x2)
+# MIPS64EL-NEXT: DataEncoding: LittleEndian (0x1)
+# MIPS64EL-NEXT: FileVersion: 1
+# MIPS64EL-NEXT: OS/ABI: SystemV (0x0)
+# MIPS64EL-NEXT: ABIVersion: 0
+# MIPS64EL-NEXT: Unused: (00 00 00 00 00 00 00)
+# MIPS64EL-NEXT: }
+# MIPS64EL-NEXT: Type: Executable (0x2)
+# MIPS64EL-NEXT: Machine: EM_MIPS (0x8)
+# MIPS64EL-NEXT: Version: 1
+# MIPS64EL-NEXT: Entry:
+# MIPS64EL-NEXT: ProgramHeaderOffset: 0x40
+# MIPS64EL-NEXT: SectionHeaderOffset:
+# MIPS64EL-NEXT: Flags [
+# MIPS64EL-NEXT: EF_MIPS_ARCH_64R2
+# MIPS64EL-NEXT: EF_MIPS_CPIC
+# MIPS64EL-NEXT: EF_MIPS_PIC
+# MIPS64EL-NEXT: ]
+
# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %taarch64
# RUN: ld.lld -m aarch64linux %taarch64 -o %t2aarch64
# RUN: llvm-readobj -file-headers %t2aarch64 | FileCheck --check-prefix=AARCH64 %s
@@ -173,5 +289,5 @@
# REQUIRES: x86,ppc,mips,aarch64
-.globl _start;
+.globl _start
_start:
diff --git a/test/ELF/end.s b/test/ELF/end.s
index 390e4445e2d8..689157f82070 100644
--- a/test/ELF/end.s
+++ b/test/ELF/end.s
@@ -36,13 +36,13 @@
// NOBSS-NEXT: SHF_ALLOC
// NOBSS-NEXT: SHF_WRITE
// NOBSS-NEXT: ]
-// NOBSS-NEXT: Address: 0x12000
+// NOBSS-NEXT: Address: 0x159
// NOBSS-NEXT: Offset:
// NOBSS-NEXT: Size: 2
// NOBSS: ]
// NOBSS: Symbols [
// NOBSS: Name: _end
-// NOBSS-NEXT: Value: 0x12002
+// NOBSS-NEXT: Value: 0x15B
// NOBSS: ]
// If the layout of the sections is changed, "_end" should point to the end of allocated address space.
@@ -60,13 +60,13 @@
// TEXTATEND-NEXT: SHF_ALLOC
// TEXTATEND-NEXT: SHF_EXECINSTR
// TEXTATEND-NEXT: ]
-// TEXTATEND-NEXT: Address: 0x12000
+// TEXTATEND-NEXT: Address: 0x160
// TEXTATEND-NEXT: Offset:
// TEXTATEND-NEXT: Size: 1
// TEXTATEND: ]
// TEXTATEND: Symbols [
// TEXTATEND: Name: _end
-// TEXTATEND-NEXT: Value: 0x12001
+// TEXTATEND-NEXT: Value: 0x161
// TEXTATEND: ]
.global _start,_end
diff --git a/test/ELF/entry.s b/test/ELF/entry.s
index c8758ece69eb..6175c7623a34 100644
--- a/test/ELF/entry.s
+++ b/test/ELF/entry.s
@@ -4,9 +4,9 @@
# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=SYM %s
# RUN: ld.lld %t1 -shared -o %t2 -e entry
# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=DSO %s
-# RUN: ld.lld %t1 -o %t2 -e 4096
+# RUN: ld.lld %t1 -o %t2 --entry=4096
# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=DEC %s
-# RUN: ld.lld %t1 -o %t2 -e 0xcafe
+# RUN: ld.lld %t1 -o %t2 --entry 0xcafe
# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=HEX %s
# RUN: ld.lld %t1 -o %t2 -e 0777
# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=OCT %s
diff --git a/test/ELF/fatal-warnings.s b/test/ELF/fatal-warnings.s
new file mode 100644
index 000000000000..0bc2a2b44476
--- /dev/null
+++ b/test/ELF/fatal-warnings.s
@@ -0,0 +1,16 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/warn-common.s -o %t2.o
+
+# RUN: ld.lld --warn-common %t1.o %t2.o -o %t1.out 2>&1 | \
+# RUN: FileCheck -check-prefix=ERR %s
+# ERR: multiple common of
+
+# RUN: not ld.lld --warn-common --fatal-warnings %t1.o %t2.o -o %t2.out 2>&1 | \
+# RUN: FileCheck -check-prefix=ERR %s
+
+.globl _start
+_start:
+
+.type arr,@object
+.comm arr,4,4
diff --git a/test/ELF/file-sym.s b/test/ELF/file-sym.s
new file mode 100644
index 000000000000..eddb461490c6
--- /dev/null
+++ b/test/ELF/file-sym.s
@@ -0,0 +1,12 @@
+# Check that we do not keep STT_FILE symbols in the symbol table
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-readobj -symbols %t.so | FileCheck %s
+
+# REQUIRES: x86
+
+# CHECK-NOT: xxx
+
+.file "xxx"
+.file ""
diff --git a/test/ELF/gc-merge-local-sym.s b/test/ELF/gc-merge-local-sym.s
new file mode 100644
index 000000000000..b02a3a4e4762
--- /dev/null
+++ b/test/ELF/gc-merge-local-sym.s
@@ -0,0 +1,34 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared -O3 --gc-sections
+// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck %s
+
+// CHECK: Name: .rodata
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: SHF_STRINGS
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1C8
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 1
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 61626300 |abc.|
+// CHECK-NEXT: )
+
+// CHECK: Symbols [
+// CHECK: Symbol {
+// CHECK-NOT: Name: bar
+
+ .global foo
+foo:
+ leaq .L.str(%rip), %rsi
+ .section .rodata.str1.1,"aMS",@progbits,1
+.L.str:
+ .asciz "abc"
+bar:
+ .asciz "def"
diff --git a/test/ELF/gc-sections-eh.s b/test/ELF/gc-sections-eh.s
index 042b68ebdfe2..88c3dd0d9ca4 100644
--- a/test/ELF/gc-sections-eh.s
+++ b/test/ELF/gc-sections-eh.s
@@ -1,10 +1,23 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
# RUN: ld.lld %t -o %t2 --gc-sections
# RUN: llvm-readobj -t %t2 | FileCheck %s
+# RUN: llvm-objdump --dwarf=frames %t2 | FileCheck --check-prefix=EH %s
+
+# RUN: ld.lld %t -o %t3
+# RUN: llvm-readobj -t %t3 | FileCheck --check-prefix=NOGC %s
+# RUN: llvm-objdump --dwarf=frames %t3 | FileCheck --check-prefix=EHNOGC %s
# CHECK-NOT: foo
+# NOGC: foo
+
+# EH: FDE cie={{.*}} pc=
+# EH-NOT: FDE
+
+# EHNOGC: FDE cie={{.*}} pc=
+# EHNOGC: FDE cie={{.*}} pc=
.section .text,"ax",@progbits,unique,0
.globl foo
diff --git a/test/ELF/gc-sections-local-sym.s b/test/ELF/gc-sections-local-sym.s
new file mode 100644
index 000000000000..89121e289cc2
--- /dev/null
+++ b/test/ELF/gc-sections-local-sym.s
@@ -0,0 +1,57 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %t2 -shared --gc-sections
+// RUN: llvm-readobj -t -s -section-data %t2 | FileCheck %s
+// REQUIRES: x86
+
+.global foo
+foo:
+
+.section .bar,"a"
+zed:
+
+// CHECK: Name: .strtab
+// CHECK-NEXT: Type: SHT_STRTAB
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00666F6F 005F4459 4E414D49 4300 |.foo._DYNAMIC.|
+// CHECK-NEXT: )
+
+// CHECK: Symbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: (0)
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _DYNAMIC
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .dynamic
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: foo
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other:
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/gc-sections-lsda.s b/test/ELF/gc-sections-lsda.s
new file mode 100644
index 000000000000..b5bed8f0c816
--- /dev/null
+++ b/test/ELF/gc-sections-lsda.s
@@ -0,0 +1,21 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld -shared --gc-sections %t.o -o %t
+
+// Test that we handle .eh_frame keeping sections alive. We could be more
+// precise and gc the entire contents of this file, but test that at least
+// we are consistent: if we keep .abc, we have to keep .foo
+
+// RUN: llvm-readobj -s %t | FileCheck %s
+// CHECK: Name: .abc
+// CHECK: Name: .foo (38)
+
+ .cfi_startproc
+ .cfi_lsda 0x1b,zed
+ .cfi_endproc
+ .section .abc,"a"
+zed:
+ .long bar-.
+ .section .foo,"ax"
+bar:
diff --git a/test/ELF/gc-sections-merge-addend.s b/test/ELF/gc-sections-merge-addend.s
new file mode 100644
index 000000000000..8595f5802be5
--- /dev/null
+++ b/test/ELF/gc-sections-merge-addend.s
@@ -0,0 +1,39 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared --gc-sections
+// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s
+
+
+// CHECK: Name: .rodata
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: SHF_STRINGS
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 1
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 62617200 |bar.|
+// CHECK-NEXT: )
+
+ .section .data.f,"aw",@progbits
+ .globl f
+f:
+ .quad .rodata.str1.1 + 4
+
+ .section .data.g,"aw",@progbits
+ .hidden g
+ .globl g
+g:
+ .quad .rodata.str1.1
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+.L.str:
+ .asciz "foo"
+.L.str.1:
+ .asciz "bar"
diff --git a/test/ELF/gc-sections-merge-implicit-addend.s b/test/ELF/gc-sections-merge-implicit-addend.s
new file mode 100644
index 000000000000..8a7c804a830a
--- /dev/null
+++ b/test/ELF/gc-sections-merge-implicit-addend.s
@@ -0,0 +1,39 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=i386-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared --gc-sections
+// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s
+
+
+// CHECK: Name: .rodata
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: SHF_STRINGS
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 1
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 62617200 |bar.|
+// CHECK-NEXT: )
+
+ .section .data.f,"aw",@progbits
+ .globl f
+f:
+ .long .rodata.str1.1 + 4
+
+ .section .data.g,"aw",@progbits
+ .hidden g
+ .globl g
+g:
+ .long .rodata.str1.1
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+.L.str:
+ .asciz "foo"
+.L.str.1:
+ .asciz "bar"
diff --git a/test/ELF/gc-sections-merge.s b/test/ELF/gc-sections-merge.s
new file mode 100644
index 000000000000..ef2688659871
--- /dev/null
+++ b/test/ELF/gc-sections-merge.s
@@ -0,0 +1,61 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: ld.lld %t.o -o %t.gc.so -shared --gc-sections
+// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s
+// RUN: llvm-readobj -s -section-data %t.gc.so | FileCheck --check-prefix=GC %s
+
+
+// CHECK: Name: .rodata
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: SHF_STRINGS
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 1
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 666F6F00 62617200 |foo.bar.|
+// CHECK-NEXT: )
+
+// GC: Name: .rodata
+// GC-NEXT: Type: SHT_PROGBITS
+// GC-NEXT: Flags [
+// GC-NEXT: SHF_ALLOC
+// GC-NEXT: SHF_MERGE
+// GC-NEXT: SHF_STRINGS
+// GC-NEXT: ]
+// GC-NEXT: Address:
+// GC-NEXT: Offset:
+// GC-NEXT: Size: 4
+// GC-NEXT: Link: 0
+// GC-NEXT: Info: 0
+// GC-NEXT: AddressAlignment: 1
+// GC-NEXT: EntrySize: 1
+// GC-NEXT: SectionData (
+// GC-NEXT: 0000: 666F6F00 |foo.|
+// GC-NEXT: )
+
+ .section .text.f,"ax",@progbits
+ .globl f
+f:
+ leaq .L.str(%rip), %rax
+ retq
+
+ .section .text.g,"ax",@progbits
+ .hidden g
+ .globl g
+g:
+ leaq .L.str.1(%rip), %rax
+ retq
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+.L.str:
+ .asciz "foo"
+.L.str.1:
+ .asciz "bar"
diff --git a/test/ELF/gc-sections-protected.s b/test/ELF/gc-sections-protected.s
new file mode 100644
index 000000000000..9f1efed5938a
--- /dev/null
+++ b/test/ELF/gc-sections-protected.s
@@ -0,0 +1,18 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared --gc-sections
+// RUN: llvm-readobj -s %t.so | FileCheck %s
+
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 1
+
+.protected g
+.globl g
+g:
+retq
diff --git a/test/ELF/gc-sections-shared.s b/test/ELF/gc-sections-shared.s
new file mode 100644
index 000000000000..d52eae2177b2
--- /dev/null
+++ b/test/ELF/gc-sections-shared.s
@@ -0,0 +1,34 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t2.so
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld --gc-sections --export-dynamic-symbol foo -o %t %t.o --as-needed %t2.so
+# RUN: llvm-readobj --dynamic-table --dyn-symbols %t | FileCheck %s
+
+# This test the property that we have a needed line for every undefined.
+# It would also be OK to drop bar2 and the need for the .so
+
+
+# CHECK: Name: bar
+# CHECK: Name: bar2
+# CHECK: Name: foo
+# CHECK: NEEDED SharedLibrary ({{.*}}.so)
+
+
+.section .text.foo, "ax"
+.globl foo
+foo:
+call bar
+
+.section .text.bar, "ax"
+.globl bar
+bar:
+ret
+
+.section .text._start, "ax"
+.globl _start
+_start:
+ret
+
+.section .text.unused, "ax"
+call bar2
diff --git a/test/ELF/gc-sections-weak.s b/test/ELF/gc-sections-weak.s
new file mode 100644
index 000000000000..625b613843ba
--- /dev/null
+++ b/test/ELF/gc-sections-weak.s
@@ -0,0 +1,24 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/gc-sections-weak.s -o %t2.o
+// RUN: ld.lld %t.o %t2.o -o %t.so -shared --gc-sections
+// RUN: llvm-readobj -s %t.so | FileCheck %s
+
+.global foo
+foo:
+nop
+
+.data
+.global bar1
+bar1:
+.quad foo
+
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 1
diff --git a/test/ELF/global_offset_table_shared.s b/test/ELF/global_offset_table_shared.s
new file mode 100644
index 000000000000..7935925ae2b3
--- /dev/null
+++ b/test/ELF/global_offset_table_shared.s
@@ -0,0 +1,9 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld -shared %t -o %t2
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+.long _GLOBAL_OFFSET_TABLE_
+
+// CHECK: Name: _GLOBAL_OFFSET_TABLE_
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
diff --git a/test/ELF/gnu-ifunc-gotpcrel.s b/test/ELF/gnu-ifunc-gotpcrel.s
new file mode 100644
index 000000000000..08aa0af37a1b
--- /dev/null
+++ b/test/ELF/gnu-ifunc-gotpcrel.s
@@ -0,0 +1,14 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/gnu-ifunc-gotpcrel.s -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t2.so
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o %t2.so -o %t
+# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s
+
+# CHECK: Dynamic Relocations {
+# CHECK-NEXT: 0x120B0 R_X86_64_GLOB_DAT foo 0x0
+# CHECK-NEXT: }
+
+.globl _start
+_start:
+mov foo@gotpcrel(%rip), %rax
diff --git a/test/ELF/gnu-ifunc-i386.s b/test/ELF/gnu-ifunc-i386.s
index 6dcdf256d70c..bc2d0f9610b3 100644
--- a/test/ELF/gnu-ifunc-i386.s
+++ b/test/ELF/gnu-ifunc-i386.s
@@ -1,7 +1,7 @@
// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
// RUN: ld.lld -static %t.o -o %tout
// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
-// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
+// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s
// REQUIRES: x86
// CHECK: Sections [
@@ -43,8 +43,10 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rel.plt
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: __rel_iplt_start
@@ -52,8 +54,10 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rel.plt
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: _start
@@ -112,13 +116,11 @@
.text
.type foo STT_GNU_IFUNC
.globl foo
-.type foo, @function
foo:
ret
.type bar STT_GNU_IFUNC
.globl bar
-.type bar, @function
bar:
ret
diff --git a/test/ELF/gnu-ifunc-nosym-i386.s b/test/ELF/gnu-ifunc-nosym-i386.s
index 1101b6d763d5..d22cedbfe6de 100644
--- a/test/ELF/gnu-ifunc-nosym-i386.s
+++ b/test/ELF/gnu-ifunc-nosym-i386.s
@@ -6,20 +6,18 @@
// Check that no __rel_iplt_end/__rel_iplt_start
// appear in symtab if there is no references to them.
// CHECK: Symbols [
-// CHECK-NEXT-NOT: __rel_iplt_end
-// CHECK-NEXT-NOT: __rel_iplt_start
+// CHECK-NOT: __rel_iplt_end
+// CHECK-NOT: __rel_iplt_start
// CHECK: ]
.text
.type foo STT_GNU_IFUNC
.globl foo
-.type foo, @function
foo:
ret
.type bar STT_GNU_IFUNC
.globl bar
-.type bar, @function
bar:
ret
diff --git a/test/ELF/gnu-ifunc-nosym.s b/test/ELF/gnu-ifunc-nosym.s
index c97fd749c02b..08e498e97c19 100644
--- a/test/ELF/gnu-ifunc-nosym.s
+++ b/test/ELF/gnu-ifunc-nosym.s
@@ -6,20 +6,18 @@
// Check that no __rela_iplt_end/__rela_iplt_start
// appear in symtab if there is no references to them.
// CHECK: Symbols [
-// CHECK-NEXT-NOT: __rela_iplt_end
-// CHECK-NEXT-NOT: __rela_iplt_start
+// CHECK-NOT: __rela_iplt_end
+// CHECK-NOT: __rela_iplt_start
// CHECK: ]
.text
.type foo STT_GNU_IFUNC
.globl foo
-.type foo, @function
foo:
ret
.type bar STT_GNU_IFUNC
.globl bar
-.type bar, @function
bar:
ret
diff --git a/test/ELF/gnu-ifunc-relative.s b/test/ELF/gnu-ifunc-relative.s
new file mode 100644
index 000000000000..dc35102c5787
--- /dev/null
+++ b/test/ELF/gnu-ifunc-relative.s
@@ -0,0 +1,23 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-readobj -r -t %tout | FileCheck %s
+// REQUIRES: x86
+
+.type foo STT_GNU_IFUNC
+.globl foo
+foo:
+ ret
+
+.globl _start
+_start:
+ call foo
+
+// CHECK: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: R_X86_64_IRELATIVE - 0x[[ADDR:.*]]
+// CHECK-NEXT: }
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x[[ADDR]]
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: GNU_IFunc
diff --git a/test/ELF/gnu-ifunc.s b/test/ELF/gnu-ifunc.s
index b04f2758e22c..5336c89a563b 100644
--- a/test/ELF/gnu-ifunc.s
+++ b/test/ELF/gnu-ifunc.s
@@ -1,7 +1,7 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
// RUN: ld.lld -static %t.o -o %tout
// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
-// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
+// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s
// REQUIRES: x86
// CHECK: Sections [
@@ -42,8 +42,10 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rela.plt
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: __rela_iplt_start
@@ -51,8 +53,10 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rela.plt
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: _start
@@ -93,6 +97,7 @@
// DISASM-NEXT: 11007: e8 34 00 00 00 callq 52
// DISASM-NEXT: 1100c: ba 58 01 01 00 movl $65880, %edx
// DISASM-NEXT: 11011: ba 88 01 01 00 movl $65928, %edx
+// DISASM-NEXT: 11016: ba 89 01 01 00 movl $65929, %edx
// DISASM-NEXT: Disassembly of section .plt:
// DISASM-NEXT: .plt:
// DISASM-NEXT: 11020: ff 35 e2 0f 00 00 pushq 4066(%rip)
@@ -108,13 +113,11 @@
.text
.type foo STT_GNU_IFUNC
.globl foo
-.type foo, @function
foo:
ret
.type bar STT_GNU_IFUNC
.globl bar
-.type bar, @function
bar:
ret
@@ -124,3 +127,4 @@ _start:
call bar
movl $__rela_iplt_start,%edx
movl $__rela_iplt_end,%edx
+ movl $__rela_iplt_end + 1,%edx
diff --git a/test/ELF/gnu-unique.s b/test/ELF/gnu-unique.s
index f7206cf8c97f..afc0da27063d 100644
--- a/test/ELF/gnu-unique.s
+++ b/test/ELF/gnu-unique.s
@@ -1,7 +1,11 @@
+// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+//
// RUN: ld.lld %t -shared -o %tout.so
-// RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck %s
-// REQUIRES: x86
+// RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck -check-prefix=GNU %s
+//
+// RUN: ld.lld %t -shared -o %tout.so --no-gnu-unique
+// RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck -check-prefix=NO %s
// Check that STB_GNU_UNIQUE is treated as a global and ends up in the dynamic
// symbol table as STB_GNU_UNIQUE.
@@ -14,11 +18,20 @@ _start:
.type symb, @gnu_unique_object
symb:
-# CHECK: Name: symb@
-# CHECK-NEXT: Value:
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Unique
-# CHECK-NEXT: Type: Object
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .data
-# CHECK-NEXT: }
+# GNU: Name: symb@
+# GNU-NEXT: Value:
+# GNU-NEXT: Size: 0
+# GNU-NEXT: Binding: Unique
+# GNU-NEXT: Type: Object
+# GNU-NEXT: Other: 0
+# GNU-NEXT: Section: .data
+# GNU-NEXT: }
+
+# NO: Name: symb@
+# NO-NEXT: Value:
+# NO-NEXT: Size: 0
+# NO-NEXT: Binding: Global
+# NO-NEXT: Type: Object
+# NO-NEXT: Other: 0
+# NO-NEXT: Section: .data
+# NO-NEXT: }
diff --git a/test/ELF/got-plt-header.s b/test/ELF/got-plt-header.s
new file mode 100644
index 000000000000..691516d1a348
--- /dev/null
+++ b/test/ELF/got-plt-header.s
@@ -0,0 +1,30 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s
+
+ call foo@plt
+
+// Check that the first .got.plt entry has the address of the dynamic table.
+
+// CHECK: Type: SHT_DYNAMIC
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2000
+
+// CHECK: Name: .got.plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x3000
+// CHECK-NEXT: Offset: 0x3000
+// CHECK-NEXT: Size: 32
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00200000 00000000 00000000 00000000
diff --git a/test/ELF/gotpc-relax-nopic.s b/test/ELF/gotpc-relax-nopic.s
new file mode 100644
index 000000000000..278173557837
--- /dev/null
+++ b/test/ELF/gotpc-relax-nopic.s
@@ -0,0 +1,81 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t1
+# RUN: llvm-readobj -symbols -r %t1 | FileCheck --check-prefix=SYMRELOC %s
+# RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+## There is no relocations.
+# SYMRELOC: Relocations [
+# SYMRELOC-NEXT: ]
+# SYMRELOC: Symbols [
+# SYMRELOC: Symbol {
+# SYMRELOC: Name: bar
+# SYMRELOC-NEXT: Value: 0x12000
+
+## 73728 = 0x12000 (bar)
+# DISASM: Disassembly of section .text:
+# DISASM-NEXT: _start:
+# DISASM-NEXT: 11000: 48 81 d0 00 20 01 00 adcq $73728, %rax
+# DISASM-NEXT: 11007: 48 81 c3 00 20 01 00 addq $73728, %rbx
+# DISASM-NEXT: 1100e: 48 81 e1 00 20 01 00 andq $73728, %rcx
+# DISASM-NEXT: 11015: 48 81 fa 00 20 01 00 cmpq $73728, %rdx
+# DISASM-NEXT: 1101c: 48 81 cf 00 20 01 00 orq $73728, %rdi
+# DISASM-NEXT: 11023: 48 81 de 00 20 01 00 sbbq $73728, %rsi
+# DISASM-NEXT: 1102a: 48 81 ed 00 20 01 00 subq $73728, %rbp
+# DISASM-NEXT: 11031: 49 81 f0 00 20 01 00 xorq $73728, %r8
+# DISASM-NEXT: 11038: 49 f7 c7 00 20 01 00 testq $73728, %r15
+
+# RUN: ld.lld -shared %t.o -o %t2
+# RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=SEC-PIC %s
+# RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM-PIC %s
+# SEC-PIC: Section {
+# SEC-PIC: Index:
+# SEC-PIC: Name: .got
+# SEC-PIC-NEXT: Type: SHT_PROGBITS
+# SEC-PIC-NEXT: Flags [
+# SEC-PIC-NEXT: SHF_ALLOC
+# SEC-PIC-NEXT: SHF_WRITE
+# SEC-PIC-NEXT: ]
+# SEC-PIC-NEXT: Address: 0x2090
+# SEC-PIC-NEXT: Offset: 0x2090
+# SEC-PIC-NEXT: Size: 8
+# SEC-PIC-NEXT: Link:
+# SEC-PIC-NEXT: Info:
+# SEC-PIC-NEXT: AddressAlignment:
+# SEC-PIC-NEXT: EntrySize:
+# SEC-PIC-NEXT: }
+
+## Check that there was no relaxation performed. All values refer to got entry.
+## Ex: 0x1000 + 4233 + 7 = 0x2090
+## 0x102a + 4191 + 7 = 0x2090
+# DISASM-PIC: Disassembly of section .text:
+# DISASM-PIC-NEXT: _start:
+# DISASM-PIC-NEXT: 1000: 48 13 05 89 10 00 00 adcq 4233(%rip), %rax
+# DISASM-PIC-NEXT: 1007: 48 03 1d 82 10 00 00 addq 4226(%rip), %rbx
+# DISASM-PIC-NEXT: 100e: 48 23 0d 7b 10 00 00 andq 4219(%rip), %rcx
+# DISASM-PIC-NEXT: 1015: 48 3b 15 74 10 00 00 cmpq 4212(%rip), %rdx
+# DISASM-PIC-NEXT: 101c: 48 0b 3d 6d 10 00 00 orq 4205(%rip), %rdi
+# DISASM-PIC-NEXT: 1023: 48 1b 35 66 10 00 00 sbbq 4198(%rip), %rsi
+# DISASM-PIC-NEXT: 102a: 48 2b 2d 5f 10 00 00 subq 4191(%rip), %rbp
+# DISASM-PIC-NEXT: 1031: 4c 33 05 58 10 00 00 xorq 4184(%rip), %r8
+# DISASM-PIC-NEXT: 1038: 4c 85 3d 51 10 00 00 testq 4177(%rip), %r15
+
+.data
+.type bar, @object
+bar:
+ .byte 1
+ .size bar, .-bar
+
+.text
+.globl _start
+.type _start, @function
+_start:
+ adcq bar@GOTPCREL(%rip), %rax
+ addq bar@GOTPCREL(%rip), %rbx
+ andq bar@GOTPCREL(%rip), %rcx
+ cmpq bar@GOTPCREL(%rip), %rdx
+ orq bar@GOTPCREL(%rip), %rdi
+ sbbq bar@GOTPCREL(%rip), %rsi
+ subq bar@GOTPCREL(%rip), %rbp
+ xorq bar@GOTPCREL(%rip), %r8
+ testq %r15, bar@GOTPCREL(%rip)
diff --git a/test/ELF/gotpc-relax-und-dso.s b/test/ELF/gotpc-relax-und-dso.s
new file mode 100644
index 000000000000..ed6c4bc9bb15
--- /dev/null
+++ b/test/ELF/gotpc-relax-und-dso.s
@@ -0,0 +1,72 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %S/Inputs/gotpc-relax-und-dso.s -o %tdso.o
+# RUN: ld.lld -shared %tdso.o -o %t.so
+# RUN: ld.lld -shared %t.o %t.so -o %tout
+# RUN: llvm-readobj -r -s %tout | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s
+
+# RELOC: Relocations [
+# RELOC-NEXT: Section ({{.*}}) .rela.dyn {
+# RELOC-NEXT: R_X86_64_GLOB_DAT dsofoo 0x0
+# RELOC-NEXT: R_X86_64_GLOB_DAT foo 0x0
+# RELOC-NEXT: R_X86_64_GLOB_DAT und 0x0
+# RELOC-NEXT: }
+# RELOC-NEXT: ]
+
+# 0x101e + 7 - 36 = 0x1001
+# 0x1025 + 7 - 43 = 0x1001
+# DISASM: Disassembly of section .text:
+# DISASM-NEXT: foo:
+# DISASM-NEXT: nop
+# DISASM: hid:
+# DISASM-NEXT: nop
+# DISASM: _start:
+# DISASM-NEXT: movq 4247(%rip), %rax
+# DISASM-NEXT: movq 4240(%rip), %rax
+# DISASM-NEXT: movq 4241(%rip), %rax
+# DISASM-NEXT: movq 4234(%rip), %rax
+# DISASM-NEXT: leaq -36(%rip), %rax
+# DISASM-NEXT: leaq -43(%rip), %rax
+# DISASM-NEXT: movq 4221(%rip), %rax
+# DISASM-NEXT: movq 4214(%rip), %rax
+# DISASM-NEXT: movq 4191(%rip), %rax
+# DISASM-NEXT: movq 4184(%rip), %rax
+# DISASM-NEXT: movq 4185(%rip), %rax
+# DISASM-NEXT: movq 4178(%rip), %rax
+# DISASM-NEXT: leaq -92(%rip), %rax
+# DISASM-NEXT: leaq -99(%rip), %rax
+# DISASM-NEXT: movq 4165(%rip), %rax
+# DISASM-NEXT: movq 4158(%rip), %rax
+
+.text
+.globl foo
+.type foo, @function
+foo:
+ nop
+
+.globl hid
+.hidden hid
+.type hid, @function
+hid:
+ nop
+
+.globl _start
+.type _start, @function
+_start:
+ movq und@GOTPCREL(%rip), %rax
+ movq und@GOTPCREL(%rip), %rax
+ movq dsofoo@GOTPCREL(%rip), %rax
+ movq dsofoo@GOTPCREL(%rip), %rax
+ movq hid@GOTPCREL(%rip), %rax
+ movq hid@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %rax
+ movq und@GOTPCREL(%rip), %rax
+ movq und@GOTPCREL(%rip), %rax
+ movq dsofoo@GOTPCREL(%rip), %rax
+ movq dsofoo@GOTPCREL(%rip), %rax
+ movq hid@GOTPCREL(%rip), %rax
+ movq hid@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %rax
diff --git a/test/ELF/gotpc-relax.s b/test/ELF/gotpc-relax.s
new file mode 100644
index 000000000000..422e10439d00
--- /dev/null
+++ b/test/ELF/gotpc-relax.s
@@ -0,0 +1,98 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t1
+# RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+## There is no relocations.
+# RELOC: Relocations [
+# RELOC: ]
+
+# 0x11003 + 7 - 10 = 0x11000
+# 0x1100a + 7 - 17 = 0x11000
+# 0x11011 + 7 - 23 = 0x11001
+# 0x11018 + 7 - 30 = 0x11001
+# DISASM: Disassembly of section .text:
+# DISASM-NEXT: foo:
+# DISASM-NEXT: 11000: 90 nop
+# DISASM: hid:
+# DISASM-NEXT: 11001: 90 nop
+# DISASM: ifunc:
+# DISASM-NEXT: 11002: c3 retq
+# DISASM: _start:
+# DISASM-NEXT: leaq -10(%rip), %rax
+# DISASM-NEXT: leaq -17(%rip), %rax
+# DISASM-NEXT: leaq -23(%rip), %rax
+# DISASM-NEXT: leaq -30(%rip), %rax
+# DISASM-NEXT: movq 4058(%rip), %rax
+# DISASM-NEXT: movq 4051(%rip), %rax
+# DISASM-NEXT: leaq -52(%rip), %rax
+# DISASM-NEXT: leaq -59(%rip), %rax
+# DISASM-NEXT: leaq -65(%rip), %rax
+# DISASM-NEXT: leaq -72(%rip), %rax
+# DISASM-NEXT: movq 4016(%rip), %rax
+# DISASM-NEXT: movq 4009(%rip), %rax
+# DISASM-NEXT: callq -93 <foo>
+# DISASM-NEXT: callq -99 <foo>
+# DISASM-NEXT: callq -104 <hid>
+# DISASM-NEXT: callq -110 <hid>
+# DISASM-NEXT: callq *3979(%rip)
+# DISASM-NEXT: callq *3973(%rip)
+# DISASM-NEXT: jmp -128 <foo>
+# DISASM-NEXT: nop
+# DISASM-NEXT: jmp -134 <foo>
+# DISASM-NEXT: nop
+# DISASM-NEXT: jmp -139 <hid>
+# DISASM-NEXT: nop
+# DISASM-NEXT: jmp -145 <hid>
+# DISASM-NEXT: nop
+# DISASM-NEXT: jmpq *3943(%rip)
+# DISASM-NEXT: jmpq *3937(%rip)
+
+.text
+.globl foo
+.type foo, @function
+foo:
+ nop
+
+.globl hid
+.hidden hid
+.type hid, @function
+hid:
+ nop
+
+.text
+.type ifunc STT_GNU_IFUNC
+.globl ifunc
+.type ifunc, @function
+ifunc:
+ ret
+
+.globl _start
+.type _start, @function
+_start:
+ movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %rax
+ movq hid@GOTPCREL(%rip), %rax
+ movq hid@GOTPCREL(%rip), %rax
+ movq ifunc@GOTPCREL(%rip), %rax
+ movq ifunc@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %rax
+ movq hid@GOTPCREL(%rip), %rax
+ movq hid@GOTPCREL(%rip), %rax
+ movq ifunc@GOTPCREL(%rip), %rax
+ movq ifunc@GOTPCREL(%rip), %rax
+
+ call *foo@GOTPCREL(%rip)
+ call *foo@GOTPCREL(%rip)
+ call *hid@GOTPCREL(%rip)
+ call *hid@GOTPCREL(%rip)
+ call *ifunc@GOTPCREL(%rip)
+ call *ifunc@GOTPCREL(%rip)
+ jmp *foo@GOTPCREL(%rip)
+ jmp *foo@GOTPCREL(%rip)
+ jmp *hid@GOTPCREL(%rip)
+ jmp *hid@GOTPCREL(%rip)
+ jmp *ifunc@GOTPCREL(%rip)
+ jmp *ifunc@GOTPCREL(%rip)
diff --git a/test/ELF/gotpcrelx.s b/test/ELF/gotpcrelx.s
new file mode 100644
index 000000000000..95dbf663ffe8
--- /dev/null
+++ b/test/ELF/gotpcrelx.s
@@ -0,0 +1,30 @@
+// RUN: llvm-mc -filetype=obj -relax-relocations -triple x86_64-pc-linux-gnu \
+// RUN: %s -o %t.o
+// RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELS %s
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -s -r %t.so | FileCheck %s
+
+movq foo@GOTPCREL(%rip), %rax
+movq bar@GOTPCREL(%rip), %rax
+
+// RELS: Relocations [
+// RELS-NEXT: Section ({{.*}}) .rela.text {
+// RELS-NEXT: R_X86_64_REX_GOTPCRELX foo 0xFFFFFFFFFFFFFFFC
+// RELS-NEXT: R_X86_64_REX_GOTPCRELX bar 0xFFFFFFFFFFFFFFFC
+// RELS-NEXT: }
+// RELS-NEXT: ]
+
+// CHECK: Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2090
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x2098 R_X86_64_GLOB_DAT bar 0x0
+// CHECK-NEXT: 0x2090 R_X86_64_GLOB_DAT foo 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/i386-got-and-copy.s b/test/ELF/i386-got-and-copy.s
new file mode 100644
index 000000000000..f5b0b8ec5bb8
--- /dev/null
+++ b/test/ELF/i386-got-and-copy.s
@@ -0,0 +1,25 @@
+# REQUIRES: x86
+
+# If there are two relocations such that the first one requires
+# dynamic COPY relocation, the second one requires GOT entry
+# creation, linker should create both - dynamic relocation
+# and GOT entry.
+
+# RUN: llvm-mc -filetype=obj -triple=i386-pc-linux \
+# RUN: %S/Inputs/copy-in-shared.s -o %t.so.o
+# RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o
+# RUN: ld.lld %t.so.o -shared -o %t.so
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-readobj -r %t.exe | FileCheck %s
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section (4) .rel.dyn {
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_COPY foo
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+ .text
+ .global _start
+_start:
+ movl $foo, (%esp) # R_386_32 - requires R_386_COPY relocation
+ movl foo@GOT, %eax # R_386_GOT32 - requires GOT entry
diff --git a/test/ELF/i386-gotpc.s b/test/ELF/i386-gotpc.s
new file mode 100644
index 000000000000..14c2fcbec064
--- /dev/null
+++ b/test/ELF/i386-gotpc.s
@@ -0,0 +1,20 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -s %t.so | FileCheck %s
+// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s
+
+movl $_GLOBAL_OFFSET_TABLE_, %eax
+
+// CHECK: Name: .got (38)
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2030
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: .text:
+// DISASM-NEXT: 1000: {{.*}} movl $4144, %eax
+// 0x2030 - 0x1000 = 4144
diff --git a/test/ELF/i386-merge.s b/test/ELF/i386-merge.s
new file mode 100644
index 000000000000..5d48d4d07f08
--- /dev/null
+++ b/test/ELF/i386-merge.s
@@ -0,0 +1,50 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t -shared
+// RUN: llvm-readobj -s -section-data %t | FileCheck %s
+
+// CHECK: Name: .mysec
+// CHECK-NEXT: Type:
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x114
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 42000000 |
+// CHECK-NEXT: )
+
+
+// CHECK: Name: .data
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2000
+// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 14010000 |
+// CHECK-NEXT: )
+
+// The content of .data should be the address of .mysec. 14010000 is 0x114 in
+// little endian.
+
+ .data
+ .long .mysec+4
+
+ .section .mysec,"aM",@progbits,4
+ .align 4
+ .long 0x42
+ .long 0x42
diff --git a/test/ELF/i386-relative.s b/test/ELF/i386-relative.s
new file mode 100644
index 000000000000..d814b5b6786a
--- /dev/null
+++ b/test/ELF/i386-relative.s
@@ -0,0 +1,14 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-readobj -r %t.so | FileCheck %s
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rel.dyn {
+// CHECK-NEXT: R_386_RELATIVE - 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+ .data
+foo:
+ .long foo
diff --git a/test/ELF/i386-relax-reloc.s b/test/ELF/i386-relax-reloc.s
new file mode 100644
index 000000000000..a7fdc404ceca
--- /dev/null
+++ b/test/ELF/i386-relax-reloc.s
@@ -0,0 +1,12 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o -relax-relocations
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-objdump -d %t.so | FileCheck %s
+
+foo:
+ movl bar@GOT(%ebx), %eax
+ movl bar+8@GOT(%ebx), %eax
+
+// CHECK: foo:
+// CHECK-NEXT: movl -4(%ebx), %eax
+// CHECK-NEXT: movl 4(%ebx), %eax
diff --git a/test/ELF/i386-tls-ie-shared.s b/test/ELF/i386-tls-ie-shared.s
new file mode 100644
index 000000000000..a2c25e2d2f81
--- /dev/null
+++ b/test/ELF/i386-tls-ie-shared.s
@@ -0,0 +1,110 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o
+// RUN: ld.lld -shared %tso.o -o %tso
+// RUN: ld.lld -shared %t.o %tso -o %t1
+// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTRELSHARED %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s
+
+// GOTRELSHARED: Section {
+// GOTRELSHARED: Index: 8
+// GOTRELSHARED: Name: .got
+// GOTRELSHARED-NEXT: Type: SHT_PROGBITS
+// GOTRELSHARED-NEXT: Flags [
+// GOTRELSHARED-NEXT: SHF_ALLOC
+// GOTRELSHARED-NEXT: SHF_WRITE
+// GOTRELSHARED-NEXT: ]
+// GOTRELSHARED-NEXT: Address: 0x1050
+// GOTRELSHARED-NEXT: Offset: 0x1050
+// GOTRELSHARED-NEXT: Size: 16
+// GOTRELSHARED-NEXT: Link: 0
+// GOTRELSHARED-NEXT: Info: 0
+// GOTRELSHARED-NEXT: AddressAlignment: 4
+// GOTRELSHARED-NEXT: EntrySize: 0
+// GOTRELSHARED-NEXT: }
+// GOTRELSHARED: Relocations [
+// GOTRELSHARED-NEXT: Section ({{.*}}) .rel.dyn {
+// GOTRELSHARED-NEXT: 0x2002 R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT: 0x200A R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT: 0x2013 R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT: 0x201C R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT: 0x2024 R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT: 0x202D R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT: 0x2036 R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT: 0x203F R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT: 0x1050 R_386_TLS_TPOFF tlslocal0 0x0
+// GOTRELSHARED-NEXT: 0x1054 R_386_TLS_TPOFF tlslocal1 0x0
+// GOTRELSHARED-NEXT: 0x1058 R_386_TLS_TPOFF tlsshared0 0x0
+// GOTRELSHARED-NEXT: 0x105C R_386_TLS_TPOFF tlsshared1 0x0
+// GOTRELSHARED-NEXT: }
+// GOTRELSHARED-NEXT: ]
+
+// DISASMSHARED: Disassembly of section test:
+// DISASMSHARED-NEXT: _start:
+// (.got)[0] = 0x2050 = 8272
+// (.got)[1] = 0x2054 = 8276
+// (.got)[2] = 0x2058 = 8280
+// (.got)[3] = 0x205C = 8284
+// DISASMSHARED-NEXT: 2000: 8b 0d 50 10 00 00 movl 4176, %ecx
+// DISASMSHARED-NEXT: 2006: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT: 2009: a1 50 10 00 00 movl 4176, %eax
+// DISASMSHARED-NEXT: 200e: 65 8b 00 movl %gs:(%eax), %eax
+// DISASMSHARED-NEXT: 2011: 03 0d 50 10 00 00 addl 4176, %ecx
+// DISASMSHARED-NEXT: 2017: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT: 201a: 8b 0d 54 10 00 00 movl 4180, %ecx
+// DISASMSHARED-NEXT: 2020: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT: 2023: a1 54 10 00 00 movl 4180, %eax
+// DISASMSHARED-NEXT: 2028: 65 8b 00 movl %gs:(%eax), %eax
+// DISASMSHARED-NEXT: 202b: 03 0d 54 10 00 00 addl 4180, %ecx
+// DISASMSHARED-NEXT: 2031: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT: 2034: 8b 0d 58 10 00 00 movl 4184, %ecx
+// DISASMSHARED-NEXT: 203a: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT: 203d: 03 0d 5c 10 00 00 addl 4188, %ecx
+// DISASMSHARED-NEXT: 2043: 65 8b 01 movl %gs:(%ecx), %eax
+
+.type tlslocal0,@object
+.section .tbss,"awT",@nobits
+.globl tlslocal0
+.align 4
+tlslocal0:
+ .long 0
+ .size tlslocal0, 4
+
+.type tlslocal1,@object
+.section .tbss,"awT",@nobits
+.globl tlslocal1
+.align 4
+tlslocal1:
+ .long 0
+ .size tlslocal1, 4
+
+.section .text
+.globl ___tls_get_addr
+.type ___tls_get_addr,@function
+___tls_get_addr:
+
+.section test, "axw"
+.globl _start
+_start:
+movl tlslocal0@indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+movl tlslocal0@indntpoff,%eax
+movl %gs:(%eax),%eax
+
+addl tlslocal0@indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+movl tlslocal1@indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+movl tlslocal1@indntpoff,%eax
+movl %gs:(%eax),%eax
+
+addl tlslocal1@indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+movl tlsshared0@indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+addl tlsshared1@indntpoff,%ecx
+movl %gs:(%ecx),%eax
diff --git a/test/ELF/icf1.s b/test/ELF/icf1.s
new file mode 100644
index 000000000000..bb060078476e
--- /dev/null
+++ b/test/ELF/icf1.s
@@ -0,0 +1,23 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s
+
+# CHECK: selected .text.f1
+# CHECK: removed .text.f2
+
+.globl _start, f1, f2
+_start:
+ ret
+
+.section .text.f1, "ax"
+f1:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
+
+.section .text.f2, "ax"
+f2:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/icf2.s b/test/ELF/icf2.s
new file mode 100644
index 000000000000..be595112b7e7
--- /dev/null
+++ b/test/ELF/icf2.s
@@ -0,0 +1,17 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/icf2.s -o %t2
+# RUN: ld.lld %t1 %t2 -o %t --icf=all --verbose | FileCheck %s
+
+# CHECK: selected .text.f1
+# CHECK: removed .text.f2
+
+.globl _start, f1, f2
+_start:
+ ret
+
+.section .text.f1, "ax"
+f1:
+ mov $60, %rdi
+ call f2
diff --git a/test/ELF/icf3.s b/test/ELF/icf3.s
new file mode 100644
index 000000000000..9f39ff6c7477
--- /dev/null
+++ b/test/ELF/icf3.s
@@ -0,0 +1,19 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/icf2.s -o %t2
+# RUN: ld.lld %t1 %t2 -o %t --icf=all --verbose | FileCheck %s
+
+# CHECK-NOT: Selected .text.f1
+# CHECK-NOT: Selected .text.f2
+
+.globl _start, f1, f2
+_start:
+ ret
+
+# This section is not mergeable because the content is different from f2.
+.section .text.f1, "ax"
+f1:
+ mov $60, %rdi
+ call f2
+ mov $0, %rax
diff --git a/test/ELF/icf4.s b/test/ELF/icf4.s
new file mode 100644
index 000000000000..ad16d48775d6
--- /dev/null
+++ b/test/ELF/icf4.s
@@ -0,0 +1,19 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t --icf=all --verbose | FileCheck %s
+
+# CHECK-NOT: Selected .text.f1
+# CHECK-NOT: Selected .text.f2
+
+.globl _start, f1, f2
+_start:
+ ret
+
+.section .text.f1, "ax"
+f1:
+ mov $1, %rax
+
+.section .text.f2, "ax"
+f2:
+ mov $0, %rax
diff --git a/test/ELF/icf5.s b/test/ELF/icf5.s
new file mode 100644
index 000000000000..cf466585c581
--- /dev/null
+++ b/test/ELF/icf5.s
@@ -0,0 +1,19 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t --icf=all --verbose | FileCheck %s
+
+# CHECK-NOT: Selected .text.f1
+# CHECK-NOT: Selected .text.f2
+
+.globl _start, f1, f2
+_start:
+ ret
+
+.section .text.f1, "ax"
+f1:
+ mov $0, %rax
+
+.section .text.f2, "awx"
+f2:
+ mov $0, %rax
diff --git a/test/ELF/icf6.s b/test/ELF/icf6.s
new file mode 100644
index 000000000000..ecb62fee2a0c
--- /dev/null
+++ b/test/ELF/icf6.s
@@ -0,0 +1,23 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s
+
+# CHECK-NOT: Selected .text.f1
+# CHECK-NOT: Selected .text.f2
+
+.globl _start, f1, f2
+_start:
+ ret
+
+.section .init, "ax"
+f1:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
+
+.section .fini, "ax"
+f2:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/icf7.s b/test/ELF/icf7.s
new file mode 100644
index 000000000000..f1fca5b2f2d5
--- /dev/null
+++ b/test/ELF/icf7.s
@@ -0,0 +1,29 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s
+# RUN: llvm-objdump -t %t2 | FileCheck -check-prefix=ALIGN %s
+
+# CHECK: selected .text.f1
+# CHECK: removed .text.f2
+
+# ALIGN: 0000000000011000 .text 00000000 _start
+# ALIGN: 0000000000011100 .text 00000000 f1
+
+.globl _start, f1, f2
+_start:
+ ret
+
+.section .text.f1, "ax"
+ .align 1
+f1:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
+
+.section .text.f2, "ax"
+ .align 256
+f2:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/image-base.s b/test/ELF/image-base.s
new file mode 100644
index 000000000000..0be5059dcad8
--- /dev/null
+++ b/test/ELF/image-base.s
@@ -0,0 +1,60 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld -image-base=0x1000000 %t -o %t1
+# RUN: llvm-readobj -program-headers %t1 | FileCheck %s
+
+.global _start
+_start:
+ nop
+
+# CHECK: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_PHDR (0x6)
+# CHECK-NEXT: Offset: 0x40
+# CHECK-NEXT: VirtualAddress: 0x1000040
+# CHECK-NEXT: PhysicalAddress: 0x1000040
+# CHECK-NEXT: FileSize: 224
+# CHECK-NEXT: MemSize: 224
+# CHECK-NEXT: Flags [ (0x4)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 8
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x1000000
+# CHECK-NEXT: PhysicalAddress: 0x1000000
+# CHECK-NEXT: FileSize: 288
+# CHECK-NEXT: MemSize: 288
+# CHECK-NEXT: Flags [ (0x4)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: VirtualAddress: 0x1001000
+# CHECK-NEXT: PhysicalAddress: 0x1001000
+# CHECK-NEXT: FileSize: 1
+# CHECK-NEXT: MemSize: 1
+# CHECK-NEXT: Flags [ (0x5)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_X (0x1)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [ (0x6)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_W (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 0
+# CHECK-NEXT: }
diff --git a/test/ELF/incompatible.s b/test/ELF/incompatible.s
index 1696d83de7ac..82055b7a104a 100644
--- a/test/ELF/incompatible.s
+++ b/test/ELF/incompatible.s
@@ -53,6 +53,7 @@
// ARCHIVE: a.o is incompatible with {{.*}}b.o
.global _start
_start:
+.data
.long foo
// REQUIRES: x86,aarch64
diff --git a/test/ELF/init-fini.s b/test/ELF/init-fini.s
index d2b24088d1e1..400679066636 100644
--- a/test/ELF/init-fini.s
+++ b/test/ELF/init-fini.s
@@ -35,7 +35,7 @@
// NOENTRY-NOT: FINI
// NOENTRY: ]
-.global _start,_init,_fini,_foo,_bar,_undef;
+.global _start,_init,_fini,_foo,_bar,_undef
_start:
_init = 0x11010
_fini = 0x11020
diff --git a/test/ELF/init_fini_priority.s b/test/ELF/init_fini_priority.s
new file mode 100644
index 000000000000..84e5dc35e9d2
--- /dev/null
+++ b/test/ELF/init_fini_priority.s
@@ -0,0 +1,37 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %t.exe
+// RUN: llvm-objdump -s %t.exe | FileCheck %s
+// REQUIRES: x86
+
+.globl _start
+_start:
+ nop
+
+.section .init_array, "aw", @init_array
+ .align 8
+ .byte 1
+.section .init_array.100, "aw", @init_array
+ .long 2
+.section .init_array.5, "aw", @init_array
+ .byte 3
+.section .init_array, "aw", @init_array
+ .byte 4
+.section .init_array, "aw", @init_array
+ .byte 5
+
+.section .fini_array, "aw", @fini_array
+ .align 8
+ .byte 0x11
+.section .fini_array.100, "aw", @fini_array
+ .long 0x12
+.section .fini_array.5, "aw", @fini_array
+ .byte 0x13
+.section .fini_array, "aw", @fini_array
+ .byte 0x14
+.section .fini_array, "aw", @fini_array
+ .byte 0x15
+
+// CHECK: Contents of section .init_array:
+// CHECK-NEXT: 03020000 00000000 010405
+// CHECK: Contents of section .fini_array:
+// CHECK-NEXT: 13120000 00000000 111415
diff --git a/test/ELF/invalid-cie-length.s b/test/ELF/invalid-cie-length.s
index 36d1e03fb567..e9ad3ca8ba82 100644
--- a/test/ELF/invalid-cie-length.s
+++ b/test/ELF/invalid-cie-length.s
@@ -6,4 +6,4 @@
.section .eh_frame
.byte 0
-// CHECK: Truncated CIE/FDE length
+// CHECK: CIE/FDE too small
diff --git a/test/ELF/invalid-cie-length3.s b/test/ELF/invalid-cie-length3.s
index 8f3ab1cf29d0..665fc80a24b4 100644
--- a/test/ELF/invalid-cie-length3.s
+++ b/test/ELF/invalid-cie-length3.s
@@ -6,4 +6,4 @@
.section .eh_frame
.long 0xFFFFFFFC
-// CHECK: CIE/FIE size is too large
+// CHECK: CIE/FIE ends past the end of the section
diff --git a/test/ELF/invalid-cie-length4.s b/test/ELF/invalid-cie-length4.s
index 4a51ca1f812d..daa20d196811 100644
--- a/test/ELF/invalid-cie-length4.s
+++ b/test/ELF/invalid-cie-length4.s
@@ -7,4 +7,4 @@
.long 0xFFFFFFFF
.byte 0
-// CHECK: Truncated CIE/FDE length
+// CHECK: CIE/FDE too large
diff --git a/test/ELF/invalid-cie-length5.s b/test/ELF/invalid-cie-length5.s
index 14054a2dee84..bfa35edf7db5 100644
--- a/test/ELF/invalid-cie-length5.s
+++ b/test/ELF/invalid-cie-length5.s
@@ -7,4 +7,4 @@
.long 0xFFFFFFFF
.quad 0xFFFFFFFFFFFFFFF4
-// CHECK: CIE/FIE size is too large
+// CHECK: CIE/FDE too large
diff --git a/test/ELF/invalid-cie-reference.s b/test/ELF/invalid-cie-reference.s
index 1b099d19b7e1..fba2467e216a 100644
--- a/test/ELF/invalid-cie-reference.s
+++ b/test/ELF/invalid-cie-reference.s
@@ -29,4 +29,4 @@
.long 0x0
.long 0x0
-// CHECK: Invalid CIE reference
+// CHECK: invalid CIE reference
diff --git a/test/ELF/invalid-dynamic-list.test b/test/ELF/invalid-dynamic-list.test
new file mode 100644
index 000000000000..0e7c820f563e
--- /dev/null
+++ b/test/ELF/invalid-dynamic-list.test
@@ -0,0 +1,37 @@
+## Different "echo" commands on Windows interpret quoted strings and
+## wildcards in similar but different way (On Windows, ARGV tokenization
+## and wildcard expansion are not done by the shell but by each command.)
+## Because of that reason, this test fails on some Windows environment.
+## We can't write quoted strings that are interpreted the same way
+## by all echo commands. So, we don't want to run this on Windows.
+
+# REQUIRES: shell
+
+# RUN: mkdir -p %t.dir
+
+# RUN: echo foobar > %t1
+# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR1 %s
+# ERR1: line 1: { expected, but got foobar
+
+# RUN: echo "{ foobar;" > %t1
+# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR2 %s
+# ERR2: line 1: unexpected EOF
+
+## Missing ';' before '}'
+# RUN: echo "{ foobar }" > %t1
+# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR3 %s
+# ERR3: line 1: ; expected, but got }
+
+## Missing final ';'
+# RUN: echo "{ foobar; }" > %t1
+# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR4 %s
+# ERR4: line 1: unexpected EOF
+
+## Missing \" in foobar definition
+# RUN echo "{ \"foobar; };" > %t1
+# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR5 %s
+# ERR5: line 1: unexpected EOF
+
+# RUN: echo "{ extern \"BOGUS\" { test }; };" > %t1
+# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR6 %s
+# ERR6: line 1: ; expected, but got BOGUS
diff --git a/test/ELF/invalid-elf.test b/test/ELF/invalid-elf.test
index 05e95cab0d27..c3a97d37ffa9 100644
--- a/test/ELF/invalid-elf.test
+++ b/test/ELF/invalid-elf.test
@@ -2,26 +2,27 @@
# RUN: not ld.lld %t %p/Inputs/invalid-data-encoding.a -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=INVALID-DATA-ENC %s
-# INVALID-DATA-ENC: Invalid data encoding: test.o
+# INVALID-DATA-ENC: invalid data encoding: test.o
# RUN: not ld.lld %t %p/Inputs/invalid-file-class.a -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=INVALID-FILE-CLASS %s
-# INVALID-FILE-CLASS: Invalid file class: test.o
+# INVALID-FILE-CLASS: invalid file class: test.o
# RUN: not ld.lld %p/Inputs/invalid-symtab-sh_info.elf -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=INVALID-SYMTAB-SHINFO %s
-# INVALID-SYMTAB-SHINFO: Invalid sh_info in symbol table
+# INVALID-SYMTAB-SHINFO: invalid sh_info in symbol table
# RUN: not ld.lld %p/Inputs/invalid-binding.elf -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=INVALID-BINDING %s
# INVALID-BINDING: unexpected binding
# RUN: not ld.lld %p/Inputs/invalid-section-index.elf -o %t2 2>&1 | \
-# RUN: FileCheck --check-prefix=INVALID-SECTION-INDEX %s
-# INVALID-SECTION-INDEX: Invalid section index
+# RUN: FileCheck --check-prefix=INVALID-SECTION-INDEX-LLD %s
+# INVALID-SECTION-INDEX-LLD: invalid section index
# RUN: not ld.lld %p/Inputs/invalid-shstrndx.so -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=INVALID-SECTION-INDEX %s
+# INVALID-SECTION-INDEX: Invalid section index
# RUN: not ld.lld %p/Inputs/invalid-shentsize-zero.elf -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=INVALID-SHENTSIZE-ZERO %s
@@ -29,6 +30,6 @@
# RUN: not ld.lld %p/Inputs/invalid-multiple-eh-relocs.elf -o %t2 2>&1 | \
# RUN: FileCheck --check-prefix=INVALID-EH-RELOCS %s
-# INVALID-EH-RELOCS: Multiple relocation sections to .eh_frame are not supported
+# INVALID-EH-RELOCS: multiple relocation sections to .eh_frame are not supported
.long foo
diff --git a/test/ELF/invalid-linkerscript.test b/test/ELF/invalid-linkerscript.test
new file mode 100644
index 000000000000..e0881662b962
--- /dev/null
+++ b/test/ELF/invalid-linkerscript.test
@@ -0,0 +1,54 @@
+## Different "echo" commands on Windows interpret quoted strings and
+## wildcards in similar but different way (On Windows, ARGV tokenization
+## and wildcard expansion are not done by the shell but by each command.)
+## Because of that reason, this test fails on some Windows environment.
+## We can't write quoted strings that are interpreted the same way
+## by all echo commands. So, we don't want to run this on Windows.
+
+# REQUIRES: shell
+
+# RUN: mkdir -p %t.dir
+
+## Note that we are using "cannot open no-such-file: " as a marker that the
+## linker keep going when it found an error. That specific error message is not
+## related to the linker script tests.
+
+# RUN: echo foobar > %t1
+# RUN: not ld.lld %t1 no-such-file 2>&1 | FileCheck -check-prefix=ERR1 %s
+# ERR1: unknown directive: foobar
+# ERR1: cannot open no-such-file:
+
+# RUN: echo "foo \"bar" > %t2
+# RUN: not ld.lld %t2 no-such-file 2>&1 | FileCheck -check-prefix=ERR2 %s
+# ERR2: unclosed quote
+# ERR2: cannot open no-such-file:
+
+# RUN: echo "/*" > %t3
+# RUN: not ld.lld %t3 no-such-file 2>&1 | FileCheck -check-prefix=ERR3 %s
+# ERR3: unclosed comment
+# ERR3: cannot open no-such-file:
+
+# RUN: echo "EXTERN (" > %t4
+# RUN: not ld.lld %t4 no-such-file 2>&1 | FileCheck -check-prefix=ERR4 %s
+# ERR4: unexpected EOF
+# ERR4: cannot open no-such-file:
+
+# RUN: echo "EXTERN (" > %t5
+# RUN: not ld.lld %t5 no-such-file 2>&1 | FileCheck -check-prefix=ERR5 %s
+# ERR5: unexpected EOF
+# ERR5: cannot open no-such-file:
+
+# RUN: echo "EXTERN xyz" > %t6
+# RUN: not ld.lld %t6 no-such-file 2>&1 | FileCheck -check-prefix=ERR6 %s
+# ERR6: ( expected, but got xyz
+# ERR6: cannot open no-such-file:
+
+# RUN: echo "INCLUDE /no/such/file" > %t7
+# RUN: not ld.lld %t7 no-such-file 2>&1 | FileCheck -check-prefix=ERR7 %s
+# ERR7: cannot open /no/such/file
+# ERR7: cannot open no-such-file:
+
+# RUN: echo "OUTPUT_FORMAT(x y z)" > %t8
+# RUN: not ld.lld %t8 no-such-file 2>&1 | FileCheck -check-prefix=ERR8 %s
+# ERR8: unexpected token: y
+# ERR8: cannot open no-such-file:
diff --git a/test/ELF/invalid-relocations.test b/test/ELF/invalid-relocations.test
index 2b4a6c4a4210..cfeb44b03c67 100644
--- a/test/ELF/invalid-relocations.test
+++ b/test/ELF/invalid-relocations.test
@@ -1,6 +1,7 @@
-# RUN: yaml2obj -format elf %s -o %t
+# RUN: yaml2obj %s -o %t
# RUN: not ld.lld %t -o %tout 2>&1 | FileCheck %s
+!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
@@ -19,4 +20,4 @@ Symbols:
Global:
- Name: lulz
-# CHECK: Invalid relocated section index
+# CHECK: invalid relocated section index
diff --git a/test/ELF/libsearch.s b/test/ELF/libsearch.s
index c965b9ba91fc..782d755f7341 100644
--- a/test/ELF/libsearch.s
+++ b/test/ELF/libsearch.s
@@ -23,7 +23,7 @@
// Should fail if cannot find specified library (without -L switch)
// RUN: not ld.lld -o %t3 %t.o -lls 2>&1 \
// RUN: | FileCheck --check-prefix=NOLIB %s
-// NOLIB: Unable to find library -lls
+// NOLIB: unable to find library -lls
// Should use explicitly specified static library
// Also ensure that we accept -L <arg>
@@ -44,6 +44,12 @@
// RUN: ld.lld -o %t3 %t.o -L%t.dir -lls
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+// Check for library search order
+// RUN: mkdir -p %t.dir2
+// RUN: cp %t.dir/libls.a %t.dir2
+// RUN: ld.lld -o %t3 %t.o -L%t.dir2 -L%t.dir -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+
// -L can be placed after -l
// RUN: ld.lld -o %t3 %t.o -lls -L%t.dir
@@ -55,7 +61,7 @@
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
// RUN: not ld.lld -o %t3 %t.o -L%t.dir -Bstatic -lls2 2>&1 \
// RUN: | FileCheck --check-prefix=NOLIB2 %s
-// NOLIB2: Unable to find library -lls2
+// NOLIB2: unable to find library -lls2
// -Bdynamic should restore default behaviour
// RUN: ld.lld -o %t3 %t.o -L%t.dir -Bstatic -Bdynamic -lls
@@ -79,5 +85,5 @@
// RUN: ld.lld -o %t3 %t.o -L%t.dir -Bstatic -call_shared -lls
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
-.globl _start,_bar;
+.globl _start,_bar
_start:
diff --git a/test/ELF/linkerscript-align.s b/test/ELF/linkerscript-align.s
new file mode 100644
index 000000000000..5f6e6f770766
--- /dev/null
+++ b/test/ELF/linkerscript-align.s
@@ -0,0 +1,41 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS { \
+# RUN: . = 0x10000; \
+# RUN: .aaa : \
+# RUN: { \
+# RUN: *(.aaa) \
+# RUN: } \
+# RUN: . = ALIGN(4096); \
+# RUN: .bbb : \
+# RUN: { \
+# RUN: *(.bbb) \
+# RUN: } \
+# RUN: . = ALIGN(4096 * 4); \
+# RUN: .ccc : \
+# RUN: { \
+# RUN: *(.ccc) \
+# RUN: } \
+# RUN: }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK: Sections:
+# CHECK-NEXT: Idx Name Size Address Type
+# CHECK-NEXT: 0 00000000 0000000000000000
+# CHECK-NEXT: 1 .aaa 00000008 0000000000010000 DATA
+# CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA
+# CHECK-NEXT: 3 .ccc 00000008 0000000000014000 DATA
+
+.global _start
+_start:
+ nop
+
+.section .aaa, "a"
+.quad 0
+
+.section .bbb, "a"
+.quad 0
+
+.section .ccc, "a"
+.quad 0
diff --git a/test/ELF/linkerscript-diagnostic.s b/test/ELF/linkerscript-diagnostic.s
new file mode 100644
index 000000000000..f42cbe82cf38
--- /dev/null
+++ b/test/ELF/linkerscript-diagnostic.s
@@ -0,0 +1,66 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## Take some valid script with multiline comments
+## and check it actually works:
+# RUN: echo "SECTIONS {" > %t.script
+# RUN: echo ".text : { *(.text) }" >> %t.script
+# RUN: echo ".keep : { *(.keep) } /*" >> %t.script
+# RUN: echo "comment line 1" >> %t.script
+# RUN: echo "comment line 2 */" >> %t.script
+# RUN: echo ".temp : { *(.temp) } }" >> %t.script
+# RUN: ld.lld -shared %t -o %t1 --script %t.script
+
+## Change ":" to "+" at line 2, check that error
+## message starts from correct line number:
+# RUN: echo "SECTIONS {" > %t.script
+# RUN: echo ".text + { *(.text) }" >> %t.script
+# RUN: echo ".keep : { *(.keep) } /*" >> %t.script
+# RUN: echo "comment line 1" >> %t.script
+# RUN: echo "comment line 2 */" >> %t.script
+# RUN: echo ".temp : { *(.temp) } }" >> %t.script
+# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR1 %s
+# ERR1: line 2:
+
+## Change ":" to "+" at line 3 now, check correct error line number:
+# RUN: echo "SECTIONS {" > %t.script
+# RUN: echo ".text : { *(.text) }" >> %t.script
+# RUN: echo ".keep + { *(.keep) } /*" >> %t.script
+# RUN: echo "comment line 1" >> %t.script
+# RUN: echo "comment line 2 */" >> %t.script
+# RUN: echo ".temp : { *(.temp) } }" >> %t.script
+# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR2 %s
+# ERR2: line 3:
+
+## Change ":" to "+" at line 6, after multiline comment,
+## check correct error line number:
+# RUN: echo "SECTIONS {" > %t.script
+# RUN: echo ".text : { *(.text) }" >> %t.script
+# RUN: echo ".keep : { *(.keep) } /*" >> %t.script
+# RUN: echo "comment line 1" >> %t.script
+# RUN: echo "comment line 2 */" >> %t.script
+# RUN: echo ".temp + { *(.temp) } }" >> %t.script
+# RUN: not ld.lld -shared %t -o %t1 --script %t.script 2>&1 | FileCheck -check-prefix=ERR5 %s
+# ERR5: line 6:
+
+## Check that text of lines and pointer to 'bad' token are working ok.
+# RUN: echo "UNKNOWN_TAG {" > %t.script
+# RUN: echo ".text : { *(.text) }" >> %t.script
+# RUN: echo ".keep : { *(.keep) }" >> %t.script
+# RUN: echo ".temp : { *(.temp) } }" >> %t.script
+# RUN: not ld.lld -shared %t -o %t1 --script %t.script > %t.log 2>&1
+# RUN: FileCheck -check-prefix=ERR6 %s < %t.log
+# ERR6: line 1:
+# ERR6-NEXT: UNKNOWN_TAG {
+# RUN: grep '^^' %t.log
+
+## One more check that text of lines and pointer to 'bad' token are working ok.
+# RUN: echo "SECTIONS {" > %t.script
+# RUN: echo ".text : { *(.text) }" >> %t.script
+# RUN: echo ".keep : { *(.keep) }" >> %t.script
+# RUN: echo "boom .temp : { *(.temp) } }" >> %t.script
+# RUN: not ld.lld -shared %t -o %t1 --script %t.script > %t.log 2>&1
+# RUN: FileCheck -check-prefix=ERR7 %s < %t.log
+# ERR7: line 4: : expected, but got .temp
+# ERR7-NEXT: boom .temp : { *(.temp) } }
+# RUN: grep '^ ^' %t.log
diff --git a/test/ELF/linkerscript-locationcounter.s b/test/ELF/linkerscript-locationcounter.s
new file mode 100644
index 000000000000..c6e8e7ef8ea8
--- /dev/null
+++ b/test/ELF/linkerscript-locationcounter.s
@@ -0,0 +1,340 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: echo "SECTIONS { \
+# RUN: . = 0xFFF0; \
+# RUN: . = . + 0x10; \
+# RUN: .plus : { *(.plus) } \
+# RUN: . = 0x11010 - 0x10; \
+# RUN: .minus : { *(.minus) } \
+# RUN: . = 0x24000 / 0x2; \
+# RUN: .div : { *(.div) } \
+# RUN: . = 0x11000 + 0x1000 * 0x2; \
+# RUN: .mul : { *(.mul) } \
+# RUN: . = 0x10000 + (0x1000 + 0x1000) * 0x2; \
+# RUN: .bracket : { *(.bracket) } \
+# RUN: . = 0x17000 & 0x15000; \
+# RUN: .and : { *(.and) } \
+# RUN: . = 0x1 ? 0x16000 : 0x999999; \
+# RUN: .ternary1 : { *(.ternary1) } \
+# RUN: . = 0x0 ? 0x999999 : 0x17000; \
+# RUN: .ternary2 : { *(.ternary2) } \
+# RUN: . = 0x0 < 0x1 ? 0x18000 : 0x999999; \
+# RUN: .less : { *(.less) } \
+# RUN: . = 0x1 <= 0x1 ? 0x19000 : 0x999999; \
+# RUN: .lesseq : { *(.lesseq) } \
+# RUN: . = 0x1 > 0x0 ? 0x20000 : 0x999999; \
+# RUN: .great : { *(.great) } \
+# RUN: . = 0x1 >= 0x1 ? 0x21000 : 0x999999; \
+# RUN: .greateq : { *(.greateq) } \
+# RUN: . = 0x1 == 0x1 ? 0x22000 : 0x999999; \
+# RUN: .eq : { *(.eq) } \
+# RUN: . = 0x2 != 0x1 ? 0x23000 : 0x999999; \
+# RUN: .neq : { *(.neq) } \
+# RUN: }" > %t.script
+# RUN: ld.lld %t --script %t.script -o %t2
+# RUN: llvm-readobj -s %t2 | FileCheck %s
+
+# CHECK: Section {
+# CHECK: Index: 1
+# CHECK: Name: .plus
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x10000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .minus
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x11000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .div
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x12000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 4
+# CHECK-NEXT: Name: .mul
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x13000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 5
+# CHECK-NEXT: Name: .bracket
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x14000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .and
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x15000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .ternary1
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x16000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .ternary2
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x17000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .less
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x18000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .lesseq
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x19000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .great
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x20000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .greateq
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x21000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .eq
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x22000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index:
+# CHECK-NEXT: Name: .neq
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x23000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+
+## Mailformed number error.
+# RUN: echo "SECTIONS { \
+# RUN: . = 0x12Q41; \
+# RUN: }" > %t.script
+# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=NUMERR %s
+# NUMERR: malformed number: 0x12Q41
+
+## Missing closing bracket.
+# RUN: echo "SECTIONS { \
+# RUN: . = 0x10000 + (0x1000 + 0x1000 * 0x2; \
+# RUN: }" > %t.script
+# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=BRACKETERR %s
+# BRACKETERR: unexpected EOF
+
+## Missing opening bracket.
+# RUN: echo "SECTIONS { \
+# RUN: . = 0x10000 + 0x1000 + 0x1000) * 0x2; \
+# RUN: }" > %t.script
+# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=BRACKETERR2 %s
+# BRACKETERR2: stray token: )
+
+## Empty expression.
+# RUN: echo "SECTIONS { \
+# RUN: . = ; \
+# RUN: }" > %t.script
+# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=ERREXPR %s
+# ERREXPR: error in location counter expression
+
+## Div by zero error.
+# RUN: echo "SECTIONS { \
+# RUN: . = 0x10000 / 0x0; \
+# RUN: }" > %t.script
+# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=DIVZERO %s
+# DIVZERO: division by zero
+
+## Broken ternary operator expression.
+# RUN: echo "SECTIONS { \
+# RUN: . = 0x1 ? 0x2; \
+# RUN: }" > %t.script
+# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=TERNERR %s
+# TERNERR: unexpected EOF
+
+.globl _start
+_start:
+nop
+
+.section .plus, "a"
+.quad 0
+
+.section .minus, "a"
+.quad 0
+
+.section .div, "a"
+.quad 0
+
+.section .mul, "a"
+.quad 0
+
+.section .bracket, "a"
+.quad 0
+
+.section .and, "a"
+.quad 0
+
+.section .ternary1, "a"
+.quad 0
+
+.section .ternary2, "a"
+.quad 0
+
+.section .less, "a"
+.quad 0
+
+.section .lesseq, "a"
+.quad 0
+
+.section .great, "a"
+.quad 0
+
+.section .greateq, "a"
+.quad 0
+
+.section .eq, "a"
+.quad 0
+
+.section .neq, "a"
+.quad 0
diff --git a/test/ELF/linkerscript-orphans.s b/test/ELF/linkerscript-orphans.s
new file mode 100644
index 000000000000..fa7d30bf7f7c
--- /dev/null
+++ b/test/ELF/linkerscript-orphans.s
@@ -0,0 +1,31 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS { .writable : { *(.writable) } }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: llvm-objdump -section-headers %t.out | \
+# RUN: FileCheck -check-prefix=TEXTORPHAN %s
+
+# RUN: echo "SECTIONS { .text : { *(.text) } }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: llvm-objdump -section-headers %t.out | \
+# RUN: FileCheck -check-prefix=WRITABLEORPHAN %s
+
+# TEXTORPHAN: Sections:
+# TEXTORPHAN-NEXT: Idx Name
+# TEXTORPHAN-NEXT: 0
+# TEXTORPHAN-NEXT: 1 .writable
+# TEXTORPHAN-NEXT: 2 .text
+
+# WRITABLEORPHAN: Sections:
+# WRITABLEORPHAN-NEXT: Idx Name
+# WRITABLEORPHAN-NEXT: 0
+# WRITABLEORPHAN-NEXT: 1 .text
+# WRITABLEORPHAN-NEXT: 2 .writable
+
+.global _start
+_start:
+ nop
+
+.section .writable,"aw"
+ .zero 4
diff --git a/test/ELF/linkerscript-phdr-check.s b/test/ELF/linkerscript-phdr-check.s
new file mode 100644
index 000000000000..c7229ed3312c
--- /dev/null
+++ b/test/ELF/linkerscript-phdr-check.s
@@ -0,0 +1,15 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS { . = 0x10000000; .text : {*(.text.*)} }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-readobj -program-headers %t1 | FileCheck %s
+# CHECK: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_PHDR (0x6)
+# CHECK-NEXT: Offset: 0x40
+# CHECK-NEXT: VirtualAddress: 0xFFFF040
+
+.global _start
+_start:
+ nop
diff --git a/test/ELF/linkerscript-repsection-va.s b/test/ELF/linkerscript-repsection-va.s
new file mode 100644
index 000000000000..4feeaa0e1c38
--- /dev/null
+++ b/test/ELF/linkerscript-repsection-va.s
@@ -0,0 +1,24 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS {.foo : {*(.foo.*)} }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK: Sections:
+# CHECK-NEXT: Idx Name Size Address Type
+# CHECK-NEXT: 0 00000000 0000000000000000
+# CHECK-NEXT: 1 .foo 00000004 0000000000000158 DATA
+# CHECK-NEXT: 2 .foo 00000004 000000000000015c DATA
+# CHECK-NEXT: 3 .text 00000001 0000000000000160 TEXT DATA
+
+.global _start
+_start:
+ nop
+
+.section .foo.1,"a"
+foo1:
+ .long 0
+
+.section .foo.2,"aw"
+foo2:
+ .long 0
diff --git a/test/ELF/linkerscript-sections-keep.s b/test/ELF/linkerscript-sections-keep.s
new file mode 100644
index 000000000000..fae6383ca499
--- /dev/null
+++ b/test/ELF/linkerscript-sections-keep.s
@@ -0,0 +1,80 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## First check that section "keep" is garbage collected without using KEEP
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.text) } \
+# RUN: .keep : { *(.keep) } \
+# RUN: .temp : { *(.temp) }}" > %t.script
+# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | \
+# RUN: FileCheck -check-prefix=SECGC %s
+# SECGC: Sections:
+# SECGC-NEXT: Idx Name Size Address Type
+# SECGC-NEXT: 0 00000000 0000000000000000
+# SECGC-NEXT: 1 .text 00000007 0000000000000158 TEXT DATA
+# SECGC-NEXT: 2 .temp 00000004 000000000000015f DATA
+
+## Now apply KEEP command to preserve the section.
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.text) } \
+# RUN: .keep : { KEEP(*(.keep)) } \
+# RUN: .temp : { *(.temp) }}" > %t.script
+# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | \
+# RUN: FileCheck -check-prefix=SECNOGC %s
+# SECNOGC: Sections:
+# SECNOGC-NEXT: Idx Name Size Address Type
+# SECNOGC-NEXT: 0 00000000 0000000000000000
+# SECNOGC-NEXT: 1 .text 00000007 0000000000000158 TEXT DATA
+# SECNOGC-NEXT: 2 .keep 00000004 000000000000015f DATA
+# SECNOGC-NEXT: 3 .temp 00000004 0000000000000163 DATA
+
+## A section name matches two entries in the SECTIONS directive. The
+## first one doesn't have KEEP, the second one does. If section that have
+## KEEP is the first in order then section is NOT collected.
+# RUN: echo "SECTIONS { \
+# RUN: .keep : { KEEP(*(.keep)) } \
+# RUN: .nokeep : { *(.keep) }}" > %t.script
+# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=MIXED1 %s
+# MIXED1: Sections:
+# MIXED1-NEXT: Idx Name Size Address Type
+# MIXED1-NEXT: 0 00000000 0000000000000000
+# MIXED1-NEXT: 1 .keep 00000004 0000000000000120 DATA
+# MIXED1-NEXT: 2 .temp 00000004 0000000000000124 DATA
+# MIXED1-NEXT: 3 .text 00000007 0000000000000128 TEXT DATA
+# MIXED1-NEXT: 4 .symtab 00000060 0000000000000000
+# MIXED1-NEXT: 5 .shstrtab 0000002d 0000000000000000
+# MIXED1-NEXT: 6 .strtab 00000012 0000000000000000
+
+## The same, but now section without KEEP is at first place.
+## gold and bfd linkers disagree here. gold collects .keep while
+## bfd keeps it. Our current behavior is compatible with bfd although
+## we can choose either way.
+# RUN: echo "SECTIONS { \
+# RUN: .nokeep : { *(.keep) } \
+# RUN: .keep : { KEEP(*(.keep)) }}" > %t.script
+# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=MIXED2 %s
+# MIXED2: Sections:
+# MIXED2-NEXT: Idx Name Size Address Type
+# MIXED2-NEXT: 0 00000000 0000000000000000
+# MIXED2-NEXT: 1 .nokeep 00000004 0000000000000120 DATA
+# MIXED2-NEXT: 2 .temp 00000004 0000000000000124 DATA
+# MIXED2-NEXT: 3 .text 00000007 0000000000000128 TEXT DATA
+# MIXED2-NEXT: 4 .symtab 00000060 0000000000000000
+# MIXED2-NEXT: 5 .shstrtab 0000002f 0000000000000000
+# MIXED2-NEXT: 6 .strtab 00000012 0000000000000000
+
+.global _start
+_start:
+ mov temp, %eax
+
+.section .keep, "a"
+keep:
+ .long 1
+
+.section .temp, "a"
+temp:
+ .long 2
diff --git a/test/ELF/linkerscript-sections-padding.s b/test/ELF/linkerscript-sections-padding.s
new file mode 100644
index 000000000000..545739efe5a8
--- /dev/null
+++ b/test/ELF/linkerscript-sections-padding.s
@@ -0,0 +1,44 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## Check that padding value works:
+# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x112233445566778899 }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: hexdump -C %t.out | FileCheck -check-prefix=YES %s
+# YES: 00000120 66 22 33 44 55 66 77 88 99 11 22 33 44 55 66 77
+
+## Confirming that address was correct:
+# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x998877665544332211 }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: hexdump -C %t.out | FileCheck -check-prefix=YES2 %s
+# YES2: 00000120 66 88 77 66 55 44 33 22 11 99 88 77 66 55 44
+
+## Default padding value is 0x00:
+# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: hexdump -C %t.out | FileCheck -check-prefix=NO %s
+# NO: 00000120 66 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+## Filler should be a hex value (1):
+# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =99 }" > %t.script
+# RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 \
+# RUN: | FileCheck --check-prefix=ERR %s
+# ERR: filler should be a hexadecimal value
+
+## Filler should be a hex value (2):
+# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99XX }" > %t.script
+# RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 \
+# RUN: | FileCheck --check-prefix=ERR2 %s
+# ERR2: not a hexadecimal value: XX
+
+.section .mysec.1,"a"
+.align 16
+.byte 0x66
+
+.section .mysec.2,"a"
+.align 16
+.byte 0x66
+
+.globl _start
+_start:
+ nop
diff --git a/test/ELF/linkerscript-sections.s b/test/ELF/linkerscript-sections.s
index 165ec335ec13..b68dac765a77 100644
--- a/test/ELF/linkerscript-sections.s
+++ b/test/ELF/linkerscript-sections.s
@@ -22,7 +22,7 @@
# SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}}
-# SEC-DEFAULT: 7 .shstrtab 0000003c {{[0-9a-f]*}}
+# SEC-DEFAULT: 7 .shstrtab 00000032 {{[0-9a-f]*}}
# SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}}
# Sections are put in order specified in linker script.
@@ -42,7 +42,7 @@
# SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
# SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}}
-# SEC-ORDER: 4 .shstrtab 0000003c {{[0-9a-f]*}}
+# SEC-ORDER: 4 .shstrtab 00000032 {{[0-9a-f]*}}
# SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}}
# SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}}
# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA
@@ -63,7 +63,7 @@
# SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}}
-# SEC-SWAP-NAMES: 7 .shstrtab 0000003c {{[0-9a-f]*}}
+# SEC-SWAP-NAMES: 7 .shstrtab 00000032 {{[0-9a-f]*}}
# SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}}
# .shstrtab from the input object file is discarded.
@@ -100,10 +100,10 @@
# SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-MULTI: 5 .symtab 00000030 {{[0-9a-f]*}}
-# SEC-MULTI: 6 .shstrtab 00000036 {{[0-9a-f]*}}
+# SEC-MULTI: 6 .shstrtab 0000002c {{[0-9a-f]*}}
# SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}}
-.globl _start;
+.globl _start
_start:
mov $60, %rax
mov $42, %rdi
diff --git a/test/ELF/linkerscript-symbol-conflict.s b/test/ELF/linkerscript-symbol-conflict.s
new file mode 100644
index 000000000000..30186ed5cb87
--- /dev/null
+++ b/test/ELF/linkerscript-symbol-conflict.s
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS {.text : {*(.text.*)} end = .;}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck %s
+# CHECK: 0000000000000121 *ABS* 00000000 end
+
+.global _start
+_start:
+ nop
diff --git a/test/ELF/linkerscript-symbols.s b/test/ELF/linkerscript-symbols.s
new file mode 100644
index 000000000000..1fcd4e8a8481
--- /dev/null
+++ b/test/ELF/linkerscript-symbols.s
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck %s
+# CHECK: 0000000000000121 *ABS* 00000000 text_end
+
+.global _start
+_start:
+ nop
diff --git a/test/ELF/linkerscript-va.s b/test/ELF/linkerscript-va.s
new file mode 100644
index 000000000000..25d0bd2268c0
--- /dev/null
+++ b/test/ELF/linkerscript-va.s
@@ -0,0 +1,24 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS {}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK: Sections:
+# CHECK-NEXT: Idx Name Size Address Type
+# CHECK-NEXT: 0 00000000 0000000000000000
+# CHECK-NEXT: 1 .foo 00000004 0000000000000120 DATA
+# CHECK-NEXT: 2 .boo 00000004 0000000000000124 DATA
+# CHECK-NEXT: 3 .text 00000001 0000000000000128 TEXT DATA
+
+.global _start
+_start:
+ nop
+
+.section .foo, "a"
+foo:
+ .long 0
+
+.section .boo, "a"
+boo:
+ .long 0
diff --git a/test/ELF/linkerscript.s b/test/ELF/linkerscript.s
index bff285b97612..4ee7416a4b84 100644
--- a/test/ELF/linkerscript.s
+++ b/test/ELF/linkerscript.s
@@ -1,3 +1,9 @@
+# There is some bad quoting interaction between lit's internal shell, which is
+# implemented in Python, and the Cygwin implementations of the Unix utilities.
+# Avoid running these tests on Windows for now by requiring a real shell.
+
+# REQUIRES: shell
+
# REQUIRES: x86
# RUN: mkdir -p %t.dir
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
@@ -10,43 +16,43 @@
# RUN: ld.lld %t -o %t2 %t.script
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "GROUP(" %t ")" > %t.script
+# RUN: echo "GROUP(\"%t\")" > %t.script
# RUN: ld.lld -o %t2 %t.script
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "INPUT(" %t ")" > %t.script
+# RUN: echo "INPUT(\"%t\")" > %t.script
# RUN: ld.lld -o %t2 %t.script
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "GROUP(" %t libxyz.a ")" > %t.script
+# RUN: echo "GROUP(\"%t\" libxyz.a )" > %t.script
# RUN: not ld.lld -o %t2 %t.script
# RUN: ld.lld -o %t2 %t.script -L%t.dir
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "GROUP(" %t =libxyz.a ")" > %t.script
+# RUN: echo "GROUP(\"%t\" =libxyz.a )" > %t.script
# RUN: not ld.lld -o %t2 %t.script
# RUN: ld.lld -o %t2 %t.script --sysroot=%t.dir
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "GROUP(" %t -lxyz ")" > %t.script
+# RUN: echo "GROUP(\"%t\" -lxyz )" > %t.script
# RUN: not ld.lld -o %t2 %t.script
# RUN: ld.lld -o %t2 %t.script -L%t.dir
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "GROUP(" %t libxyz.a ")" > %t.script
+# RUN: echo "GROUP(\"%t\" libxyz.a )" > %t.script
# RUN: not ld.lld -o %t2 %t.script
# RUN: ld.lld -o %t2 %t.script -L%t.dir
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "GROUP(" %t /libxyz.a ")" > %t.script
-# RUN: echo "GROUP(" %t /libxyz.a ")" > %t.dir/xyz.script
+# RUN: echo "GROUP(\"%t\" /libxyz.a )" > %t.script
+# RUN: echo "GROUP(\"%t\" /libxyz.a )" > %t.dir/xyz.script
# RUN: not ld.lld -o %t2 %t.script
# RUN: not ld.lld -o %t2 %t.script --sysroot=%t.dir
# RUN: ld.lld -o %t2 %t.dir/xyz.script --sysroot=%t.dir
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "GROUP(" %t.script2 ")" > %t.script1
-# RUN: echo "GROUP(" %t ")" > %t.script2
+# RUN: echo "GROUP(\"%t.script2\")" > %t.script1
+# RUN: echo "GROUP(\"%t\")" > %t.script2
# RUN: ld.lld -o %t2 %t.script1
# RUN: llvm-readobj %t2 > /dev/null
@@ -70,16 +76,16 @@
# ENTRY-OVERLOAD: Name: _start
# ENTRY-OVERLOAD-NEXT: Value: [[ENTRY]]
-# RUN: echo "OUTPUT_FORMAT(\"elf64-x86-64\") /*/*/ GROUP(" %t ")" > %t.script
+# RUN: echo "OUTPUT_FORMAT(elf64-x86-64) /*/*/ GROUP(\"%t\" )" > %t.script
# RUN: ld.lld -o %t2 %t.script
# RUN: llvm-readobj %t2 > /dev/null
-# RUN: echo "GROUP(AS_NEEDED(" %t "))" > %t.script
+# RUN: echo "GROUP(AS_NEEDED(\"%t\"))" > %t.script
# RUN: ld.lld -o %t2 %t.script
# RUN: llvm-readobj %t2 > /dev/null
# RUN: rm -f %t.out
-# RUN: echo "OUTPUT(" %t.out ")" > %t.script
+# RUN: echo "OUTPUT(\"%t.out\")" > %t.script
# RUN: ld.lld %t.script %t
# RUN: llvm-readobj %t.out > /dev/null
@@ -95,8 +101,8 @@
# RUN: ld.lld %t.script %t
# RUN: llvm-readobj %t.out > /dev/null
-# RUN: echo "INCLUDE " %t.script2 "OUTPUT(" %t.out ")" > %t.script1
-# RUN: echo "GROUP(" %t ")" > %t.script2
+# RUN: echo "INCLUDE \"%t.script2\" OUTPUT(\"%t.out\")" > %t.script1
+# RUN: echo "GROUP(\"%t\")" > %t.script2
# RUN: ld.lld %t.script1
# RUN: llvm-readobj %t2 > /dev/null
@@ -106,7 +112,7 @@
# ERR1: unknown directive: FOO
-.globl _start, _label;
+.globl _start, _label
_start:
mov $60, %rax
mov $42, %rdi
diff --git a/test/ELF/linkerscript2.s b/test/ELF/linkerscript2.s
index f83198f759fd..6ecd9e7ea975 100644
--- a/test/ELF/linkerscript2.s
+++ b/test/ELF/linkerscript2.s
@@ -1,10 +1,16 @@
+# There is some bad quoting interaction between lit's internal shell, which is
+# implemented in Python, and the Cygwin implementations of the Unix utilities.
+# Avoid running these tests on Windows for now by requiring a real shell.
+
+# REQUIRES: shell
+
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd \
# RUN: %p/Inputs/libsearch-dyn.s -o %tdyn.o
# RUN: mkdir -p %t.dir
# RUN: ld.lld -shared %tdyn.o -o %t.dir/libls.so
-# RUN: echo "SEARCH_DIR(" %t.dir ")" > %t.script
+# RUN: echo "SEARCH_DIR(\"%t.dir\")" > %t.script
# RUN: ld.lld -o %t2 --script %t.script -lls %t
.globl _start,_bar
diff --git a/test/ELF/lit.local.cfg b/test/ELF/lit.local.cfg
index 0011e796e5f4..b93a36d2b50b 100644
--- a/test/ELF/lit.local.cfg
+++ b/test/ELF/lit.local.cfg
@@ -1,2 +1,2 @@
-config.suffixes = ['.test', '.s']
+config.suffixes = ['.test', '.s', '.ll']
diff --git a/test/ELF/llvm33-rela-outside-group.s b/test/ELF/llvm33-rela-outside-group.s
new file mode 100644
index 000000000000..8e7e7c4e6a4d
--- /dev/null
+++ b/test/ELF/llvm33-rela-outside-group.s
@@ -0,0 +1,11 @@
+// Input file generated with:
+// llvm33/llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %S/Inputs/llvm33-rela-outside-group.o
+//
+// RUN: ld.lld -shared %S/Inputs/llvm33-rela-outside-group.o %S/Inputs/llvm33-rela-outside-group.o
+
+ .global bar
+ .weak _Z3fooIiEvv
+
+ .section .text._Z3fooIiEvv,"axG",@progbits,_Z3fooIiEvv,comdat
+_Z3fooIiEvv:
+ callq bar@PLT
diff --git a/test/ELF/local-dynamic.s b/test/ELF/local-dynamic.s
index 162c58cb57ed..436516a91190 100644
--- a/test/ELF/local-dynamic.s
+++ b/test/ELF/local-dynamic.s
@@ -42,6 +42,17 @@
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _DYNAMIC
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .dynamic
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: _start
// CHECK-NEXT: Value: 0x1000
// CHECK-NEXT: Size: 0
diff --git a/test/ELF/local-got-pie.s b/test/ELF/local-got-pie.s
new file mode 100644
index 000000000000..e846bd454445
--- /dev/null
+++ b/test/ELF/local-got-pie.s
@@ -0,0 +1,36 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t -pie
+// RUN: llvm-readobj -s -r %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+
+.globl _start
+_start:
+ call foo@gotpcrel
+
+ .hidden foo
+ .global foo
+foo:
+ nop
+
+// 0x20A0 - 1001 - 5 = 4250
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+// DISASM-NEXT: 1000: {{.*}} callq 4251
+// DISASM: foo:
+// DISASM-NEXT: 1005: {{.*}} nop
+
+// CHECK: Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x20A0
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 8
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x20A0 R_X86_64_RELATIVE - 0x1005
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/local-undefined-symbol.s b/test/ELF/local-undefined-symbol.s
new file mode 100644
index 000000000000..34ef847180ae
--- /dev/null
+++ b/test/ELF/local-undefined-symbol.s
@@ -0,0 +1,13 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t1
+# RUN: llvm-readobj -t %t1 | FileCheck %s
+
+# CHECK: Symbols [
+# CHECK-NOT: Name: foo
+
+.global _start
+_start:
+ jmp foo
+
+.local foo
diff --git a/test/ELF/lto/Inputs/archive-2.ll b/test/ELF/lto/Inputs/archive-2.ll
new file mode 100644
index 000000000000..8236cfe5cd84
--- /dev/null
+++ b/test/ELF/lto/Inputs/archive-2.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/archive-3.ll b/test/ELF/lto/Inputs/archive-3.ll
new file mode 100644
index 000000000000..ad8fb1e33ef2
--- /dev/null
+++ b/test/ELF/lto/Inputs/archive-3.ll
@@ -0,0 +1,5 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+define void @foo() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/archive.ll b/test/ELF/lto/Inputs/archive.ll
new file mode 100644
index 000000000000..71c1e4f35600
--- /dev/null
+++ b/test/ELF/lto/Inputs/archive.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/available-externally.ll b/test/ELF/lto/Inputs/available-externally.ll
new file mode 100644
index 000000000000..b8583eab829d
--- /dev/null
+++ b/test/ELF/lto/Inputs/available-externally.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @zed() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/comdat.s b/test/ELF/lto/Inputs/comdat.s
new file mode 100644
index 000000000000..6f6e5ae1d9df
--- /dev/null
+++ b/test/ELF/lto/Inputs/comdat.s
@@ -0,0 +1,5 @@
+ .section .text.f,"axG",@progbits,c,comdat
+ .globl foo
+
+foo:
+ retq
diff --git a/test/ELF/lto/Inputs/common.s b/test/ELF/lto/Inputs/common.s
new file mode 100644
index 000000000000..e2cd9e6d50c3
--- /dev/null
+++ b/test/ELF/lto/Inputs/common.s
@@ -0,0 +1 @@
+ .comm a,8,4
diff --git a/test/ELF/lto/Inputs/drop-debug-info.bc b/test/ELF/lto/Inputs/drop-debug-info.bc
new file mode 100644
index 000000000000..f9c471f8e0d1
--- /dev/null
+++ b/test/ELF/lto/Inputs/drop-debug-info.bc
Binary files differ
diff --git a/test/ELF/lto/Inputs/drop-linkage.ll b/test/ELF/lto/Inputs/drop-linkage.ll
new file mode 100644
index 000000000000..0e3dc7a41421
--- /dev/null
+++ b/test/ELF/lto/Inputs/drop-linkage.ll
@@ -0,0 +1,12 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+$foo = comdat any
+define linkonce void @foo() comdat {
+ ret void
+}
+
+define void @bar() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/dynsym.s b/test/ELF/lto/Inputs/dynsym.s
new file mode 100644
index 000000000000..a69f870a1b60
--- /dev/null
+++ b/test/ELF/lto/Inputs/dynsym.s
@@ -0,0 +1,3 @@
+.globl foo
+foo:
+ret
diff --git a/test/ELF/lto/Inputs/internalize-exportdyn.ll b/test/ELF/lto/Inputs/internalize-exportdyn.ll
new file mode 100644
index 000000000000..21ac3580762c
--- /dev/null
+++ b/test/ELF/lto/Inputs/internalize-exportdyn.ll
@@ -0,0 +1,6 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define weak_odr void @bah() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/internalize-undef.ll b/test/ELF/lto/Inputs/internalize-undef.ll
new file mode 100644
index 000000000000..71c1e4f35600
--- /dev/null
+++ b/test/ELF/lto/Inputs/internalize-undef.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/irmover-error.ll b/test/ELF/lto/Inputs/irmover-error.ll
new file mode 100644
index 000000000000..86ed259b2a00
--- /dev/null
+++ b/test/ELF/lto/Inputs/irmover-error.ll
@@ -0,0 +1,6 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+!0 = !{ i32 1, !"foo", i32 2 }
+
+!llvm.module.flags = !{ !0 }
diff --git a/test/ELF/lto/Inputs/linkonce-odr.ll b/test/ELF/lto/Inputs/linkonce-odr.ll
new file mode 100644
index 000000000000..0b3828846eb5
--- /dev/null
+++ b/test/ELF/lto/Inputs/linkonce-odr.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define linkonce_odr void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/linkonce.ll b/test/ELF/lto/Inputs/linkonce.ll
new file mode 100644
index 000000000000..a6738b3ad71e
--- /dev/null
+++ b/test/ELF/lto/Inputs/linkonce.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define linkonce void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/resolution.s b/test/ELF/lto/Inputs/resolution.s
new file mode 100644
index 000000000000..60b7870efbf4
--- /dev/null
+++ b/test/ELF/lto/Inputs/resolution.s
@@ -0,0 +1,4 @@
+ .data
+ .global a
+a:
+ .long 9
diff --git a/test/ELF/lto/Inputs/save-temps.ll b/test/ELF/lto/Inputs/save-temps.ll
new file mode 100644
index 000000000000..d6e6eb661f33
--- /dev/null
+++ b/test/ELF/lto/Inputs/save-temps.ll
@@ -0,0 +1,6 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @bar() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/shared.s b/test/ELF/lto/Inputs/shared.s
new file mode 100644
index 000000000000..ab79ed131c3f
--- /dev/null
+++ b/test/ELF/lto/Inputs/shared.s
@@ -0,0 +1,7 @@
+.globl printf
+.type printf, @function
+printf:
+
+.globl puts
+.type puts, @function
+puts:
diff --git a/test/ELF/lto/Inputs/start-lib1.ll b/test/ELF/lto/Inputs/start-lib1.ll
new file mode 100644
index 000000000000..9f42e6afff0f
--- /dev/null
+++ b/test/ELF/lto/Inputs/start-lib1.ll
@@ -0,0 +1,8 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @bar()
+
+define void @foo() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/start-lib2.ll b/test/ELF/lto/Inputs/start-lib2.ll
new file mode 100644
index 000000000000..68b3c8362808
--- /dev/null
+++ b/test/ELF/lto/Inputs/start-lib2.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @bar() {
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/tls-mixed.s b/test/ELF/lto/Inputs/tls-mixed.s
new file mode 100644
index 000000000000..b31ae3dd54d1
--- /dev/null
+++ b/test/ELF/lto/Inputs/tls-mixed.s
@@ -0,0 +1,4 @@
+.globl foo
+.section .tbss,"awT",@nobits
+foo:
+.long 0
diff --git a/test/ELF/lto/Inputs/type-merge.ll b/test/ELF/lto/Inputs/type-merge.ll
new file mode 100644
index 000000000000..c31642105f3a
--- /dev/null
+++ b/test/ELF/lto/Inputs/type-merge.ll
@@ -0,0 +1,8 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @zed() {
+ call void @bar()
+ ret void
+}
+declare void @bar()
diff --git a/test/ELF/lto/Inputs/type-merge2.ll b/test/ELF/lto/Inputs/type-merge2.ll
new file mode 100644
index 000000000000..79fd1f886306
--- /dev/null
+++ b/test/ELF/lto/Inputs/type-merge2.ll
@@ -0,0 +1,8 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%zed = type { i16 }
+define void @bar(%zed* %this) {
+ store %zed* %this, %zed** null
+ ret void
+}
diff --git a/test/ELF/lto/Inputs/undef-mixed.s b/test/ELF/lto/Inputs/undef-mixed.s
new file mode 100644
index 000000000000..2e4b7e114bb5
--- /dev/null
+++ b/test/ELF/lto/Inputs/undef-mixed.s
@@ -0,0 +1,3 @@
+ .globl bar
+bar:
+ retq
diff --git a/test/ELF/lto/Inputs/unnamed-addr-lib.s b/test/ELF/lto/Inputs/unnamed-addr-lib.s
new file mode 100644
index 000000000000..e6ebce024f05
--- /dev/null
+++ b/test/ELF/lto/Inputs/unnamed-addr-lib.s
@@ -0,0 +1,6 @@
+ .protected foo
+ .global foo
+foo:
+
+ .global bar
+bar:
diff --git a/test/ELF/lto/Inputs/visibility.s b/test/ELF/lto/Inputs/visibility.s
new file mode 100644
index 000000000000..db1379cc441f
--- /dev/null
+++ b/test/ELF/lto/Inputs/visibility.s
@@ -0,0 +1,8 @@
+ .global g
+g:
+ ret
+
+ .data
+ .global a
+a:
+ .long 41
diff --git a/test/ELF/lto/archive-2.ll b/test/ELF/lto/archive-2.ll
new file mode 100644
index 000000000000..6712d60c11e3
--- /dev/null
+++ b/test/ELF/lto/archive-2.ll
@@ -0,0 +1,28 @@
+; REQUIRES: x86
+; RUN: llvm-as %S/Inputs/archive-2.ll -o %t1.o
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.a -o %t3
+; RUN: llvm-readobj -t %t3 | FileCheck %s
+; RUN: ld.lld -m elf_x86_64 %t2.o --whole-archive %t.a -o %t3 -shared
+; RUN: llvm-readobj -t %t3 | FileCheck %s
+
+; CHECK: Name: _start (
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size:
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @g() {
+ call void @_start()
+ ret void
+}
+
+declare void @_start()
+
diff --git a/test/ELF/lto/archive-3.ll b/test/ELF/lto/archive-3.ll
new file mode 100644
index 000000000000..350c8929c9df
--- /dev/null
+++ b/test/ELF/lto/archive-3.ll
@@ -0,0 +1,19 @@
+; REQUIRES: x86
+; RUN: llvm-as %S/Inputs/archive-3.ll -o %t1.o
+; RUN: llvm-as %s -o %t2.o
+
+; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t3 -save-temps
+; RUN: llvm-dis %t3.lto.bc -o - | FileCheck %s
+
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+; RUN: ld.lld -m elf_x86_64 %t.a %t1.o %t2.o -o %t3 -save-temps
+; RUN: llvm-dis %t3.lto.bc -o - | FileCheck %s
+
+; CHECK: define internal void @foo() {
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/archive.ll b/test/ELF/lto/archive.ll
new file mode 100644
index 000000000000..b3f69fb9920f
--- /dev/null
+++ b/test/ELF/lto/archive.ll
@@ -0,0 +1,37 @@
+; REQUIRES: x86
+; RUN: llvm-as %S/Inputs/archive.ll -o %t1.o
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.a -o %t3 -shared
+; RUN: llvm-readobj -t %t3 | FileCheck %s
+; RUN: ld.lld -m elf_x86_64 %t2.o --whole-archive %t.a -o %t3 -shared
+; RUN: llvm-readobj -t %t3 | FileCheck %s
+
+
+; CHECK: Name: g (
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size:
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+; CHECK: Name: f (
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size:
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @g() {
+ call void @f()
+ ret void
+}
+
+declare void @f()
+
diff --git a/test/ELF/lto/asmundef.ll b/test/ELF/lto/asmundef.ll
new file mode 100644
index 000000000000..d76e418fce81
--- /dev/null
+++ b/test/ELF/lto/asmundef.ll
@@ -0,0 +1,25 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t -save-temps
+; RUN: llvm-dis %t.lto.bc -o - | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm ".weak patatino"
+module asm ".equ patatino, foo"
+
+declare void @patatino()
+
+define void @foo() {
+ ret void
+}
+
+define void @_start() {
+ call void @patatino()
+ ret void
+}
+
+; CHECK: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @foo to i8*)], section "llvm.metadata"
+; CHECK: define internal void @foo
+
diff --git a/test/ELF/lto/available-externally.ll b/test/ELF/lto/available-externally.ll
new file mode 100644
index 000000000000..74aa86002c9e
--- /dev/null
+++ b/test/ELF/lto/available-externally.ll
@@ -0,0 +1,22 @@
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-as %p/Inputs/available-externally.ll -o %t2.o
+; RUN: ld.lld %t1.o %t2.o -m elf_x86_64 -o %t.so -shared -save-temps
+; RUN: llvm-dis < %t.so.lto.bc | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo() {
+ call void @bar()
+ call void @zed()
+ ret void
+}
+define available_externally void @bar() {
+ ret void
+}
+define available_externally void @zed() {
+ ret void
+}
+
+; CHECK: define available_externally void @bar() {
+; CHECK: define void @zed() {
diff --git a/test/ELF/lto/combined-lto-object-name.ll b/test/ELF/lto/combined-lto-object-name.ll
new file mode 100644
index 000000000000..f5b7e3ae40e6
--- /dev/null
+++ b/test/ELF/lto/combined-lto-object-name.ll
@@ -0,0 +1,14 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: not ld.lld -m elf_x86_64 %t.o -o %t2 2>&1 | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @foo()
+define void @_start() {
+ call void @foo()
+ ret void
+}
+
+; CHECK: undefined symbol: foo in {{.*}}combined-lto-object-name.ll.tmp.o
diff --git a/test/ELF/lto/comdat.ll b/test/ELF/lto/comdat.ll
new file mode 100644
index 000000000000..e1384d0abd23
--- /dev/null
+++ b/test/ELF/lto/comdat.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+; CHECK: Name: foo
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+$foo = comdat any
+define void @foo() comdat {
+ ret void
+}
+
diff --git a/test/ELF/lto/comdat2.ll b/test/ELF/lto/comdat2.ll
new file mode 100644
index 000000000000..1509585f1553
--- /dev/null
+++ b/test/ELF/lto/comdat2.ll
@@ -0,0 +1,40 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o -filetype=obj
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.o -o %t2.so -shared
+; RUN: llvm-readobj -t %t2.so | FileCheck %s --check-prefix=OTHER
+
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+$c = comdat any
+
+define protected void @foo() comdat($c) {
+ ret void
+}
+
+; CHECK: Symbol {
+; CHECK: Name: foo
+; CHECK-NEXT: Value: 0x1000
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other [
+; CHECK-NEXT: STV_PROTECTED
+; CHECK-NEXT: ]
+; CHECK-NEXT: Section: .text
+; CHECK-NEXT: }
+
+; OTHER: Symbol {
+; OTHER: Name: foo
+; OTHER-NEXT: Value: 0x1000
+; OTHER-NEXT: Size: 0
+; OTHER-NEXT: Binding: Global
+; OTHER-NEXT: Type: None
+; OTHER-NEXT: Other [
+; OTHER-NEXT: STV_PROTECTED
+; OTHER-NEXT: ]
+; OTHER-NEXT: Section: .text
+; OTHER-NEXT: }
diff --git a/test/ELF/lto/common.ll b/test/ELF/lto/common.ll
new file mode 100644
index 000000000000..b02002431320
--- /dev/null
+++ b/test/ELF/lto/common.ll
@@ -0,0 +1,31 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/common.s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -s -t %t.so | FileCheck %s
+
+; CHECK: Name: .bss
+; CHECK-NEXT: Type: SHT_NOBITS
+; CHECK-NEXT: Flags [
+; CHECK-NEXT: SHF_ALLOC
+; CHECK-NEXT: SHF_WRITE
+; CHECK-NEXT: ]
+; CHECK-NEXT: Address:
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Size: 8
+; CHECK-NEXT: Link: 0
+; CHECK-NEXT: Info: 0
+; CHECK-NEXT: AddressAlignment: 8
+
+; CHECK: Name: a
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 8
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Object
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .bss
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@a = common global i32 0, align 8
diff --git a/test/ELF/lto/common2.ll b/test/ELF/lto/common2.ll
new file mode 100644
index 000000000000..59a2676e4fc9
--- /dev/null
+++ b/test/ELF/lto/common2.ll
@@ -0,0 +1,24 @@
+; RUN: llvm-as %s -o %t1.o
+; RUN: ld.lld -m elf_x86_64 %t1.o -o %t -shared -save-temps
+; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+; RUN: llvm-readobj -t %t | FileCheck %s --check-prefix=SHARED
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@a = common global i8 0, align 8
+
+; Shared library case, we ensure that the bitcode generated file
+; has not the a symbol but is appears in the final shared library
+; produced.
+; CHECK-NOT: @a = common global i8 0, align 8
+
+; SHARED: Symbol {
+; SHARED: Name: a
+; SHARED-NEXT: Value: 0x2000
+; SHARED-NEXT: Size: 1
+; SHARED-NEXT: Binding: Global
+; SHARED-NEXT: Type: Object
+; SHARED-NEXT: Other: 0
+; SHARED-NEXT: Section: .bss
+; SHARED-NEXT: }
diff --git a/test/ELF/lto/ctors.ll b/test/ELF/lto/ctors.ll
new file mode 100644
index 000000000000..7fce645f28f6
--- /dev/null
+++ b/test/ELF/lto/ctors.ll
@@ -0,0 +1,18 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared
+; RUN: llvm-readobj -sections %t.so | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }]
+define void @ctor() {
+ call void asm "nop", ""()
+ ret void
+}
+
+; The llvm.global_ctors should end up producing constructors.
+; On x86-64 (linux) we should always emit .init_array and never .ctors.
+; CHECK: Name: .init_array
+; CHECK-NOT: Name: .ctors
diff --git a/test/ELF/lto/discard-value-names.ll b/test/ELF/lto/discard-value-names.ll
new file mode 100644
index 000000000000..c6cd94fd2e18
--- /dev/null
+++ b/test/ELF/lto/discard-value-names.ll
@@ -0,0 +1,23 @@
+; RUN: llvm-as %s -o %t.o
+
+; RUN: ld.lld -m elf_x86_64 -shared -save-temps %t.o -o %t2.o
+; RUN: llvm-dis < %t2.o.lto.bc | FileCheck %s
+
+; CHECK: @GlobalValueName
+; CHECK: @foo(i32 %in)
+; CHECK: somelabel:
+; CHECK: %GV = load i32, i32* @GlobalValueName
+; CHECK: %add = add i32 %in, %GV
+; CHECK: ret i32 %add
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@GlobalValueName = global i32 0
+
+define i32 @foo(i32 %in) {
+somelabel:
+ %GV = load i32, i32* @GlobalValueName
+ %add = add i32 %in, %GV
+ ret i32 %add
+}
diff --git a/test/ELF/lto/drop-debug-info.ll b/test/ELF/lto/drop-debug-info.ll
new file mode 100644
index 000000000000..7a7ed5ea41d1
--- /dev/null
+++ b/test/ELF/lto/drop-debug-info.ll
@@ -0,0 +1,9 @@
+; REQUIRES: x86
+;
+; drop-debug-info.bc was created from "void f(void) {}" with clang 3.5 and
+; -gline-tables-only, so it contains old debug info.
+;
+; RUN: ld.lld -m elf_x86_64 -shared %p/Inputs/drop-debug-info.bc \
+; RUN: -disable-verify 2>&1 | FileCheck %s
+; CHECK: warning: ignoring debug info with an invalid version (1) in {{.*}}drop-debug-info.bc
+
diff --git a/test/ELF/lto/drop-linkage.ll b/test/ELF/lto/drop-linkage.ll
new file mode 100644
index 000000000000..fd111c18bd13
--- /dev/null
+++ b/test/ELF/lto/drop-linkage.ll
@@ -0,0 +1,14 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; REQUIRES: x86
+; RUN: llc %s -o %t.o -filetype=obj
+; RUN: llvm-as %p/Inputs/drop-linkage.ll -o %t2.o
+; RUN: ld.lld %t.o %t2.o -o %t.so -save-temps -shared
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+define void @foo() {
+ ret void
+}
+
+; CHECK: declare void @foo()
diff --git a/test/ELF/lto/duplicated.ll b/test/ELF/lto/duplicated.ll
new file mode 100644
index 000000000000..6ef6772c5f20
--- /dev/null
+++ b/test/ELF/lto/duplicated.ll
@@ -0,0 +1,10 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: not ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared 2>&1 | FileCheck %s
+; CHECK: duplicate symbol: f in {{.*}}.o and {{.*}}.o
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f() {
+ ret void
+}
diff --git a/test/ELF/lto/dynamic-list.ll b/test/ELF/lto/dynamic-list.ll
new file mode 100644
index 000000000000..0e950b3c83fd
--- /dev/null
+++ b/test/ELF/lto/dynamic-list.ll
@@ -0,0 +1,25 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo "{ foo; };" > %t.list
+; RUN: ld.lld -m elf_x86_64 -o %t --dynamic-list %t.list -pie %t.o
+; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+; CHECK: Name: foo@
+; CHECK-NEXT: Value: 0x1010
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global (0x1)
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+; CHECK-NEXT: }
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define void @foo() {
+ ret void
+}
diff --git a/test/ELF/lto/dynsym.ll b/test/ELF/lto/dynsym.ll
new file mode 100644
index 000000000000..5885960c7bc3
--- /dev/null
+++ b/test/ELF/lto/dynsym.ll
@@ -0,0 +1,25 @@
+; REQUIRES: x86
+; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t.o %p/Inputs/dynsym.s
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t2.o %t.so -o %t
+; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start() {
+ call void @foo()
+ ret void
+}
+
+; CHECK: Name: foo
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size:
+; CHECK-NEXT: Binding:
+; CHECK-NEXT: Type:
+; CHECK-NEXT: Other:
+; CHECK-NEXT: Section: .text
+define void @foo() {
+ ret void
+}
diff --git a/test/ELF/lto/inline-asm.ll b/test/ELF/lto/inline-asm.ll
new file mode 100644
index 000000000000..b6af6a5a5cbb
--- /dev/null
+++ b/test/ELF/lto/inline-asm.ll
@@ -0,0 +1,11 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo() {
+ call void asm "nop", ""()
+ ret void
+}
diff --git a/test/ELF/lto/internalize-basic.ll b/test/ELF/lto/internalize-basic.ll
new file mode 100644
index 000000000000..396b9cb60f17
--- /dev/null
+++ b/test/ELF/lto/internalize-basic.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define hidden void @foo() {
+ ret void
+}
+
+; Check that _start is not internalized.
+; CHECK: define void @_start()
+
+; Check that foo function is correctly internalized.
+; CHECK: define internal void @foo()
diff --git a/test/ELF/lto/internalize-exportdyn.ll b/test/ELF/lto/internalize-exportdyn.ll
new file mode 100644
index 000000000000..bee9a1e6a1ee
--- /dev/null
+++ b/test/ELF/lto/internalize-exportdyn.ll
@@ -0,0 +1,47 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/internalize-exportdyn.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t2 --export-dynamic -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define void @foo() {
+ ret void
+}
+
+define hidden void @bar() {
+ ret void
+}
+
+define linkonce_odr void @zed() local_unnamed_addr {
+ ret void
+}
+
+define linkonce_odr void @zed2() unnamed_addr {
+ ret void
+}
+
+define linkonce_odr void @bah() {
+ ret void
+}
+
+define linkonce_odr void @baz() {
+ ret void
+}
+
+@use_baz = global void ()* @baz
+
+; Check what gets internalized.
+; CHECK: define void @_start()
+; CHECK: define void @foo()
+; CHECK: define internal void @bar()
+; CHECK: define internal void @zed()
+; CHECK: define internal void @zed2()
+; CHECK: define weak_odr void @bah()
+; CHECK: define weak_odr void @baz()
diff --git a/test/ELF/lto/internalize-llvmused.ll b/test/ELF/lto/internalize-llvmused.ll
new file mode 100644
index 000000000000..46c90a65ff72
--- /dev/null
+++ b/test/ELF/lto/internalize-llvmused.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define hidden void @f() {
+ ret void
+}
+
+@llvm.used = appending global [1 x i8*] [ i8* bitcast (void ()* @f to i8*)]
+
+; Check that f is not internalized.
+; CHECK: define hidden void @f()
diff --git a/test/ELF/lto/internalize-undef.ll b/test/ELF/lto/internalize-undef.ll
new file mode 100644
index 000000000000..5d74c31eee8b
--- /dev/null
+++ b/test/ELF/lto/internalize-undef.ll
@@ -0,0 +1,16 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/internalize-undef.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -save-temps
+; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @f()
+define void @_start() {
+ call void @f()
+ ret void
+}
+
+; CHECK: define internal void @f()
diff --git a/test/ELF/lto/internalize-version-script.ll b/test/ELF/lto/internalize-version-script.ll
new file mode 100644
index 000000000000..c25328fb56e2
--- /dev/null
+++ b/test/ELF/lto/internalize-version-script.ll
@@ -0,0 +1,22 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo "{ global: foo; local: *; };" > %t.script
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -shared --version-script %t.script -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo() {
+ ret void
+}
+
+define void @bar() {
+ ret void
+}
+
+; Check that foo is not internalized.
+; CHECK: define void @foo()
+
+; Check that bar is correctly internalized.
+; CHECK: define internal void @bar()
diff --git a/test/ELF/lto/invalid-bitcode.ll b/test/ELF/lto/invalid-bitcode.ll
new file mode 100644
index 000000000000..eceffb10d8ad
--- /dev/null
+++ b/test/ELF/lto/invalid-bitcode.ll
@@ -0,0 +1,12 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: not ld.lld -m elf_x86_64 %t.o 2>&1 | FileCheck %s
+
+; CHECK: invalid bitcode file:
+
+; This bitcode file has no datalayout.
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/irmover-error.ll b/test/ELF/lto/irmover-error.ll
new file mode 100644
index 000000000000..aee411441c47
--- /dev/null
+++ b/test/ELF/lto/irmover-error.ll
@@ -0,0 +1,12 @@
+; RUN: llvm-as -o %t1.bc %s
+; RUN: llvm-as -o %t2.bc %S/Inputs/irmover-error.ll
+; RUN: not ld.lld -m elf_x86_64 %t1.bc %t2.bc -o %t 2>&1 | FileCheck %s
+
+; CHECK: failed to link module {{.*}}2.bc: linking module flags 'foo': IDs have conflicting values
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+!0 = !{ i32 1, !"foo", i32 1 }
+
+!llvm.module.flags = !{ !0 }
diff --git a/test/ELF/lto/linkage.ll b/test/ELF/lto/linkage.ll
new file mode 100644
index 000000000000..5af9b321eeec
--- /dev/null
+++ b/test/ELF/lto/linkage.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: ld.lld -m elf_x86_64 %t1.o %t1.o -o %t.so -shared
+; RUN: llvm-nm %t.so | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Should not encounter a duplicate symbol error for @.str
+@.str = private unnamed_addr constant [4 x i8] c"Hey\00", align 1
+
+; Should not encounter a duplicate symbol error for @llvm.global_ctors
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }]
+define internal void @ctor() {
+ ret void
+}
+
+; Should not try to merge a declaration into the combined module.
+declare i32 @llvm.ctpop.i32(i32)
+; CHECK-NOT: llvm.ctpop.i32
diff --git a/test/ELF/lto/linkonce-odr.ll b/test/ELF/lto/linkonce-odr.ll
new file mode 100644
index 000000000000..569e27154545
--- /dev/null
+++ b/test/ELF/lto/linkonce-odr.ll
@@ -0,0 +1,17 @@
+; REQUIRES: x86
+; RUN: llvm-as %p/Inputs/linkonce-odr.ll -o %t1.o
+; RUN: llc -relocation-model=pic %s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+declare void @f()
+
+define void @g() {
+ call void @f()
+ ret void
+}
+
+; Be sure that 'f' is kept and has weak_odr linkage.
+; CHECK: define weak_odr void @f()
diff --git a/test/ELF/lto/linkonce.ll b/test/ELF/lto/linkonce.ll
new file mode 100644
index 000000000000..f980eff887b1
--- /dev/null
+++ b/test/ELF/lto/linkonce.ll
@@ -0,0 +1,17 @@
+; REQUIRES: x86
+; RUN: llvm-as %p/Inputs/linkonce.ll -o %t1.o
+; RUN: llc -relocation-model=pic %s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+declare void @f()
+
+define void @g() {
+ call void @f()
+ ret void
+}
+
+; Be sure that 'f' is kept and has weak linkage.
+; CHECK: define weak void @f()
diff --git a/test/ELF/lto/lto-start.ll b/test/ELF/lto/lto-start.ll
new file mode 100644
index 000000000000..e93eecfbf033
--- /dev/null
+++ b/test/ELF/lto/lto-start.ll
@@ -0,0 +1,23 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2
+; RUN: llvm-readobj -t %t2 | FileCheck %s
+
+; CHECK: Format: ELF64-x86-64
+; CHECK-NEXT: Arch: x86_64
+; CHECK-NEXT: AddressSize: 64bit
+
+; CHECK: Name: _start
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other:
+; CHECK-NEXT: Section: .text
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/ltopasses-basic.ll b/test/ELF/lto/ltopasses-basic.ll
new file mode 100644
index 000000000000..5bd5f4122fd0
--- /dev/null
+++ b/test/ELF/lto/ltopasses-basic.ll
@@ -0,0 +1,18 @@
+; REQUIRES: x86
+; RUN: rm -f %t.so.lto.bc %t.so.lto.opt.bc %t.so.lto.o
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -mllvm -debug-pass=Arguments -shared 2>&1 | FileCheck %s --check-prefix=MLLVM
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }]
+define void @ctor() {
+ ret void
+}
+
+; `@ctor` doesn't do anything and so the optimizer should kill it, leaving no ctors
+; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
+
+; MLLVM: Pass Arguments:
diff --git a/test/ELF/lto/ltopasses-custom.ll b/test/ELF/lto/ltopasses-custom.ll
new file mode 100644
index 000000000000..3e982e079fb1
--- /dev/null
+++ b/test/ELF/lto/ltopasses-custom.ll
@@ -0,0 +1,30 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps --lto-aa-pipeline=basic-aa \
+; RUN: --lto-newpm-passes=ipsccp -shared
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2.so -save-temps --lto-newpm-passes=loweratomic -shared
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t2.so.lto.opt.bc -o - | FileCheck %s --check-prefix=ATOMIC
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @barrier() {
+ fence seq_cst
+ ret void
+}
+
+; IPSCCP won't remove the fence.
+; CHECK: define void @barrier() {
+; CHECK-NEXT: fence seq_cst
+; CHECK-NEXT: ret void
+
+; LowerAtomic will remove the fence.
+; ATOMIC: define void @barrier() {
+; ATOMIC-NEXT: ret void
+
+; Check that invalid passes are rejected gracefully.
+; RUN: not ld.lld -m elf_x86_64 %t.o -o %t2.so \
+; RUN: --lto-newpm-passes=iamnotapass -shared 2>&1 | \
+; RUN: FileCheck %s --check-prefix=INVALID
+; INVALID: unable to parse pass pipeline description: iamnotapass
diff --git a/test/ELF/lto/metadata.ll b/test/ELF/lto/metadata.ll
new file mode 100644
index 000000000000..3e73de5aab47
--- /dev/null
+++ b/test/ELF/lto/metadata.ll
@@ -0,0 +1,13 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: ld.lld -m elf_x86_64 %t1.o %t1.o -o %t.so -shared
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define weak void @foo(i32* %p) {
+ store i32 5, i32* %p, align 4, !tbaa !0
+ ret void
+}
+
+!0 = !{!"Simple C/C++ TBAA"}
diff --git a/test/ELF/lto/mix-platforms.ll b/test/ELF/lto/mix-platforms.ll
new file mode 100644
index 000000000000..3478caa5cff6
--- /dev/null
+++ b/test/ELF/lto/mix-platforms.ll
@@ -0,0 +1,10 @@
+; REQUIRES: x86
+; RUN: llvm-mc %p/Inputs/shared.s -o %t386.o -filetype=obj -triple=i386-pc-linux
+; RUN: ld.lld %t386.o -o %ti386.so -shared
+; RUN: llvm-as %s -o %tx64.o
+; RUN: not ld.lld %ti386.so %tx64.o -o %t 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: {{.*}}x64.o is incompatible with {{.*}}i386.so
diff --git a/test/ELF/lto/module-asm.ll b/test/ELF/lto/module-asm.ll
new file mode 100644
index 000000000000..1389b9f5472e
--- /dev/null
+++ b/test/ELF/lto/module-asm.ll
@@ -0,0 +1,19 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t
+; RUN: llvm-nm %t | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm ".text"
+module asm ".globl foo"
+; CHECK: T foo
+module asm "foo: ret"
+
+declare void @foo()
+
+define void @_start() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/opt-level.ll b/test/ELF/lto/opt-level.ll
new file mode 100644
index 000000000000..934bf01b6c32
--- /dev/null
+++ b/test/ELF/lto/opt-level.ll
@@ -0,0 +1,29 @@
+; RUN: llvm-as -o %t.o %s
+; RUN: ld.lld -o %t0 -m elf_x86_64 -e main --lto-O0 %t.o
+; RUN: llvm-nm %t0 | FileCheck --check-prefix=CHECK-O0 %s
+; RUN: ld.lld -o %t2 -m elf_x86_64 -e main --lto-O2 %t.o
+; RUN: llvm-nm %t2 | FileCheck --check-prefix=CHECK-O2 %s
+; RUN: ld.lld -o %t2a -m elf_x86_64 -e main %t.o
+; RUN: llvm-nm %t2a | FileCheck --check-prefix=CHECK-O2 %s
+
+; Reject invalid optimization levels.
+; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O6 %t.o 2>&1 | \
+; RUN: FileCheck --check-prefix=INVALID %s
+; INVALID: invalid optimization level for LTO: 6
+; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O-1 %t.o 2>&1 | \
+; RUN: FileCheck --check-prefix=INVALIDNEGATIVE %s
+; INVALIDNEGATIVE: invalid optimization level for LTO: -1
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK-O0: foo
+; CHECK-O2-NOT: foo
+define internal void @foo() {
+ ret void
+}
+
+define void @main() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/parallel-internalize.ll b/test/ELF/lto/parallel-internalize.ll
new file mode 100644
index 000000000000..58ed50eab894
--- /dev/null
+++ b/test/ELF/lto/parallel-internalize.ll
@@ -0,0 +1,57 @@
+; REQUIRES: x86
+; RUN: llvm-as -o %t.bc %s
+; RUN: ld.lld -m elf_x86_64 --lto-jobs=2 -save-temps -o %t %t.bc -e foo --lto-O0
+; RUN: llvm-readobj -t -dyn-symbols %t | FileCheck %s
+; RUN: llvm-nm %t0.lto.o | FileCheck --check-prefix=CHECK0 %s
+; RUN: llvm-nm %t1.lto.o | FileCheck --check-prefix=CHECK1 %s
+
+; CHECK: Symbols [
+; CHECK-NEXT: Symbol {
+; CHECK-NEXT: Name: (0)
+; CHECK-NEXT: Value: 0x0
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Local (0x0)
+; CHECK-NEXT: Type: None (0x0)
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: Undefined (0x0)
+; CHECK-NEXT: }
+; CHECK-NEXT: Symbol {
+; CHECK-NEXT: Name: bar (5)
+; CHECK-NEXT: Value: 0x11010
+; CHECK-NEXT: Size: 8
+; CHECK-NEXT: Binding: Local (0x0)
+; CHECK-NEXT: Type: Function (0x2)
+; CHECK-NEXT: Other [ (0x2)
+; CHECK-NEXT: STV_HIDDEN (0x2)
+; CHECK-NEXT: ]
+; CHECK-NEXT: Section: .text (0x2)
+; CHECK-NEXT: }
+; CHECK-NEXT: Symbol {
+; CHECK-NEXT: Name: foo (1)
+; CHECK-NEXT: Value: 0x11000
+; CHECK-NEXT: Size: 8
+; CHECK-NEXT: Binding: Global (0x1)
+; CHECK-NEXT: Type: Function (0x2)
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text (0x2)
+; CHECK-NEXT: }
+; CHECK-NEXT: ]
+; CHECK-NEXT: DynamicSymbols [
+; CHECK-NEXT: ]
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK0: U bar
+; CHECK0: T foo
+define void @foo() {
+ call void @bar()
+ ret void
+}
+
+; CHECK1: T bar
+; CHECK1: U foo
+define void @bar() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/parallel.ll b/test/ELF/lto/parallel.ll
new file mode 100644
index 000000000000..8ea62ef3ae08
--- /dev/null
+++ b/test/ELF/lto/parallel.ll
@@ -0,0 +1,24 @@
+; REQUIRES: x86
+; RUN: llvm-as -o %t.bc %s
+; RUN: ld.lld -m elf_x86_64 --lto-jobs=2 -save-temps -o %t %t.bc -shared
+; RUN: llvm-nm %t0.lto.o | FileCheck --check-prefix=CHECK0 %s
+; RUN: llvm-nm %t1.lto.o | FileCheck --check-prefix=CHECK1 %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK0-NOT: bar
+; CHECK0: T foo
+; CHECK0-NOT: bar
+define void @foo() {
+ call void @bar()
+ ret void
+}
+
+; CHECK1-NOT: foo
+; CHECK1: T bar
+; CHECK1-NOT: foo
+define void @bar() {
+ call void @foo()
+ ret void
+}
diff --git a/test/ELF/lto/pic.ll b/test/ELF/lto/pic.ll
new file mode 100644
index 000000000000..abc514d7ca3d
--- /dev/null
+++ b/test/ELF/lto/pic.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld %t.o -o %t.so -shared
+; RUN: llvm-readobj -r %t.so | FileCheck %s
+
+; CHECK: Relocations [
+; CHECK-NEXT: Section ({{.*}}) .rela.plt {
+; CHECK-NEXT: R_X86_64_JUMP_SLOT bar 0x0
+; CHECK-NEXT: }
+; CHECK-NEXT: ]
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @bar()
+define void @foo() {
+ call void @bar()
+ ret void
+}
diff --git a/test/ELF/lto/relax-relocs.ll b/test/ELF/lto/relax-relocs.ll
new file mode 100644
index 000000000000..929e124b2d8e
--- /dev/null
+++ b/test/ELF/lto/relax-relocs.ll
@@ -0,0 +1,15 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 -save-temps -shared %t.o -o %t.so
+; RUN: llvm-readobj -r %t.so.lto.o | FileCheck %s
+
+; Test that we produce R_X86_64_REX_GOTPCRELX instead of R_X86_64_GOTPCREL
+; CHECK: R_X86_64_REX_GOTPCRELX foo
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@foo = external global i32
+define i32 @bar() {
+ %t = load i32, i32* @foo
+ ret i32 %t
+}
diff --git a/test/ELF/lto/resolution.ll b/test/ELF/lto/resolution.ll
new file mode 100644
index 000000000000..b3fcf1db3a1b
--- /dev/null
+++ b/test/ELF/lto/resolution.ll
@@ -0,0 +1,27 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/resolution.s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -s --section-data %t.so | FileCheck %s
+
+; CHECK: Name: .data
+; CHECK-NEXT: Type: SHT_PROGBITS
+; CHECK-NEXT: Flags [
+; CHECK-NEXT: SHF_ALLOC
+; CHECK-NEXT: SHF_WRITE
+; CHECK-NEXT: ]
+; CHECK-NEXT: Address:
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Size: 4
+; CHECK-NEXT: Link: 0
+; CHECK-NEXT: Info: 0
+; CHECK-NEXT: AddressAlignment: 1
+; CHECK-NEXT: EntrySize: 0
+; CHECK-NEXT: SectionData (
+; CHECK-NEXT: 0000: 09000000 |{{.*}}|
+; CHECK-NEXT: )
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@a = weak global i32 8
diff --git a/test/ELF/lto/save-temps.ll b/test/ELF/lto/save-temps.ll
new file mode 100644
index 000000000000..0b0f939c53f1
--- /dev/null
+++ b/test/ELF/lto/save-temps.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+; RUN: cd %T
+; RUN: rm -f a.out a.out.lto.bc a.out.lto.o
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/save-temps.ll -o %t2.o
+; RUN: ld.lld -shared -m elf_x86_64 %t.o %t2.o -save-temps
+; RUN: llvm-nm a.out | FileCheck %s
+; RUN: llvm-nm a.out.lto.bc | FileCheck %s
+; RUN: llvm-nm a.out.lto.o | FileCheck %s
+; RUN: llvm-dis a.out.lto.bc
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo() {
+ ret void
+}
+
+; CHECK: T bar
+; CHECK: T foo
diff --git a/test/ELF/lto/shlib-undefined.ll b/test/ELF/lto/shlib-undefined.ll
new file mode 100644
index 000000000000..db60de8e21b2
--- /dev/null
+++ b/test/ELF/lto/shlib-undefined.ll
@@ -0,0 +1,27 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo .global __progname > %t2.s
+; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o
+; RUN: ld.lld -shared %t2.o -o %t2.so
+; RUN: ld.lld -o %t %t.o %t2.so
+; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+; CHECK: Name: __progname@
+; CHECK-NEXT: Value: 0x11010
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Global (0x1)
+; CHECK-NEXT: Type: Function
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+; CHECK-NEXT: }
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+define void @__progname() {
+ ret void
+}
diff --git a/test/ELF/lto/start-lib.ll b/test/ELF/lto/start-lib.ll
new file mode 100644
index 000000000000..ec73954a80ca
--- /dev/null
+++ b/test/ELF/lto/start-lib.ll
@@ -0,0 +1,27 @@
+; REQUIRES: x86
+;
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-as %p/Inputs/start-lib1.ll -o %t2.o
+; RUN: llvm-as %p/Inputs/start-lib2.ll -o %t3.o
+;
+; RUN: ld.lld -m elf_x86_64 -shared -o %t3 %t1.o %t2.o %t3.o
+; RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST1 %s
+; TEST1: Name: bar
+; TEST1: Name: foo
+;
+; RUN: ld.lld -m elf_x86_64 -shared -o %t3 -u bar %t1.o --start-lib %t2.o %t3.o
+; RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST2 %s
+; TEST2: Name: bar
+; TEST2-NOT: Name: foo
+;
+; RUN: ld.lld -m elf_x86_64 -shared -o %t3 %t1.o --start-lib %t2.o %t3.o
+; RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST3 %s
+; TEST3-NOT: Name: bar
+; TEST3-NOT: Name: foo
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_start() {
+ ret void
+}
diff --git a/test/ELF/lto/tls-mixed.ll b/test/ELF/lto/tls-mixed.ll
new file mode 100644
index 000000000000..524bb4fb44a3
--- /dev/null
+++ b/test/ELF/lto/tls-mixed.ll
@@ -0,0 +1,10 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-mc %p/Inputs/tls-mixed.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t.so -shared
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Should not encounter TLS-ness mismatch for @foo
+@foo = external thread_local global i32, align 4
diff --git a/test/ELF/lto/tls-preserve.ll b/test/ELF/lto/tls-preserve.ll
new file mode 100644
index 000000000000..8aebcb783f48
--- /dev/null
+++ b/test/ELF/lto/tls-preserve.ll
@@ -0,0 +1,25 @@
+; TLS attribute needs to be preserved.
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: ld.lld -shared %t1.o -m elf_x86_64 -o %t1
+; RUN: llvm-readobj -t %t1 | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@tsp_int = thread_local global i32 1
+
+define void @_start() {
+ %val = load i32, i32* @tsp_int
+ ret void
+}
+
+; CHECK: Symbol {
+; CHECK: Name: tsp_int
+; CHECK-NEXT: Value: 0x0
+; CHECK-NEXT: Size: 4
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: TLS
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .tdata
+; CHECK-NEXT: }
diff --git a/test/ELF/lto/type-merge.ll b/test/ELF/lto/type-merge.ll
new file mode 100644
index 000000000000..98db53970b0c
--- /dev/null
+++ b/test/ELF/lto/type-merge.ll
@@ -0,0 +1,26 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/type-merge.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -shared -save-temps
+; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo() {
+ call void @bar(i8* null)
+ ret void
+}
+declare void @bar(i8*)
+
+; CHECK: define void @foo() {
+; CHECK-NEXT: call void @bar(i8* null)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+
+; CHECK: declare void @bar(i8*)
+
+; CHECK: define void @zed() {
+; CHECK-NEXT: call void bitcast (void (i8*)* @bar to void ()*)()
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
diff --git a/test/ELF/lto/type-merge2.ll b/test/ELF/lto/type-merge2.ll
new file mode 100644
index 000000000000..f0931ddc9d5e
--- /dev/null
+++ b/test/ELF/lto/type-merge2.ll
@@ -0,0 +1,27 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %p/Inputs/type-merge2.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared -save-temps
+; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%zed = type { i8 }
+define void @foo() {
+ call void @bar(%zed* null)
+ ret void
+}
+declare void @bar(%zed*)
+
+; CHECK: %zed = type { i8 }
+; CHECK-NEXT: %zed.0 = type { i16 }
+
+; CHECK: define void @foo() {
+; CHECK-NEXT: call void bitcast (void (%zed.0*)* @bar to void (%zed*)*)(%zed* null)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+
+; CHECK: define void @bar(%zed.0* %this) {
+; CHECK-NEXT: store %zed.0* %this, %zed.0** null
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
diff --git a/test/ELF/lto/undef-mixed.ll b/test/ELF/lto/undef-mixed.ll
new file mode 100644
index 000000000000..0fff5781020c
--- /dev/null
+++ b/test/ELF/lto/undef-mixed.ll
@@ -0,0 +1,22 @@
+; REQUIRES: x86
+; RUN: llvm-mc %p/Inputs/undef-mixed.s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld %t2.o %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+; CHECK: Name: bar
+; CHECK-NEXT: Value:
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: .text
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @bar()
+define void @foo() {
+ call void @bar()
+ ret void
+}
diff --git a/test/ELF/lto/undef-weak.ll b/test/ELF/lto/undef-weak.ll
new file mode 100644
index 000000000000..215978a73df0
--- /dev/null
+++ b/test/ELF/lto/undef-weak.ll
@@ -0,0 +1,29 @@
+; REQUIRES: x86
+
+; RUN: llvm-as %S/Inputs/archive.ll -o %t1.o
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+
+
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t2.o -o %t2.so %t.a -shared
+; RUN: llvm-readobj -t %t2.so | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare extern_weak void @f()
+define void @foo() {
+ call void @f()
+ ret void
+}
+
+; We should not fetch the archive member.
+
+; CHECK: Name: f ({{.*}})
+; CHECK-NEXT: Value: 0x0
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Weak
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: Undefined
+
diff --git a/test/ELF/lto/undef.ll b/test/ELF/lto/undef.ll
new file mode 100644
index 000000000000..41da61052290
--- /dev/null
+++ b/test/ELF/lto/undef.ll
@@ -0,0 +1,20 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @bar()
+define void @foo() {
+ call void @bar()
+ ret void
+}
+
+; CHECK: Name: bar
+; CHECK-NEXT: Value: 0x0
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Global
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other: 0
+; CHECK-NEXT: Section: Undefined
diff --git a/test/ELF/lto/undefined-puts.ll b/test/ELF/lto/undefined-puts.ll
new file mode 100644
index 000000000000..54fb32cef4a2
--- /dev/null
+++ b/test/ELF/lto/undefined-puts.ll
@@ -0,0 +1,28 @@
+; REQUIRES: x86
+; RUN: llvm-mc %p/Inputs/shared.s -o %t1.o -filetype=obj -triple=x86_64-unknown-linux
+; RUN: ld.lld %t1.o -o %t1.so -shared
+; RUN: llvm-as %s -o %t2.o
+; RUN: ld.lld %t1.so %t2.o -m elf_x86_64 -o %t
+; RUN: llvm-readobj -dyn-symbols -dyn-relocations %t | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@.str = private unnamed_addr constant [6 x i8] c"blah\0A\00", align 1
+
+define i32 @_start() {
+ %str = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0))
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+
+; Check that puts symbol is present in the dynamic symbol table and
+; there's a relocation for it.
+; CHECK: Dynamic Relocations {
+; CHECK-NEXT: 0x13018 R_X86_64_JUMP_SLOT puts 0x0
+; CHECK-NEXT: }
+
+; CHECK: DynamicSymbols [
+; CHECK: Symbol {
+; CHECK: Name: puts@
diff --git a/test/ELF/lto/unnamed-addr-comdat.ll b/test/ELF/lto/unnamed-addr-comdat.ll
new file mode 100644
index 000000000000..c8c36de88d4c
--- /dev/null
+++ b/test/ELF/lto/unnamed-addr-comdat.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -save-temps -shared
+; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+$foo = comdat any
+@foo = linkonce_odr unnamed_addr constant i32 42, comdat
+
+; CHECK: @foo = internal unnamed_addr constant i32 42, comdat
diff --git a/test/ELF/lto/unnamed-addr-lib.ll b/test/ELF/lto/unnamed-addr-lib.ll
new file mode 100644
index 000000000000..c1c31f84bc8e
--- /dev/null
+++ b/test/ELF/lto/unnamed-addr-lib.ll
@@ -0,0 +1,21 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-mc %p/Inputs/unnamed-addr-lib.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+; RUN: ld.lld %t2.o -shared -o %t2.so
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.so -o %t.so -save-temps -shared
+; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+
+; This documents a small limitation of lld's internalization logic. We decide
+; that bar should be in the symbol table because if it is it will preempt the
+; one in the shared library.
+; We could add one extra bit for ODR so that we know that preemption is not
+; necessary, but that is probably not worth it.
+
+; CHECK: @foo = internal unnamed_addr constant i8 42
+; CHECK: @bar = weak_odr unnamed_addr constant i8 42
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@foo = linkonce_odr unnamed_addr constant i8 42
+@bar = linkonce_odr unnamed_addr constant i8 42
diff --git a/test/ELF/lto/unnamed-addr.ll b/test/ELF/lto/unnamed-addr.ll
new file mode 100644
index 000000000000..a2c0105fd85f
--- /dev/null
+++ b/test/ELF/lto/unnamed-addr.ll
@@ -0,0 +1,14 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -shared
+; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+@a = internal unnamed_addr constant i8 42
+
+define i8* @f() {
+ ret i8* @a
+}
+
+; CHECK: @a = internal unnamed_addr constant i8 42
diff --git a/test/ELF/lto/verify-invalid.ll b/test/ELF/lto/verify-invalid.ll
new file mode 100644
index 000000000000..16d6a3e54f12
--- /dev/null
+++ b/test/ELF/lto/verify-invalid.ll
@@ -0,0 +1,17 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -mllvm -debug-pass=Arguments \
+; RUN: 2>&1 | FileCheck -check-prefix=DEFAULT %s
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -mllvm -debug-pass=Arguments \
+; RUN: -disable-verify 2>&1 | FileCheck -check-prefix=DISABLE %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}
+
+; -disable-verify should disable the verification of bitcode.
+; DEFAULT: Pass Arguments: {{.*}} -verify {{.*}} -verify
+; DISABLE-NOT: Pass Arguments: {{.*}} -verify {{.*}} -verify
diff --git a/test/ELF/lto/version-script.ll b/test/ELF/lto/version-script.ll
new file mode 100644
index 000000000000..11a7f073ab51
--- /dev/null
+++ b/test/ELF/lto/version-script.ll
@@ -0,0 +1,50 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo "VERSION_1.0{ global: foo; local: *; }; VERSION_2.0{ global: bar; local: *; };" > %t.script
+; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -shared --version-script %t.script -save-temps
+; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+; RUN: llvm-readobj -V -dyn-symbols %t2 | FileCheck --check-prefix=DSO %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo() {
+ ret void
+}
+
+define void @bar() {
+ ret void
+}
+
+; CHECK: define void @foo()
+; CHECK: define void @bar()
+
+; DSO: DynamicSymbols [
+; DSO: Symbol {
+; DSO: Name: @ (0)
+; DSO: Value: 0x0
+; DSO: Size: 0
+; DSO: Binding: Local
+; DSO: Type: None
+; DSO: Other: 0
+; DSO: Section: Undefined
+; DSO: }
+; DSO: Symbol {
+; DSO: Name: foo@@VERSION_1.0
+; DSO: Value: 0x1000
+; DSO: Size: 1
+; DSO: Binding: Global
+; DSO: Type: Function
+; DSO: Other: 0
+; DSO: Section: .text
+; DSO: }
+; DSO: Symbol {
+; DSO: Name: bar@@VERSION_2.0
+; DSO: Value: 0x1010
+; DSO: Size: 1
+; DSO: Binding: Global
+; DSO: Type: Function
+; DSO: Other: 0
+; DSO: Section: .text
+; DSO: }
+; DSO: ]
diff --git a/test/ELF/lto/visibility.ll b/test/ELF/lto/visibility.ll
new file mode 100644
index 000000000000..718cc5b06986
--- /dev/null
+++ b/test/ELF/lto/visibility.ll
@@ -0,0 +1,35 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/visibility.s -o %t2.o -filetype=obj
+; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+; CHECK: Name: g
+; CHECK-NEXT: Value: 0x1000
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Local
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other [ (0x2)
+; CHECK-NEXT: STV_HIDDEN
+; CHECK-NEXT: ]
+; CHECK-NEXT: Section: .text
+
+; CHECK: Name: a
+; CHECK-NEXT: Value: 0x3000
+; CHECK-NEXT: Size: 0
+; CHECK-NEXT: Binding: Local
+; CHECK-NEXT: Type: None
+; CHECK-NEXT: Other [ (0x2)
+; CHECK-NEXT: STV_HIDDEN
+; CHECK-NEXT: ]
+; CHECK-NEXT: Section: .data
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare hidden void @g()
+define void @f() {
+ call void @g()
+ ret void
+}
+@a = weak hidden global i32 42
diff --git a/test/ELF/lto/weak.ll b/test/ELF/lto/weak.ll
new file mode 100644
index 000000000000..381ef7a1a347
--- /dev/null
+++ b/test/ELF/lto/weak.ll
@@ -0,0 +1,16 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared
+; RUN: llvm-readobj -t %t.so | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define weak void @f() {
+ ret void
+}
+
+; CHECK: Name: f
+; CHECK-NEXT: Value: 0x1000
+; CHECK-NEXT: Size: 1
+; CHECK-NEXT: Binding: Weak
diff --git a/test/ELF/merge-shared-str.s b/test/ELF/merge-shared-str.s
new file mode 100644
index 000000000000..2ab03a4d66ab
--- /dev/null
+++ b/test/ELF/merge-shared-str.s
@@ -0,0 +1,28 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared -O3
+// RUN: llvm-readobj -r -s %t.so | FileCheck %s
+
+
+ .section foo,"aMS",@progbits,1
+ .asciz "bar"
+ .asciz "ar"
+
+ .data
+ .quad foo + 4
+
+
+// CHECK: Name: foo
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: SHF_STRINGS
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1C8
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x1C9
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/merge-shared.s b/test/ELF/merge-shared.s
index 702a4e195f32..4c1d7c06a0ba 100644
--- a/test/ELF/merge-shared.s
+++ b/test/ELF/merge-shared.s
@@ -7,7 +7,7 @@
.long 42
.long 42
- .text
+ .data
.quad foo + 6
diff --git a/test/ELF/merge-string-align.s b/test/ELF/merge-string-align.s
index b06920ac0af8..0cb1afc8ba7d 100644
--- a/test/ELF/merge-string-align.s
+++ b/test/ELF/merge-string-align.s
@@ -1,15 +1,20 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
// RUN: ld.lld %t.o -o %t.so -shared
-// RUN: llvm-readobj -s %t.so | FileCheck %s
+// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s
- .section .rodata.str1.16,"aMS",@progbits,1
+ .section .rodata.foo,"aMS",@progbits,1
.align 16
.asciz "foo"
- .section .rodata.str1.1,"aMS",@progbits,1
+ .section .rodata.foo2,"aMS",@progbits,1
+ .align 16
.asciz "foo"
+ .section .rodata.bar,"aMS",@progbits,1
+ .align 16
+ .asciz "bar"
+
// CHECK: Name: .rodata
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
@@ -19,10 +24,18 @@
// CHECK-NEXT: ]
// CHECK-NEXT: Address:
// CHECK-NEXT: Offset:
-// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Size: 20
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 16
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 666F6F00 00000000 00000000 00000000 |foo.............|
+// CHECK-NEXT: 0010: 62617200 |bar.|
+// CHECK-NEXT: )
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+ .asciz "foo"
// CHECK: Name: .rodata
// CHECK-NEXT: Type: SHT_PROGBITS
@@ -37,3 +50,7 @@
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 666F6F00 |foo.|
+// CHECK-NEXT: )
diff --git a/test/ELF/merge-string-error.s b/test/ELF/merge-string-error.s
index 58a624329ed9..c5088acf63b6 100644
--- a/test/ELF/merge-string-error.s
+++ b/test/ELF/merge-string-error.s
@@ -5,7 +5,7 @@
.section .rodata.str1.1,"aMS",@progbits,1
.asciz "abc"
- .text
+ .data
.long .rodata.str1.1 + 4
-// CHECK: Entry is past the end of the section
+// CHECK: entry is past the end of the section
diff --git a/test/ELF/merge-string-no-null.s b/test/ELF/merge-string-no-null.s
index 70d6bbbc32e8..fd3f5073810a 100644
--- a/test/ELF/merge-string-no-null.s
+++ b/test/ELF/merge-string-no-null.s
@@ -5,4 +5,4 @@
.section .rodata.str1.1,"aMS",@progbits,1
.ascii "abc"
-// CHECK: String is not null terminated
+// CHECK: string is not null terminated
diff --git a/test/ELF/merge-string.s b/test/ELF/merge-string.s
index 40cc4415f956..2ad8afa53d6e 100644
--- a/test/ELF/merge-string.s
+++ b/test/ELF/merge-string.s
@@ -4,6 +4,8 @@
// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck %s
// RUN: ld.lld -O1 %t.o -o %t.so -shared
// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck --check-prefix=NOTAIL %s
+// RUN: ld.lld -O0 %t.o -o %t.so -shared
+// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck --check-prefix=NOMERGE %s
.section .rodata.str1.1,"aMS",@progbits,1
.asciz "abc"
@@ -32,7 +34,7 @@ zed:
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 1
-// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: EntrySize: 1
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 61626300 |abc.|
// CHECK-NEXT: )
@@ -50,11 +52,29 @@ zed:
// NOTAIL-NEXT: Link: 0
// NOTAIL-NEXT: Info: 0
// NOTAIL-NEXT: AddressAlignment: 1
-// NOTAIL-NEXT: EntrySize: 0
+// NOTAIL-NEXT: EntrySize: 1
// NOTAIL-NEXT: SectionData (
// NOTAIL-NEXT: 0000: 61626300 626300 |abc.bc.|
// NOTAIL-NEXT: )
+// NOMERGE: Name: .rodata
+// NOMERGE-NEXT: Type: SHT_PROGBITS
+// NOMERGE-NEXT: Flags [
+// NOMERGE-NEXT: SHF_ALLOC
+// NOMERGE-NEXT: SHF_MERGE
+// NOMERGE-NEXT: SHF_STRINGS
+// NOMERGE-NEXT: ]
+// NOMERGE-NEXT: Address: 0x1C8
+// NOMERGE-NEXT: Offset: 0x1C8
+// NOMERGE-NEXT: Size: 16
+// NOMERGE-NEXT: Link: 0
+// NOMERGE-NEXT: Info: 0
+// NOMERGE-NEXT: AddressAlignment: 2
+// NOMERGE-NEXT: EntrySize: 0
+// NOMERGE-NEXT: SectionData (
+// NOMERGE-NEXT: 0000: 61626300 61626300 62630000 14000000 |abc.abc.bc......|
+// NOMERGE-NEXT: )
+
// CHECK: Name: .rodata
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
@@ -68,7 +88,7 @@ zed:
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 2
-// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: EntrySize: 2
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 14000000 |....|
// CHECK-NEXT: )
diff --git a/test/ELF/merge.s b/test/ELF/merge.s
index 9cead642fa8c..5039ec2251c0 100644
--- a/test/ELF/merge.s
+++ b/test/ELF/merge.s
@@ -29,7 +29,7 @@ zed:
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 4
-// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: EntrySize: 4
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 10000000 42000000
// CHECK-NEXT: )
@@ -61,7 +61,9 @@ zed:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 2
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .mysec
// CHECK: ]
diff --git a/test/ELF/mips-26.s b/test/ELF/mips-26.s
new file mode 100644
index 000000000000..b463c1ac2127
--- /dev/null
+++ b/test/ELF/mips-26.s
@@ -0,0 +1,95 @@
+# Check R_MIPS_26 relocation handling.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t2.o
+# RUN: ld.lld %t2.o -shared -o %t.so
+# RUN: ld.lld %t1.o %t.so -o %t.exe
+# RUN: llvm-objdump -d %t.exe | FileCheck %s
+# RUN: llvm-readobj -dynamic-table -s -r -mips-plt-got %t.exe \
+# RUN: | FileCheck -check-prefix=REL %s
+
+# REQUIRES: mips
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: bar:
+# CHECK-NEXT: 20000: 0c 00 80 06 jal 131096 <loc>
+# CHECK-NEXT: 20004: 00 00 00 00 nop
+#
+# CHECK: __start:
+# CHECK-NEXT: 20008: 0c 00 80 00 jal 131072 <bar>
+# CHECK-NEXT: 2000c: 00 00 00 00 nop
+# CHECK-NEXT: 20010: 0c 00 80 10 jal 131136
+# ^-- 0x20040 gotplt[foo0]
+# CHECK-NEXT: 20014: 00 00 00 00 nop
+#
+# CHECK: loc:
+# CHECK-NEXT: 20018: 00 00 00 00 nop
+# CHECK-NEXT: Disassembly of section .plt:
+# CHECK-NEXT: .plt:
+# CHECK-NEXT: 20020: 3c 1c 00 04 lui $gp, 4
+# CHECK-NEXT: 20024: 8f 99 00 04 lw $25, 4($gp)
+# CHECK-NEXT: 20028: 27 9c 00 04 addiu $gp, $gp, 4
+# CHECK-NEXT: 2002c: 03 1c c0 23 subu $24, $24, $gp
+# CHECK-NEXT: 20030: 03 e0 78 25 move $15, $ra
+# CHECK-NEXT: 20034: 00 18 c0 82 srl $24, $24, 2
+# CHECK-NEXT: 20038: 03 20 f8 09 jalr $25
+# CHECK-NEXT: 2003c: 27 18 ff fe addiu $24, $24, -2
+# CHECK-NEXT: 20040: 3c 0f 00 04 lui $15, 4
+# CHECK-NEXT: 20044: 8d f9 00 0c lw $25, 12($15)
+# CHECK-NEXT: 20048: 03 20 00 08 jr $25
+# CHECK-NEXT: 2004c: 25 f8 00 0c addiu $24, $15, 12
+
+# REL: Name: .plt
+# REL-NEXT: Type: SHT_PROGBITS
+# REL-NEXT: Flags [ (0x6)
+# REL-NEXT: SHF_ALLOC
+# REL-NEXT: SHF_EXECINSTR
+# REL-NEXT: ]
+# REL-NEXT: Address: 0x[[PLTADDR:[0-9A-F]+]]
+
+# REL: Name: .got.plt
+# REL-NEXT: Type: SHT_PROGBITS
+# REL-NEXT: Flags [ (0x3)
+# REL-NEXT: SHF_ALLOC
+# REL-NEXT: SHF_WRITE
+# REL-NEXT: ]
+# REL-NEXT: Address: 0x[[GOTPLTADDR:[0-9A-F]+]]
+
+# REL: Relocations [
+# REL-NEXT: Section (7) .rel.plt {
+# REL-NEXT: 0x[[PLTSLOT:[0-9A-F]+]] R_MIPS_JUMP_SLOT foo0 0x0
+# REL-NEXT: }
+# REL-NEXT: ]
+
+# REL: 0x70000032 MIPS_PLTGOT 0x[[GOTPLTADDR]]
+
+# REL: Primary GOT {
+# REL: Local entries [
+# REL-NEXT: ]
+# REL-NEXT: Global entries [
+# REL-NEXT: ]
+# REL: PLT GOT {
+# REL: Entries [
+# REL-NEXT: Entry {
+# REL-NEXT: Address: 0x[[PLTSLOT]]
+# REL-NEXT: Initial: 0x[[PLTADDR]]
+# REL-NEXT: Value: 0x0
+# REL-NEXT: Type: Function
+# REL-NEXT: Section: Undefined
+# REL-NEXT: Name: foo0
+# REL-NEXT: }
+# REL-NEXT: ]
+
+ .text
+ .globl bar
+bar:
+ jal loc # R_MIPS_26 against .text + offset
+
+ .globl __start
+__start:
+ jal bar # R_MIPS_26 against global 'bar' from object file
+ jal foo0 # R_MIPS_26 against 'foo0' from DSO
+
+loc:
+ nop
diff --git a/test/ELF/mips-32.s b/test/ELF/mips-32.s
new file mode 100644
index 000000000000..7875c48d64d7
--- /dev/null
+++ b/test/ELF/mips-32.s
@@ -0,0 +1,78 @@
+# Check R_MIPS_32 relocation calculation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
+# RUN: ld.lld -shared %t-be.o -o %t-be.so
+# RUN: llvm-objdump -t -s %t-be.so \
+# RUN: | FileCheck -check-prefix=SYM -check-prefix=BE %s
+# RUN: llvm-readobj -r -dynamic-table -mips-plt-got %t-be.so \
+# RUN: | FileCheck -check-prefix=REL %s
+
+# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
+# RUN: ld.lld -shared %t-el.o -o %t-el.so
+# RUN: llvm-objdump -t -s %t-el.so \
+# RUN: | FileCheck -check-prefix=SYM -check-prefix=EL %s
+# RUN: llvm-readobj -r -dynamic-table -mips-plt-got %t-el.so \
+# RUN: | FileCheck -check-prefix=REL %s
+
+# REQUIRES: mips
+
+ .globl __start
+__start:
+ nop
+
+ .data
+ .type v1,@object
+ .size v1,4
+v1:
+ .word 0
+
+ .globl v2
+ .type v2,@object
+ .size v2,8
+v2:
+ .word v2+4 # R_MIPS_32 target v2 addend 4
+ .word v1 # R_MIPS_32 target v1 addend 0
+
+# BE: Contents of section .data:
+# BE-NEXT: 30000 00000000 00000004 00030000
+# ^-- v2+4 ^-- v1
+
+# EL: Contents of section .data:
+# EL-NEXT: 30000 00000000 04000000 00000300
+# ^-- v2+4 ^-- v1
+
+# SYM: SYMBOL TABLE:
+# SYM: 00030000 l .data 00000004 v1
+# SYM: 00030004 g .data 00000008 v2
+
+# REL: Relocations [
+# REL-NEXT: Section (7) .rel.dyn {
+# REL-NEXT: 0x30008 R_MIPS_REL32 - 0x0
+# REL-NEXT: 0x30004 R_MIPS_REL32 v2 0x0
+# REL-NEXT: }
+# REL-NEXT: ]
+
+# REL: DynamicSection [
+# REL: Tag Type Name/Value
+# REL: 0x00000012 RELSZ 16 (bytes)
+# REL: 0x00000013 RELENT 8 (bytes)
+
+# REL: Primary GOT {
+# REL-NEXT: Canonical gp value:
+# REL-NEXT: Reserved entries [
+# REL: ]
+# REL-NEXT: Local entries [
+# REL-NEXT: ]
+# REL-NEXT: Global entries [
+# REL-NEXT: Entry {
+# REL-NEXT: Address:
+# REL-NEXT: Access:
+# REL-NEXT: Initial: 0x30004
+# REL-NEXT: Value: 0x30004
+# REL-NEXT: Type: Object
+# REL-NEXT: Section: .data
+# REL-NEXT: Name: v2
+# REL-NEXT: }
+# REL-NEXT: ]
+# REL-NEXT: Number of TLS and multi-GOT entries: 0
+# REL-NEXT: }
diff --git a/test/ELF/mips-64-disp.s b/test/ELF/mips-64-disp.s
new file mode 100644
index 000000000000..1c66ba4fb9a1
--- /dev/null
+++ b/test/ELF/mips-64-disp.s
@@ -0,0 +1,89 @@
+# Check R_MIPS_GOT_DISP relocations against various kind of symbols.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
+# RUN: %p/Inputs/mips-pic.s -o %t.so.o
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.exe.o
+# RUN: ld.lld %t.so.o -shared -o %t.so
+# RUN: ld.lld %t.exe.o %t.so -o %t.exe
+# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
+# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
+
+# REQUIRES: mips
+
+# CHECK: __start:
+# CHECK-NEXT: 20000: 24 42 80 40 addiu $2, $2, -32704
+# CHECK-NEXT: 20004: 24 42 80 20 addiu $2, $2, -32736
+# CHECK-NEXT: 20008: 24 42 80 28 addiu $2, $2, -32728
+# CHECK-NEXT: 2000c: 24 42 80 30 addiu $2, $2, -32720
+# CHECK-NEXT: 20010: 24 42 80 38 addiu $2, $2, -32712
+
+# CHECK: 0000000000020014 .text 00000000 foo
+# CHECK: 0000000000037ff0 .got 00000000 .hidden _gp
+# CHECK: 0000000000020000 .text 00000000 __start
+# CHECK: 0000000000000000 g F *UND* 00000000 foo1a
+
+# GOT: Relocations [
+# GOT-NEXT: ]
+# GOT-NEXT: Primary GOT {
+# GOT-NEXT: Canonical gp value: 0x37FF0
+# GOT-NEXT: Reserved entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30000
+# GOT-NEXT: Access: -32752
+# GOT-NEXT: Initial: 0x0
+# GOT-NEXT: Purpose: Lazy resolver
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30008
+# GOT-NEXT: Access: -32744
+# GOT-NEXT: Initial: 0x8000000000000000
+# GOT-NEXT: Purpose: Module pointer (GNU extension)
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Local entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30010
+# GOT-NEXT: Access: -32736
+# GOT-NEXT: Initial: 0x20014
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30018
+# GOT-NEXT: Access: -32728
+# GOT-NEXT: Initial: 0x20004
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30020
+# GOT-NEXT: Access: -32720
+# GOT-NEXT: Initial: 0x20008
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30028
+# GOT-NEXT: Access: -32712
+# GOT-NEXT: Initial: 0x2000C
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Global entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30030
+# GOT-NEXT: Access: -32704
+# GOT-NEXT: Initial: 0x0
+# GOT-NEXT: Value: 0x0
+# GOT-NEXT: Type: Function
+# GOT-NEXT: Section: Undefined
+# GOT-NEXT: Name: foo1a
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Number of TLS and multi-GOT entries: 0
+# GOT-NEXT: }
+
+ .text
+ .global __start
+__start:
+ addiu $v0,$v0,%got_disp(foo1a) # R_MIPS_GOT_DISP
+ addiu $v0,$v0,%got_disp(foo) # R_MIPS_GOT_DISP
+ addiu $v0,$v0,%got_disp(.text+4) # R_MIPS_GOT_DISP
+ addiu $v0,$v0,%got_disp(.text+8) # R_MIPS_GOT_DISP
+ addiu $v0,$v0,%got_disp(.text+12) # R_MIPS_GOT_DISP
+
+foo:
+ nop
diff --git a/test/ELF/mips-64-got.s b/test/ELF/mips-64-got.s
new file mode 100644
index 000000000000..52ce6fb4d351
--- /dev/null
+++ b/test/ELF/mips-64-got.s
@@ -0,0 +1,87 @@
+# Check MIPS N64 ABI GOT relocations
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
+# RUN: %p/Inputs/mips-pic.s -o %t.so.o
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.exe.o
+# RUN: ld.lld %t.so.o -shared -o %t.so
+# RUN: ld.lld %t.exe.o %t.so -o %t.exe
+# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
+# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
+
+# REQUIRES: mips
+
+# CHECK: __start:
+
+# CHECK-NEXT: 20000: df 82 80 20 ld $2, -32736($gp)
+# CHECK-NEXT: 20004: 64 42 00 18 daddiu $2, $2, 24
+# CHECK-NEXT: 20008: 24 42 80 38 addiu $2, $2, -32712
+# CHECK-NEXT: 2000c: 24 42 80 28 addiu $2, $2, -32728
+# CHECK-NEXT: 20010: 24 42 80 30 addiu $2, $2, -32720
+
+# CHECK: 0000000000020018 .text 00000000 foo
+# CHECK: 0000000000037ff0 .got 00000000 .hidden _gp
+# CHECK: 0000000000020000 .text 00000000 __start
+# CHECK: 0000000000020014 .text 00000000 bar
+
+# GOT: Relocations [
+# GOT-NEXT: ]
+# GOT-NEXT: Primary GOT {
+# GOT-NEXT: Canonical gp value: 0x37FF0
+# GOT-NEXT: Reserved entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30000
+# GOT-NEXT: Access: -32752
+# GOT-NEXT: Initial: 0x0
+# GOT-NEXT: Purpose: Lazy resolver
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30008
+# GOT-NEXT: Access: -32744
+# GOT-NEXT: Initial: 0x8000000000000000
+# GOT-NEXT: Purpose: Module pointer (GNU extension)
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Local entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30010
+# GOT-NEXT: Access: -32736
+# GOT-NEXT: Initial: 0x20000
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30018
+# GOT-NEXT: Access: -32728
+# GOT-NEXT: Initial: 0x20014
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30020
+# GOT-NEXT: Access: -32720
+# GOT-NEXT: Initial: 0x20018
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Global entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30028
+# GOT-NEXT: Access: -32712
+# GOT-NEXT: Initial: 0x0
+# GOT-NEXT: Value: 0x0
+# GOT-NEXT: Type: Function
+# GOT-NEXT: Section: Undefined
+# GOT-NEXT: Name: foo1a
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Number of TLS and multi-GOT entries: 0
+# GOT-NEXT: }
+
+ .text
+ .global __start, bar
+__start:
+ ld $v0,%got_page(foo)($gp) # R_MIPS_GOT_PAGE
+ daddiu $v0,$v0,%got_ofst(foo) # R_MIPS_GOT_OFST
+ addiu $v0,$v0,%got_disp(foo1a) # R_MIPS_GOT_DISP
+ addiu $v0,$v0,%got_disp(bar) # R_MIPS_GOT_DISP
+ addiu $v0,$v0,%got_disp(foo) # R_MIPS_GOT_DISP
+
+bar:
+ nop
+foo:
+ nop
diff --git a/test/ELF/mips-64-gprel-so.s b/test/ELF/mips-64-gprel-so.s
new file mode 100644
index 000000000000..437238ef5f26
--- /dev/null
+++ b/test/ELF/mips-64-gprel-so.s
@@ -0,0 +1,23 @@
+# Check setup of GP relative offsets in a function's prologue.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-objdump -d -t %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: foo:
+# CHECK-NEXT: 10000: 3c 1c 00 01 lui $gp, 1
+# CHECK-NEXT: 10004: 03 99 e0 2d daddu $gp, $gp, $25
+# CHECK-NEXT: 10008: 67 9c 7f f0 daddiu $gp, $gp, 32752
+
+# CHECK: 0000000000027ff0 .got 00000000 .hidden _gp
+# CHECK: 0000000000010000 .text 00000000 foo
+
+ .text
+ .global foo
+foo:
+ lui $gp,%hi(%neg(%gp_rel(foo)))
+ daddu $gp,$gp,$t9
+ daddiu $gp,$gp,%lo(%neg(%gp_rel(foo)))
diff --git a/test/ELF/mips-64-rels.s b/test/ELF/mips-64-rels.s
new file mode 100644
index 000000000000..7126afc1e595
--- /dev/null
+++ b/test/ELF/mips-64-rels.s
@@ -0,0 +1,46 @@
+# Check handling multiple MIPS N64 ABI relocations packed
+# into the single relocation record.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t.exe
+# RUN: llvm-objdump -d -s -t %t.exe | FileCheck %s
+# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
+
+# REQUIRES: mips
+
+# CHECK: __start:
+# CHECK-NEXT: 20000: 3c 1c 00 01 lui $gp, 1
+# ^-- 0x20000 - 0x37ff0
+# ^-- 0 - 0xfffffffffffe8010
+# ^-- %hi(0x17ff0)
+# CHECK: loc:
+# CHECK-NEXT: 20004: 67 9c 7f f0 daddiu $gp, $gp, 32752
+# ^-- 0x20000 - 0x37ff0
+# ^-- 0 - 0xfffffffffffe8010
+# ^-- %lo(0x17ff0)
+
+# CHECK: Contents of section .rodata:
+# CHECK-NEXT: 10190 ffffffff fffe8014
+# ^-- 0x20004 - 0x37ff0 = 0xfffffffffffe8014
+
+# CHECK: 0000000000020004 .text 00000000 loc
+# CHECK: 0000000000037ff0 .got 00000000 .hidden _gp
+# CHECK: 0000000000020000 .text 00000000 __start
+
+# REL: Relocations [
+# REL-NEXT: ]
+
+ .text
+ .global __start
+__start:
+ lui $gp,%hi(%neg(%gp_rel(__start))) # R_MIPS_GPREL16
+ # R_MIPS_SUB
+ # R_MIPS_HI16
+loc:
+ daddiu $gp,$gp,%lo(%neg(%gp_rel(__start))) # R_MIPS_GPREL16
+ # R_MIPS_SUB
+ # R_MIPS_LO16
+
+ .section .rodata,"a",@progbits
+ .gpdword(loc) # R_MIPS_GPREL32
+ # R_MIPS_64
diff --git a/test/ELF/mips-64.s b/test/ELF/mips-64.s
new file mode 100644
index 000000000000..689669e4b09f
--- /dev/null
+++ b/test/ELF/mips-64.s
@@ -0,0 +1,63 @@
+# Check R_MIPS_64 relocation calculation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t.so
+# RUN: llvm-objdump -t %t.so | FileCheck -check-prefix=SYM %s
+# RUN: llvm-readobj -r -dynamic-table -mips-plt-got %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+ .global __start
+__start:
+ nop
+
+ .data
+ .type v1,@object
+ .size v1,4
+v1:
+ .quad 0
+
+ .globl v2
+ .type v2,@object
+ .size v2,8
+v2:
+ .quad v2+8 # R_MIPS_64 target v2 addend 8
+ .quad v1 # R_MIPS_64 target v1 addend 0
+
+
+# SYM: SYMBOL TABLE:
+# SYM: 00030000 l .data 00000004 v1
+# SYM: 00030008 g .data 00000008 v2
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section (7) .rela.dyn {
+# CHECK-NEXT: 0x30010 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE - 0x30000
+# ^-- v1
+# CHECK-NEXT: 0x30008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE v2 0x8
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# CHECK: DynamicSection [
+# CHECK: Tag Type Name/Value
+# CHECK: 0x0000000000000008 RELASZ 48 (bytes)
+# CHECK: 0x0000000000000009 RELAENT 24 (bytes)
+
+# CHECK: Primary GOT {
+# CHECK-NEXT: Canonical gp value:
+# CHECK-NEXT: Reserved entries [
+# CHECK: ]
+# CHECK-NEXT: Local entries [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Access:
+# CHECK-NEXT: Initial: 0x30008
+# CHECK-NEXT: Value: 0x30008
+# CHECK-NEXT: Type: Object
+# CHECK-NEXT: Section: .data
+# CHECK-NEXT: Name: v2
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Number of TLS and multi-GOT entries: 0
+# CHECK-NEXT: }
diff --git a/test/ELF/mips-align-err.s b/test/ELF/mips-align-err.s
new file mode 100644
index 000000000000..28b192ac29f3
--- /dev/null
+++ b/test/ELF/mips-align-err.s
@@ -0,0 +1,12 @@
+# REQUIRES: mips
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o \
+# RUN: -mcpu=mips32r6
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: -mcpu=mips32r6 %S/Inputs/mips-align-err.s -o %t2.o
+# RUN: not ld.lld %t.o %t2.o -o %t.exe 2>&1 | FileCheck %s
+# CHECK: improper alignment for relocation R_MIPS_PC16
+
+ .globl __start
+__start:
+.zero 1
+ beqc $5, $6, _foo # R_MIPS_PC16
diff --git a/test/ELF/mips-dynamic.s b/test/ELF/mips-dynamic.s
index 626a3556d361..3cb5c63a49f2 100644
--- a/test/ELF/mips-dynamic.s
+++ b/test/ELF/mips-dynamic.s
@@ -8,6 +8,10 @@
# RUN: llvm-readobj -sections -dynamic-table %t.exe \
# RUN: | FileCheck -check-prefix=EXE %s
+# RUN: ld.lld %t.o --image-base=0x123000 %td.so -o %t.exe
+# RUN: llvm-readobj -sections -dynamic-table %t.exe \
+# RUN: | FileCheck -check-prefix=IMAGE_BASE %s
+
# RUN: ld.lld -shared %t.o %td.so -o %t.so
# RUN: llvm-readobj -sections -dyn-symbols -dynamic-table %t.so \
# RUN: | FileCheck -check-prefix=DSO %s
@@ -24,6 +28,7 @@
# EXE-NEXT: Type: SHT_PROGBITS
# EXE-NEXT: Flags [ (0x10000003)
# EXE-NEXT: SHF_ALLOC
+# EXE-NEXT: SHF_MIPS_GPREL
# EXE-NEXT: SHF_WRITE
# EXE-NEXT: ]
# EXE-NEXT: Address: [[GOTADDR:0x[0-9a-f]+]]
@@ -44,13 +49,15 @@
# EXE-DAG: 0x00000003 PLTGOT [[GOTADDR]]
# EXE-DAG: 0x70000001 MIPS_RLD_VERSION 1
# EXE-DAG: 0x70000005 MIPS_FLAGS NOTPOT
-# EXE-DAG: 0x70000006 MIPS_BASE_ADDRESS
+# EXE-DAG: 0x70000006 MIPS_BASE_ADDRESS 0x10000
# EXE-DAG: 0x7000000A MIPS_LOCAL_GOTNO 2
-# EXE-DAG: 0x70000011 MIPS_SYMTABNO 1
-# EXE-DAG: 0x70000013 MIPS_GOTSYM 0x1
+# EXE-DAG: 0x70000011 MIPS_SYMTABNO 2
+# EXE-DAG: 0x70000013 MIPS_GOTSYM 0x2
# EXE-DAG: 0x70000016 MIPS_RLD_MAP [[RLDMAPADDR]]
# EXE: ]
+# IMAGE_BASE: 0x70000006 MIPS_BASE_ADDRESS 0x123000
+
# DSO: Sections [
# DSO: Name: .dynamic
# DSO-NEXT: Type: SHT_DYNAMIC
@@ -61,6 +68,7 @@
# DSO-NEXT: Type: SHT_PROGBITS
# DSO-NEXT: Flags [ (0x10000003)
# DSO-NEXT: SHF_ALLOC
+# DSO-NEXT: SHF_MIPS_GPREL
# DSO-NEXT: SHF_WRITE
# DSO-NEXT: ]
# DSO-NEXT: Address: [[GOTADDR:0x[0-9a-f]+]]
@@ -69,7 +77,6 @@
# DSO: ]
# DSO: DynamicSymbols [
# DSO: Name: @
-# DSO: Name: _gp@
# DSO: Name: __start@
# DSO: Name: _foo@
# DSO: ]
@@ -80,8 +87,8 @@
# DSO-DAG: 0x70000005 MIPS_FLAGS NOTPOT
# DSO-DAG: 0x70000006 MIPS_BASE_ADDRESS 0x0
# DSO-DAG: 0x7000000A MIPS_LOCAL_GOTNO 2
-# DSO-DAG: 0x70000011 MIPS_SYMTABNO 4
-# DSO-DAG: 0x70000013 MIPS_GOTSYM 0x4
+# DSO-DAG: 0x70000011 MIPS_SYMTABNO 3
+# DSO-DAG: 0x70000013 MIPS_GOTSYM 0x3
# DSO: ]
.text
diff --git a/test/ELF/mips-gnu-hash.s b/test/ELF/mips-gnu-hash.s
index 4b11f213518c..288d54043fc1 100644
--- a/test/ELF/mips-gnu-hash.s
+++ b/test/ELF/mips-gnu-hash.s
@@ -6,7 +6,7 @@
# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
# RUN: not ld.lld -shared -hash-style=gnu %t-el.o -o %t-el.so 2>&1 | FileCheck %s
-# CHECK: The .gnu.hash section is not compatible with the MIPS target.
+# CHECK: the .gnu.hash section is not compatible with the MIPS target.
# REQUIRES: mips
diff --git a/test/ELF/mips-got-and-copy.s b/test/ELF/mips-got-and-copy.s
new file mode 100644
index 000000000000..453b8c957b56
--- /dev/null
+++ b/test/ELF/mips-got-and-copy.s
@@ -0,0 +1,57 @@
+# REQUIRES: mips
+
+# If there are two relocations such that the first one requires
+# dynamic COPY relocation, the second one requires GOT entry
+# creation, linker should create both - dynamic relocation
+# and GOT entry.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.so.o -shared -o %t.so
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section (7) .rel.dyn {
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data0
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data1
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Primary GOT {
+# CHECK-NEXT: Canonical gp value: 0x37FF0
+# CHECK-NEXT: Reserved entries [
+# CHECK: ]
+# CHECK-NEXT: Local entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x30008
+# CHECK-NEXT: Access: -32744
+# CHECK-NEXT: Initial: 0x40010
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x3000C
+# CHECK-NEXT: Access: -32740
+# CHECK-NEXT: Initial: 0x40014
+# CHECK-NEXT: Value: 0x40014
+# CHECK-NEXT: Type: Object (0x1)
+# CHECK-NEXT: Section: .bss (0xD)
+# CHECK-NEXT: Name: data1@ (7)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Number of TLS and multi-GOT entries: 0
+# CHECK-NEXT: }
+
+ .text
+ .global __start
+__start:
+ # Case A: 'got' relocation goes before 'copy' relocation
+ lui $t0,%hi(data0) # R_MIPS_HI16 - requires R_MISP_COPY relocation
+ addi $t0,$t0,%lo(data0)
+ lw $t0,%got(data0)($gp) # R_MIPS_GOT16 - requires GOT entry
+
+ # Case B: 'copy' relocation goes before 'got' relocation
+ lw $t0,%got(data1)($gp) # R_MIPS_GOT16 - requires GOT entry
+ lui $t0,%hi(data1) # R_MIPS_HI16 - requires R_MISP_COPY relocation
+ addi $t0,$t0,%lo(data1)
diff --git a/test/ELF/mips-got-extsym.s b/test/ELF/mips-got-extsym.s
new file mode 100644
index 000000000000..1cf99aeed49b
--- /dev/null
+++ b/test/ELF/mips-got-extsym.s
@@ -0,0 +1,59 @@
+# Check creation of GOT entries for global symbols in case of executable
+# file linking. Symbols defined in DSO should get entries in the global part
+# of the GOT. Symbols defined in the executable itself should get local GOT
+# entries and does not need a row in .dynsym table.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o
+# RUN: ld.lld -shared %t.so.o -o %t.so
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-readobj -dt -t -mips-plt-got %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Symbols [
+# CHECK: Symbol {
+# CHECK: Name: _foo
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+
+# CHECK: Symbol {
+# CHECK: Name: bar
+# CHECK-NEXT: Value: 0x20008
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+
+# CHECK: DynamicSymbols [
+# CHECK-NOT: Name: bar
+
+# CHECK: Local entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x30008
+# CHECK-NEXT: Access: -32744
+# CHECK-NEXT: Initial: 0x20008
+# ^-- bar
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x3000C
+# CHECK-NEXT: Access: -32740
+# CHECK-NEXT: Initial: 0x0
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: Name: _foo@
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+ .text
+ .globl __start
+__start:
+ lw $t0,%got(bar)($gp)
+ lw $t0,%got(_foo)($gp)
+
+.global bar
+bar:
+ .word 0
diff --git a/test/ELF/mips-got-redundant.s b/test/ELF/mips-got-redundant.s
new file mode 100644
index 000000000000..07c3c249f4fa
--- /dev/null
+++ b/test/ELF/mips-got-redundant.s
@@ -0,0 +1,58 @@
+# Check number of redundant entries in the local part of MIPS GOT.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-readobj -mips-plt-got %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Local entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x20008
+# CHECK-NEXT: Access: -32744
+# CHECK-NEXT: Initial: 0x30000
+# ^-- loc1
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x2000C
+# CHECK-NEXT: Access: -32740
+# CHECK-NEXT: Initial: 0x40000
+# ^-- loc2, loc3, loc4
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x20010
+# CHECK-NEXT: Access: -32736
+# CHECK-NEXT: Initial: 0x40008
+# ^-- glb1
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+ .text
+ .globl foo
+foo:
+ lw $t0, %got(loc1)($gp)
+ addi $t0, $t0, %lo(loc1)
+ lw $t0, %got(loc2)($gp)
+ addi $t0, $t0, %lo(loc2)
+ lw $t0, %got(loc3)($gp)
+ addi $t0, $t0, %lo(loc3)
+ lw $t0, %got(loc4)($gp)
+ addi $t0, $t0, %lo(loc4)
+ lw $t0, %got(glb1)($gp)
+ lw $t0, %got(glb1)($gp)
+
+ .section .data.1,"aw",%progbits
+loc1:
+ .space 0x10000
+loc2:
+ .word 0
+loc3:
+ .word 0
+ .global glb1
+ .hidden glb1
+glb1:
+ .word 0
+
+ .section .data.2,"aw",%progbits
+loc4:
+ .word 0
diff --git a/test/ELF/mips-got-relocs.s b/test/ELF/mips-got-relocs.s
index 27180fbf82ea..c44cf90b7be3 100644
--- a/test/ELF/mips-got-relocs.s
+++ b/test/ELF/mips-got-relocs.s
@@ -47,10 +47,11 @@ v1:
# EXE_SYM: Sections:
# EXE_SYM: .got 0000000c 0000000000030000 DATA
# EXE_SYM: SYMBOL TABLE:
-# EXE_SYM: 00037ff0 *ABS* 00000000 _gp
+# EXE_SYM: 00037ff0 .got 00000000 .hidden _gp
# ^-- .got + GP offset (0x7ff0)
# EXE_SYM: 00040000 g .data 00000004 v1
+
# EXE_GOT_BE: Contents of section .got:
# EXE_GOT_BE: 30000 00000000 80000000 00040000
# ^ ^ ^-- v1 (0x40000)
@@ -70,7 +71,7 @@ v1:
# DSO_SYM: Sections:
# DSO_SYM: .got 0000000c 0000000000020000 DATA
# DSO_SYM: SYMBOL TABLE:
-# DSO_SYM: 00027ff0 *ABS* 00000000 _gp
+# DSO_SYM: 00027ff0 .got 00000000 .hidden _gp
# ^-- .got + GP offset (0x7ff0)
# DSO_SYM: 00030000 g .data 00000004 v1
diff --git a/test/ELF/mips-got-weak.s b/test/ELF/mips-got-weak.s
new file mode 100644
index 000000000000..a77924692a10
--- /dev/null
+++ b/test/ELF/mips-got-weak.s
@@ -0,0 +1,172 @@
+# Check R_MIPS_GOT16 relocation against weak symbols.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t1.so
+# RUN: llvm-readobj -r -dt -dynamic-table -mips-plt-got %t1.so \
+# RUN: | FileCheck -check-prefix=NOSYM %s
+# RUN: ld.lld %t.o -shared -Bsymbolic -o %t2.so
+# RUN: llvm-readobj -r -dt -dynamic-table -mips-plt-got %t2.so \
+# RUN: | FileCheck -check-prefix=SYM %s
+
+# REQUIRES: mips
+
+# NOSYM: Relocations [
+# NOSYM-NEXT: ]
+
+# NOSYM: Symbol {
+# NOSYM: Name: foo
+# NOSYM-NEXT: Value: 0x30000
+# NOSYM-NEXT: Size: 0
+# NOSYM-NEXT: Binding: Weak
+# NOSYM-NEXT: Type: None
+# NOSYM-NEXT: Other: 0
+# NOSYM-NEXT: Section: .data
+# NOSYM-NEXT: }
+# NOSYM-NEXT: Symbol {
+# NOSYM-NEXT: Name: bar
+# NOSYM-NEXT: Value: 0x0
+# NOSYM-NEXT: Size: 0
+# NOSYM-NEXT: Binding: Weak
+# NOSYM-NEXT: Type: None
+# NOSYM-NEXT: Other: 0
+# NOSYM-NEXT: Section: Undefined
+# NOSYM-NEXT: }
+# NOSYM-NEXT: Symbol {
+# NOSYM-NEXT: Name: sym
+# NOSYM-NEXT: Value: 0x30004
+# NOSYM-NEXT: Size: 0
+# NOSYM-NEXT: Binding: Global
+# NOSYM-NEXT: Type: None
+# NOSYM-NEXT: Other: 0
+# NOSYM-NEXT: Section: .data
+# NOSYM-NEXT: }
+# NOSYM-NEXT: ]
+
+# NOSYM: 0x70000011 MIPS_SYMTABNO 4
+# NOSYM-NEXT: 0x7000000A MIPS_LOCAL_GOTNO 2
+# NOSYM-NEXT: 0x70000013 MIPS_GOTSYM 0x1
+
+# NOSYM: Primary GOT {
+# NOSYM-NEXT: Canonical gp value: 0x27FF0
+# NOSYM-NEXT: Reserved entries [
+# NOSYM-NEXT: Entry {
+# NOSYM-NEXT: Address: 0x20000
+# NOSYM-NEXT: Access: -32752
+# NOSYM-NEXT: Initial: 0x0
+# NOSYM-NEXT: Purpose: Lazy resolver
+# NOSYM-NEXT: }
+# NOSYM-NEXT: Entry {
+# NOSYM-NEXT: Address: 0x20004
+# NOSYM-NEXT: Access: -32748
+# NOSYM-NEXT: Initial: 0x80000000
+# NOSYM-NEXT: Purpose: Module pointer (GNU extension)
+# NOSYM-NEXT: }
+# NOSYM-NEXT: ]
+# NOSYM-NEXT: Local entries [
+# NOSYM-NEXT: ]
+# NOSYM-NEXT: Global entries [
+# NOSYM-NEXT: Entry {
+# NOSYM-NEXT: Address: 0x20008
+# NOSYM-NEXT: Access: -32744
+# NOSYM-NEXT: Initial: 0x30000
+# NOSYM-NEXT: Value: 0x30000
+# NOSYM-NEXT: Type: None
+# NOSYM-NEXT: Section: .data
+# NOSYM-NEXT: Name: foo
+# NOSYM-NEXT: }
+# NOSYM-NEXT: Entry {
+# NOSYM-NEXT: Address: 0x2000C
+# NOSYM-NEXT: Access: -32740
+# NOSYM-NEXT: Initial: 0x0
+# NOSYM-NEXT: Value: 0x0
+# NOSYM-NEXT: Type: None
+# NOSYM-NEXT: Section: Undefined
+# NOSYM-NEXT: Name: bar
+# NOSYM-NEXT: }
+# NOSYM-NEXT: Entry {
+# NOSYM-NEXT: Address: 0x20010
+# NOSYM-NEXT: Access: -32736
+# NOSYM-NEXT: Initial: 0x30004
+# NOSYM-NEXT: Value: 0x30004
+# NOSYM-NEXT: Type: None
+# NOSYM-NEXT: Section: .data
+# NOSYM-NEXT: Name: sym
+# NOSYM-NEXT: }
+# NOSYM-NEXT: ]
+# NOSYM-NEXT: Number of TLS and multi-GOT entries: 0
+# NOSYM-NEXT: }
+
+# SYM: Relocations [
+# SYM-NEXT: ]
+
+# SYM: Symbol {
+# SYM: Name: bar
+# SYM-NEXT: Value: 0x0
+# SYM-NEXT: Size: 0
+# SYM-NEXT: Binding: Weak
+# SYM-NEXT: Type: None
+# SYM-NEXT: Other: 0
+# SYM-NEXT: Section: Undefined
+# SYM-NEXT: }
+# SYM-NEXT: ]
+
+# SYM: 0x70000011 MIPS_SYMTABNO 4
+# SYM-NEXT: 0x7000000A MIPS_LOCAL_GOTNO 4
+# SYM-NEXT: 0x70000013 MIPS_GOTSYM 0x3
+
+# SYM: Primary GOT {
+# SYM-NEXT: Canonical gp value: 0x27FF0
+# SYM-NEXT: Reserved entries [
+# SYM-NEXT: Entry {
+# SYM-NEXT: Address: 0x20000
+# SYM-NEXT: Access: -32752
+# SYM-NEXT: Initial: 0x0
+# SYM-NEXT: Purpose: Lazy resolver
+# SYM-NEXT: }
+# SYM-NEXT: Entry {
+# SYM-NEXT: Address: 0x20004
+# SYM-NEXT: Access: -32748
+# SYM-NEXT: Initial: 0x80000000
+# SYM-NEXT: Purpose: Module pointer (GNU extension)
+# SYM-NEXT: }
+# SYM-NEXT: ]
+# SYM-NEXT: Local entries [
+# SYM-NEXT: Entry {
+# SYM-NEXT: Address: 0x20008
+# SYM-NEXT: Access: -32744
+# SYM-NEXT: Initial: 0x30000
+# SYM-NEXT: }
+# SYM-NEXT: Entry {
+# SYM-NEXT: Address: 0x2000C
+# SYM-NEXT: Access: -32740
+# SYM-NEXT: Initial: 0x30004
+# SYM-NEXT: }
+# SYM-NEXT: ]
+# SYM-NEXT: Global entries [
+# SYM-NEXT: Entry {
+# SYM-NEXT: Address: 0x20010
+# SYM-NEXT: Access: -32736
+# SYM-NEXT: Initial: 0x0
+# SYM-NEXT: Value: 0x0
+# SYM-NEXT: Type: None
+# SYM-NEXT: Section: Undefined
+# SYM-NEXT: Name: bar
+# SYM-NEXT: }
+# SYM-NEXT: ]
+# SYM-NEXT: Number of TLS and multi-GOT entries: 0
+# SYM-NEXT: }
+
+ .text
+ .global sym
+ .weak foo,bar
+func:
+ lw $t0,%got(foo)($gp)
+ lw $t0,%got(bar)($gp)
+ lw $t0,%got(sym)($gp)
+
+ .data
+ .weak foo
+foo:
+ .word 0
+sym:
+ .word 0
diff --git a/test/ELF/mips-got16.s b/test/ELF/mips-got16.s
new file mode 100644
index 000000000000..ef80418ef032
--- /dev/null
+++ b/test/ELF/mips-got16.s
@@ -0,0 +1,120 @@
+# Check R_MIPS_GOT16 relocation calculation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-objdump -d -t %t.so | FileCheck %s
+# RUN: llvm-readobj -r -mips-plt-got %t.so | FileCheck -check-prefix=GOT %s
+
+# REQUIRES: mips
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: __start:
+# CHECK-NEXT: 10000: 8f 88 80 18 lw $8, -32744($gp)
+# CHECK-NEXT: 10004: 21 08 00 2c addi $8, $8, 44
+# CHECK-NEXT: 10008: 8f 88 80 1c lw $8, -32740($gp)
+# CHECK-NEXT: 1000c: 21 08 90 00 addi $8, $8, -28672
+# CHECK-NEXT: 10010: 8f 88 80 20 lw $8, -32736($gp)
+# CHECK-NEXT: 10014: 21 08 90 04 addi $8, $8, -28668
+# CHECK-NEXT: 10018: 8f 88 80 20 lw $8, -32736($gp)
+# CHECK-NEXT: 1001c: 21 08 10 04 addi $8, $8, 4100
+# CHECK-NEXT: 10020: 8f 88 80 28 lw $8, -32728($gp)
+# CHECK-NEXT: 10024: 21 08 10 08 addi $8, $8, 4104
+# CHECK-NEXT: 10028: 8f 88 80 2c lw $8, -32724($gp)
+#
+# CHECK: SYMBOL TABLE:
+# CHECK: 00051008 .data 00000000 .hidden bar
+# CHECK: 00000000 *UND* 00000000 foo
+
+# GOT: Relocations [
+# GOT-NEXT: ]
+
+# GOT: Primary GOT {
+# GOT-NEXT: Canonical gp value: 0x27FF0
+# GOT-NEXT: Reserved entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x20000
+# GOT-NEXT: Access: -32752
+# GOT-NEXT: Initial: 0x0
+# GOT-NEXT: Purpose: Lazy resolver
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x20004
+# GOT-NEXT: Access: -32748
+# GOT-NEXT: Initial: 0x80000000
+# GOT-NEXT: Purpose: Module pointer (GNU extension)
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Local entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x20008
+# GOT-NEXT: Access: -32744
+# GOT-NEXT: Initial: 0x10000
+# ^-- (0x1002c + 0x8000) & ~0xffff
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x2000C
+# GOT-NEXT: Access: -32740
+# GOT-NEXT: Initial: 0x40000
+# ^-- (0x39000 + 0x8000) & ~0xffff
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x20010
+# GOT-NEXT: Access: -32736
+# GOT-NEXT: Initial: 0x50000
+# ^-- (0x39000 + 0x10004 + 0x8000) & ~0xffff
+# ^-- (0x39000 + 0x18004 + 0x8000) & ~0xffff
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x20014
+# GOT-NEXT: Access: -32732
+# GOT-NEXT: Initial: 0x0
+# ^-- redundant unused entry
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x20018
+# GOT-NEXT: Access: -327
+# GOT-NEXT: Initial: 0x51008
+# ^-- 'bar' address
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Global entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x2001C
+# GOT-NEXT: Access: -32724
+# GOT-NEXT: Initial: 0x0
+# GOT-NEXT: Value: 0x0
+# GOT-NEXT: Type: None
+# GOT-NEXT: Section: Undefined
+# GOT-NEXT: Name: foo@
+# GOT-NEXT: }
+# GOT-NEXT: ]
+# GOT-NEXT: Number of TLS and multi-GOT entries: 0
+# GOT-NEXT: }
+
+ .text
+ .globl __start
+__start:
+ lw $t0,%got($LC0)($gp)
+ addi $t0,$t0,%lo($LC0)
+ lw $t0,%got($LC1)($gp)
+ addi $t0,$t0,%lo($LC1)
+ lw $t0,%got($LC1+0x10004)($gp)
+ addi $t0,$t0,%lo($LC1+0x10004)
+ lw $t0,%got($LC1+0x18004)($gp)
+ addi $t0,$t0,%lo($LC1+0x18004)
+ lw $t0,%got(bar)($gp)
+ addi $t0,$t0,%lo(bar)
+ lw $t0,%got(foo)($gp)
+$LC0:
+ nop
+
+ .data
+ .space 0x9000
+$LC1:
+ .word 0
+ .space 0x18000
+ .word 0
+.global bar
+.hidden bar
+bar:
+ .word 0
diff --git a/test/ELF/mips-gp-disp.s b/test/ELF/mips-gp-disp.s
index a08829c18bd4..7a0fd6409d18 100644
--- a/test/ELF/mips-gp-disp.s
+++ b/test/ELF/mips-gp-disp.s
@@ -11,17 +11,20 @@
# REQUIRES: mips
-# INT-SO-NOT: Name: _gp_disp
+# INT-SO: Name: _gp_disp
+# INT-SO-NEXT: Value:
+# INT-SO-NEXT: Size:
+# INT-SO-NEXT: Binding: Local
# EXT-SO: Name: _gp_disp
-# EXT-SO-NEXT: Value: 0x20010
+# EXT-SO-NEXT: Value: 0x20000
# DIS: Disassembly of section .text:
# DIS-NEXT: __start:
# DIS-NEXT: 10000: 3c 08 00 01 lui $8, 1
# DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
# ^-- 0x37ff0 & 0xffff
-# DIS: 00027ff0 *ABS* 00000000 _gp
+# DIS: 00027ff0 .got 00000000 .hidden _gp
# REL: Relocations [
# REL-NEXT: ]
diff --git a/test/ELF/mips-gp-local.s b/test/ELF/mips-gp-local.s
new file mode 100644
index 000000000000..8bb3c236edf0
--- /dev/null
+++ b/test/ELF/mips-gp-local.s
@@ -0,0 +1,20 @@
+# Check handling of relocations against __gnu_local_gp symbol.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld -o %t.exe %t.o
+# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: __start:
+# CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 3
+# CHECK-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752
+
+# CHECK: 00037ff0 .got 00000000 .hidden _gp
+
+ .text
+ .globl __start
+__start:
+ lui $t0,%hi(__gnu_local_gp)
+ addi $t0,$t0,%lo(__gnu_local_gp)
diff --git a/test/ELF/mips-gprel32-relocs-gp0.test b/test/ELF/mips-gprel32-relocs-gp0.test
new file mode 100644
index 000000000000..6cc837ef7889
--- /dev/null
+++ b/test/ELF/mips-gprel32-relocs-gp0.test
@@ -0,0 +1,31 @@
+# Check R_MIPS_GPREL32 relocation calculation if input file conatins
+# non-zero GP0 value in the .reginfo section.
+# FIXME: The only way to get an object file with non-zero GP0 value
+# is to link multiple object files with GOT relocations using '-r'
+# option. LLD does not calculate and generate GP0 correctly so we
+# use a binary input in this test. The input object file is a result
+# of linking two object files with R_MIPS_GPREL32 relocations.
+
+# RUN: ld.lld -shared -o %t.so %S/Inputs/mips-gprel32-gp0.o
+# RUN: llvm-objdump -s %S/Inputs/mips-gprel32-gp0.o \
+# RUN: | FileCheck -check-prefix=OBJ %s
+# RUN: llvm-objdump -s -t %t.so | FileCheck %s
+
+# OBJ: Contents of section .reginfo:
+# OBJ-NEXT: 0000 00000001 00000000 00000000 00000000
+# OBJ-NEXT: 0010 00000000 00007fef
+# ^-- GP0 value
+# OBJ: Contents of section .rodata:
+# OBJ-NEXT: 0000 ffff8011 ffff8011
+# ^-- foo addend
+# ^-- bar addend
+
+# CHECK: Contents of section .rodata:
+# CHECK: 012c fffe8010 fffe8020
+# ^ 0x10000 + 0xffff8011 + 0x7fef - 0x27ff0
+# ^ 0x10010 + 0xffff8011 + 0x7fef - 0x27ff0
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00010000 .text 00000000 foo
+# CHECK: 00010010 .text 00000000 bar
+# CHECK: 00027ff0 .got 00000000 .hidden _gp
diff --git a/test/ELF/mips-gprel32-relocs.s b/test/ELF/mips-gprel32-relocs.s
index 4f93d50363c0..fa1c5cfe9956 100644
--- a/test/ELF/mips-gprel32-relocs.s
+++ b/test/ELF/mips-gprel32-relocs.s
@@ -28,4 +28,4 @@ v1:
# CHECK: SYMBOL TABLE:
# CHECK: 00010008 .text 00000000 bar
# CHECK: 00010004 .text 00000000 foo
-# CHECK: 00027ff0 *ABS* 00000000 _gp
+# CHECK: 00027ff0 .got 00000000 .hidden _gp
diff --git a/test/ELF/mips-hilo-gp-disp.s b/test/ELF/mips-hilo-gp-disp.s
index e2e9ae7bc2e2..37cf90d9728b 100644
--- a/test/ELF/mips-hilo-gp-disp.s
+++ b/test/ELF/mips-hilo-gp-disp.s
@@ -16,6 +16,9 @@ __start:
lui $t0,%hi(_gp_disp)
addi $t0,$t0,%lo(_gp_disp)
lw $v0,%call16(_foo)($gp)
+bar:
+ lui $t0,%hi(_gp_disp)
+ addi $t0,$t0,%lo(_gp_disp)
# EXE: Disassembly of section .text:
# EXE-NEXT: __start:
@@ -23,11 +26,16 @@ __start:
# ^-- %hi(0x37ff0-0x20000)
# EXE-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752
# ^-- %lo(0x37ff0-0x20004+4)
+# EXE: bar:
+# EXE-NEXT: 2000c: 3c 08 00 01 lui $8, 1
+# ^-- %hi(0x37ff0-0x2000c)
+# EXE-NEXT: 20010: 21 08 7f e4 addi $8, $8, 32740
+# ^-- %lo(0x37ff0-0x20010+4)
# EXE: SYMBOL TABLE:
-# EXE: 00037ff0 *ABS* 00000000 _gp
+# EXE: 0002000c .text 00000000 bar
+# EXE: 00037ff0 .got 00000000 .hidden _gp
# EXE: 00020000 .text 00000000 __start
-# EXE: 00020010 .text 00000000 _foo
# SO: Disassembly of section .text:
# SO-NEXT: __start:
@@ -35,8 +43,13 @@ __start:
# ^-- %hi(0x27ff0-0x10000)
# SO-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
# ^-- %lo(0x27ff0-0x10004+4)
+# SO: bar:
+# SO-NEXT: 1000c: 3c 08 00 01 lui $8, 1
+# ^-- %hi(0x27ff0-0x1000c)
+# SO-NEXT: 10010: 21 08 7f e4 addi $8, $8, 32740
+# ^-- %lo(0x27ff0-0x10010+4)
# SO: SYMBOL TABLE:
-# SO: 00027ff0 *ABS* 00000000 _gp
+# SO: 0001000c .text 00000000 bar
+# SO: 00027ff0 .got 00000000 .hidden _gp
# SO: 00010000 .text 00000000 __start
-# SO: 00010010 .text 00000000 _foo
diff --git a/test/ELF/mips-hilo-hi-only.s b/test/ELF/mips-hilo-hi-only.s
index ad18a9f9161a..97808b515da5 100644
--- a/test/ELF/mips-hilo-hi-only.s
+++ b/test/ELF/mips-hilo-hi-only.s
@@ -14,7 +14,7 @@ __start:
_label:
nop
-# WARN: Can't find matching R_MIPS_LO16 relocation for R_MIPS_HI16
+# WARN: can't find matching R_MIPS_LO16 relocation for R_MIPS_HI16
# CHECK: Disassembly of section .text:
# CHECK-NEXT: __start:
diff --git a/test/ELF/mips-hilo.s b/test/ELF/mips-hilo.s
index d5de9422c427..4f1452831ae6 100644
--- a/test/ELF/mips-hilo.s
+++ b/test/ELF/mips-hilo.s
@@ -34,20 +34,20 @@ g1:
# CHECK-NEXT: __start:
# CHECK-NEXT: 20000: 3c 08 00 02 lui $8, 2
# ^-- %hi(__start+4)
-# CHECK-NEXT: 20004: 3c 09 00 03 lui $9, 3
+# CHECK-NEXT: 20004: 3c 09 00 04 lui $9, 4
# ^-- %hi(g1+8)
# CHECK-NEXT: 20008: 21 08 00 04 addi $8, $8, 4
# ^-- %lo(__start+4)
# CHECK-NEXT: 2000c: 21 08 00 0c addi $8, $8, 12
# ^-- %lo(g1+8)
-# CHECK-NEXT: 20010: 3c 08 00 04 lui $8, 4
+# CHECK-NEXT: 20010: 3c 08 00 05 lui $8, 5
# ^-- %hi(l1+0x10000-4)
-# CHECK-NEXT: 20014: 3c 09 00 05 lui $9, 5
+# CHECK-NEXT: 20014: 3c 09 00 06 lui $9, 6
# ^-- %hi(l1+0x20000-4)
# CHECK-NEXT: 20018: 21 08 ff fc addi $8, $8, -4
# ^-- %lo(l1-4)
# CHECK: SYMBOL TABLE:
-# CHECK: 0030000 l .data 00000004 l1
+# CHECK: 0040000 l .data 00000004 l1
# CHECK: 0020000 .text 00000000 __start
-# CHECK: 0030004 g .data 00000004 g1
+# CHECK: 0040004 g .data 00000004 g1
diff --git a/test/ELF/mips-jalr.test b/test/ELF/mips-jalr.test
index 4bdf8b6e7f00..c1b119c701b6 100644
--- a/test/ELF/mips-jalr.test
+++ b/test/ELF/mips-jalr.test
@@ -1,13 +1,18 @@
# Check that lld ignores R_MIPS_JALR relocation for now.
-# RUN: yaml2obj -format elf %s -o %t.o
+# RUN: yaml2obj %s -o %t.o
# RUN: ld.lld %t.o -o %t.so -shared
# RUN: llvm-objdump -d %t.so | FileCheck %s
+# RUN: llvm-readobj -relocations %t.so | FileCheck -check-prefix=REL %s
# REQUIRES: mips
# CHECK: 10000: 09 f8 20 03 jalr $25
+# REL: Relocations [
+# REL-NEXT: ]
+
+!ELF
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
diff --git a/test/ELF/mips-lo16-not-relative.s b/test/ELF/mips-lo16-not-relative.s
new file mode 100644
index 000000000000..614e6396cc92
--- /dev/null
+++ b/test/ELF/mips-lo16-not-relative.s
@@ -0,0 +1,23 @@
+# Check that R_MIPS_LO16 relocation is handled as non-relative,
+# and if a target symbol is a DSO data symbol, LLD create a copy
+# relocation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o
+# RUN: ld.lld %t.so.o -shared -o %t.so
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-readobj -r %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section (7) .rel.dyn {
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data0 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+ .text
+ .global __start
+__start:
+ addi $t0, $t0, %lo(data0)
diff --git a/test/ELF/mips-nonalloc.s b/test/ELF/mips-nonalloc.s
new file mode 100644
index 000000000000..7b0aa9469f9f
--- /dev/null
+++ b/test/ELF/mips-nonalloc.s
@@ -0,0 +1,21 @@
+# Check reading addends for relocations in non-allocatable sections.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %S/Inputs/mips-nonalloc.s -o %t2.o
+# RUN: ld.lld %t1.o %t2.o -o %t.exe
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Contents of section .debug_info:
+# CHECK-NEXT: 0000 ffffffff 00020000 00020000
+# ^--------^-- __start
+
+ .global __start
+__start:
+ nop
+
+.section .debug_info
+ .word 0xffffffff
+ .word __start
diff --git a/test/ELF/mips-npic-call-pic.s b/test/ELF/mips-npic-call-pic.s
new file mode 100644
index 000000000000..dbf053570bd9
--- /dev/null
+++ b/test/ELF/mips-npic-call-pic.s
@@ -0,0 +1,144 @@
+# REQUIRES: mips
+# Check LA25 stubs creation. This stub code is necessary when
+# non-PIC code calls PIC function.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %p/Inputs/mips-pic.s -o %t-pic.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-npic.o
+# RUN: ld.lld %t-npic.o %t-pic.o %p/Inputs/mips-sto-pic.o -o %t.exe
+# RUN: llvm-objdump -d %t.exe | FileCheck %s
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: __start:
+# CHECK-NEXT: 20000: 0c 00 80 0e jal 131128 <foo1b+0x4>
+# ^-- .pic.foo1a
+# CHECK-NEXT: 20004: 00 00 00 00 nop
+# CHECK-NEXT: 20008: 0c 00 80 19 jal 131172 <foo2+0x4>
+# ^-- .pic.foo2
+# CHECK-NEXT: 2000c: 00 00 00 00 nop
+# CHECK-NEXT: 20010: 0c 00 80 12 jal 131144 <foo1b+0x14>
+# ^-- .pic.foo1b
+# CHECK-NEXT: 20014: 00 00 00 00 nop
+# CHECK-NEXT: 20018: 0c 00 80 19 jal 131172 <foo2+0x4>
+# ^-- .pic.foo2
+# CHECK-NEXT: 2001c: 00 00 00 00 nop
+# CHECK-NEXT: 20020: 0c 00 80 28 jal 131232 <fnpic+0x10>
+# ^-- .pic.fpic
+# CHECK-NEXT: 20024: 00 00 00 00 nop
+# CHECK-NEXT: 20028: 0c 00 80 24 jal 131216 <fnpic>
+# CHECK-NEXT: 2002c: 00 00 00 00 nop
+#
+# CHECK: foo1a:
+# CHECK-NEXT: 20030: 00 00 00 00 nop
+#
+# CHECK: foo1b:
+# CHECK-NEXT: 20034: 00 00 00 00 nop
+#
+# CHECK-NEXT: 20038: 3c 19 00 02 lui $25, 2
+# CHECK-NEXT: 2003c: 08 00 80 0c j 131120 <foo1a>
+# CHECK-NEXT: 20040: 27 39 00 30 addiu $25, $25, 48
+# CHECK-NEXT: 20044: 00 00 00 00 nop
+# CHECK-NEXT: 20048: 3c 19 00 02 lui $25, 2
+# CHECK-NEXT: 2004c: 08 00 80 0d j 131124 <foo1b>
+# CHECK-NEXT: 20050: 27 39 00 34 addiu $25, $25, 52
+# CHECK-NEXT: 20054: 00 00 00 00 nop
+# CHECK-NEXT: 20058: 00 00 00 00 nop
+# CHECK-NEXT: 2005c: 00 00 00 00 nop
+#
+# CHECK: foo2:
+# CHECK-NEXT: 20060: 00 00 00 00 nop
+#
+# CHECK-NEXT: 20064: 3c 19 00 02 lui $25, 2
+# CHECK-NEXT: 20068: 08 00 80 18 j 131168 <foo2>
+# CHECK-NEXT: 2006c: 27 39 00 60 addiu $25, $25, 96
+# CHECK-NEXT: 20070: 00 00 00 00 nop
+# CHECK-NEXT: 20074: 00 00 00 00 nop
+# CHECK-NEXT: 20078: 00 00 00 00 nop
+# CHECK-NEXT: 2007c: 00 00 00 00 nop
+#
+# CHECK: fpic:
+# CHECK-NEXT: 20080: 00 00 00 00 nop
+# CHECK-NEXT: 20084: 00 00 00 00 nop
+# CHECK-NEXT: 20088: 00 00 00 00 nop
+# CHECK-NEXT: 2008c: 00 00 00 00 nop
+#
+# CHECK: fnpic:
+# CHECK-NEXT: 20090: 00 00 00 00 nop
+# CHECK-NEXT: 20094: 00 00 00 00 nop
+# CHECK-NEXT: 20098: 00 00 00 00 nop
+# CHECK-NEXT: 2009c: 00 00 00 00 nop
+# CHECK-NEXT: 200a0: 3c 19 00 02 lui $25, 2
+# CHECK-NEXT: 200a4: 08 00 80 20 j 131200 <fpic>
+# CHECK-NEXT: 200a8: 27 39 00 80 addiu $25, $25, 128
+
+# Make sure tha thunks are created properly no matter how
+# objects are laid out.
+#
+# RUN: ld.lld %t-pic.o %t-npic.o %p/Inputs/mips-sto-pic.o -o %t.exe
+# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=REVERSE %s
+
+# REVERSE: foo1a:
+# REVERSE-NEXT: 20000: 00 00 00 00 nop
+#
+# REVERSE: foo1b:
+# REVERSE-NEXT: 20004: 00 00 00 00 nop
+# REVERSE-NEXT: 20008: 3c 19 00 02 lui $25, 2
+# REVERSE-NEXT: 2000c: 08 00 80 00 j 131072 <foo1a>
+# REVERSE-NEXT: 20010: 27 39 00 00 addiu $25, $25, 0
+# REVERSE-NEXT: 20014: 00 00 00 00 nop
+# REVERSE-NEXT: 20018: 3c 19 00 02 lui $25, 2
+# REVERSE-NEXT: 2001c: 08 00 80 01 j 131076 <foo1b>
+# REVERSE-NEXT: 20020: 27 39 00 04 addiu $25, $25, 4
+# REVERSE-NEXT: 20024: 00 00 00 00 nop
+# REVERSE-NEXT: 20028: 00 00 00 00 nop
+# REVERSE-NEXT: 2002c: 00 00 00 00 nop
+#
+# REVERSE: foo2:
+# REVERSE-NEXT: 20030: 00 00 00 00 nop
+# REVERSE-NEXT: 20034: 3c 19 00 02 lui $25, 2
+# REVERSE-NEXT: 20038: 08 00 80 0c j 131120 <foo2>
+# REVERSE-NEXT: 2003c: 27 39 00 30 addiu $25, $25, 48
+# REVERSE-NEXT: 20040: 00 00 00 00 nop
+# REVERSE-NEXT: 20044: 00 00 00 00 nop
+# REVERSE-NEXT: 20048: 00 00 00 00 nop
+# REVERSE-NEXT: 2004c: 00 00 00 00 nop
+#
+# REVERSE: __start:
+# REVERSE-NEXT: 20050: 0c 00 80 02 jal 131080 <foo1b+0x4>
+# REVERSE-NEXT: 20054: 00 00 00 00 nop
+# REVERSE-NEXT: 20058: 0c 00 80 0d jal 131124 <foo2+0x4>
+# REVERSE-NEXT: 2005c: 00 00 00 00 nop
+# REVERSE-NEXT: 20060: 0c 00 80 06 jal 131096 <foo1b+0x14>
+# REVERSE-NEXT: 20064: 00 00 00 00 nop
+# REVERSE-NEXT: 20068: 0c 00 80 0d jal 131124 <foo2+0x4>
+# REVERSE-NEXT: 2006c: 00 00 00 00 nop
+# REVERSE-NEXT: 20070: 0c 00 80 28 jal 131232 <fnpic+0x10>
+# REVERSE-NEXT: 20074: 00 00 00 00 nop
+# REVERSE-NEXT: 20078: 0c 00 80 24 jal 131216 <fnpic>
+# REVERSE-NEXT: 2007c: 00 00 00 00 nop
+#
+# REVERSE: fpic:
+# REVERSE-NEXT: 20080: 00 00 00 00 nop
+# REVERSE-NEXT: 20084: 00 00 00 00 nop
+# REVERSE-NEXT: 20088: 00 00 00 00 nop
+# REVERSE-NEXT: 2008c: 00 00 00 00 nop
+#
+# REVERSE: fnpic:
+# REVERSE-NEXT: 20090: 00 00 00 00 nop
+# REVERSE-NEXT: 20094: 00 00 00 00 nop
+# REVERSE-NEXT: 20098: 00 00 00 00 nop
+# REVERSE-NEXT: 2009c: 00 00 00 00 nop
+# REVERSE-NEXT: 200a0: 3c 19 00 02 lui $25, 2
+# REVERSE-NEXT: 200a4: 08 00 80 20 j 131200 <fpic>
+# REVERSE-NEXT: 200a8: 27 39 00 80 addiu $25, $25, 128
+# REVERSE-NEXT: 200ac: 00 00 00 00 nop
+
+ .text
+ .globl __start
+__start:
+ jal foo1a
+ jal foo2
+ jal foo1b
+ jal foo2
+ jal fpic
+ jal fnpic
diff --git a/test/ELF/mips-options-r.test b/test/ELF/mips-options-r.test
new file mode 100644
index 000000000000..c4144057e9ad
--- /dev/null
+++ b/test/ELF/mips-options-r.test
@@ -0,0 +1,19 @@
+# Check that if input file contains .MIPS.options section and symbol
+# points to the section and the linker generates a relocatable output,
+# LLD does not crash and write section symbols point to the output
+# .MIPS.options section.
+#
+# PR 27878
+#
+# Input object file created using the following script:
+# % cat t.s
+# .text
+# nop
+# % as -mabi=64 -mips64r2 t.s
+
+# RUN: ld.lld -r %p/Inputs/mips-options.o -o %t.o
+# RUN: llvm-readobj -t %t.o | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Section: .MIPS.options
diff --git a/test/ELF/mips-options.s b/test/ELF/mips-options.s
new file mode 100644
index 000000000000..30381ae55af7
--- /dev/null
+++ b/test/ELF/mips-options.s
@@ -0,0 +1,28 @@
+# Check MIPS .MIPS.options section generation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t2.o
+# RUN: ld.lld %t1.o %t2.o -shared -o %t.so
+# RUN: llvm-readobj -symbols -mips-options %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lw $t0,%call16(g1)($gp)
+
+# CHECK: Name: _gp
+# CHECK-NEXT: Value: 0x[[GP:[0-9A-F]+]]
+
+# CHECK: MIPS Options {
+# CHECK-NEXT: ODK_REGINFO {
+# CHECK-NEXT: GP: 0x[[GP]]
+# CHECK-NEXT: General Mask: 0x10001001
+# CHECK-NEXT: Co-Proc Mask0: 0x0
+# CHECK-NEXT: Co-Proc Mask1: 0x0
+# CHECK-NEXT: Co-Proc Mask2: 0x0
+# CHECK-NEXT: Co-Proc Mask3: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
diff --git a/test/ELF/mips-pc-relocs.s b/test/ELF/mips-pc-relocs.s
index 631dd433925a..209d7d2971f5 100644
--- a/test/ELF/mips-pc-relocs.s
+++ b/test/ELF/mips-pc-relocs.s
@@ -5,7 +5,7 @@
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
# RUN: -mcpu=mips32r6 %S/Inputs/mips-dynamic.s -o %t2.o
# RUN: ld.lld %t1.o %t2.o -o %t.exe
-# RUN: llvm-objdump -mcpu=mips32r6 -d -t %t.exe | FileCheck %s
+# RUN: llvm-objdump -mcpu=mips32r6 -d -t -s %t.exe | FileCheck %s
# REQUIRES: mips
@@ -19,20 +19,27 @@ __start:
aluipc $2, %pcrel_hi(_foo) # R_MIPS_PCHI16
addiu $2, $2, %pcrel_lo(_foo) # R_MIPS_PCLO16
+ .data
+ .word _foo+8-. # R_MIPS_PC32
+
# CHECK: Disassembly of section .text:
# CHECK-NEXT: __start:
# CHECK-NEXT: 20000: ec c8 00 08 lwpc $6, 32
# ^-- (0x20020-0x20000)>>2
-# CHECK-NEXT: 20004: 20 a6 00 06 beqc $5, $6, 24
+# CHECK-NEXT: 20004: 20 a6 00 06 beqc $5, $6, 28
# ^-- (0x20020-4-0x20004)>>2
-# CHECK-NEXT: 20008: d9 20 00 05 beqzc $9, 20
+# CHECK-NEXT: 20008: d9 20 00 05 beqzc $9, 24
# ^-- (0x20020-4-0x20008)>>2
-# CHECK-NEXT: 2000c: c8 00 00 04 bc 16
+# CHECK-NEXT: 2000c: c8 00 00 04 bc 20
# ^-- (0x20020-4-0x2000c)>>2
# CHECK-NEXT: 20010: ec 5f 00 00 aluipc $2, 0
# ^-- %hi(0x20020-0x20010)
# CHECK-NEXT: 20014: 24 42 00 0c addiu $2, $2, 12
# ^-- %lo(0x20020-0x20014)
+# CHECK: Contents of section .data:
+# CHECK-NEXT: 40000 fffe0028 00000000 00000000 00000000
+# ^-- 0x20020 + 8 - 0x40000
+
# CHECK: 00020000 .text 00000000 __start
# CHECK: 00020020 .text 00000000 _foo
diff --git a/test/ELF/mips-plt-copy.s b/test/ELF/mips-plt-copy.s
new file mode 100644
index 000000000000..58883d884563
--- /dev/null
+++ b/test/ELF/mips-plt-copy.s
@@ -0,0 +1,85 @@
+# Check creating of R_MIPS_COPY and R_MIPS_JUMP_SLOT dynamic relocations
+# and corresponding PLT entries.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o
+# RUN: ld.lld %t.so.o -shared -o %t.so
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section ({{.*}}) .rel.dyn {
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data0 0x0
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data1 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section ({{.*}}) .rel.plt {
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_JUMP_SLOT foo0 0x0
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_JUMP_SLOT foo1 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# CHECK: Primary GOT {
+# CHECK: Local entries [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Number of TLS and multi-GOT entries: 0
+# CHECK-NEXT: }
+
+# CHECK: PLT GOT {
+# CHECK: Entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x{{[0-9A-F]+}}
+# CHECK-NEXT: Initial: 0x{{[0-9A-F]+}}
+# CHECK-NEXT: Value: 0x{{[0-9A-F]+}}
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: Name: foo0
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x{{[0-9A-F]+}}
+# CHECK-NEXT: Initial: 0x{{[0-9A-F]+}}
+# CHECK-NEXT: Value: 0x{{[0-9A-F]+}}
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: Name: foo1
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+
+ .text
+ .globl __start
+__start:
+ lui $t0,%hi(foo0) # R_MIPS_HI16 requires JUMP_SLOT/PLT entry
+ # for DSO defined func.
+ addi $t0,$t0,%lo(foo0)
+ lui $t0,%hi(bar) # Does not require PLT for locally defined func.
+ addi $t0,$t0,%lo(bar)
+ lui $t0,%hi(loc) # Does not require PLT for local func.
+ addi $t0,$t0,%lo(loc)
+
+ lui $t0,%hi(data0) # R_MIPS_HI16 requires COPY rel for DSO defined data.
+ addi $t0,$t0,%lo(data0)
+ lui $t0,%hi(gd) # Does not require COPY rel for locally defined data.
+ addi $t0,$t0,%lo(gd)
+ lui $t0,%hi(ld) # Does not require COPY rel for local data.
+ addi $t0,$t0,%lo(ld)
+
+ .globl bar
+ .type bar, @function
+bar:
+ nop
+loc:
+ nop
+
+ .rodata
+ .globl gd
+gd:
+ .word 0
+ld:
+ .word data1+8 # R_MIPS_32 requires REL32 dnamic relocation
+ # for DSO defined data. For now we generate COPY one.
+ .word foo1+8 # R_MIPS_32 requires PLT entry for DSO defined func.
diff --git a/test/ELF/mips-relocs.s b/test/ELF/mips-relocs.s
deleted file mode 100644
index c05b8fd3bdd1..000000000000
--- a/test/ELF/mips-relocs.s
+++ /dev/null
@@ -1,42 +0,0 @@
-# Check R_MIPS_32 relocation calculation.
-
-# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
-# RUN: ld.lld %t-be.o -o %t-be.exe
-# RUN: llvm-objdump -t %t-be.exe | FileCheck %s
-# RUN: llvm-objdump -s %t-be.exe | FileCheck -check-prefix=BE %s
-
-# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
-# RUN: ld.lld %t-el.o -o %t-el.exe
-# RUN: llvm-objdump -t %t-el.exe | FileCheck %s
-# RUN: llvm-objdump -s %t-el.exe | FileCheck -check-prefix=EL %s
-
-# REQUIRES: mips
-
- .globl __start
-__start:
- nop
-
- .data
- .type v1,@object
- .size v1,4
-v1:
- .word 0
-
- .globl v2
- .type v2,@object
- .size v2,8
-v2:
- .word v2+4 # R_MIPS_32 target v2 addend 4
- .word v1 # R_MIPS_32 target v1 addend 0
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00030000 l .data 00000004 v1
-# CHECK: 00030004 g .data 00000008 v2
-
-# BE: Contents of section .data:
-# BE-NEXT: 30000 00000000 00030008 00030000
-# ^-- v2+4 ^-- v1
-
-# EL: Contents of section .data:
-# EL-NEXT: 30000 00000000 08000300 00000300
-# ^-- v2+4 ^-- v1
diff --git a/test/ELF/mips-sto-plt.s b/test/ELF/mips-sto-plt.s
new file mode 100644
index 000000000000..bd8de416680a
--- /dev/null
+++ b/test/ELF/mips-sto-plt.s
@@ -0,0 +1,66 @@
+# Check assigning STO_MIPS_PLT flag to symbol needs a pointer equality.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o
+# RUN: ld.lld %t.so.o -shared -o %t.so
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-readobj -dt -mips-plt-got %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Symbol {
+# CHECK: Name: foo0@
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+# CHECK: Symbol {
+# CHECK: Name: foo1@
+# CHECK-NEXT: Value: 0x20050
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Other [ (0x8)
+# CHECK-NEXT: STO_MIPS_PLT
+# CHECK-NEXT: ]
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+
+# CHECK: Primary GOT {
+# CHECK: Local entries [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
+# CHECK-NEXT: ]
+# CHECK: PLT GOT {
+# CHECK: Entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Initial:
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: Name: foo0
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Initial:
+# CHECK-NEXT: Value: 0x20050
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: Name: foo1
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+ .text
+ .globl __start
+__start:
+ jal foo0 # R_MIPS_26 against 'foo0' from DSO
+ lui $t0,%hi(foo1) # R_MIPS_HI16/LO16 against 'foo1' from DSO
+ addi $t0,$t0,%lo(foo1)
+
+loc:
+ nop
diff --git a/test/ELF/mips-tls-64.s b/test/ELF/mips-tls-64.s
new file mode 100644
index 000000000000..9c05e940b1c1
--- /dev/null
+++ b/test/ELF/mips-tls-64.s
@@ -0,0 +1,86 @@
+# Check MIPS TLS 64-bit relocations handling.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
+# RUN: %p/Inputs/mips-dynamic.s -o %t.so.o
+# RUN: ld.lld -shared %t.so.o -o %t.so
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-objdump -d -s -t %t.exe | FileCheck -check-prefix=DIS %s
+# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# DIS: __start:
+# DIS-NEXT: 20000: 24 62 80 28 addiu $2, $3, -32728
+# DIS-NEXT: 20004: 24 62 80 38 addiu $2, $3, -32712
+# DIS-NEXT: 20008: 8f 82 80 20 lw $2, -32736($gp)
+# DIS-NEXT: 2000c: 24 62 80 48 addiu $2, $3, -32696
+
+# DIS: Contents of section .got:
+# DIS_NEXT: 30008 00000000 00000000 80000000 00000000
+# DIS_NEXT: 30018 00000000 00020000 00000000 00000000
+# DIS_NEXT: 30028 00000000 00000004 00000000 00000000
+# DIS_NEXT: 30038 00000000 00000000 00000000 00000004
+
+# DIS: 0000000000030000 l .tdata 00000000 .tdata
+# DIS: 0000000000030000 l .tdata 00000000 loc
+# DIS: 0000000000000004 g .tdata 00000000 foo
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section (7) .rela.dyn {
+# CHECK-NEXT: 0x30020 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x0
+# CHECK-NEXT: 0x30028 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE - 0x0
+# CHECK-NEXT: 0x30030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x0
+# CHECK-NEXT: 0x30040 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE - 0x4
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Primary GOT {
+# CHECK-NEXT: Canonical gp value: 0x37FF8
+# CHECK-NEXT: Reserved entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x30008
+# CHECK-NEXT: Access: -32752
+# CHECK-NEXT: Initial: 0x0
+# CHECK-NEXT: Purpose: Lazy resolver
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x30010
+# CHECK-NEXT: Access: -32744
+# CHECK-NEXT: Initial: 0x80000000
+# CHECK-NEXT: Purpose: Module pointer (GNU extension)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Local entries [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x30018
+# CHECK-NEXT: Access: -32736
+# CHECK-NEXT: Initial: 0x0
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: Name: foo0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Number of TLS and multi-GOT entries: 5
+# ^-- 0x30020 / -32728 - R_MIPS_TLS_GD - R_MIPS_TLS_DTPMOD32 foo
+# ^-- 0x30028 / -32720 - R_MIPS_TLS_DTPREL32 foo
+# ^-- 0x30030 / -32712 - R_MIPS_TLS_LDM - R_MIPS_TLS_DTPMOD32 loc
+# ^-- 0x30038 / -32704
+# ^-- 0x30040 / -32696 - R_MIPS_TLS_GOTTPREL - R_MIPS_TLS_TPREL32
+
+ .text
+ .global __start
+__start:
+ addiu $2, $3, %tlsgd(foo) # R_MIPS_TLS_GD
+ addiu $2, $3, %tlsldm(loc) # R_MIPS_TLS_LDM
+ lw $2, %got(foo0)($gp)
+ addiu $2, $3, %gottprel(foo) # R_MIPS_TLS_GOTTPREL
+
+ .section .tdata,"awT",%progbits
+ .global foo
+loc:
+ .word 0
+foo:
+ .word 0
diff --git a/test/ELF/mips-tls-hilo.s b/test/ELF/mips-tls-hilo.s
new file mode 100644
index 000000000000..7628cb3a6ec6
--- /dev/null
+++ b/test/ELF/mips-tls-hilo.s
@@ -0,0 +1,52 @@
+# Check MIPS R_MIPS_TLS_DTPREL_HI16/LO16 and R_MIPS_TLS_TPREL_HI16/LO16
+# relocations handling.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t.exe
+# RUN: llvm-objdump -d -t %t.exe | FileCheck -check-prefix=DIS %s
+# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s
+
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-readobj -r -mips-plt-got %t.so | FileCheck -check-prefix=SO %s
+
+# REQUIRES: mips
+
+# DIS: __start:
+# DIS-NEXT: 20000: 24 62 00 00 addiu $2, $3, 0
+# %hi(loc0 - .tdata - 0x8000) --^
+# DIS-NEXT: 20004: 24 62 80 00 addiu $2, $3, -32768
+# %lo(loc0 - .tdata - 0x8000) --^
+# DIS-NEXT: 20008: 24 62 00 00 addiu $2, $3, 0
+# %hi(loc0 - .tdata - 0x7000) --^
+# DIS-NEXT: 2000c: 24 62 90 00 addiu $2, $3, -28672
+# %lo(loc0 - .tdata - 0x7000) --^
+
+# DIS: 00030000 l .tdata 00000000 .tdata
+# DIS: 00030000 l .tdata 00000000 loc0
+
+# CHECK: Relocations [
+# CHECK-NEXT: ]
+# CHECK-NOT: Primary GOT
+
+# SO: Relocations [
+# SO-NEXT: ]
+# SO: Primary GOT {
+# SO: Local entries [
+# SO-NEXT: ]
+# SO-NEXT: Global entries [
+# SO-NEXT: ]
+# SO-NEXT: Number of TLS and multi-GOT entries: 0
+# SO-NEXT: }
+
+ .text
+ .globl __start
+ .type __start,@function
+__start:
+ addiu $2, $3, %dtprel_hi(loc0) # R_MIPS_TLS_DTPREL_HI16
+ addiu $2, $3, %dtprel_lo(loc0) # R_MIPS_TLS_DTPREL_LO16
+ addiu $2, $3, %tprel_hi(loc0) # R_MIPS_TLS_TPREL_HI16
+ addiu $2, $3, %tprel_lo(loc0) # R_MIPS_TLS_TPREL_LO16
+
+ .section .tdata,"awT",%progbits
+loc0:
+ .word 0
diff --git a/test/ELF/mips-tls.s b/test/ELF/mips-tls.s
new file mode 100644
index 000000000000..9635558c2d95
--- /dev/null
+++ b/test/ELF/mips-tls.s
@@ -0,0 +1,77 @@
+# Check MIPS TLS relocations handling.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %p/Inputs/mips-tls.s -o %t.so.o
+# RUN: ld.lld -shared %t.so.o -o %t.so
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-objdump -d -s -t %t.exe | FileCheck -check-prefix=DIS %s
+# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# DIS: __start:
+# DIS-NEXT: 20000: 24 62 80 1c addiu $2, $3, -32740
+# DIS-NEXT: 20004: 24 62 80 24 addiu $2, $3, -32732
+# DIS-NEXT: 20008: 8f 82 80 18 lw $2, -32744($gp)
+# DIS-NEXT: 2000c: 24 62 80 2c addiu $2, $3, -32724
+
+# DIS: Contents of section .got:
+# DIS_NEXT: 30004 00000000 80000000 00020000 00000000
+# DIS_NEXT: 30014 00000000 00000000 00000000 00000000
+
+# DIS: 00030000 l .tdata 00000000 .tdata
+# DIS: 00030000 l .tdata 00000000 loc
+# DIS: 00000000 g *UND* 00000000 foo
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section (7) .rel.dyn {
+# CHECK-NEXT: 0x30018 R_MIPS_TLS_DTPMOD32 - 0x0
+# CHECK-NEXT: 0x30010 R_MIPS_TLS_DTPMOD32 foo 0x0
+# CHECK-NEXT: 0x30014 R_MIPS_TLS_DTPREL32 foo 0x0
+# CHECK-NEXT: 0x30020 R_MIPS_TLS_TPREL32 foo 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Primary GOT {
+# CHECK-NEXT: Canonical gp value: 0x37FF4
+# CHECK-NEXT: Reserved entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x30004
+# CHECK-NEXT: Access: -32752
+# CHECK-NEXT: Initial: 0x0
+# CHECK-NEXT: Purpose: Lazy resolver
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x30008
+# CHECK-NEXT: Access: -32748
+# CHECK-NEXT: Initial: 0x80000000
+# CHECK-NEXT: Purpose: Module pointer (GNU extension)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Local entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x3000C
+# CHECK-NEXT: Access: -32744
+# CHECK-NEXT: Initial: 0x20000
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Number of TLS and multi-GOT entries: 5
+# ^-- 0x30010 / -32740 - R_MIPS_TLS_GD - R_MIPS_TLS_DTPMOD32 foo
+# ^-- 0x30018 / -32736 - R_MIPS_TLS_DTPREL32 foo
+# ^-- 0x3001C / -32732 - R_MIPS_TLS_LDM - R_MIPS_TLS_DTPMOD32 loc
+# ^-- 0x30020 / -32728
+# ^-- 0x30024 / -32724 - R_MIPS_TLS_GOTTPREL - R_MIPS_TLS_TPREL32
+
+ .text
+ .global __start
+__start:
+ addiu $2, $3, %tlsgd(foo) # R_MIPS_TLS_GD
+ addiu $2, $3, %tlsldm(loc) # R_MIPS_TLS_LDM
+ lw $2, %got(__start)($gp)
+ addiu $2, $3, %gottprel(foo) # R_MIPS_TLS_GOTTPREL
+
+ .section .tdata,"awT",%progbits
+loc:
+ .word 0
diff --git a/test/ELF/no-augmentation.s b/test/ELF/no-augmentation.s
new file mode 100644
index 000000000000..31cd92e39b1c
--- /dev/null
+++ b/test/ELF/no-augmentation.s
@@ -0,0 +1,19 @@
+// RUN: llvm-mc -filetype=obj -triple=mips64-unknown-freebsd %s -o %t.o
+// RUN: ld.lld --eh-frame-hdr %t.o -o %t | FileCheck -allow-empty %s
+
+// REQUIRES: mips
+
+// CHECK-NOT: corrupted or unsupported CIE information
+// CHECK-NOT: corrupted CIE
+
+.global __start
+__start:
+
+.section .eh_frame,"aw",@progbits
+ .4byte 9
+ .4byte 0x0
+ .byte 0x1
+ .string ""
+ .uleb128 0x1
+ .sleb128 -4
+ .byte 0x1f
diff --git a/test/ELF/no-inhibit-exec.s b/test/ELF/no-inhibit-exec.s
index fe2240b731fe..31638fd92cc9 100644
--- a/test/ELF/no-inhibit-exec.s
+++ b/test/ELF/no-inhibit-exec.s
@@ -6,10 +6,10 @@
# CHECK: Disassembly of section .text:
# CHECK-NEXT: _start
-# CHECK-NEXT: 11000: e8 fb ef fe ff callq -69637
+# CHECK-NEXT: 11000: e8 fb ef fe ff callq -69637
# next code will not link without noinhibit-exec flag
# because of undefined symbol _bar
-.globl _start;
+.globl _start
_start:
call _bar
diff --git a/test/ELF/no-plt-shared.s b/test/ELF/no-plt-shared.s
new file mode 100644
index 000000000000..ac45ed502c38
--- /dev/null
+++ b/test/ELF/no-plt-shared.s
@@ -0,0 +1,17 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
+// RUN: ld.lld %t2.o %t.so -o %t2.so -shared
+// RUN: llvm-readobj -r %t2.so | FileCheck %s
+
+ .data
+fp:
+ .quad bar
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: R_X86_64_64 bar 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/no-undefined.s b/test/ELF/no-undefined.s
index 94378bde40a2..fa4d5e928763 100644
--- a/test/ELF/no-undefined.s
+++ b/test/ELF/no-undefined.s
@@ -4,4 +4,4 @@
.globl _shared
_shared:
- call _unresolved
+ callq _unresolved@PLT
diff --git a/test/ELF/noplt-pie.s b/test/ELF/noplt-pie.s
new file mode 100644
index 000000000000..1eb84934184e
--- /dev/null
+++ b/test/ELF/noplt-pie.s
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t2.so
+# RUN: ld.lld %t1.o %t2.so -o %t.out
+# RUN: llvm-readobj -s -r %t.out | FileCheck %s
+
+# CHECK: Section {
+# CHECK-NOT: Name: .plt
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+# CHECK-NEXT: 0x120B0 R_X86_64_GLOB_DAT bar 0x0
+# CHECK-NEXT: 0x120B8 R_X86_64_GLOB_DAT zed 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+.global _start
+_start:
+ movq bar@GOTPCREL(%rip), %rcx
+ movq zed@GOTPCREL(%rip), %rcx
diff --git a/test/ELF/note.s b/test/ELF/note.s
new file mode 100644
index 000000000000..a383b95c9907
--- /dev/null
+++ b/test/ELF/note.s
@@ -0,0 +1,18 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t -shared
+// RUN: llvm-readobj -program-headers %t | FileCheck %s
+
+// CHECK: Type: PT_NOTE
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: VirtualAddress:
+// CHECK-NEXT: PhysicalAddress:
+// CHECK-NEXT: FileSize: 8
+// CHECK-NEXT: MemSize: 8
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: PF_R
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 1
+
+ .section .note.test,"a",@note
+ .quad 42
diff --git a/test/ELF/phdr-align.s b/test/ELF/phdr-align.s
new file mode 100644
index 000000000000..58d537b46840
--- /dev/null
+++ b/test/ELF/phdr-align.s
@@ -0,0 +1,82 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+
+# RUN: echo "SECTIONS { \
+# RUN: .bss : { *(.bss) } \
+# RUN: .data : { *(.data) } \
+# RUN: .text : { *(.text) } }" > %t.script
+# RUN: ld.lld %t.o --script %t.script -o %t
+# RUN: llvm-readobj -sections -symbols %t | FileCheck %s
+
+# CHECK: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: Name: (0)
+# CHECK-NEXT: Type: SHT_NULL
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 0
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: Name: .bss
+# CHECK-NEXT: Type: SHT_NOBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x158
+# CHECK-NEXT: Offset: 0x158
+# CHECK-NEXT: Size: 6
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x15E
+# CHECK-NEXT: Offset: 0x15E
+# CHECK-NEXT: Size: 2
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .text
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_EXECINSTR
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x160
+# CHECK-NEXT: Offset: 0x160
+# CHECK-NEXT: Size: 1
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+
+.global _start
+.text
+_start:
+ nop
+.data
+ .word 1
+.bss
+ .space 6
diff --git a/test/ELF/pie-weak.s b/test/ELF/pie-weak.s
new file mode 100644
index 000000000000..e74bcdfc09c0
--- /dev/null
+++ b/test/ELF/pie-weak.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -filetype=obj -relax-relocations=false -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld -pie %t.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOCS %s
+# RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+
+# RELOCS: Relocations [
+# RELOCS-NEXT: ]
+
+.weak foo
+
+.globl _start
+_start:
+# DISASM: _start:
+# DISASM-NEXT: 1000: 48 8b 05 69 10 00 00 movq 4201(%rip), %rax
+# ^ .got - (.text + 7)
+mov foo@gotpcrel(%rip), %rax
diff --git a/test/ELF/pie.s b/test/ELF/pie.s
new file mode 100644
index 000000000000..4cf1743ee736
--- /dev/null
+++ b/test/ELF/pie.s
@@ -0,0 +1,102 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: ld.lld -pie %t1.o -o %t
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s
+
+## Test --pic-executable alias
+# RUN: ld.lld --pic-executable %t1.o -o %t
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s
+
+# CHECK: ElfHeader {
+# CHECK-NEXT: Ident {
+# CHECK-NEXT: Magic: (7F 45 4C 46)
+# CHECK-NEXT: Class: 64-bit
+# CHECK-NEXT: DataEncoding: LittleEndian
+# CHECK-NEXT: FileVersion: 1
+# CHECK-NEXT: OS/ABI: SystemV
+# CHECK-NEXT: ABIVersion: 0
+# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT: }
+# CHECK-NEXT: Type: SharedObject
+# CHECK-NEXT: Machine: EM_X86_64
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Entry: 0x1000
+# CHECK-NEXT: ProgramHeaderOffset: 0x40
+# CHECK-NEXT: SectionHeaderOffset: 0x1110
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize: 64
+# CHECK-NEXT: ProgramHeaderEntrySize: 56
+# CHECK-NEXT: ProgramHeaderCount: 7
+# CHECK-NEXT: SectionHeaderEntrySize: 64
+# CHECK-NEXT: SectionHeaderCount: 9
+# CHECK-NEXT: StringTableSectionIndex: 7
+# CHECK-NEXT: }
+
+# CHECK: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_PHDR
+# CHECK-NEXT: Offset: 0x40
+# CHECK-NEXT: VirtualAddress: 0x40
+# CHECK-NEXT: PhysicalAddress: 0x40
+# CHECK-NEXT: FileSize: 392
+# CHECK-NEXT: MemSize: 392
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 8
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 497
+# CHECK-NEXT: MemSize: 497
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: VirtualAddress: 0x1000
+# CHECK-NEXT: PhysicalAddress: 0x1000
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_X
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: VirtualAddress: 0x1000
+# CHECK-NEXT: PhysicalAddress: 0x1000
+# CHECK-NEXT: FileSize: 112
+# CHECK-NEXT: MemSize: 112
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_DYNAMIC
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: VirtualAddress: 0x1000
+# CHECK-NEXT: PhysicalAddress: 0x1000
+# CHECK-NEXT: FileSize: 112
+# CHECK-NEXT: MemSize: 112
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 8
+# CHECK-NEXT: }
+
+.globl _start
+_start:
diff --git a/test/ELF/plt-aarch64.s b/test/ELF/plt-aarch64.s
index 6ea732ec7c68..3f124b0af49c 100644
--- a/test/ELF/plt-aarch64.s
+++ b/test/ELF/plt-aarch64.s
@@ -1,5 +1,5 @@
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t.o
-// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/shared.s -o %t2.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/plt-aarch64.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld -shared %t.o %t2.so -o %t.so
// RUN: ld.lld %t.o %t2.so -o %t.exe
diff --git a/test/ELF/plt-i686.s b/test/ELF/plt-i686.s
index 4947e0e734fd..bf07fede7989 100644
--- a/test/ELF/plt-i686.s
+++ b/test/ELF/plt-i686.s
@@ -2,12 +2,13 @@
// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so -o %t
-// RUN: llvm-readobj -s -r %t | FileCheck --check-prefix=CHECK %s
+// RUN: llvm-readobj -s -r %t | FileCheck %s
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
// RUN: ld.lld -shared %t.o %t2.so -o %t
// RUN: llvm-readobj -s -r %t | FileCheck --check-prefix=CHECKSHARED %s
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMSHARED %s
-
+// RUN: ld.lld -pie %t.o %t2.so -o %t
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMPIE %s
// REQUIRES: x86
// CHECK: Name: .plt
@@ -147,6 +148,21 @@
// DISASMSHARED-NEXT: 1046: 68 08 00 00 00 pushl $8
// DISASMSHARED-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
+// DISASMPIE: Disassembly of section .plt:
+// DISASMPIE-NEXT: .plt:
+// DISASMPIE-NEXT: 1020: ff b3 04 00 00 00 pushl 4(%ebx)
+// DISASMPIE-NEXT: 1026: ff a3 08 00 00 00 jmpl *8(%ebx)
+// DISASMPIE-NEXT: 102c: 90 nop
+// DISASMPIE-NEXT: 102d: 90 nop
+// DISASMPIE-NEXT: 102e: 90 nop
+// DISASMPIE-NEXT: 102f: 90 nop
+// DISASMPIE-NEXT: 1030: ff a3 0c 30 00 00 jmpl *12300(%ebx)
+// DISASMPIE-NEXT: 1036: 68 00 00 00 00 pushl $0
+// DISASMPIE-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
+// DISASMPIE-NEXT: 1040: ff a3 10 30 00 00 jmpl *12304(%ebx)
+// DISASMPIE-NEXT: 1046: 68 08 00 00 00 pushl $8
+// DISASMPIE-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
+
local:
.long 0
diff --git a/test/ELF/plt.s b/test/ELF/plt.s
index 1183d32c3ccc..60268a68195a 100644
--- a/test/ELF/plt.s
+++ b/test/ELF/plt.s
@@ -109,7 +109,7 @@
// DISASM2-NEXT: 11040: ff 25 da 1f 00 00 jmpq *8154(%rip)
// DISASM2-NEXT: 11046: 68 01 00 00 00 pushq $1
// DISASM2-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <.plt>
-// DISASM2-NEXT-NOT: 110C0
+// DISASM2-NOT: 110C0
.global _start
_start:
diff --git a/test/ELF/ppc64-addr16-error.s b/test/ELF/ppc64-addr16-error.s
index 57a919a9b338..2bc8ef2ae4d7 100644
--- a/test/ELF/ppc64-addr16-error.s
+++ b/test/ELF/ppc64-addr16-error.s
@@ -1,7 +1,8 @@
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
-// RUN: not ld.lld -shared %t -o %t2 2>&1 | FileCheck %s
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-addr16-error.s -o %t2
+// RUN: not ld.lld -shared %t %t2 -o %t3 2>&1 | FileCheck %s
// REQUIRES: ppc
.short sym+65539
-// CHECK: Relocation R_PPC64_ADDR16 out of range
+// CHECK: relocation R_PPC64_ADDR16 out of range
diff --git a/test/ELF/ppc64-relocs.s b/test/ELF/ppc64-relocs.s
index 61f9a1eb3ce3..28902aed26df 100644
--- a/test/ELF/ppc64-relocs.s
+++ b/test/ELF/ppc64-relocs.s
@@ -43,7 +43,7 @@ _start:
# CHECK: Disassembly of section .R_PPC64_TOC16_HI:
# CHECK: .FR_PPC64_TOC16_HI:
-# CHECK: 10010014: 3c 22 10 01 addis 1, 2, 4097
+# CHECK: 10010014: 3c 22 ff ff addis 1, 2, -1
.section .R_PPC64_TOC16_HA,"ax",@progbits
.globl .FR_PPC64_TOC16_HA
@@ -52,7 +52,7 @@ _start:
# CHECK: Disassembly of section .R_PPC64_TOC16_HA:
# CHECK: .FR_PPC64_TOC16_HA:
-# CHECK: 10010018: 3c 22 10 02 addis 1, 2, 4098
+# CHECK: 10010018: 3c 22 00 00 addis 1, 2, 0
.section .R_PPC64_REL24,"ax",@progbits
.globl .FR_PPC64_REL24
diff --git a/test/ELF/ppc64-toc-restore.s b/test/ELF/ppc64-toc-restore.s
index cee105b35e64..dbfeaece7db4 100644
--- a/test/ELF/ppc64-toc-restore.s
+++ b/test/ELF/ppc64-toc-restore.s
@@ -53,8 +53,8 @@ last:
// CHECK: Disassembly of section .plt:
// CHECK: .plt:
// CHECK: 10010020: f8 41 00 28 std 2, 40(1)
-// CHECK: 10010024: 3d 62 00 00 addis 11, 2, 0
-// CHECK: 10010028: e9 8b 80 00 ld 12, -32768(11)
+// CHECK: 10010024: 3d 62 10 03 addis 11, 2, 4099
+// CHECK: 10010028: e9 8b 80 18 ld 12, -32744(11)
// CHECK: 1001002c: e9 6c 00 00 ld 11, 0(12)
// CHECK: 10010030: 7d 69 03 a6 mtctr 11
// CHECK: 10010034: e8 4c 00 08 ld 2, 8(12)
diff --git a/test/ELF/pre_init_fini_array.s b/test/ELF/pre_init_fini_array.s
index bf32283d2579..4ddcb6947e5b 100644
--- a/test/ELF/pre_init_fini_array.s
+++ b/test/ELF/pre_init_fini_array.s
@@ -67,7 +67,9 @@ _start:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .fini_array
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -76,7 +78,9 @@ _start:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .fini_array
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -85,7 +89,9 @@ _start:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .init_array
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -94,7 +100,9 @@ _start:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .init_array
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -103,7 +111,9 @@ _start:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .preinit_array
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -112,7 +122,9 @@ _start:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .preinit_array
// CHECK-NEXT: }
diff --git a/test/ELF/progname.s b/test/ELF/progname.s
index 5712b95d276d..10cbf177c69b 100644
--- a/test/ELF/progname.s
+++ b/test/ELF/progname.s
@@ -1,10 +1,29 @@
// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
-// RUN: echo '.global __progname' > %t2.s
+// RUN: echo .global __progname > %t2.s
// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %t2.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld -o %t %t.o %t2.so
// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+// Inputs/progname-ver.so consists of the assembly file
+//
+// .global bar
+// bar:
+// .quad __progname
+//
+// linked into a library with the version script
+//
+// VER_1 {
+// global:
+// bar;
+// };
+//
+// We should create it with lld itself once we it supports that.
+
+// RUN: ld.lld -o %t %t.o %p/Inputs/progname-ver.so
+// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
// CHECK: Name: __progname@
// CHECK-NEXT: Value: 0x11000
// CHECK-NEXT: Size: 0
diff --git a/test/ELF/protected-shared.s b/test/ELF/protected-shared.s
new file mode 100644
index 000000000000..e69b10899dae
--- /dev/null
+++ b/test/ELF/protected-shared.s
@@ -0,0 +1,52 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/protected-shared.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-readobj -t --dyn-symbols %t | FileCheck %s
+
+ .global _start
+_start:
+
+ .global bar
+bar:
+
+ .data
+ .quad foo
+
+// CHECK: Name: bar
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+
+// CHECK: DynamicSymbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: @
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local (0x0)
+// CHECK-NEXT: Type: None (0x0)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined (0x0)
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: foo@
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/rel-offset.s b/test/ELF/rel-offset.s
new file mode 100644
index 000000000000..6f35bcebc4b0
--- /dev/null
+++ b/test/ELF/rel-offset.s
@@ -0,0 +1,15 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t -shared
+// RUN: llvm-readobj -r %t | FileCheck %s
+
+ .section .data.foo,"aw",@progbits
+ .quad foo
+
+ .section .data.zed,"aw",@progbits
+ .quad foo
+
+// CHECK: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x2000 R_X86_64_64 foo 0x0
+// CHECK-NEXT: 0x2008 R_X86_64_64 foo 0x0
+// CHECK-NEXT: }
diff --git a/test/ELF/relative-dynamic-reloc-pie.s b/test/ELF/relative-dynamic-reloc-pie.s
new file mode 100644
index 000000000000..d9967af52eb6
--- /dev/null
+++ b/test/ELF/relative-dynamic-reloc-pie.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld -pie %t.o -o %t.pie
+# RUN: llvm-readobj -r -dyn-symbols %t.pie | FileCheck %s
+
+## Test that we create R_X86_64_RELATIVE relocations with -pie.
+# CHECK: Relocations [
+# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+# CHECK-NEXT: 0x3000 R_X86_64_RELATIVE - 0x3000
+# CHECK-NEXT: 0x3008 R_X86_64_RELATIVE - 0x3008
+# CHECK-NEXT: 0x3010 R_X86_64_RELATIVE - 0x3009
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+.globl _start
+_start:
+nop
+
+ .data
+foo:
+ .quad foo
+
+.hidden bar
+.global bar
+bar:
+ .quad bar
+ .quad bar + 1
diff --git a/test/ELF/relative-dynamic-reloc-ppc64.s b/test/ELF/relative-dynamic-reloc-ppc64.s
index b22b33f9f469..81a7a7027bb8 100644
--- a/test/ELF/relative-dynamic-reloc-ppc64.s
+++ b/test/ELF/relative-dynamic-reloc-ppc64.s
@@ -10,10 +10,10 @@
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: 0x[[FOO_ADDR:.*]] R_PPC64_RELATIVE - 0x[[FOO_ADDR]]
// CHECK-NEXT: 0x[[BAR_ADDR:.*]] R_PPC64_RELATIVE - 0x[[BAR_ADDR]]
-// CHECK-NEXT: 0x10010 R_PPC64_RELATIVE - 0x10009
+// CHECK-NEXT: 0x20010 R_PPC64_RELATIVE - 0x20009
// CHECK-NEXT: 0x{{.*}} R_PPC64_RELATIVE - 0x[[ZED_ADDR:.*]]
// CHECK-NEXT: 0x{{.*}} R_PPC64_RELATIVE - 0x[[FOO_ADDR]]
-// CHECK-NEXT: 0x1D0 R_PPC64_ADDR64 external 0x0
+// CHECK-NEXT: 0x20028 R_PPC64_ADDR64 external 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
@@ -47,6 +47,7 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
+ .data
foo:
.quad foo
@@ -60,7 +61,7 @@ bar:
.comm zed,1
.quad zed
- .section abc,"a"
+ .section abc,"aw"
.quad foo
.quad external
diff --git a/test/ELF/relative-dynamic-reloc.s b/test/ELF/relative-dynamic-reloc.s
index 41fcd8a6a556..aac55669bb17 100644
--- a/test/ELF/relative-dynamic-reloc.s
+++ b/test/ELF/relative-dynamic-reloc.s
@@ -9,10 +9,10 @@
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: 0x[[FOO_ADDR:.*]] R_X86_64_RELATIVE - 0x[[FOO_ADDR]]
// CHECK-NEXT: 0x[[BAR_ADDR:.*]] R_X86_64_RELATIVE - 0x[[BAR_ADDR]]
-// CHECK-NEXT: 0x1010 R_X86_64_RELATIVE - 0x1009
+// CHECK-NEXT: 0x2010 R_X86_64_RELATIVE - 0x2009
// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x[[ZED_ADDR:.*]]
// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x[[FOO_ADDR]]
-// CHECK-NEXT: 0x1D0 R_X86_64_64 external 0x0
+// CHECK-NEXT: 0x2028 R_X86_64_64 external 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
@@ -46,6 +46,7 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
+ .data
foo:
.quad foo
@@ -59,7 +60,7 @@ bar:
.comm zed,1
.quad zed
- .section abc,"a"
+ .section abc,"aw"
.quad foo
.quad external
diff --git a/test/ELF/relocatable-bss.s b/test/ELF/relocatable-bss.s
new file mode 100644
index 000000000000..0411bf339c43
--- /dev/null
+++ b/test/ELF/relocatable-bss.s
@@ -0,0 +1,40 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: ld.lld -r %t1.o -o %t
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s
+
+## We check here that .bss does not occupy the space in file.
+## If it would, the SectionHeaderOffset would have offset about 5 megabytes.
+# CHECK: ElfHeader {
+# CHECK-NEXT: Ident {
+# CHECK-NEXT: Magic: (7F 45 4C 46)
+# CHECK-NEXT: Class: 64-bit
+# CHECK-NEXT: DataEncoding: LittleEndian
+# CHECK-NEXT: FileVersion: 1
+# CHECK-NEXT: OS/ABI: SystemV
+# CHECK-NEXT: ABIVersion: 0
+# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT: }
+# CHECK-NEXT: Type: Relocatable
+# CHECK-NEXT: Machine: EM_X86_64
+# CHECK-NEXT: Version:
+# CHECK-NEXT: Entry:
+# CHECK-NEXT: ProgramHeaderOffset:
+# CHECK-NEXT: SectionHeaderOffset: 0xA8
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize:
+# CHECK-NEXT: ProgramHeaderEntrySize:
+# CHECK-NEXT: ProgramHeaderCount:
+# CHECK-NEXT: SectionHeaderEntrySize:
+# CHECK-NEXT: SectionHeaderCount:
+# CHECK-NEXT: StringTableSectionIndex:
+# CHECK-NEXT: }
+
+.text
+.globl _start
+_start:
+ nop
+
+.bss
+ .space 5242880
diff --git a/test/ELF/relocatable-ehframe.s b/test/ELF/relocatable-ehframe.s
new file mode 100644
index 000000000000..d48402099c36
--- /dev/null
+++ b/test/ELF/relocatable-ehframe.s
@@ -0,0 +1,51 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable-ehframe.s -o %t2.o
+# RUN: ld.lld -r %t1.o %t2.o -o %t
+# RUN: llvm-readobj -r -s -section-data %t | FileCheck %s
+
+# CHECK: Name: .strtab
+# CHECK-NEXT: Type: SHT_STRTAB
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset
+# CHECK-NEXT: Size: 9
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 00005F73 74617274 00 |.._start.|
+# CHECK-NEXT: )
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section {{.*}} .rela.eh_frame {
+# CHECK-NEXT: 0x20 R_X86_64_PC32 foo 0x0
+# CHECK-NEXT: 0x34 R_X86_64_PC32 bar 0x0
+# CHECK-NEXT: 0x48 R_X86_64_PC32 dah 0x0
+# CHECK-NEXT: 0x78 R_X86_64_PC32 foo1 0x0
+# CHECK-NEXT: 0x8C R_X86_64_PC32 bar1 0x0
+# CHECK-NEXT: 0xA0 R_X86_64_PC32 dah1 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+.section foo,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.section bar,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.section dah,"ax",@progbits
+.cfi_startproc
+ nop
+.cfi_endproc
+
+.text
+.globl _start
+_start:
+ nop
diff --git a/test/ELF/relocatable-reloc.s b/test/ELF/relocatable-reloc.s
new file mode 100644
index 000000000000..c576073a7510
--- /dev/null
+++ b/test/ELF/relocatable-reloc.s
@@ -0,0 +1,14 @@
+// RUN: llvm-mc -filetype=obj %s -o %t.o -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o %t.o -r -o %t2.o
+// RUN: llvm-readobj -r %t2.o | FileCheck %s
+
+.weak foo
+foo:
+.quad foo
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.text {
+// CHECK-NEXT: 0x0 R_X86_64_64 foo 0x0
+// CHECK-NEXT: 0x8 R_X86_64_64 foo 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/relocatable-symbols.s b/test/ELF/relocatable-symbols.s
new file mode 100644
index 000000000000..75ed17ec5f6f
--- /dev/null
+++ b/test/ELF/relocatable-symbols.s
@@ -0,0 +1,183 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld -r %t -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
+# RUN: llvm-readobj -symbols -r %tout | FileCheck -check-prefix=SYMBOL %s
+
+# DISASM: _start:
+# DISASM-NEXT: 0: {{.*}} callq 0
+# DISASM-NEXT: 5: {{.*}} callq 0
+# DISASM-NEXT: a: {{.*}} callq 0
+# DISASM-NEXT: f: {{.*}} callq 0
+# DISASM-NEXT: 14: {{.*}} callq 0
+# DISASM-NEXT: 19: {{.*}} callq 0
+# DISASM-NEXT: 1e: {{.*}} callq 0
+# DISASM-NEXT: 23: {{.*}} callq 0
+# DISASM-NEXT: 28: {{.*}} callq 0
+# DISASM-NEXT: 2d: {{.*}} callq 0
+# DISASM-NEXT: 32: {{.*}} callq 0
+# DISASM-NEXT: 37: {{.*}} callq 0
+# DISASM-NEXT: Disassembly of section foo:
+# DISASM-NEXT: foo:
+# DISASM-NEXT: 0: 90 nop
+# DISASM-NEXT: 1: 90 nop
+# DISASM-NEXT: 2: 90 nop
+# DISASM-NEXT: Disassembly of section bar:
+# DISASM-NEXT: bar:
+# DISASM-NEXT: 0: 90 nop
+# DISASM-NEXT: 1: 90 nop
+# DISASM-NEXT: 2: 90 nop
+
+# SYMBOL: Relocations [
+# SYMBOL-NEXT: Section ({{.*}}) .rela.text {
+# SYMBOL-NEXT: 0x1 R_X86_64_PC32 __start_foo 0x0
+# SYMBOL-NEXT: 0x6 R_X86_64_PC32 __stop_foo 0x0
+# SYMBOL-NEXT: 0xB R_X86_64_PC32 __start_bar 0x0
+# SYMBOL-NEXT: 0x10 R_X86_64_PC32 __stop_bar 0x0
+# SYMBOL-NEXT: 0x15 R_X86_64_PC32 __start_doo 0x0
+# SYMBOL-NEXT: 0x1A R_X86_64_PC32 __stop_doo 0x0
+# SYMBOL-NEXT: 0x1F R_X86_64_PC32 __preinit_array_start 0x0
+# SYMBOL-NEXT: 0x24 R_X86_64_PC32 __preinit_array_end 0x0
+# SYMBOL-NEXT: 0x29 R_X86_64_PC32 __init_array_start 0x0
+# SYMBOL-NEXT: 0x2E R_X86_64_PC32 __init_array_end 0x0
+# SYMBOL-NEXT: 0x33 R_X86_64_PC32 __fini_array_start 0x0
+# SYMBOL-NEXT: 0x38 R_X86_64_PC32 __fini_array_end 0x0
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: ]
+# SYMBOL: Symbol {
+# SYMBOL: Name: __fini_array_end
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __fini_array_start
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __init_array_end
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __init_array_start
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __preinit_array_end
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __preinit_array_start
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __start_bar
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __start_doo
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __start_foo
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __stop_bar
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __stop_doo
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+# SYMBOL-NEXT: Symbol {
+# SYMBOL-NEXT: Name: __stop_foo
+# SYMBOL-NEXT: Value: 0x0
+# SYMBOL-NEXT: Size: 0
+# SYMBOL-NEXT: Binding: Global
+# SYMBOL-NEXT: Type: None
+# SYMBOL-NEXT: Other: 0
+# SYMBOL-NEXT: Section: Undefined
+# SYMBOL-NEXT: }
+
+.global _start
+.text
+_start:
+ call __start_foo
+ call __stop_foo
+
+ call __start_bar
+ call __stop_bar
+
+ call __start_doo
+ call __stop_doo
+
+ call __preinit_array_start
+ call __preinit_array_end
+ call __init_array_start
+ call __init_array_end
+ call __fini_array_start
+ call __fini_array_end
+
+.section foo,"ax"
+ nop
+ nop
+ nop
+
+.section bar,"ax"
+ nop
+ nop
+ nop
diff --git a/test/ELF/relocatable.s b/test/ELF/relocatable.s
index 9fb171d4ed50..032cb6336c08 100644
--- a/test/ELF/relocatable.s
+++ b/test/ELF/relocatable.s
@@ -1,9 +1,120 @@
# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable2.s -o %t3.o
+# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s
+# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-# RUN: not ld.lld -r %t -o %t2 2>&1 | FileCheck %s
+## Test --relocatable alias
+# RUN: ld.lld --relocatable %t1.o %t2.o %t3.o -o %t
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s
+# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s
-# CHECK: -r option is not supported. Use 'ar' command instead.
+## Verify that we can use our relocation output as input to produce executable
+# RUN: ld.lld -e main %t -o %texec
+# RUN: llvm-readobj -file-headers %texec | FileCheck -check-prefix=CHECKEXE %s
-.globl _start;
-_start:
+# CHECK: ElfHeader {
+# CHECK-NEXT: Ident {
+# CHECK-NEXT: Magic: (7F 45 4C 46)
+# CHECK-NEXT: Class: 64-bit
+# CHECK-NEXT: DataEncoding: LittleEndian
+# CHECK-NEXT: FileVersion: 1
+# CHECK-NEXT: OS/ABI: SystemV
+# CHECK-NEXT: ABIVersion: 0
+# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT: }
+# CHECK-NEXT: Type: Relocatable
+# CHECK-NEXT: Machine: EM_X86_64
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Entry: 0x0
+# CHECK-NEXT: ProgramHeaderOffset: 0x0
+# CHECK-NEXT: SectionHeaderOffset: 0x2C0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize: 64
+# CHECK-NEXT: ProgramHeaderEntrySize: 0
+# CHECK-NEXT: ProgramHeaderCount: 0
+# CHECK-NEXT: SectionHeaderEntrySize: 64
+# CHECK-NEXT: SectionHeaderCount: 7
+# CHECK-NEXT: StringTableSectionIndex: 5
+# CHECK-NEXT: }
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section (3) .rela.text {
+# CHECK-NEXT: 0x3 R_X86_64_32S x 0x0
+# CHECK-NEXT: 0xE R_X86_64_32S y 0x0
+# CHECK-NEXT: 0x23 R_X86_64_32S xx 0x0
+# CHECK-NEXT: 0x2E R_X86_64_32S yy 0x0
+# CHECK-NEXT: 0x43 R_X86_64_32S xxx 0x0
+# CHECK-NEXT: 0x4E R_X86_64_32S yyy 0x0
+# CHECK-NEXT: }
+
+# CHECKTEXT: Disassembly of section .text:
+# CHECKTEXT-NEXT: main:
+# CHECKTEXT-NEXT: 0: c7 04 25 00 00 00 00 05 00 00 00 movl $5, 0
+# CHECKTEXT-NEXT: b: c7 04 25 00 00 00 00 07 00 00 00 movl $7, 0
+# CHECKTEXT: foo:
+# CHECKTEXT-NEXT: 20: c7 04 25 00 00 00 00 01 00 00 00 movl $1, 0
+# CHECKTEXT-NEXT: 2b: c7 04 25 00 00 00 00 02 00 00 00 movl $2, 0
+# CHECKTEXT: bar:
+# CHECKTEXT-NEXT: 40: c7 04 25 00 00 00 00 08 00 00 00 movl $8, 0
+# CHECKTEXT-NEXT: 4b: c7 04 25 00 00 00 00 09 00 00 00 movl $9, 0
+
+# CHECKEXE: Format: ELF64-x86-64
+# CHECKEXE-NEXT: Arch: x86_64
+# CHECKEXE-NEXT: AddressSize: 64bit
+# CHECKEXE-NEXT: LoadName:
+# CHECKEXE-NEXT: ElfHeader {
+# CHECKEXE-NEXT: Ident {
+# CHECKEXE-NEXT: Magic: (7F 45 4C 46)
+# CHECKEXE-NEXT: Class: 64-bit
+# CHECKEXE-NEXT: DataEncoding: LittleEndian
+# CHECKEXE-NEXT: FileVersion: 1
+# CHECKEXE-NEXT: OS/ABI: SystemV (0x0)
+# CHECKEXE-NEXT: ABIVersion: 0
+# CHECKEXE-NEXT: Unused: (00 00 00 00 00 00 00)
+# CHECKEXE-NEXT: }
+# CHECKEXE-NEXT: Type: Executable
+# CHECKEXE-NEXT: Machine: EM_X86_64
+# CHECKEXE-NEXT: Version: 1
+# CHECKEXE-NEXT: Entry: 0x11000
+# CHECKEXE-NEXT: ProgramHeaderOffset: 0x40
+# CHECKEXE-NEXT: SectionHeaderOffset: 0x11E8
+# CHECKEXE-NEXT: Flags [
+# CHECKEXE-NEXT: ]
+# CHECKEXE-NEXT: HeaderSize: 64
+# CHECKEXE-NEXT: ProgramHeaderEntrySize: 56
+# CHECKEXE-NEXT: ProgramHeaderCount: 5
+# CHECKEXE-NEXT: SectionHeaderEntrySize: 64
+# CHECKEXE-NEXT: SectionHeaderCount: 6
+# CHECKEXE-NEXT: StringTableSectionIndex: 4
+# CHECKEXE-NEXT: }
+
+.text
+.type x,@object
+.bss
+.globl x
+.align 4
+x:
+.long 0
+.size x, 4
+.type y,@object
+.globl y
+.align 4
+y:
+.long 0
+.size y, 4
+
+.text
+.globl main
+.align 16, 0x90
+.type main,@function
+main:
+movl $5, x
+movl $7, y
+
+blah:
+goo:
+abs = 42
diff --git a/test/ELF/relocation-copy-alias.s b/test/ELF/relocation-copy-alias.s
new file mode 100644
index 000000000000..15712e39bc93
--- /dev/null
+++ b/test/ELF/relocation-copy-alias.s
@@ -0,0 +1,67 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy-alias.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t.so
+// RUN: ld.lld %t.o %t.so -o %t3
+// RUN: llvm-readobj --dyn-symbols -r --expand-relocs %t3 | FileCheck %s
+
+.global _start
+_start:
+movl $5, a1
+movl $5, b1
+movl $5, b2
+
+// CHECK: .rela.dyn {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_X86_64_COPY
+// CHECK-NEXT: Symbol: a1
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_X86_64_COPY
+// CHECK-NEXT: Symbol: b1
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+
+// CHECK: Name: a1
+// CHECK-NEXT: Value: [[A:.*]]
+// CHECK-NEXT: Size: 1
+// CHECK-NEXT: Binding: Global (0x1)
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss (0x7)
+
+// CHECK: Name: b1
+// CHECK-NEXT: Value: [[B:.*]]
+// CHECK-NEXT: Size: 1
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+// CHECK: Name: b2
+// CHECK-NEXT: Value: [[B]]
+// CHECK-NEXT: Size: 1
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+// CHECK: Name: a2
+// CHECK-NEXT: Value: [[A]]
+// CHECK-NEXT: Size: 1
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+// CHECK: Name: b3
+// CHECK-NEXT: Value: [[B]]
+// CHECK-NEXT: Size: 1
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
diff --git a/test/ELF/relocation-copy-flags.s b/test/ELF/relocation-copy-flags.s
new file mode 100644
index 000000000000..50b4b15267e6
--- /dev/null
+++ b/test/ELF/relocation-copy-flags.s
@@ -0,0 +1,73 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t.exe
+// RUN: llvm-readobj -s -section-data -r %t.exe | FileCheck %s
+
+ .global _start
+_start:
+ .quad x
+
+ .section foo
+ .quad y
+
+ .section bar, "aw"
+ .quad z
+
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x11000
+// CHECK-NEXT: Offset: 0x1000
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 10300100
+// CHECK-NEXT: )
+
+// CHECK: Name: bar
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x13000
+// CHECK-NEXT: Offset: 0x3000
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000000
+// CHECK-NEXT: )
+
+// CHECK: Name: foo
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+// CHECK-NEXT: Offset: 0x3008
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000000
+// CHECK-NEXT: )
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section (4) .rela.dyn {
+// CHECK-NEXT: 0x13010 R_X86_64_COPY x 0x0
+// CHECK-NEXT: 0x13000 R_X86_64_64 z 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/relocation-copy-i686.s b/test/ELF/relocation-copy-i686.s
index d61f84783cb6..f9ee32e2b35e 100644
--- a/test/ELF/relocation-copy-i686.s
+++ b/test/ELF/relocation-copy-i686.s
@@ -22,7 +22,7 @@ movl $9, z
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x13000
-// CHECK-NEXT: Offset: 0x3000
+// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 24
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
diff --git a/test/ELF/relocation-copy.s b/test/ELF/relocation-copy.s
index 2e958ad5e955..9d13241f5496 100644
--- a/test/ELF/relocation-copy.s
+++ b/test/ELF/relocation-copy.s
@@ -23,7 +23,7 @@ movl $z, %edx
// CHECK-NEXT: SHF_WRITE (0x1)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x13000
-// CHECK-NEXT: Offset: 0x3000
+// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 24
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
diff --git a/test/ELF/relocation-i686.s b/test/ELF/relocation-i686.s
index 529a35765f9e..96d760601127 100644
--- a/test/ELF/relocation-i686.s
+++ b/test/ELF/relocation-i686.s
@@ -45,8 +45,8 @@ movl bar@GOT, %eax
// ADDR-NEXT: SHF_ALLOC
// ADDR-NEXT: SHF_EXECINSTR
// ADDR-NEXT: ]
-// ADDR-NEXT: Address: 0x11030
-// ADDR-NEXT: Offset: 0x1030
+// ADDR-NEXT: Address: 0x11040
+// ADDR-NEXT: Offset: 0x1040
// ADDR-NEXT: Size: 32
// ADDR: Name: .got
@@ -69,16 +69,26 @@ R_386_GOTPC:
.section .dynamic_reloc, "ax",@progbits
call bar
-// 0x11030 - (0x11019 + 5) = 18
+// addr(.plt) + 16 - (0x11019 + 5) = 50
// CHECK: Disassembly of section .dynamic_reloc:
// CHECK-NEXT: .dynamic_reloc:
-// CHECK-NEXT: 11019: e8 22 00 00 00 calll 34
+// CHECK-NEXT: 11019: e8 32 00 00 00 calll 50
.section .R_386_GOT32,"ax",@progbits
.global R_386_GOT32
R_386_GOT32:
- movl zed@GOT, %eax
-// This is the second symbol in the got, so the offset is 4.
+ movl bar@GOT, %eax
+ movl zed@GOT, %eax
+ movl bar+8@GOT, %eax
+ movl zed+4@GOT, %eax
+
+// 4294967288 = 0xFFFFFFF8 = got[0](0x12070) - .got(0x12070) - sizeof(.got)(8)
+// 4294967292 = 0xFFFFFFFC = got[1](0x12074) - .got(0x12070) - sizeof(.got)(8)
+// 0xFFFFFFF8 + 8 = 0
+// 0xFFFFFFFC + 4 = 0
// CHECK: Disassembly of section .R_386_GOT32:
// CHECK-NEXT: R_386_GOT32:
-// CHECK-NEXT: 1101e: {{.*}} movl 4, %eax
+// CHECK-NEXT: 1101e: a1 f8 ff ff ff movl 4294967288, %eax
+// CHECK-NEXT: 11023: a1 fc ff ff ff movl 4294967292, %eax
+// CHECK-NEXT: 11028: a1 00 00 00 00 movl 0, %eax
+// CHECK-NEXT: 1102d: a1 00 00 00 00 movl 0, %eax
diff --git a/test/ELF/relocation-in-merge.s b/test/ELF/relocation-in-merge.s
index 820208a2cafe..9ce2e4f79150 100644
--- a/test/ELF/relocation-in-merge.s
+++ b/test/ELF/relocation-in-merge.s
@@ -1,7 +1,7 @@
// REQUIRES: x86
// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
// RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
-// CHECK: Relocations pointing to SHF_MERGE are not supported
+// CHECK: relocations pointing to SHF_MERGE are not supported
.section .foo,"aM",@progbits,4
.long bar
diff --git a/test/ELF/relocation-non-alloc.s b/test/ELF/relocation-non-alloc.s
new file mode 100644
index 000000000000..43f6f5ff1e4b
--- /dev/null
+++ b/test/ELF/relocation-non-alloc.s
@@ -0,0 +1,60 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -o %t2 -shared
+// RUN: llvm-readobj -s -section-data -r %t2 | FileCheck %s
+
+// CHECK: Name: .data
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2000
+// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000
+// CHECK-NEXT: )
+
+// CHECK: Name: foo
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 32
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00200000 00000000 00200000 00000000
+// CHECK-NEXT: 0010: 00200000 00000000 00200000 00000000
+// CHECK-NEXT: )
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.}}) .rela.dyn {
+// CHECK-NEXT: 0x2000 R_X86_64_RELATIVE - 0x2000
+// CHECK-NEXT: 0x2008 R_X86_64_64 zed 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+.data
+ .global zed
+zed:
+bar:
+ .quad bar
+ .quad zed
+
+ .section foo
+ .quad bar
+ .quad zed
+
+ .section foo
+ .quad bar
+ .quad zed
diff --git a/test/ELF/relocation-past-merge-end.s b/test/ELF/relocation-past-merge-end.s
index 4dadea1e7acd..993b071f62d2 100644
--- a/test/ELF/relocation-past-merge-end.s
+++ b/test/ELF/relocation-past-merge-end.s
@@ -1,7 +1,8 @@
// REQUIRES: x86
// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
// RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s
-// CHECK: Entry is past the end of the section
+// CHECK: entry is past the end of the section
+ .data
.long .foo + 1
.section .foo,"aM",@progbits,4
diff --git a/test/ELF/relocation-relative-absolute.s b/test/ELF/relocation-relative-absolute.s
new file mode 100644
index 000000000000..5253191331cc
--- /dev/null
+++ b/test/ELF/relocation-relative-absolute.s
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s
+
+.globl _start
+_start:
+
+# CHECK: relocation R_X86_64_PLT32 cannot refer to absolute symbol answer
+call answer@PLT
+
+.globl answer
+answer = 42
diff --git a/test/ELF/relocation-relative-synthetic.s b/test/ELF/relocation-relative-synthetic.s
new file mode 100644
index 000000000000..f4d449b844e4
--- /dev/null
+++ b/test/ELF/relocation-relative-synthetic.s
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t -pie
+# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s
+
+# CHECK: Dynamic Relocations {
+# CHECK-NEXT: }
+
+.globl _start
+_start:
+call __init_array_start@PLT
diff --git a/test/ELF/relocation-relative-weak.s b/test/ELF/relocation-relative-weak.s
new file mode 100644
index 000000000000..c525012acf67
--- /dev/null
+++ b/test/ELF/relocation-relative-weak.s
@@ -0,0 +1,14 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t -pie
+# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s
+
+# CHECK: Dynamic Relocations {
+# CHECK-NEXT: }
+
+.globl _start
+_start:
+
+.globl w
+.weak w
+call w@PLT
diff --git a/test/ELF/relocation-shared.s b/test/ELF/relocation-shared.s
new file mode 100644
index 000000000000..e1850944c459
--- /dev/null
+++ b/test/ELF/relocation-shared.s
@@ -0,0 +1,35 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -shared -o %t.so
+// RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s
+
+// CHECK: Name: foo
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1C8
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 380E0000 00000000
+// 0x1000 - 0x1C8 = 0xE38
+// CHECK-NEXT: )
+
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1000
+
+// CHECK: Relocations [
+// CHECK-NEXT: ]
+
+bar:
+ .section foo,"a",@progbits
+ .quad bar - .
diff --git a/test/ELF/relocation-size-shared.s b/test/ELF/relocation-size-shared.s
index 1b52e77b7d5f..d6274e9ae12e 100644
--- a/test/ELF/relocation-size-shared.s
+++ b/test/ELF/relocation-size-shared.s
@@ -7,48 +7,48 @@
// RELOCSHARED: Relocations [
// RELOCSHARED-NEXT: Section ({{.*}}) .rela.dyn {
-// RELOCSHARED-NEXT: 0x11018 R_X86_64_SIZE64 fooshared 0xFFFFFFFFFFFFFFFF
-// RELOCSHARED-NEXT: 0x11020 R_X86_64_SIZE64 fooshared 0x0
-// RELOCSHARED-NEXT: 0x11028 R_X86_64_SIZE64 fooshared 0x1
-// RELOCSHARED-NEXT: 0x11048 R_X86_64_SIZE32 fooshared 0xFFFFFFFFFFFFFFFF
-// RELOCSHARED-NEXT: 0x1104F R_X86_64_SIZE32 fooshared 0x0
-// RELOCSHARED-NEXT: 0x11056 R_X86_64_SIZE32 fooshared 0x1
+// RELOCSHARED-NEXT: 0x13018 R_X86_64_SIZE64 fooshared 0xFFFFFFFFFFFFFFFF
+// RELOCSHARED-NEXT: 0x13020 R_X86_64_SIZE64 fooshared 0x0
+// RELOCSHARED-NEXT: 0x13028 R_X86_64_SIZE64 fooshared 0x1
+// RELOCSHARED-NEXT: 0x13048 R_X86_64_SIZE32 fooshared 0xFFFFFFFFFFFFFFFF
+// RELOCSHARED-NEXT: 0x1304F R_X86_64_SIZE32 fooshared 0x0
+// RELOCSHARED-NEXT: 0x13056 R_X86_64_SIZE32 fooshared 0x1
// RELOCSHARED-NEXT: }
// RELOCSHARED-NEXT:]
-// DISASM: Disassembly of section .text:
+// DISASM: Disassembly of section test
// DISASM: _data:
-// DISASM-NEXT: 11000: 19 00
-// DISASM-NEXT: 11002: 00 00
-// DISASM-NEXT: 11004: 00 00
-// DISASM-NEXT: 11006: 00 00
-// DISASM-NEXT: 11008: 1a 00
-// DISASM-NEXT: 1100a: 00 00
-// DISASM-NEXT: 1100c: 00 00
-// DISASM-NEXT: 1100e: 00 00
-// DISASM-NEXT: 11010: 1b 00
-// DISASM-NEXT: 11012: 00 00
-// DISASM-NEXT: 11014: 00 00
-// DISASM-NEXT: 11016: 00 00
-// DISASM-NEXT: 11018: 00 00
-// DISASM-NEXT: 1101a: 00 00
-// DISASM-NEXT: 1101c: 00 00
-// DISASM-NEXT: 1101e: 00 00
-// DISASM-NEXT: 11020: 00 00
-// DISASM-NEXT: 11022: 00 00
-// DISASM-NEXT: 11024: 00 00
-// DISASM-NEXT: 11026: 00 00
-// DISASM-NEXT: 11028: 00 00
-// DISASM-NEXT: 1102a: 00 00
-// DISASM-NEXT: 1102c: 00 00
-// DISASM-NEXT: 1102e: 00 00
+// DISASM-NEXT: 13000: 19 00
+// DISASM-NEXT: 13002: 00 00
+// DISASM-NEXT: 13004: 00 00
+// DISASM-NEXT: 13006: 00 00
+// DISASM-NEXT: 13008: 1a 00
+// DISASM-NEXT: 1300a: 00 00
+// DISASM-NEXT: 1300c: 00 00
+// DISASM-NEXT: 1300e: 00 00
+// DISASM-NEXT: 13010: 1b 00
+// DISASM-NEXT: 13012: 00 00
+// DISASM-NEXT: 13014: 00 00
+// DISASM-NEXT: 13016: 00 00
+// DISASM-NEXT: 13018: 00 00
+// DISASM-NEXT: 1301a: 00 00
+// DISASM-NEXT: 1301c: 00 00
+// DISASM-NEXT: 1301e: 00 00
+// DISASM-NEXT: 13020: 00 00
+// DISASM-NEXT: 13022: 00 00
+// DISASM-NEXT: 13024: 00 00
+// DISASM-NEXT: 13026: 00 00
+// DISASM-NEXT: 13028: 00 00
+// DISASM-NEXT: 1302a: 00 00
+// DISASM-NEXT: 1302c: 00 00
+// DISASM-NEXT: 1302e: 00 00
// DISASM: _start:
-// DISASM-NEXT: 11030: 8b 04 25 19 00 00 00 movl 25, %eax
-// DISASM-NEXT: 11037: 8b 04 25 1a 00 00 00 movl 26, %eax
-// DISASM-NEXT: 1103e: 8b 04 25 1b 00 00 00 movl 27, %eax
-// DISASM-NEXT: 11045: 8b 04 25 00 00 00 00 movl 0, %eax
-// DISASM-NEXT: 1104c: 8b 04 25 00 00 00 00 movl 0, %eax
-// DISASM-NEXT: 11053: 8b 04 25 00 00 00 00 movl 0, %eax
+// DISASM-NEXT: 13030: 8b 04 25 19 00 00 00 movl 25, %eax
+// DISASM-NEXT: 13037: 8b 04 25 1a 00 00 00 movl 26, %eax
+// DISASM-NEXT: 1303e: 8b 04 25 1b 00 00 00 movl 27, %eax
+// DISASM-NEXT: 13045: 8b 04 25 00 00 00 00 movl 0, %eax
+// DISASM-NEXT: 1304c: 8b 04 25 00 00 00 00 movl 0, %eax
+// DISASM-NEXT: 13053: 8b 04 25 00 00 00 00 movl 0, %eax
.data
.global foo
@@ -57,7 +57,7 @@
foo:
.zero 26
-.text
+.section test, "awx"
_data:
// R_X86_64_SIZE64:
.quad foo@SIZE-1
diff --git a/test/ELF/relocation-size.s b/test/ELF/relocation-size.s
index aea3dafea071..58604dbcb4e4 100644
--- a/test/ELF/relocation-size.s
+++ b/test/ELF/relocation-size.s
@@ -9,84 +9,84 @@
// NORELOC: Relocations [
// NORELOC-NEXT: ]
-// DISASM: Disassembly of section .text:
+// DISASM: Disassembly of section test:
// DISASM-NEXT: _data:
-// DISASM-NEXT: 11000: 19 00
-// DISASM-NEXT: 11002: 00 00
-// DISASM-NEXT: 11004: 00 00
-// DISASM-NEXT: 11006: 00 00
-// DISASM-NEXT: 11008: 1a 00
-// DISASM-NEXT: 1100a: 00 00
-// DISASM-NEXT: 1100c: 00 00
-// DISASM-NEXT: 1100e: 00 00
-// DISASM-NEXT: 11010: 1b 00
-// DISASM-NEXT: 11012: 00 00
-// DISASM-NEXT: 11014: 00 00
-// DISASM-NEXT: 11016: 00 00
-// DISASM-NEXT: 11018: 19 00
-// DISASM-NEXT: 1101a: 00 00
-// DISASM-NEXT: 1101c: 00 00
-// DISASM-NEXT: 1101e: 00 00
-// DISASM-NEXT: 11020: 1a 00
-// DISASM-NEXT: 11022: 00 00
-// DISASM-NEXT: 11024: 00 00
-// DISASM-NEXT: 11026: 00 00
-// DISASM-NEXT: 11028: 1b 00
-// DISASM-NEXT: 1102a: 00 00
-// DISASM-NEXT: 1102c: 00 00
-// DISASM-NEXT: 1102e: 00 00
+// DISASM-NEXT: 12000: 19 00
+// DISASM-NEXT: 12002: 00 00
+// DISASM-NEXT: 12004: 00 00
+// DISASM-NEXT: 12006: 00 00
+// DISASM-NEXT: 12008: 1a 00
+// DISASM-NEXT: 1200a: 00 00
+// DISASM-NEXT: 1200c: 00 00
+// DISASM-NEXT: 1200e: 00 00
+// DISASM-NEXT: 12010: 1b 00
+// DISASM-NEXT: 12012: 00 00
+// DISASM-NEXT: 12014: 00 00
+// DISASM-NEXT: 12016: 00 00
+// DISASM-NEXT: 12018: 19 00
+// DISASM-NEXT: 1201a: 00 00
+// DISASM-NEXT: 1201c: 00 00
+// DISASM-NEXT: 1201e: 00 00
+// DISASM-NEXT: 12020: 1a 00
+// DISASM-NEXT: 12022: 00 00
+// DISASM-NEXT: 12024: 00 00
+// DISASM-NEXT: 12026: 00 00
+// DISASM-NEXT: 12028: 1b 00
+// DISASM-NEXT: 1202a: 00 00
+// DISASM-NEXT: 1202c: 00 00
+// DISASM-NEXT: 1202e: 00 00
// DISASM: _start:
-// DISASM-NEXT: 11030: 8b 04 25 19 00 00 00 movl 25, %eax
-// DISASM-NEXT: 11037: 8b 04 25 1a 00 00 00 movl 26, %eax
-// DISASM-NEXT: 1103e: 8b 04 25 1b 00 00 00 movl 27, %eax
-// DISASM-NEXT: 11045: 8b 04 25 19 00 00 00 movl 25, %eax
-// DISASM-NEXT: 1104c: 8b 04 25 1a 00 00 00 movl 26, %eax
-// DISASM-NEXT: 11053: 8b 04 25 1b 00 00 00 movl 27, %eax
+// DISASM-NEXT: 12030: 8b 04 25 19 00 00 00 movl 25, %eax
+// DISASM-NEXT: 12037: 8b 04 25 1a 00 00 00 movl 26, %eax
+// DISASM-NEXT: 1203e: 8b 04 25 1b 00 00 00 movl 27, %eax
+// DISASM-NEXT: 12045: 8b 04 25 19 00 00 00 movl 25, %eax
+// DISASM-NEXT: 1204c: 8b 04 25 1a 00 00 00 movl 26, %eax
+// DISASM-NEXT: 12053: 8b 04 25 1b 00 00 00 movl 27, %eax
// RELOCSHARED: Relocations [
// RELOCSHARED-NEXT: Section ({{.*}}) .rela.dyn {
-// RELOCSHARED-NEXT: 0x1000 R_X86_64_SIZE64 foo 0xFFFFFFFFFFFFFFFF
-// RELOCSHARED-NEXT: 0x1008 R_X86_64_SIZE64 foo 0x0
-// RELOCSHARED-NEXT: 0x1010 R_X86_64_SIZE64 foo 0x1
-// RELOCSHARED-NEXT: 0x1033 R_X86_64_SIZE32 foo 0xFFFFFFFFFFFFFFFF
-// RELOCSHARED-NEXT: 0x103A R_X86_64_SIZE32 foo 0x0
-// RELOCSHARED-NEXT: 0x1041 R_X86_64_SIZE32 foo 0x1
+// RELOCSHARED-NEXT: 0x3000 R_X86_64_SIZE64 foo 0xFFFFFFFFFFFFFFFF
+// RELOCSHARED-NEXT: 0x3008 R_X86_64_SIZE64 foo 0x0
+// RELOCSHARED-NEXT: 0x3010 R_X86_64_SIZE64 foo 0x1
+// RELOCSHARED-NEXT: 0x3033 R_X86_64_SIZE32 foo 0xFFFFFFFFFFFFFFFF
+// RELOCSHARED-NEXT: 0x303A R_X86_64_SIZE32 foo 0x0
+// RELOCSHARED-NEXT: 0x3041 R_X86_64_SIZE32 foo 0x1
// RELOCSHARED-NEXT: }
// RELOCSHARED-NEXT: ]
-// DISASMSHARED: Disassembly of section .text:
+// DISASMSHARED: Disassembly of section test:
// DISASMSHARED-NEXT: _data:
-// DISASMSHARED-NEXT: 1000: 00 00
-// DISASMSHARED-NEXT: 1002: 00 00
-// DISASMSHARED-NEXT: 1004: 00 00
-// DISASMSHARED-NEXT: 1006: 00 00
-// DISASMSHARED-NEXT: 1008: 00 00
-// DISASMSHARED-NEXT: 100a: 00 00
-// DISASMSHARED-NEXT: 100c: 00 00
-// DISASMSHARED-NEXT: 100e: 00 00
-// DISASMSHARED-NEXT: 1010: 00 00
-// DISASMSHARED-NEXT: 1012: 00 00
-// DISASMSHARED-NEXT: 1014: 00 00
-// DISASMSHARED-NEXT: 1016: 00 00
-// DISASMSHARED-NEXT: 1018: 19 00
-// DISASMSHARED-NEXT: 101a: 00 00
-// DISASMSHARED-NEXT: 101c: 00 00
-// DISASMSHARED-NEXT: 101e: 00 00
-// DISASMSHARED-NEXT: 1020: 1a 00
-// DISASMSHARED-NEXT: 1022: 00 00
-// DISASMSHARED-NEXT: 1024: 00 00
-// DISASMSHARED-NEXT: 1026: 00 00
-// DISASMSHARED-NEXT: 1028: 1b 00
-// DISASMSHARED-NEXT: 102a: 00 00
-// DISASMSHARED-NEXT: 102c: 00 00
-// DISASMSHARED-NEXT: 102e: 00 00
+// DISASMSHARED-NEXT: 3000: 00 00
+// DISASMSHARED-NEXT: 3002: 00 00
+// DISASMSHARED-NEXT: 3004: 00 00
+// DISASMSHARED-NEXT: 3006: 00 00
+// DISASMSHARED-NEXT: 3008: 00 00
+// DISASMSHARED-NEXT: 300a: 00 00
+// DISASMSHARED-NEXT: 300c: 00 00
+// DISASMSHARED-NEXT: 300e: 00 00
+// DISASMSHARED-NEXT: 3010: 00 00
+// DISASMSHARED-NEXT: 3012: 00 00
+// DISASMSHARED-NEXT: 3014: 00 00
+// DISASMSHARED-NEXT: 3016: 00 00
+// DISASMSHARED-NEXT: 3018: 19 00
+// DISASMSHARED-NEXT: 301a: 00 00
+// DISASMSHARED-NEXT: 301c: 00 00
+// DISASMSHARED-NEXT: 301e: 00 00
+// DISASMSHARED-NEXT: 3020: 1a 00
+// DISASMSHARED-NEXT: 3022: 00 00
+// DISASMSHARED-NEXT: 3024: 00 00
+// DISASMSHARED-NEXT: 3026: 00 00
+// DISASMSHARED-NEXT: 3028: 1b 00
+// DISASMSHARED-NEXT: 302a: 00 00
+// DISASMSHARED-NEXT: 302c: 00 00
+// DISASMSHARED-NEXT: 302e: 00 00
// DISASMSHARED: _start:
-// DISASMSHARED-NEXT: 1030: 8b 04 25 00 00 00 00 movl 0, %eax
-// DISASMSHARED-NEXT: 1037: 8b 04 25 00 00 00 00 movl 0, %eax
-// DISASMSHARED-NEXT: 103e: 8b 04 25 00 00 00 00 movl 0, %eax
-// DISASMSHARED-NEXT: 1045: 8b 04 25 19 00 00 00 movl 25, %eax
-// DISASMSHARED-NEXT: 104c: 8b 04 25 1a 00 00 00 movl 26, %eax
-// DISASMSHARED-NEXT: 1053: 8b 04 25 1b 00 00 00 movl 27, %eax
+// DISASMSHARED-NEXT: 3030: 8b 04 25 00 00 00 00 movl 0, %eax
+// DISASMSHARED-NEXT: 3037: 8b 04 25 00 00 00 00 movl 0, %eax
+// DISASMSHARED-NEXT: 303e: 8b 04 25 00 00 00 00 movl 0, %eax
+// DISASMSHARED-NEXT: 3045: 8b 04 25 19 00 00 00 movl 25, %eax
+// DISASMSHARED-NEXT: 304c: 8b 04 25 1a 00 00 00 movl 26, %eax
+// DISASMSHARED-NEXT: 3053: 8b 04 25 1b 00 00 00 movl 27, %eax
.data
.global foo
@@ -103,7 +103,7 @@ foo:
foohidden:
.zero 26
-.text
+.section test,"axw"
_data:
// R_X86_64_SIZE64:
.quad foo@SIZE-1
diff --git a/test/ELF/relocation.s b/test/ELF/relocation.s
index 33b0e23ee972..11832683d9be 100644
--- a/test/ELF/relocation.s
+++ b/test/ELF/relocation.s
@@ -14,7 +14,7 @@
// SEC-NEXT: ]
// SEC-NEXT: Address: 0x11030
// SEC-NEXT: Offset: 0x1030
-// SEC-NEXT: Size: 32
+// SEC-NEXT: Size: 48
// SEC: Name: .got
// SEC-NEXT: Type: SHT_PROGBITS
@@ -39,7 +39,7 @@
// SEC-NEXT: ]
// SEC-NEXT: Address: 0x13000
// SEC-NEXT: Offset: 0x3000
-// SEC-NEXT: Size: 32
+// SEC-NEXT: Size: 40
// SEC-NEXT: Link: 0
// SEC-NEXT: Info: 0
// SEC-NEXT: AddressAlignment: 8
@@ -98,6 +98,15 @@ R_X86_64_PC32:
// CHECK-NEXT: 11017: {{.*}} callq 36
// CHECK-NEXT: 1101c: {{.*}} movl $69696, %eax
+.section .R_X86_64_32S_2,"ax",@progbits
+.global R_X86_64_32S_2
+R_X86_64_32S_2:
+ mov bar2, %eax
+// plt is at 0x11030. The second plt entry is at 0x11050 == 69712
+// CHECK: Disassembly of section .R_X86_64_32S_2:
+// CHECK-NEXT: R_X86_64_32S_2:
+// CHECK-NEXT: 11021: {{.*}} movl 69712, %eax
+
.section .R_X86_64_64,"a",@progbits
.global R_X86_64_64
R_X86_64_64:
@@ -115,3 +124,11 @@ R_X86_64_GOTPCREL:
// 7952 = 0x101f0000 in little endian
// CHECK: Contents of section .R_X86_64_GOTPCREL
// CHECK-NEXT: 101d0 201f0000
+
+.section .R_X86_64_GOT32,"a",@progbits
+.global R_X86_64_GOT32
+R_X86_64_GOT32:
+ .long zed@got
+
+// CHECK: Contents of section .R_X86_64_GOT32:
+// CHECK-NEXT: f8ffffff
diff --git a/test/ELF/relro-tls.s b/test/ELF/relro-tls.s
new file mode 100644
index 000000000000..0ee5b6d328c2
--- /dev/null
+++ b/test/ELF/relro-tls.s
@@ -0,0 +1,23 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %tout
+// RUN: llvm-readobj -program-headers %tout | FileCheck %s
+
+// CHECK: Type: PT_GNU_RELRO
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: VirtualAddress:
+// CHECK-NEXT: PhysicalAddress:
+// CHECK-NEXT: FileSize: 4
+// CHECK-NEXT: MemSize: 4
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: PF_R
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 1
+
+.global _start
+_start:
+
+.global d
+.section .foo,"awT",@progbits
+d:
+.long 2
diff --git a/test/ELF/relro.s b/test/ELF/relro.s
index 692d6b271cf8..d35548740001 100644
--- a/test/ELF/relro.s
+++ b/test/ELF/relro.s
@@ -232,7 +232,7 @@
.global _start
_start:
.long bar
- jmp *bar@GOTPCREL(%rip)
+ jmp *bar2@GOTPCREL(%rip)
.section .data,"aw"
.quad 0
diff --git a/test/ELF/reproduce-error.s b/test/ELF/reproduce-error.s
new file mode 100644
index 000000000000..c66132c4bd01
--- /dev/null
+++ b/test/ELF/reproduce-error.s
@@ -0,0 +1,15 @@
+# Extracting the cpio archive can get over the path limit on windows.
+# REQUIRES: shell
+
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir
+# RUN: cd %t.dir
+
+# RUN: not ld.lld --reproduce repro abc -o t 2>&1 | FileCheck %s
+# CHECK: cannot open abc: {{N|n}}o such file or directory
+
+# RUN: grep TRAILER repro.cpio
+# RUN: cpio -id < repro.cpio
+# RUN: FileCheck --check-prefix=RSP %s < repro/response.txt
+# RSP: abc
+# RSP: -o t
diff --git a/test/ELF/reproduce-linkerscript.s b/test/ELF/reproduce-linkerscript.s
new file mode 100644
index 000000000000..a020fcc9a4f1
--- /dev/null
+++ b/test/ELF/reproduce-linkerscript.s
@@ -0,0 +1,17 @@
+# REQUIRES: x86, shell
+
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir/build
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build/foo.o
+# RUN: echo "INPUT(\"%t.dir/build/foo.o\")" > %t.dir/build/foo.script
+# RUN: cd %t.dir
+# RUN: ld.lld build/foo.script -o bar --reproduce repro
+# RUN: cpio -id < repro.cpio
+# RUN: diff build/foo.script repro/%:t.dir/build/foo.script
+# RUN: diff build/foo.o repro/%:t.dir/build/foo.o
+
+.globl _start
+_start:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/reproduce-thin-archive.s b/test/ELF/reproduce-thin-archive.s
new file mode 100644
index 000000000000..0797b6c67e9c
--- /dev/null
+++ b/test/ELF/reproduce-thin-archive.s
@@ -0,0 +1,15 @@
+# REQUIRES: x86, shell
+
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.dir/foo.o
+# RUN: cd %t.dir
+# RUN: llvm-ar --format=gnu rcT foo.a foo.o
+# RUN: ld.lld -m elf_x86_64 foo.a -o bar --reproduce repro
+# RUN: cpio -id < repro.cpio
+# RUN: diff foo.a repro/%:t.dir/foo.a
+# RUN: diff foo.o repro/%:t.dir/foo.o
+
+.globl _start
+_start:
+ nop
diff --git a/test/ELF/reproduce-windows.s b/test/ELF/reproduce-windows.s
new file mode 100644
index 000000000000..464b27098694
--- /dev/null
+++ b/test/ELF/reproduce-windows.s
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+
+# Test that a repro archive always uses / instead of \.
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir/build
+# RUN: llvm-mc %s -o %t.dir/build/foo.o -filetype=obj -triple=x86_64-pc-linux
+# RUN: cd %t.dir
+# RUN: not ld.lld build/foo.o --reproduce repro
+# RUN: cpio -t < repro.cpio | FileCheck %s
+
+# CHECK: repro/response.txt
+# CHECK: repro/{{.*}}/build/foo.o
diff --git a/test/ELF/reproduce.s b/test/ELF/reproduce.s
new file mode 100644
index 000000000000..9d256c12d827
--- /dev/null
+++ b/test/ELF/reproduce.s
@@ -0,0 +1,67 @@
+# REQUIRES: x86
+
+# Extracting the cpio archive can get over the path limit on windows.
+# REQUIRES: shell
+
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir/build1
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build1/foo.o
+# RUN: cd %t.dir
+# RUN: ld.lld --hash-style=gnu build1/foo.o -o bar -shared --as-needed --reproduce repro
+# RUN: cpio -id < repro.cpio
+# RUN: diff build1/foo.o repro/%:t.dir/build1/foo.o
+
+# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
+# RSP: {{^}}--hash-style gnu{{$}}
+# RSP-NOT: repro{{[/\\]}}
+# RSP-NEXT: {{[/\\]}}foo.o
+# RSP-NEXT: -o bar
+# RSP-NEXT: -shared
+# RSP-NEXT: --as-needed
+
+# RUN: FileCheck %s --check-prefix=VERSION < repro/version.txt
+# VERSION: LLD
+
+# RUN: mkdir -p %t.dir/build2/a/b/c
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build2/foo.o
+# RUN: cd %t.dir/build2/a/b/c
+# RUN: env LLD_REPRODUCE=repro ld.lld ./../../../foo.o -o bar -shared --as-needed
+# RUN: cpio -id < repro.cpio
+# RUN: diff %t.dir/build2/foo.o repro/%:t.dir/build2/foo.o
+
+# RUN: echo "{ local: *; };" > ver
+# RUN: echo > dyn
+# RUN: echo > file
+# RUN: echo > file2
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o 'foo bar'
+# RUN: ld.lld --reproduce repro2 'foo bar' -L"foo bar" -Lfile -Tfile2 \
+# RUN: --dynamic-list dyn -rpath file --script file --version-script ver \
+# RUN: --dynamic-linker "some unusual/path" -soname 'foo bar' -soname='foo bar'
+# RUN: cpio -id < repro2.cpio
+# RUN: FileCheck %s --check-prefix=RSP2 < repro2/response.txt
+# RSP2: "{{.*}}foo bar"
+# RSP2-NEXT: -L "{{.*}}foo bar"
+# RSP2-NEXT: -L {{.+}}file
+# RSP2-NEXT: --script {{.+}}file2
+# RSP2-NEXT: --dynamic-list {{.+}}dyn
+# RSP2-NEXT: -rpath {{.+}}file
+# RSP2-NEXT: --script {{.+}}file
+# RSP2-NEXT: --version-script [[PATH:.*]]ver
+# RSP2-NEXT: --dynamic-linker "some unusual/path"
+# RSP2-NEXT: -soname="foo bar"
+# RSP2-NEXT: -soname="foo bar"
+
+# RUN: cpio -t < repro2.cpio | FileCheck %s
+# CHECK: repro2/response.txt
+# CHECK-NEXT: repro2/version.txt
+# CHECK-NEXT: repro2/{{.*}}/dyn
+# CHECK-NEXT: repro2/{{.*}}/ver
+# CHECK-NEXT: repro2/{{.*}}/foo bar
+# CHECK-NEXT: repro2/{{.*}}/file2
+# CHECK-NEXT: repro2/{{.*}}/file
+
+.globl _start
+_start:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/resolution-shared.s b/test/ELF/resolution-shared.s
new file mode 100644
index 000000000000..e1eac070e5af
--- /dev/null
+++ b/test/ELF/resolution-shared.s
@@ -0,0 +1,15 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution-shared.s -o %t2.o
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t3 -shared
+// RUN: llvm-readobj -t %t3 | FileCheck %s
+// REQUIRES: x86
+
+ .weak foo
+foo:
+
+// CHECK: Symbol {
+// CHECK: Name: foo
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Weak
diff --git a/test/ELF/resolution.s b/test/ELF/resolution.s
index ce275c2934a4..5596212b3bac 100644
--- a/test/ELF/resolution.s
+++ b/test/ELF/resolution.s
@@ -309,7 +309,7 @@
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: UndefWeak_with_UndefWeak
// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 15
+// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Weak
// CHECK-NEXT: Type: None
// CHECK-NEXT: Other: 0
diff --git a/test/ELF/section-align-0.test b/test/ELF/section-align-0.test
index fc27ee95fd4b..35783f5a894b 100644
--- a/test/ELF/section-align-0.test
+++ b/test/ELF/section-align-0.test
@@ -1,8 +1,9 @@
-# RUN: yaml2obj -format elf %s -o %t
+# RUN: yaml2obj %s -o %t
# RUN: ld.lld %t -o %tout
# Verify that lld can handle sections with an alignment of zero.
+!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
diff --git a/test/ELF/section-name.s b/test/ELF/section-name.s
index 2d7ed4e63717..f470c48c6a37 100644
--- a/test/ELF/section-name.s
+++ b/test/ELF/section-name.s
@@ -21,11 +21,17 @@ _start:
.section .data.rel.ro.a,"aw",%progbits
.section .data.rel.ro.local,"aw",%progbits
.section .data.rel.ro.local.a,"aw",%progbits
+.section .tbss.foo,"aGwT",@nobits,foo,comdat
+.section .gcc_except_table.foo,"aG",@progbits,foo,comdat
+.section .tdata.foo,"aGwT",@progbits,foo,comdat
// CHECK-NOT: Name: .rodata.a
// CHECK: Name: .rodata
+// CHECK: Name: .gcc_except_table ({{.*}})
// CHECK-NOT: Name: .text.a
// CHECK: Name: .text
+// CHECK: Name: .tdata ({{.*}})
+// CHECK: Name: .tbss ({{.*}})
// CHECK-NOT: Name: .data.rel.ro.a
// CHECK-NOT: Name: .data.rel.ro.local.a
// CHECK: Name: .data.rel.ro
diff --git a/test/ELF/section-symbol.s b/test/ELF/section-symbol.s
index 5f04606914fb..5cf71aceec72 100644
--- a/test/ELF/section-symbol.s
+++ b/test/ELF/section-symbol.s
@@ -23,7 +23,18 @@
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _DYNAMIC
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .dynamic
+// CHECK-NEXT: }
// CHECK-NEXT: ]
foo:
- .quad foo
+ .quad foo - .
diff --git a/test/ELF/shared-be.s b/test/ELF/shared-be.s
index 0f57a4b7f0c3..12eb3131050a 100644
--- a/test/ELF/shared-be.s
+++ b/test/ELF/shared-be.s
@@ -20,17 +20,18 @@
// CHECK: DynamicSection [
// CHECK-NEXT: Tag Type Name/Value
+// CHECK-NEXT: 0x000000000000001D RUNPATH foo:bar
+// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x0000000000000007 RELA [[RELADDR]]
// CHECK-NEXT: 0x0000000000000008 RELASZ [[RELSIZE]] (bytes)
// CHECK-NEXT: 0x0000000000000009 RELAENT [[RELENT]] (bytes)
-// CHECK: 0x000000000000001D RUNPATH foo:bar
-// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
-// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0
+// CHECK: 0x0000000000000015 DEBUG 0x0
// CHECK-NEXT: 0x0000000000000000 NULL 0x0
// CHECK-NEXT: ]
.global _start
_start:
+.data
.long bar
.long zed
diff --git a/test/ELF/shared.s b/test/ELF/shared.s
index 1bf5bd1795bc..a81a09370999 100644
--- a/test/ELF/shared.s
+++ b/test/ELF/shared.s
@@ -144,6 +144,17 @@
// CHECK-NEXT: Section: Undefined
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _DYNAMIC
+// CHECK-NEXT: Value: 0x12000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .dynamic
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: _start
// CHECK-NEXT: Value: 0x11000
// CHECK-NEXT: Size: 0
@@ -243,6 +254,8 @@
// CHECK: DynamicSection [
// CHECK-NEXT: Tag Type Name/Value
+// CHECK-NEXT: 0x0000001D RUNPATH foo:bar
+// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x00000011 REL [[RELADDR]]
// CHECK-NEXT: 0x00000012 RELSZ [[RELSIZE]] (bytes)
// CHECK-NEXT: 0x00000013 RELENT [[RELENT]] (bytes)
@@ -251,8 +264,6 @@
// CHECK-NEXT: 0x00000005 STRTAB [[DYNSTRADDR]]
// CHECK-NEXT: 0x0000000A STRSZ
// CHECK-NEXT: 0x00000004 HASH [[HASHADDR]]
-// CHECK-NEXT: 0x0000001D RUNPATH foo:bar
-// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x00000015 DEBUG 0x0
// CHECK-NEXT: 0x00000000 NULL 0x0
// CHECK-NEXT: ]
@@ -291,5 +302,5 @@
.global _start
_start:
-.long bar
-.long zed
+.long bar@GOT
+.long zed@GOT
diff --git a/test/ELF/soname.s b/test/ELF/soname.s
index 9d6fe7681dac..65e95ce85add 100644
--- a/test/ELF/soname.s
+++ b/test/ELF/soname.s
@@ -1,6 +1,6 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
// RUN: ld.lld %t.o -shared -soname=bar -o %t.so
-// RUN: ld.lld %t.o -shared -soname=bar -o %t2.so
+// RUN: ld.lld %t.o -shared --soname=bar -o %t2.so
// RUN: ld.lld %t.o %t.so %t2.so -o %t
// RUN: llvm-readobj --dynamic-table %t | FileCheck %s
diff --git a/test/ELF/splitstacks.s b/test/ELF/splitstacks.s
new file mode 100644
index 000000000000..6506b48a2513
--- /dev/null
+++ b/test/ELF/splitstacks.s
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+
+# RUN: not ld.lld %t1.o -o %t 2>&1 | FileCheck %s
+# CHECK: objects using splitstacks are not supported
+
+.globl _start
+_start:
+ nop
+
+.section .note.GNU-split-stack,"",@progbits
diff --git a/test/ELF/start-lib-comdat.s b/test/ELF/start-lib-comdat.s
new file mode 100644
index 000000000000..ce03959fd74b
--- /dev/null
+++ b/test/ELF/start-lib-comdat.s
@@ -0,0 +1,23 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \
+// RUN: %p/Inputs/start-lib-comdat.s -o %t2.o
+// RUN: ld.lld -shared -o %t3 %t1.o --start-lib %t2.o --end-lib
+// RUN: llvm-readobj -t %t3 | FileCheck %s
+// RUN: ld.lld -shared -o %t3 --start-lib %t2.o --end-lib %t1.o
+// RUN: llvm-readobj -t %t3 | FileCheck %s
+
+// CHECK: Name: zed
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type:
+// CHECK-NEXT: Other:
+// CHECK-NEXT: Section: Undefined
+
+ call bar@plt
+// The other file also has a section in the zed comdat, but it defines the
+// symbol zed. That means that we will have a lazy symbol zed, but when adding
+// the actual file zed will be undefined.
+ .section .sec,"aG",@progbits,zed,comdat
diff --git a/test/ELF/start-lib.s b/test/ELF/start-lib.s
new file mode 100644
index 000000000000..013a2b206a1f
--- /dev/null
+++ b/test/ELF/start-lib.s
@@ -0,0 +1,25 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN: %p/Inputs/start-lib1.s -o %t2.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN: %p/Inputs/start-lib2.s -o %t3.o
+
+// RUN: ld.lld -o %t3 %t1.o %t2.o %t3.o
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST1 %s
+// TEST1: Name: bar
+// TEST1: Name: foo
+
+// RUN: ld.lld -o %t3 %t1.o -u bar --start-lib %t2.o %t3.o
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST2 %s
+// TEST2: Name: bar
+// TEST2-NOT: Name: foo
+
+// RUN: ld.lld -o %t3 %t1.o --start-lib %t2.o %t3.o
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TEST3 %s
+// TEST3-NOT: Name: bar
+// TEST3-NOT: Name: foo
+
+.globl _start
+_start:
diff --git a/test/ELF/startstop-gccollect.s b/test/ELF/startstop-gccollect.s
new file mode 100644
index 000000000000..b0cd41337e34
--- /dev/null
+++ b/test/ELF/startstop-gccollect.s
@@ -0,0 +1,32 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## Default run: sections foo and bar exist in output
+# RUN: ld.lld %t -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
+
+## Check that foo and bar sections are not garbage collected,
+## we do not want to reclaim sections if they can be referred
+## by __start_* and __stop_* symbols.
+# RUN: ld.lld %t --gc-sections -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
+
+# DISASM: _start:
+# DISASM-NEXT: 11000: 90 nop
+# DISASM-NEXT: Disassembly of section foo:
+# DISASM-NEXT: foo:
+# DISASM-NEXT: 11001: 90 nop
+# DISASM-NEXT: Disassembly of section bar:
+# DISASM-NEXT: bar:
+# DISASM-NEXT: 11002: 90 nop
+
+.global _start
+.text
+_start:
+ nop
+
+.section foo,"ax"
+ nop
+
+.section bar,"ax"
+ nop
diff --git a/test/ELF/startstop-shared.s b/test/ELF/startstop-shared.s
index 108184648f97..77411f3f25c9 100644
--- a/test/ELF/startstop-shared.s
+++ b/test/ELF/startstop-shared.s
@@ -3,16 +3,24 @@
// RUN: ld.lld %t.o -o %t.so -shared
// RUN: llvm-readobj -r -t %t.so | FileCheck %s
+ .data
.quad __start_foo
- .section foo,"a"
-// By default the symbol is visible and we need a dynamic reloc.
-// CHECK: R_X86_64_64 __start_foo 0x0
+ .section foo,"aw"
+// By default the symbol is hidden.
+// CHECK: R_X86_64_RELATIVE - 0x[[ADDR1:.*]]
.hidden __start_bar
.quad __start_bar
.section bar,"a"
-// Test that we are able to hide the symbol.
-// CHECK: R_X86_64_RELATIVE - 0x[[ADDR:.*]]
+// References do not affect the visibility.
+// CHECK: R_X86_64_RELATIVE - 0x[[ADDR2:.*]]
// CHECK: Name: __start_bar
-// CHECK-NEXT: Value: 0x[[ADDR]]
+// CHECK-NEXT: Value: 0x[[ADDR2]]
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Local
+
+// CHECK: Name: __start_foo
+// CHECK-NEXT: Value: 0x[[ADDR1]]
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Local
diff --git a/test/ELF/startstop.s b/test/ELF/startstop.s
index d0e88df4e7eb..a7b2e43e6a5f 100644
--- a/test/ELF/startstop.s
+++ b/test/ELF/startstop.s
@@ -20,7 +20,13 @@
// DISASM: 1014: 90 nop
-// SYMBOL: Relocations [
+// SYMBOL: Relocations [
+// SYMBOL-NEXT: Section ({{.*}}) .rela.dyn {
+// SYMBOL-NEXT: 0x3000 R_X86_64_RELATIVE - 0x3020
+// SYMBOL-NEXT: 0x3008 R_X86_64_RELATIVE - 0x3021
+// SYMBOL-NEXT: 0x3010 R_X86_64_RELATIVE - 0x3010
+// SYMBOL-NEXT: 0x3018 R_X86_64_RELATIVE - 0x3011
+// SYMBOL-NEXT: }
// SYMBOL-NEXT: ]
// SYMBOL: Symbol {
@@ -59,3 +65,11 @@ _start:
nop
nop
nop
+
+.section zed1, "aw"
+ .quad __stop_zed2
+ .quad __stop_zed2 + 1
+
+.section zed2, "aw"
+ .quad __stop_zed1
+ .quad __stop_zed1 + 1
diff --git a/test/ELF/string-gc.s b/test/ELF/string-gc.s
new file mode 100644
index 000000000000..e7f86a1c6077
--- /dev/null
+++ b/test/ELF/string-gc.s
@@ -0,0 +1,73 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t --gc-sections
+// RUN: llvm-readobj -symbols %t | FileCheck %s
+
+// CHECK: Symbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: (0)
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local (0x0)
+// CHECK-NEXT: Type: None (0x0)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined (0x0)
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: s3
+// CHECK-NEXT: Value: 0x10125
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local (0x0)
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .rodata (0x1)
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: s1
+// CHECK-NEXT: Value: 0x10120
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local (0x0)
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .rodata (0x1)
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _start
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global (0x1)
+// CHECK-NEXT: Type: Function (0x2)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text (0x2)
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+.text
+.globl _start
+.type _start,@function
+_start:
+movl $s1, %eax
+movl $s3, %eax
+
+.hidden s1
+.type s1,@object
+.section .rodata.str1.1,"aMS",@progbits,1
+.globl s1
+s1:
+.asciz "abcd"
+
+.hidden s2
+.type s2,@object
+.globl s2
+s2:
+.asciz "efgh"
+
+.type s3,@object
+s3:
+.asciz "ijkl"
+
+.type s4,@object
+.globl s4
+s4:
+.asciz "mnop"
diff --git a/test/ELF/string-table.s b/test/ELF/string-table.s
index 8393d6de6cc5..892c348f6fd0 100644
--- a/test/ELF/string-table.s
+++ b/test/ELF/string-table.s
@@ -59,9 +59,8 @@ _start:
// CHECK-NEXT: EntrySize: 0
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 00626172 002E7465 78740066 6F6F6261 |.bar..text.fooba|
-// CHECK-NEXT: 0010: 7200666F 6F626172 00666F6F 62617200 |r.foobar.foobar.|
-// CHECK-NEXT: 0020: 2E73796D 74616200 2E736873 74727461 |.symtab..shstrta|
-// CHECK-NEXT: 0030: 62002E73 74727461 6200 |b..strtab.|
+// CHECK-NEXT: 0010: 72002E73 796D7461 62002E73 68737472 |r..symtab..shstr|
+// CHECK-NEXT: 0020: 74616200 2E737472 74616200 |tab..strtab.|
// CHECK-NEXT: )
// CHECK-NEXT:}
// CHECK: Name: .strtab
diff --git a/test/ELF/strip-all.s b/test/ELF/strip-all.s
index 6d18431668ae..f322119b0dbb 100644
--- a/test/ELF/strip-all.s
+++ b/test/ELF/strip-all.s
@@ -13,12 +13,16 @@
#AFTER: .shstrtab
#AFTER-NOT: .strtab
+# Ignore --strip-all if -r is specified
+#RUN: ld.lld %t.o --strip-all -r -o %t1
+#RUN: llvm-objdump -section-headers %t1 | FileCheck %s -check-prefix BEFORE
+
# Test alias -s
#RUN: ld.lld %t.o -s -o %t1
#RUN: llvm-objdump -section-headers %t1 | FileCheck %s -check-prefix AFTER
# exits with return code 42 on linux
-.globl _start;
+.globl _start
_start:
mov $60, %rax
mov $42, %rdi
diff --git a/test/ELF/strip-debug.s b/test/ELF/strip-debug.s
new file mode 100644
index 000000000000..81f7572aa7c5
--- /dev/null
+++ b/test/ELF/strip-debug.s
@@ -0,0 +1,25 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -g %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=DEFAULT %s
+# RUN: ld.lld %t -o %t2 --strip-debug
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=STRIP %s
+# RUN: ld.lld %t -o %t2 -S
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=STRIP %s
+# RUN: ld.lld %t -o %t2 --strip-all
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=STRIP %s
+
+# DEFAULT: Name: .debug_info
+# DEFAULT: Name: .debug_abbrev
+# DEFAULT: Name: .debug_aranges
+# DEFAULT: Name: .debug_line
+
+# STRIP-NOT: Name: .debug_info
+# STRIP-NOT: Name: .debug_abbrev
+# STRIP-NOT: Name: .debug_aranges
+# STRIP-NOT: Name: .debug_line
+
+.globl _start
+_start:
+ ret
diff --git a/test/ELF/symbol-override.s b/test/ELF/symbol-override.s
new file mode 100644
index 000000000000..487885b75b36
--- /dev/null
+++ b/test/ELF/symbol-override.s
@@ -0,0 +1,46 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/symbol-override.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t1.o %t2.so -o %t
+// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+// CHECK: DynamicSymbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name:
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: do
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Function
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: foo
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Function
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+.text
+.globl foo
+.type foo,@function
+foo:
+nop
+
+.text
+.globl _start
+_start:
+callq do@plt
diff --git a/test/ELF/symbols.s b/test/ELF/symbols.s
index ccf83afdf567..a6c838cf0b74 100644
--- a/test/ELF/symbols.s
+++ b/test/ELF/symbols.s
@@ -67,7 +67,7 @@ internal:
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x12000
-// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 4
// CHECK: Symbols [
@@ -86,7 +86,9 @@ internal:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 2
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: foobar
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -95,7 +97,9 @@ internal:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 1
+// CHECK-NEXT: Other [ (0x1)
+// CHECK-NEXT: STV_INTERNAL
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: foobar
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -149,7 +153,9 @@ internal:
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 3
+// CHECK-NEXT: Other [ (0x3)
+// CHECK-NEXT: STV_PROTECTED
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: foobar
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
diff --git a/test/ELF/sysroot.s b/test/ELF/sysroot.s
index 35154be125a3..38fd8cdde402 100644
--- a/test/ELF/sysroot.s
+++ b/test/ELF/sysroot.s
@@ -14,7 +14,7 @@
// We need to be sure that there is no suitable library in the /lib directory
// RUN: not ld.lld -o %t/r %t/m.o -L/lib -l:libls.a 2>&1 \
// RUN: | FileCheck --check-prefix=NOLIB %s
-// NOLIB: Unable to find library -l:libls.a
+// NOLIB: unable to find library -l:libls.a
// Should just remove the '=' symbol if --sysroot is not specified.
// Case 1: relative path
@@ -32,5 +32,5 @@
// RUN: not ld.lld -o %t/r %r/m.o --sysroot=%t -Llib -l:libls.a
// RUN: not ld.lld -o %t/r %r/m.o --sysroot=%t -L/lib -l:libls.a
-.globl _start,_bar;
+.globl _start,_bar
_start:
diff --git a/test/ELF/tail-merge-string-align.s b/test/ELF/tail-merge-string-align.s
new file mode 100644
index 000000000000..a5d4603b6f8b
--- /dev/null
+++ b/test/ELF/tail-merge-string-align.s
@@ -0,0 +1,35 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared -O3
+// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s
+
+ .section .rodata.4a,"aMS",@progbits,1
+ .align 4
+ .asciz "abcdef"
+
+ .section .rodata.4b,"aMS",@progbits,1
+ .align 4
+ .asciz "ef"
+
+ .section .rodata.4c,"aMS",@progbits,1
+ .align 4
+ .asciz "f"
+
+
+// CHECK: Name: .rodata
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: SHF_STRINGS
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 1
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 61626364 65660000 6600 |abcdef..f.|
+// CHECK-NEXT: )
diff --git a/test/ELF/tls-archive.s b/test/ELF/tls-archive.s
new file mode 100644
index 000000000000..9a88fddffd36
--- /dev/null
+++ b/test/ELF/tls-archive.s
@@ -0,0 +1,10 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/tls-mismatch.s -o %t2
+// RUN: rm -f %t.a
+// RUN: llvm-ar cru %t.a %t2
+// RUN: ld.lld %t.a %t -o %t3
+
+.globl _start,tlsvar
+_start:
+ movq tlsvar@GOTTPOFF(%rip),%rdx
diff --git a/test/ELF/tls-dynamic-i686.s b/test/ELF/tls-dynamic-i686.s
index b2620d048864..4db6278ca21b 100644
--- a/test/ELF/tls-dynamic-i686.s
+++ b/test/ELF/tls-dynamic-i686.s
@@ -19,6 +19,14 @@ tls1:
.long 0
.size tls1, 4
+.type tls2,@object
+.globl tls2
+.hidden tls2
+.align 4
+tls2:
+ .long 0
+ .size tls2, 4
+
.section .text
.globl _start
_start:
@@ -28,13 +36,13 @@ call __tls_get_addr@plt
leal tls1@tlsgd(,%ebx,1),%eax
call __tls_get_addr@plt
-leal tls0@tlsldm(%ebx),%eax
+leal tls2@tlsldm(%ebx),%eax
call __tls_get_addr@plt
-leal tls0@dtpoff(%eax),%edx
+leal tls2@dtpoff(%eax),%edx
-leal tls1@tlsldm(%ebx),%eax
+leal tls2@tlsldm(%ebx),%eax
call __tls_get_addr@plt
-leal tls1@dtpoff(%eax),%edx
+leal tls2@dtpoff(%eax),%edx
movl %gs:0,%eax
addl tls0@gotntpoff(%ebx),%eax
@@ -59,12 +67,12 @@ addl tls1@gotntpoff(%ebx),%eax
// CHECK: Relocations [
// CHECK: Section ({{.+}}) .rel.dyn {
+// CHECK-NEXT: 0x2078 R_386_TLS_DTPMOD32 - 0x0
// CHECK-NEXT: 0x2068 R_386_TLS_DTPMOD32 tls0 0x0
// CHECK-NEXT: 0x206C R_386_TLS_DTPOFF32 tls0 0x0
+// CHECK-NEXT: 0x2080 R_386_TLS_TPOFF tls0 0x0
// CHECK-NEXT: 0x2070 R_386_TLS_DTPMOD32 tls1 0x0
// CHECK-NEXT: 0x2074 R_386_TLS_DTPOFF32 tls1 0x0
-// CHECK-NEXT: 0x2078 R_386_TLS_DTPMOD32 - 0x0
-// CHECK-NEXT: 0x2080 R_386_TLS_TPOFF tls0 0x0
// CHECK-NEXT: 0x2084 R_386_TLS_TPOFF tls1 0x0
// CHECK-NEXT: }
@@ -81,10 +89,10 @@ addl tls1@gotntpoff(%ebx),%eax
// -16 is a local module tls index offset.
// DIS-NEXT: 1018: 8d 83 f0 ff ff ff leal -16(%ebx), %eax
// DIS-NEXT: 101e: e8 4d 00 00 00 calll 77
-// DIS-NEXT: 1023: 8d 90 00 00 00 00 leal (%eax), %edx
+// DIS-NEXT: 1023: 8d 90 08 00 00 00 leal 8(%eax), %edx
// DIS-NEXT: 1029: 8d 83 f0 ff ff ff leal -16(%ebx), %eax
// DIS-NEXT: 102f: e8 3c 00 00 00 calll 60
-// DIS-NEXT: 1034: 8d 90 04 00 00 00 leal 4(%eax), %edx
+// DIS-NEXT: 1034: 8d 90 08 00 00 00 leal 8(%eax), %edx
// Initial exec model:
// DIS-NEXT: 103a: 65 a1 00 00 00 00 movl %gs:0, %eax
// DIS-NEXT: 1040: 03 83 f8 ff ff ff addl -8(%ebx), %eax
diff --git a/test/ELF/tls-dynamic.s b/test/ELF/tls-dynamic.s
index b6ae6da61bb2..b627977e3c6f 100644
--- a/test/ELF/tls-dynamic.s
+++ b/test/ELF/tls-dynamic.s
@@ -14,10 +14,13 @@
leaq c@tlsgd(%rip), %rdi
rex64
callq __tls_get_addr@PLT
- leaq c@dtpoff(%rax), %rcx
+ leaq a@dtpoff(%rax), %rcx
// Initial Exec Model Code Sequence, II
movq c@gottpoff(%rip),%rax
movq %fs:(%rax),%rax
+ movabs $a@dtpoff, %rax
+ movabs $b@dtpoff, %rax
+ movabs $a@dtpoff, %rax
.global a
.hidden a
@@ -76,6 +79,9 @@ c:
// DIS-NEXT: 102c: 00 00
// DIS-NEXT: 102e: {{.+}} leaq 4267(%rip), %rdi
// DIS-NEXT: 1035: {{.+}} callq
-// DIS-NEXT: 103b: {{.+}} leaq 8(%rax), %rcx
+// DIS-NEXT: 103b: {{.+}} leaq (%rax), %rcx
// DIS-NEXT: 1042: {{.+}} movq 4263(%rip), %rax
// DIS-NEXT: 1049: {{.+}} movq %fs:(%rax), %rax
+// DIS-NEXT: 104d: {{.+}} movabsq $0, %rax
+// DIS-NEXT: 1057: {{.+}} movabsq $4, %rax
+// DIS-NEXT: 1061: {{.+}} movabsq $0, %rax
diff --git a/test/ELF/tls-got-entry.s b/test/ELF/tls-got-entry.s
new file mode 100644
index 000000000000..c7b96697ab30
--- /dev/null
+++ b/test/ELF/tls-got-entry.s
@@ -0,0 +1,25 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-got-entry.s -o %tso.o
+// RUN: ld.lld -shared %tso.o -o %t.so
+// RUN: ld.lld %t.o %t.so -o %t1
+// RUN: llvm-readobj -r %t1 | FileCheck %s
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: R_X86_64_TPOFF64 tlsshared0 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+.globl _start
+_start:
+ .byte 0x66
+ leaq tlsshared0@tlsgd(%rip),%rdi
+ .word 0x6666
+ rex64
+ call __tls_get_addr@plt
+ .byte 0x66
+ leaq tlsshared0@tlsgd(%rip),%rdi
+ .word 0x6666
+ rex64
+ call __tls_get_addr@plt
diff --git a/test/ELF/tls-got.s b/test/ELF/tls-got.s
index aa024519a64a..f36d94e40cb1 100644
--- a/test/ELF/tls-got.s
+++ b/test/ELF/tls-got.s
@@ -24,8 +24,8 @@
// CHECK: Relocations [
// CHECK-NEXT: Section (4) .rela.dyn {
-// CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0
// CHECK-NEXT: 0x120B8 R_X86_64_TPOFF64 tls0 0x0
+// CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
diff --git a/test/ELF/tls-i686.s b/test/ELF/tls-i686.s
index 62940d6cd164..e0a1007fde16 100644
--- a/test/ELF/tls-i686.s
+++ b/test/ELF/tls-i686.s
@@ -15,7 +15,7 @@ var:
var1:
.long 1
-.text
+.section test, "awx"
.global _start
_start:
movl $var@tpoff, %edx
@@ -30,40 +30,40 @@ _start:
movl %gs:0, %ecx
leal var1@ntpoff(%ecx), %eax
-// DIS: Disassembly of section .text:
+// DIS: Disassembly of section test:
// DIS-NEXT: _start:
-// DIS-NEXT: 11000: ba 08 00 00 00 movl $8, %edx
-// DIS-NEXT: 11005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
-// DIS-NEXT: 1100c: 29 d0 subl %edx, %eax
-// DIS-NEXT: 1100e: ba 04 00 00 00 movl $4, %edx
-// DIS-NEXT: 11013: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
-// DIS-NEXT: 1101a: 29 d0 subl %edx, %eax
-// DIS-NEXT: 1101c: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
-// DIS-NEXT: 11023: 8d 81 f8 ff ff ff leal -8(%ecx), %eax
-// DIS-NEXT: 11029: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
-// DIS-NEXT: 11030: 8d 81 fc ff ff ff leal -4(%ecx), %eax
+// DIS-NEXT: 12000: ba 08 00 00 00 movl $8, %edx
+// DIS-NEXT: 12005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
+// DIS-NEXT: 1200c: 29 d0 subl %edx, %eax
+// DIS-NEXT: 1200e: ba 04 00 00 00 movl $4, %edx
+// DIS-NEXT: 12013: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
+// DIS-NEXT: 1201a: 29 d0 subl %edx, %eax
+// DIS-NEXT: 1201c: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
+// DIS-NEXT: 12023: 8d 81 f8 ff ff ff leal -8(%ecx), %eax
+// DIS-NEXT: 12029: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
+// DIS-NEXT: 12030: 8d 81 fc ff ff ff leal -4(%ecx), %eax
// RELOC: Relocations [
// RELOC-NEXT: ]
-// DISSHARED: Disassembly of section .text:
+// DISSHARED: Disassembly of section test:
// DISSHARED-NEXT: _start:
-// DISSHARED-NEXT: 1000: ba 00 00 00 00 movl $0, %edx
-// DISSHARED-NEXT: 1005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
-// DISSHARED-NEXT: 100c: 29 d0 subl %edx, %eax
-// DISSHARED-NEXT: 100e: ba 00 00 00 00 movl $0, %edx
-// DISSHARED-NEXT: 1013: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
-// DISSHARED-NEXT: 101a: 29 d0 subl %edx, %eax
-// DISSHARED-NEXT: 101c: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
-// DISSHARED-NEXT: 1023: 8d 81 00 00 00 00 leal (%ecx), %eax
-// DISSHARED-NEXT: 1029: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
-// DISSHARED-NEXT: 1030: 8d 81 00 00 00 00 leal (%ecx), %eax
+// DISSHARED-NEXT: 2000: ba 00 00 00 00 movl $0, %edx
+// DISSHARED-NEXT: 2005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
+// DISSHARED-NEXT: 200c: 29 d0 subl %edx, %eax
+// DISSHARED-NEXT: 200e: ba 00 00 00 00 movl $0, %edx
+// DISSHARED-NEXT: 2013: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
+// DISSHARED-NEXT: 201a: 29 d0 subl %edx, %eax
+// DISSHARED-NEXT: 201c: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
+// DISSHARED-NEXT: 2023: 8d 81 00 00 00 00 leal (%ecx), %eax
+// DISSHARED-NEXT: 2029: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
+// DISSHARED-NEXT: 2030: 8d 81 00 00 00 00 leal (%ecx), %eax
// RELOCSHARED: Relocations [
// RELOCSHARED-NEXT: Section (4) .rel.dyn {
-// RELOCSHARED-NEXT: 0x1001 R_386_TLS_TPOFF32 var 0x0
-// RELOCSHARED-NEXT: 0x100F R_386_TLS_TPOFF32 var1 0x0
-// RELOCSHARED-NEXT: 0x1025 R_386_TLS_TPOFF var 0x0
-// RELOCSHARED-NEXT: 0x1032 R_386_TLS_TPOFF var1 0x0
+// RELOCSHARED-NEXT: 0x2001 R_386_TLS_TPOFF32 var 0x0
+// RELOCSHARED-NEXT: 0x2025 R_386_TLS_TPOFF var 0x0
+// RELOCSHARED-NEXT: 0x200F R_386_TLS_TPOFF32 var1 0x0
+// RELOCSHARED-NEXT: 0x2032 R_386_TLS_TPOFF var1 0x0
// RELOCSHARED-NEXT: }
// RELOCSHARED-NEXT: ]
diff --git a/test/ELF/tls-in-archive.s b/test/ELF/tls-in-archive.s
new file mode 100644
index 000000000000..71f60e380f33
--- /dev/null
+++ b/test/ELF/tls-in-archive.s
@@ -0,0 +1,11 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/tls-in-archive.s -o %t1.o
+// RUN: llvm-ar cru %t.a %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
+// RUN: ld.lld %t2.o %t.a -o %tout
+
+ .globl _start
+_start:
+ movq foo@gottpoff(%rip), %rax
+ .section .tbss,"awT",@nobits
+ .weak foo
diff --git a/test/ELF/tls-initial-exec-local.s b/test/ELF/tls-initial-exec-local.s
new file mode 100644
index 000000000000..0aef3c8237b6
--- /dev/null
+++ b/test/ELF/tls-initial-exec-local.s
@@ -0,0 +1,36 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t
+// RUN: llvm-readobj -r -s %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+
+// CHECK: Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_WRITE (0x1)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2090
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x2090 R_X86_64_TPOFF64 - 0x0
+// CHECK-NEXT: 0x2098 R_X86_64_TPOFF64 - 0x4
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// 0x1007 + 4233 = 0x2090
+// 0x100e + 4234 = 0x2098
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: .text:
+// DISASM-NEXT: 1000: {{.*}} addq 4233(%rip), %rax
+// DISASM-NEXT: 1007: {{.*}} addq 4234(%rip), %rax
+
+ addq foo@GOTTPOFF(%rip), %rax
+ addq bar@GOTTPOFF(%rip), %rax
+
+ .section .tbss,"awT",@nobits
+foo:
+ .long 0
+bar:
+ .long 0
diff --git a/test/ELF/tls-offset.s b/test/ELF/tls-offset.s
new file mode 100644
index 000000000000..8f5a46d988da
--- /dev/null
+++ b/test/ELF/tls-offset.s
@@ -0,0 +1,56 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %tout
+// RUN: llvm-readobj -s %tout | FileCheck %s
+
+ .global _start
+_start:
+ retq
+
+ .section .tdata,"awT",@progbits
+ .align 4
+ .long 42
+
+ .section .tbss,"awT",@nobits
+ .align 16
+ .zero 16
+
+ .data
+ .long 1
+
+
+// Test that .tbss doesn't show up in the offset or in the address. If this
+// gets out of sync what we get a runtime is different from what the section
+// table says.
+
+// CHECK: Name: .tdata
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_TLS
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x12000
+// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: Size: 4
+
+// CHECK: Name: .tbss
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_TLS
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x12010
+// CHECK-NEXT: Offset: 0x2004
+// CHECK-NEXT: Size: 16
+
+// CHECK: Name: .data
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x12004
+// CHECK-NEXT: Offset: 0x2004
+// CHECK-NEXT: Size: 4
diff --git a/test/ELF/tls-opt-gdie.s b/test/ELF/tls-opt-gdie.s
index 3f83157086e7..6ed370e3f0b2 100644
--- a/test/ELF/tls-opt-gdie.s
+++ b/test/ELF/tls-opt-gdie.s
@@ -6,15 +6,15 @@
// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
//RELOC: Section {
-//RELOC: Index: 9
-//RELOC-NEXT: Name: .got
+//RELOC: Index:
+//RELOC: Name: .got
//RELOC-NEXT: Type: SHT_PROGBITS
//RELOC-NEXT: Flags [
//RELOC-NEXT: SHF_ALLOC
//RELOC-NEXT: SHF_WRITE
//RELOC-NEXT: ]
-//RELOC-NEXT: Address: 0x120F0
-//RELOC-NEXT: Offset: 0x20F0
+//RELOC-NEXT: Address: 0x120B0
+//RELOC-NEXT: Offset: 0x20B0
//RELOC-NEXT: Size: 16
//RELOC-NEXT: Link: 0
//RELOC-NEXT: Info: 0
@@ -23,22 +23,19 @@
//RELOC-NEXT: }
//RELOC: Relocations [
//RELOC-NEXT: Section (4) .rela.dyn {
-//RELOC-NEXT: 0x120F0 R_X86_64_TPOFF64 tlsshared0 0x0
-//RELOC-NEXT: 0x120F8 R_X86_64_TPOFF64 tlsshared1 0x0
-//RELOC-NEXT: }
-//RELOC-NEXT: Section (5) .rela.plt {
-//RELOC-NEXT: 0x13018 R_X86_64_JUMP_SLOT __tls_get_addr 0x0
+//RELOC-NEXT: 0x120B0 R_X86_64_TPOFF64 tlsshared0 0x0
+//RELOC-NEXT: 0x120B8 R_X86_64_TPOFF64 tlsshared1 0x0
//RELOC-NEXT: }
//RELOC-NEXT: ]
-//0x11009 + (4304 + 7) = 0x120F0
-//0x11019 + (4296 + 7) = 0x120F8
+//0x11009 + (4256 + 7) = 0x120B0
+//0x11019 + (4248 + 7) = 0x120B8
// DISASM: Disassembly of section .text:
// DISASM-NEXT: _start:
-// DISASM-NEXT: 11000: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
-// DISASM-NEXT: 11009: 48 03 05 e0 10 00 00 addq 4320(%rip), %rax
-// DISASM-NEXT: 11010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
-// DISASM-NEXT: 11019: 48 03 05 d8 10 00 00 addq 4312(%rip), %rax
+// DISASM-NEXT: 11000: {{.*}} movq %fs:0, %rax
+// DISASM-NEXT: 11009: {{.*}} addq 4256(%rip), %rax
+// DISASM-NEXT: 11010: {{.*}} movq %fs:0, %rax
+// DISASM-NEXT: 11019: {{.*}} addq 4248(%rip), %rax
.section .text
.globl _start
diff --git a/test/ELF/tls-opt-iele-i686-nopic.s b/test/ELF/tls-opt-iele-i686-nopic.s
index 50ade0fc76cc..b6608c16551c 100644
--- a/test/ELF/tls-opt-iele-i686-nopic.s
+++ b/test/ELF/tls-opt-iele-i686-nopic.s
@@ -4,9 +4,6 @@
// RUN: ld.lld %t.o %tso -o %t1
// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTREL %s
// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
-// RUN: ld.lld -shared %t.o %tso -o %t1
-// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTRELSHARED %s
-// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s
// GOTREL: Section {
// GOTREL: Index:
@@ -54,62 +51,6 @@
// DISASM-NEXT: 1103d: 03 0d 5c 20 01 00 addl 73820, %ecx
// DISASM-NEXT: 11043: 65 8b 01 movl %gs:(%ecx), %eax
-// GOTRELSHARED: Section {
-// GOTRELSHARED: Index: 8
-// GOTRELSHARED: Name: .got
-// GOTRELSHARED-NEXT: Type: SHT_PROGBITS
-// GOTRELSHARED-NEXT: Flags [
-// GOTRELSHARED-NEXT: SHF_ALLOC
-// GOTRELSHARED-NEXT: SHF_WRITE
-// GOTRELSHARED-NEXT: ]
-// GOTRELSHARED-NEXT: Address: 0x2050
-// GOTRELSHARED-NEXT: Offset: 0x2050
-// GOTRELSHARED-NEXT: Size: 16
-// GOTRELSHARED-NEXT: Link: 0
-// GOTRELSHARED-NEXT: Info: 0
-// GOTRELSHARED-NEXT: AddressAlignment: 4
-// GOTRELSHARED-NEXT: EntrySize: 0
-// GOTRELSHARED-NEXT: }
-// GOTRELSHARED: Relocations [
-// GOTRELSHARED-NEXT: Section ({{.*}}) .rel.dyn {
-// GOTRELSHARED-NEXT: 0x1002 R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT: 0x2050 R_386_TLS_TPOFF tlslocal0 0x0
-// GOTRELSHARED-NEXT: 0x100A R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT: 0x1013 R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT: 0x101C R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT: 0x2054 R_386_TLS_TPOFF tlslocal1 0x0
-// GOTRELSHARED-NEXT: 0x1024 R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT: 0x102D R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT: 0x1036 R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT: 0x2058 R_386_TLS_TPOFF tlsshared0 0x0
-// GOTRELSHARED-NEXT: 0x103F R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT: 0x205C R_386_TLS_TPOFF tlsshared1 0x0
-// GOTRELSHARED-NEXT: }
-// GOTRELSHARED-NEXT: ]
-
-// DISASMSHARED: Disassembly of section .text:
-// DISASMSHARED-NEXT: _start:
-// (.got)[0] = 0x2050 = 8272
-// (.got)[1] = 0x2054 = 8276
-// (.got)[2] = 0x2058 = 8280
-// (.got)[3] = 0x205C = 8284
-// DISASMSHARED-NEXT: 1000: 8b 0d 50 20 00 00 movl 8272, %ecx
-// DISASMSHARED-NEXT: 1006: 65 8b 01 movl %gs:(%ecx), %eax
-// DISASMSHARED-NEXT: 1009: a1 50 20 00 00 movl 8272, %eax
-// DISASMSHARED-NEXT: 100e: 65 8b 00 movl %gs:(%eax), %eax
-// DISASMSHARED-NEXT: 1011: 03 0d 50 20 00 00 addl 8272, %ecx
-// DISASMSHARED-NEXT: 1017: 65 8b 01 movl %gs:(%ecx), %eax
-// DISASMSHARED-NEXT: 101a: 8b 0d 54 20 00 00 movl 8276, %ecx
-// DISASMSHARED-NEXT: 1020: 65 8b 01 movl %gs:(%ecx), %eax
-// DISASMSHARED-NEXT: 1023: a1 54 20 00 00 movl 8276, %eax
-// DISASMSHARED-NEXT: 1028: 65 8b 00 movl %gs:(%eax), %eax
-// DISASMSHARED-NEXT: 102b: 03 0d 54 20 00 00 addl 8276, %ecx
-// DISASMSHARED-NEXT: 1031: 65 8b 01 movl %gs:(%ecx), %eax
-// DISASMSHARED-NEXT: 1034: 8b 0d 58 20 00 00 movl 8280, %ecx
-// DISASMSHARED-NEXT: 103a: 65 8b 01 movl %gs:(%ecx), %eax
-// DISASMSHARED-NEXT: 103d: 03 0d 5c 20 00 00 addl 8284, %ecx
-// DISASMSHARED-NEXT: 1043: 65 8b 01 movl %gs:(%ecx), %eax
-
.type tlslocal0,@object
.section .tbss,"awT",@nobits
.globl tlslocal0
diff --git a/test/ELF/tls-opt-no-plt.s b/test/ELF/tls-opt-no-plt.s
new file mode 100644
index 000000000000..53655d0934d5
--- /dev/null
+++ b/test/ELF/tls-opt-no-plt.s
@@ -0,0 +1,34 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/tls-opt-gdie.s -o %t2.o
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t.exe
+// RUN: llvm-readobj -s %t.exe | FileCheck %s
+
+// CHECK-NOT: .plt
+
+ .global _start
+_start:
+ data16
+ leaq foo@TLSGD(%rip), %rdi
+ data16
+ data16
+ rex64
+ callq __tls_get_addr@PLT
+
+ leaq bar@TLSLD(%rip), %rdi
+ callq __tls_get_addr@PLT
+ leaq bar@DTPOFF(%rax), %rax
+
+ .type bar,@object
+ .section .tdata,"awT",@progbits
+ .align 8
+bar:
+ .long 42
+
+
+ .type foo,@object
+ .section .tdata,"awT",@progbits
+ .globl foo
+ .align 8
+foo:
+ .long 42
diff --git a/test/ELF/tls-opt.s b/test/ELF/tls-opt.s
index 06577d7e1021..52468f16b09d 100644
--- a/test/ELF/tls-opt.s
+++ b/test/ELF/tls-opt.s
@@ -6,35 +6,37 @@
// NORELOC: Relocations [
// NORELOC-NEXT: ]
-// DISASM: Disassembly of section .text:
-// DISASM-NEXT: _start:
-// DISASM-NEXT: 11000: 48 c7 c0 f8 ff ff ff movq $-8, %rax
-// DISASM-NEXT: 11007: 49 c7 c7 f8 ff ff ff movq $-8, %r15
-// DISASM-NEXT: 1100e: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax
-// DISASM-NEXT: 11015: 4d 8d bf f8 ff ff ff leaq -8(%r15), %r15
-// DISASM-NEXT: 1101c: 48 81 c4 f8 ff ff ff addq $-8, %rsp
-// DISASM-NEXT: 11023: 49 81 c4 f8 ff ff ff addq $-8, %r12
-// DISASM-NEXT: 1102a: 48 c7 c0 fc ff ff ff movq $-4, %rax
-// DISASM-NEXT: 11031: 49 c7 c7 fc ff ff ff movq $-4, %r15
-// DISASM-NEXT: 11038: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax
-// DISASM-NEXT: 1103f: 4d 8d bf fc ff ff ff leaq -4(%r15), %r15
-// DISASM-NEXT: 11046: 48 81 c4 fc ff ff ff addq $-4, %rsp
-// DISASM-NEXT: 1104d: 49 81 c4 fc ff ff ff addq $-4, %r12
-// Corrupred output:
-// DISASM-NEXT: 11054: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax
-// DISASM-NEXT: 1105b: 48 d1 81 c4 f8 ff ff rolq -1852(%rcx)
-// DISASM-NEXT: 11062: ff 48 d1 decl -47(%rax)
-// DISASM-NEXT: 11065: 81 c4 f8 ff ff ff addl $4294967288, %esp
+// DISASM: _start:
+// DISASM-NEXT: 11000: 48 c7 c0 f8 ff ff ff movq $-8, %rax
+// DISASM-NEXT: 11007: 49 c7 c7 f8 ff ff ff movq $-8, %r15
+// DISASM-NEXT: 1100e: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax
+// DISASM-NEXT: 11015: 4d 8d bf f8 ff ff ff leaq -8(%r15), %r15
+// DISASM-NEXT: 1101c: 48 81 c4 f8 ff ff ff addq $-8, %rsp
+// DISASM-NEXT: 11023: 49 81 c4 f8 ff ff ff addq $-8, %r12
+// DISASM-NEXT: 1102a: 48 c7 c0 fc ff ff ff movq $-4, %rax
+// DISASM-NEXT: 11031: 49 c7 c7 fc ff ff ff movq $-4, %r15
+// DISASM-NEXT: 11038: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax
+// DISASM-NEXT: 1103f: 4d 8d bf fc ff ff ff leaq -4(%r15), %r15
+// DISASM-NEXT: 11046: 48 81 c4 fc ff ff ff addq $-4, %rsp
+// DISASM-NEXT: 1104d: 49 81 c4 fc ff ff ff addq $-4, %r12
+
// LD to LE:
-// DISASM-NEXT: 1106b: 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
-// DISASM-NEXT: 11077: 48 8d 88 f8 ff ff ff leaq -8(%rax), %rcx
-// DISASM-NEXT: 1107e: 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
-// DISASM-NEXT: 1108a: 48 8d 88 fc ff ff ff leaq -4(%rax), %rcx
+// DISASM-NEXT: 11054: 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
+// DISASM-NEXT: 11060: 48 8d 88 f8 ff ff ff leaq -8(%rax), %rcx
+// DISASM-NEXT: 11067: 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
+// DISASM-NEXT: 11073: 48 8d 88 fc ff ff ff leaq -4(%rax), %rcx
+
// GD to LE:
-// DISASM-NEXT: 11091: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
-// DISASM-NEXT: 1109a: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax
-// DISASM-NEXT: 110a1: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
-// DISASM-NEXT: 110aa: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax
+// DISASM-NEXT: 1107a: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
+// DISASM-NEXT: 11083: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax
+// DISASM-NEXT: 1108a: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
+// DISASM-NEXT: 11093: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax
+
+// LD to LE:
+// DISASM: _DTPOFF64_1:
+// DISASM-NEXT: 1109a: f8 clc
+// DISASM: _DTPOFF64_2:
+// DISASM-NEXT: 110a3: fc cld
.type tls0,@object
.section .tbss,"awT",@nobits
@@ -67,12 +69,7 @@ _start:
addq tls1@GOTTPOFF(%rip), %rsp
addq tls1@GOTTPOFF(%rip), %r12
- //Invalid input case:
- xchgq tls0@gottpoff(%rip),%rax
- shlq tls0@gottpoff
- rolq tls0@gottpoff
-
- //LD to LE:
+ // LD to LE
leaq tls0@tlsld(%rip), %rdi
callq __tls_get_addr@PLT
leaq tls0@dtpoff(%rax),%rcx
@@ -80,7 +77,7 @@ _start:
callq __tls_get_addr@PLT
leaq tls1@dtpoff(%rax),%rcx
- //GD to LE:
+ // GD to LE
.byte 0x66
leaq tls0@tlsgd(%rip),%rdi
.word 0x6666
@@ -91,3 +88,12 @@ _start:
.word 0x6666
rex64
call __tls_get_addr@plt
+
+ // LD to LE
+_DTPOFF64_1:
+ .quad tls0@DTPOFF
+ nop
+
+_DTPOFF64_2:
+ .quad tls1@DTPOFF
+ nop
diff --git a/test/ELF/tls-two-relocs.s b/test/ELF/tls-two-relocs.s
new file mode 100644
index 000000000000..7c5d6abf77f4
--- /dev/null
+++ b/test/ELF/tls-two-relocs.s
@@ -0,0 +1,30 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %tout -shared
+// RUN: llvm-readobj -r %tout | FileCheck %s
+
+ data16
+ leaq g_tls_s@TLSGD(%rip), %rdi
+ data16
+ data16
+ rex64
+ callq __tls_get_addr@PLT
+
+ data16
+ leaq g_tls_s@TLSGD(%rip), %rdi
+ data16
+ data16
+ rex64
+ callq __tls_get_addr@PLT
+
+// Check that we handle two gd relocations to the same symbol.
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section (4) .rela.dyn {
+// CHECK-NEXT: R_X86_64_DTPMOD64 g_tls_s 0x0
+// CHECK-NEXT: R_X86_64_DTPOFF64 g_tls_s 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Section (5) .rela.plt {
+// CHECK-NEXT: R_X86_64_JUMP_SLOT __tls_get_addr 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/trace-ar.s b/test/ELF/trace-ar.s
new file mode 100644
index 000000000000..1d178dc9dd37
--- /dev/null
+++ b/test/ELF/trace-ar.s
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.foo.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/trace-ar1.s -o %t.obj1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/trace-ar2.s -o %t.obj2.o
+# RUN: llvm-ar rcs %t.boo.a %t.obj1.o %t.obj2.o
+
+## Check how -t works with achieves
+# RUN: ld.lld %t.foo.o %t.boo.a -o %t.out -t 2>&1 | FileCheck %s
+# CHECK: {{.*}}.foo.o
+# CHECK-NEXT: {{.*}}.boo.a({{.*}}.obj1.o)
+# CHECK-NOT: {{.*}}.boo.a({{.*}}.obj2.o)
+
+## Test output with --start-lib
+# RUN: ld.lld %t.foo.o --start-lib %t.obj1.o %t.obj2.o -o %t.out -t 2>&1 | FileCheck --check-prefix=STARTLIB %s
+# STARTLIB: {{.*}}.foo.o
+# STARTLIB-NEXT: {{.*}}.obj1.o
+# STARTLIB-NOT: {{.*}}.obj2.o
+
+.globl _start, _used
+_start:
+ call _used
diff --git a/test/ELF/trace-symbols.s b/test/ELF/trace-symbols.s
new file mode 100644
index 000000000000..7f6bca8be216
--- /dev/null
+++ b/test/ELF/trace-symbols.s
@@ -0,0 +1,78 @@
+# Test -y symbol and -trace-symbol=symbol
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+# RUN: %p/Inputs/trace-symbols-foo-weak.s -o %t1
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+# RUN: %p/Inputs/trace-symbols-foo-strong.s -o %t2
+# RUN: ld.lld -shared %t1 -o %t1.so
+# RUN: ld.lld -shared %t2 -o %t2.so
+# RUN: llvm-ar rcs %t1.a %t1
+# RUN: llvm-ar rcs %t2.a %t2
+
+# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \
+# RUN: %t %t1 %t2 -o %t3 2>&1 | FileCheck -check-prefix=OBJECTRFOO %s
+# OBJECTRFOO: trace-symbols.s.tmp: reference to foo
+
+# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \
+# RUN: %t %t1 %t2 -o %t3 2>&1 | FileCheck -check-prefix=OBJECTDCOMMON %s
+# OBJECTDCOMMON: trace-symbols.s.tmp1: common definition of common
+
+# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \
+# RUN: %t %t1 %t2 -o %t3 2>&1 | FileCheck -check-prefix=OBJECTD1FOO %s
+# OBJECTD1FOO: trace-symbols.s.tmp: reference to foo
+# OBJECTD1FOO: trace-symbols.s.tmp1: common definition of common
+# OBJECTD1FOO: trace-symbols.s.tmp1: definition of foo
+# OBJECTD1FOO: trace-symbols.s.tmp2: definition of foo
+
+# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \
+# RUN: %t %t1 %t2 -o %t3 2>&1 | FileCheck -check-prefix=OBJECTD2FOO %s
+# RUN: ld.lld -y foo -y common --trace-symbol=hsymbol \
+# RUN: %t %t2 %t1 -o %t4 2>&1 | FileCheck -check-prefix=OBJECTD2FOO %s
+# RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 2>&1 | \
+# RUN: FileCheck -check-prefix=OBJECTD2FOO %s
+# RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 2>&1 | \
+# RUN: FileCheck -check-prefix=OBJECTD2FOO %s
+# OBJECTD2FOO: trace-symbols.s.tmp2: definition of foo
+
+# RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 2>&1 | \
+# RUN: FileCheck -check-prefix=SHLIBDCOMMON %s
+# SHLIBDCOMMON: trace-symbols.s.tmp1.so: definition of common
+
+# RUN: ld.lld -y foo -y common %t %t2.so %t1.so -o %t3 2>&1 | \
+# RUN: FileCheck -check-prefix=SHLIBD2FOO %s
+# RUN: ld.lld -y foo %t %t1.a %t2.so -o %t3 | \
+# RUN: FileCheck -check-prefix=NO-SHLIBD2FOO %s
+# SHLIBD2FOO: trace-symbols.s.tmp2.so: definition of foo
+# NO-SHLIBD2FOO-NOT: trace-symbols.s.tmp2.so: definition of foo
+
+# RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 2>&1 | \
+# RUN: FileCheck -check-prefix=ARCHIVEDCOMMON %s
+# ARCHIVEDCOMMON-NOT: trace-symbols.s.tmp1.a(trace-symbols.s.tmp1): definition of \
+# common
+
+# RUN: ld.lld -y foo %t %t1.a %t2.so -o %t3 | \
+# RUN: FileCheck -check-prefix=ARCHIVED1FOO %s
+# ARCHIVED1FOO: trace-symbols.s.tmp1.a(trace-symbols.s.tmp1): definition of foo
+
+# RUN: ld.lld -y foo %t %t1.a %t2.a -o %t3 | \
+# RUN: FileCheck -check-prefix=ARCHIVED2FOO %s
+# ARCHIVED2FOO: trace-symbols.s.tmp2.a(trace-symbols.s.tmp2): definition of foo
+
+# RUN: ld.lld -y bar %t %t1.so %t2.so -o %t3 | \
+# RUN: FileCheck -check-prefix=SHLIBDBAR %s
+# SHLIBDBAR: trace-symbols.s.tmp2.so: definition of bar
+
+# RUN: ld.lld -y foo -y bar %t %t1.so %t2.so -o %t3 | \
+# RUN: FileCheck -check-prefix=SHLIBRBAR %s
+# SHLIBRBAR-NOT: trace-symbols.s.tmp1.so: reference to bar
+
+# RUN: ld.lld -y foo -y bar %t -u bar --start-lib %t1 %t2 --end-lib -o %t3 | \
+# RUN: FileCheck -check-prefix=STARTLIB %s
+# STARTLIB: trace-symbols.s.tmp1: reference to bar
+
+.hidden hsymbol
+.globl _start
+.type _start, @function
+_start:
+call foo
diff --git a/test/ELF/trace.s b/test/ELF/trace.s
new file mode 100644
index 000000000000..4374d93da648
--- /dev/null
+++ b/test/ELF/trace.s
@@ -0,0 +1,9 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.foo.o
+
+## Check -t
+# RUN: ld.lld -shared %t.foo.o -o %t.so -t 2>&1 | FileCheck %s
+# CHECK: {{.*}}.foo.o
+
+## Check --trace alias
+# RUN: ld.lld -shared %t.foo.o -o %t.so -t 2>&1 | FileCheck %s
diff --git a/test/ELF/undef-shared.s b/test/ELF/undef-shared.s
new file mode 100644
index 000000000000..ed9103571443
--- /dev/null
+++ b/test/ELF/undef-shared.s
@@ -0,0 +1,14 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s
+
+# CHECK: undefined symbol: hidden in {{.*}}
+.global hidden
+.hidden hidden
+
+# CHECK: undefined symbol: internal in {{.*}}
+.global internal
+.internal internal
+
+# CHECK: undefined symbol: protected in {{.*}}
+.global protected
+.protected protected
diff --git a/test/ELF/undef-version-script.s b/test/ELF/undef-version-script.s
new file mode 100644
index 000000000000..9f0a5a49e72e
--- /dev/null
+++ b/test/ELF/undef-version-script.s
@@ -0,0 +1,40 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "{ local: *; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+# This does not match gold's behavior because gold does not create undefined
+# symbols in dynsym without an appropriate (e.g. PLT) relocation in the input.
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @ (0)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local (0x0)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: bar@ (1)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Weak (0x2)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo@ (5)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+.global foo
+.weak bar
diff --git a/test/ELF/undef-with-plt-addr-i686.s b/test/ELF/undef-with-plt-addr-i686.s
new file mode 100644
index 000000000000..755f0daced2e
--- /dev/null
+++ b/test/ELF/undef-with-plt-addr-i686.s
@@ -0,0 +1,23 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t3
+// RUN: llvm-readobj -t -s %t3 | FileCheck %s
+
+.globl _start
+_start:
+mov $set_data, %eax
+
+// Test that set_data has an address in the .plt
+
+// CHECK: Name: .plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x11010
+
+// CHECK: Name: set_data
+// CHECK-NEXT: Value: 0x11020
diff --git a/test/ELF/undef-with-plt-addr.s b/test/ELF/undef-with-plt-addr.s
new file mode 100644
index 000000000000..792d85f3da61
--- /dev/null
+++ b/test/ELF/undef-with-plt-addr.s
@@ -0,0 +1,45 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t3
+// RUN: llvm-readobj -t -s -r %t3 | FileCheck %s
+
+.globl _start
+_start:
+movabsq $set_data, %rax
+
+.data
+.quad foo
+// Test that set_data has an address in the .plt, but foo is not
+
+// CHECK: Name: .plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x11010
+
+// CHECK: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x13000 R_X86_64_64 foo 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: 0x13020 R_X86_64_JUMP_SLOT set_data 0x0
+// CHECK-NEXT: }
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Function
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+
+// CHECK: Name: set_data
+// CHECK-NEXT: Value: 0x11020
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Function
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
diff --git a/test/ELF/undef.s b/test/ELF/undef.s
index 374c9c884d5f..c8211c73866f 100644
--- a/test/ELF/undef.s
+++ b/test/ELF/undef.s
@@ -1,8 +1,15 @@
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-# RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s
-# CHECK: undefined symbol: foo in {{.*}}
# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/undef.s -o %t2.o
+# RUN: llvm-ar rc %t2.a %t2.o
+# RUN: not ld.lld %t.o %t2.a -o %t.exe 2>&1 | FileCheck %s
+# RUN: not ld.lld -pie %t.o %t2.a -o %t.exe 2>&1 | FileCheck %s
+# CHECK: undefined symbol: bar in {{.*}}
+# CHECK: undefined symbol: foo in {{.*}}
+# CHECK: undefined symbol: zed2 in {{.*}}2.a({{.*}}.o)
- .globl _start;
+ .globl _start
_start:
call foo
+ call bar
+ call zed1
diff --git a/test/ELF/undefined-opt.s b/test/ELF/undefined-opt.s
index 97ab5a63490a..ddd34f49b748 100644
--- a/test/ELF/undefined-opt.s
+++ b/test/ELF/undefined-opt.s
@@ -51,5 +51,16 @@
# UNK-UNDEFINED-SO-NOT: Name: unknown
# UNK-UNDEFINED-SO: ]
-.globl _start;
+# Added undefined symbols should appear in the dynamic table if necessary.
+# RUN: ld.lld -shared -o %t5 %t.o -u export
+# RUN: llvm-readobj --dyn-symbols %t5 | \
+# RUN: FileCheck --check-prefix=EXPORT-SO %s
+# EXPORT-SO: DynamicSymbols [
+# EXPORT-SO: Name: export
+# EXPORT-SO: ]
+
+.globl _start
_start:
+
+.globl export
+export:
diff --git a/test/ELF/unresolved-symbols.s b/test/ELF/unresolved-symbols.s
new file mode 100644
index 000000000000..2fa59cb0ffd7
--- /dev/null
+++ b/test/ELF/unresolved-symbols.s
@@ -0,0 +1,63 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/unresolved-symbols.s -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t.so
+
+## Check that %t2.o contains undefined symbol undef.
+# RUN: not ld.lld %t1.o %t2.o -o %t 2>&1 | \
+# RUN: FileCheck -check-prefix=UNDCHECK %s
+# UNDCHECK: undefined symbol: undef in {{.*}}2.o
+
+## Error out if unknown option value was set.
+# RUN: not ld.lld %t1.o %t2.o -o %t --unresolved-symbols=xxx 2>&1 | \
+# RUN: FileCheck -check-prefix=ERR1 %s
+# ERR1: unknown --unresolved-symbols value: xxx
+
+## Ignore all should not produce error for symbols from object except
+## case when --no-undefined specified.
+# RUN: ld.lld %t2.o -o %t1_1 --unresolved-symbols=ignore-all
+# RUN: llvm-readobj %t1_1 > /dev/null 2>&1
+# RUN: not ld.lld %t2.o -o %t1_2 --unresolved-symbols=ignore-all --no-undefined 2>&1 | \
+# RUN: FileCheck -check-prefix=ERRUND %s
+# ERRUND: undefined symbol: undef
+## Also ignore all should not produce error for symbols from DSOs.
+# RUN: ld.lld %t1.o %t.so -o %t1_3 --unresolved-symbols=ignore-all
+# RUN: llvm-readobj %t1_3 > /dev/null 2>&1
+
+## Ignoring undefines in objects should not produce error for symbol from object.
+# RUN: ld.lld %t1.o %t2.o -o %t2 --unresolved-symbols=ignore-in-object-files
+# RUN: llvm-readobj %t2 > /dev/null 2>&1
+## And still should not should produce for undefines from DSOs.
+# RUN: ld.lld %t1.o %t.so -o %t2_1 --unresolved-symbols=ignore-in-object-files
+# RUN: llvm-readobj %t2 > /dev/null 2>&1
+
+## Ignoring undefines in shared should produce error for symbol from object.
+# RUN: not ld.lld %t2.o -o %t3 --unresolved-symbols=ignore-in-shared-libs 2>&1 | \
+# RUN: FileCheck -check-prefix=ERRUND %s
+## And should not produce errors for symbols from DSO.
+# RUN: ld.lld %t1.o %t.so -o %t3_1 --unresolved-symbols=ignore-in-shared-libs
+# RUN: llvm-readobj %t3_1 > /dev/null 2>&1
+
+## Ignoring undefines in shared libs should not produce error for symbol from object
+## if we are linking DSO.
+# RUN: ld.lld -shared %t1.o -o %t4 --unresolved-symbols=ignore-in-shared-libs
+# RUN: llvm-readobj %t4 > /dev/null 2>&1
+
+## Do not report undefines if linking relocatable.
+# RUN: ld.lld -r %t1.o %t2.o -o %t5 --unresolved-symbols=report-all
+# RUN: llvm-readobj %t5 > /dev/null 2>&1
+
+## report-all is the default one. Check that we do not report
+## undefines from DSO and do report undefines from object. With
+## report-all specified and without.
+# RUN: ld.lld -shared %t1.o %t.so -o %t6 --unresolved-symbols=report-all
+# RUN: llvm-readobj %t6 > /dev/null 2>&1
+# RUN: ld.lld -shared %t1.o %t.so -o %t6_1
+# RUN: llvm-readobj %t6_1 > /dev/null 2>&1
+# RUN: not ld.lld %t2.o -o %t7 --unresolved-symbols=report-all 2>&1 | \
+# RUN: FileCheck -check-prefix=ERRUND %s
+# RUN: not ld.lld %t2.o -o %t7_1 2>&1 | \
+# RUN: FileCheck -check-prefix=ERRUND %s
+
+.globl _start
+_start:
diff --git a/test/ELF/user_def_init_array_start.s b/test/ELF/user_def_init_array_start.s
new file mode 100644
index 000000000000..6c33166d1d4e
--- /dev/null
+++ b/test/ELF/user_def_init_array_start.s
@@ -0,0 +1,10 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t2.so -shared
+// Allow user defined __init_array_start. This is used by musl because of the
+// the bfd linker not handling these properly. We always create them as
+// hidden, musl should not have problems with lld.
+
+ .hidden __init_array_start
+ .globl __init_array_start
+__init_array_start:
+ .zero 8
diff --git a/test/ELF/valid-cie-length-dw64.s b/test/ELF/valid-cie-length-dw64.s
deleted file mode 100644
index 65d6952448a2..000000000000
--- a/test/ELF/valid-cie-length-dw64.s
+++ /dev/null
@@ -1,13 +0,0 @@
-// REQUIRES: x86
-
-// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
-// RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s
-
- .section .eh_frame
- .long 0xFFFFFFFF
- .quad 1
- nop
-
-// CHECK-NOT: Truncated CIE/FDE length
-// CHECK-NOT: CIE/FIE size is too large
-// CHECK-NOT: CIE/FIE ends past the end of the section
diff --git a/test/ELF/verdef-defaultver.s b/test/ELF/verdef-defaultver.s
new file mode 100644
index 000000000000..4d847344f996
--- /dev/null
+++ b/test/ELF/verdef-defaultver.s
@@ -0,0 +1,205 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/verdef-defaultver.s -o %t1
+# RUN: echo "LIBSAMPLE_1.0{ \
+# RUN: global: a; \
+# RUN: local: *; }; \
+# RUN: LIBSAMPLE_2.0{ \
+# RUN: global: b; c; \
+# RUN: }LIBSAMPLE_1.0;" > %t.script
+# RUN: ld.lld -shared -soname shared %t1 --version-script %t.script -o %t.so
+# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s
+
+# DSO: DynamicSymbols [
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: @
+# DSO-NEXT: Value: 0x0
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Local
+# DSO-NEXT: Type: None
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: Undefined
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: a@@LIBSAMPLE_1.0
+# DSO-NEXT: Value: 0x1000
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: b@@LIBSAMPLE_2.0
+# DSO-NEXT: Value: 0x1002
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: b@LIBSAMPLE_1.0
+# DSO-NEXT: Value: 0x1001
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: c@@LIBSAMPLE_2.0
+# DSO-NEXT: Value: 0x1003
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: ]
+# DSO-NEXT: Version symbols {
+# DSO-NEXT: Section Name: .gnu.version
+# DSO-NEXT: Address: 0x240
+# DSO-NEXT: Offset: 0x240
+# DSO-NEXT: Link: 1
+# DSO-NEXT: Symbols [
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 0
+# DSO-NEXT: Name: @
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 2
+# DSO-NEXT: Name: a@@LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 3
+# DSO-NEXT: Name: b@@LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 2
+# DSO-NEXT: Name: b@LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 3
+# DSO-NEXT: Name: c@@LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: ]
+# DSO-NEXT: }
+# DSO-NEXT: SHT_GNU_verdef {
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: Base
+# DSO-NEXT: Index: 1
+# DSO-NEXT: Hash: 127830196
+# DSO-NEXT: Name: shared
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 2
+# DSO-NEXT: Hash: 98457184
+# DSO-NEXT: Name: LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 3
+# DSO-NEXT: Hash: 98456416
+# DSO-NEXT: Name: LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: }
+
+## Check that we can link against DSO produced.
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
+# RUN: ld.lld %t2 %t.so -o %t3
+# RUN: llvm-readobj -V -dyn-symbols %t3 | FileCheck --check-prefix=EXE %s
+
+# EXE: DynamicSymbols [
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: @
+# EXE-NEXT: Value: 0x0
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Local
+# EXE-NEXT: Type: None
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: a@LIBSAMPLE_1.0
+# EXE-NEXT: Value: 0x11020
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Global
+# EXE-NEXT: Type: Function
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: b@LIBSAMPLE_2.0
+# EXE-NEXT: Value: 0x11030
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Global
+# EXE-NEXT: Type: Function
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: c@LIBSAMPLE_2.0
+# EXE-NEXT: Value: 0x11040
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Global
+# EXE-NEXT: Type: Function
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined
+# EXE-NEXT: }
+# EXE-NEXT: ]
+# EXE-NEXT: Version symbols {
+# EXE-NEXT: Section Name: .gnu.version
+# EXE-NEXT: Address: 0x10228
+# EXE-NEXT: Offset: 0x228
+# EXE-NEXT: Link: 1
+# EXE-NEXT: Symbols [
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Version: 0
+# EXE-NEXT: Name: @
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Version: 2
+# EXE-NEXT: Name: a@LIBSAMPLE_1.0
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Version: 3
+# EXE-NEXT: Name: b@LIBSAMPLE_2.0
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Version: 3
+# EXE-NEXT: Name: c@LIBSAMPLE_2.0
+# EXE-NEXT: }
+# EXE-NEXT: ]
+# EXE-NEXT: }
+# EXE-NEXT: SHT_GNU_verdef {
+# EXE-NEXT: }
+# EXE-NEXT: SHT_GNU_verneed {
+# EXE-NEXT: Dependency {
+# EXE-NEXT: Version: 1
+# EXE-NEXT: Count: 2
+# EXE-NEXT: FileName: shared
+# EXE-NEXT: Entry {
+# EXE-NEXT: Hash: 98457184
+# EXE-NEXT: Flags: 0x0
+# EXE-NEXT: Index: 2
+# EXE-NEXT: Name: LIBSAMPLE_1.0
+# EXE-NEXT: }
+# EXE-NEXT: Entry {
+# EXE-NEXT: Hash: 98456416
+# EXE-NEXT: Flags: 0x0
+# EXE-NEXT: Index: 3
+# EXE-NEXT: Name: LIBSAMPLE_2.0
+# EXE-NEXT: }
+# EXE-NEXT: }
+# EXE-NEXT: }
+
+.globl _start
+_start:
+ callq a
+ callq b
+ callq c
diff --git a/test/ELF/verdef-dependency.s b/test/ELF/verdef-dependency.s
new file mode 100644
index 000000000000..92627ddc5c0f
--- /dev/null
+++ b/test/ELF/verdef-dependency.s
@@ -0,0 +1,44 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "LIBSAMPLE_1.0{ \
+# RUN: global: a; \
+# RUN: local: *; }; \
+# RUN: LIBSAMPLE_2.0{ \
+# RUN: global: b; \
+# RUN: local: *; }LIBSAMPLE_1.0; \
+# RUN: LIBSAMPLE_3.0{ \
+# RUN: global: c; \
+# RUN: }LIBSAMPLE_2.0;" > %t.script
+# RUN: ld.lld --version-script %t.script -shared -soname shared %t.o -o %t.so
+# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s
+
+# DSO: SHT_GNU_verdef {
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: Base
+# DSO-NEXT: Index: 1
+# DSO-NEXT: Hash: 127830196
+# DSO-NEXT: Name: shared
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 2
+# DSO-NEXT: Hash: 98457184
+# DSO-NEXT: Name: LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 3
+# DSO-NEXT: Hash: 98456416
+# DSO-NEXT: Name: LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 4
+# DSO-NEXT: Hash: 98456672
+# DSO-NEXT: Name: LIBSAMPLE_3.0
+# DSO-NEXT: }
+# DSO-NEXT: }
diff --git a/test/ELF/verdef.s b/test/ELF/verdef.s
new file mode 100644
index 000000000000..9463de0c0a0c
--- /dev/null
+++ b/test/ELF/verdef.s
@@ -0,0 +1,117 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "LIBSAMPLE_1.0{ \
+# RUN: global: a; \
+# RUN: local: *; }; \
+# RUN: LIBSAMPLE_2.0{ \
+# RUN: global: b; \
+# RUN: local: *; }; \
+# RUN: LIBSAMPLE_3.0{ \
+# RUN: global: c; \
+# RUN: local: *; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared -soname shared %t.o -o %t.so
+# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s
+
+# DSO: Version symbols {
+# DSO-NEXT: Section Name: .gnu.version
+# DSO-NEXT: Address: 0x228
+# DSO-NEXT: Offset: 0x228
+# DSO-NEXT: Link: 1
+# DSO-NEXT: Symbols [
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 0
+# DSO-NEXT: Name: @
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 2
+# DSO-NEXT: Name: a@@LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 3
+# DSO-NEXT: Name: b@@LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 4
+# DSO-NEXT: Name: c@@LIBSAMPLE_3.0
+# DSO-NEXT: }
+# DSO-NEXT: ]
+# DSO-NEXT: }
+# DSO-NEXT: SHT_GNU_verdef {
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: Base
+# DSO-NEXT: Index: 1
+# DSO-NEXT: Hash: 127830196
+# DSO-NEXT: Name: shared
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 2
+# DSO-NEXT: Hash: 98457184
+# DSO-NEXT: Name: LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 3
+# DSO-NEXT: Hash: 98456416
+# DSO-NEXT: Name: LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: Definition {
+# DSO-NEXT: Version: 1
+# DSO-NEXT: Flags: 0x0
+# DSO-NEXT: Index: 4
+# DSO-NEXT: Hash: 98456672
+# DSO-NEXT: Name: LIBSAMPLE_3.0
+# DSO-NEXT: }
+# DSO-NEXT: }
+# DSO-NEXT: SHT_GNU_verneed {
+# DSO-NEXT: }
+
+## Check that we can link agains DSO we produced.
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/verdef.s -o %tmain.o
+# RUN: ld.lld %tmain.o %t.so -o %tout
+# RUN: llvm-readobj -V %tout | FileCheck --check-prefix=MAIN %s
+
+# MAIN: Version symbols {
+# MAIN-NEXT: Section Name: .gnu.version
+# MAIN-NEXT: Address: 0x10228
+# MAIN-NEXT: Offset: 0x228
+# MAIN-NEXT: Link: 1
+# MAIN-NEXT: Symbols [
+# MAIN-NEXT: Symbol {
+# MAIN-NEXT: Version: 0
+# MAIN-NEXT: Name: @
+# MAIN-NEXT: }
+# MAIN-NEXT: Symbol {
+# MAIN-NEXT: Version: 2
+# MAIN-NEXT: Name: a@LIBSAMPLE_1.0
+# MAIN-NEXT: }
+# MAIN-NEXT: Symbol {
+# MAIN-NEXT: Version: 3
+# MAIN-NEXT: Name: b@LIBSAMPLE_2.0
+# MAIN-NEXT: }
+# MAIN-NEXT: Symbol {
+# MAIN-NEXT: Version: 4
+# MAIN-NEXT: Name: c@LIBSAMPLE_3.0
+# MAIN-NEXT: }
+# MAIN-NEXT: ]
+# MAIN-NEXT: }
+# MAIN-NEXT: SHT_GNU_verdef {
+# MAIN-NEXT: }
+
+.globl a
+.type a,@function
+a:
+retq
+
+.globl b
+.type b,@function
+b:
+retq
+
+.globl c
+.type c,@function
+c:
+retq
diff --git a/test/ELF/verneed-as-needed-weak.s b/test/ELF/verneed-as-needed-weak.s
new file mode 100644
index 000000000000..a8efdc42d6d4
--- /dev/null
+++ b/test/ELF/verneed-as-needed-weak.s
@@ -0,0 +1,14 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o --as-needed %S/Inputs/verneed1.so -o %t
+# RUN: llvm-readobj -V %t | FileCheck %s
+
+# CHECK: SHT_GNU_verneed {
+# CHECK-NEXT: }
+
+.weak f1
+
+.globl _start
+_start:
+.data
+.quad f1
diff --git a/test/ELF/verneed-local.s b/test/ELF/verneed-local.s
new file mode 100644
index 000000000000..a50f670ed7bd
--- /dev/null
+++ b/test/ELF/verneed-local.s
@@ -0,0 +1,8 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld %t.o %S/Inputs/verneed1.so -o %t 2>&1 | FileCheck %s
+
+# CHECK: undefined symbol: f3 in
+.globl _start
+_start:
+call f3
diff --git a/test/ELF/verneed.s b/test/ELF/verneed.s
new file mode 100644
index 000000000000..e9d7c53ba334
--- /dev/null
+++ b/test/ELF/verneed.s
@@ -0,0 +1,173 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o %S/Inputs/verneed1.so %S/Inputs/verneed2.so -o %t
+# RUN: llvm-readobj -V -sections -section-data -dyn-symbols -dynamic-table %t | FileCheck %s
+
+# CHECK: Section {
+# CHECK: Index: 1
+# CHECK-NEXT: Name: .dynsym (1)
+# CHECK-NEXT: Type: SHT_DYNSYM (0xB)
+# CHECK-NEXT: Flags [ (0x2)
+# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x101C8
+# CHECK-NEXT: Offset: 0x1C8
+# CHECK-NEXT: Size: 96
+# CHECK-NEXT: Link: 5
+# CHECK-NEXT: Info: 1
+# CHECK-NEXT: AddressAlignment: 8
+# CHECK-NEXT: EntrySize: 24
+# CHECK: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .gnu.version (9)
+# CHECK-NEXT: Type: SHT_GNU_versym (0x6FFFFFFF)
+# CHECK-NEXT: Flags [ (0x2)
+# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x10228
+# CHECK-NEXT: Offset: 0x228
+# CHECK-NEXT: Size: 8
+# CHECK-NEXT: Link: 1
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 2
+# CHECK-NEXT: EntrySize: 2
+# CHECK: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .gnu.version_r (22)
+# CHECK-NEXT: Type: SHT_GNU_verneed (0x6FFFFFFE)
+# CHECK-NEXT: Flags [ (0x2)
+# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x10230
+# CHECK-NEXT: Offset: 0x230
+# CHECK-NEXT: Size: 80
+# CHECK-NEXT: Link: 5
+# CHECK-NEXT: Info: 2
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK: Section {
+# CHECK: Index: 5
+# CHECK-NEXT: Name: .dynstr
+# CHECK-NEXT: Type: SHT_STRTAB
+# CHECK-NEXT: Flags [ (0x2)
+# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x102A8
+# CHECK-NEXT: Offset: 0x2A8
+# CHECK-NEXT: Size: 47
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 00663100 7665726E 65656431 2E736F2E |.f1.verneed1.so.|
+# CHECK-NEXT: 0010: 30007633 00663200 76320067 31007665 |0.v3.f2.v2.g1.ve|
+# CHECK-NEXT: 0020: 726E6565 64322E73 6F2E3000 763100 |rneed2.so.0.v1.|
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @ (0)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local (0x0)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: f1@v3 (1)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: f2@v2 (21)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: g1@v1 (27)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# CHECK: 0x000000006FFFFFF0 VERSYM 0x10228
+# CHECK-NEXT: 0x000000006FFFFFFE VERNEED 0x10230
+# CHECK-NEXT: 0x000000006FFFFFFF VERNEEDNUM 2
+
+# CHECK: Version symbols {
+# CHECK-NEXT: Section Name: .gnu.version
+# CHECK-NEXT: Address: 0x10228
+# CHECK-NEXT: Offset: 0x228
+# CHECK-NEXT: Link: 1
+# CHECK-NEXT: Symbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Version: 0
+# CHECK-NEXT: Name: @
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Version: 2
+# CHECK-NEXT: Name: f1@v3
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Version: 3
+# CHECK-NEXT: Name: f2@v2
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Version: 4
+# CHECK-NEXT: Name: g1@v1
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+# CHECK-NEXT: SHT_GNU_verdef {
+# CHECK-NEXT: }
+# CHECK-NEXT: SHT_GNU_verneed {
+# CHECK-NEXT: Dependency {
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Count: 2
+# CHECK-NEXT: FileName: verneed1.so.0
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Hash: 1938
+# CHECK-NEXT: Flags: 0x0
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: v2
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Hash: 1939
+# CHECK-NEXT: Flags: 0x0
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: v3
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: Dependency {
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Count: 1
+# CHECK-NEXT: FileName: verneed2.so.0
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Hash: 1937
+# CHECK-NEXT: Flags: 0x0
+# CHECK-NEXT: Index: 4
+# CHECK-NEXT: Name: v1
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+
+.globl _start
+_start:
+call f1@plt
+call f2@plt
+call g1@plt
diff --git a/test/ELF/version-script-err.s b/test/ELF/version-script-err.s
new file mode 100644
index 000000000000..15b69e98505b
--- /dev/null
+++ b/test/ELF/version-script-err.s
@@ -0,0 +1,10 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: not ld.lld -shared %t.o -o %t.so --version-script %p/Inputs/version-script-err.script 2>&1 | FileCheck %s
+// CHECK: ; expected, but got }
+
+// RUN: echo "\"" > %terr1.script
+// RUN: not ld.lld --version-script %terr1.script -shared %t.o -o %t.so 2>&1 | \
+// RUN: FileCheck -check-prefix=ERR1 %s
+// ERR1: unclosed quote
diff --git a/test/ELF/version-script-extern.s b/test/ELF/version-script-extern.s
new file mode 100644
index 000000000000..439653487bc0
--- /dev/null
+++ b/test/ELF/version-script-extern.s
@@ -0,0 +1,97 @@
+# REQUIRES: shell
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "LIBSAMPLE_1.0 { \
+# RUN: global: \
+# RUN: extern "C++" { \
+# RUN: \"foo(int)\"; \
+# RUN: \"zed(int)\"; \
+# RUN: }; \
+# RUN: }; \
+# RUN: LIBSAMPLE_2.0 { \
+# RUN: global: \
+# RUN: extern "C++" { \
+# RUN: \"bar(int)\"; \
+# RUN: }; \
+# RUN: }; " > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s
+
+# DSO: DynamicSymbols [
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: @
+# DSO-NEXT: Value: 0x0
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Local
+# DSO-NEXT: Type: None
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: Undefined
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: _Z3bari@@LIBSAMPLE_2.0
+# DSO-NEXT: Value: 0x1001
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: _Z3fooi@@LIBSAMPLE_1.0
+# DSO-NEXT: Value: 0x1000
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global
+# DSO-NEXT: Type: Function
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: _Z3zedi@@LIBSAMPLE_1.0
+# DSO-NEXT: Value: 0x1002
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global (0x1)
+# DSO-NEXT: Type: Function (0x2)
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text (0x6)
+# DSO-NEXT: }
+# DSO-NEXT: ]
+# DSO-NEXT: Version symbols {
+# DSO-NEXT: Section Name: .gnu.version
+# DSO-NEXT: Address: 0x228
+# DSO-NEXT: Offset: 0x228
+# DSO-NEXT: Link: 1
+# DSO-NEXT: Symbols [
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 0
+# DSO-NEXT: Name: @
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 3
+# DSO-NEXT: Name: _Z3bari@@LIBSAMPLE_2.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 2
+# DSO-NEXT: Name: _Z3fooi@@LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Version: 2
+# DSO-NEXT: Name: _Z3zedi@@LIBSAMPLE_1.0
+# DSO-NEXT: }
+# DSO-NEXT: ]
+# DSO-NEXT: }
+
+.text
+.globl _Z3fooi
+.type _Z3fooi,@function
+_Z3fooi:
+retq
+
+.globl _Z3bari
+.type _Z3bari,@function
+_Z3bari:
+retq
+
+.globl _Z3zedi
+.type _Z3zedi,@function
+_Z3zedi:
+retq
diff --git a/test/ELF/version-script-noundef.s b/test/ELF/version-script-noundef.s
new file mode 100644
index 000000000000..4a251d6172da
--- /dev/null
+++ b/test/ELF/version-script-noundef.s
@@ -0,0 +1,22 @@
+# REQUIRES: x86
+
+# RUN: echo "VERSION_1.0{ \
+# RUN: global: bar; \
+# RUN: };" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: not ld.lld --version-script %t.script -shared --no-undefined-version \
+# RUN: %t.o -o %t.so 2>&1 | FileCheck -check-prefix=ERR1 %s
+# ERR1: version script assignment of VERSION_1.0 to symbol bar failed: symbol not defined
+
+# RUN: echo "VERSION_1.0{ \
+# RUN: global: und; \
+# RUN: };" > %t2.script
+# RUN: not ld.lld --version-script %t2.script -shared --no-undefined-version \
+# RUN: %t.o -o %t.so 2>&1 | FileCheck -check-prefix=ERR2 %s
+# ERR2: version script assignment of VERSION_1.0 to symbol und failed: symbol not defined
+
+.text
+.globl foo
+.type foo,@function
+foo:
+callq und@PLT
diff --git a/test/ELF/version-script.s b/test/ELF/version-script.s
new file mode 100644
index 000000000000..ba9c95a96fc3
--- /dev/null
+++ b/test/ELF/version-script.s
@@ -0,0 +1,274 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
+# RUN: ld.lld -shared %t2.o -soname shared -o %t2.so
+
+# RUN: echo "{ global: foo1; foo3; local: *; };" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld --version-script %t.script -shared %t.o %t2.so -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s
+
+# RUN: echo "# comment" > %t3.script
+# RUN: echo "{ local: *; # comment" >> %t3.script
+# RUN: echo -n "}; # comment" >> %t3.script
+# RUN: ld.lld --version-script %t3.script -shared %t.o %t2.so -o %t3.so
+# RUN: llvm-readobj -dyn-symbols %t3.so | FileCheck --check-prefix=DSO2 %s
+
+# --version-script filters --dynamic-list.
+# RUN: echo "{ foo1; foo2; };" > %t.list
+# RUN: ld.lld --version-script %t.script --dynamic-list %t.list %t.o %t2.so -o %t
+# RUN: llvm-readobj -dyn-symbols %t | FileCheck --check-prefix=EXE %s
+
+# RUN: echo "VERSION_1.0{ \
+# RUN: global: foo1; \
+# RUN: local: *; }; \
+# RUN: VERSION_2.0{ \
+# RUN: global: foo3; \
+# RUN: local: *; }; " > %t4.script
+# RUN: ld.lld --version-script %t4.script -shared %t.o %t2.so -o %t4.so
+# RUN: llvm-readobj -dyn-symbols %t4.so | FileCheck --check-prefix=VERDSO %s
+
+# RUN: echo "VERSION_1.0{ \
+# RUN: global: foo1; \
+# RUN: local: *; }; \
+# RUN: { \
+# RUN: global: foo3; \
+# RUN: local: *; }; " > %t5.script
+# RUN: not ld.lld --version-script %t5.script -shared %t.o %t2.so -o %t5.so 2>&1 | \
+# RUN: FileCheck -check-prefix=ERR %s
+# ERR: anonymous version definition is used in combination with other version definitions
+
+# RUN: echo "{ \
+# RUN: global: foo1; \
+# RUN: local: *; }; \
+# RUN: VERSION_2.0 { \
+# RUN: global: foo3; \
+# RUN: local: *; }; " > %t5.script
+# RUN: not ld.lld --version-script %t5.script -shared %t.o %t2.so -o %t5.so 2>&1 | \
+# RUN: FileCheck -check-prefix=ERR %s
+
+# RUN: echo "VERSION_1.0{ \
+# RUN: global: foo1; \
+# RUN: local: *; }; \
+# RUN: VERSION_2.0 { \
+# RUN: global: foo1; \
+# RUN: local: *; }; " > %t6.script
+# RUN: ld.lld --version-script %t6.script -shared %t.o %t2.so -o %t6.so 2>&1 | \
+# RUN: FileCheck -check-prefix=WARN2 %s
+# WARN2: duplicate symbol foo1 in version script
+
+# RUN: ld.lld --version-script %t.script --dynamic-list %t.list %t.o %t2.so -o %t2
+# RUN: llvm-readobj %t2 > /dev/null
+
+# DSO: DynamicSymbols [
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: @ (0)
+# DSO-NEXT: Value: 0x0
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Local (0x0)
+# DSO-NEXT: Type: None (0x0)
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: Undefined (0x0)
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: bar@ (1)
+# DSO-NEXT: Value: 0x0
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global (0x1)
+# DSO-NEXT: Type: Function (0x2)
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: Undefined (0x0)
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: foo1@ (5)
+# DSO-NEXT: Value: 0x1000
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global (0x1)
+# DSO-NEXT: Type: None (0x0)
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: Symbol {
+# DSO-NEXT: Name: foo3@ (10)
+# DSO-NEXT: Value: 0x1007
+# DSO-NEXT: Size: 0
+# DSO-NEXT: Binding: Global (0x1)
+# DSO-NEXT: Type: None (0x0)
+# DSO-NEXT: Other: 0
+# DSO-NEXT: Section: .text
+# DSO-NEXT: }
+# DSO-NEXT: ]
+
+# DSO2: DynamicSymbols [
+# DSO2-NEXT: Symbol {
+# DSO2-NEXT: Name: @ (0)
+# DSO2-NEXT: Value: 0x0
+# DSO2-NEXT: Size: 0
+# DSO2-NEXT: Binding: Local (0x0)
+# DSO2-NEXT: Type: None (0x0)
+# DSO2-NEXT: Other: 0
+# DSO2-NEXT: Section: Undefined (0x0)
+# DSO2-NEXT: }
+# DSO2-NEXT: Symbol {
+# DSO2-NEXT: Name: bar@ (1)
+# DSO2-NEXT: Value: 0x0
+# DSO2-NEXT: Size: 0
+# DSO2-NEXT: Binding: Global (0x1)
+# DSO2-NEXT: Type: Function (0x2)
+# DSO2-NEXT: Other: 0
+# DSO2-NEXT: Section: Undefined (0x0)
+# DSO2-NEXT: }
+# DSO2-NEXT: ]
+
+# EXE: DynamicSymbols [
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: @ (0)
+# EXE-NEXT: Value: 0x0
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Local (0x0)
+# EXE-NEXT: Type: None (0x0)
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined (0x0)
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: bar@ (1)
+# EXE-NEXT: Value: 0x0
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Global (0x1)
+# EXE-NEXT: Type: Function (0x2)
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: Undefined (0x0)
+# EXE-NEXT: }
+# EXE-NEXT: Symbol {
+# EXE-NEXT: Name: foo1@ (5)
+# EXE-NEXT: Value: 0x11000
+# EXE-NEXT: Size: 0
+# EXE-NEXT: Binding: Global (0x1)
+# EXE-NEXT: Type: None (0x0)
+# EXE-NEXT: Other: 0
+# EXE-NEXT: Section: .text
+# EXE-NEXT: }
+# EXE-NEXT: ]
+
+# VERDSO: DynamicSymbols [
+# VERDSO-NEXT: Symbol {
+# VERDSO-NEXT: Name: @
+# VERDSO-NEXT: Value: 0x0
+# VERDSO-NEXT: Size: 0
+# VERDSO-NEXT: Binding: Local
+# VERDSO-NEXT: Type: None
+# VERDSO-NEXT: Other: 0
+# VERDSO-NEXT: Section: Undefined
+# VERDSO-NEXT: }
+# VERDSO-NEXT: Symbol {
+# VERDSO-NEXT: Name: bar@
+# VERDSO-NEXT: Value: 0x0
+# VERDSO-NEXT: Size: 0
+# VERDSO-NEXT: Binding: Global
+# VERDSO-NEXT: Type: Function
+# VERDSO-NEXT: Other: 0
+# VERDSO-NEXT: Section: Undefined
+# VERDSO-NEXT: }
+# VERDSO-NEXT: Symbol {
+# VERDSO-NEXT: Name: foo1@@VERSION_1.0
+# VERDSO-NEXT: Value: 0x1000
+# VERDSO-NEXT: Size: 0
+# VERDSO-NEXT: Binding: Global
+# VERDSO-NEXT: Type: None
+# VERDSO-NEXT: Other: 0
+# VERDSO-NEXT: Section: .text
+# VERDSO-NEXT: }
+# VERDSO-NEXT: Symbol {
+# VERDSO-NEXT: Name: foo3@@VERSION_2.0
+# VERDSO-NEXT: Value: 0x1007
+# VERDSO-NEXT: Size: 0
+# VERDSO-NEXT: Binding: Global
+# VERDSO-NEXT: Type: None
+# VERDSO-NEXT: Other: 0
+# VERDSO-NEXT: Section: .text
+# VERDSO-NEXT: }
+# VERDSO-NEXT: ]
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared %t.o %t2.so -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s
+
+# RUN: echo "{ global: foo1; foo3; };" > %t2.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld --version-script %t2.script -shared %t.o %t2.so -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s
+
+# ALL: DynamicSymbols [
+# ALL-NEXT: Symbol {
+# ALL-NEXT: Name: @
+# ALL-NEXT: Value: 0x0
+# ALL-NEXT: Size: 0
+# ALL-NEXT: Binding: Local
+# ALL-NEXT: Type: None
+# ALL-NEXT: Other: 0
+# ALL-NEXT: Section: Undefined
+# ALL-NEXT: }
+# ALL-NEXT: Symbol {
+# ALL-NEXT: Name: _start@
+# ALL-NEXT: Value:
+# ALL-NEXT: Size: 0
+# ALL-NEXT: Binding: Global
+# ALL-NEXT: Type: None
+# ALL-NEXT: Other: 0
+# ALL-NEXT: Section: .text
+# ALL-NEXT: }
+# ALL-NEXT: Symbol {
+# ALL-NEXT: Name: bar@
+# ALL-NEXT: Value:
+# ALL-NEXT: Size: 0
+# ALL-NEXT: Binding: Global
+# ALL-NEXT: Type: Function
+# ALL-NEXT: Other: 0
+# ALL-NEXT: Section: Undefined
+# ALL-NEXT: }
+# ALL-NEXT: Symbol {
+# ALL-NEXT: Name: foo1@
+# ALL-NEXT: Value:
+# ALL-NEXT: Size: 0
+# ALL-NEXT: Binding: Global
+# ALL-NEXT: Type: None
+# ALL-NEXT: Other: 0
+# ALL-NEXT: Section: .text
+# ALL-NEXT: }
+# ALL-NEXT: Symbol {
+# ALL-NEXT: Name: foo2@
+# ALL-NEXT: Value:
+# ALL-NEXT: Size: 0
+# ALL-NEXT: Binding: Global
+# ALL-NEXT: Type: None
+# ALL-NEXT: Other: 0
+# ALL-NEXT: Section: .text
+# ALL-NEXT: }
+# ALL-NEXT: Symbol {
+# ALL-NEXT: Name: foo3@
+# ALL-NEXT: Value:
+# ALL-NEXT: Size: 0
+# ALL-NEXT: Binding: Global
+# ALL-NEXT: Type: None
+# ALL-NEXT: Other: 0
+# ALL-NEXT: Section: .text
+# ALL-NEXT: }
+# ALL-NEXT: ]
+
+.globl foo1
+foo1:
+ call bar@PLT
+ ret
+
+.globl foo2
+foo2:
+ ret
+
+.globl foo3
+foo3:
+ call foo2@PLT
+ ret
+
+.globl _start
+_start:
+ ret
diff --git a/test/ELF/version-undef-sym.s b/test/ELF/version-undef-sym.s
new file mode 100644
index 000000000000..20e92e61f647
--- /dev/null
+++ b/test/ELF/version-undef-sym.s
@@ -0,0 +1,42 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-readobj --dyn-symbols %p/Inputs/version-undef-sym.so | FileCheck %s
+
+
+// Inputs/version-undef-sym.so consists of the assembly file
+//
+// .global bar
+// bar:
+// .weak abc1
+// .weak abc2
+// .weak abc3
+// .weak abc4
+// .weak abc5
+//
+// linked into a shared library with the version script
+//
+// VER_1 {
+// global:
+// bar;
+// };
+//
+// Assuming we can reproduce the desired property (a few undefined symbols
+// before bar) we should create it with lld itself once it supports that.
+
+
+// Show that the input .so has undefined symbols before bar. That is what would
+// get our version parsing out of sync.
+
+// CHECK: Section: Undefined
+// CHECK: Section: Undefined
+// CHECK: Section: Undefined
+// CHECK: Section: Undefined
+// CHECK: Section: Undefined
+// CHECK: Name: bar
+
+// But now we can successfully find bar.
+// RUN: ld.lld %t.o %p/Inputs/version-undef-sym.so -o %t.exe
+
+ .global _start
+_start:
+ call bar@plt
diff --git a/test/ELF/version-use.s b/test/ELF/version-use.s
new file mode 100644
index 000000000000..7ef12bc04536
--- /dev/null
+++ b/test/ELF/version-use.s
@@ -0,0 +1,9 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o %p/Inputs/version-use.so -o %t.so -shared -z defs
+// RUN: llvm-readobj -s %t.so | FileCheck %s
+
+
+ call bar@PLT
+
+// CHECK-NOT: SHT_GNU_versym
diff --git a/test/ELF/version-wildcard.test b/test/ELF/version-wildcard.test
new file mode 100644
index 000000000000..80cb9cadf159
--- /dev/null
+++ b/test/ELF/version-wildcard.test
@@ -0,0 +1,114 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "VERSION_1.0{ \
+# RUN: global: foo*; \
+# RUN: local: *; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo1@@VERSION_1.0
+# CHECK-NEXT: Value: 0x1000
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo2@@VERSION_1.0
+# CHECK-NEXT: Value: 0x1001
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo3@@VERSION_1.0
+# CHECK-NEXT: Value: 0x1007
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "VERSION_1.0{ \
+# RUN: global: foo2; \
+# RUN: local: *; }; \
+# RUN: VERSION_2.0{ \
+# RUN: global: foo*; \
+# RUN: }; " > %t2.script
+# RUN: ld.lld --version-script %t2.script -shared %t.o -o %t2.so
+# RUN: llvm-readobj -dyn-symbols %t2.so | FileCheck --check-prefix=MIX %s
+
+# MIX: DynamicSymbols [
+# MIX-NEXT: Symbol {
+# MIX-NEXT: Name: @
+# MIX-NEXT: Value: 0x0
+# MIX-NEXT: Size: 0
+# MIX-NEXT: Binding: Local
+# MIX-NEXT: Type: None
+# MIX-NEXT: Other: 0
+# MIX-NEXT: Section: Undefined
+# MIX-NEXT: }
+# MIX-NEXT: Symbol {
+# MIX-NEXT: Name: foo1@@VERSION_2.0
+# MIX-NEXT: Value: 0x1000
+# MIX-NEXT: Size: 0
+# MIX-NEXT: Binding: Global
+# MIX-NEXT: Type: None
+# MIX-NEXT: Other: 0
+# MIX-NEXT: Section: .text
+# MIX-NEXT: }
+# MIX-NEXT: Symbol {
+# MIX-NEXT: Name: foo2@@VERSION_1.0
+# MIX-NEXT: Value: 0x1001
+# MIX-NEXT: Size: 0
+# MIX-NEXT: Binding: Global
+# MIX-NEXT: Type: None
+# MIX-NEXT: Other: 0
+# MIX-NEXT: Section: .text
+# MIX-NEXT: }
+# MIX-NEXT: Symbol {
+# MIX-NEXT: Name: foo3@@VERSION_2.0
+# MIX-NEXT: Value: 0x1007
+# MIX-NEXT: Size: 0
+# MIX-NEXT: Binding: Global
+# MIX-NEXT: Type: None
+# MIX-NEXT: Other: 0
+# MIX-NEXT: Section: .text
+# MIX-NEXT: }
+# MIX-NEXT: ]
+
+.globl foo1
+foo1:
+ ret
+
+.globl foo2
+foo2:
+ call foo1@PLT
+ ret
+
+.globl foo3
+foo3:
+ call foo2@PLT
+ ret
+
+.globl _start
+_start:
+ ret
diff --git a/test/ELF/visibility.s b/test/ELF/visibility.s
index d76ed0793eb1..2043894d3d3d 100644
--- a/test/ELF/visibility.s
+++ b/test/ELF/visibility.s
@@ -20,7 +20,9 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 2
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -29,7 +31,9 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 1
+// CHECK-NEXT: Other [ (0x1)
+// CHECK-NEXT: STV_INTERNAL
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
@@ -38,10 +42,23 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 2
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _DYNAMIC
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .dynamic
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: default
// CHECK-NEXT: Value:
// CHECK-NEXT: Size: 0
@@ -56,7 +73,9 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 3
+// CHECK-NEXT: Other [ (0x3)
+// CHECK-NEXT: STV_PROTECTED
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: ]
@@ -86,7 +105,9 @@
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 3
+// CHECK-NEXT: Other [ (0x3)
+// CHECK-NEXT: STV_PROTECTED
+// CHECK-NEXT: ]
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: ]
diff --git a/test/ELF/warn-common.s b/test/ELF/warn-common.s
new file mode 100644
index 000000000000..783a9ab77b56
--- /dev/null
+++ b/test/ELF/warn-common.s
@@ -0,0 +1,25 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/warn-common.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/warn-common2.s -o %t3.o
+
+## Report multiple commons if warn-common is specified
+# RUN: ld.lld --warn-common %t1.o %t2.o -o %t.out 2>&1 | FileCheck %s --check-prefix=WARN
+# WARN: multiple common of arr
+
+## no-warn-common is ignored
+# RUN: ld.lld --no-warn-common %t1.o %t2.o -o %t.out
+# RUN: llvm-readobj %t.out > /dev/null
+
+## Report if common is overridden
+# RUN: ld.lld --warn-common %t1.o %t3.o -o %t.out 2>&1 | FileCheck %s --check-prefix=OVER
+# OVER: common arr is overridden
+
+## Report if common is overridden, but in different order
+# RUN: ld.lld --warn-common %t3.o %t1.o -o %t.out 2>&1 | FileCheck %s --check-prefix=OVER
+
+.globl _start
+_start:
+
+.type arr,@object
+.comm arr,4,4
diff --git a/test/ELF/weak-undef-hidden.s b/test/ELF/weak-undef-hidden.s
new file mode 100644
index 000000000000..70b951bf0596
--- /dev/null
+++ b/test/ELF/weak-undef-hidden.s
@@ -0,0 +1,29 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s
+
+.data
+.weak g
+.hidden g
+.quad g
+
+// CHECK: Name: .data
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000000 00000000
+// CHECK-NEXT: )
+
+// CHECK: Relocations [
+// CHECK-NEXT: ]
diff --git a/test/ELF/weak-undef-shared.s b/test/ELF/weak-undef-shared.s
new file mode 100644
index 000000000000..862a08632e26
--- /dev/null
+++ b/test/ELF/weak-undef-shared.s
@@ -0,0 +1,19 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: llvm-mc %p/Inputs/shared.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t.exe
+// RUN: llvm-readobj -t %t.exe | FileCheck %s
+
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x11020
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Function
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+
+.global _start
+_start:
+ .weak bar
+ .quad bar
diff --git a/test/ELF/weak-undef.s b/test/ELF/weak-undef.s
new file mode 100644
index 000000000000..02555535927e
--- /dev/null
+++ b/test/ELF/weak-undef.s
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t -pie
+# RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @ (0)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local (0x0)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+.weak foo
+
+.globl _start
+_start:
diff --git a/test/ELF/whole-archive.s b/test/ELF/whole-archive.s
index 0a6b30fd171e..c65f116965f7 100644
--- a/test/ELF/whole-archive.s
+++ b/test/ELF/whole-archive.s
@@ -30,5 +30,11 @@
// RUN: ld.lld -o %t3 %t.o --whole-archive %t.a --no-whole-archive
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=ADDED %s
-.globl _start;
+// --whole-archive should also work with thin archives
+// RUN: rm -f %tthin.a
+// RUN: llvm-ar --format=gnu rcsT %tthin.a %ta.o
+// RUN: ld.lld -o %t3 %t.o --whole-archive %tthin.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=ADDED %s
+
+.globl _start
_start:
diff --git a/test/ELF/wildcards.s b/test/ELF/wildcards.s
new file mode 100644
index 000000000000..2fe0f881bf46
--- /dev/null
+++ b/test/ELF/wildcards.s
@@ -0,0 +1,80 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## Default case: abc and abx included in text.
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.abc .abx) } }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: llvm-objdump -section-headers %t.out | \
+# RUN: FileCheck -check-prefix=SEC-DEFAULT %s
+# SEC-DEFAULT: Sections:
+# SEC-DEFAULT-NEXT: Idx Name Size Address Type
+# SEC-DEFAULT-NEXT: 0 00000000 0000000000000000
+# SEC-DEFAULT-NEXT: 1 .text 00000008 0000000000000120 TEXT DATA
+# SEC-DEFAULT-NEXT: 2 .abcd 00000004 0000000000000128 TEXT DATA
+# SEC-DEFAULT-NEXT: 3 .ad 00000004 000000000000012c TEXT DATA
+# SEC-DEFAULT-NEXT: 4 .ag 00000004 0000000000000130 TEXT DATA
+# SEC-DEFAULT-NEXT: 5 .symtab 00000030 0000000000000000
+# SEC-DEFAULT-NEXT: 6 .shstrtab 0000002f 0000000000000000
+# SEC-DEFAULT-NEXT: 7 .strtab 00000008 0000000000000000
+
+## Now replace the symbol with '?' and check that results are the same.
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.abc .ab?) } }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: llvm-objdump -section-headers %t.out | \
+# RUN: FileCheck -check-prefix=SEC-DEFAULT %s
+
+## Now see how replacing '?' with '*' will consume whole abcd.
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.abc .ab*) } }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: llvm-objdump -section-headers %t.out | \
+# RUN: FileCheck -check-prefix=SEC-ALL %s
+# SEC-ALL: Sections:
+# SEC-ALL-NEXT: Idx Name Size Address Type
+# SEC-ALL-NEXT: 0 00000000 0000000000000000
+# SEC-ALL-NEXT: 1 .text 0000000c 0000000000000120 TEXT DATA
+# SEC-ALL-NEXT: 2 .ad 00000004 000000000000012c TEXT DATA
+# SEC-ALL-NEXT: 3 .ag 00000004 0000000000000130 TEXT DATA
+# SEC-ALL-NEXT: 4 .symtab 00000030 0000000000000000
+# SEC-ALL-NEXT: 5 .shstrtab 00000029 0000000000000000
+# SEC-ALL-NEXT: 6 .strtab 00000008 0000000000000000
+
+## All sections started with .a are merged.
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.a*) } }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: llvm-objdump -section-headers %t.out | \
+# RUN: FileCheck -check-prefix=SEC-NO %s
+# SEC-NO: Sections:
+# SEC-NO-NEXT: Idx Name Size Address Type
+# SEC-NO-NEXT: 0 00000000 0000000000000000
+# SEC-NO-NEXT: 1 .text 00000014 0000000000000120 TEXT DATA
+# SEC-NO-NEXT: 2 .symtab 00000030 0000000000000000
+# SEC-NO-NEXT: 3 .shstrtab 00000021 0000000000000000
+# SEC-NO-NEXT: 4 .strtab 00000008 0000000000000000
+
+.text
+.section .abc,"ax",@progbits
+.long 0
+
+.text
+.section .abx,"ax",@progbits
+.long 0
+
+.text
+.section .abcd,"ax",@progbits
+.long 0
+
+.text
+.section .ad,"ax",@progbits
+.long 0
+
+.text
+.section .ag,"ax",@progbits
+.long 0
+
+
+.globl _start
+_start:
diff --git a/test/ELF/writable-merge.s b/test/ELF/writable-merge.s
index dd7b8538e57a..431cb6282d91 100644
--- a/test/ELF/writable-merge.s
+++ b/test/ELF/writable-merge.s
@@ -1,6 +1,6 @@
// REQUIRES: x86
// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
// RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
-// CHECK: Writable SHF_MERGE sections are not supported
+// CHECK: writable SHF_MERGE section is not supported
- .section .foo,"awM",@progbits,4
+.section .foo,"awM",@progbits,4
diff --git a/test/ELF/x86-64-dyn-rel-error.s b/test/ELF/x86-64-dyn-rel-error.s
new file mode 100644
index 000000000000..c814fbeb1d9a
--- /dev/null
+++ b/test/ELF/x86-64-dyn-rel-error.s
@@ -0,0 +1,12 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2.o
+// RUN: ld.lld %t2.o -shared -o %t2.so
+// RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s
+
+ .global _start
+_start:
+ .data
+ .long bar
+
+// CHECK: R_X86_64_32 cannot be used against shared object; recompile with -fPIC.
diff --git a/test/ELF/x86-64-dyn-rel-error2.s b/test/ELF/x86-64-dyn-rel-error2.s
new file mode 100644
index 000000000000..c1d3da3ae2ae
--- /dev/null
+++ b/test/ELF/x86-64-dyn-rel-error2.s
@@ -0,0 +1,12 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2.o
+// RUN: ld.lld %t2.o -shared -o %t2.so
+// RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s
+
+ .global _start
+_start:
+ .data
+ .long bar - .
+
+// CHECK: R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC.
diff --git a/test/ELF/x86-64-rela.s b/test/ELF/x86-64-rela.s
new file mode 100644
index 000000000000..41bdd76de4ca
--- /dev/null
+++ b/test/ELF/x86-64-rela.s
@@ -0,0 +1,11 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -dynamic-table %t.so | FileCheck %s
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux-gnux32 %s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -dynamic-table %t.so | FileCheck %s
+
+ call foo@plt
+
+// CHECK: 0x{{0+}}14 PLTREL{{ +}}RELA
diff --git a/test/ELF/x86-64-relax-offset.s b/test/ELF/x86-64-relax-offset.s
new file mode 100644
index 000000000000..a7c7ce6f6271
--- /dev/null
+++ b/test/ELF/x86-64-relax-offset.s
@@ -0,0 +1,13 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %s \
+// RUN: -o %t.o
+// RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux \
+// RUN: %p/Inputs/x86-64-relax-offset.s -o %t2.o
+// RUN: ld.lld %t2.o %t.o -o %t.so -shared
+// RUN: llvm-objdump -d %t.so | FileCheck %s
+
+ mov foo@gotpcrel(%rip), %rax
+ nop
+
+// CHECK: 1004: {{.*}} leaq -11(%rip), %rax
+// CHECK-NEXT: 100b: {{.*}} nop
diff --git a/test/ELF/x86-64-reloc-32-error.s b/test/ELF/x86-64-reloc-32-error.s
deleted file mode 100644
index b5d476bcf082..000000000000
--- a/test/ELF/x86-64-reloc-32-error.s
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/abs.s -o %tabs
-// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
-// RUN: not ld.lld -shared %tabs %t -o %t2 2>&1 | FileCheck %s
-// REQUIRES: x86
-
- movl $big, %edx
-
-#CHECK: R_X86_64_32 out of range
diff --git a/test/ELF/x86-64-reloc-32-fpic.s b/test/ELF/x86-64-reloc-32-fpic.s
new file mode 100644
index 000000000000..0a0f1a09fda8
--- /dev/null
+++ b/test/ELF/x86-64-reloc-32-fpic.s
@@ -0,0 +1,7 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
+# CHECK: relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC.
+
+.data
+.long _shared
diff --git a/test/ELF/x86-64-reloc-32S-error.s b/test/ELF/x86-64-reloc-32S-error.s
deleted file mode 100644
index aa19c2c32e93..000000000000
--- a/test/ELF/x86-64-reloc-32S-error.s
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
-// RUN: not ld.lld -shared %t -o %t2 2>&1 | FileCheck %s
-// REQUIRES: x86
-
- movq _start - 0x1000000000000, %rdx
-
-#CHECK: R_X86_64_32S out of range
diff --git a/test/ELF/x86-64-reloc-error.s b/test/ELF/x86-64-reloc-error.s
new file mode 100644
index 000000000000..9b7e17de793b
--- /dev/null
+++ b/test/ELF/x86-64-reloc-error.s
@@ -0,0 +1,10 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/x86-64-reloc-error.s -o %tabs
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: not ld.lld -shared %tabs %t -o %t2 2>&1 | FileCheck %s
+// REQUIRES: x86
+
+ movl $big, %edx
+ movq $foo - 0x1000000000000, %rdx
+
+# CHECK: R_X86_64_32 out of range
+# CHECK: R_X86_64_32S out of range
diff --git a/test/ELF/x86-64-reloc-pc32-fpic.s b/test/ELF/x86-64-reloc-pc32-fpic.s
new file mode 100644
index 000000000000..ed9121583c18
--- /dev/null
+++ b/test/ELF/x86-64-reloc-pc32-fpic.s
@@ -0,0 +1,7 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
+# CHECK: relocation R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC.
+
+.data
+call _shared
diff --git a/test/ELF/x86-64-reloc-range.s b/test/ELF/x86-64-reloc-range.s
new file mode 100644
index 000000000000..8319eaafa0ce
--- /dev/null
+++ b/test/ELF/x86-64-reloc-range.s
@@ -0,0 +1,13 @@
+// RUN: llvm-mc %s -o %t.o -triple x86_64-pc-linux -filetype=obj
+// RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s
+
+// CHECK: relocation R_X86_64_PC32 out of range
+// CHECK-NOT: relocation
+
+ lea foo(%rip), %rax
+ lea foo(%rip), %rax
+
+ .hidden foo
+ .bss
+ .zero 0x7fffe007
+foo:
diff --git a/test/ELF/x86-64-tls-gd-got.s b/test/ELF/x86-64-tls-gd-got.s
new file mode 100644
index 000000000000..f86c3aa14f08
--- /dev/null
+++ b/test/ELF/x86-64-tls-gd-got.s
@@ -0,0 +1,19 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/x86-64-tls-gd-got.s -o %t2.o
+# RUN: ld.lld %t1.o %t2.o -o %t
+# RUN: llvm-objdump -d %t | FileCheck %s
+
+ .globl _start
+_start:
+ .byte 0x66
+ leaq bar@tlsgd(%rip), %rdi
+ .byte 0x66
+ rex64
+ call *__tls_get_addr@GOTPCREL(%rip)
+ ret
+
+// CHECK: _start:
+// CHECK-NEXT: movq %fs:0, %rax
+// CHECK-NEXT: leaq -4(%rax), %rax
+// CHECK-NEXT: retq
diff --git a/test/ELF/x86-64-tls-gd-local.s b/test/ELF/x86-64-tls-gd-local.s
new file mode 100644
index 000000000000..843b891be56b
--- /dev/null
+++ b/test/ELF/x86-64-tls-gd-local.s
@@ -0,0 +1,52 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s
+
+ .byte 0x66
+ leaq foo@tlsgd(%rip), %rdi
+ .value 0x6666
+ rex64
+ call __tls_get_addr@PLT
+
+ .byte 0x66
+ leaq bar@tlsgd(%rip), %rdi
+ .value 0x6666
+ rex64
+ call __tls_get_addr@PLT
+
+ .section .tbss,"awT",@nobits
+
+ .hidden foo
+ .globl foo
+foo:
+ .zero 4
+
+ .hidden bar
+ .globl bar
+bar:
+ .zero 4
+
+
+// CHECK: Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_WRITE (0x1)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x20D0
+// CHECK-NEXT: Offset: 0x20D0
+// CHECK-NEXT: Size: 32
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
+// CHECK-NEXT: 0010: 00000000 00000000 04000000 00000000 |................|
+// CHECK-NEXT: )
+
+// CHECK: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x20D0 R_X86_64_DTPMOD64 - 0x0
+// CHECK-NEXT: 0x20E0 R_X86_64_DTPMOD64 - 0x0
+// CHECK-NEXT: }
diff --git a/test/ELF/x86-64-tls-pie.s b/test/ELF/x86-64-tls-pie.s
new file mode 100644
index 000000000000..5ef0f54f435d
--- /dev/null
+++ b/test/ELF/x86-64-tls-pie.s
@@ -0,0 +1,26 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-cloudabi %s -o %t1.o
+# RUN: ld.lld -pie %t1.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s
+
+# Bug 27174: R_X86_64_TPOFF32 and R_X86_64_GOTTPOFF relocations should
+# be eliminated when building a PIE executable, as the static TLS layout
+# is fixed.
+#
+# CHECK: Relocations [
+# CHECK-NEXT: ]
+
+ .globl _start
+_start:
+ movq %fs:0, %rax
+ movl $3, i@TPOFF(%rax)
+
+ movq %fs:0, %rdx
+ movq i@GOTTPOFF(%rip), %rcx
+ movl $3, (%rdx,%rcx)
+
+ .section .tbss.i,"awT",@nobits
+ .globl i
+i:
+ .long 0
+ .size i, 4
diff --git a/test/ELF/zdefs.s b/test/ELF/zdefs.s
new file mode 100644
index 000000000000..410da1812db9
--- /dev/null
+++ b/test/ELF/zdefs.s
@@ -0,0 +1,7 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t1.so
+
+# RUN: not ld.lld -z defs -shared %t.o -o %t1.so 2>&1 | FileCheck -check-prefix=ERR %s
+# ERR: undefined symbol: foo
+
+callq foo@PLT
diff --git a/test/LinkerScript/expr-precedence.test b/test/LinkerScript/expr-precedence.test
deleted file mode 100644
index 5170e34ba4b3..000000000000
--- a/test/LinkerScript/expr-precedence.test
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- RUN: linker-script-test %s | FileCheck %s
-*/
-SECTIONS {
- . = foo >= bar + 1 ? bar : 1- - - -1;
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: foo
-CHECK: greaterequal: >=
-CHECK: identifier: bar
-CHECK: plus: +
-CHECK: number: 1
-CHECK: question: ?
-CHECK: identifier: bar
-CHECK: colon: :
-CHECK: number: 1
-CHECK: minus: -
-CHECK: minus: -
-CHECK: minus: -
-CHECK: minus: -
-CHECK: number: 1
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: eof:
-CHECK: SECTIONS
-CHECK: {
-CHECK: . = (foo >= (bar + 1)) ? bar : (1 - (-(-(-1))))
-CHECK: }
-*/
diff --git a/test/LinkerScript/extern-bad-symbol.test b/test/LinkerScript/extern-bad-symbol.test
deleted file mode 100644
index 279a7cc20567..000000000000
--- a/test/LinkerScript/extern-bad-symbol.test
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-
-EXTERN(a b 3)
-/*
-CHECK-ERR: [[@LINE-2]]:12: error: expected symbol in EXTERN.
-CHECK-ERR-NEXT: {{^EXTERN\(a b 3\)}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-
-/*
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: identifier: a
-CHECK: identifier: b
-CHECK: number: 3
-CHECK: r_paren: )
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/extern-empty.test b/test/LinkerScript/extern-empty.test
deleted file mode 100644
index a5e1ece084d9..000000000000
--- a/test/LinkerScript/extern-empty.test
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-
-EXTERN()
-/*
-CHECK-ERR: [[@LINE-2]]:8: error: expected one or more symbols in EXTERN.
-CHECK-ERR-NEXT: {{^EXTERN()}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-
-/*
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/extern-valid.test b/test/LinkerScript/extern-valid.test
deleted file mode 100644
index 764b4668a34f..000000000000
--- a/test/LinkerScript/extern-valid.test
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- RUN: linker-script-test %s | FileCheck %s
-*/
-
-EXTERN(a)
-EXTERN(a b)
-EXTERN(_foo _bar _baz)
-
-/*
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: identifier: a
-CHECK: r_paren: )
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: identifier: a
-CHECK: identifier: b
-CHECK: r_paren: )
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: identifier: _foo
-CHECK: identifier: _bar
-CHECK: identifier: _baz
-CHECK: r_paren: )
-CHECK: eof:
-CHECK: EXTERN(a)
-CHECK: EXTERN(a b)
-CHECK: EXTERN(_foo _bar _baz)
-*/
diff --git a/test/LinkerScript/incomplete-ternary.test b/test/LinkerScript/incomplete-ternary.test
deleted file mode 100644
index fae30537d2de..000000000000
--- a/test/LinkerScript/incomplete-ternary.test
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
- . = foo ? bar;
-/*
-CHECK-ERR: [[@LINE-2]]:18: error: expected :
-CHECK-ERR-NEXT: {{^ \. = foo \? bar;}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: foo
-CHECK: question: ?
-CHECK: identifier: bar
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/libname-err-1.test b/test/LinkerScript/libname-err-1.test
deleted file mode 100644
index 451a469336bd..000000000000
--- a/test/LinkerScript/libname-err-1.test
+++ /dev/null
@@ -1,11 +0,0 @@
-/* RUN: linker-script-test %s 2>&1 | FileCheck %s
-*/
-
-OUTPUT_ARCH(i386:x86_64)
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-GROUP( -l### )
-ENTRY(init)
-
-/*
-CHECK: libname-err-1.test:6:10: error: expected )
-*/
diff --git a/test/LinkerScript/libname-err-2.test b/test/LinkerScript/libname-err-2.test
deleted file mode 100644
index f1d96d718151..000000000000
--- a/test/LinkerScript/libname-err-2.test
+++ /dev/null
@@ -1,11 +0,0 @@
-/* RUN: linker-script-test %s 2>&1 | FileCheck %s
-*/
-
-OUTPUT_ARCH(i386:x86_64)
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-GROUP( -l )
-ENTRY(init)
-
-/*
-CHECK: libname-err-2.test:6:10: error: expected )
-*/
diff --git a/test/LinkerScript/linker-script-outputformat.test b/test/LinkerScript/linker-script-outputformat.test
deleted file mode 100644
index b47bb38ad8d8..000000000000
--- a/test/LinkerScript/linker-script-outputformat.test
+++ /dev/null
@@ -1,12 +0,0 @@
-/* RUN: linker-script-test %s | FileCheck %s
-*/
-
-OUTPUT_FORMAT(elf64-x86-64)
-
-/*
-CHECK: kw_output_format: OUTPUT_FORMAT
-CHECK: l_paren: (
-CHECK: identifier: elf64-x86-64
-CHECK: r_paren: )
-CHECK: OUTPUT_FORMAT("elf64-x86-64")
-*/
diff --git a/test/LinkerScript/linker-script.test b/test/LinkerScript/linker-script.test
deleted file mode 100644
index 421493666e84..000000000000
--- a/test/LinkerScript/linker-script.test
+++ /dev/null
@@ -1,46 +0,0 @@
-/* RUN: linker-script-test %s | FileCheck %s
-*/
-
-OUTPUT_ARCH(i386:x86_64)
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-OUTPUT("/out/foo")
-GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) -lm -l:libgcc.a )
-ENTRY(init)
-
-/*
-CHECK: kw_output_arch: OUTPUT_ARCH
-CHECK: l_paren: (
-CHECK: identifier: i386:x86_64
-CHECK: r_paren: )
-CHECK: kw_output_format: OUTPUT_FORMAT
-CHECK: l_paren: (
-CHECK: identifier: elf64-x86-64
-CHECK: comma: ,
-CHECK: identifier: elf64-x86-64
-CHECK: comma: ,
-CHECK: identifier: elf64-x86-64
-CHECK: r_paren: )
-CHECK: kw_output: OUTPUT
-CHECK: l_paren: (
-CHECK: identifier: /out/foo
-CHECK: r_paren: )
-CHECK: kw_group: GROUP
-CHECK: l_paren: (
-CHECK: identifier: /lib/x86_64-linux-gnu/libc.so.6
-CHECK: identifier: /usr/lib/x86_64-linux-gnu/libc_nonshared.a
-CHECK: kw_as_needed: AS_NEEDED
-CHECK: l_paren: (
-CHECK: identifier: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
-CHECK: r_paren: )
-CHECK: libname: m
-CHECK: libname: :libgcc.a
-CHECK: r_paren: )
-CHECK: kw_entry: ENTRY
-CHECK: l_paren: (
-CHECK: identifier: init
-CHECK: r_paren: )
-CHECK: eof:
-CHECK: OUTPUT_FORMAT("elf64-x86-64","elf64-x86-64","elf64-x86-64")
-CHECK: GROUP(/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED(/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) -lm -l:libgcc.a)
-CHECK: ENTRY(init)
-*/
diff --git a/test/LinkerScript/memory-empty.test b/test/LinkerScript/memory-empty.test
deleted file mode 100644
index b71022afdff3..000000000000
--- a/test/LinkerScript/memory-empty.test
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- RUN: linker-script-test %s | FileCheck %s
-*/
-
-MEMORY
-{
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: r_brace: }
-CHECK: eof:
-CHECK: MEMORY
-CHECK: {
-CHECK: }
-*/
diff --git a/test/LinkerScript/memory-missing-attrs.test b/test/LinkerScript/memory-missing-attrs.test
deleted file mode 100644
index fbbf38b76514..000000000000
--- a/test/LinkerScript/memory-missing-attrs.test
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-MEMORY
-{
- ram () : ORIGIN = 0x20000000, LENGTH = 128M
-/*
-CHECK-ERR: [[@LINE-2]]:8: error: Expected memory attribute string.
-CHECK-ERR-NEXT: {{^ ram \(\) : ORIGIN = 0x20000000, LENGTH = 128M}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: identifier: ram
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: ORIGIN
-CHECK: equal: =
-CHECK: number: 0x20000000
-CHECK: comma: ,
-CHECK: kw_length: LENGTH
-CHECK: equal: =
-CHECK: number: 128M
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/memory-missing-length.test b/test/LinkerScript/memory-missing-length.test
deleted file mode 100644
index f317c9a26788..000000000000
--- a/test/LinkerScript/memory-missing-length.test
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-MEMORY
-{
- ram (rwx) : ORIGIN = 0x20000000,
-}
-/*
-CHECK-ERR: [[@LINE-2]]:1: error: expected LENGTH
-CHECK-ERR-NEXT: {{^}}}
-CHECK-ERR-NEXT: {{^\^}}
-*/
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: identifier: ram
-CHECK: l_paren: (
-CHECK: identifier: rwx
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: ORIGIN
-CHECK: equal: =
-CHECK: number: 0x20000000
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/memory-missing-name.test b/test/LinkerScript/memory-missing-name.test
deleted file mode 100644
index 46597d4351d3..000000000000
--- a/test/LinkerScript/memory-missing-name.test
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-MEMORY
-{
- (rwx) : ORIGIN = 0x20000000, LENGTH = 128M
-/*
-CHECK-ERR: [[@LINE-2]]:3: error: expected memory block definition.
-CHECK-ERR-NEXT: {{^ \(rwx\) : ORIGIN = 0x20000000, LENGTH = 128M}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: ORIGIN
-CHECK: equal: =
-CHECK: number: 0x20000000
-CHECK: comma: ,
-CHECK: kw_length: LENGTH
-CHECK: equal: =
-CHECK: number: 128M
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/memory-missing-origin.test b/test/LinkerScript/memory-missing-origin.test
deleted file mode 100644
index 50a64d17d6c5..000000000000
--- a/test/LinkerScript/memory-missing-origin.test
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-MEMORY
-{
- ram (rwx) : LENGTH = 128M
-/*
-CHECK-ERR: [[@LINE-2]]:15: error: expected ORIGIN
-CHECK-ERR-NEXT: {{^ ram \(rwx\) : LENGTH = 128M}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: identifier: ram
-CHECK: l_paren: (
-CHECK: identifier: rwx
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_length: LENGTH
-CHECK: equal: =
-CHECK: number: 128M
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/memory-valid.test b/test/LinkerScript/memory-valid.test
deleted file mode 100644
index 7a0e906c5fb5..000000000000
--- a/test/LinkerScript/memory-valid.test
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- RUN: linker-script-test %s | FileCheck %s
-*/
-
-MEMORY
-{
- ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
- rom (rx) : org = 0x0, len = 256K
- boot : o = 0x1000000, l = 0x5f00
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: identifier: ram
-CHECK: l_paren: (
-CHECK: identifier: rwx
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: ORIGIN
-CHECK: equal: =
-CHECK: number: 0x20000000
-CHECK: comma: ,
-CHECK: kw_length: LENGTH
-CHECK: equal: =
-CHECK: number: 96K
-CHECK: identifier: rom
-CHECK: l_paren: (
-CHECK: identifier: rx
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: org
-CHECK: equal: =
-CHECK: number: 0x0
-CHECK: comma: ,
-CHECK: kw_length: len
-CHECK: equal: =
-CHECK: number: 256K
-CHECK: identifier: boot
-CHECK: colon: :
-CHECK: kw_origin: o
-CHECK: equal: =
-CHECK: number: 0x1000000
-CHECK: comma: ,
-CHECK: kw_length: l
-CHECK: equal: =
-CHECK: number: 0x5f00
-CHECK: r_brace: }
-CHECK: eof:
-CHECK: MEMORY
-CHECK: {
-CHECK: ram (rwx) : ORIGIN = 536870912, LENGTH = 98304
-CHECK: rom (rx) : ORIGIN = 0, LENGTH = 262144
-CHECK: boot : ORIGIN = 16777216, LENGTH = 24320
-CHECK: }
-*/
diff --git a/test/LinkerScript/missing-entry-symbol.test b/test/LinkerScript/missing-entry-symbol.test
deleted file mode 100644
index 54e8f75c90a4..000000000000
--- a/test/LinkerScript/missing-entry-symbol.test
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
- ENTRY()
-/*
-CHECK-ERR: [[@LINE-2]]:11: error: expected identifier in ENTRY
-CHECK-ERR-NEXT: {{^ ENTRY()}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: l_brace: {
-CHECK: kw_entry: ENTRY
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/missing-input-file-name.test b/test/LinkerScript/missing-input-file-name.test
deleted file mode 100644
index c4218ccef321..000000000000
--- a/test/LinkerScript/missing-input-file-name.test
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
- .text : { ()}
-/*
-CHECK-ERR: [[@LINE-2]]:15: error: expected symbol assignment or input file name.
-CHECK-ERR-NEXT: {{^ \.text : { \(\)}}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .text
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/missing-input-sections.test b/test/LinkerScript/missing-input-sections.test
deleted file mode 100644
index 5db93444b1a9..000000000000
--- a/test/LinkerScript/missing-input-sections.test
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
- .text : { *(+)}
-/*
-CHECK-ERR: [[@LINE-2]]:16: error: expected )
-CHECK-ERR-NEXT: {{^ \.text : { \*\(\+\)}}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .text
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: plus: +
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/missing-operand.test b/test/LinkerScript/missing-operand.test
deleted file mode 100644
index cfa87bf40768..000000000000
--- a/test/LinkerScript/missing-operand.test
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -check-prefix=CHECK-ERR -input-file %t %s
-*/
-SECTIONS {
- . = foo / ;
-/*
-CHECK-ERR: [[@LINE-2]]:15: error: expected symbol, number, minus, tilde or left parenthesis.
-CHECK-ERR-NEXT: {{^ . = foo / ;}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: foo
-CHECK: slash: /
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: eof:
- */
diff --git a/test/LinkerScript/missing-output-section-name.test b/test/LinkerScript/missing-output-section-name.test
deleted file mode 100644
index 79792982b619..000000000000
--- a/test/LinkerScript/missing-output-section-name.test
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
- : { *()}
-/*
-CHECK-ERR: [[@LINE-2]]:5: error: expected symbol assignment, entry, overlay or output section name
-CHECK-ERR-NEXT: {{^ : { \*\(\)}}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/missing-symbol.test b/test/LinkerScript/missing-symbol.test
deleted file mode 100644
index 4e8777ef40b9..000000000000
--- a/test/LinkerScript/missing-symbol.test
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- RUN: linker-script-test %s 2> %t | FileCheck %s
- RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
- = foo + bar;
-/*
-CHECK-ERR: [[@LINE-2]]:5: error: expected symbol assignment, entry, overlay or output section name.
-CHECK-ERR-NEXT: {{^ = foo \+ bar;}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: equal: =
-CHECK: identifier: foo
-CHECK: plus: +
-CHECK: identifier: bar
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/test/LinkerScript/phdrs-sections.test b/test/LinkerScript/phdrs-sections.test
deleted file mode 100644
index 872b7999cb7e..000000000000
--- a/test/LinkerScript/phdrs-sections.test
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- Test PHDR parsing and section -> phdr mapping.
- RUN: linker-script-test %s | FileCheck %s
-*/
-
-PHDRS
-{
- ph_text PT_LOAD FLAGS (0x1 | 0x4);
- ph_data PT_LOAD FLAGS (0x2 | 0x4);
-}
-
-SECTIONS
-{
- .init : {} : ph_text
-}
-
-/*
-CHECK: PHDRS
-CHECK: {
-CHECK: ph_text 1 FLAGS (5);
-CHECK: ph_data 1 FLAGS (6);
-CHECK: }
-CHECK: SECTIONS
-CHECK: {
-CHECK: .init :
-CHECK: {
-CHECK: } : ph_text
-CHECK: }
-*/
diff --git a/test/LinkerScript/sections.test b/test/LinkerScript/sections.test
deleted file mode 100644
index 67f8288badaa..000000000000
--- a/test/LinkerScript/sections.test
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- This test exercises parsing typical commands found in GNU ld linker scripts.
- RUN: linker-script-test %s | FileCheck %s
-*/
-
-SEARCH_DIR("/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu");
-SECTIONS
-{
- PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
- .interp : { *(.interp) }
- .note.gnu.build-id : { *(.note.gnu.build-id) }
- .hash : { *(.hash) }
- .rela.dyn :
- {
- *(.rela.init)
- *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
- *(.rela.fini)
- *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
- }
- .rela.plt :
- {
- *(.rela.plt)
- PROVIDE_HIDDEN (__rela_iplt_start = .);
- *(.rela.iplt)
- PROVIDE_HIDDEN (__rela_iplt_end = .);
- }
- .init :
- {
- FILL (0x90909090)
- KEEP (*(SORT_NONE(.init)))
- } =0x909090909090909090909090
- PROVIDE (__etext = .);
- .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
- .exception_ranges : ONLY_IF_RO { *(.exception_ranges
- .exception_ranges*) }
- . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
- /* Exception handling */
- .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
- .ctors :
- {
- KEEP (*crtbegin.o(.ctors))
- KEEP (*crtbegin?.o(.ctors))
- KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
- }
- .dtors :
- {
- KEEP (*crtbegin.o(.dtors))
- KEEP (*crtbegin?.o(.dtors))
- KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
- KEEP (*(SORT(.dtors.*)))
- KEEP (*(.dtors))
- }
- . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
- .got.plt : { *(.got.plt) *(.igot.plt) }
- .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
- {
- *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
- }
- .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
- {
- *(.ldata .ldata.* .gnu.linkonce.l.*)
- . = ALIGN(. != 0 ? 64 / 8 : 1);
- }
- . = ALIGN(64 / 8);
- _end = .; PROVIDE (end = .);
- . = DATA_SEGMENT_END (.);
- /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
-}
-
-/*
-CHECK: kw_search_dir: SEARCH_DIR
-CHECK: l_paren: (
-CHECK: identifier: /usr/x86_64-linux-gnu/lib64
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: kw_search_dir: SEARCH_DIR
-CHECK: l_paren: (
-CHECK: identifier: =/usr/local/lib/x86_64-linux-gnu
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: kw_provide: PROVIDE
-CHECK: l_paren: (
-CHECK: identifier: __executable_start
-CHECK: equal: =
-CHECK: identifier: SEGMENT_START
-CHECK: l_paren: (
-CHECK: identifier: text-segment
-CHECK: comma: ,
-CHECK: number: 0x400000
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: SEGMENT_START
-CHECK: l_paren: (
-CHECK: identifier: text-segment
-CHECK: comma: ,
-CHECK: number: 0x400000
-CHECK: r_paren: )
-CHECK: plus: +
-CHECK: identifier: SIZEOF_HEADERS
-CHECK: semicolon: ;
-CHECK: identifier: .interp
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .interp
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .note.gnu.build-id
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .note.gnu.build-id
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .hash
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .hash
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .rela.dyn
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.init
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.text
-CHECK: identifier: .rela.text.*
-CHECK: identifier: .rela.gnu.linkonce.t.*
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.fini
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.rodata
-CHECK: identifier: .rela.rodata.*
-CHECK: identifier: .rela.gnu.linkonce.r.*
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .rela.plt
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.plt
-CHECK: r_paren: )
-CHECK: kw_provide_hidden: PROVIDE_HIDDEN
-CHECK: l_paren: (
-CHECK: identifier: __rela_iplt_start
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.iplt
-CHECK: r_paren: )
-CHECK: kw_provide_hidden: PROVIDE_HIDDEN
-CHECK: l_paren: (
-CHECK: identifier: __rela_iplt_end
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: identifier: .init
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: kw_fill: FILL
-CHECK: l_paren: (
-CHECK: number: 0x90909090
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_sort_none: SORT_NONE
-CHECK: l_paren: (
-CHECK: identifier: .init
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: kw_provide: PROVIDE
-CHECK: l_paren: (
-CHECK: identifier: __etext
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .eh_frame
-CHECK: colon: :
-CHECK: kw_only_if_ro: ONLY_IF_RO
-CHECK: l_brace: {
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .eh_frame
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .exception_ranges
-CHECK: colon: :
-CHECK: kw_only_if_ro: ONLY_IF_RO
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .exception_ranges
-CHECK: identifier: .exception_ranges*
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: l_paren: (
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: amp: &
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: number: 1
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: DATA_SEGMENT_ALIGN
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: comma: ,
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: COMMONPAGESIZE
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .eh_frame
-CHECK: colon: :
-CHECK: kw_only_if_rw: ONLY_IF_RW
-CHECK: l_brace: {
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .eh_frame
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .ctors
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: identifier: *crtbegin.o
-CHECK: l_paren: (
-CHECK: identifier: .ctors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: identifier: *crtbegin?.o
-CHECK: l_paren: (
-CHECK: identifier: .ctors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_exclude_file: EXCLUDE_FILE
-CHECK: l_paren: (
-CHECK: identifier: *crtend.o
-CHECK: identifier: *crtend?.o
-CHECK: r_paren: )
-CHECK: identifier: .ctors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_sort_by_name: SORT
-CHECK: l_paren: (
-CHECK: identifier: .ctors.*
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .ctors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .dtors
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: identifier: *crtbegin.o
-CHECK: l_paren: (
-CHECK: identifier: .dtors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: identifier: *crtbegin?.o
-CHECK: l_paren: (
-CHECK: identifier: .dtors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_exclude_file: EXCLUDE_FILE
-CHECK: l_paren: (
-CHECK: identifier: *crtend.o
-CHECK: identifier: *crtend?.o
-CHECK: r_paren: )
-CHECK: identifier: .dtors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_sort_by_name: SORT
-CHECK: l_paren: (
-CHECK: identifier: .dtors.*
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .dtors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: DATA_SEGMENT_RELRO_END
-CHECK: l_paren: (
-CHECK: identifier: SIZEOF
-CHECK: l_paren: (
-CHECK: identifier: .got.plt
-CHECK: r_paren: )
-CHECK: greaterequal: >=
-CHECK: number: 24
-CHECK: question: ?
-CHECK: number: 24
-CHECK: colon: :
-CHECK: number: 0
-CHECK: comma: ,
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .got.plt
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .got.plt
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .igot.plt
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .lrodata
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: plus: +
-CHECK: l_paren: (
-CHECK: identifier: .
-CHECK: amp: &
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: number: 1
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .lrodata
-CHECK: identifier: .lrodata.*
-CHECK: identifier: .gnu.linkonce.lr.*
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .ldata
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: plus: +
-CHECK: l_paren: (
-CHECK: identifier: .
-CHECK: amp: &
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: number: 1
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .ldata
-CHECK: identifier: .ldata.*
-CHECK: identifier: .gnu.linkonce.l.*
-CHECK: r_paren: )
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: identifier: .
-CHECK: exclaimequal: !=
-CHECK: number: 0
-CHECK: question: ?
-CHECK: number: 64
-CHECK: slash: /
-CHECK: number: 8
-CHECK: colon: :
-CHECK: number: 1
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: number: 64
-CHECK: slash: /
-CHECK: number: 8
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: _end
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: semicolon: ;
-CHECK: kw_provide: PROVIDE
-CHECK: l_paren: (
-CHECK: identifier: end
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: DATA_SEGMENT_END
-CHECK: l_paren: (
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: kw_discard: /DISCARD/
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .note.GNU-stack
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .gnu_debuglink
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .gnu.lto_*
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: r_brace: }
-CHECK: eof:
-CHECK: SEARCH_DIR("/usr/x86_64-linux-gnu/lib64")
-CHECK: SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu")
-CHECK: SECTIONS
-CHECK: {
-CHECK: PROVIDE(__executable_start = SEGMENT_START(text-segment, 4194304))
-CHECK: . = (SEGMENT_START(text-segment, 4194304) + SIZEOF_HEADERS)
-CHECK: .interp :
-CHECK: {
-CHECK: *(.interp)
-CHECK: }
-CHECK: .note.gnu.build-id :
-CHECK: {
-CHECK: *(.note.gnu.build-id)
-CHECK: }
-CHECK: .hash :
-CHECK: {
-CHECK: *(.hash)
-CHECK: }
-CHECK: .rela.dyn :
-CHECK: {
-CHECK: *(.rela.init)
-CHECK: *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
-CHECK: *(.rela.fini)
-CHECK: *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
-CHECK: }
-CHECK: .rela.plt :
-CHECK: {
-CHECK: *(.rela.plt)
-CHECK: PROVIDE_HIDDEN(__rela_iplt_start = .)
-CHECK: *(.rela.iplt)
-CHECK: PROVIDE_HIDDEN(__rela_iplt_end = .)
-CHECK: }
-CHECK: .init :
-CHECK: {
-CHECK: FILL(0x90909090)
-CHECK: KEEP(*(SORT_NONE(.init)))
-CHECK: } =0x909090909090909090909090
-CHECK: PROVIDE(__etext = .)
-CHECK: .eh_frame :
-CHECK: ONLY_IF_RO {
-CHECK: KEEP(*(.eh_frame))
-CHECK: }
-CHECK: .exception_ranges :
-CHECK: ONLY_IF_RO {
-CHECK: *(.exception_ranges .exception_ranges*)
-CHECK: }
-CHECK: . = (ALIGN(CONSTANT(MAXPAGESIZE)) - ((CONSTANT(MAXPAGESIZE) - .) & (CONSTANT(MAXPAGESIZE) - 1)))
-CHECK: . = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE))
-CHECK: .eh_frame :
-CHECK: ONLY_IF_RW {
-CHECK: KEEP(*(.eh_frame))
-CHECK: }
-CHECK: .ctors :
-CHECK: {
-CHECK: KEEP(*crtbegin.o(.ctors))
-CHECK: KEEP(*crtbegin?.o(.ctors))
-CHECK: KEEP(*(EXCLUDE_FILE(*crtend.o *crtend?.o ) .ctors))
-CHECK: KEEP(*(SORT_BY_NAME(.ctors.*)))
-CHECK: KEEP(*(.ctors))
-CHECK: }
-CHECK: .dtors :
-CHECK: {
-CHECK: KEEP(*crtbegin.o(.dtors))
-CHECK: KEEP(*crtbegin?.o(.dtors))
-CHECK: KEEP(*(EXCLUDE_FILE(*crtend.o *crtend?.o ) .dtors))
-CHECK: KEEP(*(SORT_BY_NAME(.dtors.*)))
-CHECK: KEEP(*(.dtors))
-CHECK: }
-CHECK: . = DATA_SEGMENT_RELRO_END((SIZEOF(.got.plt) >= 24) ? 24 : 0, .)
-CHECK: .got.plt :
-CHECK: {
-CHECK: *(.got.plt)
-CHECK: *(.igot.plt)
-CHECK: }
-CHECK: .lrodata (ALIGN(CONSTANT(MAXPAGESIZE)) + (. & (CONSTANT(MAXPAGESIZE) - 1))) :
-CHECK: {
-CHECK: *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
-CHECK: }
-CHECK: .ldata (ALIGN(CONSTANT(MAXPAGESIZE)) + (. & (CONSTANT(MAXPAGESIZE) - 1))) :
-CHECK: {
-CHECK: *(.ldata .ldata.* .gnu.linkonce.l.*)
-CHECK: . = ALIGN((. != 0) ? (64 / 8) : 1)
-CHECK: }
-CHECK: . = ALIGN((64 / 8))
-CHECK: _end = .
-CHECK: PROVIDE(end = .)
-CHECK: . = DATA_SEGMENT_END(.)
-CHECK: :
-CHECK: {
-CHECK: *(.note.GNU-stack)
-CHECK: *(.gnu_debuglink)
-CHECK: *(.gnu.lto_*)
-CHECK: }
-CHECK: }
-*/
diff --git a/test/Unit/lit.site.cfg.in b/test/Unit/lit.site.cfg.in
index 74c5eca91153..c2f3054a2d59 100644
--- a/test/Unit/lit.site.cfg.in
+++ b/test/Unit/lit.site.cfg.in
@@ -1,5 +1,5 @@
-## Autogenerated by LLVM/lld configuration.
-# Do not edit!
+@LIT_SITE_CFG_IN_HEADER@
+
config.llvm_src_root = "@LLVM_SOURCE_DIR@"
config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
diff --git a/test/core/Inputs/archive-basic.objtxt b/test/core/Inputs/archive-basic.objtxt
deleted file mode 100644
index ecfdacd0b6dd..000000000000
--- a/test/core/Inputs/archive-basic.objtxt
+++ /dev/null
@@ -1,21 +0,0 @@
---- !archive
-members:
- - name: bar.o
- content: !native
- defined-atoms:
- - name: bar
- scope: global
- type: code
-
- - name: bar2
- type: code
-
- - name: baz.o
- content: !native
- defined-atoms:
- - name: baz
- scope: global
- type: code
-
- - name: baz2
- type: code
diff --git a/test/core/Inputs/archive-chain.objtxt b/test/core/Inputs/archive-chain.objtxt
deleted file mode 100644
index d3cc17137c18..000000000000
--- a/test/core/Inputs/archive-chain.objtxt
+++ /dev/null
@@ -1,24 +0,0 @@
---- !archive
-members:
- - name: bar1.o
- content: !native
- defined-atoms:
- - name: bar1
- scope: global
- type: code
-
- - name: bar1b
- type: code
-
- undefined-atoms:
- - name: baz1
-
- - name: bar2.o
- content: !native
- defined-atoms:
- - name: bar2
- scope: global
- type: code
-
- - name: bar2b
- type: code
diff --git a/test/core/Inputs/archive-chain2.objtxt b/test/core/Inputs/archive-chain2.objtxt
deleted file mode 100644
index aed6b1b959e1..000000000000
--- a/test/core/Inputs/archive-chain2.objtxt
+++ /dev/null
@@ -1,21 +0,0 @@
---- !archive
-members:
- - name: baz1.o
- content: !native
- defined-atoms:
- - name: baz1
- scope: global
- type: code
-
- - name: baz1b
- type: code
-
- - name: baz2.o
- content: !native
- defined-atoms:
- - name: baz2
- scope: global
- type: code
-
- - name: baz2b
- type: code
diff --git a/test/core/Inputs/archive-tentdef-search.objtxt b/test/core/Inputs/archive-tentdef-search.objtxt
deleted file mode 100644
index 70219aac7a6d..000000000000
--- a/test/core/Inputs/archive-tentdef-search.objtxt
+++ /dev/null
@@ -1,11 +0,0 @@
---- !archive
-members:
- - name: bar.o
- content: !native
- defined-atoms:
- - name: bar
- scope: global
- type: data
-
- - name: bar2
- type: data
diff --git a/test/core/Inputs/associates.objtxt b/test/core/Inputs/associates.objtxt
deleted file mode 100644
index 29d028c27edc..000000000000
--- a/test/core/Inputs/associates.objtxt
+++ /dev/null
@@ -1,8 +0,0 @@
-defined-atoms:
- - name: f1
- merge: as-weak
- scope: global
- references:
- - kind: associate
- target: f2
- - name: f2
diff --git a/test/core/Inputs/auto-hide-coalesce.objtxt b/test/core/Inputs/auto-hide-coalesce.objtxt
deleted file mode 100644
index d82d0f41c4f4..000000000000
--- a/test/core/Inputs/auto-hide-coalesce.objtxt
+++ /dev/null
@@ -1,20 +0,0 @@
-defined-atoms:
- - name: _inlineFunc1
- scope: global
- type: code
- merge: as-weak
-
- - name: _inlineFunc2
- scope: global
- type: code
- merge: as-addressed-weak
-
- - name: _inlineFunc3
- scope: global
- type: code
- merge: as-weak
-
- - name: _inlineFunc4
- scope: global
- type: code
- merge: as-addressed-weak
diff --git a/test/core/Inputs/code-model-attributes.objtxt b/test/core/Inputs/code-model-attributes.objtxt
deleted file mode 100644
index 7c01a0d57f36..000000000000
--- a/test/core/Inputs/code-model-attributes.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-defined-atoms:
- - name: _none
- code-model: none
diff --git a/test/core/Inputs/code-model-attributes2.objtxt b/test/core/Inputs/code-model-attributes2.objtxt
deleted file mode 100644
index 92df88c7b0ea..000000000000
--- a/test/core/Inputs/code-model-attributes2.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-defined-atoms:
- - name: _mips_pic
- code-model: mips-pic
diff --git a/test/core/Inputs/code-model-attributes3.objtxt b/test/core/Inputs/code-model-attributes3.objtxt
deleted file mode 100644
index 8f2ced14f10c..000000000000
--- a/test/core/Inputs/code-model-attributes3.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-defined-atoms:
- - name: _mips_micro
- code-model: mips-micro
diff --git a/test/core/Inputs/code-model-attributes4.objtxt b/test/core/Inputs/code-model-attributes4.objtxt
deleted file mode 100644
index 160c9a00c3da..000000000000
--- a/test/core/Inputs/code-model-attributes4.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-defined-atoms:
- - name: _mips_micro_pic
- code-model: mips-micro-pic
diff --git a/test/core/Inputs/code-model-attributes5.objtxt b/test/core/Inputs/code-model-attributes5.objtxt
deleted file mode 100644
index 99bdb54e09bb..000000000000
--- a/test/core/Inputs/code-model-attributes5.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-defined-atoms:
- - name: _mips_16
- code-model: mips-16
diff --git a/test/core/Inputs/constants-coalesce.objtxt b/test/core/Inputs/constants-coalesce.objtxt
deleted file mode 100644
index ea3436f9ee28..000000000000
--- a/test/core/Inputs/constants-coalesce.objtxt
+++ /dev/null
@@ -1,9 +0,0 @@
----
-defined-atoms:
- - ref-name: L1
- type: constant
- content: [ 01, 02 ]
- - ref-name: L2
- type: constant
- merge: by-content
- content: [ 01, 02, 03, 04 ]
diff --git a/test/core/Inputs/constants-coalesce2.objtxt b/test/core/Inputs/constants-coalesce2.objtxt
deleted file mode 100644
index c8f10f414f87..000000000000
--- a/test/core/Inputs/constants-coalesce2.objtxt
+++ /dev/null
@@ -1,10 +0,0 @@
----
-defined-atoms:
- - ref-name: L2
- type: constant
- merge: by-content
- content: [ 01, 23, 45, 67, 89, AB, CD, EF ]
- - ref-name: L3
- type: constant
- merge: by-content
- content: [ 01, 02, 03 ]
diff --git a/test/core/Inputs/cstring-coalesce.objtxt b/test/core/Inputs/cstring-coalesce.objtxt
deleted file mode 100644
index d2e6327cf20c..000000000000
--- a/test/core/Inputs/cstring-coalesce.objtxt
+++ /dev/null
@@ -1,6 +0,0 @@
----
-defined-atoms:
- - ref-name: L2
- type: c-string
- merge: by-content
- content: [ 68, 65, 6c, 6c, 6f, 00 ]
diff --git a/test/core/Inputs/cstring-coalesce2.objtxt b/test/core/Inputs/cstring-coalesce2.objtxt
deleted file mode 100644
index 76dedf7cf3bd..000000000000
--- a/test/core/Inputs/cstring-coalesce2.objtxt
+++ /dev/null
@@ -1,6 +0,0 @@
----
-defined-atoms:
- - ref-name: L2
- type: c-string
- merge: by-content
- content: [ 74, 68, 65, 72, 65, 00 ]
diff --git a/test/core/Inputs/custom-section-coalesce.objtxt b/test/core/Inputs/custom-section-coalesce.objtxt
deleted file mode 100644
index de3efe339aae..000000000000
--- a/test/core/Inputs/custom-section-coalesce.objtxt
+++ /dev/null
@@ -1,15 +0,0 @@
----
-defined-atoms:
- - ref-name: L1
- type: constant
- merge: by-content
- content: [ 01, 02, 03, 04 ]
- section-choice: custom-required
- section-name: .mysection
-
- - ref-name: L2
- type: constant
- merge: by-content
- content: [ 01, 02, 03, 04 ]
- section-choice: custom-required
- section-name: .mysection2
diff --git a/test/core/Inputs/custom-section-coalesce2.objtxt b/test/core/Inputs/custom-section-coalesce2.objtxt
deleted file mode 100644
index 3e8356f0c7ee..000000000000
--- a/test/core/Inputs/custom-section-coalesce2.objtxt
+++ /dev/null
@@ -1,13 +0,0 @@
----
-defined-atoms:
- - ref-name: L1
- type: constant
- merge: by-content
- content: [ 05, 06, 07, 08 ]
- section-choice: custom-required
- section-name: .mysection
-
- - ref-name: L2
- type: constant
- merge: by-content
- content: [ 01, 02, 03, 04 ]
diff --git a/test/core/Inputs/dead-strip-attributes.objtxt b/test/core/Inputs/dead-strip-attributes.objtxt
deleted file mode 100644
index 06a71485dcd5..000000000000
--- a/test/core/Inputs/dead-strip-attributes.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-defined-atoms:
- - name: _foo2
- dead-strip: never
diff --git a/test/core/Inputs/dead-strip-attributes2.objtxt b/test/core/Inputs/dead-strip-attributes2.objtxt
deleted file mode 100644
index 3dd55c46cd92..000000000000
--- a/test/core/Inputs/dead-strip-attributes2.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-defined-atoms:
- - name: _foo3
- dead-strip: always
diff --git a/test/core/Inputs/dead-strip-basic.objtxt b/test/core/Inputs/dead-strip-basic.objtxt
deleted file mode 100644
index 05cb81bbcf94..000000000000
--- a/test/core/Inputs/dead-strip-basic.objtxt
+++ /dev/null
@@ -1,9 +0,0 @@
----
-defined-atoms:
- - name: mydead2
- scope: global
- type: data
-
- - name: bar
- scope: global
- type: data
diff --git a/test/core/Inputs/dead-strip-basic2.objtxt b/test/core/Inputs/dead-strip-basic2.objtxt
deleted file mode 100644
index 6b0b01aef642..000000000000
--- a/test/core/Inputs/dead-strip-basic2.objtxt
+++ /dev/null
@@ -1,8 +0,0 @@
----
-defined-atoms:
- - name: baz
- scope: global
- type: code
-
- - name: mydead3
- type: code
diff --git a/test/core/Inputs/dead-strip-globals.objtxt b/test/core/Inputs/dead-strip-globals.objtxt
deleted file mode 100644
index fbf2ba6d1da3..000000000000
--- a/test/core/Inputs/dead-strip-globals.objtxt
+++ /dev/null
@@ -1,9 +0,0 @@
----
-defined-atoms:
- - name: myglobal2
- scope: global
- type: data
-
- - name: bar
- scope: hidden
- type: data
diff --git a/test/core/Inputs/dead-strip-globals2.objtxt b/test/core/Inputs/dead-strip-globals2.objtxt
deleted file mode 100644
index a314bbe5ae41..000000000000
--- a/test/core/Inputs/dead-strip-globals2.objtxt
+++ /dev/null
@@ -1,8 +0,0 @@
----
-defined-atoms:
- - name: baz
- scope: hidden
- type: code
-
- - name: mydead
- type: code
diff --git a/test/core/Inputs/error-duplicate-absolutes.objtxt b/test/core/Inputs/error-duplicate-absolutes.objtxt
deleted file mode 100644
index 2b99aa37848a..000000000000
--- a/test/core/Inputs/error-duplicate-absolutes.objtxt
+++ /dev/null
@@ -1,5 +0,0 @@
----
-absolute-atoms:
- - name: absatom
- value: 0
- scope: global
diff --git a/test/core/Inputs/gnulinkonce-rearrange-resolve.objtxt b/test/core/Inputs/gnulinkonce-rearrange-resolve.objtxt
deleted file mode 100644
index e1fa42a24a52..000000000000
--- a/test/core/Inputs/gnulinkonce-rearrange-resolve.objtxt
+++ /dev/null
@@ -1,26 +0,0 @@
----
-defined-atoms:
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
diff --git a/test/core/Inputs/gnulinkonce-remaining-undef.objtxt b/test/core/Inputs/gnulinkonce-remaining-undef.objtxt
deleted file mode 100644
index 02903a6b7bc5..000000000000
--- a/test/core/Inputs/gnulinkonce-remaining-undef.objtxt
+++ /dev/null
@@ -1,34 +0,0 @@
----
-defined-atoms:
- - name: anotherfunction
- scope: global
- type: data
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: f3
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: f3
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
diff --git a/test/core/Inputs/gnulinkonce-remaining-undef2.objtxt b/test/core/Inputs/gnulinkonce-remaining-undef2.objtxt
deleted file mode 100644
index 4991476c621c..000000000000
--- a/test/core/Inputs/gnulinkonce-remaining-undef2.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-undefined-atoms:
- - name: f3
- can-be-null: never
diff --git a/test/core/Inputs/gnulinkonce-resolve.objtxt b/test/core/Inputs/gnulinkonce-resolve.objtxt
deleted file mode 100644
index f4beb37fee2a..000000000000
--- a/test/core/Inputs/gnulinkonce-resolve.objtxt
+++ /dev/null
@@ -1,25 +0,0 @@
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
diff --git a/test/core/Inputs/gnulinkonce-simple.objtxt b/test/core/Inputs/gnulinkonce-simple.objtxt
deleted file mode 100644
index 807f0d35802b..000000000000
--- a/test/core/Inputs/gnulinkonce-simple.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-undefined-atoms:
- - name: f1
- can-be-null: never
diff --git a/test/core/Inputs/inline-coalesce.objtxt b/test/core/Inputs/inline-coalesce.objtxt
deleted file mode 100644
index 2eddee647c14..000000000000
--- a/test/core/Inputs/inline-coalesce.objtxt
+++ /dev/null
@@ -1,6 +0,0 @@
----
-defined-atoms:
- - name: _inlineFunc
- scope: global
- type: code
- merge: as-weak
diff --git a/test/core/Inputs/inline-coalesce2.objtxt b/test/core/Inputs/inline-coalesce2.objtxt
deleted file mode 100644
index 2eddee647c14..000000000000
--- a/test/core/Inputs/inline-coalesce2.objtxt
+++ /dev/null
@@ -1,6 +0,0 @@
----
-defined-atoms:
- - name: _inlineFunc
- scope: global
- type: code
- merge: as-weak
diff --git a/test/core/Inputs/multiple-def-error.objtxt b/test/core/Inputs/multiple-def-error.objtxt
deleted file mode 100644
index 8a1dcdb9c37f..000000000000
--- a/test/core/Inputs/multiple-def-error.objtxt
+++ /dev/null
@@ -1,5 +0,0 @@
----
-defined-atoms:
- - name: _foo
- scope: global
- type: data
diff --git a/test/core/Inputs/sectiongroup-deadstrip.objtxt b/test/core/Inputs/sectiongroup-deadstrip.objtxt
deleted file mode 100644
index 392f7ee96898..000000000000
--- a/test/core/Inputs/sectiongroup-deadstrip.objtxt
+++ /dev/null
@@ -1,3 +0,0 @@
-undefined-atoms:
- - name: f1
- can-be-null: never
diff --git a/test/core/Inputs/sectiongroup-gnulinkonce-error.objtxt b/test/core/Inputs/sectiongroup-gnulinkonce-error.objtxt
deleted file mode 100644
index a365d37b66b5..000000000000
--- a/test/core/Inputs/sectiongroup-gnulinkonce-error.objtxt
+++ /dev/null
@@ -1,26 +0,0 @@
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
diff --git a/test/core/Inputs/sectiongroup-rearrange-resolve.objtxt b/test/core/Inputs/sectiongroup-rearrange-resolve.objtxt
deleted file mode 100644
index bcefee646ef4..000000000000
--- a/test/core/Inputs/sectiongroup-rearrange-resolve.objtxt
+++ /dev/null
@@ -1,25 +0,0 @@
-defined-atoms:
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
diff --git a/test/core/Inputs/sectiongroup-remaining-undef.objtxt b/test/core/Inputs/sectiongroup-remaining-undef.objtxt
deleted file mode 100644
index 07c7af5dc67c..000000000000
--- a/test/core/Inputs/sectiongroup-remaining-undef.objtxt
+++ /dev/null
@@ -1,34 +0,0 @@
----
-defined-atoms:
- - name: anotherfunction
- scope: global
- type: data
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: f3
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: f3
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
diff --git a/test/core/Inputs/sectiongroup-remaining-undef2.objtxt b/test/core/Inputs/sectiongroup-remaining-undef2.objtxt
deleted file mode 100644
index 4991476c621c..000000000000
--- a/test/core/Inputs/sectiongroup-remaining-undef2.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-undefined-atoms:
- - name: f3
- can-be-null: never
diff --git a/test/core/Inputs/sectiongroup-resolve.objtxt b/test/core/Inputs/sectiongroup-resolve.objtxt
deleted file mode 100644
index a047ad33fe9c..000000000000
--- a/test/core/Inputs/sectiongroup-resolve.objtxt
+++ /dev/null
@@ -1,26 +0,0 @@
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
diff --git a/test/core/Inputs/sectiongroup-simple.objtxt b/test/core/Inputs/sectiongroup-simple.objtxt
deleted file mode 100644
index 807f0d35802b..000000000000
--- a/test/core/Inputs/sectiongroup-simple.objtxt
+++ /dev/null
@@ -1,4 +0,0 @@
----
-undefined-atoms:
- - name: f1
- can-be-null: never
diff --git a/test/core/Inputs/shared-library-coalesce.objtxt b/test/core/Inputs/shared-library-coalesce.objtxt
deleted file mode 100644
index 57cdfe662d4c..000000000000
--- a/test/core/Inputs/shared-library-coalesce.objtxt
+++ /dev/null
@@ -1,28 +0,0 @@
----
-shared-library-atoms:
- - name: foo2
- load-name: libc.so
-
- - name: foo3
- load-name: libc.so
-
- - name: bar2
- load-name: libc.so
- can-be-null: at-runtime
-
- - name: bar3
- load-name: libc.so
- can-be-null: at-runtime
-
- - name: mismatchNull1
- load-name: libc.so
-
- - name: mismatchNull2
- load-name: libc.so
- can-be-null: at-runtime
-
- - name: mismatchload1
- load-name: libb.so
-
- - name: mismatchload2
- load-name: liba.so
diff --git a/test/core/Inputs/tent-merge.objtxt b/test/core/Inputs/tent-merge.objtxt
deleted file mode 100644
index 90db8fd1f446..000000000000
--- a/test/core/Inputs/tent-merge.objtxt
+++ /dev/null
@@ -1,6 +0,0 @@
----
-defined-atoms:
- - name: _foo
- scope: global
- type: data
- content: [ 00, 00, 00, 00 ]
diff --git a/test/core/Inputs/undef-coalesce-error.objtxt b/test/core/Inputs/undef-coalesce-error.objtxt
deleted file mode 100644
index f493f00bdf1a..000000000000
--- a/test/core/Inputs/undef-coalesce-error.objtxt
+++ /dev/null
@@ -1,8 +0,0 @@
----
-defined-atoms:
- - name: bar
- type: code
-
-undefined-atoms:
- - name: malloc
- - name: myfunc
diff --git a/test/core/Inputs/undef-coalesce-error2.objtxt b/test/core/Inputs/undef-coalesce-error2.objtxt
deleted file mode 100644
index 88d736fc2111..000000000000
--- a/test/core/Inputs/undef-coalesce-error2.objtxt
+++ /dev/null
@@ -1,8 +0,0 @@
----
-defined-atoms:
- - name: myfunc
- scope: global
- type: code
-
-undefined-atoms:
- - name: free
diff --git a/test/core/Inputs/undef-coalesce.objtxt b/test/core/Inputs/undef-coalesce.objtxt
deleted file mode 100644
index f493f00bdf1a..000000000000
--- a/test/core/Inputs/undef-coalesce.objtxt
+++ /dev/null
@@ -1,8 +0,0 @@
----
-defined-atoms:
- - name: bar
- type: code
-
-undefined-atoms:
- - name: malloc
- - name: myfunc
diff --git a/test/core/Inputs/undef-coalesce2.objtxt b/test/core/Inputs/undef-coalesce2.objtxt
deleted file mode 100644
index 88d736fc2111..000000000000
--- a/test/core/Inputs/undef-coalesce2.objtxt
+++ /dev/null
@@ -1,8 +0,0 @@
----
-defined-atoms:
- - name: myfunc
- scope: global
- type: code
-
-undefined-atoms:
- - name: free
diff --git a/test/core/Inputs/undef-fallback.objtxt b/test/core/Inputs/undef-fallback.objtxt
deleted file mode 100644
index c392731805cd..000000000000
--- a/test/core/Inputs/undef-fallback.objtxt
+++ /dev/null
@@ -1,7 +0,0 @@
-defined-atoms:
- - name: fallback1
-
-undefined-atoms:
- - name: def1
- fallback:
- name: fallback3
diff --git a/test/core/Inputs/undef-weak-coalesce.objtxt b/test/core/Inputs/undef-weak-coalesce.objtxt
deleted file mode 100644
index 7a5e20fad097..000000000000
--- a/test/core/Inputs/undef-weak-coalesce.objtxt
+++ /dev/null
@@ -1,20 +0,0 @@
----
-undefined-atoms:
- - name: bar1
- can-be-null: never
- - name: bar2
- can-be-null: at-runtime
- - name: bar3
- can-be-null: at-buildtime
- - name: bar4
- can-be-null: at-runtime
- - name: bar5
- can-be-null: at-buildtime
- - name: bar6
- can-be-null: never
- - name: bar7
- can-be-null: at-buildtime
- - name: bar8
- can-be-null: never
- - name: bar9
- can-be-null: at-runtime
diff --git a/test/core/Inputs/weak-coalesce.objtxt b/test/core/Inputs/weak-coalesce.objtxt
deleted file mode 100644
index 8a1dcdb9c37f..000000000000
--- a/test/core/Inputs/weak-coalesce.objtxt
+++ /dev/null
@@ -1,5 +0,0 @@
----
-defined-atoms:
- - name: _foo
- scope: global
- type: data
diff --git a/test/core/Inputs/weak-coalesce2.objtxt b/test/core/Inputs/weak-coalesce2.objtxt
deleted file mode 100644
index 1039b309f8a4..000000000000
--- a/test/core/Inputs/weak-coalesce2.objtxt
+++ /dev/null
@@ -1,6 +0,0 @@
----
-defined-atoms:
- - name: _foo
- merge: as-weak
- scope: global
- type: data
diff --git a/test/core/absolute-basic.objtxt b/test/core/absolute-basic.objtxt
deleted file mode 100644
index edfbe8629b0d..000000000000
--- a/test/core/absolute-basic.objtxt
+++ /dev/null
@@ -1,23 +0,0 @@
-# RUN: lld -core --dead-strip %s | FileCheck %s
-
-#
-# Test that absolute symbols are parsed and preserved
-#
-
----
-absolute-atoms:
- - name: putchar
- value: 0xFFFF0040
-
- - name: reset
- value: 0xFFFF0080
-
-...
-
-
-# CHECK: absolute-atoms:
-# CHECK: name: putchar
-# CHECK: value: 0x00000000FFFF0040
-# CHECK: name: reset
-# CHECK: value: 0x00000000FFFF0080
-# CHECK: ...
diff --git a/test/core/absolute-local.objtxt b/test/core/absolute-local.objtxt
deleted file mode 100644
index 1ba4c7f04326..000000000000
--- a/test/core/absolute-local.objtxt
+++ /dev/null
@@ -1,25 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that absolute symbols with local scope do not cause name conflict
-#
----
-absolute-atoms:
- - name: putchar
- ref-name: pc1
- value: 0xFFFF0040
- scope: static
-
- - name: putchar
- ref-name: pc2
- value: 0xFFFF0040
- scope: static
-...
-
-# CHECK: ---
-# CHECK: absolute-atoms:
-# CHECK: - name: putchar
-# CHECK: value: 0x00000000FFFF0040
-# CHECK: - name: putchar
-# CHECK: value: 0x00000000FFFF0040
-# CHECK: ...
diff --git a/test/core/archive-basic.objtxt b/test/core/archive-basic.objtxt
deleted file mode 100644
index 205e0a5034e5..000000000000
--- a/test/core/archive-basic.objtxt
+++ /dev/null
@@ -1,23 +0,0 @@
-# RUN: lld -core %s %p/Inputs/archive-basic.objtxt | FileCheck %s
-
-#
-# Tests archives in YAML. Tests that an undefined in a regular file will load
-# all atoms in select archive members.
-#
-
---- !native
-defined-atoms:
- - name: foo
- type: code
-
-undefined-atoms:
- - name: bar
-
-...
-
-# CHECK: name: foo
-# CHECK-NOT: undefined-atoms:
-# CHECK: name: bar
-# CHECK: name: bar2
-# CHECK-NOT: name: baz
-# CHECK: ...
diff --git a/test/core/archive-chain.objtxt b/test/core/archive-chain.objtxt
deleted file mode 100644
index 35417f0bdb68..000000000000
--- a/test/core/archive-chain.objtxt
+++ /dev/null
@@ -1,23 +0,0 @@
-# RUN: lld -core %s %p/Inputs/archive-chain.objtxt %p/Inputs/archive-chain2.objtxt | FileCheck %s
-
-#
-# Tests that an undefine in one archive can force a load from another archive.
-#
-
---- !native
-defined-atoms:
- - name: foo
- type: code
-
-undefined-atoms:
- - name: bar1
-...
-
-# CHECK: name: foo
-# CHECK: name: bar1
-# CHECK: name: bar1b
-# CHECK-NOT: name: bar2
-# CHECK: name: baz1
-# CHECK: name: baz1b
-# CHECK-NOT: name: baz2
-# CHECK: ...
diff --git a/test/core/archive-tentdef-search.objtxt b/test/core/archive-tentdef-search.objtxt
deleted file mode 100644
index 230ab0bfd0de..000000000000
--- a/test/core/archive-tentdef-search.objtxt
+++ /dev/null
@@ -1,30 +0,0 @@
-# RUN: lld -core %s %p/Inputs/archive-tentdef-search.objtxt | FileCheck -check-prefix=CHK1 %s
-# RUN: lld -core --commons-search-archives %s %p/Inputs/archive-tentdef-search.objtxt | FileCheck -check-prefix=CHK2 %s
-
-#
-# Tests that -commons-search-archives cause core linker to look for overrides
-# of tentative definition in archives, and that not using that option
-# does not search.
-#
-
---- !native
-defined-atoms:
- - name: foo
- type: code
-
- - name: bar
- scope: global
- type: zero-fill
- merge: as-tentative
-...
-
-# CHK1: name: foo
-# CHK1: name: bar
-# CHK1: merge: as-tentative
-# CHK1: ...
-
-# CHK2: name: foo
-# CHK2: name: bar
-# CHK2-NOT: merge: as-tentative
-# CHK2: name: bar2
-# CHK2: ...
diff --git a/test/core/associates.objtxt b/test/core/associates.objtxt
deleted file mode 100644
index 5c711c97f9fa..000000000000
--- a/test/core/associates.objtxt
+++ /dev/null
@@ -1,21 +0,0 @@
-# RUN: lld -core %s %p/Inputs/associates.objtxt | FileCheck %s
-
----
-defined-atoms:
- - name: f1
- merge: as-weak
- scope: global
- references:
- - kind: associate
- target: f2
- - name: f2
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: f1
-# CHECK: scope: global
-# CHECK: references:
-# CHECK: - kind: associate
-# CHECK: target: f2
-# CHECK: - name: f2
-# CHECK-NOT: - name: f2
diff --git a/test/core/auto-hide-coalesce.objtxt b/test/core/auto-hide-coalesce.objtxt
deleted file mode 100644
index 63c54951150e..000000000000
--- a/test/core/auto-hide-coalesce.objtxt
+++ /dev/null
@@ -1,39 +0,0 @@
-# RUN: lld -core %s %p/Inputs/auto-hide-coalesce.objtxt | FileCheck %s
-
-#
-# Tests auto-hide bit during coalescing
-#
-
----
-defined-atoms:
- - name: _inlineFunc1
- scope: global
- type: code
- merge: as-weak
-
- - name: _inlineFunc2
- scope: global
- type: code
- merge: as-weak
-
- - name: _inlineFunc3
- scope: global
- type: code
- merge: as-addressed-weak
-
- - name: _inlineFunc4
- scope: global
- type: code
- merge: as-addressed-weak
-...
-
-
-# CHECK: name: _inlineFunc1
-# CHECK: merge: as-weak
-# CHECK: name: _inlineFunc3
-# CHECK: merge: as-addressed-weak
-# CHECK: name: _inlineFunc4
-# CHECK: merge: as-addressed-weak
-# CHECK: name: _inlineFunc2
-# CHECK: merge: as-addressed-weak
-# CHECK: ...
diff --git a/test/core/code-model-attributes.objtxt b/test/core/code-model-attributes.objtxt
deleted file mode 100644
index 9bb4a01bd1a7..000000000000
--- a/test/core/code-model-attributes.objtxt
+++ /dev/null
@@ -1,33 +0,0 @@
-# RUN: lld -core %s %p/Inputs/code-model-attributes.objtxt \
-# RUN: %p/Inputs/code-model-attributes2.objtxt \
-# RUN: %p/Inputs/code-model-attributes3.objtxt \
-# RUN: %p/Inputs/code-model-attributes4.objtxt \
-# RUN: %p/Inputs/code-model-attributes5.objtxt | FileCheck %s
-#
-# Test that code model attributes are preserved
-#
-
----
-defined-atoms:
- - name: _def
-...
-
-# CHECK: name: _def
-# CHECK-NOT: code-model: mips-pic
-# CHECK-NOT: code-model: mips-micro
-# CHECK-NOT: code-model: mips-micro-pic
-# CHECK-NOT: code-model: mips-16
-# CHECK: name: _none
-# CHECK-NOT: code-model: mips-pic
-# CHECK-NOT: code-model: mips-micro
-# CHECK-NOT: code-model: mips-micro-pic
-# CHECK-NOT: code-model: mips-16
-# CHECK: name: _mips_pic
-# CHECK: code-model: mips-pic
-# CHECK: name: _mips_micro
-# CHECK: code-model: mips-micro
-# CHECK: name: _mips_micro_pic
-# CHECK: code-model: mips-micro-pic
-# CHECK: name: _mips_16
-# CHECK: code-model: mips-16
-# CHECK: ...
diff --git a/test/core/constants-coalesce.objtxt b/test/core/constants-coalesce.objtxt
deleted file mode 100644
index 1a9f1013e6ec..000000000000
--- a/test/core/constants-coalesce.objtxt
+++ /dev/null
@@ -1,42 +0,0 @@
-# RUN: lld -core %s %p/Inputs/constants-coalesce.objtxt \
-# RUN: %p/Inputs/constants-coalesce2.objtxt | FileCheck %s
-
-#
-# Test that duplicate merge-by-content anonymous constants are coalesced
-# and non-mergable duplicate constants are not coalesced.
-#
-
----
-defined-atoms:
- - ref-name: L4-byte
- type: constant
- merge: by-content
- content: [ 01, 02, 03, 04 ]
-
- - ref-name: L8-byte
- type: constant
- merge: by-content
- content: [ 01, 23, 45, 67, 89, AB, CD, EF ]
-
- - ref-name: L1
- type: constant
- content: [ 01, 02 ]
-...
-
-# CHECK-NOT: name:
-# CHECK: type: constant
-# CHECK: content: [ 01, 02, 03, 04 ]
-# CHECK: merge: by-content
-# CHECK: type: constant
-# CHECK: content: [ 01, 23, 45, 67, 89, AB, CD, EF ]
-# CHECK: merge: by-content
-# CHECK: type: constant
-# CHECK: content: [ 01, 02 ]
-# CHECK: type: constant
-# CHECK: content: [ 01, 02 ]
-# CHECK: type: constant
-# CHECK: content: [ 01, 02, 03 ]
-# CHECK: merge: by-content
-# CHECK: ...
-
-
diff --git a/test/core/cstring-coalesce.objtxt b/test/core/cstring-coalesce.objtxt
deleted file mode 100644
index 4d32c00daf82..000000000000
--- a/test/core/cstring-coalesce.objtxt
+++ /dev/null
@@ -1,29 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that duplicate c-strings are coalesced
-#
-
----
-defined-atoms:
- - ref-name: L0
- type: c-string
- merge: by-content
- content: [ 68, 65, 6c, 6c, 6f, 00 ]
-
- - ref-name: L1
- type: c-string
- merge: by-content
- content: [ 74, 68, 65, 72, 65, 00 ]
-...
-
-# CHECK-NOT: name:
-# CHECK: type: c-string
-# CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ]
-# CHECK: merge: by-content
-# CHECK: type: c-string
-# CHECK: content: [ 74, 68, 65, 72, 65, 00 ]
-# CHECK: merge: by-content
-# CHECK: ...
-
-
diff --git a/test/core/custom-section-coalesce.objtxt b/test/core/custom-section-coalesce.objtxt
deleted file mode 100644
index fcf04845a7dd..000000000000
--- a/test/core/custom-section-coalesce.objtxt
+++ /dev/null
@@ -1,50 +0,0 @@
-# RUN: lld -core %s %p/Inputs/custom-section-coalesce.objtxt \
-# RUN: %p/Inputs/custom-section-coalesce2.objtxt | FileCheck %s
-
-#
-# Test that custom sections are preserved when duplicate merge-by-content
-# constants are coalesced.
-#
-
----
-defined-atoms:
- - ref-name: L1
- type: constant
- merge: by-content
- content: [ 01, 02, 03, 04 ]
- section-choice: custom-required
- section-name: .mysection
-
- - ref-name: L2
- type: constant
- merge: by-content
- content: [ 05, 06, 07, 08 ]
- section-choice: custom-required
- section-name: .mysection
-
- - ref-name: L3
- type: constant
- merge: by-content
- content: [ 01, 02, 03, 04 ]
-...
-
-
-# CHECK:defined-atoms:
-# CHECK: - type: constant
-# CHECK: content: [ 01, 02, 03, 04 ]
-# CHECK: merge: by-content
-# CHECK: section-choice: custom-required
-# CHECK: section-name: .mysection
-# CHECK: - type: constant
-# CHECK: content: [ 05, 06, 07, 08 ]
-# CHECK: merge: by-content
-# CHECK: section-choice: custom-required
-# CHECK: section-name: .mysection
-# CHECK: - type: constant
-# CHECK: content: [ 01, 02, 03, 04 ]
-# CHECK: merge: by-content
-# CHECK: - type: constant
-# CHECK: content: [ 01, 02, 03, 04 ]
-# CHECK: merge: by-content
-# CHECK: section-choice: custom-required
-# CHECK: section-name: .mysection2
diff --git a/test/core/custom-section.objtxt b/test/core/custom-section.objtxt
deleted file mode 100644
index ce305e9af38e..000000000000
--- a/test/core/custom-section.objtxt
+++ /dev/null
@@ -1,34 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that custom sections are preserved
-#
-
----
-defined-atoms:
- - name: _foo1
- scope: global
- section-choice: content
-
- - name: _foo2
- scope: global
- section-choice: custom
- section-name: __foozle
-
- - name: _foo3
- scope: global
- section-choice: custom-required
- section-name: __boozle
-
-...
-
-
-# CHECK: name: _foo1
-# CHECK-NOT: section-name:
-# CHECK: name: _foo2
-# CHECK: section-choice: custom
-# CHECK: section-name: __foozle
-# CHECK: name: _foo3
-# CHECK: section-choice: custom-required
-# CHECK: section-name: __boozle
-# CHECK: ...
diff --git a/test/core/dead-strip-attributes.objtxt b/test/core/dead-strip-attributes.objtxt
deleted file mode 100644
index 2a1c97627d2b..000000000000
--- a/test/core/dead-strip-attributes.objtxt
+++ /dev/null
@@ -1,22 +0,0 @@
-# RUN: lld -core %s %p/Inputs/dead-strip-attributes.objtxt \
-# RUN: %p/Inputs/dead-strip-attributes2.objtxt | FileCheck %s
-
-#
-# Test that dead strip attributes are preserved
-#
-
----
-defined-atoms:
- - name: _foo1
- dead-strip: normal
-...
-
-
-# CHECK: name: _foo1
-# CHECK-NOT: dead-strip: never
-# CHECK-NOT: dead-strip: always
-# CHECK: name: _foo2
-# CHECK: dead-strip: never
-# CHECK: name: _foo3
-# CHECK: dead-strip: always
-# CHECK: ...
diff --git a/test/core/dead-strip-basic.objtxt b/test/core/dead-strip-basic.objtxt
deleted file mode 100644
index 1607ea9e5b89..000000000000
--- a/test/core/dead-strip-basic.objtxt
+++ /dev/null
@@ -1,45 +0,0 @@
-# RUN: lld -core --dead-strip %s %p/Inputs/dead-strip-basic.objtxt %p/Inputs/dead-strip-basic2.objtxt | FileCheck -check-prefix=CHK1 %s
-# RUN: lld -core %s %p/Inputs/dead-strip-basic.objtxt %p/Inputs/dead-strip-basic2.objtxt | FileCheck -check-prefix=CHK2 %s
-
-#
-# Test that -dead-strip removes unreachable code and data
-# and that not using that option leaves them.
-#
-
----
-defined-atoms:
- - name: entry
- dead-strip: never
- references:
- - offset: 1
- kind: pcrel32
- target: bar
- - offset: 6
- kind: pcrel32
- target: baz
-
- - name: mydead1
- scope: global
-
-undefined-atoms:
- - name: bar
-
- - name: baz
-...
-
-
-# CHK1: name: entry
-# CHK1-NOT: name: mydead1
-# CHK1: name: bar
-# CHK1-NOT: name: mydead2
-# CHK1: name: baz
-# CHK1-NOT: name: mydead3
-# CHK1: ...
-
-# CHK2: name: entry
-# CHK2: name: mydead1
-# CHK2: name: mydead2
-# CHK2: name: bar
-# CHK2: name: baz
-# CHK2: name: mydead3
-# CHK2: ...
diff --git a/test/core/dead-strip-globals.objtxt b/test/core/dead-strip-globals.objtxt
deleted file mode 100644
index e4b11b16f690..000000000000
--- a/test/core/dead-strip-globals.objtxt
+++ /dev/null
@@ -1,43 +0,0 @@
-# RUN: lld -core --dead-strip --keep-globals %s %p/Inputs/dead-strip-globals.objtxt %p/Inputs/dead-strip-globals2.objtxt | FileCheck -check-prefix=CHK1 %s
-# RUN: lld -core --dead-strip %s %p/Inputs/dead-strip-globals.objtxt %p/Inputs/dead-strip-globals2.objtxt | FileCheck -check-prefix=CHK2 %s
-
-#
-# Test that -keep-globals prevents -dead-strip from removing globals.
-#
-
----
-defined-atoms:
- - name: entry
- dead-strip: never
- references:
- - offset: 1
- kind: pcrel32
- target: bar
- - offset: 6
- kind: pcrel32
- target: baz
-
- - name: myglobal1
- scope: global
-
-undefined-atoms:
- - name: bar
- - name: baz
-...
-
-
-# CHK1: name: entry
-# CHK1: name: myglobal1
-# CHK1: name: myglobal2
-# CHK1: name: bar
-# CHK1: name: baz
-# CHK1-NOT: name: mydead
-# CHK1: ...
-
-# CHK2: name: entry
-# CHK2-NOT: name: myglobal1
-# CHK2-NOT: name: myglobal2
-# CHK2: name: bar
-# CHK2: name: baz
-# CHK2-NOT: name: mydead
-# CHK2: ...
diff --git a/test/core/dead-strip-reverse.objtxt b/test/core/dead-strip-reverse.objtxt
deleted file mode 100644
index f471bebcdf4e..000000000000
--- a/test/core/dead-strip-reverse.objtxt
+++ /dev/null
@@ -1,25 +0,0 @@
-# RUN: lld -core --dead-strip %s | FileCheck -check-prefix=CHECK1 %s
-# RUN: lld -core %s | FileCheck -check-prefix=CHECK2 %s
-
----
-defined-atoms:
- - name: entry
- dead-strip: never
- scope: global
- references:
- - kind: layout-after
- offset: 0
- target: def
- - name: def
- scope: global
- - name: dead
- scope: global
-...
-
-# CHECK1: name: entry
-# CHECK1: name: def
-# CHECK1-NOT: name: dead
-
-# CHECK2: name: entry
-# CHECK2: name: def
-# CHECK2: name: dead
diff --git a/test/core/error-atom-attribute.objtxt b/test/core/error-atom-attribute.objtxt
deleted file mode 100644
index 6643aba29eea..000000000000
--- a/test/core/error-atom-attribute.objtxt
+++ /dev/null
@@ -1,19 +0,0 @@
-# RUN: not lld -core %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that unknown atom attribute produces a readable error.
-#
-
----
-defined-atoms:
- - name: entry
- scope: hidden
- foobar: true
- dead-strip: never
-
-...
-
-
-# CHECK: error: unknown key 'foobar'
-# CHECK: foobar
diff --git a/test/core/error-atom-content-byte-value.objtxt b/test/core/error-atom-content-byte-value.objtxt
deleted file mode 100644
index 6e675576461a..000000000000
--- a/test/core/error-atom-content-byte-value.objtxt
+++ /dev/null
@@ -1,18 +0,0 @@
-# RUN: not lld -core %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that an invalid hex byte produces a readable error.
-#
-
----
-defined-atoms:
- - name: entry
- scope: hidden
- content: [ A5, 00, 4G, 1F ]
-
-...
-
-
-# CHECK: error: invalid two-digit-hex number
-# CHECK: 4G
diff --git a/test/core/error-atom-content-bytes.objtxt b/test/core/error-atom-content-bytes.objtxt
deleted file mode 100644
index a8a82b2b45e1..000000000000
--- a/test/core/error-atom-content-bytes.objtxt
+++ /dev/null
@@ -1,19 +0,0 @@
-# RUN: not lld -core %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that an out of range byte value produces a readable error.
-#
-
----
-defined-atoms:
- - name: entry
- scope: hidden
- content: [ A5, 1234, 00, 4F ]
-
-...
-
-
-# CHECK: error: out of range two-digit-hex number
-# CHECK: 1234
-
diff --git a/test/core/error-atom-type.objtxt b/test/core/error-atom-type.objtxt
deleted file mode 100644
index b0943f8e2749..000000000000
--- a/test/core/error-atom-type.objtxt
+++ /dev/null
@@ -1,19 +0,0 @@
-# RUN: not lld -core %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that an unknown content type produces a readable error.
-#
-
----
-defined-atoms:
- - name: entry
- scope: hidden
- type: superluminal
- dead-strip: never
-
-...
-
-
-# CHECK: error: unknown enumerated scalar
-# CHECK: superluminal
diff --git a/test/core/error-atom-undefined-wrong-attribue.objtxt b/test/core/error-atom-undefined-wrong-attribue.objtxt
deleted file mode 100644
index 5cdd8519c804..000000000000
--- a/test/core/error-atom-undefined-wrong-attribue.objtxt
+++ /dev/null
@@ -1,17 +0,0 @@
-# RUN: not lld -core %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that a defined attribute on an undefined atom produces a readable error.
-#
-
----
-undefined-atoms:
- - name: foo
- type: code
-
-...
-
-
-# CHECK: error: unknown key 'type'
-
diff --git a/test/core/error-duplicate-absolutes.objtxt b/test/core/error-duplicate-absolutes.objtxt
deleted file mode 100644
index 513a2f494485..000000000000
--- a/test/core/error-duplicate-absolutes.objtxt
+++ /dev/null
@@ -1,19 +0,0 @@
-# RUN: not lld -core %s %p/Inputs/error-duplicate-absolutes.objtxt 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that duplicate absolute atoms produces a readable error.
-#
-
----
-absolute-atoms:
- - name: absatom
- value: 0
- scope: global
-undefined-atoms:
- - name: undefatom
-...
-
-
-# CHECK: SymbolTable: error while merging absatom
-# CHECK: LLVM ERROR: duplicate symbol error
diff --git a/test/core/error-file-attribute.objtxt b/test/core/error-file-attribute.objtxt
deleted file mode 100644
index d8393dc5e400..000000000000
--- a/test/core/error-file-attribute.objtxt
+++ /dev/null
@@ -1,17 +0,0 @@
-# RUN: not lld -core %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that unknown file attribute produces a readable error.
-#
-
----
-aardvark: true
-defined-atoms:
- - name: entry
- scope: hidden
-
-...
-
-
-# CHECK: error: unknown key 'aardvark'
diff --git a/test/core/error-fixup-attribute.objtxt b/test/core/error-fixup-attribute.objtxt
deleted file mode 100644
index 025783a04427..000000000000
--- a/test/core/error-fixup-attribute.objtxt
+++ /dev/null
@@ -1,21 +0,0 @@
-# RUN: not lld -core %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that unknown fixup attribute produces a readable error.
-#
-
----
-defined-atoms:
- - name: entry
- scope: hidden
- references:
- - offset: 3
- kind: pcrel32
- weasel: bar
- addend: 100
-
-...
-
-
-# CHECK: error: unknown key 'weasel'
diff --git a/test/core/error-fixup-target.objtxt b/test/core/error-fixup-target.objtxt
deleted file mode 100644
index 0e20d1636f50..000000000000
--- a/test/core/error-fixup-target.objtxt
+++ /dev/null
@@ -1,26 +0,0 @@
-# RUN: not lld -core %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-#
-# Test that unbindable target name produces a readable error.
-#
-
----
-defined-atoms:
- - name: entry
- scope: hidden
- references:
- - offset: 3
- kind: pcrel32
- target: bar
- - offset: 5
- kind: pcrel32
- target: baz
-
-undefined-atoms:
- - name: bar
-
-...
-
-
-# CHECK: error: no such atom name: baz
diff --git a/test/core/fixups-addend.objtxt b/test/core/fixups-addend.objtxt
deleted file mode 100644
index d976150459c9..000000000000
--- a/test/core/fixups-addend.objtxt
+++ /dev/null
@@ -1,50 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test addends in references
-#
-
----
-defined-atoms:
- - name: foo
- type: code
- content: [ 48, 8D, 3D, 00, 00, 00, 00,
- 48, 8D, 3D, 00, 00, 00, 00 ]
- references:
- - offset: 3
- kind: pcrel32
- target: bar
- addend: 100
- - offset: 10
- kind: pcrel32
- target: bar
- addend: -50
-
- - name: func
- type: code
- content: [ 48, 8D, 3D, 00, 00, 00, 00,
- 48, 8D, 3D, 00, 00, 00, 00 ]
- references:
- - offset: 3
- kind: pcrel32
- target: bar
- addend: 8000000000
- - offset: 10
- kind: pcrel32
- target: bar
- addend: -50
-
-undefined-atoms:
- - name: bar
-
-
-...
-
-# CHECK: name: foo
-# CHECK: references:
-# CHECK: addend: 100
-# CHECK: addend: -50
-# CHECK: name: func
-# CHECK: references:
-# CHECK: addend: 8000000000
-# CHECK: addend: -50
diff --git a/test/core/fixups-dup-named.objtxt b/test/core/fixups-dup-named.objtxt
deleted file mode 100644
index 1c57cd73bf09..000000000000
--- a/test/core/fixups-dup-named.objtxt
+++ /dev/null
@@ -1,31 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test references referencing multiple atoms that have the same name
-#
-
----
-defined-atoms:
- - name: foo
- type: code
- content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ]
- references:
- - offset: 1
- kind: pcrel32
- target: bar_1
- - offset: 6
- kind: pcrel32
- target: bar_2
-
- - name: bar
- ref-name: bar_1
- scope: static
-
- - name: bar
- ref-name: bar_2
- scope: static
-
-
-...
-
-# CHECK: ...
diff --git a/test/core/fixups-named.objtxt b/test/core/fixups-named.objtxt
deleted file mode 100644
index 1427a9b705d1..000000000000
--- a/test/core/fixups-named.objtxt
+++ /dev/null
@@ -1,36 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test references to simple named atoms
-#
-
----
-defined-atoms:
- - name: foo
- type: code
- content: [ E8, 00, 00, 00, 00,
- E8, 00, 00, 00, 00 ]
- references:
- - offset: 1
- kind: pcrel32
- target: bar
- - offset: 6
- kind: pcrel32
- target: baz
-
- - name: baz
- scope: static
- type: code
-
-undefined-atoms:
- - name: bar
-
-
-...
-
-# CHECK: name: foo
-# CHECK: references:
-# CHECK: target: bar
-# CHECK: target: baz
-# CHECK: ...
-
diff --git a/test/core/fixups-unnamed.objtxt b/test/core/fixups-unnamed.objtxt
deleted file mode 100644
index 88afb6a447a2..000000000000
--- a/test/core/fixups-unnamed.objtxt
+++ /dev/null
@@ -1,40 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test references to unnamed atoms
-#
-
----
-defined-atoms:
- - name: foo
- type: code
- content: [ 48, 8D, 3D, 00, 00, 00, 00,
- 48, 8D, 3D, 00, 00, 00, 00 ]
- references:
- - offset: 3
- kind: pcrel32
- target: LC1
- - offset: 10
- kind: pcrel32
- target: LC2
-
-
- - ref-name: LC1
- type: c-string
- merge: by-content
- content: [ 68, 65, 6c, 6c, 6f, 00 ]
-
- - ref-name: LC2
- type: c-string
- merge: by-content
- content: [ 74, 68, 65, 72, 65, 00 ]
-
-
-...
-
-# CHECK: name: foo
-# CHECK: references:
-# CHECK: offset: 3
-# CHECK: offset: 10
-# CHECK: ref-name:
-# CHECK: ref-name:
diff --git a/test/core/gnulinkonce-rearrange-resolve.objtxt b/test/core/gnulinkonce-rearrange-resolve.objtxt
deleted file mode 100644
index b3df078d2314..000000000000
--- a/test/core/gnulinkonce-rearrange-resolve.objtxt
+++ /dev/null
@@ -1,53 +0,0 @@
-# RUN: lld -core %s %p/Inputs/gnulinkonce-rearrange-resolve.objtxt | FileCheck %s
-
-#
-# Test that gnu linkonce sections are parsed and the first section selected for symbol
-# resolution
-#
-
----
-defined-atoms:
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: g1
-# CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-# CHECK: type: gnu-linkonce
-# CHECK: references:
-# CHECK: - kind: group-child
-# CHECK: target: f1
-# CHECK: - kind: group-child
-# CHECK: target: f2
-# CHECK: - kind: group-child
-# CHECK: target: [[CHILD:[a-zA-Z\.0-9_]+]]
-# CHECK: - kind: group-child
-# CHECK: target: d1
-# CHECK: - name: f1
-# CHECK: - name: f2
-# CHECK: - name: g1
-# CHECK: ref-name: [[CHILD]]
-# CHECK: - name: d1
diff --git a/test/core/gnulinkonce-remaining-undef.objtxt b/test/core/gnulinkonce-remaining-undef.objtxt
deleted file mode 100644
index 5fe0ab55b5c0..000000000000
--- a/test/core/gnulinkonce-remaining-undef.objtxt
+++ /dev/null
@@ -1,43 +0,0 @@
-# RUN: lld -core %s %p/Inputs/gnulinkonce-remaining-undef.objtxt \
-# RUN: %p/Inputs/gnulinkonce-remaining-undef2.objtxt | FileCheck %s
-
-#
-# Test that gnu linkonce sections are parsed and the first section selected for
-# symbol resolution. The second file which has the same gnu linkonce section has
-# a unresolved undefined symbol. lets make sure that the symbol is kept around
-# in the final link and remains undefined.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: undefined-atoms:
-#CHECK: - name: f3
diff --git a/test/core/gnulinkonce-resolve.objtxt b/test/core/gnulinkonce-resolve.objtxt
deleted file mode 100644
index e926c39bd0e1..000000000000
--- a/test/core/gnulinkonce-resolve.objtxt
+++ /dev/null
@@ -1,63 +0,0 @@
-# RUN: lld -core %s %p/Inputs/gnulinkonce-resolve.objtxt | FileCheck %s
-
-#
-# Test that gnu linkonce sections are parsed and the first section selected for symbol
-# resolution
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: gnu-linkonce
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
diff --git a/test/core/gnulinkonce-simple.objtxt b/test/core/gnulinkonce-simple.objtxt
deleted file mode 100644
index 0576e5f75d7f..000000000000
--- a/test/core/gnulinkonce-simple.objtxt
+++ /dev/null
@@ -1,76 +0,0 @@
-# RUN: lld -core %s %p/Inputs/gnulinkonce-simple.objtxt | FileCheck %s
-
-#
-# Test that gnu linkonce sections are parsed properly when there is a reference to a
-# atom from outside the gnu linkonce section.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- references:
- - kind: layout-after
- target: anotherfunction
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: d1
- - kind: group-child
- target: g1
- - name: anotherfunction
- scope: global
- type: data
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: gnu-linkonce
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: references:
-#CHECK: - kind: layout-after
-#CHECK: offset: 0
-#CHECK: target: anotherfunction
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
diff --git a/test/core/inline-coalesce.objtxt b/test/core/inline-coalesce.objtxt
deleted file mode 100644
index 5ddc9b2624b5..000000000000
--- a/test/core/inline-coalesce.objtxt
+++ /dev/null
@@ -1,19 +0,0 @@
-# RUN: lld -core %s %p/Inputs/inline-coalesce.objtxt %p/Inputs/inline-coalesce2.objtxt | FileCheck %s
-
-#
-# Test that non-inlined inlined functions are silently coalesced
-#
-
----
-defined-atoms:
- - name: _inlineFunc
- scope: global
- type: code
- merge: as-weak
-...
-
-
-# CHECK: name: _inlineFunc
-# CHECK: merge: as-weak
-# CHECK-NOT: name: _inlineFunc
-# CHECK: ...
diff --git a/test/core/multiple-def-error.objtxt b/test/core/multiple-def-error.objtxt
deleted file mode 100644
index 5765814e53ee..000000000000
--- a/test/core/multiple-def-error.objtxt
+++ /dev/null
@@ -1,14 +0,0 @@
-# RUN: not lld -core %s %p/Inputs/multiple-def-error.objtxt 2>&1 | FileCheck %s
-
-#
-# Test that multiple definitions cause an error
-#
-
-# CHECK: duplicate symbol
-
----
-defined-atoms:
- - name: _foo
- scope: global
- type: data
-...
diff --git a/test/core/permissions.objtxt b/test/core/permissions.objtxt
deleted file mode 100644
index af33ea65c455..000000000000
--- a/test/core/permissions.objtxt
+++ /dev/null
@@ -1,57 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test permissions for known content types are implicit, but can be overridden.
-#
----
-defined-atoms:
- - name: one
- type: code
-
- - name: two
- type: data
- permissions: rw-
-
- - name: three
- type: const-data
-
- - name: four
- type: unknown
-
- - name: oddCode
- type: code
- permissions: rwx
-
- - name: oddData
- type: data
- permissions: rwx
-
- - name: oddConstData
- type: const-data
- permissions: rw-
-
- - name: oddUnknown
- type: unknown
- permissions: rw-
-
-...
-
-# CHECK: ---
-# CHECK: defined-atoms:
-# CHECK: - name: one
-# CHECK-NOT: permissions:
-# CHECK: - name: two
-# CHECK-NOT: permissions:
-# CHECK: - name: three
-# CHECK-NOT: permissions:
-# CHECK: - name: four
-# CHECK-NOT: permissions:
-# CHECK: - name: oddCode
-# CHECK: permissions: rwx
-# CHECK: - name: oddData
-# CHECK: permissions: rwx
-# CHECK: - name: oddConstData
-# CHECK: permissions: rw-
-# CHECK: - name: oddUnknown
-# CHECK: permissions: rw-
-# CHECK: ...
diff --git a/test/core/sectiongroup-deadstrip.objtxt b/test/core/sectiongroup-deadstrip.objtxt
deleted file mode 100644
index 5055c6e06b69..000000000000
--- a/test/core/sectiongroup-deadstrip.objtxt
+++ /dev/null
@@ -1,84 +0,0 @@
-# Test for section group members be preserved even if there is a
-# reference to only one functions in the group.
-# RUN: lld -core --dead-strip %s %p/Inputs/sectiongroup-deadstrip.objtxt | FileCheck %s
-
-#
-# Test that section groups are parsed properly when there is a reference to a
-# group atom from outside a group.
-#
-
----
-defined-atoms:
- - name: entry
- dead-strip: never
- references:
- - offset: 1
- kind: pcrel32
- target: d1
- - name: f1
- scope: global
- type: code
- references:
- - kind: layout-after
- target: anotherfunction
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: d1
- - kind: group-child
- target: g1
- - name: anotherfunction
- scope: global
- type: data
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: group-comdat
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: references:
-#CHECK: - kind: layout-after
-#CHECK: offset: 0
-#CHECK: target: anotherfunction
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
diff --git a/test/core/sectiongroup-gnulinkonce-error.objtxt b/test/core/sectiongroup-gnulinkonce-error.objtxt
deleted file mode 100644
index 1b8617067839..000000000000
--- a/test/core/sectiongroup-gnulinkonce-error.objtxt
+++ /dev/null
@@ -1,38 +0,0 @@
-# RUN: not lld -core %s %p/Inputs/sectiongroup-gnulinkonce-error.objtxt 2>&1 | FileCheck %s
-
-#
-# Test that section groups/gnu linkonce sections are parsed and a merge error
-# is displayed at the time of symbol resolution.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: SymbolTable: error while merging g1
-#CHECK: LLVM ERROR: duplicate symbol error
-
diff --git a/test/core/sectiongroup-rearrange-resolve.objtxt b/test/core/sectiongroup-rearrange-resolve.objtxt
deleted file mode 100644
index f191113718df..000000000000
--- a/test/core/sectiongroup-rearrange-resolve.objtxt
+++ /dev/null
@@ -1,53 +0,0 @@
-# RUN: lld -core %s %p/Inputs/sectiongroup-rearrange-resolve.objtxt | FileCheck %s
-
-#
-# Test that section groups are parsed and the first group selected for symbol
-# resolution
-#
-
----
-defined-atoms:
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: g1
-# CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-# CHECK: type: group-comdat
-# CHECK: references:
-# CHECK: - kind: group-child
-# CHECK: target: f1
-# CHECK: - kind: group-child
-# CHECK: target: f2
-# CHECK: - kind: group-child
-# CHECK: target: [[CHILD:[a-zA-Z\.0-9_]+]]
-# CHECK: - kind: group-child
-# CHECK: target: d1
-# CHECK: - name: f1
-# CHECK: - name: f2
-# CHECK: - name: g1
-# CHECK: ref-name: [[CHILD]]
-# CHECK: - name: d1
diff --git a/test/core/sectiongroup-remaining-undef.objtxt b/test/core/sectiongroup-remaining-undef.objtxt
deleted file mode 100644
index 0a292040a354..000000000000
--- a/test/core/sectiongroup-remaining-undef.objtxt
+++ /dev/null
@@ -1,42 +0,0 @@
-# RUN: lld -core %s %p/Inputs/sectiongroup-remaining-undef.objtxt %p/Inputs/sectiongroup-remaining-undef2.objtxt | FileCheck %s
-
-#
-# Test that section groups are parsed and the first group selected for symbol
-# resolution. The second file which has the same group has a unresolved
-# undefined symbol. lets make sure that the symbol is kept around in the final
-# link and remains undefined.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: undefined-atoms:
-#CHECK: - name: f3
diff --git a/test/core/sectiongroup-resolve.objtxt b/test/core/sectiongroup-resolve.objtxt
deleted file mode 100644
index 52197dbb4e91..000000000000
--- a/test/core/sectiongroup-resolve.objtxt
+++ /dev/null
@@ -1,64 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that section groups are parsed and the first group selected for symbol
-# resolution
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: group-comdat
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: ...
diff --git a/test/core/sectiongroup-simple.objtxt b/test/core/sectiongroup-simple.objtxt
deleted file mode 100644
index d81b1a1b313c..000000000000
--- a/test/core/sectiongroup-simple.objtxt
+++ /dev/null
@@ -1,76 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that section groups are parsed properly when there is a reference to a
-# group atom from outside a group.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- references:
- - kind: layout-after
- target: anotherfunction
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: d1
- - kind: group-child
- target: g1
- - name: anotherfunction
- scope: global
- type: data
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: group-comdat
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: references:
-#CHECK: - kind: layout-after
-#CHECK: offset: 0
-#CHECK: target: anotherfunction
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
diff --git a/test/core/shared-library-basic.objtxt b/test/core/shared-library-basic.objtxt
deleted file mode 100644
index 61445e7431fd..000000000000
--- a/test/core/shared-library-basic.objtxt
+++ /dev/null
@@ -1,40 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that shared-library symbols are parsed and preserved
-#
-
----
-shared-library-atoms:
- - name: malloc
- load-name: libc.so
- type: code
- size: 0
-
- - name: free
- load-name: libc.so
-
- - name: fast_malloc
- load-name: libc.so
- can-be-null: at-runtime
-
- - name: stdout
- load-name: libc.so
- type: data
- size: 8
-
-...
-
-# CHECK: shared-library-atoms:
-# CHECK: name: malloc
-# CHECK: load-name: libc.so
-# CHECK: name: free
-# CHECK: load-name: libc.so
-# CHECK: name: fast_malloc
-# CHECK: load-name: libc.so
-# CHECK: can-be-null: at-runtime
-# CHECK: name: stdout
-# CHECK: load-name: libc.so
-# CHECK: type: data
-# CHECK: size: 8
-# CHECK: ...
diff --git a/test/core/shared-library-coalesce.objtxt b/test/core/shared-library-coalesce.objtxt
deleted file mode 100644
index 1cd25d18f881..000000000000
--- a/test/core/shared-library-coalesce.objtxt
+++ /dev/null
@@ -1,55 +0,0 @@
-# RUN: lld -core %s %p/Inputs/shared-library-coalesce.objtxt | FileCheck %s
-
-#
-# Test that shared library symbols preserve their attributes and merge properly
-#
-
----
-shared-library-atoms:
- - name: foo1
- load-name: libc.so
-
- - name: foo2
- load-name: libc.so
-
- - name: bar1
- load-name: libc.so
- can-be-null: at-runtime
-
- - name: bar2
- load-name: libc.so
- can-be-null: at-runtime
-
- - name: mismatchNull1
- load-name: libc.so
- can-be-null: at-runtime
-
- - name: mismatchNull2
- load-name: libc.so
-
- - name: mismatchload1
- load-name: liba.so
-
- - name: mismatchload2
- load-name: libb.so
-
-...
-
-# CHECK: name: foo1
-# CHECK: name: foo2
-# CHECK: name: bar1
-# CHECK: can-be-null: at-runtime
-# CHECK: name: bar2
-# CHECK: can-be-null: at-runtime
-# CHECK: name: mismatchNull1
-# CHECK: can-be-null: at-runtime
-# CHECK: name: mismatchNull2
-# CHECK-NOT: can-be-null: at-runtime
-# CHECK: name: mismatchload1
-# CHECK: load-name: liba.so
-# CHECK: name: mismatchload2
-# CHECK: load-name: libb.so
-# CHECK: name: foo3
-# CHECK: name: bar3
-# CHECK: can-be-null: at-runtime
-# CHECK: ...
diff --git a/test/core/tent-merge.objtxt b/test/core/tent-merge.objtxt
deleted file mode 100644
index 8997be2833b1..000000000000
--- a/test/core/tent-merge.objtxt
+++ /dev/null
@@ -1,19 +0,0 @@
-# RUN: lld -core %s %p/Inputs/tent-merge.objtxt | FileCheck %s
-
-#
-# Test that a tentative definition and a regular global are merged into
-# one regular global
-#
-
----
-defined-atoms:
- - name: _foo
- merge: as-tentative
- scope: global
- type: zero-fill
- size: 4
-...
-
-
-# CHECK: name: _foo
-# CHECK-NOT: merge: as-tentative
diff --git a/test/core/undef-coalesce-error.objtxt b/test/core/undef-coalesce-error.objtxt
deleted file mode 100644
index f0ad8d8555ab..000000000000
--- a/test/core/undef-coalesce-error.objtxt
+++ /dev/null
@@ -1,31 +0,0 @@
-# RUN: not lld -core --undefines-are-errors %s %p/Inputs/undef-coalesce-error.objtxt %p/Inputs/undef-coalesce-error2.objtxt 2> %t.err
-# RUN: FileCheck -check-prefix=CHECKERR %s < %t.err
-# RUN: lld -core %s %p/Inputs/undef-coalesce-error.objtxt %p/Inputs/undef-coalesce-error2.objtxt | FileCheck %s
-
-#
-# Test that -undefines-are-errors triggers and error
-# and that not using that option results in undefined atoms.
-#
-
----
-defined-atoms:
- - name: foo
- type: code
-
-undefined-atoms:
- - name: malloc
- - name: free
-...
-
-# CHECKERR: free
-# CHECKERR: malloc
-# CHECKERR: symbol(s) not found
-
-# CHECK: defined-atoms:
-# CHECK: name: foo
-# CHECK: name: bar
-# CHECK: name: myfunc
-# CHECK: undefined-atoms:
-# CHECK: name: malloc
-# CHECK: name: free
-# CHECK: ...
diff --git a/test/core/undef-coalesce.objtxt b/test/core/undef-coalesce.objtxt
deleted file mode 100644
index b0ea2b928977..000000000000
--- a/test/core/undef-coalesce.objtxt
+++ /dev/null
@@ -1,26 +0,0 @@
-# RUN: lld -core %s %p/Inputs/undef-coalesce.objtxt %p/Inputs/undef-coalesce2.objtxt | FileCheck %s
-
-#
-# Test that undefined symbols are coalesced with other undefined symbols
-# and definitions override them.
-#
-
----
-defined-atoms:
- - name: foo
- type: code
-
-undefined-atoms:
- - name: malloc
- - name: free
-...
-
-# CHECK: defined-atoms:
-# CHECK: name: foo
-# CHECK: name: bar
-# CHECK: name: myfunc
-# CHECK: scope: global
-# CHECK: undefined-atoms:
-# CHECK: name: malloc
-# CHECK: name: free
-# CHECK: ...
diff --git a/test/core/undef-fallback.objtxt b/test/core/undef-fallback.objtxt
deleted file mode 100644
index aef7b6d7c26f..000000000000
--- a/test/core/undef-fallback.objtxt
+++ /dev/null
@@ -1,29 +0,0 @@
-# RUN: lld -core %p/undef-fallback.objtxt %p/Inputs/undef-fallback.objtxt | FileCheck %s
-
-# Test that fallback atoms can be parsed by YAML reader and processed by the
-# core linker.
-
----
-defined-atoms:
- - name: def1
- scope: global
-
-undefined-atoms:
- - name: undef1
- fallback:
- name: fallback1
- - name: undef2
- fallback:
- name: fallback2
-...
-
-# CHECK: defined-atoms:
-# CHECK-NEXT: - name: def1
-# CHECK-NEXT: scope: global
-# CHECK-NEXT: - name: fallback1
-# CHECK-NEXT: ref-name: fallback1
-# CHECK-NEXT: undefined-atoms:
-# CHECK-NEXT: - name: fallback1
-# CHECK-NEXT: - name: fallback2
-
-# CHECK-NOT: - name: fallback3
diff --git a/test/core/undef-weak-coalesce.objtxt b/test/core/undef-weak-coalesce.objtxt
deleted file mode 100644
index d46a05cb95cf..000000000000
--- a/test/core/undef-weak-coalesce.objtxt
+++ /dev/null
@@ -1,52 +0,0 @@
-# RUN: lld -core %s %p/Inputs/undef-weak-coalesce.objtxt| FileCheck %s
-
-#
-# Test that undefined symbols preserve their attributes and merge properly
-#
-
----
-undefined-atoms:
- - name: regular_func
- can-be-null: never
- - name: weak_import_func
- can-be-null: at-runtime
- - name: weak_func
- can-be-null: at-buildtime
- - name: bar1
- can-be-null: never
- - name: bar2
- can-be-null: at-runtime
- - name: bar3
- can-be-null: at-buildtime
- - name: bar4
- can-be-null: never
- - name: bar5
- can-be-null: at-runtime
- - name: bar6
- can-be-null: at-buildtime
- - name: bar7
- can-be-null: never
- - name: bar8
- can-be-null: at-runtime
- - name: bar9
- can-be-null: at-buildtime
-...
-
-# CHECK: - name: regular_func
-# CHECK-NEXT: - name: weak_import_func
-# CHECK-NEXT: can-be-null: at-runtime
-# CHECK-NEXT: - name: weak_func
-# CHECK-NEXT: can-be-null: at-buildtime
-# CHECK-NEXT: - name: bar1
-# CHECK-NEXT: - name: bar2
-# CHECK-NEXT: can-be-null: at-runtime
-# CHECK-NEXT: - name: bar3
-# CHECK-NEXT: can-be-null: at-buildtime
-# CHECK-NEXT: - name: bar4
-# CHECK-NEXT: - name: bar5
-# CHECK-NEXT: can-be-null: at-runtime
-# CHECK-NEXT: - name: bar7
-# CHECK-NEXT: - name: bar6
-# CHECK-NEXT: - name: bar8
-# CHECK-NEXT: - name: bar9
-# CHECK-NEXT: can-be-null: at-runtime
diff --git a/test/core/weak-coalesce.objtxt b/test/core/weak-coalesce.objtxt
deleted file mode 100644
index e92aedeb4f15..000000000000
--- a/test/core/weak-coalesce.objtxt
+++ /dev/null
@@ -1,16 +0,0 @@
-# RUN: lld -core %s %p/Inputs/weak-coalesce.objtxt \
-# RUN: %p/Inputs/weak-coalesce2.objtxt | FileCheck %s
-
----
-defined-atoms:
- - name: _foo
- merge: as-weak
- scope: global
- type: data
-...
-
-
-# CHECK: name: _foo
-# CHECK-NOT: merge: as-weak
-# CHECK-NOT: name: _foo
-# CHECK: ...
diff --git a/test/darwin/cmdline-objc_gc.objtxt b/test/darwin/cmdline-objc_gc.objtxt
new file mode 100644
index 000000000000..b5225a1d184e
--- /dev/null
+++ b/test/darwin/cmdline-objc_gc.objtxt
@@ -0,0 +1,15 @@
+# RUN: not lld -flavor darwin -arch x86_64 -objc_gc %s 2>&1 | FileCheck %s
+#
+# Test that the -objc_gc is rejected.
+#
+
+# CHECK: error: -objc_gc is not supported
+
+--- !native
+defined-atoms:
+ - name: _main
+ type: code
+ scope: global
+ content: [ 0x90 ]
+
+...
diff --git a/test/darwin/cmdline-objc_gc_compaction.objtxt b/test/darwin/cmdline-objc_gc_compaction.objtxt
new file mode 100644
index 000000000000..acf7183d95eb
--- /dev/null
+++ b/test/darwin/cmdline-objc_gc_compaction.objtxt
@@ -0,0 +1,15 @@
+# RUN: not lld -flavor darwin -arch x86_64 -objc_gc_compaction %s 2>&1 | FileCheck %s
+#
+# Test that the -objc_gc_compaction is rejected.
+#
+
+# CHECK: error: -objc_gc_compaction is not supported
+
+--- !native
+defined-atoms:
+ - name: _main
+ type: code
+ scope: global
+ content: [ 0x90 ]
+
+...
diff --git a/test/darwin/cmdline-objc_gc_only.objtxt b/test/darwin/cmdline-objc_gc_only.objtxt
new file mode 100644
index 000000000000..db1cef94ea59
--- /dev/null
+++ b/test/darwin/cmdline-objc_gc_only.objtxt
@@ -0,0 +1,15 @@
+# RUN: not lld -flavor darwin -arch x86_64 -objc_gc_only %s 2>&1 | FileCheck %s
+#
+# Test that the -objc_gc_only is rejected.
+#
+
+# CHECK: error: -objc_gc_only is not supported
+
+--- !native
+defined-atoms:
+ - name: _main
+ type: code
+ scope: global
+ content: [ 0x90 ]
+
+...
diff --git a/test/lit.cfg b/test/lit.cfg
index d8794039f152..5ff4fc4edcf2 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -177,6 +177,9 @@ for pattern in tool_patterns:
tool_path = llvm_tools_dir + '/' + tool_name
config.substitutions.append((pattern, tool_pipe + tool_path))
+# Add site-specific substitutions.
+config.substitutions.append( ('%python', config.python_executable) )
+
###
# When running under valgrind, we mangle '-vg' onto the end of the triple so we
@@ -185,9 +188,13 @@ if lit_config.useValgrind:
config.target_triple += '-vg'
# Shell execution
-if platform.system() not in ['Windows'] or lit_config.getBashPath() != '':
+if execute_external:
config.available_features.add('shell')
+# zlib compression library
+if config.have_zlib == "1":
+ config.available_features.add("zlib")
+
# Running on Darwin OS
if platform.system() in ['Darwin']:
config.available_features.add('system-linker-mach-o')
@@ -196,6 +203,10 @@ if platform.system() in ['Darwin']:
if platform.system() in ['FreeBSD', 'Linux']:
config.available_features.add('system-linker-elf')
+# Set if host-cxxabi's demangler can handle target's symbols.
+if platform.system() not in ['Windows']:
+ config.available_features.add('demangler')
+
# llvm-config knows whether it is compiled with asserts (and)
# whether we are operating in release/debug mode.
import subprocess
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index 0eeb889d1b20..5293f24c1251 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -1,5 +1,5 @@
-## Autogenerated by LLVM/lld configuration.
-# Do not edit!
+@LIT_SITE_CFG_IN_HEADER@
+
config.llvm_src_root = "@LLVM_SOURCE_DIR@"
config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
@@ -8,6 +8,7 @@ config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
config.lld_obj_root = "@LLD_BINARY_DIR@"
config.target_triple = "@TARGET_TRIPLE@"
config.python_executable = "@PYTHON_EXECUTABLE@"
+config.have_zlib = "@HAVE_LIBZ@"
# Support substitution of the tools and libs dirs with user parameters. This is
# used when we can't determine the tool dir at configuration time.
diff --git a/test/mach-o/Inputs/no-version-min-load-command-object.yaml b/test/mach-o/Inputs/no-version-min-load-command-object.yaml
new file mode 100644
index 000000000000..35f83c6fd087
--- /dev/null
+++ b/test/mach-o/Inputs/no-version-min-load-command-object.yaml
@@ -0,0 +1,22 @@
+
+# This object file has no version min and so will prevent any -r link from emitting
+# a version min.
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _main2
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
diff --git a/test/mach-o/Inputs/swift-version-1.yaml b/test/mach-o/Inputs/swift-version-1.yaml
new file mode 100644
index 000000000000..1337d7a13245
--- /dev/null
+++ b/test/mach-o/Inputs/swift-version-1.yaml
@@ -0,0 +1,18 @@
+# RUN: not lld -flavor darwin -arch x86_64 -r %s %p/Inputs/hello-world-x86_64.yaml 2>&1 | FileCheck %s
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 ]
+...
diff --git a/test/mach-o/arm-interworking-movw.yaml b/test/mach-o/arm-interworking-movw.yaml
index 7e4a2e00ae6e..0423ed644576 100644
--- a/test/mach-o/arm-interworking-movw.yaml
+++ b/test/mach-o/arm-interworking-movw.yaml
@@ -2,7 +2,7 @@
# RUN: lld -flavor darwin -arch armv7 -r -print_atoms %s -o %t | FileCheck %s
# RUN: lld -flavor darwin -arch armv7 -dylib -print_atoms %t -o %t2 \
# RUN: %p/Inputs/libSystem.yaml -sectalign __TEXT __text 0x1000 | FileCheck %s
-# RUN: llvm-objdump -d -macho %t2 | FileCheck -check-prefix=CODE %s
+# RUN: llvm-objdump -d -macho -no-symbolic-operands %t2 | FileCheck -check-prefix=CODE %s
#
# Test thumb and arm branches round trip through -r.
# Test movw/movt pairs have low bit set properly for thumb vs arm.
@@ -330,7 +330,7 @@ local-symbols:
# CODE-NEXT: movt r0, #0
# CODE-NEXT: movw r1, #1
# CODE-NEXT: movt r1, #0
-# CODE-NEXT: movw r2, _a2
+# CODE-NEXT: movw r2, #4174
# CODE-NEXT: movt r2, #0
# CODE-NEXT: movw r3, #42
# CODE-NEXT: movt r3, #0
@@ -341,7 +341,7 @@ local-symbols:
# CODE-NEXT: movt r0, #0
# CODE-NEXT: movw r1, #65495
# CODE-NEXT: movt r1, #65535
-# CODE-NEXT: movw r2, _a2
+# CODE-NEXT: movw r2, #4174
# CODE-NEXT: movt r2, #0
# CODE-NEXT: movw r3, #0
# CODE-NEXT: movt r3, #0
diff --git a/test/mach-o/arm64-relocs-errors-delta64-offset.yaml b/test/mach-o/arm64-relocs-errors-delta64-offset.yaml
index 09c596124893..08e41bc65fff 100644
--- a/test/mach-o/arm64-relocs-errors-delta64-offset.yaml
+++ b/test/mach-o/arm64-relocs-errors-delta64-offset.yaml
@@ -24,7 +24,7 @@ sections:
section: __data
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x000000000001C348
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
diff --git a/test/mach-o/data-in-code-load-command.yaml b/test/mach-o/data-in-code-load-command.yaml
new file mode 100644
index 000000000000..604592afcd3f
--- /dev/null
+++ b/test/mach-o/data-in-code-load-command.yaml
@@ -0,0 +1,35 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -no_data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -data_in_code_info -no_data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -r && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -r -data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -r -no_data_in_code_info && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+# CHECK: Load command {{[0-9]*}}
+# CHECK: cmd LC_DATA_IN_CODE
+# CHECK: cmdsize 16
+# CHECK: dataoff
+# CHECK: datasize
+
+# NO_DATA_IN_CODE_INFO-NOT: LC_DATA_IN_CODE
diff --git a/test/mach-o/dead-strip-globals.yaml b/test/mach-o/dead-strip-globals.yaml
new file mode 100644
index 000000000000..df5ff73aa441
--- /dev/null
+++ b/test/mach-o/dead-strip-globals.yaml
@@ -0,0 +1,27 @@
+# RUN: lld -flavor darwin -arch x86_64 -dead_strip -export_dynamic %s -dylib %p/Inputs/libSystem.yaml -o %t.dylib -print_atoms | FileCheck -check-prefix=CHECK1 %s
+# RUN: lld -flavor darwin -arch x86_64 -export_dynamic -dead_strip %s -dylib %p/Inputs/libSystem.yaml -o %t.dylib -print_atoms | FileCheck -check-prefix=CHECK1 %s
+# RUN: lld -flavor darwin -arch x86_64 -dead_strip %s -dylib %p/Inputs/libSystem.yaml -o %t2.dylib -print_atoms | FileCheck -check-prefix=CHECK2 %s
+
+#
+# Test that -export_dynamic -dead-strip from removing globals.
+#
+
+---
+defined-atoms:
+ - name: def
+ scope: global
+ dead-strip: never
+ - name: dead
+ scope: global
+shared-library-atoms:
+ - name: dyld_stub_binder
+ load-name: /usr/lib/libSystem.B.dylib
+ type: unknown
+...
+
+# CHECK1: name: def
+# CHECK1: name: dead
+
+# CHECK2: name: def
+# CHECK2-NOT: name: dead
+
diff --git a/test/mach-o/dependency_info.yaml b/test/mach-o/dependency_info.yaml
index dcce4381dfd3..2ec59b8afebb 100644
--- a/test/mach-o/dependency_info.yaml
+++ b/test/mach-o/dependency_info.yaml
@@ -1,8 +1,3 @@
-# XFAIL: win32
-# This test fails on Windows because the linker would use '\' instead
-# of '/' as a path separator when concatenating path components.
-# So the output from the linker would be different.
-
# Test -dependency_info option
#
# RUN: lld -flavor darwin -arch x86_64 -test_file_usage \
@@ -14,11 +9,11 @@
# RUN: -F/Custom/Frameworks \
# RUN: -framework Bar \
# RUN: -framework Foo
-# RUN: python %p/Inputs/DependencyDump.py %t.info | FileCheck %s
+# RUN: %python %p/Inputs/DependencyDump.py %t.info | FileCheck %s
# CHECK: linker-vers: lld
-# CHECK: input-file: /Custom/Frameworks/Bar.framework/Bar
-# CHECK: not-found: /Custom/Frameworks/Foo.framework/Foo
-# CHECK: input-file: /System/Library/Frameworks/Foo.framework/Foo
+# CHECK: input-file: /Custom/Frameworks{{[/\\]}}Bar.framework{{[/\\]}}Bar
+# CHECK: not-found: /Custom/Frameworks{{[/\\]}}Foo.framework{{[/\\]}}Foo
+# CHECK: input-file: /System/Library/Frameworks{{[/\\]}}Foo.framework{{[/\\]}}Foo
# CHECK: output-file: a.out
diff --git a/test/mach-o/do-not-emit-unwind-fde-arm64.yaml b/test/mach-o/do-not-emit-unwind-fde-arm64.yaml
index d306419bc5f9..70f76b5246f1 100644
--- a/test/mach-o/do-not-emit-unwind-fde-arm64.yaml
+++ b/test/mach-o/do-not-emit-unwind-fde-arm64.yaml
@@ -74,7 +74,7 @@ sections:
address: 0x0000000000000050
content: [ 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
- 0x1E, 0x0B, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x1E, 0x07, 0x00, 0x9D, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x10, 0x0C, 0x1F, 0x00,
0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -142,8 +142,8 @@ page-size: 0x00000000
# CHECK: - ref-name: L{{[0-9]*}}
# CHECK: type: unwind-cfi
# CHECK: content: [ 1C, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 50, 4C,
-# CHECK: 52, 00, 01, 78, 1E, 0B, 00, ED, FF, FF, FF, FF,
-# CHECK: FF, FF, FF, 00, 10, 0C, 1F, 00 ]
+# CHECK: 52, 00, 01, 78, 1E, 07, 00, {{..}}, {{..}}, {{..}}, {{..}}, {{..}},
+# CHECK: {{..}}, {{..}}, {{..}}, 00, 10, 0C, 1F, 00 ]
# CHECK: - type: unwind-cfi
# CHECK: content: [ 24, 00, 00, 00, 24, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, 20, 00, 00, 00, 00, 00, 00, 00,
@@ -197,7 +197,7 @@ page-size: 0x00000000
# CODE: Contents of section __eh_frame:
# This is the CIE:
# CODE-NEXT: {{[0-9abcdef]*}} 1c000000 00000000 017a504c 52000178
-# CODE-NEXT: {{[0-9abcdef]*}} 1e0b00ed ffffffff ffffff00 100c1f00
+# CODE-NEXT: {{[0-9abcdef]*}} 1e0700bd ffffffff ffffff00 100c1f00
# This is the FDE:
# CODE-NEXT: {{[0-9abcdef]*}} 24000000 24000000 a8ffffff ffffffff
# This is the important offset for FDE->func ^~~~~~~~ ~~~~~~~~
diff --git a/test/mach-o/dso_handle.yaml b/test/mach-o/dso_handle.yaml
index d39d2c230806..400e2c899c90 100644
--- a/test/mach-o/dso_handle.yaml
+++ b/test/mach-o/dso_handle.yaml
@@ -28,7 +28,7 @@ sections:
section: __data
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000008
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
relocations:
diff --git a/test/mach-o/eh-frame-relocs-arm64.yaml b/test/mach-o/eh-frame-relocs-arm64.yaml
new file mode 100644
index 000000000000..6681ded79498
--- /dev/null
+++ b/test/mach-o/eh-frame-relocs-arm64.yaml
@@ -0,0 +1,318 @@
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
+# RUN: llvm-objdump -r -s -section="__eh_frame" -macho %t | FileCheck -check-prefix=CODE %s
+# RUN: llvm-objdump -r -s -section="__eh_frame" -macho %t2 | FileCheck -check-prefix=CODE %s
+
+
+--- !mach-o
+arch: arm64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ alignment: 4
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC0, 0x03, 0x5F, 0xD6, 0xC0, 0x03, 0x5F, 0xD6,
+ 0xC0, 0x03, 0x5F, 0xD6 ]
+ - segment: __TEXT
+ section: __gcc_except_tab
+ type: S_REGULAR
+ attributes: [ ]
+ address: 0x0000000000000014
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ - segment: __DATA
+ section: __data
+ type: S_REGULAR
+ attributes: [ ]
+ address: 0x000000000000001C
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+ - segment: __LD
+ section: __compact_unwind
+ type: S_REGULAR
+ attributes: [ ]
+ alignment: 8
+ address: 0x0000000000000020
+ content: [ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000020
+ type: ARM64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: false
+ symbol: 1
+ - offset: 0x00000000
+ type: ARM64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: false
+ symbol: 1
+ - segment: __TEXT
+ section: __eh_frame
+ type: S_COALESCED
+ attributes: [ ]
+ alignment: 8
+ address: 0x0000000000000060
+ content: [ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
+ 0x1E, 0x07, 0x9B, 0xED, 0xFF, 0xFF, 0xFF, 0x10,
+ 0x10, 0x0C, 0x1F, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0xDC, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0xCB, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x10, 0x9E,
+ 0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
+ 0x1E, 0x07, 0x9B, 0xA9, 0xFF, 0xFF, 0xFF, 0x10,
+ 0x10, 0x0C, 0x1F, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x83, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x10, 0x9E,
+ 0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x0000007D
+ type: ARM64_RELOC_SUBTRACTOR
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 6
+ - offset: 0x0000007D
+ type: ARM64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 3
+ - offset: 0x0000006C
+ type: ARM64_RELOC_SUBTRACTOR
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 6
+ - offset: 0x0000006C
+ type: ARM64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 8
+ - offset: 0x0000005B
+ type: ARM64_RELOC_POINTER_TO_GOT
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 10
+ - offset: 0x00000035
+ type: ARM64_RELOC_SUBTRACTOR
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 6
+ - offset: 0x00000035
+ type: ARM64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 2
+ - offset: 0x00000024
+ type: ARM64_RELOC_SUBTRACTOR
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 6
+ - offset: 0x00000024
+ type: ARM64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 7
+ - offset: 0x00000013
+ type: ARM64_RELOC_POINTER_TO_GOT
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 9
+local-symbols:
+ - name: ltmp0
+ type: N_SECT
+ sect: 1
+ value: 0x0000000000000000
+ - name: ltmp1
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000014
+ - name: _bar1
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000014
+ - name: _bar2
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000018
+ - name: ltmp12
+ type: N_SECT
+ sect: 3
+ value: 0x000000000000001C
+ - name: ltmp13
+ type: N_SECT
+ sect: 4
+ value: 0x0000000000000020
+ - name: ltmp16
+ type: N_SECT
+ sect: 5
+ value: 0x0000000000000060
+global-symbols:
+ - name: __Z3fooi
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000008
+ - name: __Z4foo2i
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x000000000000000C
+ - name: __gxx_personality_v0
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: __gxx_personality_v1
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000004
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000010
+ - name: _someData
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 3
+ value: 0x000000000000001C
+page-size: 0x00000000
+...
+
+# CHECK: --- !native
+# CHECK: path: '<linker-internal>'
+# CHECK: defined-atoms:
+# CHECK: - ref-name: L000
+# CHECK: type: unwind-cfi
+# CHECK: content: [ 18, 00, 00, 00, 00, 00, 00, 00, 03, 7A, 50, 4C,
+# CHECK: 52, 00, 01, 78, 1E, 07, 9B, {{..}}, {{..}}, {{..}}, {{..}}, 10,
+# CHECK: 10, 0C, 1F, 00 ]
+# CHECK: alignment: 8
+# CHECK: references:
+# CHECK: - kind: unwindCIEToPersonalityFunction
+# CHECK: offset: 19
+# CHECK: target: __gxx_personality_v0
+# CHECK: - type: unwind-cfi
+# CHECK: content: [ 28, 00, 00, 00, 20, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
+# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, 04, 00, 00, 00, 00, 00, 00, 00,
+# CHECK: 08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 0E, 10, 9E,
+# CHECK: 01, 9D, 02, 00, 00, 00, 00, 00 ]
+# CHECK: alignment: 4 mod 8
+# CHECK: references:
+# CHECK: - kind: negDelta32
+# CHECK: offset: 4
+# CHECK: target: L000
+# CHECK: - kind: unwindFDEToFunction
+# CHECK: offset: 8
+# CHECK: target: __Z3fooi
+# CHECK: - kind: unwindFDEToFunction
+# CHECK: offset: 25
+# CHECK: target: _bar1
+# CHECK: - ref-name: L001
+# CHECK: type: unwind-cfi
+# CHECK: content: [ 18, 00, 00, 00, 00, 00, 00, 00, 03, 7A, 50, 4C,
+# CHECK: 52, 00, 01, 78, 1E, 07, 9B, {{..}}, {{..}}, {{..}}, {{..}}, 10,
+# CHECK: 10, 0C, 1F, 00 ]
+# CHECK: alignment: 8
+# CHECK: references:
+# CHECK: - kind: unwindCIEToPersonalityFunction
+# CHECK: offset: 19
+# CHECK: target: __gxx_personality_v1
+# CHECK: - type: unwind-cfi
+# CHECK: content: [ 28, 00, 00, 00, 20, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
+# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, 04, 00, 00, 00, 00, 00, 00, 00,
+# CHECK: 08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 0E, 10, 9E,
+# CHECK: 01, 9D, 02, 00, 00, 00, 00, 00 ]
+# CHECK: alignment: 4 mod 8
+# CHECK: references:
+# CHECK: - kind: negDelta32
+# CHECK: offset: 4
+# CHECK: target: L001
+# CHECK: - kind: unwindFDEToFunction
+# CHECK: offset: 8
+# CHECK: target: __Z4foo2i
+# CHECK: - kind: unwindFDEToFunction
+# CHECK: offset: 25
+# CHECK: target: _bar2
+# CHECK: - name: _bar1
+# CHECK: type: unwind-lsda
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: - name: _bar2
+# CHECK: type: unwind-lsda
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: - name: _someData
+# CHECK: scope: global
+# CHECK: type: data
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: - name: __gxx_personality_v0
+# CHECK: scope: global
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: alignment: 4
+# CHECK: - name: __gxx_personality_v1
+# CHECK: scope: global
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: alignment: 4
+# CHECK: - name: __Z3fooi
+# CHECK: scope: global
+# CHECK: content: [ C0, 03, 5F, D6 ]
+# CHECK: alignment: 4
+# CHECK: - name: __Z4foo2i
+# CHECK: scope: global
+# CHECK: content: [ C0, 03, 5F, D6 ]
+# CHECK: alignment: 4
+# CHECK: - name: _main
+# CHECK: scope: global
+# CHECK: content: [ C0, 03, 5F, D6 ]
+# CHECK: alignment: 4
+# CHECK: ...
+
+# # Make sure we don't have any relocations in the __eh_frame section
+# CODE-NOT: RELOCATION RECORDS FOR [__eh_frame]
+
+# Also make sure the reloc for the CIE->personality function is the
+# correct offset
+# It should be the offset from the fixup location back to the address
+# of the function we are referencing
+# CODE: Contents of section __eh_frame:
+# This is the CIE:
+# CODE-NEXT: {{[0-9abcdef]*}} 18000000 00000000 037a504c 52000178
+# CODE-NEXT: {{[0-9abcdef]*}} 1e079bd1 ffffff10 100c1f00 28000000
+# This is the important offset for CIE->pfunc
+# ^~~~~~~~~
+# Then we have an FDE starting from 28000000 above
+# CODE-NEXT: {{[0-9abcdef]*}} 20000000 c8ffffff ffffffff 04000000
+# CODE-NEXT: {{[0-9abcdef]*}} 00000000 08c3ffff ffffffff ff0e109e
+# And a new CIE starts at this 00000018 right below here
+# CODE-NEXT: {{[0-9abcdef]*}} 019d0200 00000000 18000000 00000000
+# CODE-NEXT: {{[0-9abcdef]*}} 037a504c 52000178 1e079b8d ffffff10
+# This is the important offset for its CIE->pfunc ^~~~~~~~~ \ No newline at end of file
diff --git a/test/mach-o/error-simulator-vs-macosx.yaml b/test/mach-o/error-simulator-vs-macosx.yaml
new file mode 100644
index 000000000000..bd62db39fccb
--- /dev/null
+++ b/test/mach-o/error-simulator-vs-macosx.yaml
@@ -0,0 +1,30 @@
+# RUN: lld -flavor darwin -arch i386 -macosx_version_min 10.8 %s %p/Inputs/hello-world-x86.yaml -o %t && llvm-nm -m %t | FileCheck %s
+# RUN: not lld -flavor darwin -arch i386 -ios_simulator_version_min 5.0 %s %p/Inputs/hello-world-x86.yaml -o %t 2>&1 | FileCheck %s --check-prefix=ERROR
+#
+# Test that i386 can link with a macos version but gives an error with a simululator version.
+#
+
+--- !mach-o
+arch: x86
+OS: Mac OS X
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x90 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
+# CHECK: (undefined) external dyld_stub_binder (from libSystem)
+
+# ERROR: cannot be linked due to incompatible operating systems
diff --git a/test/mach-o/function-starts-load-command.yaml b/test/mach-o/function-starts-load-command.yaml
new file mode 100644
index 000000000000..9f251898f6e0
--- /dev/null
+++ b/test/mach-o/function-starts-load-command.yaml
@@ -0,0 +1,32 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -function_starts && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -no_function_starts && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -function_starts -no_function_starts && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+# CHECK: Load command {{[0-9]*}}
+# CHECK: cmd LC_FUNCTION_STARTS
+# CHECK: cmdsize 16
+# CHECK: dataoff
+# CHECK: datasize
+
+# NO_FUNCTION_STARTS-NOT: LC_FUNCTION_STARTS
diff --git a/test/mach-o/hello-world-x86_64.yaml b/test/mach-o/hello-world-x86_64.yaml
index 340ceefbe7cb..8803c4476c39 100644
--- a/test/mach-o/hello-world-x86_64.yaml
+++ b/test/mach-o/hello-world-x86_64.yaml
@@ -54,7 +54,7 @@ sections:
section: __compact_unwind
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000028
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
@@ -71,7 +71,7 @@ sections:
section: __eh_frame
type: S_COALESCED
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000048
content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
@@ -116,4 +116,5 @@ undefined-symbols:
# CHECK: (undefined) external ___stdoutp (from libSystem)
# CHECK: (undefined) external _fprintf (from libSystem)
# CHECK: (undefined) external dyld_stub_binder (from libSystem)
+# CHECK: {{[0-9a-f]+}} (__TEXT,__text) [referenced dynamically] external __mh_execute_header
# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
diff --git a/test/mach-o/interposing-section.yaml b/test/mach-o/interposing-section.yaml
index 76e33904d113..4f6bafc200fb 100644
--- a/test/mach-o/interposing-section.yaml
+++ b/test/mach-o/interposing-section.yaml
@@ -31,7 +31,7 @@ sections:
section: __interpose
type: S_INTERPOSING
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000010
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
diff --git a/test/mach-o/lazy-bind-x86_64.yaml b/test/mach-o/lazy-bind-x86_64.yaml
index 1b4699feed35..ee3e2278b15b 100644
--- a/test/mach-o/lazy-bind-x86_64.yaml
+++ b/test/mach-o/lazy-bind-x86_64.yaml
@@ -83,6 +83,17 @@ undefined-symbols:
# CHECK-HELPERS: 68 10 00 00 00 pushq $16
# CHECK-HELPERS: 68 20 00 00 00 pushq $32
+# Make sure the stub helper is correctly aligned
+# CHECK-DYLIBS: sectname __stub_helper
+# CHECK-DYLIBS-NEXT: segname __TEXT
+# CHECK-DYLIBS-NEXT: addr
+# CHECK-DYLIBS-NEXT: size
+# CHECK-DYLIBS-NEXT: offset
+# CHECK-DYLIBS-NEXT: align 2^2 (4)
+
+# Make sure the __nl_symbol_ptr section is used instea of __got as this is x86_64
+# CHECK-DYLIBS: sectname __nl_symbol_ptr
+# CHECK-DYLIBS-NEXT: segname __DATA
# CHECK-DYLIBS: cmd LC_LOAD_DYLIB
# CHECK-DYLIBS: name /usr/lib/libbar.dylib (offset 24)
diff --git a/test/mach-o/mach_header-cpusubtype.yaml b/test/mach-o/mach_header-cpusubtype.yaml
new file mode 100644
index 000000000000..fa9024f999db
--- /dev/null
+++ b/test/mach-o/mach_header-cpusubtype.yaml
@@ -0,0 +1,34 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.4 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_LIB64
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.5 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=LIB64
+# RUN: lld -flavor darwin -arch x86_64 -dylib -macosx_version_min 10.5 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=DYLIB
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: start
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000001
+
+...
+
+# NO_LIB64: MH_MAGIC_64 X86_64 ALL 0x00 EXECUTE
+# LIB64: MH_MAGIC_64 X86_64 ALL LIB64 EXECUTE
+# DYLIB: MH_MAGIC_64 X86_64 ALL 0x00 DYLIB
diff --git a/test/mach-o/mh_bundle_header.yaml b/test/mach-o/mh_bundle_header.yaml
index 558df2ca2e95..e440141c5689 100644
--- a/test/mach-o/mh_bundle_header.yaml
+++ b/test/mach-o/mh_bundle_header.yaml
@@ -1,5 +1,5 @@
-# RUN: lld -flavor darwin -arch x86_64 %s -bundle -o %t %p/Inputs/libSystem.yaml
-# RUN: llvm-nm -m -n %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 %s -bundle -o %t %p/Inputs/libSystem.yaml && llvm-nm -m -n %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 %s -bundle -dead_strip -o %t %p/Inputs/libSystem.yaml && llvm-nm -m -n %t | FileCheck %s
#
# Test that __mh_bundle_header symbol is available for bundles
#
@@ -19,7 +19,7 @@ sections:
section: __data
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000008
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
relocations:
@@ -39,6 +39,7 @@ global-symbols:
type: N_SECT
scope: [ N_EXT ]
sect: 1
+ desc: [ N_NO_DEAD_STRIP ]
value: 0x0000000000000000
undefined-symbols:
- name: __mh_bundle_header
@@ -49,5 +50,5 @@ undefined-symbols:
...
-# CHECK_NOT: __mh_bundle_header
+# CHECK: __mh_bundle_header
# CHECK: _foo
diff --git a/test/mach-o/mh_dylib_header.yaml b/test/mach-o/mh_dylib_header.yaml
index 07429b30c943..96b67aacae21 100644
--- a/test/mach-o/mh_dylib_header.yaml
+++ b/test/mach-o/mh_dylib_header.yaml
@@ -19,7 +19,7 @@ sections:
section: __data
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000008
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
relocations:
diff --git a/test/mach-o/objc-category-list-atom.yaml b/test/mach-o/objc-category-list-atom.yaml
new file mode 100644
index 000000000000..e06117124190
--- /dev/null
+++ b/test/mach-o/objc-category-list-atom.yaml
@@ -0,0 +1,70 @@
+# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %t -o %t2 | FileCheck %s
+
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_catlist
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ alignment: 8
+ address: 0x00000000000003F8
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000008
+ type: X86_64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 0
+ - offset: 0x00000000
+ type: X86_64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 1
+undefined-symbols:
+ - name: __category1
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: __category2
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+page-size: 0x00000000
+...
+
+# Make sure we atomize the category list section by pointer sized atoms.
+
+# CHECK: path: '<linker-internal>'
+# CHECK: defined-atoms:
+# CHECK: - type: objc-category-list
+# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+# CHECK: merge: by-content
+# CHECK: alignment: 8
+# CHECK: references:
+# CHECK: - kind: pointer64
+# CHECK: offset: 0
+# CHECK: target: __category2
+# CHECK: - type: objc-category-list
+# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+# CHECK: merge: by-content
+# CHECK: alignment: 8
+# CHECK: references:
+# CHECK: - kind: pointer64
+# CHECK: offset: 0
+# CHECK: target: __category1
+# CHECK: undefined-atoms:
+# CHECK: - name: __category1
+# CHECK: - name: __category2
+# CHECK: ...
diff --git a/test/mach-o/objc-image-info-host-vs-simulator.yaml b/test/mach-o/objc-image-info-host-vs-simulator.yaml
new file mode 100644
index 000000000000..f836a7423271
--- /dev/null
+++ b/test/mach-o/objc-image-info-host-vs-simulator.yaml
@@ -0,0 +1,23 @@
+# RUN: not lld -flavor darwin -arch x86_64 -r %s 2>&1 | FileCheck %s
+
+# The file is built for the host, but the objc image info flags are for
+# the simulator.
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 ]
+...
+
+# CHECK: {{.*}} cannot be linked. It contains ObjC built for the simulator while we are linking a non-simulator target \ No newline at end of file
diff --git a/test/mach-o/objc-image-info-invalid-size.yaml b/test/mach-o/objc-image-info-invalid-size.yaml
new file mode 100644
index 000000000000..47fce886f2cc
--- /dev/null
+++ b/test/mach-o/objc-image-info-invalid-size.yaml
@@ -0,0 +1,20 @@
+# RUN: not lld -flavor darwin -arch x86_64 -r %s 2>&1 | FileCheck %s
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+...
+
+# CHECK: error: __DATA/__objc_imageinfo in file {{.*}} should be 8 bytes in size \ No newline at end of file
diff --git a/test/mach-o/objc-image-info-invalid-version.yaml b/test/mach-o/objc-image-info-invalid-version.yaml
new file mode 100644
index 000000000000..04d62e9fb789
--- /dev/null
+++ b/test/mach-o/objc-image-info-invalid-version.yaml
@@ -0,0 +1,20 @@
+# RUN: not lld -flavor darwin -arch x86_64 -r %s 2>&1 | FileCheck %s
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 ]
+...
+
+# CHECK: error: __DATA/__objc_imageinfo in file {{.*}} should have version=0 \ No newline at end of file
diff --git a/test/mach-o/objc-image-info-mismatched-swift-version.yaml b/test/mach-o/objc-image-info-mismatched-swift-version.yaml
new file mode 100644
index 000000000000..efb7c319285b
--- /dev/null
+++ b/test/mach-o/objc-image-info-mismatched-swift-version.yaml
@@ -0,0 +1,20 @@
+# RUN: not lld -flavor darwin -arch x86_64 -r %s %p/Inputs/swift-version-1.yaml 2>&1 | FileCheck %s
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 ]
+...
+
+# CHECK: different swift versions \ No newline at end of file
diff --git a/test/mach-o/objc-image-info-pass-output.yaml b/test/mach-o/objc-image-info-pass-output.yaml
new file mode 100644
index 000000000000..7fc95a846324
--- /dev/null
+++ b/test/mach-o/objc-image-info-pass-output.yaml
@@ -0,0 +1,30 @@
+# RUN: lld -flavor darwin -ios_simulator_version_min 5.0 -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s
+
+# Make sure that we have an objc image info in the output. It should have
+# been generated by the objc pass.
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00 ]
+...
+
+# CHECK: --- !native
+# CHECK: path: '<linker-internal>'
+# CHECK: defined-atoms:
+# CHECK: - scope: hidden
+# CHECK: type: objc-image-info
+# CHECK: content: [ 00, 00, 00, 00, 20, 02, 00, 00 ]
+# CHECK: alignment: 4
+# CHECK: ... \ No newline at end of file
diff --git a/test/mach-o/objc-image-info-simulator-vs-host.yaml b/test/mach-o/objc-image-info-simulator-vs-host.yaml
new file mode 100644
index 000000000000..c4f9bd58f968
--- /dev/null
+++ b/test/mach-o/objc-image-info-simulator-vs-host.yaml
@@ -0,0 +1,23 @@
+# RUN: not lld -flavor darwin -ios_simulator_version_min 5.0 -arch x86_64 -r %s 2>&1 | FileCheck %s
+
+# The file is built for the simulator, but the objc image info flags are for
+# the host.
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+...
+
+# CHECK: {{.*}} cannot be linked. It contains ObjC built for a non-simulator target while we are linking a simulator target \ No newline at end of file
diff --git a/test/mach-o/objc-image-info-unsupported-gc.yaml b/test/mach-o/objc-image-info-unsupported-gc.yaml
new file mode 100644
index 000000000000..9f98369a39cb
--- /dev/null
+++ b/test/mach-o/objc-image-info-unsupported-gc.yaml
@@ -0,0 +1,20 @@
+# RUN: not lld -flavor darwin -arch x86_64 -r %s 2>&1 | FileCheck %s
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 ]
+...
+
+# CHECK: error: __DATA/__objc_imageinfo in file {{.*}} uses GC. This is not supported \ No newline at end of file
diff --git a/test/mach-o/objc_export_list.yaml b/test/mach-o/objc_export_list.yaml
index 9eb0af77726e..e67a4c7ece75 100644
--- a/test/mach-o/objc_export_list.yaml
+++ b/test/mach-o/objc_export_list.yaml
@@ -15,7 +15,7 @@ sections:
section: __objc_data
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000000
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
diff --git a/test/mach-o/parse-cfstring32.yaml b/test/mach-o/parse-cfstring32.yaml
index 657e733a779b..8e746f276664 100644
--- a/test/mach-o/parse-cfstring32.yaml
+++ b/test/mach-o/parse-cfstring32.yaml
@@ -21,7 +21,7 @@ sections:
section: __cfstring
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000010
content: [ 0x00, 0x00, 0x00, 0x00, 0xC8, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
diff --git a/test/mach-o/parse-compact-unwind64.yaml b/test/mach-o/parse-compact-unwind64.yaml
index b61961a3d0b0..af8967476e16 100644
--- a/test/mach-o/parse-compact-unwind64.yaml
+++ b/test/mach-o/parse-compact-unwind64.yaml
@@ -23,7 +23,7 @@ sections:
section: __compact_unwind
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000020
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
diff --git a/test/mach-o/parse-data-relocs-x86_64.yaml b/test/mach-o/parse-data-relocs-x86_64.yaml
index 6b05e26372b8..72a256ef1f02 100644
--- a/test/mach-o/parse-data-relocs-x86_64.yaml
+++ b/test/mach-o/parse-data-relocs-x86_64.yaml
@@ -76,6 +76,13 @@ sections:
# Note the addend here is -16 because that is the offset from here back
# to _d.
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+# .quad . - _foo
+# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
+# The subtractor references _d which is the first nonlocal label in this
+# section. The unsigned references _foo.
+# Note the addend here is -16 because that is the offset from here back
+# to _d.
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
# .quad L1
# This is a X86_64_RELOC_UNSIGNED without extern set.
# In this case, we encode the section number for L1 in the relocation, and
@@ -95,121 +102,146 @@ sections:
# section. The unsigned references _foo.
# Note the addend here is -40 because that is the offset from here back
# to _d.
- 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
# .quad _foo + 4 - .
# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
# The subtractor references _d which is the first nonlocal label in this
# section. The unsigned references _foo.
-# Note the addend here is -44. It would have been -48 because that
+# Note the addend here is -52. It would have been -56 because that
# would take us from the address of this relocation back to _d. But as
-# we also add 4 for the offset, we get -44.
- 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+# we also add 4 for the offset, we get -52.
+ 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
# .quad L1 - .
# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
# The subtractor references _d which is the first nonlocal label in this
# section. The unsigned does not have extern set, so the relocation
# number is the section number for L1.
-# Note the addend here is -54. Of that, -56 would be the offset from
+# Note the addend here is -62. Of that, -64 would be the offset from
# this location from _d. The remaining 2 is the absolute address
# of L1.
- 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
# .long _foo - .
# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
# The subtractor references _d which is the first nonlocal label in this
# section. The unsigned references _foo.
-# Note the addend here is -64 because that is the offset from here back
+# Note the addend here is -72 because that is the offset from here back
+# to _d.
+ 0xB8, 0xFF, 0xFF, 0xFF,
+# .long . - _foo
+# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
+# The subtractor references _d which is the first nonlocal label in this
+# section. The unsigned references _foo.
+# Note the addend here is -76 because that is the offset from here back
# to _d.
- 0xC0, 0xFF, 0xFF, 0xFF,
+ 0xB4, 0xFF, 0xFF, 0xFF,
# .long _foo + 4 - .
# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
# The subtractor references _d which is the first nonlocal label in this
# section. The unsigned references _foo.
-# Note the addend here is -64. It would have been -68 because that
+# Note the addend here is -76. It would have been -80 because that
# would take us from the address of this relocation back to _d. But as
-# we also add 4 for the offset, we get -64.
- 0xC0, 0xFF, 0xFF, 0xFF,
+# we also add 4 for the offset, we get -76.
+ 0xB4, 0xFF, 0xFF, 0xFF,
# .long L1 - .
# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
# The subtractor references _d which is the first nonlocal label in this
# section. The unsigned does not have extern set, so the relocation
# number is the section number for L1.
-# Note the addend here is -70. Of that, -72 would be the offset from
+# Note the addend here is -82. Of that, -84 would be the offset from
# this location from _d. The remaining 2 is the absolute address
# of L1.
- 0xBA, 0xFF, 0xFF, 0xFF ]
+ 0xAE, 0xFF, 0xFF, 0xFF ]
relocations:
- - offset: 0x00000048
+ - offset: 0x00000054
type: X86_64_RELOC_SUBTRACTOR
length: 2
pc-rel: false
extern: true
symbol: 2
- - offset: 0x00000048
+ - offset: 0x00000054
type: X86_64_RELOC_UNSIGNED
length: 2
pc-rel: false
extern: false
symbol: 2
- - offset: 0x00000044
+ - offset: 0x00000050
type: X86_64_RELOC_SUBTRACTOR
length: 2
pc-rel: false
extern: true
symbol: 2
- - offset: 0x00000044
+ - offset: 0x00000050
type: X86_64_RELOC_UNSIGNED
length: 2
pc-rel: false
extern: true
symbol: 0
- - offset: 0x00000040
+ - offset: 0x0000004C
+ type: X86_64_RELOC_SUBTRACTOR
+ length: 2
+ pc-rel: false
+ extern: true
+ symbol: 0
+ - offset: 0x0000004C
+ type: X86_64_RELOC_UNSIGNED
+ length: 2
+ pc-rel: false
+ extern: true
+ symbol: 2
+ - offset: 0x00000048
type: X86_64_RELOC_SUBTRACTOR
length: 2
pc-rel: false
extern: true
symbol: 2
- - offset: 0x00000040
+ - offset: 0x00000048
type: X86_64_RELOC_UNSIGNED
length: 2
pc-rel: false
extern: true
symbol: 0
- - offset: 0x00000038
+ - offset: 0x00000040
type: X86_64_RELOC_SUBTRACTOR
length: 3
pc-rel: false
extern: true
symbol: 2
- - offset: 0x00000038
+ - offset: 0x00000040
type: X86_64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: false
symbol: 2
- - offset: 0x00000030
+ - offset: 0x00000038
type: X86_64_RELOC_SUBTRACTOR
length: 3
pc-rel: false
extern: true
symbol: 2
- - offset: 0x00000030
+ - offset: 0x00000038
type: X86_64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
symbol: 0
- - offset: 0x00000028
+ - offset: 0x00000030
type: X86_64_RELOC_SUBTRACTOR
length: 3
pc-rel: false
extern: true
symbol: 2
- - offset: 0x00000028
+ - offset: 0x00000030
type: X86_64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
symbol: 0
+ - offset: 0x00000028
+ type: X86_64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: false
+ symbol: 2
- offset: 0x00000020
type: X86_64_RELOC_UNSIGNED
length: 3
@@ -217,10 +249,16 @@ sections:
extern: false
symbol: 2
- offset: 0x00000018
+ type: X86_64_RELOC_SUBTRACTOR
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 0
+ - offset: 0x00000018
type: X86_64_RELOC_UNSIGNED
length: 3
pc-rel: false
- extern: false
+ extern: true
symbol: 2
- offset: 0x00000010
type: X86_64_RELOC_SUBTRACTOR
@@ -266,12 +304,13 @@ page-size: 0x00000000
# CHECK:defined-atoms:
# CHECK: - name: _d
# CHECK: type: data
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
-# CHECK: 00, 00, 00, 00, F0, FF, FF, FF, FF, FF, FF, FF,
-# CHECK: {{..}}, {{..}}, 00, 00, 00, 00, 00, 00, {{..}}, {{..}}, 00, 00,
-# CHECK: 00, 00, 00, 00, D8, FF, FF, FF, FF, FF, FF, FF,
-# CHECK: D4, FF, FF, FF, FF, FF, FF, FF, {{..}}, {{..}}, {{..}}, {{..}},
-# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, C0, FF, FF, FF, C0, FF, FF, FF,
+# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
+# CHECK: 00, 00, 00, 00, F0, FF, FF, FF, FF, FF, FF, FF,
+# CHECK: 18, 00, 00, 00, 00, 00, 00, 00, {{..}}, {{..}}, 00, 00,
+# CHECK: 00, 00, 00, 00, {{..}}, {{..}}, 00, 00, 00, 00, 00, 00,
+# CHECK: D0, FF, FF, FF, FF, FF, FF, FF, CC, FF, FF, FF,
+# CHECK: FF, FF, FF, FF, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}},
+# CHECK: B8, FF, FF, FF, B4, FF, FF, FF, B4, FF, FF, FF,
# CHECK: {{..}}, {{..}}, {{..}}, {{..}} ]
# CHECK: dead-strip: never
# CHECK: references:
@@ -285,32 +324,38 @@ page-size: 0x00000000
# CHECK: - kind: delta64
# CHECK: offset: 16
# CHECK: target: _foo
-# CHECK: - kind: pointer64Anon
+# CHECK: - kind: negDelta64
# CHECK: offset: 24
-# CHECK: target: L003
+# CHECK: target: _foo
# CHECK: - kind: pointer64Anon
# CHECK: offset: 32
# CHECK: target: L003
+# CHECK: - kind: pointer64Anon
+# CHECK: offset: 40
+# CHECK: target: L003
# CHECK: addend: 2
# CHECK: - kind: delta64
-# CHECK: offset: 40
+# CHECK: offset: 48
# CHECK: target: _foo
# CHECK: - kind: delta64
-# CHECK: offset: 48
+# CHECK: offset: 56
# CHECK: target: _foo
# CHECK: addend: 4
# CHECK: - kind: delta64Anon
-# CHECK: offset: 56
+# CHECK: offset: 64
# CHECK: target: L003
# CHECK: - kind: delta32
-# CHECK: offset: 64
+# CHECK: offset: 72
+# CHECK: target: _foo
+# CHECK: - kind: negDelta32
+# CHECK: offset: 76
# CHECK: target: _foo
# CHECK: - kind: delta32
-# CHECK: offset: 68
+# CHECK: offset: 80
# CHECK: target: _foo
# CHECK: addend: 4
# CHECK: - kind: delta32Anon
-# CHECK: offset: 72
+# CHECK: offset: 84
# CHECK: target: L003
# CHECK: - name: _foo
# CHECK: content: [ C3 ]
@@ -323,4 +368,5 @@ page-size: 0x00000000
# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
# CHECK: section-choice: custom-required
# CHECK: section-name: __DATA/__custom
+# CHECK: dead-strip: never
diff --git a/test/mach-o/parse-data.yaml b/test/mach-o/parse-data.yaml
index 61d77290d108..3b422e04cae7 100644
--- a/test/mach-o/parse-data.yaml
+++ b/test/mach-o/parse-data.yaml
@@ -22,7 +22,7 @@ sections:
section: __data
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000000
content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x11, 0x12, 0x13, 0x14, 0x21, 0x22, 0x23, 0x24,
@@ -31,7 +31,7 @@ sections:
section: __custom
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000018
content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ]
- segment: __DATA
diff --git a/test/mach-o/parse-eh-frame.yaml b/test/mach-o/parse-eh-frame.yaml
index 69324800e991..6453474024bb 100644
--- a/test/mach-o/parse-eh-frame.yaml
+++ b/test/mach-o/parse-eh-frame.yaml
@@ -22,7 +22,7 @@ sections:
section: __eh_frame
type: S_COALESCED
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000058
content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
diff --git a/test/mach-o/sdk-version-error.yaml b/test/mach-o/sdk-version-error.yaml
new file mode 100644
index 000000000000..2607bb8e9c58
--- /dev/null
+++ b/test/mach-o/sdk-version-error.yaml
@@ -0,0 +1,22 @@
+# RUN: not lld -flavor darwin -arch x86_64 -sdk_version 10.blah %s -o %t 2>&1 | FileCheck %s --check-prefix=ERROR
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+# ERROR: malformed sdkVersion value \ No newline at end of file
diff --git a/test/mach-o/sectattrs.yaml b/test/mach-o/sectattrs.yaml
new file mode 100644
index 000000000000..800ba55d1b3b
--- /dev/null
+++ b/test/mach-o/sectattrs.yaml
@@ -0,0 +1,30 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -dylib \
+# RUN: %p/Inputs/libSystem.yaml -o %t \
+# RUN: && llvm-objdump -private-headers %t | FileCheck %s
+#
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ ]
+ address: 0x0000000000000000
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x8B, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x5D, 0xC3 ]
+global-symbols:
+ - name: _get
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+
+...
+
+
+# CHECK: PURE_INSTRUCTIONS SOME_INSTRUCTIONS
+
diff --git a/test/mach-o/seg-protection-arm64.yaml b/test/mach-o/seg-protection-arm64.yaml
new file mode 100644
index 000000000000..f63b33ad2dc3
--- /dev/null
+++ b/test/mach-o/seg-protection-arm64.yaml
@@ -0,0 +1,78 @@
+# RUN: lld -flavor darwin -arch arm64 %s %p/Inputs/hello-world-arm64.yaml -o %t && llvm-objdump -private-headers %t | FileCheck %s
+
+--- !mach-o
+arch: arm64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: start
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000001
+
+...
+
+# CHECK: Load command 0
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 72
+# CHECK: segname __PAGEZERO
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot ---
+# CHECK: initprot ---
+# CHECK: nsects 0
+# CHECK: flags (none)
+# CHECK: Load command 1
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 152
+# CHECK: segname __TEXT
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot r-x
+# CHECK: initprot r-x
+# CHECK: nsects 1
+# CHECK: flags (none)
+# CHECK: Section
+# CHECK: sectname __text
+# CHECK: segname __TEXT
+# CHECK: addr
+# CHECK: size
+# CHECK: offset
+# CHECK: align 2^0 (1)
+# CHECK: reloff 0
+# CHECK: nreloc 0
+# CHECK: type S_REGULAR
+# CHECK: attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
+# CHECK: reserved1 0
+# CHECK: reserved2 0
+# CHECK: Load command 2
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 72
+# CHECK: segname __LINKEDIT
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot r--
+# CHECK: initprot r--
+# CHECK: nsects 0
+# CHECK: flags (none)
diff --git a/test/mach-o/seg-protection-x86_64.yaml b/test/mach-o/seg-protection-x86_64.yaml
new file mode 100644
index 000000000000..474f72f4c57f
--- /dev/null
+++ b/test/mach-o/seg-protection-x86_64.yaml
@@ -0,0 +1,78 @@
+# RUN: lld -flavor darwin -arch x86_64 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump -private-headers %t | FileCheck %s
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: start
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000001
+
+...
+
+# CHECK: Load command 0
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 72
+# CHECK: segname __PAGEZERO
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot ---
+# CHECK: initprot ---
+# CHECK: nsects 0
+# CHECK: flags (none)
+# CHECK: Load command 1
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 152
+# CHECK: segname __TEXT
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot rwx
+# CHECK: initprot r-x
+# CHECK: nsects 1
+# CHECK: flags (none)
+# CHECK: Section
+# CHECK: sectname __text
+# CHECK: segname __TEXT
+# CHECK: addr
+# CHECK: size
+# CHECK: offset
+# CHECK: align 2^0 (1)
+# CHECK: reloff 0
+# CHECK: nreloc 0
+# CHECK: type S_REGULAR
+# CHECK: attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
+# CHECK: reserved1 0
+# CHECK: reserved2 0
+# CHECK: Load command 2
+# CHECK: cmd LC_SEGMENT_64
+# CHECK: cmdsize 72
+# CHECK: segname __LINKEDIT
+# CHECK: vmaddr
+# CHECK: vmsize
+# CHECK: fileoff
+# CHECK: filesize
+# CHECK: maxprot rwx
+# CHECK: initprot r--
+# CHECK: nsects 0
+# CHECK: flags (none)
diff --git a/test/mach-o/source-version.yaml b/test/mach-o/source-version.yaml
new file mode 100644
index 000000000000..169e97571357
--- /dev/null
+++ b/test/mach-o/source-version.yaml
@@ -0,0 +1,28 @@
+# RUN: not lld -flavor darwin -arch x86_64 -source_version 10.blah %s -o %t 2>&1 | FileCheck %s --check-prefix=ERROR
+# RUN: lld -flavor darwin -arch x86_64 -source_version 10.1.2.3.4 %s -o %t -dylib %p/Inputs/libSystem.yaml && llvm-objdump -private-headers %t | FileCheck %s
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+# ERROR: malformed source_version value
+
+# CHECK: Load command {{[0-9]*}}
+# CHECK: cmd LC_SOURCE_VERSION
+# CHECK: cmdsize 16
+# CHECK: version 10.1.2.3.4 \ No newline at end of file
diff --git a/test/mach-o/subsections-via-symbols-default.yaml b/test/mach-o/subsections-via-symbols-default.yaml
new file mode 100644
index 000000000000..93ddbc943f9a
--- /dev/null
+++ b/test/mach-o/subsections-via-symbols-default.yaml
@@ -0,0 +1,28 @@
+# RUN: lld -flavor darwin -ios_simulator_version_min 5.0 -arch x86_64 -r %s -o %t
+# RUN: llvm-readobj -file-headers %t | FileCheck %s
+
+# Make sure that we have an objc image info in the output. It should have
+# been generated by the objc pass.
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __DATA
+ section: __objc_imageinfo
+ type: S_REGULAR
+ attributes: [ S_ATTR_NO_DEAD_STRIP ]
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00 ]
+...
+
+# The ObjC pass creates a new image info in a new MachoFile internal to the pass.
+# Make sure that we still have MH_SUBSECTIONS_VIA_SYMBOLS in the output file, even
+# though that file in the ObjCPass didn't get it set from being parsed.
+
+# CHECK: MH_SUBSECTIONS_VIA_SYMBOLS \ No newline at end of file
diff --git a/test/mach-o/unwind-info-simple-arm64.yaml b/test/mach-o/unwind-info-simple-arm64.yaml
index 8e87230e2833..2ef6dda8f3af 100644
--- a/test/mach-o/unwind-info-simple-arm64.yaml
+++ b/test/mach-o/unwind-info-simple-arm64.yaml
@@ -125,7 +125,7 @@ sections:
section: __compact_unwind
type: S_REGULAR
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x00000000000000A8
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
diff --git a/test/mach-o/unwind-info-simple-x86_64.yaml b/test/mach-o/unwind-info-simple-x86_64.yaml
index 1d2294a99678..7dfae1b71581 100644
--- a/test/mach-o/unwind-info-simple-x86_64.yaml
+++ b/test/mach-o/unwind-info-simple-x86_64.yaml
@@ -117,10 +117,6 @@ defined-atoms:
- name: _main
scope: global
content: [ C3 ]
- references:
- - kind: branch32
- offset: 9
- target: __Z3barv
- name: _needsDwarfButNoCompactUnwind
scope: global
content: [ C3 ]
diff --git a/test/mach-o/version-min-load-command-object.yaml b/test/mach-o/version-min-load-command-object.yaml
new file mode 100644
index 000000000000..33001cc6f715
--- /dev/null
+++ b/test/mach-o/version-min-load-command-object.yaml
@@ -0,0 +1,35 @@
+# RUN: lld -flavor darwin -arch x86_64 %s -o %t -r -macosx_version_min 10.8 && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 %s -o %t -r && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 %s -o %t -r %p/Inputs/no-version-min-load-command-object.yaml && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_VERSION_MIN
+
+# If we are emitting an object file, then we only emit a min version load command if the source object file(s) all have
+# version(s) and either known platforms or contain min version load commands themselves.
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+min-os-version-kind: LC_VERSION_MIN_MACOSX
+min-os-version: 10.8
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+# CHECK: Load command {{[0-9]*}}
+# CHECK: cmd LC_VERSION_MIN_MACOSX
+# CHECK: cmdsize 16
+# CHECK: version 10.8
+# CHECK: sdk n/a
+
+# NO_VERSION_MIN-NOT: LC_VERSION_MIN_MACOSX \ No newline at end of file
diff --git a/test/mach-o/version-min-load-command.yaml b/test/mach-o/version-min-load-command.yaml
new file mode 100644
index 000000000000..aa378a71fcf4
--- /dev/null
+++ b/test/mach-o/version-min-load-command.yaml
@@ -0,0 +1,43 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml 2>&1 | FileCheck %s --check-prefix=WARNING
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -version_load_command && llvm-objdump -private-headers %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -no_version_load_command && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_VERSION_MIN
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static -version_load_command -no_version_load_command && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_VERSION_MIN
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/libSystem.yaml -static && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=NO_VERSION_MIN
+
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 -sdk_version 10.9 %s -o %t -dylib %p/Inputs/libSystem.yaml && llvm-objdump -private-headers %t | FileCheck %s --check-prefix=SDK_VERSION
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+# CHECK: Load command {{[0-9]*}}
+# CHECK: cmd LC_VERSION_MIN_MACOSX
+# CHECK: cmdsize 16
+# CHECK: version 10.8
+# CHECK: sdk 10.8
+
+# SDK_VERSION: Load command {{[0-9]*}}
+# SDK_VERSION: cmd LC_VERSION_MIN_MACOSX
+# SDK_VERSION: cmdsize 16
+# SDK_VERSION: version 10.8
+# SDK_VERSION: sdk 10.9
+
+# WARNING: warning: -sdk_version is required when emitting min version load command. Setting sdk version to match provided min version
+
+# NO_VERSION_MIN-NOT: LC_VERSION_MIN_MACOSX
diff --git a/test/old-elf/AArch64/Inputs/fn.c b/test/old-elf/AArch64/Inputs/fn.c
deleted file mode 100644
index 54939a2426b2..000000000000
--- a/test/old-elf/AArch64/Inputs/fn.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int fn()
-{
- return 0;
-}
diff --git a/test/old-elf/AArch64/Inputs/fn.o b/test/old-elf/AArch64/Inputs/fn.o
deleted file mode 100644
index 53e47ad37742..000000000000
--- a/test/old-elf/AArch64/Inputs/fn.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/AArch64/Inputs/general-dyn-tls-0.yaml b/test/old-elf/AArch64/Inputs/general-dyn-tls-0.yaml
deleted file mode 100644
index e355a3d85cdf..000000000000
--- a/test/old-elf/AArch64/Inputs/general-dyn-tls-0.yaml
+++ /dev/null
@@ -1,64 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_AARCH64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: FF4300D1E00F00B900040011E103002A48D03BD50801009108010091000100B9E10B00B9FF430091C0035FD6
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000014
- Symbol: var
- Type: R_AARCH64_TLSLE_ADD_TPREL_HI12
- - Offset: 0x0000000000000018
- Symbol: var
- Type: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .tbss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Size: 4
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
-# - Name: test_tls.c
-# Type: STT_FILE
- - Name: '$d.1'
- Section: .tbss
- - Name: '$x.0'
- Section: .text
- - Name: .tbss
- Type: STT_TLS
- Section: .tbss
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000002C
- - Name: var
- Type: STT_TLS
- Section: .tbss
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/AArch64/Inputs/initfini-option.c b/test/old-elf/AArch64/Inputs/initfini-option.c
deleted file mode 100644
index 6021fb57ffa9..000000000000
--- a/test/old-elf/AArch64/Inputs/initfini-option.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <stdio.h>
-
-void init() {
- printf("%s\n", __FUNCTION__);
-}
-
-void fini() {
- printf("%s\n", __FUNCTION__);
-}
-
-int main() {
-}
diff --git a/test/old-elf/AArch64/Inputs/initfini-option.o b/test/old-elf/AArch64/Inputs/initfini-option.o
deleted file mode 100644
index c75079b013fa..000000000000
--- a/test/old-elf/AArch64/Inputs/initfini-option.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/AArch64/Inputs/initfini.c b/test/old-elf/AArch64/Inputs/initfini.c
deleted file mode 100644
index 8369d68a8dab..000000000000
--- a/test/old-elf/AArch64/Inputs/initfini.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-
-void __attribute__ ((constructor)) constructor() {
- printf("%s\n", __FUNCTION__);
-}
-
-void __attribute__ ((destructor)) destructor() {
- printf("%s\n", __FUNCTION__);
-}
-
-int main() {
- return 0;
-}
diff --git a/test/old-elf/AArch64/Inputs/initfini.o b/test/old-elf/AArch64/Inputs/initfini.o
deleted file mode 100644
index 030fe59878be..000000000000
--- a/test/old-elf/AArch64/Inputs/initfini.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/AArch64/Inputs/initial-exec-tls-1.yaml b/test/old-elf/AArch64/Inputs/initial-exec-tls-1.yaml
deleted file mode 100644
index 2a6104a150ea..000000000000
--- a/test/old-elf/AArch64/Inputs/initial-exec-tls-1.yaml
+++ /dev/null
@@ -1,77 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_AARCH64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .tbss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Size: 16
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742065653461393664373236383264353237636635353336313135366235656531383662303964363138292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420623065376165623639343236646331346637376466626535343533333536366664363866396466632900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
- - Name: '$d.0'
- Type: STT_TLS
- Section: .tbss
- - Name: '$d.1'
- Section: .comment
- - Name: .tbss
- Type: STT_TLS
- Section: .tbss
- - Type: STT_SECTION
- Section: .text
- - Type: STT_SECTION
- Section: .data
- - Type: STT_SECTION
- Section: .bss
- - Type: STT_SECTION
- Section: .comment
- - Type: STT_SECTION
- Section: .note.GNU-stack
- Global:
- - Name: e0
- Type: STT_TLS
- Section: .tbss
- Size: 0x0000000000000004
- - Name: e1
- Type: STT_TLS
- Section: .tbss
- Value: 0x0000000000000004
- Size: 0x0000000000000004
- - Name: e2
- Type: STT_TLS
- Section: .tbss
- Value: 0x0000000000000008
- Size: 0x0000000000000004
- - Name: e3
- Type: STT_TLS
- Section: .tbss
- Value: 0x000000000000000C
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/AArch64/Inputs/main.c b/test/old-elf/AArch64/Inputs/main.c
deleted file mode 100644
index 0280c9127076..000000000000
--- a/test/old-elf/AArch64/Inputs/main.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int main() {
- fn();
- return 0;
-}
diff --git a/test/old-elf/AArch64/Inputs/main.o b/test/old-elf/AArch64/Inputs/main.o
deleted file mode 100644
index 8c0f049da6a8..000000000000
--- a/test/old-elf/AArch64/Inputs/main.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/AArch64/Inputs/no-interp-section.c b/test/old-elf/AArch64/Inputs/no-interp-section.c
deleted file mode 100644
index 3981c038ed33..000000000000
--- a/test/old-elf/AArch64/Inputs/no-interp-section.c
+++ /dev/null
@@ -1 +0,0 @@
-int c = 10;
diff --git a/test/old-elf/AArch64/Inputs/no-interp-section.o b/test/old-elf/AArch64/Inputs/no-interp-section.o
deleted file mode 100644
index 36b41fdbf782..000000000000
--- a/test/old-elf/AArch64/Inputs/no-interp-section.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/AArch64/Inputs/zerosizedsection.o b/test/old-elf/AArch64/Inputs/zerosizedsection.o
deleted file mode 100644
index 10123fcef90d..000000000000
--- a/test/old-elf/AArch64/Inputs/zerosizedsection.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/AArch64/Inputs/zerosizedsection.s b/test/old-elf/AArch64/Inputs/zerosizedsection.s
deleted file mode 100644
index 651ee3aab503..000000000000
--- a/test/old-elf/AArch64/Inputs/zerosizedsection.s
+++ /dev/null
@@ -1,3 +0,0 @@
-.text
-.data
-.word .text
diff --git a/test/old-elf/AArch64/defsym.test b/test/old-elf/AArch64/defsym.test
deleted file mode 100644
index f9864092ddc3..000000000000
--- a/test/old-elf/AArch64/defsym.test
+++ /dev/null
@@ -1,22 +0,0 @@
-RUN: lld -flavor old-gnu -target aarch64--linux-gnu --defsym=main=fn \
-RUN: --noinhibit-exec %p/Inputs/fn.o -o %t
-RUN: llvm-readobj -symbols %t | FileCheck %s
-
-CHECK: Symbol {
-CHECK: Name: main (1)
-CHECK: Value: 0x4001A4
-CHECK: Size: 0
-CHECK: Binding: Global (0x1)
-CHECK: Type: Function (0x2)
-CHECK: Other: 0
-CHECK: Section: .text (0x5)
-CHECK: }
-CHECK: Symbol {
-CHECK: Name: fn (11)
-CHECK: Value: 0x4001A4
-CHECK: Size: 8
-CHECK: Binding: Global (0x1)
-CHECK: Type: Function (0x2)
-CHECK: Other: 0
-CHECK: Section: .text (0x5)
-CHECK: }
diff --git a/test/old-elf/AArch64/dontignorezerosize-sections.test b/test/old-elf/AArch64/dontignorezerosize-sections.test
deleted file mode 100644
index 8f3b27702208..000000000000
--- a/test/old-elf/AArch64/dontignorezerosize-sections.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# This tests that lld is not ignoring zero sized sections
-RUN: lld -flavor old-gnu -target aarch64--linux-gnu %p/Inputs/zerosizedsection.o \
-RUN: --noinhibit-exec --output-filetype=yaml -o %t
-RUN: FileCheck %s < %t
-
-CHECK: references:
-CHECK: - kind: layout-after
-CHECK: offset: 0
-CHECK: target: L000
diff --git a/test/old-elf/AArch64/dynamicvars.test b/test/old-elf/AArch64/dynamicvars.test
deleted file mode 100644
index 80228f0cd4b2..000000000000
--- a/test/old-elf/AArch64/dynamicvars.test
+++ /dev/null
@@ -1,113 +0,0 @@
-# Tests that the dynamic variables created by the linker are set to the right
-# values.
-
-# RUN: yaml2obj --format elf -docnum 1 %s -o %t.o
-# RUN: lld -flavor old-gnu -target aarch64 -e main %t.o -o %t1 --noinhibit-exec
-# RUN: llvm-readobj -sections -symbols %t1 | FileCheck %s
-
-
-# CHECK: Name: .dynamic
-# CHECK: Type: SHT_DYNAMIC
-# CHECK: Address: [[TARGETA:[0xa-fA-f0-9]+]]
-# CHECK: Name: .got.plt
-# CHECK: Type: SHT_PROGBITS
-# CHECK: Address: [[TARGETB:[0xa-fA-f0-9]+]]
-# CHECK: Name: _DYNAMIC
-# CHECK: Value: [[TARGETA]]
-# CHECK: Section: .dynamic
-# CHECK: Name: _GLOBAL_OFFSET_TABLE_
-# CHECK: Value: [[TARGETB]]
-# CHECK: Section: .got.plt
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- - Name: .text.startup
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: FD7BBFA900000090FD030091000000910000009400008052FD7BC1A8C0035FD6
- - Name: .rela.text.startup
- Type: SHT_RELA
- Flags: [ SHF_INFO_LINK ]
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text.startup
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: .rodata.str1.8
- Type: R_AARCH64_ADR_PREL_PG_HI21
- - Offset: 0x000000000000000C
- Symbol: .rodata.str1.8
- Type: R_AARCH64_ADD_ABS_LO12_NC
- - Offset: 0x0000000000000010
- Symbol: puts
- Type: R_AARCH64_CALL26
- - Name: .rodata.str1.8
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000008
- Content: '7465737400000000'
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 004743433A2028474E552920342E392E33203230313530333234202870726572656C656173652900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
- - Name: test.c
- Type: STT_FILE
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .text.startup
- Type: STT_SECTION
- Section: .text.startup
- - Name: '$x'
- Section: .text.startup
- - Name: .rodata.str1.8
- Type: STT_SECTION
- Section: .rodata.str1.8
- - Name: '$d'
- Section: .rodata.str1.8
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text.startup
- Size: 0x0000000000000020
- - Name: puts
-...
diff --git a/test/old-elf/AArch64/dynlib-nointerp-section.test b/test/old-elf/AArch64/dynlib-nointerp-section.test
deleted file mode 100644
index c4f4edab61b1..000000000000
--- a/test/old-elf/AArch64/dynlib-nointerp-section.test
+++ /dev/null
@@ -1,5 +0,0 @@
-RUN: lld -flavor old-gnu -target aarch64--linux-gnu %p/Inputs/no-interp-section.o \
-RUN: -o %t -shared
-RUN: llvm-objdump -section-headers %t | FileCheck %s
-
-CHECK-NOT: .interp
diff --git a/test/old-elf/AArch64/general-dyn-tls-0.test b/test/old-elf/AArch64/general-dyn-tls-0.test
deleted file mode 100644
index ae2af94d057d..000000000000
--- a/test/old-elf/AArch64/general-dyn-tls-0.test
+++ /dev/null
@@ -1,103 +0,0 @@
-# Check for correct offsets when handling relocations for general dynamic TLS
-# access in executable binaries.
-#
-# The test case was generated from following code snippet:
-#
-# == test_tls.c ==
-#
-# __thread int var;
-# void foo (int x) {
-# var = x + 1;
-# }
-#
-# == test_main.c ==
-# #include <stdio.h>
-#
-# extern __thread int var;
-# extern void foo (int);
-#
-# int main () {
-# foo (10);
-# return var;
-# }
-#
-# The objects are compiled with -fpic.
-
-#RUN: yaml2obj -format=elf %p/Inputs/general-dyn-tls-0.yaml -o=%t-t1.o
-#RUN: yaml2obj -format=elf %s -o %t-t0.o
-#RUN: lld -flavor old-gnu -target arm64 --noinhibit-exec -o %t.exe %t-t0.o %t-t1.o
-#RUN: llvm-readobj -relocations %t.exe | FileCheck %s -check-prefix=CHECKRELOCATION
-#RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-#CHECKRELOCATION: Relocations [
-#CHECKRELOCATION: .rela.dyn {
-#CHECKRELOCATION: 0x401090 R_AARCH64_TLSDESC var 0x0
-#CHECKRELOCATION: }
-
-#CHECK: Contents of section .text:
-#CHECK: 400250 a8c31fb8 40018052 0b000094 000000b0 ....@..R........
-# \_ adrp x0, 401000 <_DYNAMIC> (R_AARCH64_TLSDESC_ADR_PAGE21)
-#CHECK-NEXT: 400260 014840f9 00400291 20003fd6 49d03bd5 .H@..@.. .?.I.;.
-# \_ | | ldr x1, [x0,#144] (R_AARCH64_TLSDESC_LD64_LO12_NC)
-# \_ | add x0, x0, #0x90 (R_AARCH64_TLSDESC_ADD_LO12_NC)
-# \_ blr x1 (R_AARCH64_TLSDESC_CALL)
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_AARCH64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: FD7BBFA9FD030091FF4300D1E8031F2AA8C31FB8400180520000009400000090010040F90000009120003FD649D03BD5286960B8E003082ABF030091FD7BC1A8C0035FD6
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000018
- Symbol: foo
- Type: R_AARCH64_CALL26
- - Offset: 0x000000000000001C
- Symbol: var
- Type: R_AARCH64_TLSDESC_ADR_PAGE21
- - Offset: 0x0000000000000020
- Symbol: var
- Type: R_AARCH64_TLSDESC_LD64_LO12_NC
- - Offset: 0x0000000000000024
- Symbol: var
- Type: R_AARCH64_TLSDESC_ADD_LO12_NC
- - Offset: 0x0000000000000028
- Symbol: var
- Type: R_AARCH64_TLSDESC_CALL
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
- - Name: '$x.0'
- Section: .text
- Global:
- - Name: foo
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000044
- - Name: var
- Type: STT_TLS
diff --git a/test/old-elf/AArch64/initfini.test b/test/old-elf/AArch64/initfini.test
deleted file mode 100644
index c5f385082edc..000000000000
--- a/test/old-elf/AArch64/initfini.test
+++ /dev/null
@@ -1,23 +0,0 @@
-# This tests the functionality that lld is able to read
-# init_array/fini_array sections in the input ELF. This
-# corresponds to the the .init_array/.fini_array sections
-# in the output ELF.
-
-RUN: lld -flavor old-gnu -target aarch64--linux-gnu %p/Inputs/initfini.o \
-RUN: --noinhibit-exec --output-filetype=yaml -o %t
-RUN: FileCheck %s < %t
-
-CHECK: type: data
-CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECK: section-name: .init_array
-CHECK: references:
-CHECK: - kind: R_AARCH64_ABS64
-CHECK: offset: 0
-CHECK: target: constructor
-CHECK: type: data
-CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECK: section-name: .fini_array
-CHECK: references:
-CHECK: - kind: R_AARCH64_ABS64
-CHECK: offset: 0
-CHECK: target: destructor
diff --git a/test/old-elf/AArch64/initial-exec-tls-0.test b/test/old-elf/AArch64/initial-exec-tls-0.test
deleted file mode 100644
index 4cb5f9c7052a..000000000000
--- a/test/old-elf/AArch64/initial-exec-tls-0.test
+++ /dev/null
@@ -1,146 +0,0 @@
-# Check for initial executable TLS access across different modules. For
-# this case compiler will emit R_AARCH64_TLSLD_ADR_PAGE21 and
-# R_AARCH64_TLSLD_ADD_LO12_NC static relocations and linker should create
-# a R_AARCH64_TLS_TPREL64 dynamic relocation for variable access.
-
-# The test case was generated from following code snippet:
-#
-# t1.c (initial-exec-tls-1.yaml)
-#
-# __thread int e0;
-# __thread int e1;
-# __thread int e2;
-# __thread int e3;
-#
-# t0.c (initial-exec-tls-0.test)
-#
-# extern __thread int e0;
-# extern __thread int e1;
-# extern __thread int e2;
-# extern __thread int e3;
-#
-# int main ()
-# {
-# e0 = 1;
-# e1 = 2;
-# e1 = 3;
-# e1 = 4;
-# }
-
-#RUN: yaml2obj -format=elf %p/Inputs/initial-exec-tls-1.yaml -o=%t-t1.o
-#RUN: yaml2obj -format=elf %s -o %t-t0.o
-#RUN: lld -flavor old-gnu -target arm64 --noinhibit-exec -o %t.exe %t-t0.o %t-t1.o
-#RUN: llvm-readobj -relocations %t.exe | FileCheck %s -check-prefix=CHECKRELOCATION
-#RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e0 0x0
-#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e1 0x0
-#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e2 0x0
-#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e3 0x0
-
-#CHECK: Contents of section .text:
-#CHECK-NEXT: 4002c0 ff4300d1 e8031f2a e9031e32 0a0000b0 .C.....*...2....
-# \_ adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
-#CHECK-NEXT: 4002d0 4a4940f9 4bd03bd5 ec030032 6c692ab8 JI@.K.;....2li*.
-# \_ ldr x10, [x10,#144] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
-#CHECK-NEXT: 4002e0 0a0000b0 4a4d40f9 ec031f32 6c692ab8 ....JM@....2li*.
-# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
-# \_ ldr x10, [x10,#152] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
-#CHECK-NEXT: 4002f0 0a0000b0 4a5140f9 ec070032 6c692ab8 ....JQ@....2li*.
-# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
-# \_ ldr x10, [x10,#160] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
-#CHECK-NEXT: 400300 0a0000b0 4a5540f9 ec031e32 6c692ab8 ....JU@....2li*.
-# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
-# \_ ldr x10, [x10,#168] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_AARCH64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: FF4300D1E8031F2AE9031E320A0000904A0140F94BD03BD5EC0300326C692AB80A0000904A0140F9EC031F326C692AB80A0000904A0140F9EC0700326C692AB80A0000904A0140F9EC031E326C692AB8E003082AE90F00B9FF430091C0035FD6
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x000000000000000C
- Symbol: e0
- Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
- - Offset: 0x0000000000000010
- Symbol: e0
- Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
- - Offset: 0x0000000000000020
- Symbol: e1
- Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
- - Offset: 0x0000000000000024
- Symbol: e1
- Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
- - Offset: 0x0000000000000030
- Symbol: e2
- Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
- - Offset: 0x0000000000000034
- Symbol: e2
- Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
- - Offset: 0x0000000000000040
- Symbol: e3
- Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
- - Offset: 0x0000000000000044
- Symbol: e3
- Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742065653461393664373236383264353237636635353336313135366235656531383662303964363138292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420623065376165623639343236646331346637376466626535343533333536366664363866396466632900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
- - Name: '$d.1'
- Section: .comment
- - Name: '$x.0'
- Section: .text
- - Type: STT_SECTION
- Section: .text
- - Type: STT_SECTION
- Section: .data
- - Type: STT_SECTION
- Section: .bss
- - Type: STT_SECTION
- Section: .comment
- - Type: STT_SECTION
- Section: .note.GNU-stack
- Global:
- - Name: e0
- Type: STT_TLS
- - Name: e1
- Type: STT_TLS
- - Name: e2
- Type: STT_TLS
- - Name: e3
- Type: STT_TLS
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000060
-...
diff --git a/test/old-elf/AArch64/local-tls.test b/test/old-elf/AArch64/local-tls.test
deleted file mode 100644
index f339ae20e154..000000000000
--- a/test/old-elf/AArch64/local-tls.test
+++ /dev/null
@@ -1,184 +0,0 @@
-# Check for correct offsets when handling relocations for local TLS
-# access (R_AARCH64_TLSLE_ADD_TPREL_HI12, R_AARCH64_TLSLE_ADD_TPREL_LO12_NC)
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 --noinhibit-exec -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 4001dc 48d03bd5 08010091 08610091 090140b9 H.;......a....@.
-# \_ | | <foo1>:
-# \_ | add x8, x8, #0x0 (R_AARCH64_TLSLE_ADD_TPREL_HI12)
-# \_ add x8, x8, #0x18 (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC)
-# CHECK-NEXT: 4001ec e003092a c0035fd6 48d03bd5 08010091 ...*.._.H.;.....
-# \_ | <foo2>:
-# \_ add x8, x8, #0x0 (R_AARCH64_TLSLE_ADD_TPREL_HI12)
-# CHECK-NEXT: 4001fc 08710091 090140b9 e003092a c0035fd6 .q....@....*.._.
-# \_ add x8, x8, #0x1c (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC)
-# CHECK-NEXT: 40020c 48d03bd5 08010091 08410091 090140b9 H.;......A....@.
-# \_ | | <foo3>:
-# \_ | add x8, x8, #0x0 (R_AARCH64_TLSLE_ADD_TPREL_HI12)
-# \_ add x8, x8, #0x10 (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC)
-# CHECK-NEXT: 40021c e003092a c0035fd6 48d03bd5 08010091 ...*.._.H.;.....
-# \_ | <foo3>:
-# \_ add x8, x8, #0x0 (R_AARCH64_TLSLE_ADD_TPREL_HI12)
-# CHECK-NEXT: 40022c 08510091 090140b9 e003092a c0035fd6 .Q....@....*.._.
-# \_ add x8, x8, #0x14 (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC)
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_AARCH64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 48D03BD50801009108010091090140B9E003092AC0035FD648D03BD50801009108010091090140B9E003092AC0035FD648D03BD50801009108010091090140B9E003092AC0035FD648D03BD50801009108010091090140B9E003092AC0035FD6FD7BBFA9FD030091FF8300D1BFC31FB8E4FFFF97A0831FB8E8FFFF97A0431FB8ECFFFF97E01300B9F0FFFF970800009008010091E00F00B9E00308AAA1835FB8A2435FB8E31340B9E40F40B900000094E1031F2AE00B00B9E003012ABF030091FD7BC1A8C0035FD6
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: v1
- Type: R_AARCH64_TLSLE_ADD_TPREL_HI12
- - Offset: 0x0000000000000008
- Symbol: v1
- Type: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
- - Offset: 0x000000000000001C
- Symbol: v2
- Type: R_AARCH64_TLSLE_ADD_TPREL_HI12
- - Offset: 0x0000000000000020
- Symbol: v2
- Type: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
- - Offset: 0x0000000000000034
- Symbol: v3
- Type: R_AARCH64_TLSLE_ADD_TPREL_HI12
- - Offset: 0x0000000000000038
- Symbol: v3
- Type: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
- - Offset: 0x000000000000004C
- Symbol: v4
- Type: R_AARCH64_TLSLE_ADD_TPREL_HI12
- - Offset: 0x0000000000000050
- Symbol: v4
- Type: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
- - Offset: 0x000000000000008C
- Symbol: .rodata.str1.1
- Type: R_AARCH64_ADR_PREL_PG_HI21
- - Offset: 0x0000000000000090
- Symbol: .rodata.str1.1
- Type: R_AARCH64_ADD_ABS_LO12_NC
- - Offset: 0x00000000000000AC
- Symbol: printf
- Type: R_AARCH64_CALL26
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Content: '0300000004000000'
- - Name: .tbss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Size: 8
- - Name: .rodata.str1.1
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 25692025692025692025690A00
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
- - Name: '$d.1'
- Type: STT_TLS
- Section: .tdata
- - Name: '$d.2'
- Type: STT_TLS
- Section: .tbss
- - Name: '$d.3'
- Section: .rodata.str1.1
- - Name: '$x.0'
- Section: .text
- - Name: v2
- Type: STT_TLS
- Section: .tbss
- Value: 0x0000000000000004
- Size: 0x0000000000000004
- - Name: v4
- Type: STT_TLS
- Section: .tdata
- Value: 0x0000000000000004
- Size: 0x0000000000000004
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .tdata
- Type: STT_SECTION
- Section: .tdata
- - Name: .tbss
- Type: STT_SECTION
- Section: .tbss
- - Name: .rodata.str1.1
- Type: STT_SECTION
- Section: .rodata.str1.1
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- Global:
- - Name: foo1
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000018
- - Name: foo2
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000018
- Size: 0x0000000000000018
- - Name: foo3
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000030
- Size: 0x0000000000000018
- - Name: foo4
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000048
- Size: 0x0000000000000018
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000060
- Size: 0x0000000000000068
- - Name: v1
- Type: STT_TLS
- Section: .tbss
- Size: 0x0000000000000004
- - Name: v3
- Type: STT_TLS
- Section: .tdata
- Size: 0x0000000000000004
- - Name: printf
-...
diff --git a/test/old-elf/AArch64/rel-abs16-overflow.test b/test/old-elf/AArch64/rel-abs16-overflow.test
deleted file mode 100644
index 06221c902bd7..000000000000
--- a/test/old-elf/AArch64/rel-abs16-overflow.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# Check handling of R_AARCH64_ABS16 relocation overflow.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target arm64 -o %t-exe %t-obj 2>&1 | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}}: reference from data1+0 to data1+0 of type 259 (R_AARCH64_ABS16)
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0
- Symbol: data1
- Type: R_AARCH64_ABS16
- Addend: 0
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 4
diff --git a/test/old-elf/AArch64/rel-abs16.test b/test/old-elf/AArch64/rel-abs16.test
deleted file mode 100644
index e6b817570eb4..000000000000
--- a/test/old-elf/AArch64/rel-abs16.test
+++ /dev/null
@@ -1,53 +0,0 @@
-# Check handling of R_AARCH64_ABS16 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401060 60100000 00000000 `.......
-# ^^ data1 - 0x400000 = 0x1060
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401060 g .data 00000004 data1
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data1
- Type: R_AARCH64_ABS16
- Addend: -4194304
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 4
- - Name: data2
- Section: .data
- Value: 0x4
- Size: 4
diff --git a/test/old-elf/AArch64/rel-abs32-overflow.test b/test/old-elf/AArch64/rel-abs32-overflow.test
deleted file mode 100644
index 17154c6ddc82..000000000000
--- a/test/old-elf/AArch64/rel-abs32-overflow.test
+++ /dev/null
@@ -1,53 +0,0 @@
-# Check handling of R_AARCH64_ABS32 relocation overflow.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target arm64 -o %t-exe %t-obj 2>&1 | FileCheck %s
-
-# CHECK-DAG: Relocation out of range in file {{.*}}: reference from data1+0 to data2+34359738369 of type 258 (R_AARCH64_ABS32)
-# CHECK-DAG: Relocation out of range in file {{.*}}: reference from data2+0 to data1+34359738369 of type 258 (R_AARCH64_ABS32)
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data2
- Type: R_AARCH64_ABS32
- Addend: 0x800000001
- - Offset: 0x4
- Symbol: data1
- Type: R_AARCH64_ABS32
- Addend: 0x800000001
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 4
- - Name: data2
- Section: .data
- Value: 0x4
- Size: 4
diff --git a/test/old-elf/AArch64/rel-abs32.test b/test/old-elf/AArch64/rel-abs32.test
deleted file mode 100644
index 7faa662d3462..000000000000
--- a/test/old-elf/AArch64/rel-abs32.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_AARCH64_ABS32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401060 65104080 61104080 e.@.a.@.
-# ^^ data2 + 0x80000001 = 0x80401069
-# ^^ data1 + 0x80000001 = 0x80401061
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401060 g .data 00000004 data1
-# CHECK: 00401064 g .data 00000004 data2
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data2
- Type: R_AARCH64_ABS32
- Addend: 0x80000001
- - Offset: 0x4
- Symbol: data1
- Type: R_AARCH64_ABS32
- Addend: 0x80000001
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 4
- - Name: data2
- Section: .data
- Value: 0x4
- Size: 4
diff --git a/test/old-elf/AArch64/rel-abs64.test b/test/old-elf/AArch64/rel-abs64.test
deleted file mode 100644
index 0304584d121d..000000000000
--- a/test/old-elf/AArch64/rel-abs64.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_AARCH64_ABS64 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401060 69104000 00000080 61104000 00000080 i.@.....a.@.....
-# ^^ data2 + 0x8000000000000001 = 0x8000000000401069
-# ^^ data1 + 0x8000000000000001 = 0x8000000000401061
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401060 g .data 00000008 data1
-# CHECK: 00401068 g .data 00000008 data2
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "00000000000000000000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data2
- Type: R_AARCH64_ABS64
- Addend: -9223372036854775807
- - Offset: 0x8
- Symbol: data1
- Type: R_AARCH64_ABS64
- Addend: -9223372036854775807
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 8
- - Name: data2
- Section: .data
- Value: 0x8
- Size: 8
diff --git a/test/old-elf/AArch64/rel-adr_prel_lo21-overflow.test b/test/old-elf/AArch64/rel-adr_prel_lo21-overflow.test
deleted file mode 100644
index 4f8e6b607bc7..000000000000
--- a/test/old-elf/AArch64/rel-adr_prel_lo21-overflow.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Check handling of R_AARCH64_ADR_PREL_PG_HI21 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-
-# CHECK: Relocation out of range in file {{.*}}: reference from _start+0 to data1+1048577 of type 274 (R_AARCH64_ADR_PREL_LO21)
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000090"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-- Name: .data
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.text
- Type: SHT_RELA
- Info: .text
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data1
- Type: R_AARCH64_ADR_PREL_LO21
- Addend: 0x100001
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 8
diff --git a/test/old-elf/AArch64/rel-adr_prel_lo21.test b/test/old-elf/AArch64/rel-adr_prel_lo21.test
deleted file mode 100644
index 36a9489c1aa4..000000000000
--- a/test/old-elf/AArch64/rel-adr_prel_lo21.test
+++ /dev/null
@@ -1,51 +0,0 @@
-# REQUIRES: arm64
-
-# Check handling of R_AARCH64_ADR_PREL_LO21 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -d -t %t-exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: _start:
-# CHECK-NEXT: 4001b0: 80 75 00 90 adrp x0, #15400960
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401060 g .data 00000004 data1
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000090"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.text
- Type: SHT_RELA
- Info: .text
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data1
- Type: R_AARCH64_ADR_PREL_LO21
- Addend: 0
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 8
diff --git a/test/old-elf/AArch64/rel-adr_prel_pg_hi21-overflow.test b/test/old-elf/AArch64/rel-adr_prel_pg_hi21-overflow.test
deleted file mode 100644
index f095f60e82a6..000000000000
--- a/test/old-elf/AArch64/rel-adr_prel_pg_hi21-overflow.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Check handling of R_AARCH64_ADR_PREL_PG_HI21 relocation overflow.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-
-# CHECK-DAG: Relocation out of range in file {{.*}}: reference from _start+0 to data1+2147483649 of type 275 (R_AARCH64_ADR_PREL_PG_HI21)
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000090"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-- Name: .data
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 4096
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.text
- Type: SHT_RELA
- Info: .text
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data1
- Type: R_AARCH64_ADR_PREL_PG_HI21
- Addend: 0x80000001
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 8
diff --git a/test/old-elf/AArch64/rel-adr_prel_pg_hi21.test b/test/old-elf/AArch64/rel-adr_prel_pg_hi21.test
deleted file mode 100644
index 36a20c2f6473..000000000000
--- a/test/old-elf/AArch64/rel-adr_prel_pg_hi21.test
+++ /dev/null
@@ -1,52 +0,0 @@
-# REQUIRES: arm64
-
-# Check handling of R_AARCH64_ADR_PREL_PG_HI21 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -d -t %t-exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: _start:
-# CHECK-NEXT: 4001b0: 00 00 00 d0 adrp x0, #8192
-# CHECK: SYMBOL TABLE:
-# CHECK: 00402000 g .data 00000004 data1
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000090"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-- Name: .data
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 4096
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.text
- Type: SHT_RELA
- Info: .text
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data1
- Type: R_AARCH64_ADR_PREL_PG_HI21
- Addend: 0
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 8
diff --git a/test/old-elf/AArch64/rel-bad.test b/test/old-elf/AArch64/rel-bad.test
deleted file mode 100644
index 7d2ed192de56..000000000000
--- a/test/old-elf/AArch64/rel-bad.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# Check handling of a bad relocation (in this case dynamic in a static object).
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target arm64 -o %t-exe %t-obj 2>&1 | FileCheck %s
-
-# CHECK: Unhandled reference type in file {{.*}}: reference from data1+4 to data1+0 of type 1024 (R_AARCH64_COPY)
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x4
- Symbol: data1
- Type: R_AARCH64_COPY
- Addend: 0
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 8
diff --git a/test/old-elf/AArch64/rel-prel16-overflow.test b/test/old-elf/AArch64/rel-prel16-overflow.test
deleted file mode 100644
index ea08f9700ee4..000000000000
--- a/test/old-elf/AArch64/rel-prel16-overflow.test
+++ /dev/null
@@ -1,53 +0,0 @@
-# Check handling of R_AARCH64_PREL16 relocation overflow.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target arm64 -o %t-exe %t-obj 2>&1 | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}}: reference from data1+0 to data2+524289 of type 262 (R_AARCH64_PREL16)
-# CHECK: Relocation out of range in file {{.*}}: reference from data2+0 to data1+524289 of type 262 (R_AARCH64_PREL16)
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data2
- Type: R_AARCH64_PREL16
- Addend: 0x80001
- - Offset: 0x2
- Symbol: data1
- Type: R_AARCH64_PREL16
- Addend: 0x80001
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 2
- - Name: data2
- Section: .data
- Value: 0x2
- Size: 2
diff --git a/test/old-elf/AArch64/rel-prel16.test b/test/old-elf/AArch64/rel-prel16.test
deleted file mode 100644
index 11e6028e253b..000000000000
--- a/test/old-elf/AArch64/rel-prel16.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_AARCH64_PREL16 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401060 0380ff7f 00000000 ........
-# ^^ data2 - data1 + 0x8001 = 0x8003
-# ^^ data1 - data2 + 0x8001 = 0x7fff
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401060 g .data 00000002 data1
-# CHECK: 00401062 g .data 00000006 data2
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data2
- Type: R_AARCH64_PREL16
- Addend: 0x8001
- - Offset: 0x2
- Symbol: data1
- Type: R_AARCH64_PREL16
- Addend: 0x8001
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 2
- - Name: data2
- Section: .data
- Value: 0x2
- Size: 2
diff --git a/test/old-elf/AArch64/rel-prel32-overflow.test b/test/old-elf/AArch64/rel-prel32-overflow.test
deleted file mode 100644
index 513adad08efe..000000000000
--- a/test/old-elf/AArch64/rel-prel32-overflow.test
+++ /dev/null
@@ -1,53 +0,0 @@
-# Check handling of R_AARCH64_PREL32 relocation overflow.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target arm64 -o %t-exe %t-obj 2>&1 | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}}: reference from data1+0 to data2+34359738369 of type 261 (R_AARCH64_PREL32)
-# CHECK: Relocation out of range in file {{.*}}: reference from data2+0 to data1+34359738369 of type 261 (R_AARCH64_PREL32)
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data2
- Type: R_AARCH64_PREL32
- Addend: 0x800000001
- - Offset: 0x4
- Symbol: data1
- Type: R_AARCH64_PREL32
- Addend: 0x800000001
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 4
- - Name: data2
- Section: .data
- Value: 0x4
- Size: 4
diff --git a/test/old-elf/AArch64/rel-prel32.test b/test/old-elf/AArch64/rel-prel32.test
deleted file mode 100644
index 0e178ba97f41..000000000000
--- a/test/old-elf/AArch64/rel-prel32.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_AARCH64_PREL32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401060 05000080 fdffff7f ........
-# ^^ data2 - data1 + 0x80000001 = 0x80000005
-# ^^ data1 - data2 + 0x80000001 = 0x7ffffffd
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401060 g .data 00000004 data1
-# CHECK: 00401064 g .data 00000004 data2
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data2
- Type: R_AARCH64_PREL32
- Addend: 0x80000001
- - Offset: 0x4
- Symbol: data1
- Type: R_AARCH64_PREL32
- Addend: 0x80000001
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 4
- - Name: data2
- Section: .data
- Value: 0x4
- Size: 4
diff --git a/test/old-elf/AArch64/rel-prel64.test b/test/old-elf/AArch64/rel-prel64.test
deleted file mode 100644
index 3a3eb8b90fc3..000000000000
--- a/test/old-elf/AArch64/rel-prel64.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_AARCH64_PREL64 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401060 09000000 00000080 f9ffffff ffffff7f ................
-# ^^ data2 - data1 + 0x8000000000000001 = 0x8000000000000009
-# ^^ data1 - data2 + 0x8000000000000001 = 0x7ffffffffffffff9
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401060 g .data 00000008 data1
-# CHECK: 00401068 g .data 00000008 data2
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "00000000000000000000000000000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 8
- Relocations:
- - Offset: 0x0
- Symbol: data2
- Type: R_AARCH64_PREL64
- Addend: -9223372036854775807
- - Offset: 0x8
- Symbol: data1
- Type: R_AARCH64_PREL64
- Addend: -9223372036854775807
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Size: 8
- - Name: data2
- Section: .data
- Value: 0x8
- Size: 8
diff --git a/test/old-elf/ARM/Inputs/fn.c b/test/old-elf/ARM/Inputs/fn.c
deleted file mode 100644
index 37c897ebb7f2..000000000000
--- a/test/old-elf/ARM/Inputs/fn.c
+++ /dev/null
@@ -1 +0,0 @@
-int fn() { return 1; }
diff --git a/test/old-elf/ARM/Inputs/libfn.so b/test/old-elf/ARM/Inputs/libfn.so
deleted file mode 100755
index 51934714841b..000000000000
--- a/test/old-elf/ARM/Inputs/libfn.so
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/ARM/Inputs/libobj.so b/test/old-elf/ARM/Inputs/libobj.so
deleted file mode 100755
index 85b3ae4ca3d1..000000000000
--- a/test/old-elf/ARM/Inputs/libobj.so
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/ARM/Inputs/obj.c b/test/old-elf/ARM/Inputs/obj.c
deleted file mode 100644
index fb6a9f13f698..000000000000
--- a/test/old-elf/ARM/Inputs/obj.c
+++ /dev/null
@@ -1,4 +0,0 @@
-static struct S {
-} s;
-
-struct S *const object = &s;
diff --git a/test/old-elf/ARM/arm-symbols.test b/test/old-elf/ARM/arm-symbols.test
deleted file mode 100644
index ddf3c80862a5..000000000000
--- a/test/old-elf/ARM/arm-symbols.test
+++ /dev/null
@@ -1,51 +0,0 @@
-# Check that symbols formed from ARM instructions are valid:
-# 1. Symbol address.
-# 2. Symbol content size.
-# 3. Symbol content.
-
-# RUN: yaml2obj -format=elf %s > %t-a.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-a.o -o %t-a
-# RUN: llvm-readobj -symbols %t-a | FileCheck -check-prefix=SYM-ADDR %s
-# RUN: llvm-readobj -symbols %t-a | FileCheck -check-prefix=SYM-SIZE %s
-# RUN: llvm-objdump -s -t %t-a | FileCheck -check-prefix=SYM-CONTENT %s
-
-# SYM-ADDR: Name: main (1)
-# SYM-ADDR-NEXT: Value: 0x400074
-
-# SYM-SIZE: Name: main (1)
-# SYM-SIZE-NEXT: Value: 0x{{[0-9a-f]+}}
-# SYM-SIZE-NEXT: Size: 28
-
-# SYM-CONTENT: Contents of section .text:
-# SYM-CONTENT-NEXT: 400074 04b02de5 00b08de2 0030a0e3 0300a0e1 ..-......0......
-# SYM-CONTENT-NEXT: 400084 00d04be2 04b09de4 1eff2fe1 ..K......./.
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/old-elf/ARM/defsym.test b/test/old-elf/ARM/defsym.test
deleted file mode 100644
index 7d4fa7fcd4dc..000000000000
--- a/test/old-elf/ARM/defsym.test
+++ /dev/null
@@ -1,50 +0,0 @@
-# Check that defined symbols are present in the generated executable
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu --defsym=main=fn \
-# RUN: -Bstatic --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck %s
-
-# CHECK: Name: main (1)
-# CHECK-NEXT: Value: 0x400074
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .text (0x1)
-# CHECK: Name: fn (6)
-# CHECK-NEXT: Value: 0x400074
-# CHECK-NEXT: Size: {{[0-9]+}}
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .text (0x1)
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: fn
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/old-elf/ARM/dynamic-symbols.test b/test/old-elf/ARM/dynamic-symbols.test
deleted file mode 100644
index 13963be8e701..000000000000
--- a/test/old-elf/ARM/dynamic-symbols.test
+++ /dev/null
@@ -1,83 +0,0 @@
-# Check that proper dynamic symbols are present in the generated executable
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=STATIC %s
-
-# STATIC-NOT: Name: _GLOBAL_OFFSET_TABLE_
-# STATIC-NOT: Name: _DYNAMIC
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=EXEC-DYN %s
-
-# EXEC-DYN: Name: _GLOBAL_OFFSET_TABLE_
-# EXEC-DYN-NEXT: Value: 0x401000
-# EXEC-DYN-NEXT: Size: 0
-# EXEC-DYN-NEXT: Binding: Global (0x1)
-# EXEC-DYN-NEXT: Type: Object (0x1)
-# EXEC-DYN-NEXT: Other: 0
-# EXEC-DYN-NEXT: Section: Absolute (0xFFF1)
-# EXEC-DYN: Name: _DYNAMIC
-# EXEC-DYN-NEXT: Value: 0x400130
-# EXEC-DYN-NEXT: Size: 0
-# EXEC-DYN-NEXT: Binding: Global (0x1)
-# EXEC-DYN-NEXT: Type: Object (0x1)
-# EXEC-DYN-NEXT: Other: 0
-# EXEC-DYN-NEXT: Section: Absolute (0xFFF1)
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -shared --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=SHARED %s
-
-# SHARED: Name: _GLOBAL_OFFSET_TABLE_
-# SHARED-NEXT: Value: 0x401000
-# SHARED-NEXT: Size: 0
-# SHARED-NEXT: Binding: Global (0x1)
-# SHARED-NEXT: Type: Object (0x1)
-# SHARED-NEXT: Other: 0
-# SHARED-NEXT: Section: Absolute (0xFFF1)
-# SHARED: Name: _DYNAMIC
-# SHARED-NEXT: Value: 0x4000EC
-# SHARED-NEXT: Size: 0
-# SHARED-NEXT: Binding: Global (0x1)
-# SHARED-NEXT: Type: Object (0x1)
-# SHARED-NEXT: Other: 0
-# SHARED-NEXT: Section: Absolute (0xFFF1)
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- - Name: .got
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: 0000
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/old-elf/ARM/entry-point.test b/test/old-elf/ARM/entry-point.test
deleted file mode 100644
index 4cfee4aa6c7b..000000000000
--- a/test/old-elf/ARM/entry-point.test
+++ /dev/null
@@ -1,113 +0,0 @@
-# 1. Check entry point address for ARM code - should be even.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-arm.o -o %t-arm
-# RUN: llvm-readobj -file-headers %t-arm | FileCheck -check-prefix=ARM-ENTRY %s
-#
-# ARM-ENTRY: Entry: 0x400074
-
-# 2. Check entry point address for Thumb code - should be odd.
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-thm.o -o %t-thm
-# RUN: llvm-readobj -file-headers %t-thm | FileCheck -check-prefix=THM-ENTRY %s
-#
-# THM-ENTRY: Entry: 0x400075
-
-# 3. Check wrong entry point address align for ARM code.
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-arm-wrong.o
-# RUN: not lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-arm-wrong.o -o %t-arm-wrong 2> %t-error
-# FileCheck -check-prefix=ARM-WRONG %s < %t-error
-#
-# ARM-WRONG: Two least bits must be zero for ARM entry point
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF00231846BD465DF8047B7047
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-
-# arm-wrong.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000006
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000002
-...
diff --git a/test/old-elf/ARM/exidx.test b/test/old-elf/ARM/exidx.test
deleted file mode 100644
index a277cfcd09ae..000000000000
--- a/test/old-elf/ARM/exidx.test
+++ /dev/null
@@ -1,254 +0,0 @@
-# .ARM.exidx contents checking
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target arm-none-linux-eabi -static -o %t %t.o
-# RUN: llvm-objdump -s -t -section-headers %t | FileCheck %s
-#
-# CHECK: Sections:
-# CHECK: Idx Name Size Address Type
-# CHECK: 2 .ARM.extab 0000000c 00000000004000b4 DATA
-# CHECK: 3 .ARM.exidx 00000018 00000000004000c0
-# CHECK: Contents of section .text:
-# CHECK: 4000a4 1846aff3 00801846 0837bd46 80bd00bf
-# ^
-# 4000b0: bd80 pop {r7, pc}
-# CHECK: Contents of section .ARM.extab:
-# CHECK: 4000b4 01970181 b0b00884 00000000
-# CHECK: Contents of section .ARM.exidx:
-# CHECK: 4000c0 b4ffff7f 08809780 bcffff7f 08809780
-# ^ offset to 400074 (__aeabi_unwind_cpp_pr0)
-# CHECK: 4000d0 c4ffff7f e0ffff7f
-# ^ ^
-# offset to 400094 (_start) handler at 4000B0
-#
-# CHECK: SYMBOL TABLE:
-# CHECK: 004000b4 .ARM.extab 00000000 $d.2
-# CHECK: 004000c0 .ARM.exidx 00000000 $d.1
-# CHECK: 00400074 g F .text 00000010 __aeabi_unwind_cpp_pr0
-# CHECK: 00400094 g F .text 00000020 _start
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF00231846BD465DF8047B704780B400AF00231846BD465DF8047B704780B582B000AF3B1D1846FFF7FEFF3B1D1846FFF7FEFF18460837BD4680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x000000000000002A
- Symbol: _ZN1AILi1EEC1Ev
- Type: R_ARM_THM_CALL
- - Offset: 0x0000000000000032
- Symbol: _ZN1AILi1EED1Ev
- Type: R_ARM_THM_CALL
- - Name: .ARM.extab
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: 01970181B0B0088400000000
- - Name: .ARM.exidx
- Type: SHT_ARM_EXIDX
- Flags: [ SHF_ALLOC, SHF_LINK_ORDER ]
- Link: .text
- AddressAlign: 0x0000000000000004
- Content: '000000000880978010000000088097802000000000000000'
- - Name: .rel.ARM.exidx
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .ARM.exidx
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: .text
- Type: R_ARM_PREL31
- - Offset: 0x0000000000000000
- Symbol: __aeabi_unwind_cpp_pr0
- Type: R_ARM_NONE
- - Offset: 0x0000000000000008
- Symbol: .text
- Type: R_ARM_PREL31
- - Offset: 0x0000000000000010
- Symbol: .text
- Type: R_ARM_PREL31
- - Offset: 0x0000000000000010
- Symbol: __aeabi_unwind_cpp_pr1
- Type: R_ARM_NONE
- - Offset: 0x0000000000000014
- Symbol: .ARM.extab
- Type: R_ARM_PREL31
- - Name: .text._ZN1AILi1EEC2Ev
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000004
- Content: 80B582B000AF78600120FFF7FEFF7B6818460837BD4680BD
- - Name: .rel.text._ZN1AILi1EEC2Ev
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text._ZN1AILi1EEC2Ev
- Relocations:
- - Offset: 0x000000000000000A
- Symbol: f
- Type: R_ARM_THM_CALL
- - Name: .ARM.extab.text._ZN1AILi1EEC2Ev
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_GROUP ]
- AddressAlign: 0x0000000000000004
- Content: 01970181B0B0088400000000
- - Name: .ARM.exidx.text._ZN1AILi1EEC2Ev
- Type: SHT_ARM_EXIDX
- Flags: [ SHF_ALLOC, SHF_LINK_ORDER, SHF_GROUP ]
- Link: .text._ZN1AILi1EEC2Ev
- AddressAlign: 0x0000000000000004
- Content: '0000000000000000'
- - Name: .rel.ARM.exidx.text._ZN1AILi1EEC2Ev
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .ARM.exidx.text._ZN1AILi1EEC2Ev
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: .text._ZN1AILi1EEC2Ev
- Type: R_ARM_PREL31
- - Offset: 0x0000000000000000
- Symbol: __aeabi_unwind_cpp_pr1
- Type: R_ARM_NONE
- - Offset: 0x0000000000000004
- Symbol: .ARM.extab.text._ZN1AILi1EEC2Ev
- Type: R_ARM_PREL31
- - Name: .text._ZN1AILi1EED2Ev
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000004
- Content: 80B582B000AF78604FF0FF30FFF7FEFF7B6818460837BD4680BD00BF
- - Name: .rel.text._ZN1AILi1EED2Ev
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text._ZN1AILi1EED2Ev
- Relocations:
- - Offset: 0x000000000000000C
- Symbol: f
- Type: R_ARM_THM_CALL
- - Name: .ARM.extab.text._ZN1AILi1EED2Ev
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_GROUP ]
- AddressAlign: 0x0000000000000004
- Content: 01970181B0B0088400000000
- - Name: .ARM.exidx.text._ZN1AILi1EED2Ev
- Type: SHT_ARM_EXIDX
- Flags: [ SHF_ALLOC, SHF_LINK_ORDER, SHF_GROUP ]
- Link: .text._ZN1AILi1EED2Ev
- AddressAlign: 0x0000000000000004
- Content: '0000000000000000'
- - Name: .rel.ARM.exidx.text._ZN1AILi1EED2Ev
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .ARM.exidx.text._ZN1AILi1EED2Ev
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: .text._ZN1AILi1EED2Ev
- Type: R_ARM_PREL31
- - Offset: 0x0000000000000000
- Symbol: __aeabi_unwind_cpp_pr1
- Type: R_ARM_NONE
- - Offset: 0x0000000000000004
- Symbol: .ARM.extab.text._ZN1AILi1EED2Ev
- Type: R_ARM_PREL31
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: '$t.1'
- Section: .text
- - Name: .ARM.extab
- Type: STT_SECTION
- Section: .ARM.extab
- - Name: .ARM.exidx
- Type: STT_SECTION
- Section: .ARM.exidx
- - Name: '$d.1'
- Section: .ARM.exidx
- - Name: '$d.2'
- Section: .ARM.extab
- - Name: .text._ZN1AILi1EEC2Ev
- Type: STT_SECTION
- Section: .text._ZN1AILi1EEC2Ev
- - Name: '$t.2'
- Section: .text._ZN1AILi1EEC2Ev
- - Name: .ARM.extab.text._ZN1AILi1EEC2Ev
- Type: STT_SECTION
- Section: .ARM.extab.text._ZN1AILi1EEC2Ev
- - Name: '$d.3'
- Section: .ARM.extab.text._ZN1AILi1EEC2Ev
- - Name: .ARM.exidx.text._ZN1AILi1EEC2Ev
- Type: STT_SECTION
- Section: .ARM.exidx.text._ZN1AILi1EEC2Ev
- - Name: '$d.4'
- Section: .ARM.exidx.text._ZN1AILi1EEC2Ev
- - Name: .text._ZN1AILi1EED2Ev
- Type: STT_SECTION
- Section: .text._ZN1AILi1EED2Ev
- - Name: '$t.3'
- Section: .text._ZN1AILi1EED2Ev
- - Name: .ARM.extab.text._ZN1AILi1EED2Ev
- Type: STT_SECTION
- Section: .ARM.extab.text._ZN1AILi1EED2Ev
- - Name: '$d.5'
- Section: .ARM.extab.text._ZN1AILi1EED2Ev
- - Name: .ARM.exidx.text._ZN1AILi1EED2Ev
- Type: STT_SECTION
- Section: .ARM.exidx.text._ZN1AILi1EED2Ev
- - Name: '$d.6'
- Section: .ARM.exidx.text._ZN1AILi1EED2Ev
- Global:
- - Name: __aeabi_unwind_cpp_pr0
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x0000000000000010
- - Name: __aeabi_unwind_cpp_pr1
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000011
- Size: 0x0000000000000010
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000021
- Size: 0x000000000000001E
- Weak:
- - Name: _ZN1AILi1EEC1Ev
- Type: STT_FUNC
- Section: .text._ZN1AILi1EEC2Ev
- Value: 0x0000000000000001
- Size: 0x0000000000000018
- - Name: _ZN1AILi1EED1Ev
- Type: STT_FUNC
- Section: .text._ZN1AILi1EED2Ev
- Value: 0x0000000000000001
- Size: 0x000000000000001A
- - Name: _ZN1AILi1EEC2Ev
- Type: STT_FUNC
- Section: .text._ZN1AILi1EEC2Ev
- Value: 0x0000000000000001
- Size: 0x0000000000000018
- - Name: f
- - Name: _ZN1AILi1EED2Ev
- Type: STT_FUNC
- Section: .text._ZN1AILi1EED2Ev
- Value: 0x0000000000000001
- Size: 0x000000000000001A
-...
diff --git a/test/old-elf/ARM/header-flags.test b/test/old-elf/ARM/header-flags.test
deleted file mode 100644
index 735d65225216..000000000000
--- a/test/old-elf/ARM/header-flags.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# Various checks for header flags.
-
-# 1. Check header flags for statically linked executable with default options.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t.o -o %t
-# RUN: llvm-readobj -file-headers %t | FileCheck -check-prefix=STATIC-DEF %s
-#
-# STATIC-DEF: Flags {{.}} (0x5000400)
-# ABI version 5 + hard float ^^
-
-# 2. Check header flags for dynamically linked executable with default options.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi \
-# RUN: --noinhibit-exec %t.o -o %t
-# RUN: llvm-readobj -file-headers %t | FileCheck -check-prefix=EXEC-DYN-DEF %s
-#
-# EXEC-DYN-DEF: Flags {{.}} (0x5000400)
-# ABI version 5 + hard float ^^
-
-# 3. Check header flags for shared object with default options.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -shared \
-# RUN: --noinhibit-exec %t.o -o %t
-# RUN: llvm-readobj -file-headers %t | FileCheck -check-prefix=SHARED-DEF %s
-#
-# SHARED-DEF: Flags {{.}} (0x5000400)
-# ABI version 5 + hard float ^^
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/old-elf/ARM/mapping-code-model.test b/test/old-elf/ARM/mapping-code-model.test
deleted file mode 100644
index affa10b464f8..000000000000
--- a/test/old-elf/ARM/mapping-code-model.test
+++ /dev/null
@@ -1,160 +0,0 @@
-# Check that mapping symbols are treated as ARM or Thumb code properly.
-#
-# 1. ARM <=> Thumb generates both veneers.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-a-arm.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-t-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu --defsym=main=f_a \
-# RUN: -Bstatic --noinhibit-exec %t-a-arm.o %t-t-thm.o -o %t
-# RUN: llvm-objdump -t %t | FileCheck -check-prefix=INTER %s
-
-# INTER: SYMBOL TABLE:
-# INTER: {{[0-9a-f]+}} l F .text {{[0-9a-f]+}} __f_t_from_arm
-# INTER: {{[0-9a-f]+}} l F .text {{[0-9a-f]+}} __f_a_from_thumb
-
-# 2. Thumb <=> Thumb doesn't generate veneers.
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-a-thm.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-t-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu --defsym=main=f_t \
-# RUN: -Bstatic --noinhibit-exec %t-t-thm.o %t-a-thm.o -o %t
-# RUN: llvm-objdump -t %t | FileCheck -check-prefix=THUMB %s
-
-# THUMB: SYMBOL TABLE:
-# THUMB-NOT: {{[0-9a-f]+}} l F .text {{[0-9a-f]+}} __f_t_from_thumb
-# THUMB-NOT: {{[0-9a-f]+}} l F .text {{[0-9a-f]+}} __f_a_from_thumb
-
-# f-a-arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00482DE904B08DE2FEFFFFEBFEFFFFEA0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: f_t
- Type: R_ARM_CALL
- - Offset: 0x000000000000000C
- Symbol: f_t
- Type: R_ARM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$a'
- Section: .text
- Size: 0x0000000000000002
- - Name: '$a.f_a'
- Section: .text
- Value: 0x0000000000000002
- Global:
- - Name: f_a
- Type: STT_FUNC
- Section: .text
- - Name: f_t
-
-# f-a-thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF00231846BD465DF8047B7047
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$t'
- Section: .text
- Size: 0x0000000000000002
- - Name: '$t.f_a'
- Section: .text
- Value: 0x0000000000000002
- Global:
- - Name: f_a
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-
-# f-t-thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B500AFFFF7FEFFFFF7FEBF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: f_a
- Type: R_ARM_THM_CALL
- - Offset: 0x0000000000000008
- Symbol: f_a
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$t'
- Section: .text
- Size: 0x0000000000000002
- - Name: '$t.f_t'
- Section: .text
- Value: 0x0000000000000002
- Global:
- - Name: f_t
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: f_a
-...
diff --git a/test/old-elf/ARM/mapping-symbols.test b/test/old-elf/ARM/mapping-symbols.test
deleted file mode 100644
index c6a4b7afc50b..000000000000
--- a/test/old-elf/ARM/mapping-symbols.test
+++ /dev/null
@@ -1,122 +0,0 @@
-# Check that mapping symbols have zero size, local binding and none type.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-a.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-t.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-a.o %t-t.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck %s
-
-# CHECK: Name: $a (1)
-# CHECK-NEXT: Value: 0x{{[0-9a-f]+}}
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-#
-# CHECK: Name: $t (9)
-# CHECK-NEXT: Value: 0x{{[0-9a-f]+}}
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-#
-# CHECK: Name: $d (24)
-# CHECK-NEXT: Value: 0x{{[0-9a-f]+}}
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00482DE904B08DE2FEFFFFEB0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: _Z1fv
- Type: R_ARM_CALL
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$a'
- Section: .text
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- - Name: _Z1fv
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF40F20003C0F200031B681846BD465DF8047B7047
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: _ZL1i
- Type: R_ARM_THM_MOVW_ABS_NC
- - Offset: 0x0000000000000008
- Symbol: _ZL1i
- Type: R_ARM_THM_MOVT_ABS
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Size: 4
-Symbols:
- Local:
- - Name: _ZL1i
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- - Name: '$d'
- Section: .bss
- - Name: '$t'
- Section: .text
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/old-elf/ARM/missing-symbol.test b/test/old-elf/ARM/missing-symbol.test
deleted file mode 100644
index a0d3dd51e57b..000000000000
--- a/test/old-elf/ARM/missing-symbol.test
+++ /dev/null
@@ -1,38 +0,0 @@
-# Check that _MISSING_SYMBOL_ symbol is not resolved
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t 2>&1 | FileCheck %s
-
-# CHECK: Undefined symbol: {{.*}}: _MISSING_SYMBOL_
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B483B000AF40F20003C0F200037B60002318460C37BD465DF8047B704700BF
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: _MISSING_SYMBOL_
-...
diff --git a/test/old-elf/ARM/plt-dynamic.test b/test/old-elf/ARM/plt-dynamic.test
deleted file mode 100644
index 905f628edb49..000000000000
--- a/test/old-elf/ARM/plt-dynamic.test
+++ /dev/null
@@ -1,200 +0,0 @@
-# Check that PLT entries are properly generated when link dynamically.
-#
-# 1. ARM code generates PLT entries.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: --noinhibit-exec %t-arm.o -lfn -L%p/Inputs -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=ARM %s
-
-# ARM: Contents of section .rel.plt:
-# ARM-NEXT: 400134 0c104000 16010000
-# GOT addr = 0x40100c ^^
-# ARM-NEXT: Contents of section .plt:
-# ARM-NEXT: 40013c 04e02de5 04e09fe5 0ee08fe0 00f0bee5
-# ^ -- PLT0 --
-# ARM-NEXT: 40014c bc0e0000 00c68fe2 00ca8ce2 b4febce5
-# -- ^ ^ -- PLT_fn -- ^
-# ARM-NEXT: Contents of section .text:
-# ARM-NEXT: 40015c {{[0-9a-f]+}} {{[0-9a-f]+}} f9ffffea
-# b PLT_fn ^^
-# ARM: Contents of section .got.plt:
-# ARM-NEXT: 401000 00000000 00000000 00000000 3c014000
-# PLT0 addr = 0x40013c ^^
-
-# 2. Thumb code generates PLT entries with veneers.
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: --noinhibit-exec %t-thm.o -lfn -L%p/Inputs -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM %s
-
-# THM: Contents of section .rel.plt:
-# THM-NEXT: 400134 0c104000 16010000
-# GOT addr = 0x40100c ^^
-# THM-NEXT: Contents of section .plt:
-# THM-NEXT: 40013c 04e02de5 04e09fe5 0ee08fe0 00f0bee5
-# ^ -- PLT0 --
-# THM-NEXT: 40014c bc0e0000 78470000 00c68fe2 00ca8ce2
-# -- ^ veneer ^ ^ -- PLT_fn --
-# THM-NEXT: 40015c b0febce5
-# -- ^
-# THM: Contents of section .text:
-# THM-NEXT: 400160 {{[0-9a-f]+}} fff7f4bf
-# b PLT_fn ^^
-
-# 3. Thumb code generates PLT entries without veneers when bl->blx is done.
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: --noinhibit-exec %t-thm.o -lfn -L%p/Inputs -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-BLX %s
-
-# THM-BLX: Contents of section .rel.plt:
-# THM-BLX-NEXT: 400134 0c104000 16010000
-# GOT addr = 0x40100c ^^
-# THM-BLX-NEXT: Contents of section .plt:
-# THM-BLX-NEXT: 40013c 04e02de5 04e09fe5 0ee08fe0 00f0bee5
-# ^ -- PLT0 --
-# THM-BLX-NEXT: 40014c bc0e0000 00c68fe2 00ca8ce2 b4febce5
-# -- ^ ^ -- PLT_fn -- ^
-# THM-BLX: Contents of section .text:
-# THM-BLX-NEXT: 40015c {{[0-9a-f]+}} fff7f6ef
-# blx PLT_fn ^^
-
-# Generation of mapping symbols.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: --noinhibit-exec %t-arm.o -lfn -L%p/Inputs -o %t-arm
-# RUN: llvm-readobj -symbols %t-arm | FileCheck -check-prefix=ARM-MAPPING %s
-
-# ARM-MAPPING: Name: {{[$]?[a]?[.]?}}__PLT0
-# ARM-MAPPING: Name: {{[$]?[d]?[.]?}}__PLT0_d
-# ARM-MAPPING: Name: {{[$]?[a]?[.]?}}__plt_fn
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: --noinhibit-exec %t-thm.o -lfn -L%p/Inputs -o %t-thm
-# RUN: llvm-readobj -symbols %t-thm | FileCheck -check-prefix=THM-MAPPING %s
-
-# THM-MAPPING: Name: {{[$]?[a]?[.]?}}__PLT0
-# THM-MAPPING: Name: {{[$]?[d]?[.]?}}__PLT0_d
-# THM-MAPPING: Name: {{[$]?[t]?[.]?}}__plt_from_thumb_fn
-# THM-MAPPING: Name: {{[$]?[a]?[.]?}}__plt_fn
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: fn
- Type: R_ARM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- - Name: fn
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B500AFFFF7FEBF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: fn
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: fn
-
-# thm-c.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B500AFFFF7FEFF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: fn
- Type: R_ARM_THM_CALL
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: fn
-...
diff --git a/test/old-elf/ARM/plt-ifunc-interwork.test b/test/old-elf/ARM/plt-ifunc-interwork.test
deleted file mode 100644
index 29d8282edf26..000000000000
--- a/test/old-elf/ARM/plt-ifunc-interwork.test
+++ /dev/null
@@ -1,396 +0,0 @@
-# Check that PLT entries are properly generated for cases when
-# referenced from both ARM and Thumb code.
-#
-# 1. ARM code generates PLT without transition veneer.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-arm.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=ARM-ONE %s
-
-# ARM-ONE: Contents of section .plt:
-# ARM-ONE-NEXT: 40007c 00c68fe2 00ca8ce2 7cffbce5
-# ^ regular veneer ^
-# Next line shows that .plt section ends.
-# ARM-ONE-NEXT: Contents of section .text:
-
-# 2. Thumb code generates PLT with transition veneer.
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-f1-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-thm.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-ONE %s
-
-# THM-ONE: Contents of section .plt:
-# THM-ONE-NEXT: 40007c 78470000 00c68fe2 00ca8ce2 78ffbce5
-# bx pc ^^ ^ regular veneer ^
-# Next line shows that .plt section ends.
-# THM-ONE-NEXT: Contents of section .text:
-
-# 3. ARM + Thumb code generate same single PLT with transition veneer.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-f1-thm-for-arm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-arm.o %t-f1-thm-for-arm.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-ONE %s
-
-# 4. Thumb + ARM code generate same single PLT with transition veneer.
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-f1-thm-for-arm.o
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-thm-for-arm.o %t-f1-arm.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-ONE %s
-
-# 5. ARM + ARM code generate two PLTs without transition veneers.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
-# RUN: yaml2obj -format=elf -docnum 4 %s > %t-f2-arm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-arm.o %t-f2-arm.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=ARM-TWO %s
-
-# ARM-TWO: Contents of section .plt:
-# ARM-TWO-NEXT: 400084 00c68fe2 00ca8ce2 74ffbce5 00c68fe2
-# ^ regular veneer 1 ^ ^ --
-# ARM-TWO-NEXT: 400094 00ca8ce2 6cffbce5
-# --- regular veneer 2 ^
-# Next line shows that .plt section ends.
-# ARM-TWO-NEXT: Contents of section .text:
-
-# 6. ARM + Thumb code generate two PLTs without and with transition veneer.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-f1-arm.o
-# RUN: yaml2obj -format=elf -docnum 5 %s > %t-f2-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-arm.o %t-f2-thm.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=ARM-THM-TWO %s
-
-# ARM-THM-TWO: Contents of section .plt:
-# ARM-THM-TWO-NEXT: 400084 00c68fe2 00ca8ce2 74ffbce5 78470000
-# ^ regular veneer 1 ^ ^^ bx pc 2
-# ARM-THM-TWO-NEXT: 400094 00c68fe2 00ca8ce2 68ffbce5
-# ^ regular veneer 2 ^
-# Next line shows that .plt section ends.
-# ARM-THM-TWO-NEXT: Contents of section .text:
-
-# 7. Thumb + ARM code generate two PLTs with and without transition veneer.
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-f1-thm.o
-# RUN: yaml2obj -format=elf -docnum 4 %s > %t-f2-arm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-thm.o %t-f2-arm.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-ARM-TWO %s
-
-# THM-ARM-TWO: Contents of section .plt:
-# THM-ARM-TWO-NEXT: 400084 78470000 00c68fe2 00ca8ce2 70ffbce
-# bx pc 1 ^^ ^ regular veneer 1 ^
-# THM-ARM-TWO-NEXT: 400094 00c68fe2 00ca8ce2 68ffbce5
-# ^ regular veneer 2 ^
-# Next line shows that .plt section ends.
-# THM-ARM-TWO-NEXT: Contents of section .text:
-
-# 8. Thumb + Thumb code generate two PLTs with transition veneers.
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-f1-thm.o
-# RUN: yaml2obj -format=elf -docnum 5 %s > %t-f2-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-thm.o %t-f2-thm.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-TWO %s
-
-# THM-TWO: Contents of section .plt:
-# THM-TWO-NEXT: 400084 78470000 00c68fe2 00ca8ce2 70ffbce5
-# bx pc 1 ^^ ^ regular veneer 1 ^
-# THM-TWO-NEXT: 400094 78470000 00c68fe2 00ca8ce2 64ffbce5
-# bx pc 2 ^^ ^ regular veneer 2 ^
-# Next line shows that .plt section ends.
-# THM-TWO-NEXT: Contents of section .text:
-
-# 9. Thumb code generates PLT without transition veneer when bl->blx is done.
-# RUN: yaml2obj -format=elf -docnum 6 %s > %t-f1-thm-c.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-f1-thm-c.o -o %t
-# RUN: llvm-objdump -s %t | FileCheck -check-prefix=THM-BL %s
-
-# THM-BL: Contents of section .plt:
-# THM-BL-NEXT: 40007c 00c68fe2 00ca8ce2 7cffbce5
-# ^ regular veneer ^
-# Next line shows that .plt section ends.
-# THM-BL-NEXT: Contents of section .text:
-
-# f1-arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE2003000E3003040E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: main
- Type: R_ARM_MOVW_ABS_NC
- - Offset: 0x000000000000000C
- Symbol: main
- Type: R_ARM_MOVT_ABS
- - Offset: 0x0000000000000028
- Symbol: f1
- Type: R_ARM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f1
- Type: STT_GNU_IFUNC
- Section: .text
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000020
-
-# f1-thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF40F20003C0F200031846BD465DF8047B704700BF80B500AFFFF7FEBF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: main
- Type: R_ARM_THM_MOVW_ABS_NC
- - Offset: 0x0000000000000008
- Symbol: main
- Type: R_ARM_THM_MOVT_ABS
- - Offset: 0x000000000000001C
- Symbol: f1
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f1
- Type: STT_GNU_IFUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000019
-
-# f1-thm-for-arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B500AFFFF7FEBF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: f1
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: f1
-
-# f2-arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE2003000E3003040E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: f
- Type: R_ARM_MOVW_ABS_NC
- - Offset: 0x000000000000000C
- Symbol: f
- Type: R_ARM_MOVT_ABS
- - Offset: 0x0000000000000028
- Symbol: f2
- Type: R_ARM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f2
- Type: STT_GNU_IFUNC
- Section: .text
- - Name: f
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000020
-
-# f2-thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF40F20003C0F200031846BD465DF8047B704700BF80B500AFFFF7FEBF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: f
- Type: R_ARM_THM_MOVW_ABS_NC
- - Offset: 0x0000000000000008
- Symbol: f
- Type: R_ARM_THM_MOVT_ABS
- - Offset: 0x000000000000001C
- Symbol: f2
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f2
- Type: STT_GNU_IFUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: f
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000019
-
-# f1-thm-c.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF40F20003C0F200031846BD465DF8047B704700BF80B500AFFFF7FEFF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: main
- Type: R_ARM_THM_MOVW_ABS_NC
- - Offset: 0x0000000000000008
- Symbol: main
- Type: R_ARM_THM_MOVT_ABS
- - Offset: 0x000000000000001C
- Symbol: f1
- Type: R_ARM_THM_CALL
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f1
- Type: STT_GNU_IFUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000019
-...
diff --git a/test/old-elf/ARM/plt-ifunc-mapping.test b/test/old-elf/ARM/plt-ifunc-mapping.test
deleted file mode 100644
index 8c6d23aec084..000000000000
--- a/test/old-elf/ARM/plt-ifunc-mapping.test
+++ /dev/null
@@ -1,109 +0,0 @@
-# Check that mapping symbols are properly generated for IFUNC PLT entries.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-arm.o %t-thm.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck %s
-
-# CHECK: Name: {{[$]?[a]?[.]?}}__plt_ifunc_f1
-# CHECK: Name: {{[$]?[t]?[.]?}}__plt_from_thumb_ifunc_f2
-# CHECK: Name: {{[$]?[a]?[.]?}}__plt_ifunc_f2
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE2003000E3003040E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: main
- Type: R_ARM_MOVW_ABS_NC
- - Offset: 0x000000000000000C
- Symbol: main
- Type: R_ARM_MOVT_ABS
- - Offset: 0x0000000000000028
- Symbol: f1
- Type: R_ARM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f1
- Type: STT_GNU_IFUNC
- Section: .text
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000020
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF40F20003C0F200031846BD465DF8047B704700BF80B500AFFFF7FEBF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: f
- Type: R_ARM_THM_MOVW_ABS_NC
- - Offset: 0x0000000000000008
- Symbol: f
- Type: R_ARM_THM_MOVT_ABS
- - Offset: 0x000000000000001C
- Symbol: f2
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f2
- Type: STT_GNU_IFUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: f
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000019
-...
diff --git a/test/old-elf/ARM/rel-abs32.test b/test/old-elf/ARM/rel-abs32.test
deleted file mode 100644
index 7dcf632f53d3..000000000000
--- a/test/old-elf/ARM/rel-abs32.test
+++ /dev/null
@@ -1,58 +0,0 @@
-# Check handling of R_ARM_ABS32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401000 84004000
-# data = 0x400084 ^^
-# data main addr content
-# 0x400084 = 0x400074 + 0x10
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} main
-# CHECK: 00401000 g .data 00000004 data
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '10000000'
- - Name: .rel.data
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .data
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: main
- Type: R_ARM_ABS32
- Addend: 0
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000001C
- - Name: data
- Type: STT_OBJECT
- Section: .data
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/ARM/rel-arm-call.test b/test/old-elf/ARM/rel-arm-call.test
deleted file mode 100644
index 64b789204286..000000000000
--- a/test/old-elf/ARM/rel-arm-call.test
+++ /dev/null
@@ -1,112 +0,0 @@
-# Check handling of R_ARM_CALL relocation.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400084 1eff2fe1 00482de9 04b08de2 f7ffffeb
-# offset = -0x24 ^^
-# call site offset PC(arm) _Z1fv addr
-# 0x400090 + (-0x24) + 0x8 = 0x400074
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} _Z1fv
-# CHECK: 00400088 g F .text {{[0-9a-f]+}} main
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: not lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t 2> %t-error
-# RUN: FileCheck -check-prefix=OVERFLOW %s < %t-error
-
-# OVERFLOW: Relocation out of range {{.*}} (R_ARM_CALL)
-
-# good.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE200D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEB0030A0E30300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x000000000000001C
- Symbol: _Z1fv
- Type: R_ARM_CALL
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000014
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000014
- Size: 0x0000000000000018
-
-# overflow.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE200D04BE204B09DE41EFF2FE100482DE904B08DE2000080EB0030A0E30300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x000000000000001C
- Symbol: _Z1fv
- Type: R_ARM_CALL
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000014
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000014
- Size: 0x0000000000000018
-...
diff --git a/test/old-elf/ARM/rel-arm-jump24-veneer-b.test b/test/old-elf/ARM/rel-arm-jump24-veneer-b.test
deleted file mode 100644
index 76e9523dbbe7..000000000000
--- a/test/old-elf/ARM/rel-arm-jump24-veneer-b.test
+++ /dev/null
@@ -1,122 +0,0 @@
-# Check veneer generation for R_ARM_JUMP24 relocation (B instruction call).
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=STATIC %s
-
-# STATIC: Contents of section .text:
-# STATIC: 400074 010000ea
-# Call from main:
-# offset = 0x4 ^^
-# call site offset PC(arm) ___Z1fv_from_arm addr
-# 0x400074 + 0x4 + 0x8 = 0x400080
-#
-# Code of the veneer:
-# STATIC: {{[0-9a-f]+}} {{[0-9a-f]+}} 04f01fe5
-# STATIC: 400084 79004000
-# ^^ call addr = 0x400079
-# call addr _Z1fv addr Thumb mode
-# 0x400079 = 0x400078 | 0x1
-#
-# STATIC: SYMBOL TABLE:
-# STATIC: 00400080 l F .text {{[0-9a-f]+}} ___Z1fv_from_arm
-# STATIC: 00400074 g F .text {{[0-9a-f]+}} main
-# STATIC: 00400078 g F .text {{[0-9a-f]+}} _Z1fv
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi \
-# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=EXEC-DYN %s
-
-# EXEC-DYN: Contents of section .text:
-# EXEC-DYN: 400114 010000ea
-# Call from main:
-# offset = 0x4 ^^
-# call site offset PC(arm) ___Z1fv_from_arm addr
-# 0x400114 + 0x4 + 0x8 = 0x400120
-#
-# Code of the veneer:
-# EXEC-DYN: {{[0-9a-f]+}} {{[0-9a-f]+}} 04f01fe5
-# EXEC-DYN: 400124 19014000
-# call addr = 0x400119 ^^
-# call addr _Z1fv addr Thumb mode
-# 0x400119 = 0x400118 | 0x1
-#
-# EXEC-DYN: SYMBOL TABLE:
-# EXEC-DYN: 00400120 l F .text {{[0-9a-f]+}} ___Z1fv_from_arm
-# EXEC-DYN: 00400114 g F .text {{[0-9a-f]+}} main
-# EXEC-DYN: 00400118 g F .text {{[0-9a-f]+}} _Z1fv
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: FEFFFFEA
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: _Z1fv
- Type: R_ARM_JUMP24
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- - Name: _Z1fv
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 4FF0000318467047
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/old-elf/ARM/rel-arm-jump24-veneer-bl.test b/test/old-elf/ARM/rel-arm-jump24-veneer-bl.test
deleted file mode 100644
index 300355fbb11c..000000000000
--- a/test/old-elf/ARM/rel-arm-jump24-veneer-bl.test
+++ /dev/null
@@ -1,120 +0,0 @@
-# Check veneer generation for R_ARM_JUMP24 relocation (BL<c> instruction call).
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=STATIC %s
-
-# STATIC: Contents of section .text:
-# STATIC: 400084 0400000b
-# Call from main:
-# offset = 0x10 ^^
-# call site offset PC(arm) ___Z1fv_from_arm addr
-# 0x400084 + 0x10 + 0x8 = 0x40009c
-#
-# Code of the veneer:
-# STATIC: 400094 {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 95004000
-# call addr = 0x400095 ^^
-# call addr _Z1fv addr Thumb mode
-# 0x400095 = 0x400094 | 0x1
-#
-# STATIC: SYMBOL TABLE:
-# STATIC: 0040009c l F .text {{[0-9a-f]+}} ___Z1fv_from_arm
-# STATIC: 00400074 g F .text {{[0-9a-f]+}} main
-# STATIC: 00400094 g F .text {{[0-9a-f]+}} _Z1fv
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi \
-# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=EXEC-DYN %s
-
-# EXEC-DYN: Contents of section .text:
-# EXEC-DYN: 400124 0400000b
-# Call from main:
-# offset = 0x10 ^^
-# call site offset PC(arm) ___Z1fv_from_arm addr
-# 0x400124 + 0x10 + 0x8 = 0x40013c
-#
-# Code of the veneer:
-# EXEC-DYN: 400134 {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 35014000
-# call addr = 0x400135 ^^
-# call addr _Z1fv addr Thumb mode
-# 0x400135 = 0x400134 | 0x1
-#
-# EXEC-DYN: SYMBOL TABLE:
-# EXEC-DYN: 0040013c l F .text {{[0-9a-f]+}} ___Z1fv_from_arm
-# EXEC-DYN: 00400114 g F .text {{[0-9a-f]+}} main
-# EXEC-DYN: 00400134 g F .text {{[0-9a-f]+}} _Z1fv
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00482DE904B08DE20030A0E3000053E3FEFFFF0B0030A0E30300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000010
- Symbol: _Z1fv
- Type: R_ARM_JUMP24
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- - Name: _Z1fv
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 4FF0000318467047
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/old-elf/ARM/rel-arm-jump24.test b/test/old-elf/ARM/rel-arm-jump24.test
deleted file mode 100644
index c0d8ccc8d386..000000000000
--- a/test/old-elf/ARM/rel-arm-jump24.test
+++ /dev/null
@@ -1,108 +0,0 @@
-# Check handling of R_ARM_JUMP24 relocation.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400094 04b08de2 f5ffffea 0030a0e1 0300a0e1
-# offset = -0x2C ^^
-# call site offset PC(arm) _Z1fv addr
-# 0x400098 + (-0x2C) + 0x8 = 0x400074
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} _Z1fv
-# CHECK: 00400090 g F .text {{[0-9a-f]+}} main
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: not lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t 2> %t-error
-# RUN: FileCheck -check-prefix=OVERFLOW %s < %t-error
-
-# OVERFLOW: Relocation out of range {{.*}} (R_ARM_JUMP24)
-
-# good.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000024
- Symbol: _Z1fv
- Type: R_ARM_JUMP24
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000001C
-
-# overflow.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2000080EA0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000024
- Symbol: _Z1fv
- Type: R_ARM_JUMP24
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000001C
-...
diff --git a/test/old-elf/ARM/rel-arm-mov.test b/test/old-elf/ARM/rel-arm-mov.test
deleted file mode 100644
index b492cc259060..000000000000
--- a/test/old-elf/ARM/rel-arm-mov.test
+++ /dev/null
@@ -1,64 +0,0 @@
-# Check handling of R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS relocation pair.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400074 04b02de5 00b08de2 003001e3 403040e3
-# addrL = 0x1000 ^^
-# addrH = 0x40 ^^
-# addrH addrL _ZL5data1 addr
-# (0x40 << 16) + 0x1000 = 0x401000
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401000 l .bss 00000004 _ZL5data1
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} main
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE2003000E3003040E30A20A0E3002083E50030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: _ZL5data1
- Type: R_ARM_MOVW_ABS_NC
- Addend: 0
- - Offset: 0x000000000000000C
- Symbol: _ZL5data1
- Type: R_ARM_MOVT_ABS
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Size: 4
-Symbols:
- Local:
- - Name: _ZL5data1
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/old-elf/ARM/rel-arm-prel31.test b/test/old-elf/ARM/rel-arm-prel31.test
deleted file mode 100644
index b07d5dd9fd75..000000000000
--- a/test/old-elf/ARM/rel-arm-prel31.test
+++ /dev/null
@@ -1,90 +0,0 @@
-# Check handling of R_ARM_PREL31 relocation.
-# RUN: yaml2obj -format=elf -docnum=1 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec --defsym=main=__gxx_personality_v0 %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .ARM.extab:
-# CHECK: 4000a4 b1fffe7f
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400054 g F .text {{[0-9a-f]+}} __gxx_personality_v0
-
-# RUN: yaml2obj -format=elf -docnum=2 %s > %t-o.o
-# RUN: not lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec --defsym=main=__gxx_personality_v0 %t-o.o -o %t 2> %t-error
-# RUN: FileCheck -check-prefix=OVERFLOW %s < %t-error
-
-# OVERFLOW: Relocation out of range {{.*}} (R_ARM_PREL31)
-
-# good.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .ARM.extab
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x4
- Content: 0000FF7F84019701B0B0B008FFFF01080E2432003A040000
- - Name: .rel.ARM.extab
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x4
- Info: .ARM.extab
- Relocations:
- - Offset: 0
- Symbol: __gxx_personality_v0
- Type: R_ARM_PREL31
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x4
- Content: 80B400AF00231846BD465DF8047B704780B582B000AF3B1D1846FFF7FEFFFFF7FEFFFFF7FEFF0420FFF7FEFF0346184601230360002240F20001C0F20001FFF7FEFF3B1D1846FFF7FEFFFFF7FEFF00BF
-Symbols:
- Local:
- Global:
- - Name: __gxx_personality_v0
- Type: STT_FUNC
- Section: .text
- Value: 0x1
-
-# overflow.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .ARM.extab
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x4
- Content: 0000004084019701B0B0B008FFFF01080E2432003A040000
- - Name: .rel.ARM.extab
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x4
- Info: .ARM.extab
- Relocations:
- - Offset: 0
- Symbol: __gxx_personality_v0
- Type: R_ARM_PREL31
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x4
- Content: 80B400AF00231846BD465DF8047B704780B582B000AF3B1D1846FFF7FEFFFFF7FEFFFFF7FEFF0420FFF7FEFF0346184601230360002240F20001C0F20001FFF7FEFF3B1D1846FFF7FEFFFFF7FEFF00BF
-Symbols:
- Local:
- Global:
- - Name: __gxx_personality_v0
- Type: STT_FUNC
- Section: .text
- Value: 0x1
-...
diff --git a/test/old-elf/ARM/rel-arm-target1.test b/test/old-elf/ARM/rel-arm-target1.test
deleted file mode 100644
index 064c68661875..000000000000
--- a/test/old-elf/ARM/rel-arm-target1.test
+++ /dev/null
@@ -1,114 +0,0 @@
-# Check handling of R_ARM_TARGET1 relocation.
-#
-# 1. R_ARM_TARGET1 is equal to R_ARM_ABS32
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-abs32.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec --target1-abs %t-abs32.o -o %t-abs32
-# RUN: llvm-objdump -s -t %t-abs32 | FileCheck -check-prefix=CHECK-ABS32 %s
-#
-# CHECK-ABS32: Contents of section .data:
-# CHECK-ABS32-NEXT: 401000 84004000
-# CHECK-ABS32: SYMBOL TABLE:
-# CHECK-ABS32: 00400074 g F .text {{[0-9a-f]+}} main
-# CHECK-ABS32: 00401000 g .data 00000004 data
-#
-# 2. R_ARM_TARGET1 is equal to R_ARM_REL32
-# Check handling of R_ARM_REL32 relocation.
-# RUN: yaml2obj -format=elf %s -docnum 2 > %t-rel32.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec --target1-rel %t-rel32.o -o %t-rel32
-# RUN: llvm-objdump -s -t %t-rel32 | FileCheck -check-prefix=CHECK-REL32 %s
-#
-# CHECK-REL32: Contents of section .text:
-# CHECK-REL32-NEXT: 400074 {{[0-9a-f]+}} 880fff00
-# CHECK-REL32: SYMBOL TABLE:
-# CHECK-REL32: 00400074 g F .text {{[0-9a-f]+}} main
-# CHECK-REL32: 00401000 g .bss {{[0-9a-f]+}} _myref
-
-# abs32.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '10000000'
- - Name: .rel.data
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .data
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: main
- Type: R_ARM_TARGET1
- Addend: 0
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000001C
- - Name: data
- Type: STT_OBJECT
- Section: .data
- Size: 0x0000000000000004
-# rel32.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF0000FF0000231846BD465DF8047B7047
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: _myref
- Type: R_ARM_TARGET1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Global:
- - Name: _myref
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x0000000000000014
-...
diff --git a/test/old-elf/ARM/rel-arm-thm-interwork.test b/test/old-elf/ARM/rel-arm-thm-interwork.test
deleted file mode 100644
index 3e0e30a614ee..000000000000
--- a/test/old-elf/ARM/rel-arm-thm-interwork.test
+++ /dev/null
@@ -1,121 +0,0 @@
-# Check ARM <=> Thumb interwork.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
-
-# Check R_ARM_CALL veneer to call Thumb code
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=ARM-CALL %s
-
-# ARM-CALL: Contents of section .text:
-# ARM-CALL: 400074 00482de9 04b08de2 000000fa 0088bde8
-# offset = 0x0 ^^
-# call site offset PC(arm) _Z2f2v addr
-# 0x40007C + 0x0 + 0x8 = 0x400084
-# ARM-CALL: SYMBOL TABLE:
-# ARM-CALL: 00400074 g F .text {{[0-9a-f]+}} _Z1fv
-# ARM-CALL: 00400084 g F .text {{[0-9a-f]+}} _Z2f2v
-# ARM-CALL: 00400090 g F .text {{[0-9a-f]+}} main
-
-# Check R_ARM_THM_CALL veneer to call ARM code
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=THM-CALL %s
-
-# THM-CALL: Contents of section .text:
-# THM-CALL: 400094 00bffff7 eeef0023 184680bd
-# offset = -0x24 ^^
-# call site aligned = Align(0x400096, 4) = 0x400094
-# call site aligned offset PC(thm) _Z1fv addr
-# 0x400094 + (-0x24) + 0x4 = 0x400074
-# THM-CALL: SYMBOL TABLE:
-# THM-CALL: 00400074 g F .text {{[0-9a-f]+}} _Z1fv
-# THM-CALL: 00400084 g F .text {{[0-9a-f]+}} _Z2f2v
-# THM-CALL: 00400090 g F .text {{[0-9a-f]+}} main
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00482DE904B08DE2FEFFFFEB0088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: _Z2f2v
- Type: R_ARM_CALL
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000010
- - Name: _Z2f2v
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AFBD465DF8047B704780B500AF00BFFFF7FEFF0023184680BD
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000012
- Symbol: _Z1fv
- Type: R_ARM_THM_CALL
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z2f2v
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x000000000000000C
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000000D
- Size: 0x0000000000000010
- - Name: _Z1fv
-...
diff --git a/test/old-elf/ARM/rel-base-prel.test b/test/old-elf/ARM/rel-base-prel.test
deleted file mode 100644
index 054ce58ff7b8..000000000000
--- a/test/old-elf/ARM/rel-base-prel.test
+++ /dev/null
@@ -1,61 +0,0 @@
-# Check handling of R_ARM_BASE_PREL relocation.
-# It only works for _GLOBAL_OFFSET_TABLE_ symbol, and returns error
-# for other cases.
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401004 fcffffff
-# offset = -0x4 ^^
-# addr site offset _GOT_
-# 0x401004 + (-0x4) = 0x401000
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401000 g *ABS* {{[0-9a-f]+}} _GLOBAL_OFFSET_TABLE_
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF00231846BD465DF8047B7047
- - Name: .got
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '00000000'
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '00000000'
- - Name: .rel.data
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .data
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: _GLOBAL_OFFSET_TABLE_
- Type: R_ARM_BASE_PREL
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: _GLOBAL_OFFSET_TABLE_
-...
diff --git a/test/old-elf/ARM/rel-copy.test b/test/old-elf/ARM/rel-copy.test
deleted file mode 100644
index f181f72a2192..000000000000
--- a/test/old-elf/ARM/rel-copy.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Check handling of R_ARM_COPY relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi \
-# RUN: --noinhibit-exec %t-o.o -lobj -L%p/Inputs -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-# RUN: llvm-readobj -relocations %t | FileCheck -check-prefix=READOBJ %s
-
-# CHECK: Contents of section .rel.dyn:
-# CHECK-NEXT: 400138 00104000 14010000
-# addr = 0x401000 ^^ ^^ rel_type = 0x14 => R_ARM_COPY
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401000 g .bss 00000004 object
-#
-# READOBJ: 0x401000 R_ARM_COPY object
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B483B000AF40F20003C0F200031B687B60002318460C37BD465DF8047B7047
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000006
- Symbol: object
- Type: R_ARM_THM_MOVW_ABS_NC
- - Offset: 0x000000000000000A
- Symbol: object
- Type: R_ARM_THM_MOVT_ABS
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$t'
- Section: .text
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: object
-...
diff --git a/test/old-elf/ARM/rel-glob-dat.test b/test/old-elf/ARM/rel-glob-dat.test
deleted file mode 100644
index 34f50c5b0e3d..000000000000
--- a/test/old-elf/ARM/rel-glob-dat.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# Check handling of R_ARM_GLOB_DAT relocation.
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -shared \
-# RUN: --noinhibit-exec %t-o.o -lfn -L%p/Inputs -o %t
-# RUN: llvm-readobj -relocations %t | FileCheck %s
-
-# CHECK: 0x401000 R_ARM_GLOB_DAT fn
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00482DE904B08DE208D04DE224209FE502208FE020309FE5033092E708300BE508301BE533FF2FE10030A0E10300A0E104D04BE20088BDE82000000000000000
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000038
- Symbol: _GLOBAL_OFFSET_TABLE_
- Type: R_ARM_BASE_PREL
- - Offset: 0x000000000000003C
- Symbol: fn
- Type: R_ARM_GOT_BREL
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$a'
- Section: .text
- - Name: '$d'
- Section: .text
- Value: 0x0000000000000038
- Global:
- - Name: f
- Type: STT_FUNC
- Section: .text
- - Name: _GLOBAL_OFFSET_TABLE_
- - Name: fn
-...
diff --git a/test/old-elf/ARM/rel-got-brel.test b/test/old-elf/ARM/rel-got-brel.test
deleted file mode 100644
index c8786d81127f..000000000000
--- a/test/old-elf/ARM/rel-got-brel.test
+++ /dev/null
@@ -1,63 +0,0 @@
-# Check handling of R_ARM_GOT_BREL relocation.
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .got:
-# CHECK-NEXT: 401000 75004000 81004000
-# f_thumb = 0x400075 ^^ ^^ main_thumb = 0x400081
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 401008 00000000 04000000
-# GOT[0] offset = 0x0 ^^ ^^ GOT[1] offset = 0x4
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} f
-# CHECK: 00400080 g F .text {{[0-9a-f]+}} main
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AFBD465DF8047B704780B400AF00231846BD465DF8047B7047
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '0000000000000000'
- - Name: .rel.data
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .data
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: f
- Type: R_ARM_GOT_BREL
- - Offset: 0x0000000000000004
- Symbol: main
- Type: R_ARM_GOT_BREL
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: f
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000000D
- - Name: _GLOBAL_OFFSET_TABLE_
-...
diff --git a/test/old-elf/ARM/rel-group-relocs.test b/test/old-elf/ARM/rel-group-relocs.test
deleted file mode 100644
index 16e82b3e4271..000000000000
--- a/test/old-elf/ARM/rel-group-relocs.test
+++ /dev/null
@@ -1,71 +0,0 @@
-# Check handling of group relocations (R_ARM_ALU_PC_G0_NC, R_ARM_ALU_PC_G1_NC,
-# R_ARM_LDR_PC_G2).
-#
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: -e plt_func %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400074 00c68fe2 00ca8ce2 84ffbce5
-# Disassembly of section .text:
-# plt_func:
-# 400074: 00 c6 8f e2 add r12, pc, #0, #12
-# ^ after execution: r12=0x40007c
-# 400078: 00 ca 8c e2 add r12, r12, #0, #20
-# ^ after execution: r12=0x40007C
-# 40007c: 84 ff bc e5 ldr pc, [r12, #3972]!
-# ^ referenced address is 0x401000, after execution pc=0x400074
-# CHECK: Contents of section .data:
-# CHECK: 401000 74004000
-# ^ this value is written to pc after execution of comand 0x40007c
-# ^ this address is referenced by command at 0x40007c
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400074 g F .text 0000000c plt_func
-# CHECK: 00401000 g .data 00000004 got_func
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x4
- Content: 00C08FE200C08CE200F0BCE5
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 0x4
- Relocations:
- - Offset: 0
- Symbol: got_func
- Type: R_ARM_ALU_PC_G0_NC
- Addend: -8
- - Offset: 0x4
- Symbol: got_func
- Type: R_ARM_ALU_PC_G1_NC
- Addend: -4
- - Offset: 0x8
- Symbol: got_func
- Type: R_ARM_LDR_PC_G2
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x4
- Content: 74004000
-Symbols:
- Local:
- Global:
- - Name: plt_func
- Type: STT_FUNC
- Section: .text
- Size: 0xC
- - Name: got_func
- Section: .data
- Size: 0x4
-...
diff --git a/test/old-elf/ARM/rel-ifunc.test b/test/old-elf/ARM/rel-ifunc.test
deleted file mode 100644
index 7044534af1e3..000000000000
--- a/test/old-elf/ARM/rel-ifunc.test
+++ /dev/null
@@ -1,101 +0,0 @@
-# Check handling of IFUNC (gnu_indirect_function).
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .rel.plt:
-# CHECK: 400074 00104000
-# CHECK: Contents of section .plt:
-# CHECK: 40007c 00c68fe2 00ca8ce2 7cffbce5
-# CHECK: Contents of section .text:
-# CHECK: 4001a8 00482de9 04b08de2 d4ffffeb b0ffffeb
-# ^ bl #-320 (to address 0x400080=__plt_ifunc_myfunc)
-# CHECK: Contents of section .got.plt:
-# CHECK: 401000 c0004000
-# CHECK: SYMBOL TABLE:
-# CHECK: 004000c0 g .text 00000020 myfunc
-# CHECK: 00400074 g *ABS* 00000000 __rel_iplt_start
-# CHECK: 0040007c g *ABS* 00000000 __rel_iplt_end
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20130A0E30300A0E100D04BE204B09DE41EFF2FE104B02DE500B08DE20230A0E30300A0E100D04BE204B09DE41EFF2FE104B02DE500B08DE2003000E3003040E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE208D04DE208000BE508301BE533FF2FE10030A0E10300A0E104D04BE20088BDE800482DE904B08DE210D04DE2003000E3003040E308300BE5190000EA08301BE50C300BE50C301BE5003093E510300BE50C301BE5043093E57330EFE614300BE514301BE5A00053E30130A0030030A0137330EFE6000053E30600000A10301BE5003093E50300A0E1DAFFFFEB0020A0E110301BE5002083E508301BE5083083E208300BE508201BE5003000E3003040E3030052E1E0FFFF3A04D04BE20088BDE800482DE904B08DE2D4FFFFEBFEFFFFEB0030A0E30300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000040
- Symbol: myfunc1
- Type: R_ARM_MOVW_ABS_NC
- - Offset: 0x0000000000000044
- Symbol: myfunc1
- Type: R_ARM_MOVT_ABS
- - Offset: 0x000000000000008C
- Symbol: __rel_iplt_start
- Type: R_ARM_MOVW_ABS_NC
- - Offset: 0x0000000000000090
- Symbol: __rel_iplt_start
- Type: R_ARM_MOVT_ABS
- - Offset: 0x0000000000000108
- Symbol: __rel_iplt_end
- Type: R_ARM_MOVW_ABS_NC
- - Offset: 0x000000000000010C
- Symbol: __rel_iplt_end
- Type: R_ARM_MOVT_ABS
- - Offset: 0x000000000000012C
- Symbol: myfunc
- Type: R_ARM_CALL
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: '$a'
- Section: .text
- - Name: elf_ifunc_invoke
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000058
- Size: 0x0000000000000028
- - Name: apply_irel
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000080
- Size: 0x00000000000000A0
- Global:
- - Name: myfunc1
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000001C
- - Name: myfunc2
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000001C
- Size: 0x000000000000001C
- - Name: myfunc
- Type: STT_GNU_IFUNC
- Section: .text
- Value: 0x0000000000000038
- Size: 0x0000000000000020
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000120
- Size: 0x000000000000001C
- Weak:
- - Name: __rel_iplt_start
- - Name: __rel_iplt_end
-...
diff --git a/test/old-elf/ARM/rel-jump-slot.test b/test/old-elf/ARM/rel-jump-slot.test
deleted file mode 100644
index 2a4f4eba8d84..000000000000
--- a/test/old-elf/ARM/rel-jump-slot.test
+++ /dev/null
@@ -1,50 +0,0 @@
-# Check handling of R_ARM_JUMP_SLOT relocation.
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -shared \
-# RUN: --noinhibit-exec %t-o.o -lfn -L%p/Inputs -o %t
-# RUN: llvm-readobj -relocations %t | FileCheck %s
-
-# CHECK: 0x40100C R_ARM_JUMP_SLOT fn 0x0
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00482DE904B08DE2FEFFFFEB0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: fn
- Type: R_ARM_CALL
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$a'
- Section: .text
- Global:
- - Name: f
- Type: STT_FUNC
- Section: .text
- - Name: fn
-...
diff --git a/test/old-elf/ARM/rel-rel32.test b/test/old-elf/ARM/rel-rel32.test
deleted file mode 100644
index 9e5aab000523..000000000000
--- a/test/old-elf/ARM/rel-rel32.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# Check handling of R_ARM_REL32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400074 {{[0-9a-f]+}} 880fff00
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} main
-# CHECK: 00401000 g .bss {{[0-9a-f]+}} _myref
-
----
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF0000FF0000231846BD465DF8047B7047
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: _myref
- Type: R_ARM_REL32
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Global:
- - Name: _myref
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x0000000000000014
-...
diff --git a/test/old-elf/ARM/rel-thm-call.test b/test/old-elf/ARM/rel-thm-call.test
deleted file mode 100644
index 7e7289a99768..000000000000
--- a/test/old-elf/ARM/rel-thm-call.test
+++ /dev/null
@@ -1,114 +0,0 @@
-# Check handling of R_ARM_THM_CALL relocation.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400084 fff7f6ff 00231846 80bd00bf
-# ^^ offset = -0x14
-# call site offset PC(thm) _Z1fv addr
-# 0x400084 + (-0x14) + 0x4 = 0x400074
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} _Z1fv
-# CHECK: 00400080 g F .text {{[0-9a-f]+}} main
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: not lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t 2> %t-error
-# RUN: FileCheck -check-prefix=OVERFLOW %s < %t-error
-
-# OVERFLOW: Relocation out of range {{.*}} (R_ARM_THM_CALL)
-
-# good.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AFBD465DF8047B704780B500AFFFF7FEFF0023184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000010
- Symbol: _Z1fv
- Type: R_ARM_THM_CALL
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x000000000000000C
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000000D
- Size: 0x000000000000000E
-
-# overflow.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AFBD465DF8047B704780B500AF00F400D00023184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000010
- Symbol: _Z1fv
- Type: R_ARM_THM_CALL
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x000000000000000C
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000000D
- Size: 0x000000000000000E
-...
diff --git a/test/old-elf/ARM/rel-thm-jump11.test b/test/old-elf/ARM/rel-thm-jump11.test
deleted file mode 100644
index e074b9ae1abf..000000000000
--- a/test/old-elf/ARM/rel-thm-jump11.test
+++ /dev/null
@@ -1,209 +0,0 @@
-# Check handling of R_ARM_THM_JUMP11 relocation.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 4001a4 0021c7e7
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400138 g F .text 00000060 __gnu_h2f_internal
-# CHECK: 004001a4 g F .text 00000004 __gnu_h2f_alternative
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: not lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t 2> %t-error
-# RUN: FileCheck -check-prefix=OVERFLOW %s < %t-error
-
-# OVERFLOW: Relocation out of range {{.*}} (R_ARM_THM_JUMP11)
-
-# good.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 70B4020CC0F3C754FF2CC0F3160302F4004080B241D0002C08BF002B3BD0A4F17F0543F4000315F10E0FA8BF41F6FF7209DA15F1190FA3BFA4F166066FF07F42F2406FF07F4212EA03060CD001325208964208BF03EA42021344B3F1807F24BF5B08A4F17E0501B30F2D26DC15F1180F11DB15F10E0FB5BF4FF6F2710E35CFF6FF71AD02B7BF491BAAB2CB40002202EB5333034398B270BC70470029FBD040EA533370BC43F4FC407047102DDEDD6FEAD0336FEAC33398B2EDE740F4F84398B2E9E700BFC0F3842310B4A3F11F040029B4FA84F400F400424FEA541408BF0024C0F309002146140481B943B14203703302EBC35343EA04005DF8044B704760B1B0FA80F3153B98405B42EFE744EA40305DF8044B40F0FF40704720465DF8044B704700BF01216BE70121FEE7002167E70021FEE7
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x000000000000012A
- Symbol: __gnu_h2f_internal
- Type: R_ARM_THM_JUMP11
- - Offset: 0x0000000000000132
- Symbol: __gnu_h2f_internal
- Type: R_ARM_THM_JUMP11
- - Name: .text.startup
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 0020FFF7FEBF00BF
- - Name: .rel.text.startup
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text.startup
- Relocations:
- - Offset: 0x0000000000000002
- Symbol: __gnu_h2f_alternative
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$t'
- Section: .text
- - Name: __gnu_f2h_internal
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x00000000000000C2
- Global:
- - Name: __gnu_f2h_alternative
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000012D
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_h2f_alternative
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000131
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_h2f_ieee
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000129
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: main
- Type: STT_FUNC
- Section: .text.startup
- Value: 0x0000000000000001
- Size: 0x0000000000000006
- - Name: __gnu_f2h_ieee
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000125
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_h2f_internal
- Type: STT_FUNC
- Section: .text
- Value: 0x00000000000000C5
- Size: 0x000000000000005E
- Visibility: STV_HIDDEN
-
-# overflow.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 70B4020CC0F3C754FF2CC0F3160302F4004080B241D0002C08BF002B3BD0A4F17F0543F4000315F10E0FA8BF41F6FF7209DA15F1190FA3BFA4F166066FF07F42F2406FF07F4212EA03060CD001325208964208BF03EA42021344B3F1807F24BF5B08A4F17E0501B30F2D26DC15F1180F11DB15F10E0FB5BF4FF6F2710E35CFF6FF71AD02B7BF491BAAB2CB40002202EB5333034398B270BC70470029FBD040EA533370BC43F4FC407047102DDEDD6FEAD0336FEAC33398B2EDE740F4F84398B2E9E700BFC0F3842310B4A3F11F040029B4FA84F400F400424FEA541408BF0024C0F309002146140481B943B14203703302EBC35343EA04005DF8044B704760B1B0FA80F3153B98405B42EFE744EA40305DF8044B40F0FF40704720465DF8044B704700BF01216BE70121FEE7002167E7002100E4
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x000000000000012A
- Symbol: __gnu_h2f_internal
- Type: R_ARM_THM_JUMP11
- - Offset: 0x0000000000000132
- Symbol: __gnu_h2f_internal
- Type: R_ARM_THM_JUMP11
- - Name: .text.startup
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 0020FFF7FEBF00BF
- - Name: .rel.text.startup
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text.startup
- Relocations:
- - Offset: 0x0000000000000002
- Symbol: __gnu_h2f_alternative
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$t'
- Section: .text
- - Name: __gnu_f2h_internal
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x00000000000000C2
- Global:
- - Name: __gnu_f2h_alternative
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000012D
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_h2f_alternative
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000131
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_h2f_ieee
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000129
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: main
- Type: STT_FUNC
- Section: .text.startup
- Value: 0x0000000000000001
- Size: 0x0000000000000006
- - Name: __gnu_f2h_ieee
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000125
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_h2f_internal
- Type: STT_FUNC
- Section: .text
- Value: 0x00000000000000C5
- Size: 0x000000000000005E
- Visibility: STV_HIDDEN
-...
diff --git a/test/old-elf/ARM/rel-thm-jump24-veneer.test b/test/old-elf/ARM/rel-thm-jump24-veneer.test
deleted file mode 100644
index 5893b53da84a..000000000000
--- a/test/old-elf/ARM/rel-thm-jump24-veneer.test
+++ /dev/null
@@ -1,120 +0,0 @@
-# Check veneer generation for R_ARM_THM_JUMP24 relocation (B instruction call).
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=STATIC %s
-
-# STATIC: Contents of section .text:
-# STATIC: 400074 {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 00f000b8
-# Call from main:
-# offset = 0x0 ^^
-# call site offset PC(thm) ___Z1fv_from_thumb addr
-# 0x400080 + 0x0 + 0x4 = 0x400084
-#
-# Code of the veneer:
-# STATIC: 400084 78470000 f9ffffea
-# offset = -0x1C ^^
-# call site offset PC(arm) _Z1fv
-# 0x400088 + (-0x1C) + 0x8 = 0x400074
-#
-# STATIC: SYMBOL TABLE:
-# STATIC: 00400084 l F .text {{[0-9a-f]+}} ___Z1fv_from_thumb
-# STATIC: 00400074 g F .text {{[0-9a-f]+}} _Z1fv
-# STATIC: 00400080 g F .text {{[0-9a-f]+}} main
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi \
-# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=EXEC-DYN %s
-
-# EXEC-DYN: Contents of section .text:
-# EXEC-DYN: 400114 {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 00f000b8
-# Call from main:
-# offset = 0x0 ^^
-# call site offset PC(thm) ___Z1fv_from_thumb addr
-# 0x400120 + 0x0 + 0x4 = 0x400124
-#
-# Code of the veneer:
-# EXEC-DYN: 400124 78470000 f9ffffea
-# offset = -0x1C ^^
-# call site offset PC(arm) _Z1fv
-# 0x400128 + (-0x1C) + 0x8 = 0x400114
-#
-# EXEC-DYN: SYMBOL TABLE:
-# EXEC-DYN: 00400124 l F .text {{[0-9a-f]+}} ___Z1fv_from_thumb
-# EXEC-DYN: 00400114 g F .text {{[0-9a-f]+}} _Z1fv
-# EXEC-DYN: 00400120 g F .text {{[0-9a-f]+}} main
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 0030A0E30300A0E11EFF2FE1
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: FFF7FEBF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: _Z1fv
- Type: R_ARM_THM_JUMP24
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: _Z1fv
-...
diff --git a/test/old-elf/ARM/rel-thm-jump24.test b/test/old-elf/ARM/rel-thm-jump24.test
deleted file mode 100644
index b58bc053aca0..000000000000
--- a/test/old-elf/ARM/rel-thm-jump24.test
+++ /dev/null
@@ -1,110 +0,0 @@
-# Check handling of R_ARM_THM_JUMP24 relocation.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400084 80b500af fff7f4bf 03461846 80bd00bf
-# ^^ offset = -0x18
-# call site offset PC(thm) _Z1fv addr
-# 0x400088 + (-0x18) + 0x4 = 0x400074
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} _Z1fv
-# CHECK: 00400084 g F .text {{[0-9a-f]+}} main
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: not lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t 2> %t-error
-# RUN: FileCheck -check-prefix=OVERFLOW %s < %t-error
-
-# OVERFLOW: Relocation out of range {{.*}} (R_ARM_THM_JUMP24)
-
-# good.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF00231846BD465DF8047B704780B500AFFFF7FEBF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000014
- Symbol: _Z1fv
- Type: R_ARM_THM_JUMP24
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000011
-
-# overflow.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF00231846BD465DF8047B704780B500AF00F400900346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000014
- Symbol: _Z1fv
- Type: R_ARM_THM_JUMP24
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000011
-...
diff --git a/test/old-elf/ARM/rel-thm-mov.test b/test/old-elf/ARM/rel-thm-mov.test
deleted file mode 100644
index 5e2e134ce781..000000000000
--- a/test/old-elf/ARM/rel-thm-mov.test
+++ /dev/null
@@ -1,70 +0,0 @@
-# 1. Check handling of R_ARM_THM_MOVW_ABS_NC and R_THM_ARM_MOVT_ABS relocation pair.
-# 2. Check that instructions are not cropped for symbols that address Thumb code.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck %s
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=INSN-CROP %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400074 {{[0-9a-f]+}} 41f20003 c0f24003 0a221a60
-# addrL = 0x1000 ^^
-# addrH = 0x40 ^^
-# addrH addrL _ZL5data1 addr
-# (0x40 << 16) + 0x1000 = 0x401000
-# CHECK: SYMBOL TABLE:
-# CHECK: 00401000 l .bss 00000004 _ZL5data1
-# CHECK: 00400074 g F .text {{[0-9a-f]+}} main
-#
-# INSN-CROP: Contents of section .text:
-# INSN-CROP: 400074 80b400af
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF40F20003C0F200030A221A6000231846BD465DF8047B7047
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: _ZL5data1
- Type: R_ARM_THM_MOVW_ABS_NC
- Addend: 0
- - Offset: 0x0000000000000008
- Symbol: _ZL5data1
- Type: R_ARM_THM_MOVT_ABS
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Size: 4
-Symbols:
- Local:
- - Name: _ZL5data1
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/old-elf/ARM/rel-tls-ie32.test b/test/old-elf/ARM/rel-tls-ie32.test
deleted file mode 100644
index e05b262cd1bc..000000000000
--- a/test/old-elf/ARM/rel-tls-ie32.test
+++ /dev/null
@@ -1,125 +0,0 @@
-# Check handling of R_ARM_TLS_IE32 relocation.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-tls.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-tlsv.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-tls.o %t-tlsv.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=STATIC %s
-
-# STATIC: Contents of section .got:
-# STATIC-NEXT: 401008 08000000 0c000000
-# tp_off(i) = 0x08 ^^ ^^ tp_off(j) = 0x0c
-# tp_off(i) + sizeof(i) = tp_off(j)
-# 0x08 + 0x04 = 0x0c
-# STATIC: SYMBOL TABLE:
-# STATIC: 00400094 g F .text {{[0-9a-f]+}} main
-# STATIC: 00000000 g .tdata 00000004 i
-# sizeof(i) = 0x04 ^^
-# STATIC: 00000004 g .tdata 00000004 j
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-tls.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-tlsv.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi \
-# RUN: --noinhibit-exec %t-tls.o %t-tlsv.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=EXEC-DYN %s
-
-# EXEC-DYN: Contents of section .rel.dyn:
-# EXEC-DYN-NEXT: 400134 08104000 13000000 0c104000 13000000
-# addr(i) = 0x401008 ^^ ^^ addr(j) = 0x40100c
-# EXEC-DYN: Contents of section .got:
-# EXEC-DYN-NEXT: 401008 00000000 04000000
-# tls_off(i) = 0x00 ^^ ^^ tls_off(j) = 0x04
-# EXEC-DYN: SYMBOL TABLE:
-# EXEC-DYN: 00400144 g F .text {{[0-9a-f]+}} main
-# EXEC-DYN: 00000000 g .tdata 00000004 i
-# EXEC-DYN: 00000004 g .tdata 00000004 j
-
-# tls.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF0C4B7B441B681DEE702FD2580A4B7B441B681DEE701FCB581A44084B7B441B681DEE701FCB585B0013441846BD465DF8047B70472E000000260000001C000000
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000038
- Symbol: i
- Type: R_ARM_TLS_IE32
- - Offset: 0x000000000000003C
- Symbol: i
- Type: R_ARM_TLS_IE32
- - Offset: 0x0000000000000040
- Symbol: j
- Type: R_ARM_TLS_IE32
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: i
- Type: STT_TLS
- - Name: j
- Type: STT_TLS
-
-# tlsv.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Content: 05000000FBFFFFFF
-Symbols:
- Global:
- - Name: i
- Type: STT_TLS
- Section: .tdata
- Size: 0x0000000000000004
- - Name: j
- Type: STT_TLS
- Section: .tdata
- Value: 0x0000000000000004
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/ARM/rel-tls-le32.test b/test/old-elf/ARM/rel-tls-le32.test
deleted file mode 100644
index eba4f950515b..000000000000
--- a/test/old-elf/ARM/rel-tls-le32.test
+++ /dev/null
@@ -1,73 +0,0 @@
-# Check handling of R_ARM_TLS_LE32 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=STATIC %s
-
-# STATIC: Contents of section .text:
-# STATIC: 4000b4 {{[0-9a-f]+}} 08000000
-# tp_off = 0x000008 ^^
-# STATIC: SYMBOL TABLE:
-# STATIC: 00400094 g F .text {{[0-9a-f]+}} main
-# STATIC: 00000000 g .tdata 00000004 i
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=EXEC-DYN %s
-
-# EXEC-DYN: Contents of section .text:
-# EXEC-DYN: 400154 {{[0-9a-f]+}} 08000000
-# tp_off = 0x000008 ^^
-# EXEC-DYN: SYMBOL TABLE:
-# EXEC-DYN: 00400134 g F .text {{[0-9a-f]+}} main
-# EXEC-DYN: 00000000 g .tdata 00000004 i
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE2703F1DEE10209FE5023093E70300A0E100D04BE204B09DE41EFF2FE100000000
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000024
- Symbol: i
- Type: R_ARM_TLS_LE32
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Content: '05000000'
-Symbols:
- Global:
- - Name: i
- Type: STT_TLS
- Section: .tdata
- Size: 0x0000000000000004
- - Name: main
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/old-elf/ARM/rel-v4bx.test b/test/old-elf/ARM/rel-v4bx.test
deleted file mode 100644
index d2d3a7772b47..000000000000
--- a/test/old-elf/ARM/rel-v4bx.test
+++ /dev/null
@@ -1,72 +0,0 @@
-# REQUIRES: arm
-
-# Check handling of R_ARM_V4BX relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi \
-# RUN: --noinhibit-exec %t-o.o -o %t
-# RUN: llvm-objdump -d -triple=armv4t %t | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK: main:
-# The following instruction creates a RM_ARM_V4BX relocation that
-# allows the linker to replace the bx instruction to a ARMv4
-# compatible one. Currently lld does not change it.
-# CHECK: 400114: 1e ff 2f 01 bxeq lr
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 1EFF2F01
- - Name: .rel.text
- Type: SHT_REL
- Flags: [ SHF_INFO_LINK ]
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: ''
- Type: R_ARM_V4BX
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- - Name: .ARM.attributes
- Type: SHT_ARM_ATTRIBUTES
- AddressAlign: 0x0000000000000001
- Content: 4115000000616561626900010B000000060208010901
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: '$a'
- Section: .text
- - Name: .ARM.attributes
- Type: STT_SECTION
- Section: .ARM.attributes
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/old-elf/ARM/thm-symbols.test b/test/old-elf/ARM/thm-symbols.test
deleted file mode 100644
index 6377d1e3ef89..000000000000
--- a/test/old-elf/ARM/thm-symbols.test
+++ /dev/null
@@ -1,51 +0,0 @@
-# Check that symbols formed from Thumb instructions are valid:
-# 1. Symbol address.
-# 2. Symbol content size.
-# 3. Symbol content.
-
-# RUN: yaml2obj -format=elf %s > %t-t.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu \
-# RUN: -Bstatic --noinhibit-exec %t-t.o -o %t-t
-# RUN: llvm-readobj -symbols %t-t | FileCheck -check-prefix=SYM-ADDR %s
-# RUN: llvm-readobj -symbols %t-t | FileCheck -check-prefix=SYM-SIZE %s
-# RUN: llvm-objdump -s -t %t-t | FileCheck -check-prefix=SYM-CONTENT %s
-
-# SYM-ADDR: Name: main (1)
-# SYM-ADDR-NEXT: Value: 0x400075
-
-# SYM-SIZE: Name: main (1)
-# SYM-SIZE-NEXT: Value: 0x{{[0-9a-f]+}}
-# SYM-SIZE-NEXT: Size: 16
-
-# SYM-CONTENT: Contents of section .text:
-# SYM-CONTENT-NEXT: 400074 80b400af 00231846 bd465df8 047b7047 .....#.F.F]..{pG
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF00231846BD465DF8047B7047
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/old-elf/ARM/two-got-for-symbol.test b/test/old-elf/ARM/two-got-for-symbol.test
deleted file mode 100644
index e0420eff1918..000000000000
--- a/test/old-elf/ARM/two-got-for-symbol.test
+++ /dev/null
@@ -1,62 +0,0 @@
-# Check that two GOT entries containing R_ARM_JUMP_SLOT and
-# R_ARM_GLOB_DAT may be present for the same symbol in the linked binary.
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -shared \
-# RUN: --noinhibit-exec %t-o.o -lfn -L%p/Inputs -o %t
-# RUN: llvm-readobj -relocations %t | FileCheck %s
-
-# CHECK: 0x401000 R_ARM_GLOB_DAT fn 0x0
-# CHECK: 0x401010 R_ARM_JUMP_SLOT fn 0x0
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 10482DE908B08DE20CD04DE230209FE502208FE02C309FE5033092E710300BE5FEFFFFEB0040A0E110301BE533FF2FE10030A0E1033084E00300A0E108D04BE21088BDE82C00000000000000
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: fn
- Type: R_ARM_CALL
- - Offset: 0x0000000000000044
- Symbol: _GLOBAL_OFFSET_TABLE_
- Type: R_ARM_BASE_PREL
- - Offset: 0x0000000000000048
- Symbol: fn
- Type: R_ARM_GOT_BREL
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: '$a'
- Section: .text
- - Name: '$d'
- Section: .text
- Value: 0x0000000000000044
- Global:
- - Name: f
- Type: STT_FUNC
- Section: .text
- - Name: fn
- - Name: _GLOBAL_OFFSET_TABLE_
-...
diff --git a/test/old-elf/ARM/undef-lazy-symbol.test b/test/old-elf/ARM/undef-lazy-symbol.test
deleted file mode 100644
index 361c6482dabe..000000000000
--- a/test/old-elf/ARM/undef-lazy-symbol.test
+++ /dev/null
@@ -1,133 +0,0 @@
-# Check that _GLOBAL_OFFSET_TABLE_ symbol is resolved
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-got.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-got.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=GOT %s
-
-# GOT: Name: _GLOBAL_OFFSET_TABLE_ (183)
-# GOT-NEXT: Value: {{[0-9]+}}
-# GOT-NEXT: Size: 0
-# GOT-NEXT: Binding: Global (0x1)
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Other: 0
-# GOT-NEXT: Section: Absolute (0xFFF1)
-
-# Check that __exidx_start/_end symbols are resolved
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-exidx.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --defsym=main=fn --noinhibit-exec %t-exidx.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=EXIDX %s
-
-# EXIDX: Name: __exidx_start (186)
-# EXIDX-NEXT: Value: {{[0-9]+}}
-# EXIDX-NEXT: Size: 0
-# EXIDX-NEXT: Binding: Global (0x1)
-# EXIDX-NEXT: Type: Object (0x1)
-# EXIDX-NEXT: Other: 0
-# EXIDX-NEXT: Section: Absolute (0xFFF1)
-#
-# EXIDX: Name: __exidx_end (200)
-# EXIDX-NEXT: Value: {{[0-9]+}}
-# EXIDX-NEXT: Size: 0
-# EXIDX-NEXT: Binding: Global (0x1)
-# EXIDX-NEXT: Type: Object (0x1)
-# EXIDX-NEXT: Other: 0
-# EXIDX-NEXT: Section: Absolute (0xFFF1)
-
-# Check that all symbols are resolved
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-got.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-exidx.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-got.o %t-exidx.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=SYMS %s
-
-# SYMS: Name: _GLOBAL_OFFSET_TABLE_ (186)
-# SYMS-NEXT: Value: {{[0-9]+}}
-# SYMS-NEXT: Size: 0
-# SYMS-NEXT: Binding: Global (0x1)
-# SYMS-NEXT: Type: Object (0x1)
-# SYMS-NEXT: Other: 0
-# SYMS-NEXT: Section: Absolute (0xFFF1)
-#
-# SYMS: Name: __exidx_start (208)
-# SYMS-NEXT: Value: {{[0-9]+}}
-# SYMS-NEXT: Size: 0
-# SYMS-NEXT: Binding: Global (0x1)
-# SYMS-NEXT: Type: Object (0x1)
-# SYMS-NEXT: Other: 0
-# SYMS-NEXT: Section: Absolute (0xFFF1)
-#
-# SYMS: Name: __exidx_end (222)
-# SYMS-NEXT: Value: {{[0-9]+}}
-# SYMS-NEXT: Size: 0
-# SYMS-NEXT: Binding: Global (0x1)
-# SYMS-NEXT: Type: Object (0x1)
-# SYMS-NEXT: Other: 0
-# SYMS-NEXT: Section: Absolute (0xFFF1)
-
-# got.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B483B000AF40F20003C0F200037B60002318460C37BD465DF8047B704700BF
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: _GLOBAL_OFFSET_TABLE_
-
-# exidx.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B483B000AF40F20003C0F200037B60002318460C37BD465DF8047B704700BF
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: fn
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: __exidx_start
- - Name: __exidx_end
-...
diff --git a/test/old-elf/ARM/veneer-mapping.test b/test/old-elf/ARM/veneer-mapping.test
deleted file mode 100644
index ccd93eea4fbd..000000000000
--- a/test/old-elf/ARM/veneer-mapping.test
+++ /dev/null
@@ -1,92 +0,0 @@
-# Check that mapping symbols are properly generated for veneers.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o
-# RUN: lld -flavor old-gnu -target arm-linux-gnu --defsym=main=fa \
-# RUN: -Bstatic --noinhibit-exec %t-arm.o %t-thm.o -o %t
-# RUN: llvm-readobj -symbols %t | FileCheck %s
-
-# CHECK: Name: $a.__ft_from_arm
-# CHECK: Name: $d.__ft_from_arm
-# CHECK: Name: $t.__fa_from_thumb
-# CHECK: Name: $a.__fa_from_thumb
-
-# arm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: ft
- Type: R_ARM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: fa
- Type: STT_FUNC
- Section: .text
- - Name: ft
-
-# thm.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B500AFFFF7FEBF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: fa
- Type: R_ARM_THM_JUMP24
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Global:
- - Name: ft
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: fa
-...
diff --git a/test/old-elf/ARM/weak-branch.test b/test/old-elf/ARM/weak-branch.test
deleted file mode 100644
index 76c7a4d15b65..000000000000
--- a/test/old-elf/ARM/weak-branch.test
+++ /dev/null
@@ -1,221 +0,0 @@
-# Check weak references fixup.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-jmp11.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-jmp11.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=JMP11-CHECK %s
-
-# JMP11-CHECK: Contents of section .text:
-# JMP11-CHECK: 400194 704700bf 01216be7 012100bf 002167e7
-# ^ NOP (thumb16)
-# 40019c: 2101 movs r1, #1
-# 40019e: bf00 nop
-# JMP11-CHECK: 4001a4 002100bf
-# ^ NOP (thumb16)
-# 4001a4: 2100 movs r1, #0
-# 4001a6: bf00 nop
-# JMP11-CHECK: SYMBOL TABLE:
-# JMP11-CHECK: 00000000 w *UND* 00000000 __gnu_h2f_internal
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm-call.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-thm-call.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=THM-CALL-CHECK %s
-
-# THM-CALL-CHECK: Contents of section .text:
-# THM-CALL-CHECK: 400064 80b500af fff7f4ff aff30080 03461846
-# ^ NOP.W
-# 400068: f7ff fff4 bl 400054 <my_fn>
-# 40006c: f3af 8000 nop.w
-# 400070: 4603 mov r3, r0 ; return value has not been changed after weak fn call
-#
-# THM-CALL-CHECK: SYMBOL TABLE:
-# THM-CALL-CHECK: 00000000 w *UND* 00000000 weak_fn
-
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-arm-call.o
-# RUN: lld -flavor old-gnu -target arm -m armelf_linux_eabi -Bstatic \
-# RUN: --noinhibit-exec %t-arm-call.o -o %t
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=ARM-CALL-CHECK %s
-
-# ARM-CALL-CHECK: Contents of section .text:
-# ARM-CALL-CHECK: 400074 04b08de2 f5ffffeb 00f020e3 0030a0e1
-# ^ NOP
-# 400078: ebfffff5 bl 400054 <my_fn>
-# 40007c: e320f000 nop {0}
-# 400080: e1a03000 mov r3, r0 ; return value has not been changed after weak fn call
-#
-# ARM-CALL-CHECK: SYMBOL TABLE:
-# ARM-CALL-CHECK: 00000000 w *UND* 00000000 weak_fn
-
-# jump11.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 70B4020CC0F3C754FF2CC0F3160302F4004080B241D0002C08BF002B3BD0A4F17F0543F4000315F10E0FA8BF41F6FF7209DA15F1190FA3BFA4F166066FF07F42F2406FF07F4212EA03060CD001325208964208BF03EA42021344B3F1807F24BF5B08A4F17E0501B30F2D26DC15F1180F11DB15F10E0FB5BF4FF6F2710E35CFF6FF71AD02B7BF491BAAB2CB40002202EB5333034398B270BC70470029FBD040EA533370BC43F4FC407047102DDEDD6FEAD0336FEAC33398B2EDE740F4F84398B2E9E700BFC0F3842310B4A3F11F040029B4FA84F400F400424FEA541408BF0024C0F309002146140481B943B14203703302EBC35343EA04005DF8044B704760B1B0FA80F3153B98405B42EFE744EA40305DF8044B40F0FF40704720465DF8044B704700BF01216BE70121FEE7002167E70021FEE7
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x000000000000012A
- Symbol: __gnu_h2f_internal
- Type: R_ARM_THM_JUMP11
- - Offset: 0x0000000000000132
- Symbol: __gnu_h2f_internal
- Type: R_ARM_THM_JUMP11
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: '$t'
- Section: .text
- - Name: __gnu_f2h_internal
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x00000000000000C2
- Global:
- - Name: __gnu_f2h_ieee
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000125
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_h2f_ieee
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000129
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_f2h_alternative
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000012D
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- - Name: __gnu_h2f_alternative
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000131
- Size: 0x0000000000000004
- Visibility: STV_HIDDEN
- Weak:
- - Name: __gnu_h2f_internal
-# thm-call.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 80B400AF01231846BD465DF8047B704780B500AFFFF7FEFFFFF7FEFF0346184680BD00BF
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000014
- Symbol: my_fn
- Type: R_ARM_THM_CALL
- - Offset: 0x0000000000000018
- Symbol: weak_fn
- Type: R_ARM_THM_CALL
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: '$t'
- Section: .text
- Global:
- - Name: my_fn
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- Size: 0x0000000000000010
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000011
- Size: 0x0000000000000012
- Weak:
- - Name: weak_fn
-# arm-call.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_ARM
- Flags: [ EF_ARM_EABI_VER5 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 04B02DE500B08DE20130A0E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEBFEFFFFEB0030A0E10300A0E10088BDE8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: .text
- Relocations:
- - Offset: 0x0000000000000024
- Symbol: my_fn
- Type: R_ARM_CALL
- - Offset: 0x0000000000000028
- Symbol: weak_fn
- Type: R_ARM_CALL
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: '$a'
- Section: .text
- Global:
- - Name: my_fn
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000001C
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000001C
- Size: 0x000000000000001C
- Weak:
- - Name: weak_fn
-...
diff --git a/test/old-elf/Hexagon/Inputs/dynobj-data.c b/test/old-elf/Hexagon/Inputs/dynobj-data.c
deleted file mode 100644
index 0f4ea9b80526..000000000000
--- a/test/old-elf/Hexagon/Inputs/dynobj-data.c
+++ /dev/null
@@ -1,3 +0,0 @@
-int d = 10;
-
-int fn() { return d; }
diff --git a/test/old-elf/Hexagon/Inputs/dynobj-data.o b/test/old-elf/Hexagon/Inputs/dynobj-data.o
deleted file mode 100644
index 13d283cd0eff..000000000000
--- a/test/old-elf/Hexagon/Inputs/dynobj-data.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Hexagon/Inputs/dynobj.c b/test/old-elf/Hexagon/Inputs/dynobj.c
deleted file mode 100644
index f17fdadd6945..000000000000
--- a/test/old-elf/Hexagon/Inputs/dynobj.c
+++ /dev/null
@@ -1,26 +0,0 @@
-extern int shankar;
-static int a;
-static int b;
-int c;
-int fn2() {
- return 0;
-}
-
-int fn1() {
- return 0;
-}
-
-int fn() {
- a = 10;
- b = 20;
- c = 10;
- shankar = 20;
- return 0;
-}
-
-int fn3() {
- fn();
- fn1();
- fn2();
- return 0;
-}
diff --git a/test/old-elf/Hexagon/Inputs/dynobj.o b/test/old-elf/Hexagon/Inputs/dynobj.o
deleted file mode 100644
index 6c184f2edd60..000000000000
--- a/test/old-elf/Hexagon/Inputs/dynobj.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Hexagon/Inputs/got-plt-order.c b/test/old-elf/Hexagon/Inputs/got-plt-order.c
deleted file mode 100644
index 621f670ef7c5..000000000000
--- a/test/old-elf/Hexagon/Inputs/got-plt-order.c
+++ /dev/null
@@ -1,6 +0,0 @@
-int c = 10;
-int fn() { c = 20; return 0; }
-
-int fn1() {
- return fn();
-}
diff --git a/test/old-elf/Hexagon/Inputs/got-plt-order.o b/test/old-elf/Hexagon/Inputs/got-plt-order.o
deleted file mode 100644
index e97678b739bd..000000000000
--- a/test/old-elf/Hexagon/Inputs/got-plt-order.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Hexagon/Inputs/libMaxAlignment.a b/test/old-elf/Hexagon/Inputs/libMaxAlignment.a
deleted file mode 100644
index cc5461a09ae4..000000000000
--- a/test/old-elf/Hexagon/Inputs/libMaxAlignment.a
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Hexagon/Inputs/sda-base.o b/test/old-elf/Hexagon/Inputs/sda-base.o
deleted file mode 100644
index 410a3d47d320..000000000000
--- a/test/old-elf/Hexagon/Inputs/sda-base.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Hexagon/Inputs/sdata1.c b/test/old-elf/Hexagon/Inputs/sdata1.c
deleted file mode 100644
index 77c2a54c36a1..000000000000
--- a/test/old-elf/Hexagon/Inputs/sdata1.c
+++ /dev/null
@@ -1,3 +0,0 @@
-static int a = 0;
-
-int b = 10;
diff --git a/test/old-elf/Hexagon/Inputs/sdata1.o b/test/old-elf/Hexagon/Inputs/sdata1.o
deleted file mode 100644
index bf908fed27e9..000000000000
--- a/test/old-elf/Hexagon/Inputs/sdata1.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Hexagon/Inputs/sdata2.c b/test/old-elf/Hexagon/Inputs/sdata2.c
deleted file mode 100644
index 96b37271d773..000000000000
--- a/test/old-elf/Hexagon/Inputs/sdata2.c
+++ /dev/null
@@ -1,6 +0,0 @@
-int sdata1 = 10;
-int sdata2 = 20;
-int sdata3 = 30;
-
-int sbss1 = 0;
-
diff --git a/test/old-elf/Hexagon/Inputs/sdata2.o b/test/old-elf/Hexagon/Inputs/sdata2.o
deleted file mode 100644
index e4ec810866e5..000000000000
--- a/test/old-elf/Hexagon/Inputs/sdata2.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Hexagon/Inputs/use-shared.hexagon b/test/old-elf/Hexagon/Inputs/use-shared.hexagon
deleted file mode 100644
index 9e5ffb42d36a..000000000000
--- a/test/old-elf/Hexagon/Inputs/use-shared.hexagon
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Hexagon/dynlib-data.test b/test/old-elf/Hexagon/dynlib-data.test
deleted file mode 100644
index 2da312b54d43..000000000000
--- a/test/old-elf/Hexagon/dynlib-data.test
+++ /dev/null
@@ -1,9 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/dynobj-data.o \
-RUN: -o %t --noinhibit-exec -shared
-RUN: llvm-objdump -s %t > %t1
-RUN: FileCheck -check-prefix=CHECKRELOCS %s < %t1
-
-CHECKRELOCS: Contents of section .text:
-CHECKRELOCS: 00f8 01c09da0 01d89da1 3c400000 18c4496a ........<@....Ij
-CHECKRELOCS: 0108 ff7fff0f 00ff9897 00c08091 38c09d91 ............8...
-CHECKRELOCS: 0118 1ec01e96 ....
diff --git a/test/old-elf/Hexagon/dynlib-gotoff.test b/test/old-elf/Hexagon/dynlib-gotoff.test
deleted file mode 100644
index f31d23bc5ebc..000000000000
--- a/test/old-elf/Hexagon/dynlib-gotoff.test
+++ /dev/null
@@ -1,128 +0,0 @@
-# This tests GOT's and PLT's for dynamic libraries for Hexagon
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/dynobj.o \
-RUN: -o %t --output-filetype=yaml -shared --noinhibit-exec
-RUN: FileCheck -check-prefix=CHECKGOTPLT %s < %t
-
- - name: .PLT0
-CHECKGOTPLT: type: stub
-CHECKGOTPLT: content: [ 00, 40, 00, 00, 1C, C0, 49, 6A, 0E, 42, 9C, E2,
-CHECKGOTPLT: 4F, 40, 9C, 91, 3C, C0, 9C, 91, 0E, 42, 0E, 8C,
-CHECKGOTPLT: 00, C0, 9C, 52 ]
-CHECKGOTPLT: alignment: 16
-CHECKGOTPLT: section-name: .plt
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
-CHECKGOTPLT: offset: 0
- target: __got0
-CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
-CHECKGOTPLT: offset: 4
- target: __got0
-CHECKGOTPLT: addend: 4
- - name: __plt_fn
-CHECKGOTPLT: type: stub
-CHECKGOTPLT: content: [ 00, 40, 00, 00, 0E, C0, 49, 6A, 1C, C0, 8E, 91,
-CHECKGOTPLT: 00, C0, 9C, 52 ]
-CHECKGOTPLT: alignment: 16
-CHECKGOTPLT: section-name: .plt
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
-CHECKGOTPLT: offset: 0
- target: __got_fn
-CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
-CHECKGOTPLT: offset: 4
- target: __got_fn
-CHECKGOTPLT: addend: 4
- - name: __plt_fn1
-CHECKGOTPLT: type: stub
-CHECKGOTPLT: content: [ 00, 40, 00, 00, 0E, C0, 49, 6A, 1C, C0, 8E, 91,
-CHECKGOTPLT: 00, C0, 9C, 52 ]
-CHECKGOTPLT: alignment: 16
-CHECKGOTPLT: section-name: .plt
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
-CHECKGOTPLT: offset: 0
- target: __got_fn1
-CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
-CHECKGOTPLT: offset: 4
- target: __got_fn1
-CHECKGOTPLT: addend: 4
- - name: __plt_fn2
-CHECKGOTPLT: type: stub
-CHECKGOTPLT: content: [ 00, 40, 00, 00, 0E, C0, 49, 6A, 1C, C0, 8E, 91,
-CHECKGOTPLT: 00, C0, 9C, 52 ]
-CHECKGOTPLT: alignment: 16
-CHECKGOTPLT: section-name: .plt
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_B32_PCREL_X
-CHECKGOTPLT: offset: 0
- target: __got_fn2
-CHECKGOTPLT: - kind: R_HEX_6_PCREL_X
-CHECKGOTPLT: offset: 4
- target: __got_fn2
-CHECKGOTPLT: addend: 4
- - name: __got0
-CHECKGOTPLT: type: got
-CHECKGOTPLT: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-CHECKGOTPLT: 00, 00, 00, 00 ]
-CHECKGOTPLT: alignment: 8
-CHECKGOTPLT: section-name: .got.plt
-CHECKGOTPLT: permissions: rw-
- - name: __got_c
-CHECKGOTPLT: type: got
-CHECKGOTPLT: content: [ 00, 00, 00, 00 ]
-CHECKGOTPLT: alignment: 4
-CHECKGOTPLT: section-name: .got
-CHECKGOTPLT: permissions: rw-
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_GLOB_DAT
-CHECKGOTPLT: offset: 0
-CHECKGOTPLT: target: c
- - name: __got_shankar
-CHECKGOTPLT: type: got
-CHECKGOTPLT: content: [ 00, 00, 00, 00 ]
-CHECKGOTPLT: alignment: 4
-CHECKGOTPLT: section-name: .got
-CHECKGOTPLT: permissions: rw-
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_GLOB_DAT
-CHECKGOTPLT: offset: 0
-CHECKGOTPLT: target: shankar
- - name: __got_fn
-CHECKGOTPLT: type: got
-CHECKGOTPLT: content: [ 00, 00, 00, 00 ]
-CHECKGOTPLT: alignment: 4
-CHECKGOTPLT: section-name: .got.plt
-CHECKGOTPLT: permissions: rw-
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_JMP_SLOT
-CHECKGOTPLT: offset: 0
-CHECKGOTPLT: target: fn
-CHECKGOTPLT: - kind: R_HEX_32
-CHECKGOTPLT: offset: 0
- target: .PLT0
- - name: __got_fn1
-CHECKGOTPLT: type: got
-CHECKGOTPLT: content: [ 00, 00, 00, 00 ]
-CHECKGOTPLT: alignment: 4
-CHECKGOTPLT: section-name: .got.plt
-CHECKGOTPLT: permissions: rw-
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_JMP_SLOT
-CHECKGOTPLT: offset: 0
-CHECKGOTPLT: target: fn1
-CHECKGOTPLT: - kind: R_HEX_32
-CHECKGOTPLT: offset: 0
- target: .PLT0
- - name: __got_fn2
-CHECKGOTPLT: type: got
-CHECKGOTPLT: content: [ 00, 00, 00, 00 ]
-CHECKGOTPLT: alignment: 4
-CHECKGOTPLT: section-name: .got.plt
-CHECKGOTPLT: permissions: rw-
-CHECKGOTPLT: references:
-CHECKGOTPLT: - kind: R_HEX_JMP_SLOT
-CHECKGOTPLT: offset: 0
-CHECKGOTPLT: target: fn2
-CHECKGOTPLT: - kind: R_HEX_32
-CHECKGOTPLT: offset: 0
- target: .PLT0
diff --git a/test/old-elf/Hexagon/dynlib-hash.test b/test/old-elf/Hexagon/dynlib-hash.test
deleted file mode 100644
index e26368120970..000000000000
--- a/test/old-elf/Hexagon/dynlib-hash.test
+++ /dev/null
@@ -1,9 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/dynobj.o \
-RUN: -o %t --noinhibit-exec -shared
-RUN: llvm-objdump -s %t > %t1
-RUN: FileCheck -check-prefix=CHECKHASH %s < %t1
-
-CHECKHASH: Contents of section .hash:
-CHECKHASH: 0094 03000000 07000000 06000000 01000000
-CHECKHASH: 00a4 04000000 00000000 00000000 00000000
-CHECKHASH: 00b4 00000000 03000000 02000000 05000000
diff --git a/test/old-elf/Hexagon/dynlib-rela.test b/test/old-elf/Hexagon/dynlib-rela.test
deleted file mode 100644
index 86e38ede6280..000000000000
--- a/test/old-elf/Hexagon/dynlib-rela.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# Tests that the relocation sections have the right alignment.
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/use-shared.hexagon -shared -o %t1
-RUN: llvm-readobj -sections %t1 > %t2
-RUN: FileCheck -check-prefix=SECTIONS %s < %t2
-
-SECTIONS: Section {
-SECTIONS: Name: .rela.plt (23)
-SECTIONS: AddressAlignment: 4
-SECTIONS: }
diff --git a/test/old-elf/Hexagon/dynlib-syms.test b/test/old-elf/Hexagon/dynlib-syms.test
deleted file mode 100644
index 08f8930bb205..000000000000
--- a/test/old-elf/Hexagon/dynlib-syms.test
+++ /dev/null
@@ -1,7 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/dynobj.o \
-RUN: -o %t --noinhibit-exec -shared
-RUN: llvm-nm -n -M %t > %t1
-RUN: FileCheck -check-prefix=CHECKSYMS %s < %t1
-
-CHECKSYMS: 0000025c A _DYNAMIC
-CHECKSYMS: 00001008 A _GLOBAL_OFFSET_TABLE_
diff --git a/test/old-elf/Hexagon/dynlib.test b/test/old-elf/Hexagon/dynlib.test
deleted file mode 100644
index 9e591ed06075..000000000000
--- a/test/old-elf/Hexagon/dynlib.test
+++ /dev/null
@@ -1,36 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/use-shared.hexagon -shared -o %t1
-RUN: llvm-readobj -dyn-symbols %t1 > %t2
-RUN: FileCheck -check-prefix=DYNSYMS %s < %t2
-RUN: llvm-readobj -program-headers %t1 | FileCheck %s
-
-DYNSYMS: DynamicSymbols [
-DYNSYMS: Symbol {
-DYNSYMS: Name: fn2
-DYNSYMS-NEXT: Value:
-DYNSYMS-NEXT: Size:
-DYNSYMS-NEXT: Binding: Global
-DYNSYMS-NEXT: Type: Function
-DYNSYMS-NEXT: Other:
-DYNSYMS-NEXT: Section: .text
-DYNSYMS: }
-DYNSYMS: Symbol {
-DYNSYMS: Name: fn1
-DYNSYMS-NEXT: Value:
-DYNSYMS-NEXT: Size:
-DYNSYMS-NEXT: Binding: Global
-DYNSYMS-NEXT: Type: Function
-DYNSYMS-NEXT: Other:
-DYNSYMS-NEXT: Section: .text
-DYNSYMS: }
-DYNSYMS: Symbol {
-DYNSYMS: Name: fn3
-DYNSYMS-NEXT: Value:
-DYNSYMS-NEXT: Size:
-DYNSYMS-NEXT: Binding: Global
-DYNSYMS-NEXT: Type: Function
-DYNSYMS-NEXT: Other:
-DYNSYMS-NEXT: Section: .text
-DYNSYMS-NEXT: }
-DYNSYMS-NEXT: ]
-
-CHECK-NOT: PT_PHDR
diff --git a/test/old-elf/Hexagon/hexagon-got-plt-order.test b/test/old-elf/Hexagon/hexagon-got-plt-order.test
deleted file mode 100644
index e2d37d1f6440..000000000000
--- a/test/old-elf/Hexagon/hexagon-got-plt-order.test
+++ /dev/null
@@ -1,5 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/got-plt-order.o -o %t -shared
-RUN: llvm-objdump -section-headers %t | FileCheck %s
-
-CHECK: .got
-CHECK-NEXT: .got.plt
diff --git a/test/old-elf/Hexagon/hexagon-plt-setup.test b/test/old-elf/Hexagon/hexagon-plt-setup.test
deleted file mode 100644
index 51d8bd6a6b71..000000000000
--- a/test/old-elf/Hexagon/hexagon-plt-setup.test
+++ /dev/null
@@ -1,12 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/use-shared.hexagon \
-RUN: --output-filetype=yaml --noinhibit-exec -o %t2
-RUN: FileCheck %s < %t2
-
-CHECK: - name: fn3
-CHECK: references:
-CHECK: - kind: R_HEX_B22_PCREL
-CHECK: offset: 4
- target:
-CHECK: - kind: R_HEX_B22_PCREL
-CHECK: offset: 8
- target:
diff --git a/test/old-elf/Hexagon/maxalignment.test b/test/old-elf/Hexagon/maxalignment.test
deleted file mode 100644
index 15a2bf3d80be..000000000000
--- a/test/old-elf/Hexagon/maxalignment.test
+++ /dev/null
@@ -1,8 +0,0 @@
-# This tests that we lld is able to get the contentType properly for archives
-# when they intermittently get loaded at an address whose alignment is 2
-
-RUN: lld -flavor old-gnu -target hexagon --whole-archive %p/Inputs/libMaxAlignment.a \
-RUN: --noinhibit-exec -static -o %t
-RUN: llvm-nm %t | FileCheck %s
-
-CHECK: {{[0-9a-f]+}} D a
diff --git a/test/old-elf/Hexagon/rela-order.test b/test/old-elf/Hexagon/rela-order.test
deleted file mode 100644
index 777b923fd737..000000000000
--- a/test/old-elf/Hexagon/rela-order.test
+++ /dev/null
@@ -1,9 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/dynobj.o -shared \
-RUN: --noinhibit-exec -o %t
-RUN: llvm-objdump -section-headers %t | FileCheck %s
-
-CHECK: .dynsym
-CHECK-NEXT: .dynstr
-CHECK-NEXT: .rela.dyn
-CHECK-NEXT: .rela.plt
-CHECK-NEXT: .plt
diff --git a/test/old-elf/Hexagon/sda-base.test b/test/old-elf/Hexagon/sda-base.test
deleted file mode 100644
index cfcafbce8377..000000000000
--- a/test/old-elf/Hexagon/sda-base.test
+++ /dev/null
@@ -1,4 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/sda-base.o -o %t1 --noinhibit-exec
-RUN: llvm-nm -n %t1 | FileCheck %s -check-prefix=sdabase
-
-sdabase: 00002000 A _SDA_BASE_
diff --git a/test/old-elf/Hexagon/zerofillquick-sdata.test b/test/old-elf/Hexagon/zerofillquick-sdata.test
deleted file mode 100644
index 1b932fe6e7b1..000000000000
--- a/test/old-elf/Hexagon/zerofillquick-sdata.test
+++ /dev/null
@@ -1,18 +0,0 @@
-# This tests that a typeZeroFillFast atom is associated with a section that has
-# the correct memory size.
-
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/sdata1.o %p/Inputs/sdata2.o \
-RUN: -o %t --noinhibit-exec -static
-RUN: llvm-readobj -sections %t | FileCheck -check-prefix=CHECKSECTIONSANDSIZE %s
-
-CHECKSECTIONSANDSIZE: Section {
-CHECKSECTIONSANDSIZE: Name: .sdata (13)
-CHECKSECTIONSANDSIZE: Address: 0x1000
-CHECKSECTIONSANDSIZE: Offset: 0x1000
-CHECKSECTIONSANDSIZE: Size: 24
-CHECKSECTIONSANDSIZE: }
-CHECKSECTIONSANDSIZE: Section {
-CHECKSECTIONSANDSIZE: Name: .bss (20)
-CHECKSECTIONSANDSIZE: Address: 0x1018
-CHECKSECTIONSANDSIZE: Offset: 0x1018
-CHECKSECTIONSANDSIZE: }
diff --git a/test/old-elf/Inputs/abs-test.i386 b/test/old-elf/Inputs/abs-test.i386
deleted file mode 100644
index 8556c24da551..000000000000
--- a/test/old-elf/Inputs/abs-test.i386
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/allowduplicates.objtxt b/test/old-elf/Inputs/allowduplicates.objtxt
deleted file mode 100644
index 9b8ba8902aba..000000000000
--- a/test/old-elf/Inputs/allowduplicates.objtxt
+++ /dev/null
@@ -1,12 +0,0 @@
-defined-atoms:
- - name: .text
- alignment: 16
- section-choice: custom-required
- section-name: .text
- - name: main
- scope: global
- content: [ B8, 00, 00, 00, 00, C7, 44, 24, FC, 00, 00, 00,
- 00, C3 ]
- alignment: 16
- section-choice: custom-required
- section-name: .text
diff --git a/test/old-elf/Inputs/bar.o.x86-64 b/test/old-elf/Inputs/bar.o.x86-64
deleted file mode 100644
index 467485f0bb96..000000000000
--- a/test/old-elf/Inputs/bar.o.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/branch-test.hexagon b/test/old-elf/Inputs/branch-test.hexagon
deleted file mode 100644
index 1ffb47228e32..000000000000
--- a/test/old-elf/Inputs/branch-test.hexagon
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/branch-test.ppc b/test/old-elf/Inputs/branch-test.ppc
deleted file mode 100644
index 4698941e7503..000000000000
--- a/test/old-elf/Inputs/branch-test.ppc
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/consecutive-weak-defs.o.yaml b/test/old-elf/Inputs/consecutive-weak-defs.o.yaml
deleted file mode 100644
index cbd9c665b6d5..000000000000
--- a/test/old-elf/Inputs/consecutive-weak-defs.o.yaml
+++ /dev/null
@@ -1,65 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 554889E5E8000000005DC3554889E5B8640000005DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000005
- Symbol: my_weak_func
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: my_func
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000000B
- Weak:
- - Name: my_weak_func
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000000B
- Size: 0x000000000000000B
- - Name: my_weak_func2
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000000B
- Size: 0x000000000000000B
- - Name: my_weak_func3
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000000B
- Size: 0x000000000000000B
-...
diff --git a/test/old-elf/Inputs/constants-merge.x86-64 b/test/old-elf/Inputs/constants-merge.x86-64
deleted file mode 100644
index 0087eb8f8cb5..000000000000
--- a/test/old-elf/Inputs/constants-merge.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/constdata.x86-64 b/test/old-elf/Inputs/constdata.x86-64
deleted file mode 100644
index d877a5535357..000000000000
--- a/test/old-elf/Inputs/constdata.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/foo.o.x86-64 b/test/old-elf/Inputs/foo.o.x86-64
deleted file mode 100644
index 72a89eefa8ed..000000000000
--- a/test/old-elf/Inputs/foo.o.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/globalconst.c b/test/old-elf/Inputs/globalconst.c
deleted file mode 100644
index 08395a88e7ca..000000000000
--- a/test/old-elf/Inputs/globalconst.c
+++ /dev/null
@@ -1,2 +0,0 @@
-/* compile the code with -fmerge-all-constants */
-const char mystr[] = "foobar";
diff --git a/test/old-elf/Inputs/globalconst.o.x86-64 b/test/old-elf/Inputs/globalconst.o.x86-64
deleted file mode 100644
index d8e266e76334..000000000000
--- a/test/old-elf/Inputs/globalconst.o.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/gotpcrel.S b/test/old-elf/Inputs/gotpcrel.S
deleted file mode 100644
index 300675f59612..000000000000
--- a/test/old-elf/Inputs/gotpcrel.S
+++ /dev/null
@@ -1,11 +0,0 @@
- .text
- .globl main
- .align 16, 0x90
- .type main,@function
-main: # @main
- movq blah@GOTPCREL(%rip), %rax
- movq main@GOTPCREL(%rip), %rax
- ret
-
- .weak blah
- .type blah,@function
diff --git a/test/old-elf/Inputs/gotpcrel.x86-64 b/test/old-elf/Inputs/gotpcrel.x86-64
deleted file mode 100644
index f9c61d0edf15..000000000000
--- a/test/old-elf/Inputs/gotpcrel.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/group-cmd-search-1.ls b/test/old-elf/Inputs/group-cmd-search-1.ls
deleted file mode 100644
index 965369309a20..000000000000
--- a/test/old-elf/Inputs/group-cmd-search-1.ls
+++ /dev/null
@@ -1 +0,0 @@
-GROUP ( shared.so-x86-64 )
diff --git a/test/old-elf/Inputs/group-cmd-search-2.ls b/test/old-elf/Inputs/group-cmd-search-2.ls
deleted file mode 100644
index f1eee6a35efa..000000000000
--- a/test/old-elf/Inputs/group-cmd-search-2.ls
+++ /dev/null
@@ -1 +0,0 @@
-GROUP ( /shared.so-x86-64 )
diff --git a/test/old-elf/Inputs/group-cmd-search-3.ls b/test/old-elf/Inputs/group-cmd-search-3.ls
deleted file mode 100644
index 83ce0ca62fb1..000000000000
--- a/test/old-elf/Inputs/group-cmd-search-3.ls
+++ /dev/null
@@ -1 +0,0 @@
-GROUP ( -l:shared.so-x86-64 -lfnarchive )
diff --git a/test/old-elf/Inputs/ifunc.S b/test/old-elf/Inputs/ifunc.S
deleted file mode 100644
index 0ac1f5a5b0bb..000000000000
--- a/test/old-elf/Inputs/ifunc.S
+++ /dev/null
@@ -1,21 +0,0 @@
- .text
- .globl hey;
- .type hey, @function;
-hey:
- .type hey, @gnu_indirect_function;
- leaq __hey_1(%rip), %rax
- ret
-
- .text
- .type __hey_1, @function;
- .globl __hey_1;
-__hey_1:
- movq $42, %rax
- ret
-
- .text
- .type plt, @function;
- .globl plt;
-plt:
- call hey@PLT
- ret
diff --git a/test/old-elf/Inputs/ifunc.cpp b/test/old-elf/Inputs/ifunc.cpp
deleted file mode 100644
index 2e520277d36c..000000000000
--- a/test/old-elf/Inputs/ifunc.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-extern "C" int hey();
-
-int main() { return hey(); }
diff --git a/test/old-elf/Inputs/ifunc.cpp.x86-64 b/test/old-elf/Inputs/ifunc.cpp.x86-64
deleted file mode 100644
index 20c812cabd2c..000000000000
--- a/test/old-elf/Inputs/ifunc.cpp.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/ifunc.x86-64 b/test/old-elf/Inputs/ifunc.x86-64
deleted file mode 100644
index 36c8e04ca837..000000000000
--- a/test/old-elf/Inputs/ifunc.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/libfnarchive.a b/test/old-elf/Inputs/libfnarchive.a
deleted file mode 100644
index 753acd6e2c65..000000000000
--- a/test/old-elf/Inputs/libfnarchive.a
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/libifunc.x86-64.so b/test/old-elf/Inputs/libifunc.x86-64.so
deleted file mode 100644
index 0f05b308ce78..000000000000
--- a/test/old-elf/Inputs/libifunc.x86-64.so
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/libundef.so b/test/old-elf/Inputs/libundef.so
deleted file mode 100644
index 41f2a668f360..000000000000
--- a/test/old-elf/Inputs/libundef.so
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/libweaksym.so b/test/old-elf/Inputs/libweaksym.so
deleted file mode 100755
index 7ff4ea56ae60..000000000000
--- a/test/old-elf/Inputs/libweaksym.so
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/main-with-global-def.o.yaml b/test/old-elf/Inputs/main-with-global-def.o.yaml
deleted file mode 100644
index d3eeb8fe24b6..000000000000
--- a/test/old-elf/Inputs/main-with-global-def.o.yaml
+++ /dev/null
@@ -1,55 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 554889E5B8C80000005DC3554889E54883EC10C745FC00000000B000E8000000004883C4105DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x000000000000001D
- Symbol: my_func
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000000B
- Size: 0x000000000000001C
- - Name: my_weak_func2
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000000B
- - Name: my_func
-...
diff --git a/test/old-elf/Inputs/mainobj.x86_64 b/test/old-elf/Inputs/mainobj.x86_64
deleted file mode 100644
index d0f29418237d..000000000000
--- a/test/old-elf/Inputs/mainobj.x86_64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/no-unique-section-names.x86-64 b/test/old-elf/Inputs/no-unique-section-names.x86-64
deleted file mode 100644
index fd92f5f0c6e7..000000000000
--- a/test/old-elf/Inputs/no-unique-section-names.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/object-test.elf-hexagon b/test/old-elf/Inputs/object-test.elf-hexagon
deleted file mode 100644
index bfc85a7d0b76..000000000000
--- a/test/old-elf/Inputs/object-test.elf-hexagon
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/object-test.elf-i386 b/test/old-elf/Inputs/object-test.elf-i386
deleted file mode 100644
index 872684c7fcc1..000000000000
--- a/test/old-elf/Inputs/object-test.elf-i386
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/phdr.i386 b/test/old-elf/Inputs/phdr.i386
deleted file mode 100644
index 7c83dd314891..000000000000
--- a/test/old-elf/Inputs/phdr.i386
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/quickdata-sort-test.o.elf-hexagon b/test/old-elf/Inputs/quickdata-sort-test.o.elf-hexagon
deleted file mode 100644
index 03d028707129..000000000000
--- a/test/old-elf/Inputs/quickdata-sort-test.o.elf-hexagon
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon b/test/old-elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon
deleted file mode 100644
index 410a3d47d320..000000000000
--- a/test/old-elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/quickdata-test.elf-hexagon b/test/old-elf/Inputs/quickdata-test.elf-hexagon
deleted file mode 100644
index c3ae53a6babe..000000000000
--- a/test/old-elf/Inputs/quickdata-test.elf-hexagon
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/reloc-test.elf-i386 b/test/old-elf/Inputs/reloc-test.elf-i386
deleted file mode 100644
index 1a5558131fff..000000000000
--- a/test/old-elf/Inputs/reloc-test.elf-i386
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/reloc-xb.x86 b/test/old-elf/Inputs/reloc-xb.x86
deleted file mode 100644
index 4d9770aa2356..000000000000
--- a/test/old-elf/Inputs/reloc-xb.x86
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/reloc-xt.x86 b/test/old-elf/Inputs/reloc-xt.x86
deleted file mode 100644
index dcdfbfb09f71..000000000000
--- a/test/old-elf/Inputs/reloc-xt.x86
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/relocs-dynamic.x86-64 b/test/old-elf/Inputs/relocs-dynamic.x86-64
deleted file mode 100644
index 0c44924d18e6..000000000000
--- a/test/old-elf/Inputs/relocs-dynamic.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/relocs.x86-64 b/test/old-elf/Inputs/relocs.x86-64
deleted file mode 100644
index 112dfa733db9..000000000000
--- a/test/old-elf/Inputs/relocs.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/responsefile b/test/old-elf/Inputs/responsefile
deleted file mode 100644
index 2fe657a0e3b0..000000000000
--- a/test/old-elf/Inputs/responsefile
+++ /dev/null
@@ -1 +0,0 @@
---inresponsefile
diff --git a/test/old-elf/Inputs/rodata-test.hexagon b/test/old-elf/Inputs/rodata-test.hexagon
deleted file mode 100644
index f448748e2abe..000000000000
--- a/test/old-elf/Inputs/rodata-test.hexagon
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/rodata-test.i386 b/test/old-elf/Inputs/rodata-test.i386
deleted file mode 100644
index 09f71eb59969..000000000000
--- a/test/old-elf/Inputs/rodata-test.i386
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/rodata.c b/test/old-elf/Inputs/rodata.c
deleted file mode 100644
index b43c9c945898..000000000000
--- a/test/old-elf/Inputs/rodata.c
+++ /dev/null
@@ -1,4 +0,0 @@
-const unsigned char *str = "llvm";
-int foo() {
- return str[0];
-}
diff --git a/test/old-elf/Inputs/rodata.o b/test/old-elf/Inputs/rodata.o
deleted file mode 100644
index f13ddc9bba98..000000000000
--- a/test/old-elf/Inputs/rodata.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/section-test.i386 b/test/old-elf/Inputs/section-test.i386
deleted file mode 100644
index 2b447a9f8f5b..000000000000
--- a/test/old-elf/Inputs/section-test.i386
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/shared.c b/test/old-elf/Inputs/shared.c
deleted file mode 100644
index 2be91c4b9e45..000000000000
--- a/test/old-elf/Inputs/shared.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-
-extern int i;
-int i = 42;
-
-// Undefined weak function in a dynamic library.
-__attribute__((weak)) void weakfoo();
-
-// Regular function in a dynamic library.
-void foo() {
- // Try to call weakfoo so that the reference to weekfoo will be included in
- // the resulting .so file.
- if (weakfoo)
- weakfoo();
- puts("Fooo!!");
-}
diff --git a/test/old-elf/Inputs/shared.so-x86-64 b/test/old-elf/Inputs/shared.so-x86-64
deleted file mode 100644
index 0240f0e67431..000000000000
--- a/test/old-elf/Inputs/shared.so-x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/shndx.o-x86_64 b/test/old-elf/Inputs/shndx.o-x86_64
deleted file mode 100644
index 9e3e5d8526d7..000000000000
--- a/test/old-elf/Inputs/shndx.o-x86_64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/stripped-empty.x86_64 b/test/old-elf/Inputs/stripped-empty.x86_64
deleted file mode 100644
index 7368ba280d79..000000000000
--- a/test/old-elf/Inputs/stripped-empty.x86_64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/target-test.hexagon b/test/old-elf/Inputs/target-test.hexagon
deleted file mode 100644
index 7da114561920..000000000000
--- a/test/old-elf/Inputs/target-test.hexagon
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/target-test.ppc b/test/old-elf/Inputs/target-test.ppc
deleted file mode 100644
index 001be338c20d..000000000000
--- a/test/old-elf/Inputs/target-test.ppc
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/tls-tbss-size.yaml b/test/old-elf/Inputs/tls-tbss-size.yaml
deleted file mode 100644
index 0577dd157c6e..000000000000
--- a/test/old-elf/Inputs/tls-tbss-size.yaml
+++ /dev/null
@@ -1,59 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .tbss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Size: 16
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
- - Name: t1.c
- Type: STT_FILE
- - Name: .tbss
- Type: STT_TLS
- Section: .tbss
- Global:
- - Name: t0
- Type: STT_TLS
- Section: .tbss
- Size: 0x0000000000000004
- - Name: t1
- Type: STT_TLS
- Section: .tbss
- Value: 0x0000000000000004
- Size: 0x0000000000000004
- - Name: t2
- Type: STT_TLS
- Section: .tbss
- Value: 0x0000000000000008
- Size: 0x0000000000000004
- - Name: t3
- Type: STT_TLS
- Section: .tbss
- Value: 0x000000000000000C
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/Inputs/tls.S b/test/old-elf/Inputs/tls.S
deleted file mode 100644
index 7d9eab647b53..000000000000
--- a/test/old-elf/Inputs/tls.S
+++ /dev/null
@@ -1,50 +0,0 @@
- .text
- .globl main
- .align 16, 0x90
- .type main,@function
-main: # @main
- callq GOTTPOFF
- addl %fs:tls1@TPOFF, %eax
- addl %fs:tls0@TPOFF, %eax
- addl %fs:tls2@TPOFF, %eax
- ret
-
- .text
- .globl GOTTPOFF
- .type GOTTPOFF,@function
-GOTTPOFF:
- movq tls2@GOTTPOFF(%rip), %rax
- movl %fs:0(%rax), %eax
- ret
-
- .text
- .globl TLSLD
- .type TLSLD,@function
-TLSLD:
- leaq tls0@tlsld(%rip), %rdi
- call __tls_get_addr@plt
- leaq tls0@dtpoff(%rax), %rax
- ret
-
- .type tls0,@object # @tls0
- .section .tbss,"awT",@nobits
- .globl tls0
- .align 4
-tls0:
- .long 0 # 0x0
- .size tls0, 4
-
- .type tls1,@object # @tls1
- .globl tls1
- .align 4
-tls1:
- .long 0 # 0x0
- .size tls1, 4
-
- .type tls2,@object # @tls2
- .section .tdata,"awT",@progbits
- .globl tls2
- .align 4
-tls2:
- .long 1 # 0x1
- .size tls2, 4
diff --git a/test/old-elf/Inputs/tls.c b/test/old-elf/Inputs/tls.c
deleted file mode 100644
index 672350756562..000000000000
--- a/test/old-elf/Inputs/tls.c
+++ /dev/null
@@ -1,11 +0,0 @@
-extern __thread int tls0;
-extern __thread int tls1;
-extern __thread int tls2;
-
-__thread int tls0 = 0;
-__thread int tls1 = 0;
-__thread int tls2 = 1;
-
-int main() {
- return tls0 + tls1 + tls2;
-}
diff --git a/test/old-elf/Inputs/tls.x86-64 b/test/old-elf/Inputs/tls.x86-64
deleted file mode 100644
index b420ce89b19b..000000000000
--- a/test/old-elf/Inputs/tls.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/tlsAddr.x86-64 b/test/old-elf/Inputs/tlsAddr.x86-64
deleted file mode 100644
index 16cc9ab25abf..000000000000
--- a/test/old-elf/Inputs/tlsAddr.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/tlsaddr.c b/test/old-elf/Inputs/tlsaddr.c
deleted file mode 100644
index f62d57b3bfb4..000000000000
--- a/test/old-elf/Inputs/tlsaddr.c
+++ /dev/null
@@ -1,8 +0,0 @@
-__thread int tls0 = 0;
-__thread int tls1 = 0;
-__thread int tls2 = 1;
-__thread int tls3 = 2;
-
-int main() {
- return tls0 + tls1 + tls2;
-}
diff --git a/test/old-elf/Inputs/undef-from-main-so.c b/test/old-elf/Inputs/undef-from-main-so.c
deleted file mode 100644
index f1cb63db7ada..000000000000
--- a/test/old-elf/Inputs/undef-from-main-so.c
+++ /dev/null
@@ -1 +0,0 @@
-int x[2] = {1, 2};
diff --git a/test/old-elf/Inputs/undef-from-main.c b/test/old-elf/Inputs/undef-from-main.c
deleted file mode 100644
index 366d934dd84f..000000000000
--- a/test/old-elf/Inputs/undef-from-main.c
+++ /dev/null
@@ -1,5 +0,0 @@
-extern int x[2];
-
-int main() {
- x[0] = 2;
-}
diff --git a/test/old-elf/Inputs/undef-pc32.o b/test/old-elf/Inputs/undef-pc32.o
deleted file mode 100644
index 954916d59991..000000000000
--- a/test/old-elf/Inputs/undef-pc32.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/undef.o b/test/old-elf/Inputs/undef.o
deleted file mode 100644
index 3c9b60c6ca33..000000000000
--- a/test/old-elf/Inputs/undef.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/undef2-so.o.yaml b/test/old-elf/Inputs/undef2-so.o.yaml
deleted file mode 100644
index f640cea39a5d..000000000000
--- a/test/old-elf/Inputs/undef2-so.o.yaml
+++ /dev/null
@@ -1,49 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000001
- Content: 554889E5488B05000000008B005DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000007
- Symbol: myexportedsymbol
- Type: R_X86_64_GOTPCREL
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: func
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000000F
- - Name: _GLOBAL_OFFSET_TABLE_
- - Name: myexportedsymbol
diff --git a/test/old-elf/Inputs/use-shared-32s.c b/test/old-elf/Inputs/use-shared-32s.c
deleted file mode 100644
index 63054cb036ea..000000000000
--- a/test/old-elf/Inputs/use-shared-32s.c
+++ /dev/null
@@ -1,8 +0,0 @@
-void foo();
-
-void (*func)();
-
-int main() {
- func = foo;
- func();
-}
diff --git a/test/old-elf/Inputs/use-shared-32s.x86-64 b/test/old-elf/Inputs/use-shared-32s.x86-64
deleted file mode 100644
index 7e223677b93f..000000000000
--- a/test/old-elf/Inputs/use-shared-32s.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/use-shared.c b/test/old-elf/Inputs/use-shared.c
deleted file mode 100644
index b370eaa4fac2..000000000000
--- a/test/old-elf/Inputs/use-shared.c
+++ /dev/null
@@ -1,7 +0,0 @@
-extern int i;
-void foo();
-
-int main() {
- foo();
- return i;
-}
diff --git a/test/old-elf/Inputs/use-shared.x86-64 b/test/old-elf/Inputs/use-shared.x86-64
deleted file mode 100644
index 25e1eb87a2b4..000000000000
--- a/test/old-elf/Inputs/use-shared.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/weaksym.o b/test/old-elf/Inputs/weaksym.o
deleted file mode 100644
index 010ce704a313..000000000000
--- a/test/old-elf/Inputs/weaksym.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/writersyms.o b/test/old-elf/Inputs/writersyms.o
deleted file mode 100644
index 7cd472d99d77..000000000000
--- a/test/old-elf/Inputs/writersyms.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/Inputs/x86-64-relocs.S b/test/old-elf/Inputs/x86-64-relocs.S
deleted file mode 100644
index 2547c0f19bb0..000000000000
--- a/test/old-elf/Inputs/x86-64-relocs.S
+++ /dev/null
@@ -1,12 +0,0 @@
- .text
- .globl main
- .align 16, 0x90
- .type main,@function
-main: # @main
- call foo@PLT
- ret
-
- .globl foo
- .type foo,@function
-foo:
- ret
diff --git a/test/old-elf/Mips/abi-flags-01.test b/test/old-elf/Mips/abi-flags-01.test
deleted file mode 100644
index d2eb13f3186a..000000000000
--- a/test/old-elf/Mips/abi-flags-01.test
+++ /dev/null
@@ -1,35 +0,0 @@
-# Check rejecting .MIPS.abiflags section with a wrong version.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: {{.*}}abi-flags-01.test.tmp.o: .MIPS.abiflags section has unsupported version '1'
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- Version: 1
- ISA: MIPS32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/abi-flags-02.test b/test/old-elf/Mips/abi-flags-02.test
deleted file mode 100644
index f3c1f29abc55..000000000000
--- a/test/old-elf/Mips/abi-flags-02.test
+++ /dev/null
@@ -1,92 +0,0 @@
-# Check generation of .MIPS.abiflags section under the following conditions:
-# - There is the only input object file
-# - The input file has valid .MIPS.abiflags section
-#
-# The .MIPS.abiflags section in the output file should have the same
-# settings as the input section.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -s -program-headers -mips-abi-flags %t.so | FileCheck %s
-
-# CHECK: Section {
-# CHECK: Index: 1
-# CHECK-NEXT: Name: .MIPS.abiflags
-# CHECK-NEXT: Type: SHT_MIPS_ABIFLAGS
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: SHF_ALLOC
-# CHECK-NEXT: ]
-# CHECK-NEXT: Address: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: Size: 24
-# CHECK-NEXT: Link: 0
-# CHECK-NEXT: Info: 0
-# CHECK-NEXT: AddressAlignment: 8
-# CHECK-NEXT: EntrySize: 24
-# CHECK-NEXT: }
-
-# CHECK: ProgramHeaders [
-# CHECK-NEXT: ProgramHeader {
-# CHECK-NEXT: Type: PT_MIPS_ABIFLAGS (0x70000003)
-# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: PhysicalAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: FileSize: 24
-# CHECK-NEXT: MemSize: 24
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: PF_R
-# CHECK-NEXT: ]
-# CHECK-NEXT: Alignment: 8
-# CHECK-NEXT: }
-
-# CHECK: MIPS ABI Flags {
-# CHECK-NEXT: Version: 0
-# CHECK-NEXT: ISA: MIPS32r2
-# CHECK-NEXT: ISA Extension: None (0x0)
-# CHECK-NEXT: ASEs [ (0x800)
-# CHECK-NEXT: microMIPS (0x800)
-# CHECK-NEXT: ]
-# CHECK-NEXT: FP ABI: Hard float (32-bit CPU, Any FPU) (0x5)
-# CHECK-NEXT: GPR size: 32
-# CHECK-NEXT: CPR1 size: 32
-# CHECK-NEXT: CPR2 size: 0
-# CHECK-NEXT: Flags 1 [ (0x0)
-# CHECK-NEXT: ]
-# CHECK-NEXT: Flags 2: 0x0
-# CHECK-NEXT: }
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- ISAExtension: EXT_NONE
- ASEs: [ MICROMIPS ]
- FpABI: FP_XX
- GPRSize: REG_32
- CPR1Size: REG_32
- CPR2Size: REG_NONE
- Flags1: [ ]
- Flags2: 0x0
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/abi-flags-03.test b/test/old-elf/Mips/abi-flags-03.test
deleted file mode 100644
index a28bb2826730..000000000000
--- a/test/old-elf/Mips/abi-flags-03.test
+++ /dev/null
@@ -1,149 +0,0 @@
-# Check generation of .MIPS.abiflags section under the following conditions:
-# - There are multiple input object files
-# - Every input file has valid .MIPS.abiflags section
-# - All .MIPS.abiflags sections are compatible with each other
-#
-# The .MIPS.abiflags section in the output file should reproduce result
-# of merging input object file sections.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t3.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t1.o %t2.o %t3.o
-# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s
-
-# CHECK: MIPS ABI Flags {
-# CHECK-NEXT: Version: 0
-# CHECK-NEXT: ISA: MIPS32r2
-# CHECK-NEXT: ISA Extension: None (0x0)
-# CHECK-NEXT: ASEs [ (0x810)
-# CHECK-NEXT: MDMX (0x10)
-# CHECK-NEXT: microMIPS (0x800)
-# CHECK-NEXT: ]
-# CHECK-NEXT: FP ABI: Hard float (double precision) (0x1)
-# CHECK-NEXT: GPR size: 32
-# CHECK-NEXT: CPR1 size: 64
-# CHECK-NEXT: CPR2 size: 0
-# CHECK-NEXT: Flags 1 [ (0x1)
-# CHECK-NEXT: ODDSPREG
-# CHECK-NEXT: ]
-# CHECK-NEXT: Flags 2: 0x0
-# CHECK-NEXT: }
-
-# o1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- ISAExtension: EXT_NONE
- ASEs: [ MDMX ]
- FpABI: FP_DOUBLE
- GPRSize: REG_32
- CPR1Size: REG_64
- CPR2Size: REG_NONE
- Flags1: [ ]
- Flags2: 0x0
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# o2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- ISAExtension: EXT_NONE
- ASEs: [ MICROMIPS ]
- FpABI: FP_XX
- GPRSize: REG_32
- CPR1Size: REG_32
- CPR2Size: REG_NONE
- Flags1: [ODDSPREG]
- Flags2: 0x0
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# o3.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- ISAExtension: EXT_NONE
- ASEs: [ MICROMIPS ]
- FpABI: FP_XX
- GPRSize: REG_32
- CPR1Size: REG_32
- CPR2Size: REG_NONE
- Flags1: [ ]
- Flags2: 0x0
-
-Symbols:
- Global:
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/abi-flags-04.test b/test/old-elf/Mips/abi-flags-04.test
deleted file mode 100644
index 6cde797dd3a0..000000000000
--- a/test/old-elf/Mips/abi-flags-04.test
+++ /dev/null
@@ -1,125 +0,0 @@
-# Check generation of .MIPS.abiflags section under the following conditions:
-# - There are multiple input object files
-# - Every input file has valid .MIPS.abiflags section
-# - .MIPS.abiflags sections have different but compatible FP ABI
-#
-# The .MIPS.abiflags section in the output file should reproduce result
-# of merging FP ABI flags.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-xx.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-double.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-64.o
-# RUN: yaml2obj -format=elf -docnum 4 %s > %t-64a.o
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1 %t-xx.o %t-double.o
-# RUN: llvm-readobj -mips-abi-flags %t1 | FileCheck -check-prefix=XX-DOUBLE %s
-
-# XX-DOUBLE: FP ABI: Hard float (double precision) (0x1)
-# XX-DOUBLE: GPR size: 32
-# XX-DOUBLE: CPR1 size: 32
-# XX-DOUBLE: Flags 1 [ (0x0)
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2 %t-xx.o %t-64.o
-# RUN: llvm-readobj -mips-abi-flags %t2 | FileCheck -check-prefix=XX-64 %s
-
-# XX-64: FP ABI: Hard float (32-bit CPU, 64-bit FPU) (0x6)
-# XX-64: GPR size: 32
-# XX-64: CPR1 size: 64
-# XX-64: Flags 1 [ (0x1)
-# XX-64: ODDSPREG (0x1)
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t3 %t-xx.o %t-64a.o
-# RUN: llvm-readobj -mips-abi-flags %t3 | FileCheck -check-prefix=XX-64A %s
-
-# XX-64A: FP ABI: Hard float compat (32-bit CPU, 64-bit FPU) (0x7)
-# XX-64A: GPR size: 32
-# XX-64A: CPR1 size: 64
-# XX-64A: Flags 1 [ (0x0)
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t4 %t-64.o %t-64a.o
-# RUN: llvm-readobj -mips-abi-flags %t4 | FileCheck -check-prefix=64-64A %s
-
-# 64-64A: FP ABI: Hard float (32-bit CPU, 64-bit FPU) (0x6)
-# 64-64A: GPR size: 32
-# 64-64A: CPR1 size: 64
-# 64-64A: Flags 1 [ (0x1)
-# 64-64A: ODDSPREG (0x1)
-
-# xx.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- FpABI: FP_XX
- GPRSize: REG_32
- CPR1Size: REG_32
-
-# double.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- FpABI: FP_DOUBLE
- GPRSize: REG_32
- CPR1Size: REG_32
-
-# 64.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- FpABI: FP_64
- GPRSize: REG_32
- CPR1Size: REG_64
- Flags1: [ODDSPREG]
-
-# 64a.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- FpABI: FP_64A
- GPRSize: REG_32
- CPR1Size: REG_64
- Flags1: []
-...
diff --git a/test/old-elf/Mips/abi-flags-05.test b/test/old-elf/Mips/abi-flags-05.test
deleted file mode 100644
index 6a009db7344a..000000000000
--- a/test/old-elf/Mips/abi-flags-05.test
+++ /dev/null
@@ -1,186 +0,0 @@
-# Check generation of .MIPS.abiflags section under the following conditions:
-# - There are multiple input object files
-# - Every input file has valid .MIPS.abiflags section
-# - .MIPS.abiflags sections have different and incompatible FP ABI
-#
-# The .MIPS.abiflags section in the output file should reproduce result
-# of merging FP ABI flags but the linker must show a warning.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-xx.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-dbl.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-sgl.o
-# RUN: yaml2obj -format=elf -docnum 4 %s > %t-soft.o
-# RUN: yaml2obj -format=elf -docnum 5 %s > %t-64.o
-# RUN: yaml2obj -format=elf -docnum 6 %s > %t-64a.o
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1 %t-xx.o %t-sgl.o 2>&1 \
-# RUN: | FileCheck -check-prefix=XX-SINGLE-WARN %s
-
-# XX-SINGLE-WARN: FP ABI {{-mfpxx|-msingle-float}} is incompatible with {{-msingle-float|-mfpxx}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2 %t-xx.o %t-soft.o 2>&1 \
-# RUN: | FileCheck -check-prefix=XX-SOFT-WARN %s
-
-# XX-SOFT-WARN: FP ABI {{-mfpxx|-msoft-float}} is incompatible with {{-msoft-float|-mfpxx}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t3 %t-dbl.o %t-sgl.o 2>&1 \
-# RUN: | FileCheck -check-prefix=DOUBLE-SINGLE-WARN %s
-
-# DOUBLE-SINGLE-WARN: FP ABI {{-mdouble-float|-msingle-float}} is incompatible with {{-msingle-float|-mdouble-float}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t4 %t-dbl.o %t-soft.o 2>&1 \
-# RUN: | FileCheck -check-prefix=DOUBLE-SOFT-WARN %s
-
-# DOUBLE-SOFT-WARN: FP ABI {{-mdouble-float|-msoft-float}} is incompatible with {{-msoft-float|-mdouble-float}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t5 %t-dbl.o %t-64.o 2>&1 \
-# RUN: | FileCheck -check-prefix=DOUBLE-64-WARN %s
-
-# DOUBLE-64-WARN: FP ABI {{-mdouble-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-mdouble-float}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t6 %t-dbl.o %t-64a.o 2>&1 \
-# RUN: | FileCheck -check-prefix=DOUBLE-64A-WARN %s
-
-# DOUBLE-64A-WARN: FP ABI {{-mdouble-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-mdouble-float}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t7 %t-sgl.o %t-soft.o 2>&1 \
-# RUN: | FileCheck -check-prefix=SINGLE-SOFT-WARN %s
-
-# SINGLE-SOFT-WARN: FP ABI {{-msingle-float|-msoft-float}} is incompatible with {{-msoft-float|-msingle-float}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t8 %t-sgl.o %t-64.o 2>&1 \
-# RUN: | FileCheck -check-prefix=SINGLE-64-WARN %s
-
-# SINGLE-64-WARN: FP ABI {{-msingle-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-msingle-float}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t9 %t-sgl.o %t-64a.o 2>&1 \
-# RUN: | FileCheck -check-prefix=SINGLE-64A-WARN %s
-
-# SINGLE-64A-WARN: FP ABI {{-msingle-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-msingle-float}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t10 %t-soft.o %t-64.o 2>&1 \
-# RUN: | FileCheck -check-prefix=SOFT-64-WARN %s
-
-# SOFT-64-WARN: FP ABI {{-msoft-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-msoft-float}}
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t11 %t-soft.o %t-64a.o 2>&1 \
-# RUN: | FileCheck -check-prefix=SOFT-64A-WARN %s
-
-# SOFT-64A-WARN: FP ABI {{-msoft-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-msoft-float}}
-
-# xx.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- FpABI: FP_XX
- GPRSize: REG_32
- CPR1Size: REG_32
-
-# double.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- FpABI: FP_DOUBLE
- GPRSize: REG_32
- CPR1Size: REG_32
-
-# single.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- FpABI: FP_SINGLE
- GPRSize: REG_32
- CPR1Size: REG_32
-
-# soft.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- FpABI: FP_SOFT
- GPRSize: REG_32
- CPR1Size: REG_NONE
-
-# 64.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- FpABI: FP_64
- GPRSize: REG_32
- CPR1Size: REG_64
- Flags1: [ODDSPREG]
-
-# 64a.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- FpABI: FP_64A
- GPRSize: REG_32
- CPR1Size: REG_64
- Flags1: []
-...
diff --git a/test/old-elf/Mips/abi-flags-06.test b/test/old-elf/Mips/abi-flags-06.test
deleted file mode 100644
index d7df379039bb..000000000000
--- a/test/old-elf/Mips/abi-flags-06.test
+++ /dev/null
@@ -1,79 +0,0 @@
-# Check generation of .MIPS.abiflags section under the following conditions:
-# - There are multiple input object files
-# - Not all input files have a .MIPS.abiflags section
-#
-# The .MIPS.abiflags section in the output file should reproduce result
-# of merging input object file sections and data come from ELF header flags.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-abi.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-elf.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-abi.o %t-elf.o
-# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s
-
-# CHECK: MIPS ABI Flags {
-# CHECK-NEXT: Version: 0
-# CHECK-NEXT: ISA: MIPS32r2
-# CHECK-NEXT: ISA Extension: None (0x0)
-# CHECK-NEXT: ASEs [ (0x810)
-# CHECK-NEXT: MDMX (0x10)
-# CHECK-NEXT: microMIPS (0x800)
-# CHECK-NEXT: ]
-# CHECK-NEXT: FP ABI: Hard float (double precision) (0x1)
-# CHECK-NEXT: GPR size: 32
-# CHECK-NEXT: CPR1 size: 64
-# CHECK-NEXT: CPR2 size: 0
-# CHECK-NEXT: Flags 1 [ (0x0)
-# CHECK-NEXT: ]
-# CHECK-NEXT: Flags 2: 0x0
-# CHECK-NEXT: }
-
-# abi.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- ISAExtension: EXT_NONE
- ASEs: [ MDMX ]
- FpABI: FP_DOUBLE
- GPRSize: REG_32
- CPR1Size: REG_64
- CPR2Size: REG_NONE
- Flags1: [ ]
- Flags2: 0x0
-
-# elf.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/abi-flags-07.test b/test/old-elf/Mips/abi-flags-07.test
deleted file mode 100644
index 6cae9b2feb4d..000000000000
--- a/test/old-elf/Mips/abi-flags-07.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Check that .MIPS.abiflags section is not written if no input object files
-# contain that section.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t1.o %t2.o
-# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s
-
-# CHECK: There is no .MIPS.abiflags section in the file.
-
-# abi.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# elf.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/abi-flags-08.test b/test/old-elf/Mips/abi-flags-08.test
deleted file mode 100644
index c4b75bcf4516..000000000000
--- a/test/old-elf/Mips/abi-flags-08.test
+++ /dev/null
@@ -1,71 +0,0 @@
-# Check that the linker shows errors if ELF header flags
-# and .MIPS.abiflags section are incompatible.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-isa.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-ext.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-ases.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t-isa.o 2>&1 \
-# RUN: | FileCheck -check-prefix=ISA-ERR %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2.so %t-ext.o 2>&1 \
-# RUN: | FileCheck -check-prefix=EXT-ERR %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t3.so %t-ases.o 2>&1 \
-# RUN: | FileCheck -check-prefix=ASE-ERR %s
-# RUN: llvm-readobj -mips-abi-flags %t1.so %t2.so %t3.so \
-# RUN: | FileCheck -check-prefix=SEC %s
-
-# ISA-ERR: inconsistent ISA between .MIPS.abiflags and ELF header e_flags field
-# EXT-ERR: inconsistent ISA between .MIPS.abiflags and ELF header e_flags field
-# ASE-ERR: inconsistent ASEs between .MIPS.abiflags and ELF header e_flags field
-
-# SEC: There is no .MIPS.abiflags section in the file.
-
-# isa.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
-
-# ext.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_3, EF_MIPS_MACH_4650]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS3
- ISAExtension: EXT_4120
-
-# ases.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- ASEs: []
-
-...
diff --git a/test/old-elf/Mips/abi-flags-09.test b/test/old-elf/Mips/abi-flags-09.test
deleted file mode 100644
index 1ab03abe3810..000000000000
--- a/test/old-elf/Mips/abi-flags-09.test
+++ /dev/null
@@ -1,67 +0,0 @@
-# Check position of PT_MIPS_ABIFLAGS segment.
-# It should go right after the PT_INTERP segment.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s
-
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_INTERP
-# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: PhysicalAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: FileSize: 13
-# CHECK-NEXT: MemSize: 13
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: PF_R
-# CHECK-NEXT: ]
-# CHECK-NEXT: Alignment: 1
-# CHECK-NEXT: }
-# CHECK-NEXT: ProgramHeader {
-# CHECK-NEXT: Type: PT_MIPS_ABIFLAGS
-# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: PhysicalAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: FileSize: 24
-# CHECK-NEXT: MemSize: 24
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: PF_R
-# CHECK-NEXT: ]
-# CHECK-NEXT: Alignment: 8
-# CHECK-NEXT: }
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- ISAExtension: EXT_NONE
- ASEs: [ MICROMIPS ]
- FpABI: FP_XX
- GPRSize: REG_32
- CPR1Size: REG_32
- CPR2Size: REG_NONE
- Flags1: [ ]
- Flags2: 0x0
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/abi-flags-10.test b/test/old-elf/Mips/abi-flags-10.test
deleted file mode 100644
index 50732d5c1151..000000000000
--- a/test/old-elf/Mips/abi-flags-10.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Check that SHT_MIPS_REGINFO section does not get a separate segment
-# if there is a SHT_MIPS_ABIFLAGS section.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s
-
-# CHECK: ProgramHeaders [
-# CHECK-NEXT: ProgramHeader {
-# CHECK-NEXT: Type: PT_PHDR
-# CHECK: }
-# CHECK-NEXT: ProgramHeader {
-# CHECK-NEXT: Type: PT_INTERP
-# CHECK: }
-# CHECK-NEXT: ProgramHeader {
-# CHECK-NEXT: Type: PT_MIPS_ABIFLAGS
-# CHECK: }
-# CHECK-NOT: Type: PT_MIPS_REGINFO
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "F0000000E0000000D0000000C0000000B000000000100000"
-
-- Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 2
- ISAExtension: EXT_NONE
- ASEs: [ MICROMIPS ]
- FpABI: FP_XX
- GPRSize: REG_32
- CPR1Size: REG_32
- CPR2Size: REG_NONE
- Flags1: [ ]
- Flags2: 0x0
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/abi-flags-11.test b/test/old-elf/Mips/abi-flags-11.test
deleted file mode 100644
index e0e8547abbc7..000000000000
--- a/test/old-elf/Mips/abi-flags-11.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check position of PT_MIPS_REGINFO segment.
-# It should go right after the PT_INTERP segment.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s
-
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_INTERP
-# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: PhysicalAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: FileSize: 13
-# CHECK-NEXT: MemSize: 13
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: PF_R
-# CHECK-NEXT: ]
-# CHECK-NEXT: Alignment: 1
-# CHECK-NEXT: }
-# CHECK-NEXT: ProgramHeader {
-# CHECK-NEXT: Type: PT_MIPS_REGINFO
-# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: PhysicalAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: FileSize: 24
-# CHECK-NEXT: MemSize: 24
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: PF_R
-# CHECK-NEXT: ]
-# CHECK-NEXT: Alignment: 4
-# CHECK-NEXT: }
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Size: 4
- AddressAlign: 16
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "F0000000E0000000D0000000C0000000B000000000100000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/base-address-64.test b/test/old-elf/Mips/base-address-64.test
deleted file mode 100644
index 6b553d227820..000000000000
--- a/test/old-elf/Mips/base-address-64.test
+++ /dev/null
@@ -1,80 +0,0 @@
-# Check executable base address configuration. Base address should be
-# equal to 0x400000 and the MIPS_BASE_ADDRESS dynamic tag's value should
-# be the same.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el --noinhibit-exec -o %t.exe %t.o
-# RUN: llvm-readobj -dynamic-table -program-headers %t.exe | FileCheck %s
-
-# CHECK: DynamicSection [ (15 entries)
-# CHECK: Tag Type Name/Value
-# CHECK-NEXT: 0x0000000000000004 HASH 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x0000000000000005 STRTAB 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x0000000000000006 SYMTAB 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x000000000000000A STRSZ 1 (bytes)
-# CHECK-NEXT: 0x000000000000000B SYMENT 24 (bytes)
-# CHECK-NEXT: 0x0000000070000001 MIPS_RLD_VERSION 1
-# CHECK-NEXT: 0x0000000070000016 MIPS_RLD_MAP 0x120002000
-# CHECK-NEXT: 0x0000000070000035 MIPS_RLD_MAP_REL 0x1DB8
-# CHECK-NEXT: 0x0000000070000005 MIPS_FLAGS NOTPOT
-# CHECK-NEXT: 0x0000000070000006 MIPS_BASE_ADDRESS 0x120000000
-# CHECK-NEXT: 0x000000007000000A MIPS_LOCAL_GOTNO 2
-# CHECK-NEXT: 0x0000000070000011 MIPS_SYMTABNO 1
-# CHECK-NEXT: 0x0000000070000013 MIPS_GOTSYM 0x1
-# CHECK-NEXT: 0x0000000000000003 PLTGOT 0x120001000
-# CHECK-NEXT: 0x0000000000000000 NULL 0x0
-# CHECK-NEXT: ]
-
-# CHECK: ProgramHeaders [
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_PHDR (0x6)
-# CHECK: Offset: 0x40
-# CHECK: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK: }
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_INTERP (0x3)
-# CHECK: Offset: 0x190
-# CHECK: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK: }
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_LOAD (0x1)
-# CHECK-NEXT: Offset: 0x0
-# CHECK-NEXT: VirtualAddress: 0x120000000
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ARCH_64R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x10
- Size: 0x00
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x10
- Size: 0x00
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: main
- Section: .text
diff --git a/test/old-elf/Mips/base-address.test b/test/old-elf/Mips/base-address.test
deleted file mode 100644
index 67c04326cc15..000000000000
--- a/test/old-elf/Mips/base-address.test
+++ /dev/null
@@ -1,95 +0,0 @@
-# Check executable base address configuration. Base address should be
-# equal to 0x400000 and the MIPS_BASE_ADDRESS dynamic tag's value should
-# be the same.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel --noinhibit-exec -o %t.exe %t.o
-# RUN: llvm-readobj -dynamic-table -program-headers %t.exe | FileCheck %s
-
-# CHECK: DynamicSection [ (15 entries)
-# CHECK: Tag Type Name/Value
-# CHECK-NEXT: 0x00000004 HASH 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000005 STRTAB 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000006 SYMTAB 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x0000000A STRSZ 1 (bytes)
-# CHECK-NEXT: 0x0000000B SYMENT 16 (bytes)
-# CHECK-NEXT: 0x70000001 MIPS_RLD_VERSION 1
-# CHECK-NEXT: 0x70000016 MIPS_RLD_MAP 0x402000
-# CHECK-NEXT: 0x70000035 MIPS_RLD_MAP_REL 0x1E9C
-# CHECK-NEXT: 0x70000005 MIPS_FLAGS NOTPOT
-# CHECK-NEXT: 0x70000006 MIPS_BASE_ADDRESS 0x400000
-# CHECK-NEXT: 0x7000000A MIPS_LOCAL_GOTNO 2
-# CHECK-NEXT: 0x70000011 MIPS_SYMTABNO 1
-# CHECK-NEXT: 0x70000013 MIPS_GOTSYM 0x1
-# CHECK-NEXT: 0x00000003 PLTGOT 0x401000
-# CHECK-NEXT: 0x00000000 NULL 0x0
-# CHECK-NEXT: ]
-
-# CHECK: ProgramHeaders [
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_PHDR (0x6)
-# CHECK: Offset: 0x34
-# CHECK: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK: }
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_INTERP (0x3)
-# CHECK: Offset: 0xF4
-# CHECK: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK: }
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_LOAD (0x1)
-# CHECK: Offset: 0x0
-# CHECK: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK: }
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_LOAD (0x1)
-# CHECK: Offset: 0x1000
-# CHECK: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK: }
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_LOAD (0x1)
-# CHECK: Offset: 0x2000
-# CHECK: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK: }
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_DYNAMIC (0x2)
-# CHECK: Offset: 0x12C
-# CHECK: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK: }
-# CHECK: ]
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x00
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x00
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: main
- Section: .text
diff --git a/test/old-elf/Mips/ctors-order.test b/test/old-elf/Mips/ctors-order.test
deleted file mode 100644
index b33ed43292e7..000000000000
--- a/test/old-elf/Mips/ctors-order.test
+++ /dev/null
@@ -1,164 +0,0 @@
-# Check ordering of .ctors.* sections.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-crtbeginS.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-crtendS.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-obj.o
-# RUN: lld -flavor old-gnu -target mipsel -shared --output-filetype=yaml \
-# RUN: %t-crtbeginS.o %t-obj.o %t-crtendS.o | FileCheck %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so \
-# RUN: %t-crtbeginS.o %t-obj.o %t-crtendS.o
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=RAW %s
-
-# CHECK: defined-atoms:
-# CHECK-NEXT: - type: data
-# CHECK-NEXT: alignment: 4
-# CHECK-NEXT: section-choice: custom-required
-# CHECK-NEXT: section-name: .ctors
-# CHECK-NEXT: references:
-# CHECK-NEXT: - kind: layout-after
-# CHECK-NEXT: offset: 0
-# CHECK-NEXT: target: __CTOR_LIST__
-# CHECK-NEXT: - name: __CTOR_LIST__
-# CHECK-NEXT: type: data
-# CHECK-NEXT: content: [ FF, FF, FF, FF ]
-# CHECK-NEXT: alignment: 4
-# CHECK-NEXT: section-choice: custom-required
-# CHECK-NEXT: section-name: .ctors
-# CHECK-NEXT: - type: data
-# CHECK-NEXT: content: [ 11, 11, 11, 11 ]
-# CHECK-NEXT: alignment: 4
-# CHECK-NEXT: section-choice: custom-required
-# CHECK-NEXT: section-name: .ctors.1
-# CHECK-NEXT: - type: data
-# CHECK-NEXT: content: [ 22, 22, 22, 22 ]
-# CHECK-NEXT: alignment: 4
-# CHECK-NEXT: section-choice: custom-required
-# CHECK-NEXT: section-name: .ctors.2
-# CHECK-NEXT: - ref-name: L004
-# CHECK-NEXT: type: data
-# CHECK-NEXT: alignment: 4
-# CHECK-NEXT: section-choice: custom-required
-# CHECK-NEXT: section-name: .ctors
-# CHECK-NEXT: references:
-# CHECK-NEXT: - kind: layout-after
-# CHECK-NEXT: offset: 0
-# CHECK-NEXT: target: __CTOR_END__
-# CHECK-NEXT: - name: __CTOR_END__
-# CHECK-NEXT: type: data
-# CHECK-NEXT: content: [ 00, 00, 00, 00 ]
-# CHECK-NEXT: alignment: 4
-# CHECK-NEXT: section-choice: custom-required
-# CHECK-NEXT: section-name: .ctors
-
-# RAW: Contents of section .ctors:
-# RAW-NEXT: 1000 ffffffff 11111111 22222222 00000000
-
-# crtbeginS.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .ctors
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Content: 'FFFFFFFF'
-
-Symbols:
- Local:
- - Name: .ctors
- Type: STT_SECTION
- Section: .ctors
- - Name: __CTOR_LIST__
- Type: STT_OBJECT
- Section: .ctors
-
-# crtendS.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x0F
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: .ctors
- Type: R_MIPS_GOT16
- - Offset: 0x04
- Symbol: .ctors
- Type: R_MIPS_LO16
- - Offset: 0x08
- Symbol: .ctors
- Type: R_MIPS_GOT16
- - Offset: 0x0C
- Symbol: .ctors
- Type: R_MIPS_LO16
- - Name: .ctors
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .ctors
- Type: STT_SECTION
- Section: .ctors
- - Name: __CTOR_END__
- Type: STT_OBJECT
- Section: .ctors
- - Name: __do_global_ctors_aux
- Type: STT_FUNC
- Section: .text
-
-# obj.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .ctors.2
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Content: '22222222'
- - Name: .ctors.1
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Content: '11111111'
-
-Symbols:
- Local:
- - Name: .ctors.2
- Type: STT_SECTION
- Section: .ctors.2
- - Name: .ctors.1
- Type: STT_SECTION
- Section: .ctors.1
-...
diff --git a/test/old-elf/Mips/driver-hash-style.test b/test/old-elf/Mips/driver-hash-style.test
deleted file mode 100644
index 0ab636c427c9..000000000000
--- a/test/old-elf/Mips/driver-hash-style.test
+++ /dev/null
@@ -1,15 +0,0 @@
-# REQUIRES: mips
-
-# Check that the driver rejects all --hash-style arguments except 'sysv'
-# because it is the only style supported by MIPS ABI.
-
-# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
-# RUN: not lld -flavor old-gnu -target mips --hash-style=both %t.o -o %t.exe 2>&1 \
-# RUN: | FileCheck %s
-# RUN: not lld -flavor old-gnu -target mips --hash-style=gnu %t.o -o %t.exe 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: error: .gnu.hash is incompatible with the MIPS ABI
-
- .globl __start;
-__start:
diff --git a/test/old-elf/Mips/dt-textrel-64.test b/test/old-elf/Mips/dt-textrel-64.test
deleted file mode 100644
index 152e82372799..000000000000
--- a/test/old-elf/Mips/dt-textrel-64.test
+++ /dev/null
@@ -1,74 +0,0 @@
-# Check that if a dynamic relocation R_MIPS_64 modify a read-only section,
-# .dynamic section contains the DT_TEXTREL tag.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck %s
-
-# CHECK: 0x{{[0-9A-F]+}} TEXTREL
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x08
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x4
- Size: 0x8
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_64
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x8
- - Name: T1
-...
diff --git a/test/old-elf/Mips/dt-textrel.test b/test/old-elf/Mips/dt-textrel.test
deleted file mode 100644
index af86f4926273..000000000000
--- a/test/old-elf/Mips/dt-textrel.test
+++ /dev/null
@@ -1,74 +0,0 @@
-# Check that if a dynamic relocation modify a read-only section,
-# .dynamic section contains the DT_TEXTREL tag.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck %s
-
-# CHECK: 0x{{[0-9A-F]+}} TEXTREL
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x04
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x04
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: '00000000'
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_32
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- - Name: T1
-...
diff --git a/test/old-elf/Mips/dynamic-linking.test b/test/old-elf/Mips/dynamic-linking.test
deleted file mode 100644
index aeab7645ed51..000000000000
--- a/test/old-elf/Mips/dynamic-linking.test
+++ /dev/null
@@ -1,22 +0,0 @@
-# REQUIRES: mips
-
-# Check _DYNAMIC_LINKING symbol definition.
-
-# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
-# RUN: lld -flavor old-gnu -target mips %t.o -o %t.exe
-# RUN: llvm-nm %t.exe | FileCheck -check-prefix=EXE-DYN %s
-
-# EXE-DYN: 00000001 A _DYNAMIC_LINKING
-
-# RUN: lld -flavor old-gnu -target mips -static %t.o -o %t.exe
-# RUN: llvm-nm -just-symbol-name %t.exe | FileCheck -check-prefix=EXE-STATIC %s
-
-# EXE-STATIC-NOT: _DYNAMIC_LINKING
-
-# RUN: lld -flavor old-gnu -target mips -shared %t.o -o %t.so
-# RUN: llvm-nm -just-symbol-name %t.so | FileCheck -check-prefix=DYNLIB %s
-
-# DYNLIB-NOT: _DYNAMIC_LINKING
-
- .globl __start;
-__start:
diff --git a/test/old-elf/Mips/dynamic-sym.test b/test/old-elf/Mips/dynamic-sym.test
deleted file mode 100644
index 43a69d82c3a3..000000000000
--- a/test/old-elf/Mips/dynamic-sym.test
+++ /dev/null
@@ -1,41 +0,0 @@
-# Check _DYNAMIC symbol's value
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -e T0 -o %t.so %t.o
-# RUN: llvm-objdump -h -t %t.so | FileCheck -check-prefix=SHARED %s
-
-# SHARED: Sections:
-# SHARED: Idx Name Size Address Type
-# SHARED: 5 .dynamic 00000068 00000000[[ADDR:[0-9a-f]+]]
-
-# SHARED: SYMBOL TABLE:
-# SHARED: [[ADDR]] g .dynamic 00000000 _DYNAMIC
-
-# RUN: lld -flavor old-gnu -target mipsel -e main -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -h -t %t.exe | FileCheck -check-prefix=EXE %s
-
-# EXE: Sections:
-# EXE: Idx Name Size Address Type
-# EXE: 6 .dynamic 00000078 00000000[[ADDR:[0-9a-f]+]]
-
-# EXE: SYMBOL TABLE:
-# EXE: [[ADDR]] g .dynamic 00000000 _DYNAMIC
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
- AddressAlign: 0x10
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
diff --git a/test/old-elf/Mips/dynlib-dynamic.test b/test/old-elf/Mips/dynlib-dynamic.test
deleted file mode 100644
index fca036a52624..000000000000
--- a/test/old-elf/Mips/dynlib-dynamic.test
+++ /dev/null
@@ -1,110 +0,0 @@
-# Check MIPS specific tags in the dynamic table.
-
-# Build shared library
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec -o %t.so %t.o
-# RUN: llvm-readobj -dynamic-table %t.so | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK: Arch: mipsel
-# CHECK: AddressSize: 32bit
-# CHECK: LoadName:
-# CHECK: DynamicSection [ (13 entries)
-# CHECK: Tag Type Name/Value
-# CHECK-NEXT: 0x00000004 HASH 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000005 STRTAB 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000006 SYMTAB 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x0000000A STRSZ 17 (bytes)
-# CHECK-NEXT: 0x0000000B SYMENT 16 (bytes)
-# CHECK-NEXT: 0x70000001 MIPS_RLD_VERSION 1
-# CHECK-NEXT: 0x70000005 MIPS_FLAGS NOTPOT
-# CHECK-NEXT: 0x70000006 MIPS_BASE_ADDRESS 0x0
-# CHECK-NEXT: 0x7000000A MIPS_LOCAL_GOTNO 4
-# CHECK-NEXT: 0x70000011 MIPS_SYMTABNO 4
-# CHECK-NEXT: 0x70000013 MIPS_GOTSYM 0x2
-# CHECK-NEXT: 0x00000003 PLTGOT 0x1000
-# CHECK-NEXT: 0x00000000 NULL 0x0
-# CHECK-NEXT: ]
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x18
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: '$.str1'
- Type: R_MIPS_GOT16
- - Offset: 0x04
- Symbol: '$.str1'
- Type: R_MIPS_LO16
- - Offset: 0x08
- Symbol: '$.str2'
- Type: R_MIPS_GOT16
- - Offset: 0x0C
- Symbol: '$.str2'
- Type: R_MIPS_LO16
- - Offset: 0x10
- Symbol: glob2
- Type: R_MIPS_CALL16
- - Offset: 0x14
- Symbol: ext1
- Type: R_MIPS_CALL16
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x00
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x00
- - Name: .rodata.str1
- Type: SHT_PROGBITS
- AddressAlign: 0x01
- Size: 0x05
- - Name: .rodata.str2
- Type: SHT_PROGBITS
- AddressAlign: 0x01
- Size: 0x05
-
-Symbols:
- Local:
- - Name: '$.str1'
- Section: .rodata.str1
- - Name: '$.str2'
- Section: .rodata.str2
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .rodata.str1
- Type: STT_SECTION
- Section: .rodata.str1
- - Name: .rodata.str2
- Type: STT_SECTION
- Section: .rodata.str2
- Global:
- - Name: glob
- Section: .text
- - Name: ext1
- - Name: glob2
diff --git a/test/old-elf/Mips/dynlib-dynsym-micro.test b/test/old-elf/Mips/dynlib-dynsym-micro.test
deleted file mode 100644
index 6757847fac73..000000000000
--- a/test/old-elf/Mips/dynlib-dynsym-micro.test
+++ /dev/null
@@ -1,208 +0,0 @@
-# 1. Check sorting of .dynsym content accordingly to .got section
-# in case of using microMIPS relocations.
-# 2. Check that microMIPS records in a dynamic symbol table have:
-# - cleared the STO_MIPS_MICROMIPS flag
-# - adjusted adress
-
-# Build shared library
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec -o %t-so %t.o
-# RUN: llvm-readobj -dyn-symbols %t-so | FileCheck -check-prefix=CHECK-DYN %s
-
-# Build shared library (yaml format)
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec \
-# RUN: --output-filetype=yaml -o %t-yaml %t.o
-# RUN: FileCheck -check-prefix=CHECK-GOT %s < %t-yaml
-
-# CHECK-DYN: Format: ELF32-mips
-# CHECK-DYN: Arch: mipsel
-# CHECK-DYN: AddressSize: 32bit
-# CHECK-DYN: LoadName:
-# CHECK-DYN: DynamicSymbols [
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: @ (0)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Local (0x0)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: bar@ (5)
-# CHECK-DYN: Value: 0x139
-# CHECK-DYN: Size: 4
-# CHECK-DYN: Binding: Global (0x1)
-# CHECK-DYN: Type: Function (0x2)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: .text (0x4)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: foo@ (1)
-# CHECK-DYN: Value: 0x121
-# CHECK-DYN: Size: 24
-# CHECK-DYN: Binding: Global (0x1)
-# CHECK-DYN: Type: Function (0x2)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: .text (0x4)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: ext1@ (9)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Global (0x1)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: ext2@ (14)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Global (0x1)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: ]
-
-# CHECK-GOT: - type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: - type: got
-# CHECK-GOT: content: [ 00, 00, 00, 80 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: - ref-name: L000
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_32_HI16
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: L007
-# CHECK-GOT: - ref-name: L002
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_32_HI16
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: L008
-# CHECK-GOT: - ref-name: L004
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: foo
-# CHECK-GOT: - ref-name: L005
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: ext1
-# CHECK-GOT: - ref-name: L006
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: ext2
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x1C
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: .rodata.str1
- Type: R_MICROMIPS_GOT16
- - Offset: 0x04
- Symbol: .rodata.str1
- Type: R_MICROMIPS_LO16
- - Offset: 0x08
- Symbol: .rodata.str2
- Type: R_MICROMIPS_GOT16
- - Offset: 0x0C
- Symbol: .rodata.str2
- Type: R_MICROMIPS_LO16
- - Offset: 0x10
- Symbol: foo
- Type: R_MICROMIPS_CALL16
- - Offset: 0x14
- Symbol: ext1
- Type: R_MICROMIPS_CALL16
- - Offset: 0x18
- Symbol: ext2
- Type: R_MICROMIPS_CALL16
- - Name: .rodata.str1
- Type: SHT_PROGBITS
- AddressAlign: 0x01
- Size: 0x05
- - Name: .rodata.str2
- Type: SHT_PROGBITS
- AddressAlign: 0x01
- Size: 0x05
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .rodata.str1
- Type: STT_SECTION
- Section: .rodata.str1
- - Name: .rodata.str2
- Type: STT_SECTION
- Section: .rodata.str2
- Global:
- - Name: bar
- Section: .text
- Value: 0x18
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: foo
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: ext1
- - Name: ext2
-...
diff --git a/test/old-elf/Mips/dynlib-dynsym.test b/test/old-elf/Mips/dynlib-dynsym.test
deleted file mode 100644
index 23b0cd6a90c2..000000000000
--- a/test/old-elf/Mips/dynlib-dynsym.test
+++ /dev/null
@@ -1,202 +0,0 @@
-# Check sorting of .dynsym content accordingly to .got section.
-
-# Build shared library
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec -o %t-so %t.o
-# RUN: llvm-readobj -dyn-symbols %t-so | FileCheck -check-prefix=CHECK-DYN %s
-
-# Build shared library (yaml format)
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec \
-# RUN: --output-filetype=yaml -o %t-yaml %t.o
-# RUN: FileCheck -check-prefix=CHECK-GOT %s < %t-yaml
-
-# CHECK-DYN: Format: ELF32-mips
-# CHECK-DYN: Arch: mipsel
-# CHECK-DYN: AddressSize: 32bit
-# CHECK-DYN: LoadName:
-# CHECK-DYN: DynamicSymbols [
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: @ (0)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Local (0x0)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: bar@ (5)
-# CHECK-DYN: Value: 0x138
-# CHECK-DYN: Size: 4
-# CHECK-DYN: Binding: Global (0x1)
-# CHECK-DYN: Type: Function (0x2)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: .text (0x4)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: foo@ (1)
-# CHECK-DYN: Value: 0x120
-# CHECK-DYN: Size: 24
-# CHECK-DYN: Binding: Global (0x1)
-# CHECK-DYN: Type: Function (0x2)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: .text (0x4)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: ext1@ (9)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Global (0x1)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: ext2@ (14)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Global (0x1)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: ]
-
-# CHECK-GOT: - type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: - type: got
-# CHECK-GOT: content: [ 00, 00, 00, 80 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: - ref-name: L000
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_32_HI16
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: L007
-# CHECK-GOT: - ref-name: L002
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_32_HI16
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: L008
-# CHECK-GOT: - ref-name: L004
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: foo
-# CHECK-GOT: - ref-name: L005
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: ext1
-# CHECK-GOT: - ref-name: L006
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: ext2
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x1C
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: .rodata.str1
- Type: R_MIPS_GOT16
- - Offset: 0x04
- Symbol: .rodata.str1
- Type: R_MIPS_LO16
- - Offset: 0x08
- Symbol: .rodata.str2
- Type: R_MIPS_GOT16
- - Offset: 0x0C
- Symbol: .rodata.str2
- Type: R_MIPS_LO16
- - Offset: 0x10
- Symbol: foo
- Type: R_MIPS_CALL16
- - Offset: 0x14
- Symbol: ext1
- Type: R_MIPS_CALL16
- - Offset: 0x18
- Symbol: ext2
- Type: R_MIPS_CALL16
- - Name: .rodata.str1
- Type: SHT_PROGBITS
- AddressAlign: 0x01
- Size: 0x05
- - Name: .rodata.str2
- Type: SHT_PROGBITS
- AddressAlign: 0x01
- Size: 0x05
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .rodata.str1
- Type: STT_SECTION
- Section: .rodata.str1
- - Name: .rodata.str2
- Type: STT_SECTION
- Section: .rodata.str2
- Global:
- - Name: bar
- Section: .text
- Value: 0x18
- - Name: foo
- Section: .text
- - Name: ext1
- - Name: ext2
-...
diff --git a/test/old-elf/Mips/dynlib-fileheader-64.test b/test/old-elf/Mips/dynlib-fileheader-64.test
deleted file mode 100644
index f3b45d4d738e..000000000000
--- a/test/old-elf/Mips/dynlib-fileheader-64.test
+++ /dev/null
@@ -1,72 +0,0 @@
-# Check ELF Header for 64-bit shared library.
-
-# Build shared library
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Format: ELF64-mips
-# CHECK: Arch: mips64el
-# CHECK: AddressSize: 64bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 64-bit (0x2)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 0
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: SharedObject (0x3)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x80000006)
-# CHECK: EF_MIPS_ARCH_64R2 (0x80000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_PIC (0x2)
-# CHECK: ]
-# CHECK: HeaderSize: 64
-# CHECK: ProgramHeaderEntrySize: 56
-# CHECK: ProgramHeaderCount: {{[0-9]+}}
-# CHECK: SectionHeaderEntrySize: 64
-# CHECK: SectionHeaderCount: {{[0-9]+}}
-# CHECK: StringTableSectionIndex: {{[0-9]+}}
-# CHECK: }
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- Global:
- - Name: data
- Type: STT_OBJECT
- Section: .data
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/dynlib-fileheader-micro-64.test b/test/old-elf/Mips/dynlib-fileheader-micro-64.test
deleted file mode 100644
index 531cee134caf..000000000000
--- a/test/old-elf/Mips/dynlib-fileheader-micro-64.test
+++ /dev/null
@@ -1,75 +0,0 @@
-# Check ELF Header for shared library in case of microMIPS symbols.
-
-# Build shared library
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Format: ELF64-mips
-# CHECK-NEXT: Arch: mips64el
-# CHECK-NEXT: AddressSize: 64bit
-# CHECK-NEXT: LoadName:
-# CHECK-NEXT: ElfHeader {
-# CHECK-NEXT: Ident {
-# CHECK-NEXT: Magic: (7F 45 4C 46)
-# CHECK-NEXT: Class: 64-bit (0x2)
-# CHECK-NEXT: DataEncoding: LittleEndian (0x1)
-# CHECK-NEXT: FileVersion: 1
-# CHECK-NEXT: OS/ABI: SystemV (0x0)
-# CHECK-NEXT: ABIVersion: 0
-# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
-# CHECK-NEXT: }
-# CHECK-NEXT: Type: SharedObject (0x3)
-# CHECK-NEXT: Machine: EM_MIPS (0x8)
-# CHECK-NEXT: Version: 1
-# CHECK-NEXT: Entry: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: Flags [ (0x82000007)
-# CHECK-NEXT: EF_MIPS_ARCH_64R2 (0x80000000)
-# CHECK-NEXT: EF_MIPS_CPIC (0x4)
-# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
-# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
-# CHECK-NEXT: EF_MIPS_PIC (0x2)
-# CHECK-NEXT: ]
-# CHECK-NEXT: HeaderSize: 64
-# CHECK-NEXT: ProgramHeaderEntrySize: 56
-# CHECK-NEXT: ProgramHeaderCount: {{[0-9]+}}
-# CHECK-NEXT: SectionHeaderEntrySize: 64
-# CHECK-NEXT: SectionHeaderCount: {{[0-9]+}}
-# CHECK-NEXT: StringTableSectionIndex: {{[0-9]+}}
-# CHECK-NEXT:}
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_MICROMIPS, EF_MIPS_ARCH_64R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- Other: [ STO_MIPS_MICROMIPS ]
diff --git a/test/old-elf/Mips/dynlib-fileheader-micro.test b/test/old-elf/Mips/dynlib-fileheader-micro.test
deleted file mode 100644
index dcd38f1036d0..000000000000
--- a/test/old-elf/Mips/dynlib-fileheader-micro.test
+++ /dev/null
@@ -1,79 +0,0 @@
-# Check ELF Header for shared library in case of microMIPS symbols.
-
-# Build shared library
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK-NEXT: Arch: mipsel
-# CHECK-NEXT: AddressSize: 32bit
-# CHECK-NEXT: LoadName:
-# CHECK-NEXT: ElfHeader {
-# CHECK-NEXT: Ident {
-# CHECK-NEXT: Magic: (7F 45 4C 46)
-# CHECK-NEXT: Class: 32-bit (0x1)
-# CHECK-NEXT: DataEncoding: LittleEndian (0x1)
-# CHECK-NEXT: FileVersion: 1
-# CHECK-NEXT: OS/ABI: SystemV (0x0)
-# CHECK-NEXT: ABIVersion: 0
-# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
-# CHECK-NEXT: }
-# CHECK-NEXT: Type: SharedObject (0x3)
-# CHECK-NEXT: Machine: EM_MIPS (0x8)
-# CHECK-NEXT: Version: 1
-# CHECK-NEXT: Entry: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: Flags [ (0x72001007)
-# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# CHECK-NEXT: EF_MIPS_ARCH_32R2 (0x70000000)
-# CHECK-NEXT: EF_MIPS_CPIC (0x4)
-# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
-# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
-# CHECK-NEXT: EF_MIPS_PIC (0x2)
-# CHECK-NEXT: ]
-# CHECK-NEXT: HeaderSize: 52
-# CHECK-NEXT: ProgramHeaderEntrySize: 32
-# CHECK-NEXT: ProgramHeaderCount: {{[0-9]+}}
-# CHECK-NEXT: SectionHeaderEntrySize: 40
-# CHECK-NEXT: SectionHeaderCount: {{[0-9]+}}
-# CHECK-NEXT: StringTableSectionIndex: {{[0-9]+}}
-# CHECK-NEXT:}
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x00
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x00
- - Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x08
- ISA: MIPS32
- ISARevision: 2
- ASEs: [ MICROMIPS ]
-
-Symbols:
- Global:
- - Name: glob
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
diff --git a/test/old-elf/Mips/dynlib-fileheader.test b/test/old-elf/Mips/dynlib-fileheader.test
deleted file mode 100644
index a3b4a19a90f1..000000000000
--- a/test/old-elf/Mips/dynlib-fileheader.test
+++ /dev/null
@@ -1,76 +0,0 @@
-# Check ELF Header for shared library.
-
-# Build shared library
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK: Arch: mipsel
-# CHECK: AddressSize: 32bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 32-bit (0x1)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 0
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: SharedObject (0x3)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x70001007)
-# CHECK: EF_MIPS_ABI_O32 (0x1000)
-# CHECK: EF_MIPS_ARCH_32R2 (0x70000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: EF_MIPS_PIC (0x2)
-# CHECK: ]
-# CHECK: HeaderSize: 52
-# CHECK: ProgramHeaderEntrySize: 32
-# CHECK: ProgramHeaderCount: {{[0-9]+}}
-# CHECK: SectionHeaderEntrySize: 40
-# CHECK: SectionHeaderCount: {{[0-9]+}}
-# CHECK: StringTableSectionIndex: {{[0-9]+}}
-# CHECK:}
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x00
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x00
- - Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x08
- ISA: MIPS32
- ISARevision: 2
-
-Symbols:
- Global:
- - Name: glob
- Section: .text
diff --git a/test/old-elf/Mips/dynsym-table-1.test b/test/old-elf/Mips/dynsym-table-1.test
deleted file mode 100644
index 8821ae358254..000000000000
--- a/test/old-elf/Mips/dynsym-table-1.test
+++ /dev/null
@@ -1,127 +0,0 @@
-# Check that LLD does not populate an executable file dynamic symbol table
-# by unnecessary symbols.
-# 1. bar.so defines T2
-# 2. foo.so defines T1 and references T2
-# 3. main.o reference T1
-# 4. a.out dynamic table should contain T1 entry only
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-bar.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-foo.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-main.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t-bar.so %t-bar.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t-foo.so %t-foo.o %t-bar.so
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe --as-needed \
-# RUN: %t-main.o %t-foo.so %t-bar.so
-# RUN: llvm-readobj -dt -dynamic-table %t.exe | FileCheck %s
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T1@ ({{.*}})
-# CHECK-NEXT: Value: {{.*}}
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 8
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: 0x00000003 PLTGOT 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000001 NEEDED SharedLibrary (dynsym-table-1.test.tmp-foo.so)
-# CHECK-NEXT: 0x00000000 NULL 0x0
-
-# bar.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
-Symbols:
- Global:
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Size: 0x08
-
-# foo.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x08
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T2
- Type: R_MIPS_CALL16
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- - Name: T2
-
-# main.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x08
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_32
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- - Name: T1
-...
diff --git a/test/old-elf/Mips/dynsym-table-2.test b/test/old-elf/Mips/dynsym-table-2.test
deleted file mode 100644
index ad85bfe84e43..000000000000
--- a/test/old-elf/Mips/dynsym-table-2.test
+++ /dev/null
@@ -1,105 +0,0 @@
-# Check that LLD does not populate a shared library dynamic symbol table
-# by unnecessary symbols.
-# 1. bar.so defines T2 and T3
-# 2. foo.so defines T1 and references T2
-# 4. foo.so dynamic table should contain T1 and T2 entries only
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-bar.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-foo.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t-bar.so %t-bar.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t-foo.so %t-foo.o %t-bar.so
-# RUN: llvm-readobj -dt -dynamic-table %t-foo.so | FileCheck %s
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T1@ ({{.*}})
-# CHECK-NEXT: Value: {{.*}}
-# CHECK-NEXT: Size: 8
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .text (0x4)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T2@ ({{.*}})
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: 0x00000003 PLTGOT 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000001 NEEDED SharedLibrary (dynsym-table-2.test.tmp-bar.so)
-# CHECK-NEXT: 0x00000000 NULL 0x0
-
-# bar.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
-Symbols:
- Global:
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- - Name: T3
- Type: STT_FUNC
- Section: .text
- Value: 0x04
- Size: 0x04
-
-# foo.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x08
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T2
- Type: R_MIPS_CALL16
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- - Name: T2
-...
diff --git a/test/old-elf/Mips/e-flags-merge-1-64.test b/test/old-elf/Mips/e-flags-merge-1-64.test
deleted file mode 100644
index 3e52afd223cd..000000000000
--- a/test/old-elf/Mips/e-flags-merge-1-64.test
+++ /dev/null
@@ -1,30 +0,0 @@
-# Check that the linker shows an error when object
-# file has unsupported ASE flags.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-mips16.o
-# RUN: not lld -flavor old-gnu -target mips64el -e T -o %t.exe %t-mips16.o 2>&1 | \
-# RUN: FileCheck -check-prefix=MIPS16 %s
-
-# MIPS16: Unsupported extension: MIPS16
-
-# mips16.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64, EF_MIPS_ARCH_ASE_M16]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Global:
- - Name: T
- Section: .text
-...
diff --git a/test/old-elf/Mips/e-flags-merge-1.test b/test/old-elf/Mips/e-flags-merge-1.test
deleted file mode 100644
index bc100534112d..000000000000
--- a/test/old-elf/Mips/e-flags-merge-1.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# Check that the linker shows an error when object file has missed
-# or unsupported ABI and ARCH flags or unsupported ASE flags.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-no-abi.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T -o %t.exe %t-no-abi.o 2>&1 | \
-# RUN: FileCheck -check-prefix=INVALID-ABI %s
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-mips16.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T -o %t.exe %t-mips16.o 2>&1 | \
-# RUN: FileCheck -check-prefix=MIPS16 %s
-
-# INVALID-ABI: Unsupported ABI
-# MIPS16: Unsupported extension: MIPS16
-
-# no-abi.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: []
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T
- Section: .text
-
-# mips16.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_M16]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T
- Section: .text
-...
diff --git a/test/old-elf/Mips/e-flags-merge-10.test b/test/old-elf/Mips/e-flags-merge-10.test
deleted file mode 100644
index 5dacaa0e069d..000000000000
--- a/test/old-elf/Mips/e-flags-merge-10.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# Check that LLD shows an error and does not link files with mips32r2
-# and mips32r6 instructions sets.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-32r2.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-32r6.o
-
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so \
-# RUN: %t-32r2.o %t-32r6.o 2>&1 | FileCheck %s
-
-# CHECK: Linking modules with incompatible ISA
-
-# 32r2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# 32r6.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/e-flags-merge-11.test b/test/old-elf/Mips/e-flags-merge-11.test
deleted file mode 100644
index e61eb0d6d65a..000000000000
--- a/test/old-elf/Mips/e-flags-merge-11.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# Check that LLD shows an error and does not link files with mips64r2
-# and mips64r6 instructions sets.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-64r2.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-64r6.o
-
-# RUN: not lld -flavor old-gnu -target mips64el -shared -o %t.so \
-# RUN: %t-64r2.o %t-64r6.o 2>&1 | FileCheck %s
-
-# CHECK: Linking modules with incompatible ISA
-
-# 64r2.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# 64r6.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64R6]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/e-flags-merge-12.test b/test/old-elf/Mips/e-flags-merge-12.test
deleted file mode 100644
index 0a0c43fc996a..000000000000
--- a/test/old-elf/Mips/e-flags-merge-12.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# Check that LLD shows an error and does not link files with O32 and N32 ABIs.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o32.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-n32.o
-
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so \
-# RUN: %t-o32.o %t-n32.o 2>&1 | FileCheck %s
-
-# CHECK: Linking modules with incompatible ABI
-
-# o32.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_32BITMODE, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# n32.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI2,
- EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/e-flags-merge-2-64.test b/test/old-elf/Mips/e-flags-merge-2-64.test
deleted file mode 100644
index 4e024d2a465b..000000000000
--- a/test/old-elf/Mips/e-flags-merge-2-64.test
+++ /dev/null
@@ -1,33 +0,0 @@
-# Check that the linker copies ELF header flags from the single input object
-# file to the generated executable
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -e T -o %t.exe %t.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Flags [ (0x62000001)
-# CHECK-NEXT: EF_MIPS_ARCH_64 (0x60000000)
-# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
-# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
-# CHECK-NEXT: ]
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ARCH_64, EF_MIPS_NOREORDER, EF_MIPS_MICROMIPS ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Global:
- - Name: T
- Section: .text
-...
diff --git a/test/old-elf/Mips/e-flags-merge-2.test b/test/old-elf/Mips/e-flags-merge-2.test
deleted file mode 100644
index 3ca531728728..000000000000
--- a/test/old-elf/Mips/e-flags-merge-2.test
+++ /dev/null
@@ -1,35 +0,0 @@
-# Check that the linker copies ELF header flags from the single input object
-# file to the generated executable
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T -o %t.exe %t.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Flags [ (0x52001001)
-# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# CHECK-NEXT: EF_MIPS_ARCH_32 (0x50000000)
-# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
-# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
-# CHECK-NEXT: ]
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32,
- EF_MIPS_NOREORDER, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T
- Section: .text
-...
diff --git a/test/old-elf/Mips/e-flags-merge-3-64.test b/test/old-elf/Mips/e-flags-merge-3-64.test
deleted file mode 100644
index 45326813e12f..000000000000
--- a/test/old-elf/Mips/e-flags-merge-3-64.test
+++ /dev/null
@@ -1,130 +0,0 @@
-# Check PIC/CPIC flags merging in case of multiple input objects.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-none.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-cpic.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-pic.o
-# RUN: yaml2obj -format=elf -docnum 4 %s > %t-both.o
-
-# RUN: lld -flavor old-gnu -target mips64el -e T1 -o %t-abi1.exe \
-# RUN: %t-none.o %t-pic.o 2>&1 | FileCheck -check-prefix=ABI-CALLS-WARN %s
-# RUN: llvm-readobj -file-headers %t-abi1.exe \
-# RUN: | FileCheck -check-prefix=ABI-CALLS1 %s
-
-# RUN: lld -flavor old-gnu -target mips64el -e T1 -o %t-abi2.exe \
-# RUN: %t-cpic.o %t-none.o 2>&1 | FileCheck -check-prefix=ABI-CALLS-WARN %s
-# RUN: llvm-readobj -file-headers %t-abi2.exe \
-# RUN: | FileCheck -check-prefix=ABI-CALLS2 %s
-
-# RUN: lld -flavor old-gnu -target mips64el -e T2 -o %t-cpic.exe %t-cpic.o %t-pic.o
-# RUN: llvm-readobj -file-headers %t-cpic.exe | FileCheck -check-prefix=CPIC %s
-
-# RUN: lld -flavor old-gnu -target mips64el -e T3 -o %t-both.exe %t-pic.o %t-both.o
-# RUN: llvm-readobj -file-headers %t-both.exe | FileCheck -check-prefix=BOTH %s
-
-# ABI-CALLS-WARN: lld warning: linking abicalls and non-abicalls files
-
-# ABI-CALLS1: Flags [ (0x60000004)
-# ABI-CALLS1-NEXT: EF_MIPS_ARCH_64 (0x60000000)
-# ABI-CALLS1-NEXT: EF_MIPS_CPIC (0x4)
-# ABI-CALLS1-NEXT: ]
-
-# ABI-CALLS2: Flags [ (0x60000004)
-# ABI-CALLS2-NEXT: EF_MIPS_ARCH_64 (0x60000000)
-# ABI-CALLS2-NEXT: EF_MIPS_CPIC (0x4)
-# ABI-CALLS2-NEXT: ]
-
-# CPIC: Flags [ (0x60000004)
-# CPIC-NEXT: EF_MIPS_ARCH_64 (0x60000000)
-# CPIC-NEXT: EF_MIPS_CPIC (0x4)
-# CPIC-NEXT: ]
-
-# BOTH: Flags [ (0x60000006)
-# BOTH-NEXT: EF_MIPS_ARCH_64 (0x60000000)
-# BOTH-NEXT: EF_MIPS_CPIC (0x4)
-# BOTH-NEXT: EF_MIPS_PIC (0x2)
-# BOTH-NEXT: ]
-
-# none.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
-
-# cpic.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64, EF_MIPS_CPIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64, EF_MIPS_PIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Global:
- - Name: T3
- Section: .text
-
-# both.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64, EF_MIPS_CPIC, EF_MIPS_PIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Global:
- - Name: T4
- Section: .text
-...
diff --git a/test/old-elf/Mips/e-flags-merge-3.test b/test/old-elf/Mips/e-flags-merge-3.test
deleted file mode 100644
index 612f0b458631..000000000000
--- a/test/old-elf/Mips/e-flags-merge-3.test
+++ /dev/null
@@ -1,134 +0,0 @@
-# Check PIC/CPIC flags merging in case of multiple input objects.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-none.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-cpic.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-pic.o
-# RUN: yaml2obj -format=elf -docnum 4 %s > %t-both.o
-
-# RUN: lld -flavor old-gnu -target mipsel -e T1 -o %t-abi1.exe \
-# RUN: %t-none.o %t-pic.o 2>&1 | FileCheck -check-prefix=ABI-CALLS-WARN %s
-# RUN: llvm-readobj -file-headers %t-abi1.exe \
-# RUN: | FileCheck -check-prefix=ABI-CALLS1 %s
-
-# RUN: lld -flavor old-gnu -target mipsel -e T1 -o %t-abi2.exe \
-# RUN: %t-cpic.o %t-none.o 2>&1 | FileCheck -check-prefix=ABI-CALLS-WARN %s
-# RUN: llvm-readobj -file-headers %t-abi2.exe \
-# RUN: | FileCheck -check-prefix=ABI-CALLS2 %s
-
-# RUN: lld -flavor old-gnu -target mipsel -e T2 -o %t-cpic.exe %t-cpic.o %t-pic.o
-# RUN: llvm-readobj -file-headers %t-cpic.exe | FileCheck -check-prefix=CPIC %s
-
-# RUN: lld -flavor old-gnu -target mipsel -e T3 -o %t-both.exe %t-pic.o %t-both.o
-# RUN: llvm-readobj -file-headers %t-both.exe | FileCheck -check-prefix=BOTH %s
-
-# ABI-CALLS-WARN: lld warning: linking abicalls and non-abicalls files
-
-# ABI-CALLS1: Flags [ (0x50001004)
-# ABI-CALLS1-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# ABI-CALLS1-NEXT: EF_MIPS_ARCH_32 (0x50000000)
-# ABI-CALLS1-NEXT: EF_MIPS_CPIC (0x4)
-# ABI-CALLS1-NEXT: ]
-
-# ABI-CALLS2: Flags [ (0x50001004)
-# ABI-CALLS2-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# ABI-CALLS2-NEXT: EF_MIPS_ARCH_32 (0x50000000)
-# ABI-CALLS2-NEXT: EF_MIPS_CPIC (0x4)
-# ABI-CALLS2-NEXT: ]
-
-# CPIC: Flags [ (0x50001004)
-# CPIC-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# CPIC-NEXT: EF_MIPS_ARCH_32 (0x50000000)
-# CPIC-NEXT: EF_MIPS_CPIC (0x4)
-# CPIC-NEXT: ]
-
-# BOTH: Flags [ (0x50001006)
-# BOTH-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# BOTH-NEXT: EF_MIPS_ARCH_32 (0x50000000)
-# BOTH-NEXT: EF_MIPS_CPIC (0x4)
-# BOTH-NEXT: EF_MIPS_PIC (0x2)
-# BOTH-NEXT: ]
-
-# none.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
-
-# cpic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_PIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T3
- Section: .text
-
-# both.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_PIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T4
- Section: .text
-...
diff --git a/test/old-elf/Mips/e-flags-merge-4-64.test b/test/old-elf/Mips/e-flags-merge-4-64.test
deleted file mode 100644
index 59a8bf131d95..000000000000
--- a/test/old-elf/Mips/e-flags-merge-4-64.test
+++ /dev/null
@@ -1,64 +0,0 @@
-# Check ELF flags merging.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-none.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-noreorder.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-micro.o
-
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so \
-# RUN: %t-none.o %t-noreorder.o %t-micro.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Flags [ (0x82000001)
-# CHECK-NEXT: EF_MIPS_ARCH_64R2 (0x80000000)
-# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
-# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
-# CHECK-NEXT: ]
-
-# none.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_5]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-# noreorder.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64, EF_MIPS_NOREORDER]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-# micro.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64R2, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-...
diff --git a/test/old-elf/Mips/e-flags-merge-4.test b/test/old-elf/Mips/e-flags-merge-4.test
deleted file mode 100644
index 6a2de375e624..000000000000
--- a/test/old-elf/Mips/e-flags-merge-4.test
+++ /dev/null
@@ -1,65 +0,0 @@
-# Check ELF flags merging.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-none.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-noreorder.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-micro.o
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so \
-# RUN: %t-none.o %t-noreorder.o %t-micro.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Flags [ (0x52001001)
-# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# CHECK-NEXT: EF_MIPS_ARCH_32 (0x50000000)
-# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
-# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
-# CHECK-NEXT: ]
-
-# none.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# noreorder.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_NOREORDER]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# micro.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/e-flags-merge-5-64.test b/test/old-elf/Mips/e-flags-merge-5-64.test
deleted file mode 100644
index f1fdac2c8c05..000000000000
--- a/test/old-elf/Mips/e-flags-merge-5-64.test
+++ /dev/null
@@ -1,42 +0,0 @@
-# Check that LLD does not allow to mix 32 and 64-bit MIPS object files.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-32.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-64.o
-
-# RUN: not lld -flavor old-gnu -target mips64el -shared -o %t.so \
-# RUN: %t-32.o %t-64.o 2>&1 | FileCheck %s
-
-# CHECK: ELF64 expected, but got ELF32
-
-# 32.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# 64.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-...
diff --git a/test/old-elf/Mips/e-flags-merge-5.test b/test/old-elf/Mips/e-flags-merge-5.test
deleted file mode 100644
index 56edc4bfa10f..000000000000
--- a/test/old-elf/Mips/e-flags-merge-5.test
+++ /dev/null
@@ -1,42 +0,0 @@
-# Check that LLD does not allow to mix 32 and 64-bit MIPS object files.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-32.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-64.o
-
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so \
-# RUN: %t-32.o %t-64.o 2>&1 | FileCheck %s
-
-# CHECK: ELF32 expected, but got ELF64
-
-# 32.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# 64.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/e-flags-merge-6-64.test b/test/old-elf/Mips/e-flags-merge-6-64.test
deleted file mode 100644
index 9f83365441af..000000000000
--- a/test/old-elf/Mips/e-flags-merge-6-64.test
+++ /dev/null
@@ -1,79 +0,0 @@
-# Check selecting ELF header ARCH flag.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-m3.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-m5.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-m64.o
-# RUN: yaml2obj -format=elf -docnum 4 %s > %t-m64r2.o
-
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so \
-# RUN: %t-m64.o %t-m5.o %t-m64r2.o %t-m3.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Flags [ (0x80000000)
-# CHECK-NEXT: EF_MIPS_ARCH_64R2 (0x80000000)
-# CHECK-NEXT: ]
-
-# m3.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_3]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-# m5.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_5]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-# m64.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-# m64r2.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-...
diff --git a/test/old-elf/Mips/e-flags-merge-6.test b/test/old-elf/Mips/e-flags-merge-6.test
deleted file mode 100644
index 0d8bcee5ad64..000000000000
--- a/test/old-elf/Mips/e-flags-merge-6.test
+++ /dev/null
@@ -1,80 +0,0 @@
-# Check selecting ELF header ARCH flag.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-m1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-m2.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-m32.o
-# RUN: yaml2obj -format=elf -docnum 4 %s > %t-m32r2.o
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so \
-# RUN: %t-m32.o %t-m2.o %t-m32r2.o %t-m1.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Flags [ (0x70001000)
-# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# CHECK-NEXT: EF_MIPS_ARCH_32R2 (0x70000000)
-# CHECK-NEXT: ]
-
-# m1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_1]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# m2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# m32.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# m32r2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/e-flags-merge-7-64.test b/test/old-elf/Mips/e-flags-merge-7-64.test
deleted file mode 100644
index 0e74ac53684a..000000000000
--- a/test/old-elf/Mips/e-flags-merge-7-64.test
+++ /dev/null
@@ -1,42 +0,0 @@
-# Check that LLD does not allow to mix nan2008 and legacy MIPS object files.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-2008.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-legacy.o
-
-# RUN: not lld -flavor old-gnu -target mips64el -shared -o %t.so \
-# RUN: %t-2008.o %t-legacy.o 2>&1 | FileCheck %s
-
-# CHECK: Linking -mnan=2008 and -mnan=legacy modules
-
-# 2008.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64, EF_MIPS_NAN2008]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-# legacy.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-...
diff --git a/test/old-elf/Mips/e-flags-merge-7.test b/test/old-elf/Mips/e-flags-merge-7.test
deleted file mode 100644
index 08051df506be..000000000000
--- a/test/old-elf/Mips/e-flags-merge-7.test
+++ /dev/null
@@ -1,42 +0,0 @@
-# Check that LLD does not allow to mix nan2008 and legacy MIPS object files.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-2008.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-legacy.o
-
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so \
-# RUN: %t-2008.o %t-legacy.o 2>&1 | FileCheck %s
-
-# CHECK: Linking -mnan=2008 and -mnan=legacy modules
-
-# 2008.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_NAN2008]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# legacy.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/e-flags-merge-8.test b/test/old-elf/Mips/e-flags-merge-8.test
deleted file mode 100644
index 2a2fdfee3c46..000000000000
--- a/test/old-elf/Mips/e-flags-merge-8.test
+++ /dev/null
@@ -1,65 +0,0 @@
-# Check that LLD links files with mips32 and mips64 instructions
-# if all these files satisfy O32 ABI.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-32.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-64.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-64r2.o
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-32.o %t-64.o %t-64r2.o
-# RUN: llvm-readobj -file-headers %t.so | FileCheck %s
-
-# CHECK: Flags [ (0x80001100)
-# CHECK-NEXT: EF_MIPS_32BITMODE (0x100)
-# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# CHECK-NEXT: EF_MIPS_ARCH_64R2 (0x80000000)
-# CHECK-NEXT: ]
-
-
-# 32.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# 64.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_64, EF_MIPS_32BITMODE]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# 64r2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_64R2, EF_MIPS_32BITMODE]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/e-flags-merge-9.test b/test/old-elf/Mips/e-flags-merge-9.test
deleted file mode 100644
index ada24d788c9a..000000000000
--- a/test/old-elf/Mips/e-flags-merge-9.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# Check that LLD shows an error and does not link files with mips32r2
-# and mips64 instructions sets.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-32r2.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-64.o
-
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so \
-# RUN: %t-32r2.o %t-64.o 2>&1 | FileCheck %s
-
-# CHECK: Linking modules with incompatible ISA
-
-# 32r2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-# 64.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_64, EF_MIPS_32BITMODE]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/entry-name.test b/test/old-elf/Mips/entry-name.test
deleted file mode 100644
index f6ce0c4f223b..000000000000
--- a/test/old-elf/Mips/entry-name.test
+++ /dev/null
@@ -1,26 +0,0 @@
-# Check name of executable entry symbol.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel --noinhibit-exec -o %t.exe %t.o
-# RUN: llvm-nm %t.exe | FileCheck %s
-
-# CHECK: U __start
-# CHECK: {{[0-9A-F]+}} T main
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: main
- Section: .text
diff --git a/test/old-elf/Mips/exe-dynamic.test b/test/old-elf/Mips/exe-dynamic.test
deleted file mode 100644
index 93fdce9fdc7d..000000000000
--- a/test/old-elf/Mips/exe-dynamic.test
+++ /dev/null
@@ -1,110 +0,0 @@
-# Check MIPS specific tags in the dynamic table in case executable linking.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK: Arch: mipsel
-# CHECK: AddressSize: 32bit
-# CHECK: LoadName:
-# CHECK: DynamicSection [ (20 entries)
-# CHECK: Tag Type Name/Value
-# CHECK-NEXT: 0x00000004 HASH 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000005 STRTAB 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000006 SYMTAB 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x0000000A STRSZ 28 (bytes)
-# CHECK-NEXT: 0x0000000B SYMENT 16 (bytes)
-# CHECK-NEXT: 0x00000002 PLTRELSZ 8 (bytes)
-# CHECK-NEXT: 0x70000032 MIPS_PLTGOT 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000014 PLTREL REL
-# CHECK-NEXT: 0x00000017 JMPREL 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x70000001 MIPS_RLD_VERSION 1
-# CHECK-NEXT: 0x70000016 MIPS_RLD_MAP 0x40200C
-# CHECK-NEXT: 0x70000035 MIPS_RLD_MAP_REL 0x1E0C
-# CHECK-NEXT: 0x70000005 MIPS_FLAGS NOTPOT
-# CHECK-NEXT: 0x70000006 MIPS_BASE_ADDRESS 0x400000
-# CHECK-NEXT: 0x7000000A MIPS_LOCAL_GOTNO 2
-# CHECK-NEXT: 0x70000011 MIPS_SYMTABNO 2
-# CHECK-NEXT: 0x70000013 MIPS_GOTSYM 0x2
-# CHECK-NEXT: 0x00000003 PLTGOT 0x{{[0-9A-F]+}}
-# CHECK-NEXT: 0x00000001 NEEDED SharedLibrary (exe-dynamic.test.tmp.so)
-# CHECK-NEXT: 0x00000000 NULL 0x0
-# CHECK-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: 0000000C000000000000000C000000000000000C00000000
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_26
- Addend: 0
- - Offset: 0x08
- Symbol: .text
- Type: R_MIPS_26
- Addend: 0
- - Offset: 0x10
- Symbol: glob
- Type: R_MIPS_26
- Addend: 0
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- Value: 0x08
- - Name: T1
-...
diff --git a/test/old-elf/Mips/exe-dynsym-micro.test b/test/old-elf/Mips/exe-dynsym-micro.test
deleted file mode 100644
index 477e174f3d6c..000000000000
--- a/test/old-elf/Mips/exe-dynsym-micro.test
+++ /dev/null
@@ -1,94 +0,0 @@
-# Check that symbol referenced by an entry in the global part of GOT
-# has a corresponded entry in the .dynsym section. This test covers
-# the case when the GOT entry created because of the R_MICROMIPS_GOT16
-# relocation.
-
-# Build executable
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t.o
-# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK-DYN %s
-
-# Build executabl (yaml format)e
-# RUN: lld -flavor old-gnu -target mipsel -e glob \
-# RUN: --output-filetype=yaml -o %t.yaml %t.o
-# RUN: FileCheck -check-prefix=CHECK-GOT %s < %t.yaml
-
-# CHECK-DYN: Format: ELF32-mips
-# CHECK-DYN: Arch: mipsel
-# CHECK-DYN: AddressSize: 32bit
-# CHECK-DYN: LoadName:
-# CHECK-DYN: DynamicSymbols [
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: @ (0)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Local (0x0)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: weakf@ (1)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Weak (0x2)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: ]
-
-# CHECK-GOT: - type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: - type: got
-# CHECK-GOT: content: [ 00, 00, 00, 80 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: - ref-name: L000
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: weakf
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: weakf
- Type: R_MICROMIPS_GOT16
-
-Symbols:
- Global:
- - Name: glob
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
- Weak:
- - Name: weakf
diff --git a/test/old-elf/Mips/exe-dynsym.test b/test/old-elf/Mips/exe-dynsym.test
deleted file mode 100644
index c50ce67d5f57..000000000000
--- a/test/old-elf/Mips/exe-dynsym.test
+++ /dev/null
@@ -1,91 +0,0 @@
-# Check that symbol referenced by an entry in the global part of GOT
-# has a corresponded entry in the .dynsym section.
-
-# Build executable
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t.o
-# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK-DYN %s
-
-# Build executabl (yaml format)e
-# RUN: lld -flavor old-gnu -target mipsel -e glob \
-# RUN: --output-filetype=yaml -o %t.yaml %t.o
-# RUN: FileCheck -check-prefix=CHECK-GOT %s < %t.yaml
-
-# CHECK-DYN: Format: ELF32-mips
-# CHECK-DYN: Arch: mipsel
-# CHECK-DYN: AddressSize: 32bit
-# CHECK-DYN: LoadName:
-# CHECK-DYN: DynamicSymbols [
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: @ (0)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Local (0x0)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: Symbol {
-# CHECK-DYN: Name: weakf@ (1)
-# CHECK-DYN: Value: 0x0
-# CHECK-DYN: Size: 0
-# CHECK-DYN: Binding: Weak (0x2)
-# CHECK-DYN: Type: None (0x0)
-# CHECK-DYN: Other: 0
-# CHECK-DYN: Section: Undefined (0x0)
-# CHECK-DYN: }
-# CHECK-DYN: ]
-
-# CHECK-GOT: - type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: - type: got
-# CHECK-GOT: content: [ 00, 00, 00, 80 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: - ref-name: L000
-# CHECK-GOT: type: got
-# CHECK-GOT: content: [ 00, 00, 00, 00 ]
-# CHECK-GOT: alignment: 4
-# CHECK-GOT: section-choice: custom-required
-# CHECK-GOT: section-name: .got
-# CHECK-GOT: permissions: rw-
-# CHECK-GOT: references:
-# CHECK-GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# CHECK-GOT: offset: 0
-# CHECK-GOT: target: weakf
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: weakf
- Type: R_MIPS_GOT16
-
-Symbols:
- Global:
- - Name: glob
- Section: .text
- Weak:
- - Name: weakf
diff --git a/test/old-elf/Mips/exe-fileheader-02.test b/test/old-elf/Mips/exe-fileheader-02.test
deleted file mode 100644
index b3cd88c139b6..000000000000
--- a/test/old-elf/Mips/exe-fileheader-02.test
+++ /dev/null
@@ -1,62 +0,0 @@
-# Check that LLD set ABIVersion to '1' if it generates executable
-# file without EF_MIPS_PIC in the ELF header.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK: Arch: mipsel
-# CHECK: AddressSize: 32bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 32-bit (0x1)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 1
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: Executable (0x2)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x50001005)
-# CHECK: EF_MIPS_ABI_O32 (0x1000)
-# CHECK: EF_MIPS_ARCH_32 (0x50000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: ]
-# CHECK: HeaderSize: 52
-# CHECK: ProgramHeaderEntrySize: 32
-# CHECK: ProgramHeaderCount: {{[0-9]+}}
-# CHECK: SectionHeaderEntrySize: 40
-# CHECK: SectionHeaderCount: {{[0-9]+}}
-# CHECK: StringTableSectionIndex: {{[0-9]+}}
-# CHECK: }
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
-...
diff --git a/test/old-elf/Mips/exe-fileheader-03.test b/test/old-elf/Mips/exe-fileheader-03.test
deleted file mode 100644
index dfe4fcc43e67..000000000000
--- a/test/old-elf/Mips/exe-fileheader-03.test
+++ /dev/null
@@ -1,72 +0,0 @@
-# Check that LLD set ABIVersion to '3' if it generates executable
-# file with FP_64 / FP_64A floating point abi flags.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK: Arch: mipsel
-# CHECK: AddressSize: 32bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 32-bit (0x1)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 3
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: Executable (0x2)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x50001005)
-# CHECK: EF_MIPS_ABI_O32 (0x1000)
-# CHECK: EF_MIPS_ARCH_32 (0x50000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: ]
-# CHECK: HeaderSize: 52
-# CHECK: ProgramHeaderEntrySize: 32
-# CHECK: ProgramHeaderCount: {{[0-9]+}}
-# CHECK: SectionHeaderEntrySize: 40
-# CHECK: SectionHeaderCount: {{[0-9]+}}
-# CHECK: StringTableSectionIndex: {{[0-9]+}}
-# CHECK: }
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
- - Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- AddressAlign: 8
- ISA: MIPS32
- ISARevision: 1
- ISAExtension: EXT_NONE
- FpABI: FP_64
- GPRSize: REG_32
- CPR1Size: REG_64
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
-...
diff --git a/test/old-elf/Mips/exe-fileheader-64.test b/test/old-elf/Mips/exe-fileheader-64.test
deleted file mode 100644
index 20bb43a216d5..000000000000
--- a/test/old-elf/Mips/exe-fileheader-64.test
+++ /dev/null
@@ -1,66 +0,0 @@
-# Check ELF Header for 64-bit executable file.
-
-# Build executable
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -e glob -o %t.exe %t-o.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF64-mips
-# CHECK: Arch: mips64el
-# CHECK: AddressSize: 64bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 64-bit (0x2)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 0
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: Executable (0x2)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x60000007)
-# CHECK: EF_MIPS_ARCH_64 (0x60000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: EF_MIPS_PIC (0x2)
-# CHECK: ]
-# CHECK: HeaderSize: 64
-# CHECK: ProgramHeaderEntrySize: 56
-# CHECK: ProgramHeaderCount: {{[0-9]+}}
-# CHECK: SectionHeaderEntrySize: 64
-# CHECK: SectionHeaderCount: {{[0-9]+}}
-# CHECK: StringTableSectionIndex: {{[0-9]+}}
-# CHECK: }
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ARCH_64 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
-...
diff --git a/test/old-elf/Mips/exe-fileheader-be-64.test b/test/old-elf/Mips/exe-fileheader-be-64.test
deleted file mode 100644
index 70457fe217c6..000000000000
--- a/test/old-elf/Mips/exe-fileheader-be-64.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Check ELF Header for non-pic big-endian 64-bit executable file.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64 -o %t.exe %t.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF64-mips
-# CHECK: Arch: mips64
-# CHECK: AddressSize: 64bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 64-bit (0x2)
-# CHECK: DataEncoding: BigEndian (0x2)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 0
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: Executable (0x2)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x60000007)
-# CHECK: EF_MIPS_ARCH_64 (0x60000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: EF_MIPS_PIC (0x2)
-# CHECK: ]
-# CHECK: HeaderSize: 64
-# CHECK: ProgramHeaderEntrySize: 56
-# CHECK: ProgramHeaderCount: {{[0-9]+}}
-# CHECK: SectionHeaderEntrySize: 64
-# CHECK: SectionHeaderCount: {{[0-9]+}}
-# CHECK: StringTableSectionIndex: {{[0-9]+}}
-# CHECK: }
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
-...
diff --git a/test/old-elf/Mips/exe-fileheader-be.test b/test/old-elf/Mips/exe-fileheader-be.test
deleted file mode 100644
index 292a92e59097..000000000000
--- a/test/old-elf/Mips/exe-fileheader-be.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Check ELF Header for non-pic big-endian 32-bit executable file.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips -o %t.exe %t.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK: Arch: mips
-# CHECK: AddressSize: 32bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 32-bit (0x1)
-# CHECK: DataEncoding: BigEndian (0x2)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 1
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: Executable (0x2)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x50001005)
-# CHECK: EF_MIPS_ABI_O32 (0x1000)
-# CHECK: EF_MIPS_ARCH_32 (0x50000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: ]
-# CHECK: HeaderSize: 52
-# CHECK: ProgramHeaderEntrySize: 32
-# CHECK: ProgramHeaderCount: {{[0-9]+}}
-# CHECK: SectionHeaderEntrySize: 40
-# CHECK: SectionHeaderCount: {{[0-9]+}}
-# CHECK: StringTableSectionIndex: {{[0-9]+}}
-# CHECK: }
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
-...
diff --git a/test/old-elf/Mips/exe-fileheader-micro-64.test b/test/old-elf/Mips/exe-fileheader-micro-64.test
deleted file mode 100644
index a37d2d710637..000000000000
--- a/test/old-elf/Mips/exe-fileheader-micro-64.test
+++ /dev/null
@@ -1,68 +0,0 @@
-# Check ELF Header for 64-bit executable file in case of microMIPS entry symbol.
-
-# Build executable
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -e glob -o %t.exe %t-o.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF64-mips
-# CHECK: Arch: mips64el
-# CHECK: AddressSize: 64bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 64-bit (0x2)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 0
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: Executable (0x2)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x82000007)
-# CHECK: EF_MIPS_ARCH_64R2 (0x80000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_MICROMIPS (0x2000000)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: EF_MIPS_PIC (0x2)
-# CHECK: ]
-# CHECK: HeaderSize: 64
-# CHECK: ProgramHeaderEntrySize: 56
-# CHECK: ProgramHeaderCount: 6
-# CHECK: SectionHeaderEntrySize: 64
-# CHECK: SectionHeaderCount: 12
-# CHECK: StringTableSectionIndex: 9
-# CHECK: }
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_MICROMIPS, EF_MIPS_ARCH_64R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
-...
diff --git a/test/old-elf/Mips/exe-fileheader-micro.test b/test/old-elf/Mips/exe-fileheader-micro.test
deleted file mode 100644
index 0adaf5b17373..000000000000
--- a/test/old-elf/Mips/exe-fileheader-micro.test
+++ /dev/null
@@ -1,69 +0,0 @@
-# Check ELF Header for non-pic executable file in case
-# of microMIPS entry symbol.
-
-# Build executable
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t-o.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK-NEXT: Arch: mipsel
-# CHECK-NEXT: AddressSize: 32bit
-# CHECK-NEXT: LoadName:
-# CHECK-NEXT: ElfHeader {
-# CHECK-NEXT: Ident {
-# CHECK-NEXT: Magic: (7F 45 4C 46)
-# CHECK-NEXT: Class: 32-bit (0x1)
-# CHECK-NEXT: DataEncoding: LittleEndian (0x1)
-# CHECK-NEXT: FileVersion: 1
-# CHECK-NEXT: OS/ABI: SystemV (0x0)
-# CHECK-NEXT: ABIVersion: 1
-# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
-# CHECK-NEXT: }
-# CHECK-NEXT: Type: Executable (0x2)
-# CHECK-NEXT: Machine: EM_MIPS (0x8)
-# CHECK-NEXT: Version: 1
-# CHECK-NEXT: Entry: 0x{{[0-9A-F]+[13579bdf]}}
-# CHECK-NEXT: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: Flags [ (0x72001005)
-# CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# CHECK-NEXT: EF_MIPS_ARCH_32R2 (0x70000000)
-# CHECK-NEXT: EF_MIPS_CPIC (0x4)
-# CHECK-NEXT: EF_MIPS_MICROMIPS (0x2000000)
-# CHECK-NEXT: EF_MIPS_NOREORDER (0x1)
-# CHECK-NEXT: ]
-# CHECK-NEXT: HeaderSize: 52
-# CHECK-NEXT: ProgramHeaderEntrySize: 32
-# CHECK-NEXT: ProgramHeaderCount: 6
-# CHECK-NEXT: SectionHeaderEntrySize: 40
-# CHECK-NEXT: SectionHeaderCount: 12
-# CHECK-NEXT: StringTableSectionIndex: 9
-# CHECK-NEXT: }
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
-...
diff --git a/test/old-elf/Mips/exe-fileheader-n32.test b/test/old-elf/Mips/exe-fileheader-n32.test
deleted file mode 100644
index f6a1725b4443..000000000000
--- a/test/old-elf/Mips/exe-fileheader-n32.test
+++ /dev/null
@@ -1,65 +0,0 @@
-# Check ELF Header for N32 ABI executable file.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -o %t.exe %t.o
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK-NEXT: Arch: mipsel
-# CHECK-NEXT: AddressSize: 32bit
-# CHECK-NEXT: LoadName:
-# CHECK-NEXT: ElfHeader {
-# CHECK-NEXT: Ident {
-# CHECK-NEXT: Magic: (7F 45 4C 46)
-# CHECK-NEXT: Class: 32-bit
-# CHECK-NEXT: DataEncoding: LittleEndian
-# CHECK-NEXT: FileVersion: 1
-# CHECK-NEXT: OS/ABI: SystemV
-# CHECK-NEXT: ABIVersion: 0
-# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
-# CHECK-NEXT: }
-# CHECK-NEXT: Type: Executable
-# CHECK-NEXT: Machine: EM_MIPS
-# CHECK-NEXT: Version: 1
-# CHECK-NEXT: Entry: 0x10000130
-# CHECK-NEXT: ProgramHeaderOffset: 0x34
-# CHECK-NEXT: SectionHeaderOffset: 0x22C0
-# CHECK-NEXT: Flags [ (0x60000027)
-# CHECK-NEXT: EF_MIPS_ABI2
-# CHECK-NEXT: EF_MIPS_ARCH_64
-# CHECK-NEXT: EF_MIPS_CPIC
-# CHECK-NEXT: EF_MIPS_NOREORDER
-# CHECK-NEXT: EF_MIPS_PIC
-# CHECK-NEXT: ]
-# CHECK-NEXT: HeaderSize: 52
-# CHECK-NEXT: ProgramHeaderEntrySize: 32
-# CHECK-NEXT: ProgramHeaderCount: {{[0-9]+}}
-# CHECK-NEXT: SectionHeaderEntrySize: 40
-# CHECK-NEXT: SectionHeaderCount: {{[0-9]+}}
-# CHECK-NEXT: StringTableSectionIndex: {{[0-9]+}}
-# CHECK-NEXT: }
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI2, EF_MIPS_ARCH_64 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 8
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: __start
- Section: .text
-...
diff --git a/test/old-elf/Mips/exe-fileheader.test b/test/old-elf/Mips/exe-fileheader.test
deleted file mode 100644
index 0188a682b3fb..000000000000
--- a/test/old-elf/Mips/exe-fileheader.test
+++ /dev/null
@@ -1,105 +0,0 @@
-# Check ELF Header for non-pic executable file.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: Format: ELF32-mips
-# CHECK: Arch: mipsel
-# CHECK: AddressSize: 32bit
-# CHECK: LoadName:
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 32-bit (0x1)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: SystemV (0x0)
-# CHECK: ABIVersion: 1
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: Executable (0x2)
-# CHECK: Machine: EM_MIPS (0x8)
-# CHECK: Version: 1
-# CHECK: Entry: 0x{{[0-9A-F]+}}
-# CHECK: ProgramHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: SectionHeaderOffset: 0x{{[0-9A-F]+}}
-# CHECK: Flags [ (0x50001005)
-# CHECK: EF_MIPS_ABI_O32 (0x1000)
-# CHECK: EF_MIPS_ARCH_32 (0x50000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: ]
-# CHECK: HeaderSize: 52
-# CHECK: ProgramHeaderEntrySize: 32
-# CHECK: ProgramHeaderCount: {{[0-9]+}}
-# CHECK: SectionHeaderEntrySize: 40
-# CHECK: SectionHeaderCount: {{[0-9]+}}
-# CHECK: StringTableSectionIndex: {{[0-9]+}}
-# CHECK: }
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_26
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- - Name: T1
-...
diff --git a/test/old-elf/Mips/exe-got-micro.test b/test/old-elf/Mips/exe-got-micro.test
deleted file mode 100644
index 7b3a919880de..000000000000
--- a/test/old-elf/Mips/exe-got-micro.test
+++ /dev/null
@@ -1,115 +0,0 @@
-# Check that external symbol defined in the executable file
-# and referenced by R_MICROMIPS_CALL16 relocation has a corresponded
-# entry in the local GOT section.
-#
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob \
-# RUN: --output-filetype=yaml -o %t.exe %t-o.o %t.so
-# RUN: FileCheck -check-prefix=GOT %s < %t.exe
-
-# GOT header
-# GOT: - type: got
-# GOT: content: [ 00, 00, 00, 00 ]
-# GOT: alignment: 4
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# GOT: - type: got
-# GOT: content: [ 00, 00, 00, 80 ]
-# GOT: alignment: 4
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# Local GOT entry for 'glob' symbol
-# GOT: - ref-name: L000
-# GOT: type: got
-# GOT: content: [ 00, 00, 00, 00 ]
-# GOT: alignment: 4
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# GOT: references:
-# GOT: - kind: R_MIPS_32
-# GOT: offset: 0
-# GOT: target: glob
-# Global GOT entry for 'T1' symbol
-# GOT: - ref-name: L001
-# GOT: type: got
-# GOT: content: [ 00, 00, 00, 00 ]
-# GOT: alignment: 4
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# GOT: references:
-# GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# GOT: offset: 0
-# GOT: target: T1
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: glob
- Type: R_MICROMIPS_CALL16
- - Offset: 0x04
- Symbol: T1
- Type: R_MICROMIPS_CALL16
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
-...
diff --git a/test/old-elf/Mips/exe-got.test b/test/old-elf/Mips/exe-got.test
deleted file mode 100644
index 636de16b4202..000000000000
--- a/test/old-elf/Mips/exe-got.test
+++ /dev/null
@@ -1,116 +0,0 @@
-# Check that external symbol defined in the executable file
-# and referenced by R_MIPS_CALL16 relocation has a corresponded
-# entry in the local GOT section.
-#
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob \
-# RUN: --output-filetype=yaml -o %t.exe %t-o.o %t.so
-# RUN: FileCheck -check-prefix=GOT %s < %t.exe
-
-# GOT header
-# GOT: - type: got
-# GOT: content: [ 00, 00, 00, 00 ]
-# GOT: alignment: 4
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# GOT: - type: got
-# GOT: content: [ 00, 00, 00, 80 ]
-# GOT: alignment: 4
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# Local GOT entry for 'glob' symbol
-# GOT: - ref-name: L000
-# GOT: type: got
-# GOT: content: [ 00, 00, 00, 00 ]
-# GOT: alignment: 4
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# GOT: references:
-# GOT: - kind: R_MIPS_32
-# GOT: offset: 0
-# GOT: target: glob
-# Global GOT entry for 'T1' symbol
-# GOT: - ref-name: L001
-# GOT: type: got
-# GOT: content: [ 00, 00, 00, 00 ]
-# GOT: alignment: 4
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# GOT: references:
-# GOT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# GOT: offset: 0
-# GOT: target: T1
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: glob
- Type: R_MIPS_CALL16
- Addend: 0
- - Offset: 0x04
- Symbol: T1
- Type: R_MIPS_CALL16
- Addend: 0
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- - Name: T1
-...
diff --git a/test/old-elf/Mips/got-page-32-micro.test b/test/old-elf/Mips/got-page-32-micro.test
deleted file mode 100644
index 5457ab9f1879..000000000000
--- a/test/old-elf/Mips/got-page-32-micro.test
+++ /dev/null
@@ -1,251 +0,0 @@
-# Check handling of R_MICROMIPS_GOT_DISP / PAGE / OFST relocations
-# in case of O32 ABI.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -symbols -dyn-symbols -mips-plt-got %t.exe \
-# RUN: | FileCheck -check-prefix=GOT %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RAW %s
-
-# GOT: Symbol {
-# GOT: Name: LT3
-# GOT-NEXT: Value: 0x[[LT3:[0-9A-F]+]]
-# GOT: Symbol {
-# GOT: Name: LT4
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: T0
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: LT1
-# GOT-NEXT: Value: 0x[[LT1:[0-9A-F]+]]
-# GOT: Symbol {
-# GOT: Name: LT2
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: T1@
-# GOT-NEXT: Value: 0x0
-# GOT: Symbol {
-# GOT: Name: T2@
-# GOT-NEXT: Value: 0x0
-
-# GOT: Primary GOT {
-# GOT-NEXT: Canonical gp value: 0x408FF0
-# GOT-NEXT: Reserved entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401000
-# GOT-NEXT: Access: -32752
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Purpose: Lazy resolver
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401004
-# GOT-NEXT: Access: -32748
-# GOT-NEXT: Initial: 0x80000000
-# GOT-NEXT: Purpose: Module pointer (GNU extension)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x[[LT1]]
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x40100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x400000
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x400000
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401014
-# GOT-NEXT: Access: -32732
-# GOT-NEXT: Initial: 0x[[LT3]]
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401018
-# GOT-NEXT: Access: -32728
-# GOT-NEXT: Initial: 0x400000
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x40101C
-# GOT-NEXT: Access: -32724
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401020
-# GOT-NEXT: Access: -32720
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Number of TLS and multi-GOT entries: 0
-# GOT-NEXT: }
-
-# RAW: Contents of section .text:
-# RAW-NEXT: {{[0-9a-f]+}} 00002c80 00001880 00002c80 00003080
-# ^ = -32724 (T1)
-# ^ = -32744 (LT1)
-# ^ -32724 (T1)
-# ^ -32720 (T2)
-# RAW-NEXT: {{[0-9a-f]+}} 00001c80 00002080 00000000 00000000
-# ^ -32740 (PAGE)
-# ^ -32736 (PAGE)
-# ^ T1 OFST
-# ^ T2 OFST
-# RAW-NEXT: {{[0-9a-f]+}} 0000a501 0000a901 00002480 00002880
-# ^ LT1 OFST
-# ^ LT2 OFST
-# ^ = -32732 (LT3)
-# ^ -32728 (PAGE)
-# RAW-NEXT: {{[0-9a-f]+}} 0000b101 00000000
-# ^ LT4 OFST
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ARCH_32R2, EF_MIPS_ABI_O32, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x4
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 0x4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ARCH_32R2, EF_MIPS_ABI_O32, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x4
- Size: 0x38
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MICROMIPS_GOT_DISP
- - Offset: 0x4
- Symbol: LT1
- Type: R_MICROMIPS_GOT_DISP
- - Offset: 0x8
- Symbol: T1
- Type: R_MICROMIPS_GOT_PAGE
- - Offset: 0xC
- Symbol: T2
- Type: R_MICROMIPS_GOT_PAGE
- - Offset: 0x10
- Symbol: LT1
- Type: R_MICROMIPS_GOT_PAGE
- - Offset: 0x14
- Symbol: LT2
- Type: R_MICROMIPS_GOT_PAGE
- - Offset: 0x18
- Symbol: T1
- Type: R_MICROMIPS_GOT_OFST
- - Offset: 0x1C
- Symbol: T2
- Type: R_MICROMIPS_GOT_OFST
- - Offset: 0x20
- Symbol: LT1
- Type: R_MICROMIPS_GOT_OFST
- - Offset: 0x24
- Symbol: LT2
- Type: R_MICROMIPS_GOT_OFST
- - Offset: 0x28
- Symbol: LT3
- Type: R_MICROMIPS_GOT_DISP
- - Offset: 0x2C
- Symbol: LT4
- Type: R_MICROMIPS_GOT_PAGE
- - Offset: 0x30
- Symbol: LT4
- Type: R_MICROMIPS_GOT_OFST
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: LT3
- Type: STT_FUNC
- Section: .text
- Value: 0x30
- Size: 0x4
- Other: [STO_MIPS_MICROMIPS]
- - Name: LT4
- Type: STT_FUNC
- Section: .text
- Value: 0x34
- Size: 0x4
- Other: [STO_MIPS_MICROMIPS]
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x8
- Other: [STO_MIPS_MICROMIPS]
- - Name: LT1
- Type: STT_FUNC
- Section: .text
- Value: 0x28
- Size: 0x4
- Other: [STO_MIPS_MICROMIPS]
- - Name: LT2
- Type: STT_FUNC
- Section: .text
- Value: 0x2c
- Size: 0x4
- Other: [STO_MIPS_MICROMIPS]
- - Name: T1
- - Name: T2
-...
diff --git a/test/old-elf/Mips/got-page-32.test b/test/old-elf/Mips/got-page-32.test
deleted file mode 100644
index 44f45536d501..000000000000
--- a/test/old-elf/Mips/got-page-32.test
+++ /dev/null
@@ -1,244 +0,0 @@
-# Check handling of R_MIPS_GOT_DISP / PAGE / OFST relocations.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -symbols -dyn-symbols -mips-plt-got %t.exe \
-# RUN: | FileCheck -check-prefix=GOT %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RAW %s
-
-# GOT: Symbol {
-# GOT: Name: LT3 (12)
-# GOT-NEXT: Value: 0x[[LT3:[0-9A-F]+]]
-# GOT: Symbol {
-# GOT: Name: LT4 (16)
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: T0 (1)
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: LT1 (4)
-# GOT-NEXT: Value: 0x[[LT1:[0-9A-F]+]]
-# GOT: Symbol {
-# GOT: Name: LT2 (8)
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: T1@ (1)
-# GOT-NEXT: Value: 0x0
-# GOT: Symbol {
-# GOT: Name: T2@ (4)
-# GOT-NEXT: Value: 0x0
-
-# GOT: Primary GOT {
-# GOT-NEXT: Canonical gp value: 0x408FF0
-# GOT-NEXT: Reserved entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401000
-# GOT-NEXT: Access: -32752
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Purpose: Lazy resolver
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401004
-# GOT-NEXT: Access: -32748
-# GOT-NEXT: Initial: 0x80000000
-# GOT-NEXT: Purpose: Module pointer (GNU extension)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x[[LT1]]
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x40100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x400000
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x400000
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401014
-# GOT-NEXT: Access: -32732
-# GOT-NEXT: Initial: 0x[[LT3]]
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401018
-# GOT-NEXT: Access: -32728
-# GOT-NEXT: Initial: 0x400000
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x40101C
-# GOT-NEXT: Access: -32724
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401020
-# GOT-NEXT: Access: -32720
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Number of TLS and multi-GOT entries: 0
-# GOT-NEXT: }
-
-# RAW: Contents of section .text:
-# RAW-NEXT: {{[0-9a-f]+}} 2c800000 18800000 2c800000 30800000
-# ^ = -32724 (T1)
-# ^ = -32744 (LT1)
-# ^ -32724 (T1)
-# ^ -32720 (T2)
-# RAW-NEXT: {{[0-9a-f]+}} 1c800000 20800000 00000000 00000000
-# ^ -32740 (PAGE)
-# ^ -32736 (PAGE)
-# ^ T1 OFST
-# ^ T2 OFST
-# RAW-NEXT: {{[0-9a-f]+}} 9c010000 a0010000 24800000 28800000
-# ^ LT1 OFST
-# ^ LT2 OFST
-# ^ = -32732 (LT3)
-# ^ -32728 (PAGE)
-# RAW-NEXT: {{[0-9a-f]+}} a8010000 00000000
-# ^ LT4 OFST
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ARCH_32, EF_MIPS_ABI_O32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 0x4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ARCH_32, EF_MIPS_ABI_O32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x4
- Size: 0x38
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MIPS_GOT_DISP
- - Offset: 0x4
- Symbol: LT1
- Type: R_MIPS_GOT_DISP
- - Offset: 0x8
- Symbol: T1
- Type: R_MIPS_GOT_PAGE
- - Offset: 0xC
- Symbol: T2
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x10
- Symbol: LT1
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x14
- Symbol: LT2
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x18
- Symbol: T1
- Type: R_MIPS_GOT_OFST
- - Offset: 0x1C
- Symbol: T2
- Type: R_MIPS_GOT_OFST
- - Offset: 0x20
- Symbol: LT1
- Type: R_MIPS_GOT_OFST
- - Offset: 0x24
- Symbol: LT2
- Type: R_MIPS_GOT_OFST
- - Offset: 0x28
- Symbol: LT3
- Type: R_MIPS_GOT_DISP
- - Offset: 0x2C
- Symbol: LT4
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x30
- Symbol: LT4
- Type: R_MIPS_GOT_OFST
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: LT3
- Type: STT_FUNC
- Section: .text
- Value: 0x30
- Size: 0x4
- - Name: LT4
- Type: STT_FUNC
- Section: .text
- Value: 0x34
- Size: 0x4
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x8
- - Name: LT1
- Type: STT_FUNC
- Section: .text
- Value: 0x28
- Size: 0x4
- - Name: LT2
- Type: STT_FUNC
- Section: .text
- Value: 0x2c
- Size: 0x4
- - Name: T1
- - Name: T2
-...
diff --git a/test/old-elf/Mips/got-page-64-micro.test b/test/old-elf/Mips/got-page-64-micro.test
deleted file mode 100644
index 37bae77001e4..000000000000
--- a/test/old-elf/Mips/got-page-64-micro.test
+++ /dev/null
@@ -1,210 +0,0 @@
-# Check handling of R_MICROMIPS_GOT_DISP / PAGE / OFST relocations
-# in case of N64 ABI.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -symbols -dyn-symbols -mips-plt-got %t.exe \
-# RUN: | FileCheck -check-prefix=GOT %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RAW %s
-
-# GOT: Symbol {
-# GOT: Name: T0
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: LT1
-# GOT-NEXT: Value: 0x[[LT1:[0-9A-F]+]]
-# GOT: Symbol {
-# GOT: Name: LT2
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: T1@
-# GOT-NEXT: Value: 0x0
-# GOT: Symbol {
-# GOT: Name: T2@
-# GOT-NEXT: Value: 0x0
-
-# GOT: Primary GOT {
-# GOT-NEXT: Canonical gp value: 0x120008FF0
-# GOT-NEXT: Reserved entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001000
-# GOT-NEXT: Access: -32752
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Purpose: Lazy resolver
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x8000000000000000
-# GOT-NEXT: Purpose: Module pointer (GNU extension)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x[[LT1]]
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001018
-# GOT-NEXT: Access: -32728
-# GOT-NEXT: Initial: 0x120000000
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001020
-# GOT-NEXT: Access: -32720
-# GOT-NEXT: Initial: 0x120000000
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001028
-# GOT-NEXT: Access: -32712
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001030
-# GOT-NEXT: Access: -32704
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Number of TLS and multi-GOT entries: 0
-# GOT-NEXT: }
-
-# RAW: Contents of section .text:
-# RAW-NEXT: {{[0-9a-f]+}} 38800000 20800000 38800000 40800000
-# ^ = -32712 (T1)
-# ^ = -32736 (LT1)
-# ^ -32712 (T1)
-# ^ -32704 (T2)
-# RAW-NEXT: {{[0-9a-f]+}} 28800000 30800000 00000000 00000000
-# ^ -32728 (PAGE)
-# ^ -32720 (PAGE)
-# ^ T1 OFST
-# ^ T2 OFST
-# RAW-NEXT: {{[0-9a-f]+}} 59020000 5d020000 00000000 00000000
-# ^ LT1 OFST
-# ^ LT2 OFST
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ARCH_64R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x4
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 0x4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ARCH_64R2, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x4
- Size: 0x30
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MIPS_GOT_DISP
- - Offset: 0x4
- Symbol: LT1
- Type: R_MIPS_GOT_DISP
- - Offset: 0x8
- Symbol: T1
- Type: R_MIPS_GOT_PAGE
- - Offset: 0xC
- Symbol: T2
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x10
- Symbol: LT1
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x14
- Symbol: LT2
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x18
- Symbol: T1
- Type: R_MIPS_GOT_OFST
- - Offset: 0x1C
- Symbol: T2
- Type: R_MIPS_GOT_OFST
- - Offset: 0x20
- Symbol: LT1
- Type: R_MIPS_GOT_OFST
- - Offset: 0x24
- Symbol: LT2
- Type: R_MIPS_GOT_OFST
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x8
- Other: [STO_MIPS_MICROMIPS]
- - Name: LT1
- Type: STT_FUNC
- Section: .text
- Value: 0x28
- Size: 0x4
- Other: [STO_MIPS_MICROMIPS]
- - Name: LT2
- Type: STT_FUNC
- Section: .text
- Value: 0x2c
- Size: 0x4
- Other: [STO_MIPS_MICROMIPS]
- - Name: T1
- - Name: T2
-...
diff --git a/test/old-elf/Mips/got-page-64.test b/test/old-elf/Mips/got-page-64.test
deleted file mode 100644
index 3c6ef57c78f5..000000000000
--- a/test/old-elf/Mips/got-page-64.test
+++ /dev/null
@@ -1,203 +0,0 @@
-# Check handling of R_MIPS_GOT_DISP / PAGE / OFST relocations.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -symbols -dyn-symbols -mips-plt-got %t.exe \
-# RUN: | FileCheck -check-prefix=GOT %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RAW %s
-
-# GOT: Symbol {
-# GOT: Name: T0 (1)
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: LT1 (4)
-# GOT-NEXT: Value: 0x[[LT1:[0-9A-F]+]]
-# GOT: Symbol {
-# GOT: Name: LT2 (8)
-# GOT-NEXT: Value: 0x{{[0-9A-F]+}}
-# GOT: Symbol {
-# GOT: Name: T1@ (1)
-# GOT-NEXT: Value: 0x0
-# GOT: Symbol {
-# GOT: Name: T2@ (4)
-# GOT-NEXT: Value: 0x0
-
-# GOT: Primary GOT {
-# GOT-NEXT: Canonical gp value: 0x120008FF0
-# GOT-NEXT: Reserved entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001000
-# GOT-NEXT: Access: -32752
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Purpose: Lazy resolver
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x8000000000000000
-# GOT-NEXT: Purpose: Module pointer (GNU extension)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x[[LT1]]
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001018
-# GOT-NEXT: Access: -32728
-# GOT-NEXT: Initial: 0x120000000
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001020
-# GOT-NEXT: Access: -32720
-# GOT-NEXT: Initial: 0x120000000
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001028
-# GOT-NEXT: Access: -32712
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001030
-# GOT-NEXT: Access: -32704
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Number of TLS and multi-GOT entries: 0
-# GOT-NEXT: }
-
-# RAW: Contents of section .text:
-# RAW-NEXT: {{[0-9a-f]+}} 38800000 20800000 38800000 40800000
-# ^ = -32712 (T1)
-# ^ = -32736 (LT1)
-# ^ -32712 (T1)
-# ^ -32704 (T2)
-# RAW-NEXT: {{[0-9a-f]+}} 28800000 30800000 00000000 00000000
-# ^ -32728 (PAGE)
-# ^ -32720 (PAGE)
-# ^ T1 OFST
-# ^ T2 OFST
-# RAW-NEXT: {{[0-9a-f]+}} 50020000 54020000 00000000 00000000
-# ^ LT1 OFST
-# ^ LT2 OFST
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 0x4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x4
- Size: 0x30
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MIPS_GOT_DISP
- - Offset: 0x4
- Symbol: LT1
- Type: R_MIPS_GOT_DISP
- - Offset: 0x8
- Symbol: T1
- Type: R_MIPS_GOT_PAGE
- - Offset: 0xC
- Symbol: T2
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x10
- Symbol: LT1
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x14
- Symbol: LT2
- Type: R_MIPS_GOT_PAGE
- - Offset: 0x18
- Symbol: T1
- Type: R_MIPS_GOT_OFST
- - Offset: 0x1C
- Symbol: T2
- Type: R_MIPS_GOT_OFST
- - Offset: 0x20
- Symbol: LT1
- Type: R_MIPS_GOT_OFST
- - Offset: 0x24
- Symbol: LT2
- Type: R_MIPS_GOT_OFST
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x8
- - Name: LT1
- Type: STT_FUNC
- Section: .text
- Value: 0x28
- Size: 0x4
- - Name: LT2
- Type: STT_FUNC
- Section: .text
- Value: 0x2c
- Size: 0x4
- - Name: T1
- - Name: T2
-...
diff --git a/test/old-elf/Mips/got16-2.test b/test/old-elf/Mips/got16-2.test
deleted file mode 100644
index 01f11a5920cd..000000000000
--- a/test/old-elf/Mips/got16-2.test
+++ /dev/null
@@ -1,73 +0,0 @@
-# Check handling of R_MIPS_GOT16 relocation against local
-# symbols when addresses of local data cross 64 KBytes border.
-
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t-exe %t-obj
-# RUN: llvm-objdump -s %t-exe | FileCheck %s
-
-# CHECK: Contents of section .got:
-# CHECK-NEXT: 40a000 00000000 00000080 00004000 00004100 ..........@...A.
-# lazy module 0x400000 0x410000
-# resolver pointer for L1 for L2
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: '00000000000000000000000000000000'
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Address: 0x1000
- Relocations:
- - Offset: 0
- Symbol: L1
- Type: R_MIPS_GOT16
- - Offset: 4
- Symbol: L1
- Type: R_MIPS_LO16
- - Offset: 8
- Symbol: L2
- Type: R_MIPS_GOT16
- - Offset: 12
- Symbol: L2
- Type: R_MIPS_LO16
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x9000
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: L1
- Type: STT_OBJECT
- Section: .data
- Value: 0x00
- Size: 0x8000
- - Name: L2
- Type: STT_OBJECT
- Section: .data
- Value: 0x8000
- Size: 0x04
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x04
diff --git a/test/old-elf/Mips/got16-micro.test b/test/old-elf/Mips/got16-micro.test
deleted file mode 100644
index 25de08e95c4e..000000000000
--- a/test/old-elf/Mips/got16-micro.test
+++ /dev/null
@@ -1,165 +0,0 @@
-# REQUIRES: mips
-
-# Check handling of global/local R_MICROMIPS_GOT16 relocations.
-# RUN: llvm-mc -triple=mipsel -mattr=micromips -relocation-model=pic \
-# RUN: -filetype=obj -o=%t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec \
-# RUN: --output-filetype=yaml %t.o \
-# RUN: | FileCheck -check-prefix YAML %s
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec -o %t2 %t.o
-# RUN: llvm-objdump -t -disassemble -mattr=micromips %t2 \
-# RUN: | FileCheck -check-prefix RAW %s
-
-# Function glob
-# YAML: - name: main
-# YAML: scope: global
-# YAML: content: [ 5C, FC, 00, 00, 42, 30, 00, 00, 5C, FC, 00, 00,
-# YAML: 42, 30, 00, 00, 5C, FC, 00, 00, 5C, FC, 00, 00,
-# YAML: 5C, FC, 00, 00 ]
-# YAML: alignment: 4 mod 16
-# YAML: code-model: mips-micro
-# YAML: references:
-# YAML-NEXT: - kind: R_MICROMIPS_GOT16
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: L000
-# YAML-NEXT: - kind: R_MICROMIPS_LO16
-# YAML-NEXT: offset: 4
-# YAML-NEXT: target: data_1
-# YAML-NEXT: - kind: R_MICROMIPS_GOT16
-# YAML-NEXT: offset: 8
-# YAML-NEXT: target: L001
-# YAML-NEXT: - kind: R_MICROMIPS_LO16
-# YAML-NEXT: offset: 12
-# YAML-NEXT: target: data_2
-# YAML-NEXT: - kind: R_MICROMIPS_GOT16
-# YAML-NEXT: offset: 16
-# YAML-NEXT: target: L002
-# YAML-NEXT: - kind: R_MICROMIPS_CALL16
-# YAML-NEXT: offset: 20
-# YAML-NEXT: target: L003
-# YAML-NEXT: - kind: R_MICROMIPS_CALL16
-# YAML-NEXT: offset: 24
-# YAML-NEXT: target: L004
-
-# Local GOT entries:
-# YAML: - ref-name: L000
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: LLD_R_MIPS_32_HI16
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: data_1
-# YAML-NEXT: - ref-name: L001
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: LLD_R_MIPS_32_HI16
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: data_2
-# YAML-NEXT: - ref-name: L002
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: R_MIPS_32
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: data_h
-
-# Global GOT entries:
-# YAML-NEXT: - ref-name: L003
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: bar
-# YAML-NEXT: - kind: R_MIPS_32
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: bar
-# YAML-NEXT: - ref-name: L004
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: foo
-
-# RAW: Disassembly of section .text:
-# RAW: main:
-# RAW-NEXT: {{[0x0-9a-f]+}}: 5c fc 18 80 lw $2, -32744($gp)
-# RAW-NEXT: {{[0x0-9a-f]+}}: 42 30 40 10 addiu $2, $2, 4160
-# RAW-NEXT: {{[0x0-9a-f]+}}: 5c fc 1c 80 lw $2, -32740($gp)
-# RAW-NEXT: {{[0x0-9a-f]+}}: 42 30 60 20 addiu $2, $2, 8288
-# RAW-NEXT: {{[0x0-9a-f]+}}: 5c fc 20 80 lw $2, -32736($gp)
-# RAW-NEXT: {{[0x0-9a-f]+}}: 5c fc 24 80 lw $2, -32732($gp)
-# RAW-NEXT: {{[0x0-9a-f]+}}: 5c fc 28 80 lw $2, -32728($gp)
-
-# RAW: SYMBOL TABLE:
-# RAW: {{[0x0-9a-f]+}} *UND* 00000000
-# RAW: {{[0x0-9a-f]+}} l .data 00001020 data_1
-# RAW: {{[0x0-9a-f]+}} l .data 00000001 data_2
-# RAW: {{[0x0-9a-f]+}} g F .text 00000004 bar
-# RAW: {{[0x0-9a-f]+}} g F .text 0000001c main
-# RAW: {{[0x0-9a-f]+}} g .data 00000001 data_h
-
- .data
- .type data_1, @object
- .size data_1, 4128
-data_1:
- .byte 1
- .space 4127
- .type data_2, @object
- .size data_2, 1
-data_2:
- .byte 2
- .hidden data_h
- .globl data_h
- .type data_h, @object
- .size data_h, 1
-data_h:
- .byte 3
-
- .text
- .globl bar
- .set micromips
- .ent bar
- .type bar, @function
-bar:
- nop
- .end bar
- .size bar, .-bar
-
- .globl main
- .set micromips
- .ent main
- .type main, @function
-main:
- lw $2,%got(data_1)($28)
- addiu $2,$2,%lo(data_1)
- lw $2,%got(data_2)($28)
- addiu $2,$2,%lo(data_2)
- lw $2,%got(data_h)($28)
- lw $2,%call16(bar)($28)
- lw $2,%call16(foo)($28)
-
- .end main
- .size main, .-main
diff --git a/test/old-elf/Mips/got16.test b/test/old-elf/Mips/got16.test
deleted file mode 100644
index 4dde15a11c26..000000000000
--- a/test/old-elf/Mips/got16.test
+++ /dev/null
@@ -1,196 +0,0 @@
-# REQUIRES: mips
-
-# Check handling of global/local GOT16 relocations.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec \
-# RUN: --output-filetype=yaml %t.o \
-# RUN: | FileCheck -check-prefix YAML %s
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec -o %t2 %t.o
-# RUN: llvm-objdump -t -disassemble %t2 | FileCheck -check-prefix RAW %s
-
-# Function glob
-# YAML: - name: glob
-# YAML: scope: global
-# YAML: content: [ 00, 00, 84, 8F, 00, 00, 84, 24, 01, 00, 84, 8F,
-# YAML: 00, 02, 84, 24, 00, 00, 84, 8F, 00, 00, 84, 8F,
-# YAML: 00, 00, 84, 8F ]
-# YAML: alignment: 4
-# YAML: references:
-# YAML: - kind: R_MIPS_GOT16
-# YAML: offset: 0
-# YAML: target: L000
-# YAML: - kind: R_MIPS_LO16
-# YAML: offset: 4
-# YAML: target: L009
-# YAML: - kind: R_MIPS_GOT16
-# YAML: offset: 8
-# YAML: target: L002
-# YAML: addend: 66048
-# YAML: - kind: R_MIPS_LO16
-# YAML: offset: 12
-# YAML: target: L009
-# YAML: addend: 512
-# YAML: - kind: R_MIPS_GOT16
-# YAML: offset: 16
-# YAML: target: L004
-# YAML: - kind: R_MIPS_CALL16
-# YAML: offset: 20
-# YAML: target: L005
-# YAML: - kind: R_MIPS_CALL16
-# YAML: offset: 24
-# YAML: target: L006
-
-# Local GOT entries:
-# YAML: - ref-name: L000
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: LLD_R_MIPS_32_HI16
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: L009
-# YAML-NEXT: - ref-name: L002
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: LLD_R_MIPS_32_HI16
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: L009
-# YAML-NEXT: addend: 66048
-# YAML-NEXT: - ref-name: L004
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: R_MIPS_32
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: hidden
-
-# Global GOT entries:
-# YAML-NEXT: - ref-name: L005
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: glob
-# YAML-NEXT: - kind: R_MIPS_32
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: glob
-# YAML-NEXT: - ref-name: L006
-# YAML-NEXT: type: got
-# YAML-NEXT: content: [ 00, 00, 00, 00 ]
-# YAML-NEXT: alignment: 4
-# YAML-NEXT: section-choice: custom-required
-# YAML-NEXT: section-name: .got
-# YAML-NEXT: permissions: rw-
-# YAML-NEXT: references:
-# YAML-NEXT: - kind: LLD_R_MIPS_GLOBAL_GOT
-# YAML-NEXT: offset: 0
-# YAML-NEXT: target: extern
-
-# RAW: Disassembly of section .text:
-# RAW: glob:
-# RAW-NEXT: {{[0x0-9a-f]+}}: 18 80 84 8f lw $4, -32744($gp)
-# RAW-NEXT: {{[0x0-9a-f]+}}: 00 20 84 24 addiu $4, $4, 8192
-# RAW-NEXT: {{[0x0-9a-f]+}}: 1c 80 84 8f lw $4, -32740($gp)
-# RAW-NEXT: {{[0x0-9a-f]+}}: 00 22 84 24 addiu $4, $4, 8704
-# RAW-NEXT: {{[0x0-9a-f]+}}: 20 80 84 8f lw $4, -32736($gp)
-# RAW-NEXT: {{[0x0-9a-f]+}}: 24 80 84 8f lw $4, -32732($gp)
-# RAW-NEXT: {{[0x0-9a-f]+}}: 28 80 84 8f lw $4, -32728($gp)
-
-# RAW: SYMBOL TABLE:
-# RAW: {{[0x0-9a-f]+}} *UND* 00000000
-# RAW: {{[0x0-9a-f]+}} l .data 00000000 str1
-# RAW: {{[0x0-9a-f]+}} l .data 00000005 str2
-# RAW: {{[0x0-9a-f]+}} g F .text 0000001c glob
-# RAW: {{[0x0-9a-f]+}} g .data 00000004 hidden
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: '0000848F000084240100848F000284240000848F0000848F0000848F'
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: .data
- Type: R_MIPS_GOT16
- - Offset: 0x04
- Symbol: .data
- Type: R_MIPS_LO16
- - Offset: 0x08
- Symbol: .data
- Type: R_MIPS_GOT16
- - Offset: 0x0C
- Symbol: .data
- Type: R_MIPS_LO16
- - Offset: 0x10
- Symbol: hidden
- Type: R_MIPS_GOT16
- - Offset: 0x14
- Symbol: glob
- Type: R_MIPS_CALL16
- - Offset: 0x18
- Symbol: extern
- Type: R_MIPS_CALL16
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x10209
-
-Symbols:
- Local:
- - Name: str1
- Type: STT_OBJECT
- Section: .data
- Size: 0x10200
- - Name: str2
- Type: STT_OBJECT
- Section: .data
- Value: 0x10200
- Size: 0x05
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- Global:
- - Name: glob
- Section: .text
- - Name: hidden
- Type: STT_OBJECT
- Section: .data
- Value: 0x10205
- Size: 0x04
- Visibility: STV_HIDDEN
- - Name: extern
diff --git a/test/old-elf/Mips/gotsym.test b/test/old-elf/Mips/gotsym.test
deleted file mode 100644
index bc89ba5d3768..000000000000
--- a/test/old-elf/Mips/gotsym.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# Check _gp_disp and GOT_OFFSET_TABLE value
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec -o %t.so %t.o
-# RUN: llvm-objdump -h -t %t.so | FileCheck -check-prefix=SHARED %s
-
-# SHARED: Sections:
-# SHARED: Idx Name Size Address Type
-# SHARED: 6 .got 00000008 0000000000001000 DATA
-# SHARED: SYMBOL TABLE:
-# SHARED: 00001000 .got 00000000 _GLOBAL_OFFSET_TABLE_
-# SHARED: 00008ff0 g *ABS* 00000000 _gp
-# SHARED: 00008ff0 g *ABS* 00000000 _gp_disp
-
-# RUN: lld -flavor old-gnu -target mipsel -e main --noinhibit-exec -o %t.exe %t.o
-# RUN: llvm-objdump -h -t %t.exe | FileCheck -check-prefix=EXE %s
-
-# EXE: Sections:
-# EXE: Idx Name Size Address Type
-# EXE: 7 .got 00000008 0000000000401000 DATA
-# EXE: SYMBOL TABLE:
-# EXE: 00401000 .got 00000000 _GLOBAL_OFFSET_TABLE_
-# EXE: 00408ff0 g *ABS* 00000000 _gp
-# EXE: 00408ff0 g *ABS* 00000000 _gp_disp
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x04
-
-Symbols:
- Global:
- - Name: main
- Section: .text
diff --git a/test/old-elf/Mips/gp-sym-1-micro.test b/test/old-elf/Mips/gp-sym-1-micro.test
deleted file mode 100644
index 0e1bea9c38da..000000000000
--- a/test/old-elf/Mips/gp-sym-1-micro.test
+++ /dev/null
@@ -1,88 +0,0 @@
-# Check that microMIPS relocations against __gnu_local_gp
-# use "gp" value as target.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -symbols %t.exe | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=SEC %s
-
-# SYM: Name: _gp
-# SYM-NEXT: Value: 0x408FF0
-
-# SEC: Contents of section .text:
-# SEC-NEXT: 400184 00004100 0000f08f 2000bc00 ..A..... ...
-# SEC: Contents of section .got:
-# SEC-NEXT: 401000 00000000 00000080 ........
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 12
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: __gnu_local_gp
- Type: R_MICROMIPS_HI16
- - Offset: 0x04
- Symbol: __gnu_local_gp
- Type: R_MICROMIPS_LO16
- - Offset: 0x08
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: __gnu_local_gp
- - Name: T1
-...
diff --git a/test/old-elf/Mips/gp-sym-1.test b/test/old-elf/Mips/gp-sym-1.test
deleted file mode 100644
index ebb73c3afd60..000000000000
--- a/test/old-elf/Mips/gp-sym-1.test
+++ /dev/null
@@ -1,86 +0,0 @@
-# Check that relocations against __gnu_local_gp use "gp" value as target.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -symbols %t.exe | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=SEC %s
-
-# SYM: Name: _gp
-# SYM-NEXT: Value: 0x408FF0
-
-# SEC: Contents of section .text:
-# SEC-NEXT: 400190 41000000 f08f0000 60001000
-# SEC: Contents of section .got:
-# SEC-NEXT: 401000 00000000 00000080
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 12
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: __gnu_local_gp
- Type: R_MIPS_HI16
- - Offset: 0x04
- Symbol: __gnu_local_gp
- Type: R_MIPS_LO16
- - Offset: 0x08
- Symbol: T1
- Type: R_MIPS_26
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- - Name: __gnu_local_gp
- - Name: T1
-...
diff --git a/test/old-elf/Mips/gp-sym-2.test b/test/old-elf/Mips/gp-sym-2.test
deleted file mode 100644
index b6d95f350af3..000000000000
--- a/test/old-elf/Mips/gp-sym-2.test
+++ /dev/null
@@ -1,103 +0,0 @@
-# Check that R_MIPS32 relocation against __gnu_local_gp causes emitting
-# of R_MIPS_REL32 relocation in case of shared library file linking
-# and does not produce any dynamic relocation in case of linking a non-shared
-# executable file.
-
-# Now the test failed because the __gnu_local_gp symbol becomes defined
-# absolute symbol and we do not generate R_MIPS_REL32 in case of shared
-# library linking.
-# XFAIL: *
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t-1.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t-1.so
-# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=EXE %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t-2.so %t-o.o %t-1.so
-# RUN: llvm-readobj -r %t-2.so | FileCheck -check-prefix=SO %s
-
-# EXE: Relocations [
-# EXE-NEXT: ]
-
-# SO: Relocations [
-# SO-NEXT: Section (5) .rel.dyn {
-# SO-NEXT: 0x0 R_MIPS_NONE - 0x0
-# SO-NEXT: 0x2EC R_MIPS_REL32 __gnu_local_gp 0x0
-# SO-NEXT: }
-# SO-NEXT: ]
-
-# so.so
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_PIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 12
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: __gnu_local_gp
- Type: R_MIPS_32
- - Offset: 0x04
- Symbol: T1
- Type: R_MIPS_LO16
- - Offset: 0x08
- Symbol: T2
- Type: R_MIPS_CALL16
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- - Name: __gnu_local_gp
- - Name: T1
- - Name: T2
-...
diff --git a/test/old-elf/Mips/hilo16-1.test b/test/old-elf/Mips/hilo16-1.test
deleted file mode 100644
index b284140f748f..000000000000
--- a/test/old-elf/Mips/hilo16-1.test
+++ /dev/null
@@ -1,40 +0,0 @@
-# REQUIRES: mips
-
-# Check handling multiple HI16 relocation followed by a single LO16 relocation.
-
-# RUN: llvm-mc -arch=mipsel -filetype=obj -o=%t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: T0:
-# CHECK-NEXT: 400180: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: 42 00 08 3c lui $8, 66
-# CHECK-NEXT: {{[0-9a-f]+}}: 3e 00 08 3c lui $8, 62
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 02 08 3c lui $8, 576
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 fe 08 3c lui $8, 65088
-# CHECK-NEXT: {{[0-9a-f]+}}: a5 01 08 25 addiu $8, $8, 421
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400180 g F .text 00000024 T0
-# CHECK: 004001a4 g F .text 00000004 T1
-
- .text
- .globl T0
-T0:
- lui $8, %hi(T1+1)
- lui $8, %hi(T1-1)
- lui $8, %hi(T1+0x1ff)
- lui $8, %hi(T1+(-0x1ff))
- lui $8, %hi(T1+0x1ffff)
- lui $8, %hi(T1+(-0x1ffff))
- lui $8, %hi(T1+0x1ffffff)
- lui $8, %hi(T1+(-0x1ffffff))
- addiu $8, $8, %lo(T1+(-0x1ffffff))
-
- .globl T1
-T1:
- nop
diff --git a/test/old-elf/Mips/hilo16-2.test b/test/old-elf/Mips/hilo16-2.test
deleted file mode 100644
index e47b9003a8dd..000000000000
--- a/test/old-elf/Mips/hilo16-2.test
+++ /dev/null
@@ -1,70 +0,0 @@
-# REQUIRES: mips
-
-# Check handling of HI16 and LO16 relocations for regular symbol.
-#
-# R_MIPS_HI16: (AHL + S) - (short)(AHL + S)
-# R_MIPS_LO16: AHL + S
-# where AHL = (AHI << 16) + ALO
-
-# RUN: llvm-mc -arch=mipsel -filetype=obj -o=%t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: T0:
-# CHECK-NEXT: 400180: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: c1 01 08 25 addiu $8, $8, 449
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: bf 01 08 25 addiu $8, $8, 447
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: bf 03 08 25 addiu $8, $8, 959
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: c1 ff 08 25 addiu $8, $8, -63
-#
-# CHECK: T1:
-# CHECK-NEXT: 4001a0: 42 00 08 3c lui $8, 66
-# CHECK-NEXT: {{[0-9a-f]+}}: bf 01 08 25 addiu $8, $8, 447
-# CHECK-NEXT: {{[0-9a-f]+}}: 3e 00 08 3c lui $8, 62
-# CHECK-NEXT: {{[0-9a-f]+}}: c1 01 08 25 addiu $8, $8, 449
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 02 08 3c lui $8, 576
-# CHECK-NEXT: {{[0-9a-f]+}}: bf 01 08 25 addiu $8, $8, 447
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 fe 08 3c lui $8, 65088
-# CHECK-NEXT: {{[0-9a-f]+}}: c1 01 08 25 addiu $8, $8, 449
-#
-# CHECK: T2:
-# CHECK-NEXT: 4001c0: 00 00 00 00 nop
-
- .section .text.1,"ax",@progbits
- .align 4
- .globl T0
-T0:
- lui $8, %hi(T2+1)
- addiu $8, $8, %lo(T2+1)
- lui $8, %hi(T2+(-1))
- addiu $8, $8, %lo(T2+(-1))
- lui $8, %hi(T2+0x1ff)
- addiu $8, $8, %lo(T2+0x1ff)
- lui $8, %hi(T2+(-0x1ff))
- addiu $8, $8, %lo(T2+(-0x1ff))
- .size T0, .-T0
-
- .section .text.2,"ax",@progbits
- .align 4
- .globl T1
-T1:
- lui $8, %hi(T2+0x1ffff)
- addiu $8, $8, %lo(T2+0x1ffff)
- lui $8, %hi(T2+(-0x1ffff))
- addiu $8, $8, %lo(T2+(-0x1ffff))
- lui $8, %hi(T2+0x1ffffff)
- addiu $8, $8, %lo(T2+0x1ffffff)
- lui $8, %hi(T2+(-0x1ffffff))
- addiu $8, $8, %lo(T2+(-0x1ffffff))
- .size T1, .-T1
-
- .section .text.3,"ax",@progbits
- .align 4
- .globl T2
-T2:
- nop
- .size T2, .-T2
diff --git a/test/old-elf/Mips/hilo16-3-overflow.test b/test/old-elf/Mips/hilo16-3-overflow.test
deleted file mode 100644
index 94fc90b3be54..000000000000
--- a/test/old-elf/Mips/hilo16-3-overflow.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# Check R_MIPS_HI16 relocation overflow handling.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}} reference from T0+0 to _gp_disp+2147483648 of type 5 (R_MIPS_HI16)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0080000000000000"
-# ^ %hi(gp+0x80000000)
-# ^ %lo(gp+0x80000000)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: _gp_disp
- Type: R_MIPS_HI16
- - Offset: 0x4
- Symbol: _gp_disp
- Type: R_MIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: _gp_disp
diff --git a/test/old-elf/Mips/hilo16-3.test b/test/old-elf/Mips/hilo16-3.test
deleted file mode 100644
index 17873c0a629c..000000000000
--- a/test/old-elf/Mips/hilo16-3.test
+++ /dev/null
@@ -1,74 +0,0 @@
-# Check handling of HI16 and LO16 relocations for _gp_disp.
-#
-# R_MIPS_HI16: (AHL + GP - P) - (short)(AHL + GP - P)
-# R_MIPS_LO16: AHL + GP - P + 4
-# where AHL = (AHI << 16) + ALO
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-objdump -s -t %t.so | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 00d0 0100083c 218f0885 0100083c 178f0885
-# CHECK-NEXT: 00e0 0100083c 0f910885 0100083c 098d0885
-# CHECK-NEXT: 00f0 0200083c ffff0885
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 000000d0 g F .text 00000028 T0
-# CHECK: 00008ff0 g *ABS* 00000000 _gp_disp
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000083C010008850000083CFFFF08850000083CFF0108850000083C01FE08850200083CFFFF0885"
-# ^ %hi(gp+1) ^ %hi(gp-1) ^ %hi(gp+0x1ff) ^ %hi(gp-0x1ff) ^ %lo(gp+0x1ffff)
-# ^ %lo(gp+1) ^ %lo(gp-1) ^ %lo(gp+0x1ff) ^ %lo(gp-0x1ff)
-# ^ %hi(gp+0x1ffff)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: _gp_disp
- Type: R_MIPS_HI16
- - Offset: 0x4
- Symbol: _gp_disp
- Type: R_MIPS_LO16
- - Offset: 0x8
- Symbol: _gp_disp
- Type: R_MIPS_HI16
- - Offset: 0xC
- Symbol: _gp_disp
- Type: R_MIPS_LO16
- - Offset: 0x10
- Symbol: _gp_disp
- Type: R_MIPS_HI16
- - Offset: 0x14
- Symbol: _gp_disp
- Type: R_MIPS_LO16
- - Offset: 0x18
- Symbol: _gp_disp
- Type: R_MIPS_HI16
- - Offset: 0x1C
- Symbol: _gp_disp
- Type: R_MIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 80
- - Name: _gp_disp
diff --git a/test/old-elf/Mips/hilo16-4.test b/test/old-elf/Mips/hilo16-4.test
deleted file mode 100644
index 2db17344e30f..000000000000
--- a/test/old-elf/Mips/hilo16-4.test
+++ /dev/null
@@ -1,93 +0,0 @@
-# REQUIRES: mips
-
-# Check pairing of R_MIPS_HI16 and R_MIPS_LO16 relocations.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel -e glob1 -o %t-exe %t-obj
-# RUN: llvm-objdump -t -disassemble %t-exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK: glob1:
-# CHECK-NEXT: 400130: 40 00 04 3c lui $4, 64
-# CHECK-NEXT: 400134: ff 9f a6 8c lw $6, -24577($5)
-
-# CHECK: glob2:
-# CHECK-NEXT: 400138: 00 20 c7 80 lb $7, 8192($6)
-# CHECK-NEXT: 40013c: 04 20 c8 80 lb $8, 8196($6)
-
-# CHECK: glob3:
-# CHECK-NEXT: 400140: 40 80 05 3c lui $5, 32832
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400130 g F .text 00000008 glob1
-# CHECK: 00400138 g F .text 00000008 glob2
-# CHECK: 00400140 g F .text 00000004 glob3
-# CHECK: 00402000 g .data 0000000c X
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
-# glob1:
-# lui $4,%hi(X) # rel A
-# lw $6,%lo(X+32767)($5) # rel B
-# glob2:
-# lb $7,%lo(X)($6) # rel C
-# lb $8,%lo(X+4)($6) # rel D
-# glob3:
-# lui $5,%hi(X+32767) # rel E
- Content: "0000043CFF7FA68C0000C7800400C880FF7F053C"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Content: "000000000000000000000000"
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x10 # rel E
- Symbol: X
- Type: R_MIPS_HI16
- - Offset: 0x04 # rel B
- Symbol: X
- Type: R_MIPS_LO16
- - Offset: 0x00 # rel A
- Symbol: X
- Type: R_MIPS_HI16
- - Offset: 0x0C # rel D
- Symbol: X
- Type: R_MIPS_LO16
- - Offset: 0x08 # rel C
- Symbol: X
- Type: R_MIPS_LO16
-
-Symbols:
- Global:
- - Name: glob1
- Section: .text
- Value: 0x0
- Size: 8
- - Name: glob2
- Section: .text
- Value: 0x8
- Size: 8
- - Name: glob3
- Section: .text
- Value: 0x10
- Size: 4
- - Name: X
- Section: .data
- Value: 0x0
- Size: 12
diff --git a/test/old-elf/Mips/hilo16-5.test b/test/old-elf/Mips/hilo16-5.test
deleted file mode 100644
index 597425e8ba74..000000000000
--- a/test/old-elf/Mips/hilo16-5.test
+++ /dev/null
@@ -1,103 +0,0 @@
-# Check that linker shows a warning when
-# there is orphaned R_MIPS_HI16 relocation.
-
-# RUN: yaml2obj -format=elf -o %t-so.o -docnum 1 %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -o %t-o.o -docnum 2 %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so 2>&1 \
-# RUN: | FileCheck -check-prefix=DIAG %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=DATA %s
-
-# DIAG: lld warning: cannot matching LO16 relocation
-# DIAG: lld warning: cannot matching LO16 relocation
-
-# DATA: Contents of section .data:
-# DATA-NEXT: 402000 40000000 10200000 40000000 @.... ..@...
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .data
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Content: "000000000000000000000000"
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MIPS_HI16
- - Offset: 0x08
- Symbol: D2
- Type: R_MIPS_HI16
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_LO16
- - Offset: 0x08
- Symbol: .text
- Type: R_MIPS_HI16
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
-
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: D1
- - Name: D2
-...
diff --git a/test/old-elf/Mips/hilo16-8-micro.test b/test/old-elf/Mips/hilo16-8-micro.test
deleted file mode 100644
index ef8ac782341c..000000000000
--- a/test/old-elf/Mips/hilo16-8-micro.test
+++ /dev/null
@@ -1,81 +0,0 @@
-# REQUIRES: mips
-
-# Check calculation of AHL addendums for R_MICROMIPS_HI16 / R_MICROMIPS_LO16
-# relocations for a regular symbol.
-
-# RUN: llvm-mc -arch=mipsel -filetype=obj -mattr=micromips -o=%t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -d -mattr=micromips %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: T0:
-# CHECK-NEXT: 400180: a8 41 40 00 lui $8, 64
-# CHECK-NEXT: 400184: 08 31 c1 01 addiu $8, $8, 449
-# CHECK-NEXT: 400188: a8 41 41 00 lui $8, 65
-# CHECK-NEXT: 40018c: 08 31 bf 81 addiu $8, $8, -32321
-# CHECK-NEXT: 400190: a8 41 41 00 lui $8, 65
-# CHECK-NEXT: 400194: 08 31 40 82 addiu $8, $8, -32192
-# CHECK-NEXT: 400198: a8 41 42 00 lui $8, 66
-# CHECK-NEXT: 40019c: 08 31 c0 81 addiu $8, $8, -32320
-#
-# CHECK: T1:
-# CHECK-NEXT: 4001a0: a8 41 40 40 lui $8, 16448
-# CHECK-NEXT: 4001a4: 08 31 c0 01 addiu $8, $8, 448
-# CHECK-NEXT: 4001a8: a8 41 40 80 lui $8, 32832
-# CHECK-NEXT: 4001ac: 08 31 c0 01 addiu $8, $8, 448
-# CHECK-NEXT: 4001b0: a8 41 c1 80 lui $8, 32961
-# CHECK-NEXT: 4001b4: 08 31 40 82 addiu $8, $8, -32192
-# CHECK-NEXT: 4001b8: 00 00 00 00 nop
-# CHECK-NEXT: 4001bc: 00 00 00 00 nop
-#
-# CHECK: T2:
-# CHECK-NEXT: 4001c0: 00 00 00 00 nop
-# CHECK-NEXT: 4001c4: a8 41 40 00 lui $8, 64
-# CHECK-NEXT: 4001c8: a8 41 40 00 lui $8, 64
-# CHECK-NEXT: 4001cc: a8 41 41 00 lui $8, 65
-# CHECK-NEXT: 4001d0: a8 41 42 00 lui $8, 66
-# CHECK-NEXT: 4001d4: a8 41 40 40 lui $8, 16448
-# CHECK-NEXT: 4001d8: a8 41 40 80 lui $8, 32832
-# CHECK-NEXT: 4001dc: a8 41 c1 80 lui $8, 32961
-# CHECK-NEXT: 4001e0: 08 31 00 82 addiu $8, $8, -32256
-
- .section .text.1,"ax",@progbits
- .align 4
- .globl T0
-T0:
- lui $8, %hi(T2+1)
- addiu $8, $8, %lo(T2+1)
- lui $8, %hi(T2+0x7fff)
- addiu $8, $8, %lo(T2+0x7fff)
- lui $8, %hi(T2+0x8080)
- addiu $8, $8, %lo(T2+0x8080)
- lui $8, %hi(T2+0x18000)
- addiu $8, $8, %lo(T2+0x18000)
- .size T0, .-T0
-
- .section .text.2,"ax",@progbits
- .align 4
- .globl T1
-T1:
- lui $8, %hi(T2+0x40000000)
- addiu $8, $8, %lo(T2+0x40000000)
- lui $8, %hi(T2+0x80000000)
- addiu $8, $8, %lo(T2+0x80000000)
- lui $8, %hi(T2+0x80808080)
- addiu $8, $8, %lo(T2+0x80808080)
- .size T1, .-T1
-
- .section .text.3,"ax",@progbits
- .align 4
- .globl T2
-T2:
- nop
- lui $8, %hi(T0+0x1)
- lui $8, %hi(T0+0x7fff)
- lui $8, %hi(T0+0x8080)
- lui $8, %hi(T0+0x18000)
- lui $8, %hi(T0+0x40000000)
- lui $8, %hi(T0+0x80000000)
- lui $8, %hi(T0+0x80808080)
- addiu $8, $8, %lo(T0+0x80808080)
- .size T2, .-T2
diff --git a/test/old-elf/Mips/hilo16-9-micro.test b/test/old-elf/Mips/hilo16-9-micro.test
deleted file mode 100644
index 293e35f36cd5..000000000000
--- a/test/old-elf/Mips/hilo16-9-micro.test
+++ /dev/null
@@ -1,142 +0,0 @@
-# Check calculation of AHL addendums for R_MICROMIPS_HI16 / R_MICROMIPS_LO16
-# relocations for the _gp_disp symbol.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-objdump -s -t %t.so | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 0110 00000100 0000e08e 00000100 0000d60e
-# CHECK-NEXT: 0120 00000100 00004f0f 00000000 00000000
-# CHECK-NEXT: 0130 00000200 0000bf0e 00000140 0000378f
-# CHECK-NEXT: 0140 00000100 00000100 00000200 00000300
-# CHECK-NEXT: 0150 00000140 00001f8f
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00000110 g F .text 00000018 T0
-# CHECK: 00000130 g F .text 00000010 T1
-# CHECK: 00000140 g F .text 00000018 T2
-# CHECK: 00008ff0 g *ABS* 00000000 _gp_disp
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text.1
- Type: SHT_PROGBITS
- Content: "0000000000000100000000000000FF7F0000010000008080"
-# ^ %hi(gp+0x1) ^ %hi(gp+0x7fff) ^ %lo(gp+0x8080)
-# ^ %lo(gp+0x1) ^ %lo(gp+0x7fff)
-# ^ %hi(gp+0x8080)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text.1
- Type: SHT_REL
- Info: .text.1
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0x4
- Symbol: _gp_disp
- Type: R_MICROMIPS_LO16
- - Offset: 0x8
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0xC
- Symbol: _gp_disp
- Type: R_MICROMIPS_LO16
- - Offset: 0x10
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0x14
- Symbol: _gp_disp
- Type: R_MICROMIPS_LO16
-
-- Name: .text.2
- Type: SHT_PROGBITS
- Content: "00000200000000800000004000008000"
-# ^ %hi(gp+0x18000) ^ %lo(gp+0x40000080)
-# ^ %lo(gp+0x18000)
-# ^ %hi(gp+0x40000080)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text.2
- Type: SHT_REL
- Info: .text.2
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0x4
- Symbol: _gp_disp
- Type: R_MICROMIPS_LO16
- - Offset: 0x8
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0xC
- Symbol: _gp_disp
- Type: R_MICROMIPS_LO16
-
-- Name: .text.3
- Type: SHT_PROGBITS
- Content: "000000000000000000000100000002000000004000008000"
-# ^ %hi(gp+0x1) ^ %hi(gp+0x8080) ^ %lo(gp+0x40000080)
-# ^ %hi(gp+0x7fff) ^ %hi(gp+0x40000080)
-# ^ %hi(gp+0x18000)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text.3
- Type: SHT_REL
- Info: .text.3
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0x4
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0x8
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0xC
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0x10
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0x14
- Symbol: _gp_disp
- Type: R_MICROMIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text.1
- Type: STT_FUNC
- Value: 0
- Size: 24
- Other: [STO_MIPS_MICROMIPS]
- - Name: T1
- Section: .text.2
- Type: STT_FUNC
- Value: 0
- Size: 16
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
- Section: .text.3
- Type: STT_FUNC
- Value: 0
- Size: 24
- Other: [STO_MIPS_MICROMIPS]
- - Name: _gp_disp
diff --git a/test/old-elf/Mips/initfini-micro.test b/test/old-elf/Mips/initfini-micro.test
deleted file mode 100644
index ca2708f1bb29..000000000000
--- a/test/old-elf/Mips/initfini-micro.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Check that if _init/_fini symbols are microMIPS encoded, DT_INIT/DT_FINI tags
-# use adjusted values with set the last bit.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -symbols -dynamic-table %t.so | FileCheck %s
-
-# CHECK: Name: _init (1)
-# CHECK-NEXT: Value: 0xF5
-# CHECK: Name: _fini (7)
-# CHECK-NEXT: Value: 0xF9
-#
-# CHECK: 0x0000000C INIT 0xF5
-# CHECK: 0x0000000D FINI 0xF9
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x18
-
-Symbols:
- Global:
- - Name: _init
- Type: STT_FUNC
- Section: .text
- Value: 0x0
- Size: 0x4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: _fini
- Type: STT_FUNC
- Section: .text
- Value: 0x4
- Size: 0x4
- Other: [ STO_MIPS_MICROMIPS ]
-...
diff --git a/test/old-elf/Mips/interpreter-64.test b/test/old-elf/Mips/interpreter-64.test
deleted file mode 100644
index 7cfd0c51a3c4..000000000000
--- a/test/old-elf/Mips/interpreter-64.test
+++ /dev/null
@@ -1,26 +0,0 @@
-# Check program interpreter setup.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -e main -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .interp:
-# CHECK-NEXT: {{[0-9a-f]+}} 2f6c6962 36342f6c 642e736f 2e3100 /lib64/ld.so.1.
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64 ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x08
-
-Symbols:
- Global:
- - Name: main
- Section: .text
diff --git a/test/old-elf/Mips/interpreter-n32.test b/test/old-elf/Mips/interpreter-n32.test
deleted file mode 100644
index 7d17256ba43c..000000000000
--- a/test/old-elf/Mips/interpreter-n32.test
+++ /dev/null
@@ -1,27 +0,0 @@
-# Check program interpreter setup in case of N32 ABI.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .interp:
-# CHECK-NEXT: {{[0-9a-f ]+}} /lib32/ld.so.1.
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64, EF_MIPS_ABI2 ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 8
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
diff --git a/test/old-elf/Mips/interpreter.test b/test/old-elf/Mips/interpreter.test
deleted file mode 100644
index 4ae17b42df1c..000000000000
--- a/test/old-elf/Mips/interpreter.test
+++ /dev/null
@@ -1,26 +0,0 @@
-# Check program interpreter setup.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e main -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .interp:
-# CHECK-NEXT: {{[0-9a-f]+}} 2f6c6962 2f6c642e 736f2e31 00 /lib/ld.so.1.
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x04
-
-Symbols:
- Global:
- - Name: main
- Section: .text
diff --git a/test/old-elf/Mips/invalid-reginfo.test b/test/old-elf/Mips/invalid-reginfo.test
deleted file mode 100644
index 2856ecc92607..000000000000
--- a/test/old-elf/Mips/invalid-reginfo.test
+++ /dev/null
@@ -1,28 +0,0 @@
-# Check that LLD shows an error if .reginfo section has invalid size
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -o %t.exe %t.o 2>&1 | FileCheck %s
-
-# CHECK: Invalid size of MIPS_REGINFO section
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x01
- Size: 0x25
-Symbols:
- Global:
- - Name: main
- Section: .text
diff --git a/test/old-elf/Mips/jalx-align-err.test b/test/old-elf/Mips/jalx-align-err.test
deleted file mode 100644
index 8fc5310bbad8..000000000000
--- a/test/old-elf/Mips/jalx-align-err.test
+++ /dev/null
@@ -1,46 +0,0 @@
-# Check that LLD shows an error if jalx target value is not word-aligned.
-
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t-exe %t-obj 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: The jalx target 0x{{[0-9a-f]+}} is not word-aligned
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 6
- Size: 2
diff --git a/test/old-elf/Mips/jalx-jalr.test b/test/old-elf/Mips/jalx-jalr.test
deleted file mode 100644
index d02e9d7c2bac..000000000000
--- a/test/old-elf/Mips/jalx-jalr.test
+++ /dev/null
@@ -1,47 +0,0 @@
-# Check that R_MIPS_JALR relocation does not affect code in case of cross jump.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9a-f]+}} 08002003 00000000
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_MICROMIPS, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Content: "0800200300000000"
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: M1
- Type: R_MIPS_JALR
-
-Symbols:
- Global:
- - Name: __start
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
- - Name: M1
- Type: STT_FUNC
- Section: .text
- Value: 4
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
diff --git a/test/old-elf/Mips/jalx.test b/test/old-elf/Mips/jalx.test
deleted file mode 100644
index 60d6ea71193c..000000000000
--- a/test/old-elf/Mips/jalx.test
+++ /dev/null
@@ -1,71 +0,0 @@
-# Check jal => jalx conversion in case of mixed microMIPS and regular code.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T1 -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RAW %s
-# RUN: llvm-nm %t.exe | FileCheck -check-prefix=SYM %s
-
-# RAW: Contents of section .text:
-# RAW-NEXT: 400130 00000000 4c001074 10f04d00 4e001074
-
-# SYM: 00400138 T M1
-# SYM: 00400130 T M2
-# SYM: 0040013c T T1
-# SYM: 00400134 T T2
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_MICROMIPS, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Content: "000000000000000c00f400000000000c"
-# ^ M2 ^ T2 ^ M1 ^ T1
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 4
- Symbol: M2
- Type: R_MIPS_26
- - Offset: 8
- Symbol: T2
- Type: R_MICROMIPS_26_S1
- - Offset: 12
- Symbol: M1
- Type: R_MIPS_26
-
-Symbols:
- Global:
- - Name: M2
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Value: 4
- Size: 4
- - Name: M1
- Type: STT_FUNC
- Section: .text
- Value: 8
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 12
- Size: 4
diff --git a/test/old-elf/Mips/jump-fix-err.test b/test/old-elf/Mips/jump-fix-err.test
deleted file mode 100644
index 0e5a5298a731..000000000000
--- a/test/old-elf/Mips/jump-fix-err.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Check that LLD shows an error in case
-# of replacing an unknown unstruction by jalx.
-
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: not lld -flavor old-gnu -target mipsel -o %t-exe %t-obj 2>&1 | FileCheck %s
-
-# CHECK: Unsupported jump opcode (0x0) for ISA modes cross call
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T0
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Type: STT_FUNC
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
diff --git a/test/old-elf/Mips/la25-stub-be.test b/test/old-elf/Mips/la25-stub-be.test
deleted file mode 100644
index 9527e7a80644..000000000000
--- a/test/old-elf/Mips/la25-stub-be.test
+++ /dev/null
@@ -1,113 +0,0 @@
-# REQUIRES: mips
-
-# Check LA25 stubs creation in the big-endian case.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-npic.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-pic.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-main.o
-# RUN: lld -flavor old-gnu -target mips -o %t.exe %t-npic.o %t-pic.o %t-main.o
-
-# RUN: llvm-objdump -disassemble %t.exe | FileCheck %s
-
-# CHECK: 400170: 3c 19 00 40 lui $25, 64
-# CHECK-NEXT: 400174: 08 10 00 50 j 4194624
-# CHECK-NEXT: 400178: 27 39 01 40 addiu $25, $25, 320
-# CHECK-NEXT: 40017c: 00 00 00 00 nop
-
-# npic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1N
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_PIC]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# main.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 40
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 8
- Symbol: .text
- Type: R_MIPS_26
- - Offset: 16
- Symbol: __start
- Type: R_MIPS_26
- - Offset: 24
- Symbol: T1N
- Type: R_MIPS_26
- - Offset: 32
- Symbol: T1
- Type: R_MIPS_26
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 16
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: __start
- Section: .text
- - Name: T1
- - Name: T1N
-...
diff --git a/test/old-elf/Mips/la25-stub-micro-be.test b/test/old-elf/Mips/la25-stub-micro-be.test
deleted file mode 100644
index 0bea3e6ac8b0..000000000000
--- a/test/old-elf/Mips/la25-stub-micro-be.test
+++ /dev/null
@@ -1,121 +0,0 @@
-# REQUIRES: mips
-
-# Check LA25 stubs creation in the big-endian case.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-npic.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-pic.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-main.o
-# RUN: lld -flavor old-gnu -target mips -o %t.exe %t-npic.o %t-pic.o %t-main.o
-
-# RUN: llvm-objdump -disassemble -mattr=micromips %t.exe | FileCheck %s
-
-# CHECK: 400170: 41 be 00 40 lui $fp, 64
-# CHECK-NEXT: 400174: d4 20 00 a0 j 4194624
-# CHECK-NEXT: 400178: 33 39 01 41 addiu $25, $25, 321
-# CHECK-NEXT: 40017c: 00 00 00 00 nop
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_CPIC, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1N
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
-
-# main.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_CPIC, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Content: '0000000000000000f400000000000000f400000000000000f400000000000000f400000000000000'
-# jal loc jal glob jal T1N jal T1
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 8
- Symbol: .text
- Type: R_MICROMIPS_26_S1
- - Offset: 16
- Symbol: glob
- Type: R_MICROMIPS_26_S1
- - Offset: 24
- Symbol: T1N
- Type: R_MICROMIPS_26_S1
- - Offset: 32
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 16
- Size: 24
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: __start
- Section: .text
- Size: 16
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- - Name: T1N
-...
diff --git a/test/old-elf/Mips/la25-stub-micro.test b/test/old-elf/Mips/la25-stub-micro.test
deleted file mode 100644
index c01da5908829..000000000000
--- a/test/old-elf/Mips/la25-stub-micro.test
+++ /dev/null
@@ -1,136 +0,0 @@
-# Check microMIPS LA25 stubs creation when PIC code
-# is called from non-PIC routines.
-
-# Build executable from pic and non-pic code.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-npic.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-pic.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-main.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe \
-# RUN: %t-npic.o %t-pic.o %t-main.o
-
-# RUN: llvm-nm %t.exe | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=ASM %s
-
-# SYM: 00400140 T T1
-# SYM: 00400130 T T1N
-# SYM: 00400144 T glob
-# SYM: 00400154 t loc
-
-# ASM: Contents of section .text:
-# ASM-NEXT: 400130 00000000 00000000 00000000 00000000
-# ASM-NEXT: 400140 00000000 00000000 00000000 10f05100
-# 0x100055 << 2 == 0x400154 (jalx glob) --^
-# ASM-NEXT: 400150 00000000 20f4a200 00000000 20f49800
-# ^-- 0x100055 << 2 == 0x400154 (jal glob)
-# 0x10004c << 2 == 0x400130 (jal T1N) --^
-# ASM-NEXT: 400160 00000000 20f4b800 00000000 00000000
-# ^-- 0x100054 << 2 == 0x400170 (jal T1 stub)
-# ASM-NEXT: 400170 b9414000 20d4a000 39334101 00000000
-# ^-- j 0x400140 (T1)
-
-# npic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_CPIC, EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x04
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1N
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x04
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
-
-# main.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_CPIC, EF_MIPS_MICROMIPS ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: '000000000000000000f400000000000000f400000000000000f400000000000000f4000000000000'
-# jal loc jal glob jal T1N jal T1
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x08
- Symbol: .text
- Type: R_MICROMIPS_26_S1
- - Offset: 0x10
- Symbol: glob
- Type: R_MICROMIPS_26_S1
- - Offset: 0x18
- Symbol: T1N
- Type: R_MICROMIPS_26_S1
- - Offset: 0x20
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 0x10
- Size: 0x18
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- Size: 0x10
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- - Name: T1N
-...
diff --git a/test/old-elf/Mips/la25-stub-npic-01.test b/test/old-elf/Mips/la25-stub-npic-01.test
deleted file mode 100644
index 9ff6af06cb2b..000000000000
--- a/test/old-elf/Mips/la25-stub-npic-01.test
+++ /dev/null
@@ -1,153 +0,0 @@
-# Check that LA25 stubs are created for branch relocations
-# when a PIC function is called from non-pic code.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-pic.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-reg.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-micro.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe \
-# RUN: %t-reg.o %t-micro.o %t-pic.o
-
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK-NOT: Contents of section .plt:
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400130 5c001000 0f000000 0e000000 0d000000
-# ^ T0 ^ .pic.T1 (0x400170)
-# ^ 0x400134 + 0x3c = 0x400170
-# ^ ...
-# CHECK-NEXT: 400140 2000c000 1e000000 1c000000 00001a00
-# ^ T3 ^ .pic.T2
-# ^ ...
-# CHECK-NEXT: 400150 00000c00 00000000 00000000 00000000
-# CHECK-NEXT: 400160 00000000 00000000 00000000 00000000
-# ^ T1 ^ T2
-# CHECK-NEXT: 400170 4000193c 58001008 60013927 00000000
-# ^ .pic.T1
-# CHECK-NEXT: 400180 b9414000 20d4b200 39336501 00000000
-# ^ .pic.T2
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400130 g F .text 00000010 T0
-# CHECK: 00400140 g F .text 00000014 T3
-# CHECK: 00400160 g F .text 00000004 T1
-# CHECK: 00400164 g F .text 00000004 T2
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32,
- EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
-
-# reg.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 16
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_26
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_PC16
- - Offset: 8
- Symbol: T1
- Type: R_MIPS_PC21_S2
- - Offset: 12
- Symbol: T1
- Type: R_MIPS_PC26_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Size: 16
- - Name: T1
-
-# micro.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 20
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T2
- Type: R_MICROMIPS_26_S1
- - Offset: 4
- Symbol: T2
- Type: R_MICROMIPS_PC7_S1
- - Offset: 8
- Symbol: T2
- Type: R_MICROMIPS_PC10_S1
- - Offset: 12
- Symbol: T2
- Type: R_MICROMIPS_PC16_S1
- - Offset: 16
- Symbol: T2
- Type: R_MICROMIPS_PC23_S2
-
-Symbols:
- Global:
- - Name: T3
- Section: .text
- Size: 20
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
-...
diff --git a/test/old-elf/Mips/la25-stub-npic-02.test b/test/old-elf/Mips/la25-stub-npic-02.test
deleted file mode 100644
index 4f2eb14d8c92..000000000000
--- a/test/old-elf/Mips/la25-stub-npic-02.test
+++ /dev/null
@@ -1,123 +0,0 @@
-# Check that LA25 stubs are created for branch relocations
-# when a PIC function is defined in a non-PIC file and
-# is called from non-pic code.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t1.o %t2.o
-
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK-NOT: Contents of section .plt:
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400130 00000000 00000000 58001000 09000000
-# ^ T1 ^ T2 ^ .pic.T1 (0x400160)
-# CHECK-NEXT: 400140 08000000 07000000 2000b800 12000000
-# ^ .pic.T2 (0x400170)
-# CHECK-NEXT: 400150 10000000 00000e00 00000600 00000000
-# CHECK-NEXT: 400160 4000193c 4c001008 30013927 00000000
-# ^ .pic.T1
-# CHECK-NEXT: 400170 b9414000 20d49a00 39333501 00000000
-# ^ .pic.T2
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400130 g F .text 00000004 T1
-# CHECK: 00400134 g F .text 00000004 T2
-# CHECK: 00400138 g F .text 00000010 T0
-# CHECK: 00400148 g F .text 00000014 T3
-
-# 1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- Other: [STO_MIPS_PIC]
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
- Other: [STO_MIPS_MICROMIPS, STO_MIPS_PIC]
-
-# 2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 36
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_26
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_PC16
- - Offset: 8
- Symbol: T1
- Type: R_MIPS_PC21_S2
- - Offset: 12
- Symbol: T1
- Type: R_MIPS_PC26_S2
- - Offset: 16
- Symbol: T2
- Type: R_MICROMIPS_26_S1
- - Offset: 20
- Symbol: T2
- Type: R_MICROMIPS_PC7_S1
- - Offset: 24
- Symbol: T2
- Type: R_MICROMIPS_PC10_S1
- - Offset: 28
- Symbol: T2
- Type: R_MICROMIPS_PC16_S1
- - Offset: 32
- Symbol: T2
- Type: R_MICROMIPS_PC23_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Value: 0
- Size: 16
- - Name: T3
- Section: .text
- Value: 16
- Size: 20
- Other: [STO_MIPS_MICROMIPS]
- - Name: T1
- - Name: T2
-...
diff --git a/test/old-elf/Mips/la25-stub-npic-shared.test b/test/old-elf/Mips/la25-stub-npic-shared.test
deleted file mode 100644
index 72bac30f86ad..000000000000
--- a/test/old-elf/Mips/la25-stub-npic-shared.test
+++ /dev/null
@@ -1,152 +0,0 @@
-# Check that PLT entries are created for branch relocations
-# when a PIC shared library function is called from non-pic code.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-pic.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-reg.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-micro.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-pic.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-reg.o %t-micro.o %t.so
-
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .plt:
-# CHECK-NEXT: 400190 40001c3c 0020998f 00209c27 23c01c03
-# CHECK-NEXT: 4001a0 2578e003 82c01800 09f82003 feff1827
-# CHECK-NEXT: 4001b0 40000f3c 0820f98d 08002003 0820f825
-# ^ PLT.T1
-# CHECK-NEXT: 4001c0 00799307 22ff0000 9945020f
-# ^ PLT.T2
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 4001cc 6c001000 f8ff0000 f7ff1f00 f6ffff03
-# ^ T0 ^ PLT.T1 (0x4001b0)
-# ^ 0x4001d0 -32 = 0x4001b0
-# ^ ...
-# CHECK-NEXT: 4001dc 2000e000 70000000 ee030000 0000ecff
-# ^ T3 ^ PLT.T2
-# ^ ...
-# CHECK-NEXT: 4001ec 7f00f5ff
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 004001cc g F .text 00000010 T0
-# CHECK: 004001dc g F .text 00000014 T3
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32,
- EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
-
-# reg.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 16
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_26
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_PC16
- - Offset: 8
- Symbol: T1
- Type: R_MIPS_PC21_S2
- - Offset: 12
- Symbol: T1
- Type: R_MIPS_PC26_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Size: 16
- - Name: T1
-
-# micro.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 20
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T2
- Type: R_MICROMIPS_26_S1
- - Offset: 4
- Symbol: T2
- Type: R_MICROMIPS_PC7_S1
- - Offset: 8
- Symbol: T2
- Type: R_MICROMIPS_PC10_S1
- - Offset: 12
- Symbol: T2
- Type: R_MICROMIPS_PC16_S1
- - Offset: 16
- Symbol: T2
- Type: R_MICROMIPS_PC23_S2
-
-Symbols:
- Global:
- - Name: T3
- Section: .text
- Size: 20
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
-...
diff --git a/test/old-elf/Mips/la25-stub-pic.test b/test/old-elf/Mips/la25-stub-pic.test
deleted file mode 100644
index 8db88404aaef..000000000000
--- a/test/old-elf/Mips/la25-stub-pic.test
+++ /dev/null
@@ -1,144 +0,0 @@
-# Check that we do not create LA26 stubs and PLT entries
-# when a PIC function is called from PIC code.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-reg.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-micro.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o %t-reg.o %t-micro.o
-
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK-NOT: Contents of section .plt:
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400130 00000000 00000000 4c001000 fdff0000
-# ^ T1 ^ T2 ^ T1 (0x400130)
-# ^ 0x40013c - 12 = 0x0x400130
-# CHECK-NEXT: 400140 fcff1f00 fbffff03 20009a00 74000000
-# ^ T2 (0x400134)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400130 g F .text 00000004 T1
-# CHECK: 00400134 g F .text 00000004 T2
-# CHECK: 00400138 g F .text 00000010 T0
-# CHECK: 00400148 g F .text 00000014 T3
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32,
- EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
-
-# reg.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_PIC]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 16
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_26
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_PC16
- - Offset: 8
- Symbol: T1
- Type: R_MIPS_PC21_S2
- - Offset: 12
- Symbol: T1
- Type: R_MIPS_PC26_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Size: 16
- - Name: T1
-
-# micro.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32,
- EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 20
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T2
- Type: R_MICROMIPS_26_S1
- - Offset: 4
- Symbol: T2
- Type: R_MICROMIPS_PC7_S1
- - Offset: 8
- Symbol: T2
- Type: R_MICROMIPS_PC10_S1
- - Offset: 12
- Symbol: T2
- Type: R_MICROMIPS_PC16_S1
- - Offset: 16
- Symbol: T2
- Type: R_MICROMIPS_PC23_S2
-
-Symbols:
- Global:
- - Name: T3
- Section: .text
- Size: 20
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
-...
diff --git a/test/old-elf/Mips/la25-stub.test b/test/old-elf/Mips/la25-stub.test
deleted file mode 100644
index 4df7f85e8c89..000000000000
--- a/test/old-elf/Mips/la25-stub.test
+++ /dev/null
@@ -1,133 +0,0 @@
-# Check LA25 stubs creation when PIC code is called from non-PIC routines.
-
-# Build executable from pic and non-pic code.
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-npic.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-pic.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-main.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe \
-# RUN: %t-npic.o %t-pic.o %t-main.o
-
-# RUN: llvm-readobj -t %t.exe | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=ASM %s
-
-# SYM: Name: loc (13)
-# SYM-NEXT: Value: 0x400154
-# SYM: Name: T1N (1)
-# SYM-NEXT: Value: 0x400130
-# SYM: Name: T1 (5)
-# SYM-NEXT: Value: 0x400140
-# SYM: Name: glob (8)
-# SYM-NEXT: Value: 0x400144
-
-# ASM: Contents of section .text:
-# ASM-NEXT: 400130 00000000 00000000 00000000 00000000
-# ASM-NEXT: 400140 00000000 00000000 00000000 51001000
-# 0x100051 << 2 == 0x400144 (glob) --^
-# ASM-NEXT: 400150 00000000 51001000 00000000 4c001000
-# ^-- 0x100051 << 2 == 0x400144 (glob)
-# 0x100044 << 2 == 0x400110 (T1N) --^
-# ASM-NEXT: 400160 00000000 5c001000 00000000 00000000
-# ^-- 0x10005c << 2 == 0x400170 (T1 stub)
-# ASM-NEXT: 400170 4000193c 50001008 40013927 00000000
-# ^-- j 0x400140 (T1)
-
-# npic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x04
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1N
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# pic.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC, EF_MIPS_PIC ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x04
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# main.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32, EF_MIPS_CPIC ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x28
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x08
- Symbol: .text
- Type: R_MIPS_26
- Addend: 0
- - Offset: 0x10
- Symbol: glob
- Type: R_MIPS_26
- Addend: 0
- - Offset: 0x18
- Symbol: T1N
- Type: R_MIPS_26
- Addend: 0
- - Offset: 0x20
- Symbol: T1
- Type: R_MIPS_26
- Addend: 0
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 0x10
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- - Name: T1
- - Name: T1N
-...
diff --git a/test/old-elf/Mips/mips-options-01.test b/test/old-elf/Mips/mips-options-01.test
deleted file mode 100644
index 8f2e63ca3b5f..000000000000
--- a/test/old-elf/Mips/mips-options-01.test
+++ /dev/null
@@ -1,34 +0,0 @@
-# Check that LLD does not write a .MIPS.options section if input
-# object file does not contain such section.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t.o
-# RUN: llvm-readobj -s -dynamic-table %t.so | FileCheck %s
-
-# CHECK: Sections [
-# CHECK-NOT: Name: .MIPS.options
-
-# CHECK: DynamicSection [
-# CHECK-NOT: 0x{{[0-9A-F]+}} MIPS_OPTIONS
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/mips-options-02.test b/test/old-elf/Mips/mips-options-02.test
deleted file mode 100644
index a5f19e55735f..000000000000
--- a/test/old-elf/Mips/mips-options-02.test
+++ /dev/null
@@ -1,104 +0,0 @@
-# Check merging input .MIPS.options sections.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t1.o %t2.o
-# RUN: llvm-readobj -s -dynamic-table %t.so | FileCheck -check-prefix=SEC %s
-# RUN: llvm-objdump -s -t %t.so | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -program-headers %t.so | FileCheck -check-prefix=PHDR %s
-
-# SEC: Index: 1
-# SEC-NEXT: Name: .MIPS.options (1)
-# SEC-NEXT: Type: SHT_MIPS_OPTIONS (0x7000000D)
-# SEC-NEXT: Flags [ (0x8000002)
-# SEC-NEXT: SHF_ALLOC (0x2)
-# SEC-NEXT: SHF_MIPS_NOSTRIP (0x8000000)
-# SEC-NEXT: ]
-# SEC-NEXT: Address: 0x[[OPT_ADDR:[0-9A-F]+]]
-# SEC-NEXT: Offset: {{[0-9A-F]+}}
-# SEC-NEXT: Size: 40
-# SEC-NEXT: Link: 0
-# SEC-NEXT: Info: 0
-# SEC-NEXT: AddressAlignment: 8
-# SEC-NEXT: EntrySize: 1
-
-# SEC: DynamicSection [
-# SEC: 0x{{[0-9A-F]+}} MIPS_OPTIONS 0x[[OPT_ADDR]]
-
-# RAW: Contents of section .MIPS.options:
-# RAW-NEXT: {{[0-9a-f]+}} 01280000 00000000 f0000001 00000000
-# RAW-NEXT: {{[0-9a-f]+}} e0000002 d0000003 b0000004 c0000005
-# RAW-NEXT: {{[0-9a-f]+}} f08f0000 00000000
-
-# RAW: SYMBOL TABLE:
-# RAW: 0000000000008ff0 g *ABS* 00000000 _gp
-
-# Check that %t.so contains only two PT_LOAD segments
-# PHDR: ProgramHeaders
-# PHDR: Type: PT_LOAD
-# PHDR: Type: PT_LOAD
-# PHDR-NOT: Type: PT_LOAD
-# PHDR: Type: PT_DYNAMIC
-
-# t1.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 8
-# v ODK_NULL 0x18 bytes long v ODK_REGINFO
- Content: "0018000000000000000000000000000000000000000000000128000000000000F000000000000000E0000000D0000000B0000000C00000000010000000000000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t2.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 8
-# v ODK_NULL 0x18 bytes long v ODK_REGINFO
- Content: "00180000000000000000000000000000000000000000000001280000000000000000000100000000000000020000000300000004000000050000010000000000"
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/mips-options-03.test b/test/old-elf/Mips/mips-options-03.test
deleted file mode 100644
index a0dea5709b6f..000000000000
--- a/test/old-elf/Mips/mips-options-03.test
+++ /dev/null
@@ -1,41 +0,0 @@
-# Check handling a zero-filled input .MIPS.options section.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t.o
-# RUN: llvm-objdump -s -t %t.so | FileCheck %s
-
-# CHECK: Contents of section .MIPS.options:
-# CHECK-NEXT: {{[0-9a-f]+}} 01280000 00000000 00000000 00000000
-# CHECK-NEXT: {{[0-9a-f]+}} 00000000 00000000 00000000 00000000
-# CHECK-NEXT: {{[0-9a-f]+}} f08f0000 00000000
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00008ff0 g *ABS* 00000000 _gp
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 8
- Content: "01280000000000000000000000000000000000000000000000000000000000000000000000000000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/mips-options-04.test b/test/old-elf/Mips/mips-options-04.test
deleted file mode 100644
index 5df94aae9257..000000000000
--- a/test/old-elf/Mips/mips-options-04.test
+++ /dev/null
@@ -1,77 +0,0 @@
-# Check that .MIPS.options sections from shared libraries do not affect
-# output .MIPS.options section content.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t.so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t.exe.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t.so %t.exe.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .MIPS.options:
-# CHECK-NEXT: {{[0-9a-f]+}} 01280000 00000000 44444444 00000000
-# CHECK-NEXT: {{[0-9a-f]+}} 44444444 44444444 44444444 44444444
-# CHECK-NEXT: {{[0-9a-f]+}} f08f0020 01000000
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 20008ff0 g *ABS* 00000000 _gp
-
-# t.so.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 8
- Content: "01280000000000001111111100000000111111111111111111111111111111110010000000000000"
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t.exe.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 8
- Content: "01280000000000004444444400000000444444444444444444444444444444440010000000000000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/mips-options-05.test b/test/old-elf/Mips/mips-options-05.test
deleted file mode 100644
index f7e9728b3cf4..000000000000
--- a/test/old-elf/Mips/mips-options-05.test
+++ /dev/null
@@ -1,119 +0,0 @@
-# Check that .MIPS.options section gets register usage mask from "used" files
-# only. In this test case we take only t2.o from liboptions.a and should not
-# add register usage masks from t1.o to the output .MIPS.options section.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: llvm-ar q %T/liboptions.a %t1.o %t2.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t3.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t3.o -L%T -loptions
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .MIPS.options:
-# CHECK-NEXT: {{[0-9a-f]+}} 01280000 00000000 66666666 00000000
-# CHECK-NEXT: {{[0-9a-f]+}} 66666666 66666666 66666666 66666666
-# CHECK-NEXT: {{[0-9a-f]+}} f08f0020 01000000
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 20008ff0 g *ABS* 00000000 _gp
-
-# t1.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 8
- Content: "01280000000000001111111100000000111111111111111111111111111111110010000000000000"
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t2.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 8
- Content: "01280000000000002222222200000000222222222222222222222222222222220010000000000000"
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t3.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T2
- Type: R_MIPS_32
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 8
- Content: "01280000000000004444444400000000444444444444444444444444444444440010000000000000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T2
-...
diff --git a/test/old-elf/Mips/mips-options-gp0.test b/test/old-elf/Mips/mips-options-gp0.test
deleted file mode 100644
index 73e578347f2c..000000000000
--- a/test/old-elf/Mips/mips-options-gp0.test
+++ /dev/null
@@ -1,77 +0,0 @@
-# Check reading GP0 value from .MIPS.options section
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -e G1 -shared -o %t.so %t.o
-# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=SEC %s
-
-# SYM: Name: L1
-# SYM-NEXT: Value: 0x15C
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Local (0x0)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x5)
-
-# SYM: Name: _gp
-# SYM-NEXT: Value: 0x8FF0
-# SYM-NEXT: Size: 0
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Object (0x1)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: Absolute (0xFFF1)
-
-# 0xffff816c == 0x0 (addend) + 0x015C (L1) + 0x1000 (GP0) - 0x8ff0 (_gp)
-# SEC: Contents of section .rodata:
-# SEC-NEXT: {{[0-9a-f]+}} 6c81ffff 00000000 00000000 00000000
-
-!ELF
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64R2 ]
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
-
-- Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 16
-
-- Name: .rel.rodata
- Type: SHT_RELA
- Link: .symtab
- Info: .rodata
- AddressAlign: 0x04
- Relocations:
- - Offset: 0
- Symbol: L1
- Type: R_MIPS_GPREL32
-
-- Name: .MIPS.options
- Type: SHT_MIPS_OPTIONS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x01
- Content: "012800000000000000000000000000000000000000000000000000000000000000100000"
-
-Symbols:
- Local:
- - Name: L1
- Section: .text
- Value: 0x00
- Size: 0x04
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
- Global:
- - Name: G1
- Section: .text
- Value: 0x04
- Size: 0x04
diff --git a/test/old-elf/Mips/n32-rela-chain.test b/test/old-elf/Mips/n32-rela-chain.test
deleted file mode 100644
index 9569eb7c5855..000000000000
--- a/test/old-elf/Mips/n32-rela-chain.test
+++ /dev/null
@@ -1,68 +0,0 @@
-# Check grouping of multiple consecutive relocations in case of N32
-# and 64-bit MIPS ABIs.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 10000130 00001001 00002004
-
-# CHECK: 10002000 l .data 00000004 D0
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64, EF_MIPS_ABI2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 8
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: D0
- Type: R_MIPS_32
- Addend: 0x10000
- - Offset: 0
- Symbol: D0
- Type: R_MIPS_HI16
- - Offset: 4
- Symbol: D0
- Type: R_MIPS_32
- Addend: 4
- - Offset: 4
- Symbol: D0
- Type: R_MIPS_LO16
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Local:
- - Name: D0
- Type: STT_FUNC
- Section: .data
- Value: 0
- Size: 4
- Global:
- - Name: __start
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 8
-...
diff --git a/test/old-elf/Mips/n64-rel-chain.test b/test/old-elf/Mips/n64-rel-chain.test
deleted file mode 100644
index 3797c4321701..000000000000
--- a/test/old-elf/Mips/n64-rel-chain.test
+++ /dev/null
@@ -1,204 +0,0 @@
-# Check handling MIPS N64 ABI relocation "chains".
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -s -t -dt -mips-plt-got %t.exe | \
-# RUN: FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RAW %s
-
-# SYM: Section {
-# SYM: Index: 6
-# SYM-NEXT: Name: .rodata
-# SYM-NEXT: Type: SHT_PROGBITS
-# SYM-NEXT: Flags [
-# SYM-NEXT: SHF_ALLOC
-# SYM-NEXT: ]
-# SYM-NEXT: Address: 0x120000230
-#
-# SYM: Symbol {
-# SYM: Name: LT1
-# SYM-NEXT: Value: 0x120000210
-# SYM-NEXT: Size: 16
-# SYM-NEXT: Binding: Global
-# SYM-NEXT: Type: Function
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text
-# SYM-NEXT: }
-# SYM: Symbol {
-# SYM: Name: T0
-# SYM-NEXT: Value: 0x120000220
-# SYM-NEXT: Size: 16
-# SYM-NEXT: Binding: Global
-# SYM-NEXT: Type: Function
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text
-# SYM-NEXT: }
-# SYM: Symbol {
-# SYM: Name: T1@
-# SYM-NEXT: Value: 0x0
-# SYM-NEXT: Size: 0
-# SYM-NEXT: Binding: Global
-# SYM-NEXT: Type: Function
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: Undefined
-# SYM-NEXT: }
-#
-# SYM: Canonical gp value: 0x120008FF0
-# SYM: Local entries [
-# SYM-NEXT: Entry {
-# SYM-NEXT: Address: 0x{{[0-9A-F]+}}
-# SYM-NEXT: Access: -32736
-# SYM-NEXT: Initial: 0x120000000
-# SYM-NEXT: }
-# SYM-NEXT: ]
-# SYM-NEXT: Global entries [
-# SYM-NEXT: Entry {
-# SYM-NEXT: Address: 0x{{[0-9A-F]+}}
-# SYM-NEXT: Access: -32728
-# SYM-NEXT: Initial: 0x0
-# SYM-NEXT: Value: 0x0
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Section: Undefined (0x0)
-# SYM-NEXT: Name: T1@ (1)
-# SYM-NEXT: }
-# SYM-NEXT: ]
-
-# RAW: Contents of section .text:
-# RAW-NEXT: 120000210 01000000 00000000 e08d0000 00000000
-# ^
-# S - GP = 0x120000210 - 0x120008ff0 = -36320
-# S - A = 0 - (-36320) = 36320
-# (AHL + S + 0x8000) >> 16 = 1
-# ^
-# S - GP = 0x120000210 - 0x120008ff0 = -36320
-# S - A = 0 - (-36320) = 36320
-# AHL + S = 0x8DE0
-# RAW-NEXT: 120000220 20800000 38020000 28800000 00000000
-# ^ 0x8020 = -32736 GOT
-# ^ (0x120000230 + 8 - page) = 0x238
-# ^ 0x8028 = -32728
-# RAW: Contents of section .pdr:
-# RAW-NEXT: 0000 10020020 20020020
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 8
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
-
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 8
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 32
-
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 8
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: LT1
- Type: R_MIPS_GPREL16
- Type2: R_MIPS_SUB
- Type3: R_MIPS_HI16
- - Offset: 0x08
- Symbol: LT1
- Type: R_MIPS_GPREL16
- Type2: R_MIPS_SUB
- Type3: R_MIPS_LO16
- - Offset: 0x10
- Symbol: .rodata
- Type: R_MIPS_GOT_PAGE
- Addend: 8
- - Offset: 0x14
- Symbol: .rodata
- Type: R_MIPS_GOT_OFST
- Addend: 8
- - Offset: 0x18
- Symbol: T1
- Type: R_MIPS_CALL16
-
- - Name: .pdr
- Type: SHT_PROGBITS
- AddressAlign: 4
- Size: 8
-
- - Name: .rela.pdr
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 8
- Info: .pdr
- Relocations:
- - Offset: 0x00
- Symbol: LT1
- Type: R_MIPS_32
- - Offset: 0x04
- Symbol: T0
- Type: R_MIPS_32
-
- - Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 16
- Size: 16
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
- - Name: .pdr
- Type: STT_SECTION
- Section: .pdr
-
- Global:
- - Name: LT1
- Type: STT_FUNC
- Section: .text
- Value: 0x00
- Size: 0x10
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0x10
- Size: 0x10
- - Name: T1
-...
diff --git a/test/old-elf/Mips/n64-rel-shift.test b/test/old-elf/Mips/n64-rel-shift.test
deleted file mode 100644
index 31a780beb998..000000000000
--- a/test/old-elf/Mips/n64-rel-shift.test
+++ /dev/null
@@ -1,48 +0,0 @@
-# Check that LLD shift right relocation result after calculation
-# each relocations in N64 relocation chain.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t.o
-# RUN: llvm-objdump -s %t.so | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9a-f]+}} 00000000 01000000 00000000 00000000
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 16
-
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 8
- Info: .text
- Relocations:
- - Offset: 4
- Symbol: T1
- Addend: 8
- Type: R_MIPS_PC19_S2
- Type2: R_MIPS_64
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 8
- - Name: bar
- Type: STT_FUNC
- Section: .text
- Value: 8
- Size: 8
diff --git a/test/old-elf/Mips/opt-emulation.test b/test/old-elf/Mips/opt-emulation.test
deleted file mode 100644
index a48b49bfaa02..000000000000
--- a/test/old-elf/Mips/opt-emulation.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# Check MIPS specific arguments of the -m command line option.
-
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel -m elf32ltsmip -o %t-exe %t-obj
-# RUN: llvm-readobj -file-headers %t-exe | FileCheck -check-prefix=LE-O32 %s
-# RUN: lld -flavor old-gnu -target mipsel -melf32ltsmip -o %t-exe %t-obj
-# RUN: llvm-readobj -file-headers %t-exe | FileCheck -check-prefix=LE-O32 %s
-
-# LE-O32: Class: 32-bit (0x1)
-# LE-O32: DataEncoding: LittleEndian (0x1)
-# LE-O32: FileVersion: 1
-# LE-O32: OS/ABI: SystemV (0x0)
-# LE-O32: ABIVersion: 1
-# LE-O32: Machine: EM_MIPS (0x8)
-# LE-O32: Version: 1
-# LE-O32: Flags [ (0x70001005)
-# LE-O32-NEXT: EF_MIPS_ABI_O32 (0x1000)
-# LE-O32-NEXT: EF_MIPS_ARCH_32R2 (0x70000000)
-# LE-O32-NEXT: EF_MIPS_CPIC (0x4)
-# LE-O32-NEXT: EF_MIPS_NOREORDER (0x1)
-# LE-O32-NEXT: ]
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0x0
- Size: 4
diff --git a/test/old-elf/Mips/pc23-range.test b/test/old-elf/Mips/pc23-range.test
deleted file mode 100644
index 89e9ab7bb73f..000000000000
--- a/test/old-elf/Mips/pc23-range.test
+++ /dev/null
@@ -1,54 +0,0 @@
-# Check that LLD shows an error if ADDIUPC immediate is out of range.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -o %t.exe %t.o 2>&1 | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}}: reference from __start+4 to T0+4 of type 173 (R_MICROMIPS_PC23_S2)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000080780100"
-# ^ PC23: 1 << 2 = 4 => T0 + 4 - 4 = T0
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x4000000
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 4
- Symbol: T0
- Type: R_MICROMIPS_PC23_S2
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Type: STT_FUNC
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: TZ
- Section: .data
- Type: STT_FUNC
- Value: 0
- Size: 0x2000000
- - Name: T0
- Section: .data
- Type: STT_FUNC
- Value: 0x2000000
- Size: 4
diff --git a/test/old-elf/Mips/plt-entry-mixed-1.test b/test/old-elf/Mips/plt-entry-mixed-1.test
deleted file mode 100644
index e05eec4c8109..000000000000
--- a/test/old-elf/Mips/plt-entry-mixed-1.test
+++ /dev/null
@@ -1,114 +0,0 @@
-# REQUIRES: mips
-
-# Conditions:
-# a) Object file contains both R_MIPS_26 and microMIPS non-jal relocations.
-# b) The R_MIPS_26 relocation handled first.
-# Check:
-# a) PLT contains the only regular entry.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t.o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o.o %t.so
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .plt:
-# CHECK-NEXT: .plt:
-# CHECK-NEXT: 400170: 40 00 1c 3c lui $gp, 64
-# CHECK-NEXT: 400174: 00 20 99 8f lw $25, 8192($gp)
-# CHECK-NEXT: 400178: 00 20 9c 27 addiu $gp, $gp, 8192
-# CHECK-NEXT: 40017c: 23 c0 1c 03 subu $24, $24, $gp
-# CHECK-NEXT: 400180: 25 78 e0 03 move $15, $ra
-# CHECK-NEXT: 400184: 82 c0 18 00 srl $24, $24, 2
-# CHECK-NEXT: 400188: 09 f8 20 03 jalr $25
-# CHECK-NEXT: 40018c: fe ff 18 27 addiu $24, $24, -2
-# CHECK-NEXT: 400190: 40 00 0f 3c lui $15, 64
-# CHECK-NEXT: 400194: 08 20 f9 8d lw $25, 8200($15)
-# CHECK-NEXT: 400198: 08 00 20 03 jr $25
-# CHECK-NEXT: 40019c: 08 20 f8 25 addiu $24, $15, 8200
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000C00000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MIPS_26
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x8
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-entry-mixed-2.test b/test/old-elf/Mips/plt-entry-mixed-2.test
deleted file mode 100644
index 299aa5ce065c..000000000000
--- a/test/old-elf/Mips/plt-entry-mixed-2.test
+++ /dev/null
@@ -1,93 +0,0 @@
-# REQUIRES: mips
-
-# Conditions:
-# a) Object file contains both R_MIPS_26 and R_MICROMIPS_26_S1 relocations.
-# Check:
-# a) PLT contains both regular and compressed PLT entries
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t.o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o.o %t.so
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# FIXME (simon): Check the disassembler output when llvm-objdump starts
-# to support microMIPS instruction encoding.
-
-# CHECK: Contents of section .plt:
-# CHECK-NEXT: 400170 40001c3c 0020998f 00209c27 23c01c03
-# CHECK-NEXT: 400180 2578e003 82c01800 09f82003 feff1827
-# CHECK-NEXT: 400190 40000f3c 0820f98d 08002003 0820f825
-# CHECK-NEXT: 4001a0 00799a07 22ff0000 9945020f
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000C000000000000000000000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: T2
- Type: R_MIPS_26
- - Offset: 0x8
- Symbol: T2
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 0x8
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
-...
diff --git a/test/old-elf/Mips/plt-entry-mixed-3.test b/test/old-elf/Mips/plt-entry-mixed-3.test
deleted file mode 100644
index c946ecc82d2f..000000000000
--- a/test/old-elf/Mips/plt-entry-mixed-3.test
+++ /dev/null
@@ -1,98 +0,0 @@
-# REQUIRES: mips
-
-# Conditions:
-# a) Object file contains microMIPS instructions.
-# b) There is a relocation refers arbitrary symbols and requires a PLT entry.
-# Check:
-# a) PLT contains a compressed entry.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t.o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o.o %t.so
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# FIXME (simon): Check the disassembler output when llvm-objdump starts
-# to support microMIPS instruction encoding.
-
-# CHECK: Contents of section .plt:
-# CHECK-NEXT: 400170 8079a407 23ff0000 35052525 0233feff .y..#...5.%%.3..
-# CHECK-NEXT: 400180 ff0df945 830f000c 0079a007 22ff0000 ...E.....y.."...
-# CHECK-NEXT: 400190 9945020f .E..
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 16
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 16
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-entry-mixed-4.test b/test/old-elf/Mips/plt-entry-mixed-4.test
deleted file mode 100644
index ba8b04866b98..000000000000
--- a/test/old-elf/Mips/plt-entry-mixed-4.test
+++ /dev/null
@@ -1,85 +0,0 @@
-# REQUIRES: mips
-
-# Conditions:
-# a) Object file contains R_MIPS_26 relocation refers to the microMIPS symbol.
-# Check:
-# a) PLT contains a regular non-compressed entry.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t.o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o.o %t.so
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# FIXME (simon): Check the disassembler output when llvm-objdump starts
-# to support microMIPS instruction encoding.
-
-# CHECK: Contents of section .plt:
-# CHECK-NEXT: 400170 40001c3c 0020998f 00209c27 23c01c03
-# CHECK-NEXT: 400180 2578e003 82c01800 09f82003 feff1827
-# CHECK-NEXT: 400190 40000f3c 0820f98d 08002003 0820f825
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000C00000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MIPS_26
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x8
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-entry-r6-be.test b/test/old-elf/Mips/plt-entry-r6-be.test
deleted file mode 100644
index 3e15ece894e0..000000000000
--- a/test/old-elf/Mips/plt-entry-r6-be.test
+++ /dev/null
@@ -1,109 +0,0 @@
-# REQUIRES: mips
-
-# Check generation of PLT entries in case of R6 big-endian target ABI.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .plt:
-# CHECK-NEXT: .plt:
-# CHECK-NEXT: 400160: 3c 1c 00 40 lui $gp, 64
-# CHECK-NEXT: 400164: 8f 99 20 00 lw $25, 8192($gp)
-# CHECK-NEXT: 400168: 27 9c 20 00 addiu $gp, $gp, 8192
-# CHECK-NEXT: 40016c: 03 1c c0 23 subu $24, $24, $gp
-# CHECK-NEXT: 400170: 03 e0 78 25 move $15, $ra
-# CHECK-NEXT: 400174: 00 18 c0 82 srl $24, $24, 2
-# CHECK-NEXT: 400178: 03 20 f8 09 jalr $25
-# CHECK-NEXT: 40017c: 27 18 ff fe addiu $24, $24, -2
-# CHECK-NEXT: 400180: 3c 0f 00 40 lui $15, 64
-# CHECK-NEXT: 400184: 8d f9 20 08 lw $25, 8200($15)
-# CHECK-NEXT: 400188: 03 20 00 09 jr $25
-# CHECK-NEXT: 40018c: 25 f8 20 08 addiu $24, $15, 8200
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0C00000000000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MIPS_26
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x8
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-entry-r6.test b/test/old-elf/Mips/plt-entry-r6.test
deleted file mode 100644
index 0d8bbf494afe..000000000000
--- a/test/old-elf/Mips/plt-entry-r6.test
+++ /dev/null
@@ -1,109 +0,0 @@
-# REQUIRES: mips
-
-# Check generation of PLT entries in case of R6 target ABI.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .plt:
-# CHECK-NEXT: .plt:
-# CHECK-NEXT: 400160: 40 00 1c 3c lui $gp, 64
-# CHECK-NEXT: 400164: 00 20 99 8f lw $25, 8192($gp)
-# CHECK-NEXT: 400168: 00 20 9c 27 addiu $gp, $gp, 8192
-# CHECK-NEXT: 40016c: 23 c0 1c 03 subu $24, $24, $gp
-# CHECK-NEXT: 400170: 25 78 e0 03 move $15, $ra
-# CHECK-NEXT: 400174: 82 c0 18 00 srl $24, $24, 2
-# CHECK-NEXT: 400178: 09 f8 20 03 jalr $25
-# CHECK-NEXT: 40017c: fe ff 18 27 addiu $24, $24, -2
-# CHECK-NEXT: 400180: 40 00 0f 3c lui $15, 64
-# CHECK-NEXT: 400184: 08 20 f9 8d lw $25, 8200($15)
-# CHECK-NEXT: 400188: 09 00 20 03 jr $25
-# CHECK-NEXT: 40018c: 08 20 f8 25 addiu $24, $15, 8200
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000C00000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MIPS_26
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x8
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-header-be.test b/test/old-elf/Mips/plt-header-be.test
deleted file mode 100644
index e453e44f76d6..000000000000
--- a/test/old-elf/Mips/plt-header-be.test
+++ /dev/null
@@ -1,104 +0,0 @@
-# REQUIRES: mips
-
-# Check initialization of big-endian .plt header entries.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -section-headers -disassemble %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .plt:
-# CHECK-NEXT: .plt:
-# CHECK-NEXT: 400160: 3c 1c 00 40 lui $gp, 64
-# CHECK-NEXT: 400164: 8f 99 20 00 lw $25, 8192($gp)
-# CHECK-NEXT: 400168: 27 9c 20 00 addiu $gp, $gp, 8192
-# CHECK-NEXT: 40016c: 03 1c c0 23 subu $24, $24, $gp
-# CHECK-NEXT: 400170: 03 e0 78 25 move $15, $ra
-# CHECK-NEXT: 400174: 00 18 c0 82 srl $24, $24, 2
-# CHECK-NEXT: 400178: 03 20 f8 09 jalr $25
-# CHECK-NEXT: 40017c: 27 18 ff fe addiu $24, $24, -2
-
-# CHECK-NEXT: 400180: 3c 0f 00 40 lui $15, 64
-# CHECK-NEXT: 400184: 8d f9 20 08 lw $25, 8200($15)
-# CHECK-NEXT: 400188: 03 20 00 08 jr $25
-# CHECK-NEXT: 40018c: 25 f8 20 08 addiu $24, $15, 8200
-
-# CHECK: Sections:
-# CHECK: Idx Name Size Address Type
-# CHECK: 6 .plt 00000030 0000000000400160 TEXT DATA
-# CHECK: 10 .got.plt 0000000c 0000000000402000 DATA
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 12
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 32
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 8
- Symbol: .text
- Type: R_MIPS_26
- - Offset: 16
- Symbol: __start
- Type: R_MIPS_26
- - Offset: 24
- Symbol: T1
- Type: R_MIPS_26
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 16
- - Name: .text
- Type: STT_SECTION
- Section: .text
-
- Global:
- - Name: __start
- Section: .text
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-header-micro-be.test b/test/old-elf/Mips/plt-header-micro-be.test
deleted file mode 100644
index e9aa51ef85eb..000000000000
--- a/test/old-elf/Mips/plt-header-micro-be.test
+++ /dev/null
@@ -1,105 +0,0 @@
-# REQUIRES: mips
-
-# Check initialization of .plt header entries
-# if all PLT entries use microMIPS big-endian encoding.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: lld -flavor old-gnu -target mips -shared -o %t.so %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mips -o %t.exe %t2.o %t.so
-# RUN: llvm-objdump -section-headers -d -mattr=micromips %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .plt:
-# CHECK-NEXT: .plt:
-# CHECK-NEXT: 400170: 79 80 07 a4 addiupc $3, 7824
-# CHECK-NEXT: 400174: ff 23 00 00 lw $25, 0($3)
-# CHECK-NEXT: 400178: 05 35 subu16 $2, $2, $3
-# CHECK-NEXT: 40017a: 25 25 srl16 $2, $2, 2
-# CHECK-NEXT: 40017c: 33 02 ff fe addiu $24, $2, -2
-# CHECK-NEXT: 400180: 0d ff move $15, $ra
-# CHECK-NEXT: 400182: 45 f9 jalrs16 $25
-# CHECK-NEXT: 400184: 0f 83 move $gp, $3
-# CHECK-NEXT: 400186: 0c 00 nop
-
-# CHECK-NEXT: 400188: 79 00 07 a0 addiupc $2, 7808
-# CHECK-NEXT: 40018c: ff 22 00 00 lw $25, 0($2)
-# CHECK-NEXT: 400190: 45 99 jr16 $25
-# CHECK-NEXT: 400192: 0f 02 move $24, $2
-
-# CHECK: Sections:
-# CHECK: Idx Name Size Address Type
-# CHECK: 6 .plt 00000024 0000000000400170 TEXT DATA
-# CHECK: 10 .got.plt 0000000c 0000000000402000 DATA
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 12
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: '0000000000000000f40000000000000000000000f400000000000000f4000000'
-# jal .text jal __start jal T1
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 8
- Symbol: .text
- Type: R_MICROMIPS_26_S1
- - Offset: 20
- Symbol: __start
- Type: R_MICROMIPS_26_S1
- - Offset: 28
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 16
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: __start
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-header-micro.test b/test/old-elf/Mips/plt-header-micro.test
deleted file mode 100644
index 743c4c332184..000000000000
--- a/test/old-elf/Mips/plt-header-micro.test
+++ /dev/null
@@ -1,108 +0,0 @@
-# REQUIRES: mips
-
-# Check initialization of .plt header entries
-# if all PLT entries use microMIPS encoding.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -d -mattr=micromips %t.exe | FileCheck -check-prefix=DIS %s
-# RUN: llvm-objdump -section-headers %t.exe | FileCheck -check-prefix=EXE %s
-
-# DIS: Disassembly of section .plt:
-# DIS-NEXT: .plt:
-# DIS-NEXT: 400170: 80 79 a4 07 addiupc $3, 7824
-# DIS-NEXT: 400174: 23 ff 00 00 lw $25, 0($3)
-# DIS-NEXT: 400178: 35 05 subu16 $2, $2, $3
-# DIS-NEXT: 40017a: 25 25 srl16 $2, $2, 2
-# DIS-NEXT: 40017c: 02 33 fe ff addiu $24, $2, -2
-# DIS-NEXT: 400180: ff 0d move $15, $ra
-# DIS-NEXT: 400182: f9 45 jalrs16 $25
-# DIS-NEXT: 400184: 83 0f move $gp, $3
-# DIS-NEXT: 400186: 00 0c nop
-
-# DIS-NEXT: 400188: 00 79 a0 07 addiupc $2, 7808
-# DIS-NEXT: 40018c: 22 ff 00 00 lw $25, 0($2)
-# DIS-NEXT: 400190: 99 45 jr16 $25
-# DIS-NEXT: 400192: 02 0f move $24, $2
-
-# EXE: Sections:
-# EXE: Idx Name Size Address Type
-# EXE: 6 .plt 00000024 0000000000400170 TEXT DATA
-# EXE: 10 .got.plt 0000000c 0000000000402000 DATA
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: '000000000000000000f4000000000000f400000000000000f400000000000000'
-# jal .text jal glob jal T1
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x08
- Symbol: .text
- Type: R_MICROMIPS_26_S1
- - Offset: 0x10
- Symbol: glob
- Type: R_MICROMIPS_26_S1
- - Offset: 0x18
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 0x10
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-header-mixed.test b/test/old-elf/Mips/plt-header-mixed.test
deleted file mode 100644
index 456f5a91c98b..000000000000
--- a/test/old-elf/Mips/plt-header-mixed.test
+++ /dev/null
@@ -1,105 +0,0 @@
-# REQUIRES: mips
-
-# Check initialization of .plt header entries if there are both regular
-# and microMIPS encoded PLT entries. Check that R_MIPS_26 and R_MICROMIPS_26_S1
-# relocation with the same target cause generation of two distinct PLT entries.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e globR -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DIS %s
-# RUN: llvm-objdump -section-headers %t.exe | FileCheck -check-prefix=EXE %s
-
-# DIS: Disassembly of section .plt:
-# DIS-NEXT: .plt:
-# DIS-NEXT: 400170: 40 00 1c 3c lui $gp, 64
-# DIS-NEXT: 400174: 00 20 99 8f lw $25, 8192($gp)
-# DIS-NEXT: 400178: 00 20 9c 27 addiu $gp, $gp, 8192
-# DIS-NEXT: 40017c: 23 c0 1c 03 subu $24, $24, $gp
-# DIS-NEXT: 400180: 25 78 e0 03 move $15, $ra
-# DIS-NEXT: 400184: 82 c0 18 00 srl $24, $24, 2
-# DIS-NEXT: 400188: 09 f8 20 03 jalr $25
-# DIS-NEXT: 40018c: fe ff 18 27 addiu $24, $24, -2
-
-# DIS-NEXT: 400190: 40 00 0f 3c lui $15, 64
-# DIS-NEXT: 400194: 08 20 f9 8d lw $25, 8200($15)
-# DIS-NEXT: 400198: 08 00 20 03 jr $25
-# DIS-NEXT: 40019c: 08 20 f8 25 addiu $24, $15, 8200
-
-# FIXME (simon): Check micromips PLT entry
-# DIS-NEXT: 4001a8: 99 45 02 0f jal 201922148
-
-# EXE: Sections:
-# EXE: Idx Name Size Address Type
-# EXE: 6 .plt 0000003c 0000000000400170 TEXT DATA
-# EXE: 10 .got.plt 0000000c 0000000000402000 DATA
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x8
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x0
- Symbol: T1
- Type: R_MIPS_26
- - Offset: 0x4
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Global:
- - Name: globR
- Section: .text
- Value: 0x0
- Size: 0x4
- - Name: globM
- Section: .text
- Value: 0x4
- Size: 0x4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
-...
diff --git a/test/old-elf/Mips/plt-header.test b/test/old-elf/Mips/plt-header.test
deleted file mode 100644
index 6d303254d16d..000000000000
--- a/test/old-elf/Mips/plt-header.test
+++ /dev/null
@@ -1,99 +0,0 @@
-# REQUIRES: mips
-
-# Check initialization of .plt header entries.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -section-headers -disassemble %t.exe | \
-# RUN: FileCheck -check-prefix=EXE %s
-
-# EXE: Disassembly of section .plt:
-# EXE: .plt:
-# PLT0 entry. Points to the .got.plt[0]
-# EXE-NEXT: 400160: 40 00 1c 3c lui $gp, 64
-# EXE-NEXT: 400164: 00 20 99 8f lw $25, 8192($gp)
-# EXE-NEXT: 400168: 00 20 9c 27 addiu $gp, $gp, 8192
-# EXE-NEXT: 40016c: 23 c0 1c 03 subu $24, $24, $gp
-# EXE-NEXT: 400170: 25 78 e0 03 move $15, $ra
-# EXE-NEXT: 400174: 82 c0 18 00 srl $24, $24, 2
-# EXE-NEXT: 400178: 09 f8 20 03 jalr $25
-# EXE-NEXT: 40017c: fe ff 18 27 addiu $24, $24, -2
-
-# EXE: Sections:
-# EXE: Idx Name Size Address Type
-# EXE: 6 .plt 00000030 0000000000400160 TEXT DATA
-# EXE: 10 .got.plt 0000000c 0000000000402000 DATA
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x20
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x08
- Symbol: .text
- Type: R_MIPS_26
- - Offset: 0x10
- Symbol: glob
- Type: R_MIPS_26
- - Offset: 0x18
- Symbol: T1
- Type: R_MIPS_26
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 0x10
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- - Name: T1
-...
diff --git a/test/old-elf/Mips/r26-1-micro.test b/test/old-elf/Mips/r26-1-micro.test
deleted file mode 100644
index c59b5aa61a53..000000000000
--- a/test/old-elf/Mips/r26-1-micro.test
+++ /dev/null
@@ -1,131 +0,0 @@
-# REQUIRES: mips
-
-# Check handling of R_MICROMIPS_26_S1 relocation.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: llvm-readobj -relocations %t-o.o | \
-# RUN: FileCheck -check-prefix=OBJ-REL %s
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -relocations %t.exe | FileCheck -check-prefix=EXE-REL %s
-# RUN: llvm-objdump -section-headers %t.exe | FileCheck -check-prefix=EXE %s
-# RUN: llvm-objdump -s -d -mattr=micromips %t.exe | \
-# RUN: FileCheck -check-prefix=DIS %s
-
-# Object file has three R_MICROMIPS_26_S1 relocations
-# OBJ-REL: Relocations [
-# OBJ-REL-NEXT: Section (2) .rel.text {
-# OBJ-REL-NEXT: 0x8 R_MICROMIPS_26_S1 loc 0x0
-# OBJ-REL-NEXT: 0x10 R_MICROMIPS_26_S1 glob 0x0
-# OBJ-REL-NEXT: 0x18 R_MICROMIPS_26_S1 T1 0x0
-# OBJ-REL-NEXT: }
-# OBJ-REL-NEXT: ]
-
-# Executable file has the only relocation for external symbol
-# EXE-REL: Relocations [
-# EXE-REL-NEXT: Section (5) .rel.plt {
-# EXE-REL-NEXT: 0x402008 R_MIPS_JUMP_SLOT T1 0x0
-# EXE-REL-NEXT: }
-# EXE-REL-NEXT: ]
-
-# EXE: Sections:
-# EXE: Idx Name Size Address Type
-# EXE: 6 .plt 00000024 0000000000400160 TEXT DATA
-# EXE: 10 .got.plt 0000000c 0000000000402000 DATA
-
-# DIS: Disassembly of section .plt:
-# DIS-NEXT: .plt:
-# DIS-NEXT: 400160: 80 79 a8 07 addiupc $3, 7840
-# DIS-NEXT: 400164: 23 ff 00 00 lw $25, 0($3)
-# DIS-NEXT: 400168: 35 05 subu16 $2, $2, $3
-# DIS-NEXT: 40016a: 25 25 srl16 $2, $2, 2
-# DIS-NEXT: 40016c: 02 33 fe ff addiu $24, $2, -2
-# DIS-NEXT: 400170: ff 0d move $15, $ra
-# DIS-NEXT: 400172: f9 45 jalrs16 $25
-# DIS-NEXT: 400174: 83 0f move $gp, $3
-# DIS-NEXT: 400176: 00 0c nop
-
-# DIS-NEXT: 400178: 00 79 a4 07 addiupc $2, 7824
-# DIS-NEXT: 40017c: 22 ff 00 00 lw $25, 0($2)
-# DIS-NEXT: 400180: 99 45 jr16 $25
-# DIS-NEXT: 400182: 02 0f move $24, $2
-
-# DIS: Contents of section .text:
-# DIS-NEXT: 400184 09f82003 00000000 2400ca0c 00000000 .. .....$.......
-# DIS-NEXT: 400194 2000c20c 00000000 2000bc0c 00000000 ....... .......
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: '09F82003000000000400000C000000000000000C000000000000000C00000000'
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x08
- Symbol: loc
- Type: R_MICROMIPS_26_S1
- - Offset: 0x10
- Symbol: glob
- Type: R_MICROMIPS_26_S1
- - Offset: 0x18
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 0x10
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
-...
diff --git a/test/old-elf/Mips/r26-1.test b/test/old-elf/Mips/r26-1.test
deleted file mode 100644
index 41c58deceedb..000000000000
--- a/test/old-elf/Mips/r26-1.test
+++ /dev/null
@@ -1,132 +0,0 @@
-# REQUIRES: mips
-
-# Check handling of R_MIPS_26 relocation.
-
-# Build shared library
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: llvm-readobj -relocations %t-o.o | \
-# RUN: FileCheck -check-prefix=OBJ-REL %s
-# RUN: lld -flavor old-gnu -target mipsel -e glob -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -section-headers -disassemble %t.exe | \
-# RUN: FileCheck -check-prefix=EXE %s
-# RUN: llvm-readobj -relocations %t.exe | FileCheck -check-prefix=EXE-REL %s
-
-# Object file has three R_MIPS_26 relocations
-# OBJ-REL: Relocations [
-# OBJ-REL-NEXT: Section (2) .rel.text {
-# OBJ-REL-NEXT: 0x8 R_MIPS_26 .text 0x0
-# OBJ-REL-NEXT: 0x10 R_MIPS_26 glob 0x0
-# OBJ-REL-NEXT: 0x18 R_MIPS_26 T1 0x0
-# OBJ-REL-NEXT: }
-# OBJ-REL-NEXT: ]
-
-# Executable file has the only relocation for external symbol
-# EXE-REL: Relocations [
-# EXE-REL-NEXT: Section (5) .rel.plt {
-# EXE-REL-NEXT: 0x402008 R_MIPS_JUMP_SLOT T1 0x0
-# EXE-REL-NEXT: }
-# EXE-REL-NEXT: ]
-
-# EXE: Disassembly of section .plt:
-# EXE: .plt:
-# PLTA entry. Points to the .got.plt[1]
-# EXE: 400180: 40 00 0f 3c lui $15, 64
-# EXE-NEXT: 400184: 08 20 f9 8d lw $25, 8200($15)
-# EXE-NEXT: 400188: 08 00 20 03 jr $25
-# EXE-NEXT: 40018c: 08 20 f8 25 addiu $24, $15, 8200
-
-# EXE: Disassembly of section .text:
-# EXE: glob:
-# EXE-NEXT: 400190: 09 f8 20 03 jalr $25
-# EXE-NEXT: 400194: 00 00 00 00 nop
-#
-# Jump to 'loc' label address
-# EXE-NEXT: 400198: 68 00 10 0c jal 4194720
-# EXE-NEXT: 40019c: 00 00 00 00 nop
-#
-# EXE: loc:
-# Jump to 'glob' label address
-# EXE-NEXT: 4001a0: 64 00 10 0c jal 4194704
-# EXE-NEXT: 4001a4: 00 00 00 00 nop
-#
-# Jump to the first PLT entry (.plt + 32) for T1 entry
-# EXE-NEXT: 4001a8: 60 00 10 0c jal 4194688
-# EXE-NEXT: 4001ac: 00 00 00 00 nop
-
-# EXE: Sections:
-# EXE: Idx Name Size Address Type
-# EXE: 6 .plt 00000030 0000000000400160 TEXT DATA
-# EXE: 10 .got.plt 0000000c 0000000000402000 DATA
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: '09F82003000000000400000C000000000000000C000000000000000C00000000'
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x08
- Symbol: .text
- Type: R_MIPS_26
- - Offset: 0x10
- Symbol: glob
- Type: R_MIPS_26
- - Offset: 0x18
- Symbol: T1
- Type: R_MIPS_26
-
-Symbols:
- Local:
- - Name: loc
- Section: .text
- Value: 0x10
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: glob
- Section: .text
- - Name: T1
-...
diff --git a/test/old-elf/Mips/r26-2-micro.test b/test/old-elf/Mips/r26-2-micro.test
deleted file mode 100644
index 7d4f86e57f70..000000000000
--- a/test/old-elf/Mips/r26-2-micro.test
+++ /dev/null
@@ -1,31 +0,0 @@
-# REQUIRES: mips
-
-# Check reading addendum for R_MICROMIPS_26_S1 relocation.
-# RUN: llvm-mc -arch=mipsel -filetype=obj -mattr=micromips -o=%t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -o %t.exe %t.o
-# RUN: llvm-objdump -d -mattr=micromips %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: __start:
-# CHECK-NEXT: 400180: 10 f0 60 70 jalx 2154688
-# CHECK-NEXT: 400184: 00 00 00 00 nop
-# CHECK-NEXT: 400188: 10 f0 68 70 jalx 2154704
-# CHECK-NEXT: 40018c: 00 00 00 00 nop
-# CHECK-NEXT: 400190: 10 f0 58 00 jalx 2097328
-# CHECK-NEXT: 400194: 00 00 00 00 nop
-# CHECK-NEXT: 400198: 10 f0 62 00 jalx 2097348
-# CHECK-NEXT: 40019c: 00 00 00 00 nop
-#
-# CHECK: loc:
-# CHECK-NEXT: 4001a0: 00 00 00 00 nop
-
- .text
- .globl __start
-__start:
- jal __start + 0x1C000
- jal loc + 0x1C000
- jal __start + 0x7ffffe2
- jal loc + 0x7ffffea
-
-loc:
- nop
diff --git a/test/old-elf/Mips/r26-2.test b/test/old-elf/Mips/r26-2.test
deleted file mode 100644
index b9db959d3ea7..000000000000
--- a/test/old-elf/Mips/r26-2.test
+++ /dev/null
@@ -1,31 +0,0 @@
-# REQUIRES: mips
-
-# Check reading addendum for R_MIPS_26 relocation.
-# RUN: llvm-mc -arch=mipsel -filetype=obj -o=%t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -o %t.exe %t.o
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: __start:
-# CHECK-NEXT: 400180: 60 70 10 0c jal 4309376
-# CHECK-NEXT: 400184: 00 00 00 00 nop
-# CHECK-NEXT: 400188: 68 70 10 0c jal 4309408
-# CHECK-NEXT: 40018c: 00 00 00 00 nop
-# CHECK-NEXT: 400190: 5f 00 10 0c jal 4194684
-# CHECK-NEXT: 400194: 00 00 00 00 nop
-# CHECK-NEXT: 400198: 67 00 10 0c jal 4194716
-# CHECK-NEXT: 40019c: 00 00 00 00 nop
-#
-# CHECK: loc:
-# CHECK-NEXT: 4001a0: 00 00 00 00 nop
-
- .text
- .globl __start
-__start:
- jal __start + 0x1C000
- jal loc + 0x1C000
- jal __start + (-1)
- jal loc + (-1)
-
-loc:
- nop
diff --git a/test/old-elf/Mips/reginfo-01.test b/test/old-elf/Mips/reginfo-01.test
deleted file mode 100644
index ee7cd6a5fcee..000000000000
--- a/test/old-elf/Mips/reginfo-01.test
+++ /dev/null
@@ -1,30 +0,0 @@
-# Check that LLD does not write a .reginfo section if input
-# object file does not contain such section.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -s %t.so | FileCheck %s
-
-# CHECK-NOT: Name: .reginfo
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/reginfo-02.test b/test/old-elf/Mips/reginfo-02.test
deleted file mode 100644
index 41eac01a11b1..000000000000
--- a/test/old-elf/Mips/reginfo-02.test
+++ /dev/null
@@ -1,107 +0,0 @@
-# Check merging input .reginfo sections.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t1.o %t2.o
-# RUN: llvm-readobj -program-headers -s -t -mips-reginfo %t.so | FileCheck %s
-
-# CHECK: Index: 1
-# CHECK-NEXT: Name: .reginfo (1)
-# CHECK-NEXT: Type: SHT_MIPS_REGINFO
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: SHF_ALLOC
-# CHECK-NEXT: ]
-# CHECK-NEXT: Address: {{[0-9A-F]+}}
-# CHECK-NEXT: Offset: {{[0-9A-F]+}}
-# CHECK-NEXT: Size: 24
-# CHECK-NEXT: Link: 0
-# CHECK-NEXT: Info: 0
-# CHECK-NEXT: AddressAlignment: 4
-# CHECK-NEXT: EntrySize: 24
-
-# CHECK: Name: _gp
-# CHECK-NEXT: 0x8FF0
-
-# CHECK: ProgramHeaders [
-# CHECK-NEXT: ProgramHeader {
-# CHECK-NEXT: Type: PT_MIPS_REGINFO
-# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: VirtualAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: PhysicalAddress: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: FileSize: 24
-# CHECK-NEXT: MemSize: 24
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: PF_R
-# CHECK-NEXT: ]
-# CHECK-NEXT: Alignment: 4
-# CHECK-NEXT: }
-
-# CHECK: MIPS RegInfo {
-# CHECK-NEXT: GP: 0x8FF0
-# CHECK-NEXT: General Mask: 0x10000F0
-# CHECK-NEXT: Co-Proc Mask0: 0x20000E0
-# CHECK-NEXT: Co-Proc Mask1: 0x30000D0
-# CHECK-NEXT: Co-Proc Mask2: 0x40000C0
-# CHECK-NEXT: Co-Proc Mask3: 0x50000B0
-# CHECK-NEXT: }
-
-# t1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "F0000000E0000000D0000000C0000000B000000000100000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "000000010000000200000003000000040000000500000100"
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/reginfo-03.test b/test/old-elf/Mips/reginfo-03.test
deleted file mode 100644
index edee1440d358..000000000000
--- a/test/old-elf/Mips/reginfo-03.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Check handling a zero-filled input .reginfo section.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -t -mips-reginfo %t.so | FileCheck %s
-
-# CHECK: Name: _gp
-# CHECK-NEXT: 0x8FF0
-
-# CHECK: MIPS RegInfo {
-# CHECK-NEXT: GP: 0x8FF0
-# CHECK-NEXT: General Mask: 0x0
-# CHECK-NEXT: Co-Proc Mask0: 0x0
-# CHECK-NEXT: Co-Proc Mask1: 0x0
-# CHECK-NEXT: Co-Proc Mask2: 0x0
-# CHECK-NEXT: Co-Proc Mask3: 0x0
-# CHECK-NEXT: }
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "000000000000000000000000000000000000000000000000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/reginfo-04.test b/test/old-elf/Mips/reginfo-04.test
deleted file mode 100644
index bad34e5003f7..000000000000
--- a/test/old-elf/Mips/reginfo-04.test
+++ /dev/null
@@ -1,81 +0,0 @@
-# Check that .reginfo sections from shared libraries do not affect
-# output .reginfo section content.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t.exe.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.so %t.exe.o
-# RUN: llvm-readobj -t -mips-reginfo %t.exe | FileCheck %s
-
-# CHECK: Name: _gp
-# CHECK-NEXT: 0x408FF0
-
-# CHECK: MIPS RegInfo {
-# CHECK-NEXT: GP: 0x408FF0
-# CHECK-NEXT: General Mask: 0x44444444
-# CHECK-NEXT: Co-Proc Mask0: 0x44444444
-# CHECK-NEXT: Co-Proc Mask1: 0x44444444
-# CHECK-NEXT: Co-Proc Mask2: 0x44444444
-# CHECK-NEXT: Co-Proc Mask3: 0x44444444
-# CHECK-NEXT: }
-
-# t.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "111111111111111111111111111111111111111100100000"
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t.exe.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "444444444444444444444444444444444444444400000000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/reginfo-05.test b/test/old-elf/Mips/reginfo-05.test
deleted file mode 100644
index 9de9fa62149a..000000000000
--- a/test/old-elf/Mips/reginfo-05.test
+++ /dev/null
@@ -1,123 +0,0 @@
-# Check that .reginfo section gets register usage mask from "used" files only.
-# In this test case we take only t2.o from libreginfo.a and should not add
-# register usage masks from t1.o to the output .reginfo section.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: llvm-ar q %T/libreginfo.a %t1.o %t2.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t3.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t3.o -L%T -lreginfo
-# RUN: llvm-readobj -t -mips-reginfo %t.exe | FileCheck %s
-
-# CHECK: Name: _gp
-# CHECK-NEXT: 0x408FF0
-
-# CHECK: MIPS RegInfo {
-# CHECK-NEXT: GP: 0x408FF0
-# CHECK-NEXT: General Mask: 0x66666666
-# CHECK-NEXT: Co-Proc Mask0: 0x66666666
-# CHECK-NEXT: Co-Proc Mask1: 0x66666666
-# CHECK-NEXT: Co-Proc Mask2: 0x66666666
-# CHECK-NEXT: Co-Proc Mask3: 0x66666666
-# CHECK-NEXT: }
-
-# t1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "111111111111111111111111111111111111111100000000"
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "222222222222222222222222222222222222222200000000"
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t3.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T2
- Type: R_MIPS_32
-
-- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: "444444444444444444444444444444444444444400000000"
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T2
-...
diff --git a/test/old-elf/Mips/rel-16-overflow.test b/test/old-elf/Mips/rel-16-overflow.test
deleted file mode 100644
index e2a73f693361..000000000000
--- a/test/old-elf/Mips/rel-16-overflow.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Check R_MIPS_16 relocation overflow handling.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}} reference from T0+0 to T1+32767 of type 1 (R_MIPS_16)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "ff7f00000000000000000000"
-# ^ T1
-# ^ T0 A := 0x7fff
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-16.test b/test/old-elf/Mips/rel-16.test
deleted file mode 100644
index 24961e8b78ff..000000000000
--- a/test/old-elf/Mips/rel-16.test
+++ /dev/null
@@ -1,51 +0,0 @@
-# Check handling of R_MIPS_16 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 00f0 f0000000 00000000 00000000
-# ^ V = (T1 - 8) = T0
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 000000f0 g F .text 00000008 T0
-# CHECK: 000000f8 g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "f8ff00000000000000000000"
-# ^ T1
-# ^ T0 A := 0xfff8 = -8
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-32-be.test b/test/old-elf/Mips/rel-32-be.test
deleted file mode 100644
index 3eac8a2848f0..000000000000
--- a/test/old-elf/Mips/rel-32-be.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Check handling of R_MIPS_32 relocation in the big-endian case.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 402000 00000000 01402088 01402084
-# ^^ D2 + 0x1000080 = 0x1402088
-# ^^ D1 + 0x1000080 = 0x1402084
-# CHECK: SYMBOL TABLE:
-# CHECK: 00402004 g .data 00000004 D1
-# CHECK: 00402008 g .data 00000004 D2
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2MSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- AddressAlign: 16
- Flags: [SHF_ALLOC]
- Size: 4
-
-- Name: .data
- Type: SHT_PROGBITS
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
- Content: "000000000100008001000080"
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 4
- Symbol: D2
- Type: R_MIPS_32
- - Offset: 8
- Symbol: D1
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0
- Size: 4
- - Name: D1
- Section: .data
- Value: 4
- Size: 4
- - Name: D2
- Section: .data
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-32.test b/test/old-elf/Mips/rel-32.test
deleted file mode 100644
index f028d79c8688..000000000000
--- a/test/old-elf/Mips/rel-32.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_MIPS_32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 402000 00000000 09204080 05204080 ..... @.. @.
-# ^^ data2 + 0x80000001 = 0x80402009
-# ^^ data1 + 0x80000001 = 0x80402005
-# CHECK: SYMBOL TABLE:
-# CHECK: 00402004 g .data 00000004 data1
-# CHECK: 00402008 g .data 00000004 data2
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "000000000100008001000080"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x4
- Symbol: data2
- Type: R_MIPS_32
- - Offset: 0x8
- Symbol: data1
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Value: 0x4
- Size: 4
- - Name: data2
- Section: .data
- Value: 0x8
- Size: 4
diff --git a/test/old-elf/Mips/rel-64.test b/test/old-elf/Mips/rel-64.test
deleted file mode 100644
index c97ff991c0c4..000000000000
--- a/test/old-elf/Mips/rel-64.test
+++ /dev/null
@@ -1,61 +0,0 @@
-# Check handling of R_MIPS_64 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 120002000 d1010020 01000000 d0010020 01000100 ... ....... ....
-# ^^ __start + 1 = 0x1200001d1
-# ^^ __start + 0x1000000000000
-# = 0x10001200001d0
-# CHECK: SYMBOL TABLE:
-# CHECK: 00000001200001d0 g .rodata 00000008 __start
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_ALLOC]
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x10
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: __start
- Type: R_MIPS_64
- Addend: 1
- - Offset: 0x8
- Symbol: __start
- Type: R_MIPS_64
- Addend: 0x1000000000000
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0x0
- Size: 8
- - Name: data1
- Section: .data
- Value: 0x0
- Size: 8
- - Name: data2
- Section: .data
- Value: 0x8
- Size: 8
diff --git a/test/old-elf/Mips/rel-call-hilo-01.test b/test/old-elf/Mips/rel-call-hilo-01.test
deleted file mode 100644
index 88f2e337d928..000000000000
--- a/test/old-elf/Mips/rel-call-hilo-01.test
+++ /dev/null
@@ -1,109 +0,0 @@
-# Check handling of R_MIPS_CALL_HI16 / R_MIPS_CALL_LO16 relocations.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t1.so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2.so %t2.so.o %t1.so
-# RUN: llvm-objdump -s -t %t2.so | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -mips-plt-got %t2.so | FileCheck -check-prefix=GOT %s
-
-# RAW: Contents of section .text:
-# RAW-NEXT: 0110 00000000 18800000 00000000 1c800000
-# ^ -32744 ^ -32740
-# RAW-NEXT: 0120 00000000
-
-# RAW: SYMBOL TABLE:
-# RAW: 00000120 l F .text 00000004 T1
-
-# GOT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x120
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# t1.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t2.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 20
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_CALL_HI16
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_CALL_LO16
- - Offset: 8
- Symbol: T2
- Type: R_MIPS_CALL_HI16
- - Offset: 12
- Symbol: T2
- Type: R_MIPS_CALL_LO16
-
-Symbols:
- Local:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 16
- Size: 4
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 16
- - Name: T2
-...
diff --git a/test/old-elf/Mips/rel-call-hilo-micro.test b/test/old-elf/Mips/rel-call-hilo-micro.test
deleted file mode 100644
index 0df68def92b3..000000000000
--- a/test/old-elf/Mips/rel-call-hilo-micro.test
+++ /dev/null
@@ -1,154 +0,0 @@
-# Check handling of R_MICROMIPS_CALL_HI16 / R_MICROMIPS_CALL_LO16 relocations.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t1.so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2.so %t2.so.o %t1.so
-# RUN: llvm-objdump -s -t %t2.so | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -mips-plt-got %t2.so | FileCheck -check-prefix=GOT %s
-
-# RAW: Contents of section .text:
-# RAW-NEXT: 0130 00000000 00001880 00000000 00002080
-# ^ -32744 ^ -32736
-# RAW-NEXT: 0140 00000000 00001c80 00000000 00002480
-# ^ -32740 ^ -32732
-# RAW-NEXT: 0150 00000000 00000000
-
-# RAW: SYMBOL TABLE:
-# RAW: 00000140 l F .text 00000014 T1
-# RAW: 00000154 l F .text 00000004 M1
-
-# GOT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x140
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x155
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1014
-# GOT-NEXT: Access: -32732
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: M2@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# t1.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: M2
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
-
-# t2.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 40
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MICROMIPS_CALL_HI16
- - Offset: 4
- Symbol: T1
- Type: R_MICROMIPS_CALL_LO16
- - Offset: 8
- Symbol: T2
- Type: R_MICROMIPS_CALL_HI16
- - Offset: 12
- Symbol: T2
- Type: R_MICROMIPS_CALL_LO16
- - Offset: 16
- Symbol: M1
- Type: R_MICROMIPS_CALL_HI16
- - Offset: 20
- Symbol: M1
- Type: R_MICROMIPS_CALL_LO16
- - Offset: 24
- Symbol: M2
- Type: R_MICROMIPS_CALL_HI16
- - Offset: 28
- Symbol: M2
- Type: R_MICROMIPS_CALL_LO16
-
-Symbols:
- Local:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 16
- Size: 4
- - Name: M1
- Section: .text
- Type: STT_FUNC
- Value: 36
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 16
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
- - Name: M2
-...
diff --git a/test/old-elf/Mips/rel-copy-micro.test b/test/old-elf/Mips/rel-copy-micro.test
deleted file mode 100644
index ba47c84a2c5c..000000000000
--- a/test/old-elf/Mips/rel-copy-micro.test
+++ /dev/null
@@ -1,159 +0,0 @@
-# Check R_MIPS_COPY relocation emitting
-# when linking non-shared executable file.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so1.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t-so1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-so2.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2.so %t-so2.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t1.so %t2.so
-# RUN: llvm-readobj -dt -r -dynamic-table %t.exe | FileCheck %s
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (5) .rel.dyn {
-# CHECK-NEXT: 0x402010 R_MIPS_COPY D1 0x0
-# CHECK-NEXT: 0x402018 R_MIPS_COPY D2 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D1@ (1)
-# CHECK-NEXT: Value: 0x402010
-# CHECK-NEXT: Size: 8
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .bss
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D2@ (4)
-# CHECK-NEXT: Value: 0x402018
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .bss
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSection [ ({{.*}} entries)
-# CHECK: 0x00000001 NEEDED SharedLibrary (rel-copy-micro.test.tmp1.so)
-# CHECK: 0x00000001 NEEDED SharedLibrary (rel-copy-micro.test.tmp2.so)
-# CHECK-NEXT: 0x00000000 NULL 0x0
-# CHECK-NEXT: ]
-
-# so1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
-
-# so2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x04
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MICROMIPS_HI16
- - Offset: 0x00
- Symbol: D1
- Type: R_MICROMIPS_LO16
- - Offset: 0x08
- Symbol: D2
- Type: R_MICROMIPS_HI16
- - Offset: 0x08
- Symbol: D2
- Type: R_MICROMIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
-...
diff --git a/test/old-elf/Mips/rel-copy-pc.test b/test/old-elf/Mips/rel-copy-pc.test
deleted file mode 100644
index cf723f53719c..000000000000
--- a/test/old-elf/Mips/rel-copy-pc.test
+++ /dev/null
@@ -1,113 +0,0 @@
-# Check R_MIPS_COPY relocation emitting caused by R_MIPS_PCHI16 / R_MIPS_PCLO16
-# relocations when linking non-shared executable file.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r -dynamic-table %t.exe | FileCheck %s
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (5) .rel.dyn {
-# CHECK-NEXT: 0x402008 R_MIPS_COPY D1 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D1@ (1)
-# CHECK-NEXT: Value: 0x402008
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .bss
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSection [ ({{.*}} entries)
-# CHECK: 0x00000001 NEEDED SharedLibrary (rel-copy-pc.test.tmp.so)
-# CHECK-NEXT: 0x00000000 NULL 0x0
-# CHECK-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .data
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: D1
- Type: R_MIPS_PCHI16
- - Offset: 0
- Symbol: D1
- Type: R_MIPS_PCLO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0
- Size: 4
- - Name: D1
-...
diff --git a/test/old-elf/Mips/rel-copy.test b/test/old-elf/Mips/rel-copy.test
deleted file mode 100644
index 751034dcd728..000000000000
--- a/test/old-elf/Mips/rel-copy.test
+++ /dev/null
@@ -1,177 +0,0 @@
-# Check R_MIPS_COPY relocation emitting
-# when linking non-shared executable file.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so1.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t-so1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-so2.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2.so %t-so2.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t1.so %t2.so
-# RUN: llvm-readobj -dt -r -dynamic-table %t.exe | FileCheck %s
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (5) .rel.dyn {
-# CHECK-NEXT: 0x402004 R_MIPS_REL32 D2 0x0
-# CHECK-NEXT: 0x402010 R_MIPS_COPY D1 0x0
-# CHECK-NEXT: 0x402018 R_MIPS_COPY D3 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D1@ (1)
-# CHECK-NEXT: Value: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .bss
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D3@ (4)
-# CHECK-NEXT: Value: 0x{{[0-9A-F]+}}
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .bss
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D2@ (7)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSection [ ({{.*}} entries)
-# CHECK: 0x00000001 NEEDED SharedLibrary (rel-copy.test.tmp1.so)
-# CHECK: 0x00000001 NEEDED SharedLibrary (rel-copy.test.tmp2.so)
-# CHECK-NEXT: 0x00000000 NULL 0x0
-# CHECK-NEXT: ]
-
-# so1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# so2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x04
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: D3
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: D1
- Type: R_MIPS_LO16
- - Offset: 0x04
- Symbol: D2
- Type: R_MIPS_32
- - Offset: 0x08
- Symbol: D3
- Type: R_MIPS_HI16
- - Offset: 0x08
- Symbol: D3
- Type: R_MIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- - Name: D3
-...
diff --git a/test/old-elf/Mips/rel-dynamic-01-micro.test b/test/old-elf/Mips/rel-dynamic-01-micro.test
deleted file mode 100644
index 56dd7dfdeccd..000000000000
--- a/test/old-elf/Mips/rel-dynamic-01-micro.test
+++ /dev/null
@@ -1,201 +0,0 @@
-# REQUIRES: mips
-
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# Check:
-# a) Emitting R_MIPS_COPY, R_MIPS_JUMP_SLOT relocations.
-# b) PLT entries creation.
-# c) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -d -mattr=micromips %t.exe | FileCheck -check-prefix=DIS %s
-# RUN: llvm-readobj -dt -r %t.exe | FileCheck -check-prefix=PLT-SYM %s
-
-# DIS: Disassembly of section .plt:
-# DIS-NEXT: .plt:
-# DIS-NEXT: 4001b0: 80 79 94 07 addiupc $3, 7760
-# DIS-NEXT: 4001b4: 23 ff 00 00 lw $25, 0($3)
-# DIS-NEXT: 4001b8: 35 05 subu16 $2, $2, $3
-# DIS-NEXT: 4001ba: 25 25 srl16 $2, $2, 2
-# DIS-NEXT: 4001bc: 02 33 fe ff addiu $24, $2, -2
-# DIS-NEXT: 4001c0: ff 0d move $15, $ra
-# DIS-NEXT: 4001c2: f9 45 jalrs16 $25
-# DIS-NEXT: 4001c4: 83 0f move $gp, $3
-# DIS-NEXT: 4001c6: 00 0c nop
-
-# DIS-NEXT: 4001c8: 00 79 90 07 addiupc $2, 7744
-# DIS-NEXT: 4001cc: 22 ff 00 00 lw $25, 0($2)
-# DIS-NEXT: 4001d0: 99 45 jr16 $25
-# DIS-NEXT: 4001d2: 02 0f move $24, $2
-
-# DIS-NEXT: 4001d4: 00 79 8e 07 addiupc $2, 7736
-# DIS-NEXT: 4001d8: 22 ff 00 00 lw $25, 0($2)
-# DIS-NEXT: 4001dc: 99 45 jr16 $25
-# DIS-NEXT: 4001de: 02 0f move $24, $2
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: Section (5) .rel.dyn {
-# PLT-SYM-NEXT: 0x402020 R_MIPS_COPY D1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Section (6) .rel.plt {
-# PLT-SYM-NEXT: 0x402008 R_MIPS_JUMP_SLOT T3 0x0
-# PLT-SYM-NEXT: 0x40200C R_MIPS_JUMP_SLOT T1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: DynamicSymbols [
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: @ (0)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Local (0x0)
-# PLT-SYM-NEXT: Type: None (0x0)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: D1@ (1)
-# PLT-SYM-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-SYM-NEXT: Size: 8
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Object (0x1)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: .bss
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T1@ (4)
-# PLT-SYM-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 8
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T3@ (7)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
-
-# o.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T3
- Type: R_MICROMIPS_26_S1
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_LO16
- - Offset: 0x04
- Symbol: D1
- Type: R_MICROMIPS_HI16
- - Offset: 0x04
- Symbol: D1
- Type: R_MICROMIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
-...
diff --git a/test/old-elf/Mips/rel-dynamic-01.test b/test/old-elf/Mips/rel-dynamic-01.test
deleted file mode 100644
index e24449eeeb58..000000000000
--- a/test/old-elf/Mips/rel-dynamic-01.test
+++ /dev/null
@@ -1,261 +0,0 @@
-# REQUIRES: mips
-
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# Check:
-# a) Emitting R_MIPS_REL32, R_MIPS_COPY, R_MIPS_JUMP_SLOT relocations.
-# b) PLT entries creation.
-# c) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -disassemble %t.exe | FileCheck -check-prefix=PLT %s
-# RUN: llvm-readobj -dt -r %t.exe | FileCheck -check-prefix=PLT-SYM %s
-# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
-
-# PLT: Disassembly of section .plt:
-# PLT-NEXT: .plt:
-# PLT-NEXT: 4001f0: 40 00 1c 3c lui $gp, 64
-# PLT-NEXT: 4001f4: 00 20 99 8f lw $25, 8192($gp)
-# PLT-NEXT: 4001f8: 00 20 9c 27 addiu $gp, $gp, 8192
-# PLT-NEXT: 4001fc: 23 c0 1c 03 subu $24, $24, $gp
-# PLT-NEXT: 400200: 25 78 e0 03 move $15, $ra
-# PLT-NEXT: 400204: 82 c0 18 00 srl $24, $24, 2
-# PLT-NEXT: 400208: 09 f8 20 03 jalr $25
-# PLT-NEXT: 40020c: fe ff 18 27 addiu $24, $24, -2
-#
-# PLT-NEXT: 400210: 40 00 0f 3c lui $15, 64
-# PLT-NEXT: 400214: 08 20 f9 8d lw $25, 8200($15)
-# PLT-NEXT: 400218: 08 00 20 03 jr $25
-# PLT-NEXT: 40021c: 08 20 f8 25 addiu $24, $15, 8200
-#
-# PLT-NEXT: 400220: 40 00 0f 3c lui $15, 64
-# PLT-NEXT: 400224: 0c 20 f9 8d lw $25, 8204($15)
-# PLT-NEXT: 400228: 08 00 20 03 jr $25
-# PLT-NEXT: 40022c: 0c 20 f8 25 addiu $24, $15, 8204
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: Section (5) .rel.dyn {
-# PLT-SYM-NEXT: 0x402014 R_MIPS_REL32 T2 0x0
-# PLT-SYM-NEXT: 0x402014 R_MIPS_REL32 D2 0x0
-# PLT-SYM-NEXT: 0x402020 R_MIPS_COPY D1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Section (6) .rel.plt {
-# PLT-SYM-NEXT: 0x402008 R_MIPS_JUMP_SLOT T3 0x0
-# PLT-SYM-NEXT: 0x40200C R_MIPS_JUMP_SLOT T1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: DynamicSymbols [
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: @ (0)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Local (0x0)
-# PLT-SYM-NEXT: Type: None (0x0)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: D1@ (1)
-# PLT-SYM-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-SYM-NEXT: Size: 4
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Object (0x1)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: .bss
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T1@ (4)
-# PLT-SYM-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 8
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T3@ (10)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T2@ (7)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: D2@ (13)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 4
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Object (0x1)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x{{[0-9A-F]+}}
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x{{[0-9A-F]+}}
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D2@ (13)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T3
- Type: R_MIPS_26
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_LO16
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_32
-
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_HI16
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_LO16
- - Offset: 0x04
- Symbol: D2
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- Type: STT_OBJECT
-...
diff --git a/test/old-elf/Mips/rel-dynamic-02.test b/test/old-elf/Mips/rel-dynamic-02.test
deleted file mode 100644
index 24b7c624c6a0..000000000000
--- a/test/old-elf/Mips/rel-dynamic-02.test
+++ /dev/null
@@ -1,101 +0,0 @@
-# Conditions:
-# a) Linking a shared library.
-# b) Relocations' targets are undefined symbols.
-# Check:
-# a) Emitting R_MIPS_REL32 relocations for both undefined symbols.
-# b) There should be no PLT entries.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec -o %t.so %t.o
-# RUN: llvm-readobj -dt -r -s %t.so | FileCheck %s
-
-# CHECK: Sections [
-# CHECK: Section {
-# CHECK-NOT: Name: .plt ({{[0-9]+}})
-#
-# CHECK: Relocations [
-# CHECK-NEXT: Section (4) .rel.dyn {
-# CHECK-NEXT: 0x[[ADDR1:[0-9A-Z]+]] R_MIPS_REL32 T1 0x0
-# CHECK-NEXT: 0x[[ADDR2:[0-9A-Z]+]] R_MIPS_REL32 T1 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-#
-# CHECK: Symbol {
-# CHECK: Name: T0@
-# CHECK-NEXT: Value: 0x[[ADDR1]]
-# CHECK-NEXT: Size: 8
-# CHECK-NEXT: Binding: Global
-# CHECK-NEXT: Type: Function
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .text
-# CHECK-NEXT: }
-# CHECK: Symbol {
-# CHECK: Name: D0@
-# CHECK-NEXT: Value: 0x[[ADDR2]]
-# CHECK-NEXT: Size: 8
-# CHECK-NEXT: Binding: Global
-# CHECK-NEXT: Type: Object
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .data
-# CHECK-NEXT: }
-# CHECK: Symbol {
-# CHECK: Name: T1@
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global
-# CHECK-NEXT: Type: None
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined
-# CHECK-NEXT: }
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_32
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T1
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0
- Size: 8
diff --git a/test/old-elf/Mips/rel-dynamic-03-micro.test b/test/old-elf/Mips/rel-dynamic-03-micro.test
deleted file mode 100644
index 891649d8cdbc..000000000000
--- a/test/old-elf/Mips/rel-dynamic-03-micro.test
+++ /dev/null
@@ -1,133 +0,0 @@
-# REQUIRES: mips
-
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' target is a symbol defined in the shared object.
-# c) The target symbol is referenced by both branch (R_MICROMIPS_26_S1)
-# and regular (R_MIPS_32) relocations.
-# Check:
-# a) There should be no R_MIPS_REL32 relocation.
-# b) Linker creates a single PLT entry.
-# c) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -d -mattr=micromips %t.exe | FileCheck -check-prefix=DIS %s
-# RUN: llvm-readobj -dt -r %t.exe | FileCheck -check-prefix=PLT-SYM %s
-
-# DIS: Disassembly of section .plt:
-# DIS-NEXT: .plt:
-# DIS-NEXT: 400170: 80 79 a4 07 addiupc $3, 7824
-# DIS-NEXT: 400174: 23 ff 00 00 lw $25, 0($3)
-# DIS-NEXT: 400178: 35 05 subu16 $2, $2, $3
-# DIS-NEXT: 40017a: 25 25 srl16 $2, $2, 2
-# DIS-NEXT: 40017c: 02 33 fe ff addiu $24, $2, -2
-# DIS-NEXT: 400180: ff 0d move $15, $ra
-# DIS-NEXT: 400182: f9 45 jalrs16 $25
-# DIS-NEXT: 400184: 83 0f move $gp, $3
-# DIS-NEXT: 400186: 00 0c nop
-
-# DIS-NEXT: 400188: 00 79 a0 07 addiupc $2, 7808
-# DIS-NEXT: 40018c: 22 ff 00 00 lw $25, 0($2)
-# DIS-NEXT: 400190: 99 45 jr16 $25
-# DIS-NEXT: 400192: 02 0f move $24, $2
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: Section (5) .rel.plt {
-# PLT-SYM-NEXT: 0x402008 R_MIPS_JUMP_SLOT T1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: Name: T1@ (1)
-# PLT-SYM-NEXT: Value: 0x400189
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 8
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
-
-# o.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T1
- Type: R_MICROMIPS_26_S1
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T1
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
-...
diff --git a/test/old-elf/Mips/rel-dynamic-03.test b/test/old-elf/Mips/rel-dynamic-03.test
deleted file mode 100644
index 2552473ca80f..000000000000
--- a/test/old-elf/Mips/rel-dynamic-03.test
+++ /dev/null
@@ -1,129 +0,0 @@
-# REQUIRES: mips
-
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' target is a symbol defined in the shared object.
-# c) The target symbol is referenced by both branch (R_MIPS_26)
-# and regular (R_MIPS_32) relocations.
-# Check:
-# a) There should be no R_MIPS_REL32 relocation.
-# b) Linker creates a single PLT entry.
-# c) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -disassemble %t.exe | FileCheck -check-prefix=PLT %s
-# RUN: llvm-readobj -dt -r %t.exe | FileCheck -check-prefix=PLT-SYM %s
-
-# PLT: Disassembly of section .plt:
-# PLT-NEXT: .plt:
-# PLT-NEXT: 400160: 40 00 1c 3c lui $gp, 64
-# PLT-NEXT: 400164: 00 20 99 8f lw $25, 8192($gp)
-# PLT-NEXT: 400168: 00 20 9c 27 addiu $gp, $gp, 8192
-# PLT-NEXT: 40016c: 23 c0 1c 03 subu $24, $24, $gp
-# PLT-NEXT: 400170: 25 78 e0 03 move $15, $ra
-# PLT-NEXT: 400174: 82 c0 18 00 srl $24, $24, 2
-# PLT-NEXT: 400178: 09 f8 20 03 jalr $25
-# PLT-NEXT: 40017c: fe ff 18 27 addiu $24, $24, -2
-#
-# PLT-NEXT: 400180: 40 00 0f 3c lui $15, 64
-# PLT-NEXT: 400184: 08 20 f9 8d lw $25, 8200($15)
-# PLT-NEXT: 400188: 08 00 20 03 jr $25
-# PLT-NEXT: 40018c: 08 20 f8 25 addiu $24, $15, 8200
-#
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: Section (5) .rel.plt {
-# PLT-SYM-NEXT: 0x402008 R_MIPS_JUMP_SLOT T1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: Name: T1@ (1)
-# PLT-SYM-NEXT: Value: 0x400180
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 8
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T1
- Type: R_MIPS_26
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T1
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
-...
diff --git a/test/old-elf/Mips/rel-dynamic-04-micro.test b/test/old-elf/Mips/rel-dynamic-04-micro.test
deleted file mode 100644
index de1131c67f43..000000000000
--- a/test/old-elf/Mips/rel-dynamic-04-micro.test
+++ /dev/null
@@ -1,226 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# c) Relocations modify a writable section.
-# d) The first symbol is referenced by R_MIPS32 relocation only
-# e) The second symbol is referenced by R_MIPS_32
-# and R_MICROMIPS_26_S1 relocations.
-# f) The third symbol is referenced by R_MICROMIPS_26_S1
-# and R_MIPS_32 relocations.
-# Check:
-# a) There should be the only R_MIPS_REL32 relocation.
-# b) Linker creates a couple of PLT entry for both symbols referenced
-# by the R_MICROMIPS_26_S1 branch relocation.
-# c) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r -s %t.exe | FileCheck -check-prefix=PLT %s
-# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
-
-# PLT: Section {
-# PLT: Index: 5
-# PLT-NEXT: Name: .rel.dyn (31)
-# PLT-NEXT: Type: SHT_REL (0x9)
-# PLT-NEXT: Flags [ (0x2)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x4010A0
-# PLT-NEXT: Offset: 0x10A0
-# PLT-NEXT: Size: 8
-# PLT-NEXT: Link: 3
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 4
-# PLT-NEXT: EntrySize: 8
-# PLT-NEXT: }
-# PLT-NEXT: Section {
-# PLT-NEXT: Index: 6
-# PLT-NEXT: Name: .rel.plt (40)
-# PLT-NEXT: Type: SHT_REL (0x9)
-# PLT-NEXT: Flags [ (0x2)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x4010A8
-# PLT-NEXT: Offset: 0x10A8
-# PLT-NEXT: Size: 16
-# PLT-NEXT: Link: 3
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 4
-# PLT-NEXT: EntrySize: 8
-# PLT-NEXT: }
-# PLT-NEXT: Section {
-# PLT-NEXT: Index: 7
-# PLT-NEXT: Name: .plt (49)
-# PLT-NEXT: Type: SHT_PROGBITS (0x1)
-# PLT-NEXT: Flags [ (0x6)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: SHF_EXECINSTR (0x4)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x4010C0
-# PLT-NEXT: Offset: 0x10C0
-# PLT-NEXT: Size: 48
-# PLT-NEXT: Link: 0
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 16
-# PLT-NEXT: EntrySize: 0
-# PLT-NEXT: }
-
-# PLT: Relocations [
-# PLT-NEXT: Section (5) .rel.dyn {
-# PLT-NEXT: 0x400120 R_MIPS_REL32 T1 0x0
-# PLT-NEXT: }
-# PLT-NEXT: Section (6) .rel.plt {
-# PLT-NEXT: 0x403008 R_MIPS_JUMP_SLOT T2 0x0
-# PLT-NEXT: 0x40300C R_MIPS_JUMP_SLOT T3 0x0
-# PLT-NEXT: }
-# PLT-NEXT: ]
-
-# PLT: DynamicSymbols [
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: @ (0)
-# PLT-NEXT: Value: 0x0
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Local (0x0)
-# PLT-NEXT: Type: None (0x0)
-# PLT-NEXT: Other: 0
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T2@ (4)
-# PLT-NEXT: Value: 0x4010D9
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T3@ (7)
-# PLT-NEXT: Value: 0x4010E5
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T1@ (1)
-# PLT-NEXT: Value: 0x0
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 0
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x402008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
-
-# o.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x14
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- # There is no branch relocation for T1.
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_32
- # The R_MIPS_32 relocation for T2 might produce R_MIPS_REL32 ...
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_32
- # ... but R_MICROMIPS_26_S1 creates PLT entry
- # and makes R_MIPS_REL32 redundant.
- - Offset: 0x08
- Symbol: T2
- Type: R_MICROMIPS_26_S1
- # Create PLT entry for T3 symbol.
- - Offset: 0x0c
- Symbol: T3
- Type: R_MICROMIPS_26_S1
- # Take in account existing PLT entry and do not create R_MIPS_REL32.
- - Offset: 0x10
- Symbol: T3
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x14
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
-...
diff --git a/test/old-elf/Mips/rel-dynamic-04.test b/test/old-elf/Mips/rel-dynamic-04.test
deleted file mode 100644
index df8c676af330..000000000000
--- a/test/old-elf/Mips/rel-dynamic-04.test
+++ /dev/null
@@ -1,221 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# c) Relocations modify a writable section.
-# d) The first symbol is referenced by R_MIPS32 relocation only
-# e) The second symbol is referenced by R_MIPS_32 and R_MIPS26 relocations.
-# f) The third symbol is referenced by R_MIPS26 and R_MIPS_32 relocations.
-# Check:
-# a) There should be the only R_MIPS_REL32 relocation.
-# b) Linker creates a couple of PLT entry for both symbols referenced
-# by the R_MIPS_26 branch relocation.
-# c) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r -s %t.exe | FileCheck -check-prefix=PLT %s
-# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
-
-# PLT: Section {
-# PLT: Index: 5
-# PLT-NEXT: Name: .rel.dyn (31)
-# PLT-NEXT: Type: SHT_REL (0x9)
-# PLT-NEXT: Flags [ (0x2)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x40109C
-# PLT-NEXT: Offset: 0x109C
-# PLT-NEXT: Size: 8
-# PLT-NEXT: Link: 3
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 4
-# PLT-NEXT: EntrySize: 8
-# PLT-NEXT: }
-# PLT-NEXT: Section {
-# PLT-NEXT: Index: 6
-# PLT-NEXT: Name: .rel.plt (40)
-# PLT-NEXT: Type: SHT_REL (0x9)
-# PLT-NEXT: Flags [ (0x2)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x4010A4
-# PLT-NEXT: Offset: 0x10A4
-# PLT-NEXT: Size: 16
-# PLT-NEXT: Link: 3
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 4
-# PLT-NEXT: EntrySize: 8
-# PLT-NEXT: }
-# PLT-NEXT: Section {
-# PLT-NEXT: Index: 7
-# PLT-NEXT: Name: .plt (49)
-# PLT-NEXT: Type: SHT_PROGBITS (0x1)
-# PLT-NEXT: Flags [ (0x6)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: SHF_EXECINSTR (0x4)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x4010C0
-# PLT-NEXT: Offset: 0x10C0
-# PLT-NEXT: Size: 64
-# PLT-NEXT: Link: 0
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 16
-# PLT-NEXT: EntrySize: 0
-# PLT-NEXT: }
-
-# PLT: Relocations [
-# PLT-NEXT: Section (5) .rel.dyn {
-# PLT-NEXT: 0x400120 R_MIPS_REL32 T1 0x0
-# PLT-NEXT: }
-# PLT-NEXT: Section (6) .rel.plt {
-# PLT-NEXT: 0x403008 R_MIPS_JUMP_SLOT T2 0x0
-# PLT-NEXT: 0x40300C R_MIPS_JUMP_SLOT T3 0x0
-# PLT-NEXT: }
-# PLT-NEXT: ]
-
-# PLT: DynamicSymbols [
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: @ (0)
-# PLT-NEXT: Value: 0x0
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Local (0x0)
-# PLT-NEXT: Type: None (0x0)
-# PLT-NEXT: Other: 0
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T2@ (4)
-# PLT-NEXT: Value: 0x4010E0
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T3@ (7)
-# PLT-NEXT: Value: 0x4010F0
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T1@ (1)
-# PLT-NEXT: Value: 0x0
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 0
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x402008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
-
-# o.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- # There is no branch relocation for T1.
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_32
- # The R_MIPS_32 relocation for T2 might produce R_MIPS_REL32 ...
- - Offset: 0x00
- Symbol: T2
- Type: R_MIPS_32
- # ... but R_MIPS_26 creates PLT entry and makes R_MIPS_REL32 redundant.
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_26
- # Create PLT entry for T3 symbol.
- - Offset: 0x00
- Symbol: T3
- Type: R_MIPS_26
- # Take in account existing PLT entry and do not create R_MIPS_REL32.
- - Offset: 0x04
- Symbol: T3
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
-...
diff --git a/test/old-elf/Mips/rel-dynamic-05-micro.test b/test/old-elf/Mips/rel-dynamic-05-micro.test
deleted file mode 100644
index 16c6a9c6aad5..000000000000
--- a/test/old-elf/Mips/rel-dynamic-05-micro.test
+++ /dev/null
@@ -1,192 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# c) Relocations modify a read-only section.
-# d) The first symbol is referenced by R_MIPS32 relocation only
-# e) The second symbol is referenced by R_MIPS_32
-# and R_MICROMIPS_26_S1 relocations.
-# f) The third symbol is referenced by R_MICROMIPS_26_S1
-# and R_MIPS_32 relocations.
-# Check:
-# a) There should be no R_MIPS_REL32 relocations.
-# b) Linker creates PLT entries for all three relocations.
-# c) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r -s %t.exe | FileCheck -check-prefix=PLT %s
-
-# PLT: Section {
-# PLT: Index: 5
-# PLT-NEXT: Name: .rel.plt (31)
-# PLT-NEXT: Type: SHT_REL (0x9)
-# PLT-NEXT: Flags [ (0x2)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x400194
-# PLT-NEXT: Offset: 0x194
-# PLT-NEXT: Size: 24
-# PLT-NEXT: Link: 3
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 4
-# PLT-NEXT: EntrySize: 8
-# PLT-NEXT: }
-# PLT-NEXT: Section {
-# PLT-NEXT: Index: 6
-# PLT-NEXT: Name: .plt (40)
-# PLT-NEXT: Type: SHT_PROGBITS (0x1)
-# PLT-NEXT: Flags [ (0x6)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: SHF_EXECINSTR (0x4)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x4001B0
-# PLT-NEXT: Offset: 0x1B0
-# PLT-NEXT: Size: 60
-# PLT-NEXT: Link: 0
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 16
-# PLT-NEXT: EntrySize: 0
-# PLT-NEXT: }
-
-# PLT: Relocations [
-# PLT-NEXT: Section (5) .rel.plt {
-# PLT-NEXT: 0x402008 R_MIPS_JUMP_SLOT T1 0x0
-# PLT-NEXT: 0x40200C R_MIPS_JUMP_SLOT T2 0x0
-# PLT-NEXT: 0x402010 R_MIPS_JUMP_SLOT T3 0x0
-# PLT-NEXT: }
-# PLT-NEXT: ]
-
-# PLT: DynamicSymbols [
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: @ (0)
-# PLT-NEXT: Value: 0x0
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Local (0x0)
-# PLT-NEXT: Type: None (0x0)
-# PLT-NEXT: Other: 0
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T1@ (1)
-# PLT-NEXT: Value: 0x4001C9
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T2@ (4)
-# PLT-NEXT: Value: 0x4001D5
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T3@ (7)
-# PLT-NEXT: Value: 0x4001E1
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
-
-# o.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x14
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- # There is no branch relocation for T1.
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_32
- # The R_MIPS_32 relocation for T2 might produce R_MIPS_REL32 ...
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_32
- # ... but R_MICROMIPS_26_S1 creates PLT entry and makes R_MIPS_REL32 redundant.
- - Offset: 0x08
- Symbol: T2
- Type: R_MICROMIPS_26_S1
- # Create PLT entry for T3 symbol.
- - Offset: 0x0C
- Symbol: T3
- Type: R_MICROMIPS_26_S1
- # Take in account existing PLT entry and do not create R_MIPS_REL32.
- - Offset: 0x10
- Symbol: T3
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 0x14
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
-...
diff --git a/test/old-elf/Mips/rel-dynamic-05.test b/test/old-elf/Mips/rel-dynamic-05.test
deleted file mode 100644
index 8348bc511fbd..000000000000
--- a/test/old-elf/Mips/rel-dynamic-05.test
+++ /dev/null
@@ -1,188 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# c) Relocations modify a read-only section.
-# d) The first symbol is referenced by R_MIPS32 relocation only
-# e) The second symbol is referenced by R_MIPS_32 and R_MIPS26 relocations.
-# f) The third symbol is referenced by R_MIPS26 and R_MIPS_32 relocations.
-# Check:
-# a) There should be no R_MIPS_REL32 relocations.
-# b) Linker creates PLT entries for all three relocations.
-# c) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r -s %t.exe | FileCheck -check-prefix=PLT %s
-
-# PLT: Section {
-# PLT: Index: 5
-# PLT-NEXT: Name: .rel.plt (31)
-# PLT-NEXT: Type: SHT_REL (0x9)
-# PLT-NEXT: Flags [ (0x2)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x{{[0-9A-F]+}}
-# PLT-NEXT: Offset: 0x{{[0-9A-F]+}}
-# PLT-NEXT: Size: 24
-# PLT-NEXT: Link: 3
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 4
-# PLT-NEXT: EntrySize: 8
-# PLT-NEXT: }
-# PLT-NEXT: Section {
-# PLT-NEXT: Index: 6
-# PLT-NEXT: Name: .plt (40)
-# PLT-NEXT: Type: SHT_PROGBITS (0x1)
-# PLT-NEXT: Flags [ (0x6)
-# PLT-NEXT: SHF_ALLOC (0x2)
-# PLT-NEXT: SHF_EXECINSTR (0x4)
-# PLT-NEXT: ]
-# PLT-NEXT: Address: 0x{{[0-9A-F]+}}
-# PLT-NEXT: Offset: 0x{{[0-9A-F]+}}
-# PLT-NEXT: Size: 80
-# PLT-NEXT: Link: 0
-# PLT-NEXT: Info: 0
-# PLT-NEXT: AddressAlignment: 16
-# PLT-NEXT: EntrySize: 0
-# PLT-NEXT: }
-
-# PLT: Relocations [
-# PLT-NEXT: Section (5) .rel.plt {
-# PLT-NEXT: {{[0-9A-F]+}} R_MIPS_JUMP_SLOT T1 0x0
-# PLT-NEXT: {{[0-9A-F]+}} R_MIPS_JUMP_SLOT T2 0x0
-# PLT-NEXT: {{[0-9A-F]+}} R_MIPS_JUMP_SLOT T3 0x0
-# PLT-NEXT: }
-# PLT-NEXT: ]
-
-# PLT: DynamicSymbols [
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: @ (0)
-# PLT-NEXT: Value: 0x0
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Local (0x0)
-# PLT-NEXT: Type: None (0x0)
-# PLT-NEXT: Other: 0
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T1@ (1)
-# PLT-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T2@ (4)
-# PLT-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: Symbol {
-# PLT-NEXT: Name: T3@ (7)
-# PLT-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-NEXT: Size: 0
-# PLT-NEXT: Binding: Global (0x1)
-# PLT-NEXT: Type: Function (0x2)
-# PLT-NEXT: Other: 8
-# PLT-NEXT: Section: Undefined (0x0)
-# PLT-NEXT: }
-# PLT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
-
-# o.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- # There is no branch relocation for T1.
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_32
- # The R_MIPS_32 relocation for T2 might produce R_MIPS_REL32 ...
- - Offset: 0x00
- Symbol: T2
- Type: R_MIPS_32
- # ... but R_MIPS_26 creates PLT entry and makes R_MIPS_REL32 redundant.
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_26
- # Create PLT entry for T3 symbol.
- - Offset: 0x00
- Symbol: T3
- Type: R_MIPS_26
- # Take in account existing PLT entry and do not create R_MIPS_REL32.
- - Offset: 0x04
- Symbol: T3
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
-...
diff --git a/test/old-elf/Mips/rel-dynamic-06-64.test b/test/old-elf/Mips/rel-dynamic-06-64.test
deleted file mode 100644
index 6b0d28993f94..000000000000
--- a/test/old-elf/Mips/rel-dynamic-06-64.test
+++ /dev/null
@@ -1,114 +0,0 @@
-# Conditions:
-# a) Linking a shared library.
-# b) The first relocation modifies a regular .text section.
-# c) The second relocation modifies a .pdr section without SHF_ALLOC flag.
-# Check:
-# a) There should be no PLT entries.
-# b) Linker creates a single R_MIPS_REL32 relocation.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t.o
-# RUN: llvm-readobj -dt -r -s %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-readobj -mips-plt-got %t.so | FileCheck -check-prefix=GOT %s
-
-# SYM: Sections [
-# SYM: Section {
-# SYM-NOT: Name: .plt ({{[0-9]+}})
-
-# SYM: Relocations [
-# SYM-NEXT: Section (4) .rel.dyn {
-# SYM-NEXT: 0x[[ADDR:[0-9A-Z]+]] R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T0 0x0
-# SYM-NEXT: }
-# SYM-NEXT: ]
-
-# SYM: Symbol {
-# SYM: Name: @ (0)
-# SYM-NEXT: Value: 0x0
-# SYM-NEXT: Size: 0
-# SYM-NEXT: Binding: Local (0x0)
-# SYM-NEXT: Type: None (0x0)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: Undefined (0x0)
-# SYM-NEXT: }
-# SYM: Symbol {
-# SYM: Name: T1@ (4)
-# SYM-NEXT: Value: 0x174
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x5)
-# SYM-NEXT: }
-# SYM: Symbol {
-# SYM: Name: T0@ (1)
-# SYM-NEXT: Value: 0x[[ADDR]]
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x5)
-# SYM-NEXT: }
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x170
-# GOT-NEXT: Value: 0x170
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: .text (0x5)
-# GOT-NEXT: Name: T0@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_RELA
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T0
- Type: R_MIPS_64
-
-- Name: .pdr
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
-
-- Name: .rel.pdr
- Type: SHT_RELA
- Info: .pdr
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_64
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
diff --git a/test/old-elf/Mips/rel-dynamic-06.test b/test/old-elf/Mips/rel-dynamic-06.test
deleted file mode 100644
index ead7dfb08ddf..000000000000
--- a/test/old-elf/Mips/rel-dynamic-06.test
+++ /dev/null
@@ -1,115 +0,0 @@
-# Conditions:
-# a) Linking a shared library.
-# b) The first relocation modifies a regular .text section.
-# c) The second relocation modifies a .pdr section without SHF_ALLOC flag.
-# Check:
-# a) There should be no PLT entries.
-# b) Linker creates a single R_MIPS_REL32 relocation.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -dt -r -s %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-readobj -mips-plt-got %t.so | FileCheck -check-prefix=GOT %s
-
-# SYM: Sections [
-# SYM: Section {
-# SYM-NOT: Name: .plt ({{[0-9]+}})
-
-# SYM: Relocations [
-# SYM-NEXT: Section (4) .rel.dyn {
-# SYM-NEXT: 0x[[ADDR:[0-9A-Z]+]] R_MIPS_REL32 T0 0x0
-# SYM-NEXT: }
-# SYM-NEXT: ]
-
-# SYM: Symbol {
-# SYM: Name: @ (0)
-# SYM-NEXT: Value: 0x0
-# SYM-NEXT: Size: 0
-# SYM-NEXT: Binding: Local (0x0)
-# SYM-NEXT: Type: None (0x0)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: Undefined (0x0)
-# SYM-NEXT: }
-# SYM: Symbol {
-# SYM: Name: T1@ (4)
-# SYM-NEXT: Value: 0x104
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x5)
-# SYM-NEXT: }
-# SYM: Symbol {
-# SYM: Name: T0@ (1)
-# SYM-NEXT: Value: 0x[[ADDR]]
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x5)
-# SYM-NEXT: }
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x100
-# GOT-NEXT: Value: 0x100
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: .text (0x5)
-# GOT-NEXT: Name: T0@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T0
- Type: R_MIPS_32
-
-- Name: .pdr
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: []
-
-- Name: .rel.pdr
- Type: SHT_REL
- Info: .pdr
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
diff --git a/test/old-elf/Mips/rel-dynamic-07-64.test b/test/old-elf/Mips/rel-dynamic-07-64.test
deleted file mode 100644
index 823a66d521e2..000000000000
--- a/test/old-elf/Mips/rel-dynamic-07-64.test
+++ /dev/null
@@ -1,348 +0,0 @@
-# Conditions:
-# a) Linking a shared library.
-# b) There ars multiple R_MIPS_64 relocations with various targets.
-# Check:
-# a) Emitting of R_MIPS_REL32 relocations.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t1.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -shared --noinhibit-exec \
-# RUN: -o %t2.so %t-o.o %t1.so
-# RUN: llvm-readobj -dt -r -sections %t2.so | FileCheck %s
-# RUN: llvm-readobj -mips-plt-got %t2.so | FileCheck -check-prefix=GOT %s
-
-# CHECK: Sections [
-# CHECK: Section {
-# CHECK-NOT: Name: .plt ({{[0-9]+}})
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (4) .rel.dyn {
-# CHECK-NEXT: 0x2000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T0 0x0
-# CHECK-NEXT: 0x2000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T4 0x0
-# CHECK-NEXT: 0x2000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D2 0x0
-# CHECK-NEXT: 0x2004 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T1 0x0
-# CHECK-NEXT: 0x2008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T2 0x0
-# CHECK-NEXT: 0x2004 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D0 0x0
-# CHECK-NEXT: 0x2008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D1 0x0
-# CHECK-NEXT: 0x2004 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D4 0x0
-# CHECK-NEXT: 0x2008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE U1 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T0@ (1)
-# CHECK-NEXT: Value: 0x324
-# CHECK-NEXT: Size: 8
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .text (0x5)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T4@ (7)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D2@ (25)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T1@ (16)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T2@ (19)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D0@ (4)
-# CHECK-NEXT: Value: 0x2004
-# CHECK-NEXT: Size: 8
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .data (0x8)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D1@ (22)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D4@ (10)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: U1@ (13)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x324
-# GOT-NEXT: Value: 0x324
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: .text (0x5)
-# GOT-NEXT: Name: T0@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1018
-# GOT-NEXT: Access: -32728
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: None (0x0)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T4@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1020
-# GOT-NEXT: Access: -32720
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D2@ (25)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1028
-# GOT-NEXT: Access: -32712
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (16)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1030
-# GOT-NEXT: Access: -32704
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (19)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1038
-# GOT-NEXT: Access: -32696
-# GOT-NEXT: Initial: 0x2004
-# GOT-NEXT: Value: 0x2004
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: .data (0x8)
-# GOT-NEXT: Name: D0@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1040
-# GOT-NEXT: Access: -32688
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D1@ (22)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1048
-# GOT-NEXT: Access: -32680
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: None (0x0)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D4@ (10)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1050
-# GOT-NEXT: Access: -32672
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: None (0x0)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: U1@ (13)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00 # T0 is a defined function
- Symbol: T0
- Type: R_MIPS_64
- - Offset: 0x04 # T1 is a function from shared lib
- Symbol: T1
- Type: R_MIPS_64
- - Offset: 0x08 # T2 has unknown type and defined in shared lib
- Symbol: T2
- Type: R_MIPS_64
- - Offset: 0x00 # T4 is an undefined function
- Symbol: T4
- Type: R_MIPS_64
- - Offset: 0x04 # D0 is a defined data object
- Symbol: D0
- Type: R_MIPS_64
- - Offset: 0x08 # D1 is a data object from shared lib
- Symbol: D1
- Type: R_MIPS_64
- - Offset: 0x00 # D2 has unknown type and defined in shared lib
- Symbol: D2
- Type: R_MIPS_64
- - Offset: 0x04 # D4 is an undefined data object
- Symbol: D4
- Type: R_MIPS_64
- - Offset: 0x08 # U1 is undefined and has unknown type
- Symbol: U1
- Type: R_MIPS_64
-
-Symbols:
- Local:
- - Name: LT0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: LD0
- Section: .data
- Type: STT_OBJECT
- Value: 0
- Size: 4
-
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- - Name: T4
- Type: STT_FUNC
-
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- - Name: D4
- Type: STT_OBJECT
- - Name: U1
-...
diff --git a/test/old-elf/Mips/rel-dynamic-07.test b/test/old-elf/Mips/rel-dynamic-07.test
deleted file mode 100644
index 41c31c66a5f3..000000000000
--- a/test/old-elf/Mips/rel-dynamic-07.test
+++ /dev/null
@@ -1,363 +0,0 @@
-# Conditions:
-# a) Linking a shared library.
-# b) There ars multiple R_MIPS_32 relocations with various targets.
-# Check:
-# a) Emitting of R_MIPS_REL32 relocations.
-# b) There should be no R_MIPS_REL32 relocations for the _gp_disp symbol.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -shared --noinhibit-exec \
-# RUN: -o %t2.so %t-o.o %t1.so
-# RUN: llvm-readobj -dt -r -sections %t2.so | FileCheck %s
-# RUN: llvm-readobj -mips-plt-got %t2.so | FileCheck -check-prefix=GOT %s
-
-# CHECK: Sections [
-# CHECK: Section {
-# CHECK-NOT: Name: .plt ({{[0-9]+}})
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (4) .rel.dyn {
-# CHECK-NEXT: 0x2000 R_MIPS_REL32 T0 0x0
-# CHECK-NEXT: 0x2000 R_MIPS_REL32 T4 0x0
-# CHECK-NEXT: 0x2000 R_MIPS_REL32 D2 0x0
-# CHECK-NEXT: 0x2004 R_MIPS_REL32 T1 0x0
-# CHECK-NEXT: 0x2008 R_MIPS_REL32 T2 0x0
-# CHECK-NEXT: 0x2004 R_MIPS_REL32 D0 0x0
-# CHECK-NEXT: 0x2008 R_MIPS_REL32 D1 0x0
-# CHECK-NEXT: 0x2004 R_MIPS_REL32 D4 0x0
-# CHECK-NEXT: 0x2008 R_MIPS_REL32 U1 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T0@ (1)
-# CHECK-NEXT: Value: 0x214
-# CHECK-NEXT: Size: 8
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .text (0x5)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T4@ (7)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D2@ (25)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T1@ (16)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T2@ (19)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D0@ (4)
-# CHECK-NEXT: Value: 0x2004
-# CHECK-NEXT: Size: 8
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .data (0x8)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D1@ (22)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D4@ (10)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: U1@ (13)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x214
-# GOT-NEXT: Value: 0x214
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: .text (0x5)
-# GOT-NEXT: Name: T0@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: None (0x0)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T4@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D2@ (25)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1014
-# GOT-NEXT: Access: -32732
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (16)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1018
-# GOT-NEXT: Access: -32728
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (19)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x101C
-# GOT-NEXT: Access: -32724
-# GOT-NEXT: Initial: 0x2004
-# GOT-NEXT: Value: 0x2004
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: .data (0x8)
-# GOT-NEXT: Name: D0@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1020
-# GOT-NEXT: Access: -32720
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D1@ (22)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1024
-# GOT-NEXT: Access: -32716
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: None (0x0)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D4@ (10)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1028
-# GOT-NEXT: Access: -32712
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: None (0x0)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: U1@ (13)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: _gp_disp
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: _gp_disp
- Type: R_MIPS_LO16
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00 # T0 is a defined function
- Symbol: T0
- Type: R_MIPS_32
- - Offset: 0x04 # T1 is a function from shared lib
- Symbol: T1
- Type: R_MIPS_32
- - Offset: 0x08 # T2 has unknown type and defined in shared lib
- Symbol: T2
- Type: R_MIPS_32
- - Offset: 0x00 # T4 is an undefined function
- Symbol: T4
- Type: R_MIPS_32
- - Offset: 0x04 # D0 is a defined data object
- Symbol: D0
- Type: R_MIPS_32
- - Offset: 0x08 # D1 is a data object from shared lib
- Symbol: D1
- Type: R_MIPS_32
- - Offset: 0x00 # D2 has unknown type and defined in shared lib
- Symbol: D2
- Type: R_MIPS_32
- - Offset: 0x04 # D4 is an undefined data object
- Symbol: D4
- Type: R_MIPS_32
- - Offset: 0x08 # U1 is undefined and has unknown type
- Symbol: U1
- Type: R_MIPS_32
-
-Symbols:
- Local:
- - Name: LT0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: LD0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
-
- Global:
- - Name: _gp_disp
- Type: STT_OBJECT
-
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- - Name: T4
- Type: STT_FUNC
-
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- - Name: D4
- Type: STT_OBJECT
- - Name: U1
diff --git a/test/old-elf/Mips/rel-dynamic-08-64.test b/test/old-elf/Mips/rel-dynamic-08-64.test
deleted file mode 100644
index 019b8e5161a8..000000000000
--- a/test/old-elf/Mips/rel-dynamic-08-64.test
+++ /dev/null
@@ -1,275 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) There ars multiple R_MIPS_64/R_MIPS_HI16/R_MIPS_LO16 relocations
-# with various targets.
-# Check:
-# a) Emitting of R_MIPS_REL32 relocations.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 --noinhibit-exec \
-# RUN: -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r -sections %t.exe | FileCheck %s
-# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
-
-# CHECK: Sections [
-# CHECK: Section {
-# CHECK-NOT: Name: .plt ({{[0-9]+}})
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (5) .rel.dyn {
-# CHECK-NEXT: 0x120002000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D2 0x0
-# CHECK-NEXT: 0x120002004 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T1 0x0
-# CHECK-NEXT: 0x120002008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T2 0x0
-# CHECK-NEXT: 0x120002008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D1 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D2@ (10)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T1@ (1)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T2@ (4)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D1@ (7)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D2@ (10)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001018
-# GOT-NEXT: Access: -32728
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001020
-# GOT-NEXT: Access: -32720
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x120001028
-# GOT-NEXT: Access: -32712
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D1@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_RELA
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: _gp_disp
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: _gp_disp
- Type: R_MIPS_LO16
-
-- Name: .rel.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00 # LT0 is a locally defined function
- Symbol: LT0
- Type: R_MIPS_64
- - Offset: 0x00 # LD0 is a locally defined data object
- Symbol: LD0
- Type: R_MIPS_64
- - Offset: 0x00 # T0 is a defined function
- Symbol: T0
- Type: R_MIPS_64
- - Offset: 0x04 # T1 is a function from shared lib
- Symbol: T1
- Type: R_MIPS_64
- - Offset: 0x08 # T2 has unknown type and defined in shared lib
- Symbol: T2
- Type: R_MIPS_64
- - Offset: 0x00 # T4 is an undefined function
- Symbol: T4
- Type: R_MIPS_64
- - Offset: 0x04 # D0 is a defined data object
- Symbol: D0
- Type: R_MIPS_64
- - Offset: 0x08 # D1 is a data object from shared lib
- Symbol: D1
- Type: R_MIPS_64
- - Offset: 0x00 # D2 has unknown type and defined in shared lib
- Symbol: D2
- Type: R_MIPS_64
- - Offset: 0x04 # D4 is an undefined data object
- Symbol: D4
- Type: R_MIPS_64
- - Offset: 0x08 # U1 is undefined and has unknown type
- Symbol: U1
- Type: R_MIPS_64
-
-Symbols:
- Local:
- - Name: LT0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: LD0
- Section: .data
- Type: STT_OBJECT
- Value: 0
- Size: 4
-
- Global:
- - Name: _gp_disp
- Type: STT_OBJECT
-
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- - Name: T4
- Type: STT_FUNC
-
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- - Name: D4
- Type: STT_OBJECT
- - Name: U1
-...
diff --git a/test/old-elf/Mips/rel-dynamic-08-micro.test b/test/old-elf/Mips/rel-dynamic-08-micro.test
deleted file mode 100644
index 2d25b504ee28..000000000000
--- a/test/old-elf/Mips/rel-dynamic-08-micro.test
+++ /dev/null
@@ -1,278 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) There ars multiple R_MIPS_32/R_MICROMIPS_HI16/R_MICROMIPS_LO16
-# relocations with various targets.
-# Check:
-# a) Emitting of R_MIPS_REL32 relocations.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 --noinhibit-exec \
-# RUN: -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r -sections %t.exe | FileCheck %s
-# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
-
-# CHECK: Sections [
-# CHECK: Section {
-# CHECK-NOT: Name: .plt ({{[0-9]+}})
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (5) .rel.dyn {
-# CHECK-NEXT: 0x402000 R_MIPS_REL32 D2 0x0
-# CHECK-NEXT: 0x402004 R_MIPS_REL32 T1 0x0
-# CHECK-NEXT: 0x402008 R_MIPS_REL32 T2 0x0
-# CHECK-NEXT: 0x402008 R_MIPS_REL32 D1 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D2@ (10)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T1@ (1)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T2@ (4)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D1@ (7)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D2@ (10)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x40100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401014
-# GOT-NEXT: Access: -32732
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D1@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: _gp_disp
- Type: R_MICROMIPS_HI16
- - Offset: 0x00
- Symbol: _gp_disp
- Type: R_MICROMIPS_LO16
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00 # LT0 is a locally defined function
- Symbol: LT0
- Type: R_MIPS_32
- - Offset: 0x00 # LD0 is a locally defined data object
- Symbol: LD0
- Type: R_MIPS_32
- - Offset: 0x00 # T0 is a defined function
- Symbol: T0
- Type: R_MIPS_32
- - Offset: 0x04 # T1 is a function from shared lib
- Symbol: T1
- Type: R_MIPS_32
- - Offset: 0x08 # T2 has unknown type and defined in shared lib
- Symbol: T2
- Type: R_MIPS_32
- - Offset: 0x00 # T4 is an undefined function
- Symbol: T4
- Type: R_MIPS_32
- - Offset: 0x04 # D0 is a defined data object
- Symbol: D0
- Type: R_MIPS_32
- - Offset: 0x08 # D1 is a data object from shared lib
- Symbol: D1
- Type: R_MIPS_32
- - Offset: 0x00 # D2 has unknown type and defined in shared lib
- Symbol: D2
- Type: R_MIPS_32
- - Offset: 0x04 # D4 is an undefined data object
- Symbol: D4
- Type: R_MIPS_32
- - Offset: 0x08 # U1 is undefined and has unknown type
- Symbol: U1
- Type: R_MIPS_32
-
-Symbols:
- Local:
- - Name: LT0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: LD0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
-
- Global:
- - Name: _gp_disp
- Type: STT_OBJECT
-
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- - Name: T4
- Type: STT_FUNC
-
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- - Name: D4
- Type: STT_OBJECT
- - Name: U1
-...
diff --git a/test/old-elf/Mips/rel-dynamic-08.test b/test/old-elf/Mips/rel-dynamic-08.test
deleted file mode 100644
index a89e6ecf480e..000000000000
--- a/test/old-elf/Mips/rel-dynamic-08.test
+++ /dev/null
@@ -1,275 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) There ars multiple R_MIPS_32/R_MIPS_HI16/R_MIPS_LO16 relocations
-# with various targets.
-# Check:
-# a) Emitting of R_MIPS_REL32 relocations.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 --noinhibit-exec \
-# RUN: -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r -sections %t.exe | FileCheck %s
-# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
-
-# CHECK: Sections [
-# CHECK: Section {
-# CHECK-NOT: Name: .plt ({{[0-9]+}})
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (5) .rel.dyn {
-# CHECK-NEXT: 0x402000 R_MIPS_REL32 D2 0x0
-# CHECK-NEXT: 0x402004 R_MIPS_REL32 T1 0x0
-# CHECK-NEXT: 0x402008 R_MIPS_REL32 T2 0x0
-# CHECK-NEXT: 0x402008 R_MIPS_REL32 D1 0x0
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# CHECK: DynamicSymbols [
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: @ (0)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Local (0x0)
-# CHECK-NEXT: Type: None (0x0)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D2@ (10)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T1@ (1)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: T2@ (4)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 0
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D1@ (7)
-# CHECK-NEXT: Value: 0x0
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: Undefined (0x0)
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D2@ (10)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x40100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T1@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401014
-# GOT-NEXT: Access: -32732
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D1@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: _gp_disp
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: _gp_disp
- Type: R_MIPS_LO16
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00 # LT0 is a locally defined function
- Symbol: LT0
- Type: R_MIPS_32
- - Offset: 0x00 # LD0 is a locally defined data object
- Symbol: LD0
- Type: R_MIPS_32
- - Offset: 0x00 # T0 is a defined function
- Symbol: T0
- Type: R_MIPS_32
- - Offset: 0x04 # T1 is a function from shared lib
- Symbol: T1
- Type: R_MIPS_32
- - Offset: 0x08 # T2 has unknown type and defined in shared lib
- Symbol: T2
- Type: R_MIPS_32
- - Offset: 0x00 # T4 is an undefined function
- Symbol: T4
- Type: R_MIPS_32
- - Offset: 0x04 # D0 is a defined data object
- Symbol: D0
- Type: R_MIPS_32
- - Offset: 0x08 # D1 is a data object from shared lib
- Symbol: D1
- Type: R_MIPS_32
- - Offset: 0x00 # D2 has unknown type and defined in shared lib
- Symbol: D2
- Type: R_MIPS_32
- - Offset: 0x04 # D4 is an undefined data object
- Symbol: D4
- Type: R_MIPS_32
- - Offset: 0x08 # U1 is undefined and has unknown type
- Symbol: U1
- Type: R_MIPS_32
-
-Symbols:
- Local:
- - Name: LT0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: LD0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
-
- Global:
- - Name: _gp_disp
- Type: STT_OBJECT
-
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- - Name: T4
- Type: STT_FUNC
-
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- - Name: D4
- Type: STT_OBJECT
- - Name: U1
-...
diff --git a/test/old-elf/Mips/rel-dynamic-09-micro.test b/test/old-elf/Mips/rel-dynamic-09-micro.test
deleted file mode 100644
index 2011ae079645..000000000000
--- a/test/old-elf/Mips/rel-dynamic-09-micro.test
+++ /dev/null
@@ -1,109 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are undefined symbols.
-# Check:
-# a) There should be no dynamic relocations.
-# b) There should be no PLT entries.
-#
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel --noinhibit-exec -e T0 -o %t2-exe %t-obj
-# RUN: llvm-readobj -dt -r -s %t2-exe | FileCheck -check-prefix=PLT-SYM %s
-
-# PLT-SYM: Sections [
-# PLT-SYM: Section {
-# PLT-SYM-NOT: Name: .plt ({{[0-9]+}})
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: DynamicSymbols [
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: @ (0)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Local (0x0)
-# PLT-SYM-NEXT: Type: None (0x0)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T3
- Type: R_MICROMIPS_26_S1
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_LO16
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_32
-
- - Offset: 0x04
- Symbol: D1
- Type: R_MICROMIPS_HI16
- - Offset: 0x04
- Symbol: D1
- Type: R_MICROMIPS_LO16
- - Offset: 0x04
- Symbol: D2
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- Type: STT_OBJECT
diff --git a/test/old-elf/Mips/rel-dynamic-09.test b/test/old-elf/Mips/rel-dynamic-09.test
deleted file mode 100644
index 9b02ec1b5707..000000000000
--- a/test/old-elf/Mips/rel-dynamic-09.test
+++ /dev/null
@@ -1,107 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are undefined symbols.
-# Check:
-# a) There should be no dynamic relocations.
-# b) There should be no PLT entries.
-#
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel --noinhibit-exec -e T0 -o %t2-exe %t-obj
-# RUN: llvm-readobj -dt -r -s %t2-exe | FileCheck -check-prefix=PLT-SYM %s
-
-# PLT-SYM: Sections [
-# PLT-SYM: Section {
-# PLT-SYM-NOT: Name: .plt ({{[0-9]+}})
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: DynamicSymbols [
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: @ (0)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Local (0x0)
-# PLT-SYM-NEXT: Type: None (0x0)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T3
- Type: R_MIPS_26
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_LO16
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_32
-
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_HI16
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_LO16
- - Offset: 0x04
- Symbol: D2
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- Type: STT_OBJECT
diff --git a/test/old-elf/Mips/rel-dynamic-10-micro.test b/test/old-elf/Mips/rel-dynamic-10-micro.test
deleted file mode 100644
index 4600af85c27c..000000000000
--- a/test/old-elf/Mips/rel-dynamic-10-micro.test
+++ /dev/null
@@ -1,166 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the other object.
-# Check:
-# a) There should be no dynamic relocations.
-# b) There should be no PLT entries.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o2.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o1.o %t-o2.o
-# RUN: llvm-readobj -dt -r -s %t.exe | FileCheck -check-prefix=PLT-SYM %s
-
-# PLT-SYM: Sections [
-# PLT-SYM: Section {
-# PLT-SYM-NOT: Name: .plt ({{[0-9]+}})
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: DynamicSymbols [
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: @ (0)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Local (0x0)
-# PLT-SYM-NEXT: Type: None (0x0)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# o1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o2.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T3
- Type: R_MICROMIPS_26_S1
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_LO16
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_32
-
- - Offset: 0x04
- Symbol: D1
- Type: R_MICROMIPS_HI16
- - Offset: 0x04
- Symbol: D1
- Type: R_MICROMIPS_LO16
- - Offset: 0x04
- Symbol: D2
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- Type: STT_OBJECT
-...
diff --git a/test/old-elf/Mips/rel-dynamic-10.test b/test/old-elf/Mips/rel-dynamic-10.test
deleted file mode 100644
index 68a311df73e4..000000000000
--- a/test/old-elf/Mips/rel-dynamic-10.test
+++ /dev/null
@@ -1,160 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the other object.
-# Check:
-# a) There should be no dynamic relocations.
-# b) There should be no PLT entries.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o2.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o1.o %t-o2.o
-# RUN: llvm-readobj -dt -r -s %t.exe | FileCheck -check-prefix=PLT-SYM %s
-
-# PLT-SYM: Sections [
-# PLT-SYM: Section {
-# PLT-SYM-NOT: Name: .plt ({{[0-9]+}})
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: DynamicSymbols [
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: @ (0)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Local (0x0)
-# PLT-SYM-NEXT: Type: None (0x0)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# o1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o2.o
----
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T3
- Type: R_MIPS_26
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_HI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_LO16
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_32
-
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_HI16
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_LO16
- - Offset: 0x04
- Symbol: D2
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- Type: STT_OBJECT
-...
diff --git a/test/old-elf/Mips/rel-dynamic-11.test b/test/old-elf/Mips/rel-dynamic-11.test
deleted file mode 100644
index 01edbd64812f..000000000000
--- a/test/old-elf/Mips/rel-dynamic-11.test
+++ /dev/null
@@ -1,110 +0,0 @@
-# Conditions:
-# a) Linking a shared library.
-# b) Relocations' targets are symbols defined in the other shared object.
-# Check:
-# a) Emitting R_MIPS_REL32 relocations for both symbols.
-# b) There should be no PLT entries.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2.so %t-o.o %t1.so
-# RUN: llvm-readobj -dt -r -s %t2.so | FileCheck -check-prefix=PLT-SYM %s
-
-# PLT-SYM: Sections [
-# PLT-SYM: Section {
-# PLT-SYM-NOT: Name: .plt ({{[0-9]+}})
-#
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: Section (4) .rel.dyn {
-# PLT-SYM-NEXT: 0x150 R_MIPS_REL32 T1 0x0
-# PLT-SYM-NEXT: 0x2000 R_MIPS_REL32 T1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-#
-# PLT-SYM: Name: T1@ (7)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_32
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T1
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
-...
diff --git a/test/old-elf/Mips/rel-dynamic-12.test b/test/old-elf/Mips/rel-dynamic-12.test
deleted file mode 100644
index c684df3f2628..000000000000
--- a/test/old-elf/Mips/rel-dynamic-12.test
+++ /dev/null
@@ -1,237 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# c) Relocations are R_MIPS_PCHI16 / R_MIPS_PCLO16.
-# Check:
-# a) Emitting R_MIPS_REL32, R_MIPS_COPY, R_MIPS_JUMP_SLOT relocations.
-# b) STO_MIPS_PLT flag in the dynamic symbol table for symbols require
-# a pointer equality.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r %t.exe | FileCheck -check-prefix=PLT-SYM %s
-# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: Section (5) .rel.dyn {
-# PLT-SYM-NEXT: 0x402014 R_MIPS_REL32 T2 0x0
-# PLT-SYM-NEXT: 0x402014 R_MIPS_REL32 D2 0x0
-# PLT-SYM-NEXT: 0x402020 R_MIPS_COPY D1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Section (6) .rel.plt {
-# PLT-SYM-NEXT: 0x402008 R_MIPS_JUMP_SLOT T3 0x0
-# PLT-SYM-NEXT: 0x40200C R_MIPS_JUMP_SLOT T1 0x0
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# PLT-SYM: DynamicSymbols [
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: @ (0)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Local (0x0)
-# PLT-SYM-NEXT: Type: None (0x0)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: D1@ (1)
-# PLT-SYM-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-SYM-NEXT: Size: 4
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Object (0x1)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: .bss
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T1@ (4)
-# PLT-SYM-NEXT: Value: 0x{{[0-9A-F]+}}
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 8
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T3@ (10)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T2@ (7)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 0
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Function (0x2)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: D2@ (13)
-# PLT-SYM-NEXT: Value: 0x0
-# PLT-SYM-NEXT: Size: 4
-# PLT-SYM-NEXT: Binding: Global (0x1)
-# PLT-SYM-NEXT: Type: Object (0x1)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: ]
-
-# GOT: Local entries [
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x{{[0-9A-F]+}}
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x{{[0-9A-F]+}}
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Object (0x1)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: D2@ (13)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x0C
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
- - Name: T3
- Section: .text
- Type: STT_FUNC
- Value: 0x8
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 4
- - Name: D2
- Section: .data
- Type: STT_OBJECT
- Value: 0x4
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x04
- Symbol: T3
- Type: R_MIPS_26
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_PCHI16
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_PCLO16
- - Offset: 0x04
- Symbol: T2
- Type: R_MIPS_32
-
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_PCHI16
- - Offset: 0x04
- Symbol: D1
- Type: R_MIPS_PCLO16
- - Offset: 0x04
- Symbol: D2
- Type: R_MIPS_32
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: T3
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
- - Name: D2
- Type: STT_OBJECT
-...
diff --git a/test/old-elf/Mips/rel-dynamic-13.test b/test/old-elf/Mips/rel-dynamic-13.test
deleted file mode 100644
index 2bf014e51025..000000000000
--- a/test/old-elf/Mips/rel-dynamic-13.test
+++ /dev/null
@@ -1,94 +0,0 @@
-# Conditions:
-# a) Linking a non-shared 32-bit executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# Check:
-# a) Emitting R_MIPS_REL32 relocation.
-# b) Applying addendum from the original relocation.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
-
-# RAW: Contents of section .data:
-# RAW-NEXT: 402000 01000000
-
-# REL: Relocations [
-# REL-NEXT: Section (5) .rel.dyn {
-# REL-NEXT: 0x402000 R_MIPS_REL32 T1 0x0
-# REL-NEXT: }
-# REL-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_32
- Addend: 1
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T1
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/rel-dynamic-14.test b/test/old-elf/Mips/rel-dynamic-14.test
deleted file mode 100644
index 33197ae92b81..000000000000
--- a/test/old-elf/Mips/rel-dynamic-14.test
+++ /dev/null
@@ -1,94 +0,0 @@
-# Conditions:
-# a) Linking a non-shared 64-bit executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# Check:
-# a) Emitting R_MIPS_REL32/R_MIPS_64 relocation.
-# b) Applying addendum from the original relocation.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
-
-# RAW: Contents of section .data:
-# RAW-NEXT: 120002000 04000000 00000000
-
-# REL: Relocations [
-# REL-NEXT: Section (5) .rel.dyn {
-# REL-NEXT: 0x120002000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T1 0x0
-# REL-NEXT: }
-# REL-NEXT: ]
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_64
- Addend: 4
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T1
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/rel-dynamic-15.test b/test/old-elf/Mips/rel-dynamic-15.test
deleted file mode 100644
index 13e2083bfc02..000000000000
--- a/test/old-elf/Mips/rel-dynamic-15.test
+++ /dev/null
@@ -1,81 +0,0 @@
-# Check that LLD generates dynamic relocation R_MIPS_REL32 for local
-# symbols if the symbols referenced by R_MIPS_32 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s
-
-# RAW: Contents of section .text:
-# RAW-NEXT: 0120 00000000 00000000
-# RAW: Contents of section .data.rel.local:
-# RAW-NEXT: 2000 20010000 00000000
-
-# REL: Relocations [
-# REL-NEXT: Section (4) .rel.dyn {
-# REL-NEXT: 0x2000 R_MIPS_REL32 - 0x0
-# REL-NEXT: 0x2004 R_MIPS_REL32 T1 0x0
-# REL-NEXT: }
-# REL-NEXT: ]
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 8
-
- - Name: .data.rel.local
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 4
- Size: 8
-
- - Name: .rel.data.rel.local
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .data.rel.local
- Relocations:
- - Offset: 0
- Symbol: .text
- Type: R_MIPS_32
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_32
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
- - Name: .data.rel.local
- Type: STT_SECTION
- Section: .data.rel.local
-
- Global:
- - Name: D0
- Type: STT_OBJECT
- Section: .data.rel.local
- Value: 0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 4
- Size: 4
-...
diff --git a/test/old-elf/Mips/rel-eh-01.test b/test/old-elf/Mips/rel-eh-01.test
deleted file mode 100644
index 08e5d78683a8..000000000000
--- a/test/old-elf/Mips/rel-eh-01.test
+++ /dev/null
@@ -1,186 +0,0 @@
-# Check R_MIPS_EH relocation handling: writing result of a relocation
-# calculation, adding GOT entries etc.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t1.o %t2.o %t.so
-# RUN: llvm-objdump -s -t %t.exe | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
-
-# RAW: Contents of section .gnu_extab:
-# RAW-NEXT: 400178 001880ff ff000000 1c80ffff 2080ffff
-# ^ T1 GOT entry = 0xffff8018 = -32744
-# ^ L1 GOT entry = 0xffff801c = -32740
-# E1 GOT entry = 0xffff8020 = -32736 ^
-# RAW: Contents of section .got:
-# RAW-NEXT: 401000 00000000 00000080 60014000 00204000
-# RAW-NEXT: 401010 00000000
-
-# RAW: SYMBOL TABLE:
-# RAW: 00402000 l .data 00000004 L1
-# RAW: 00400160 g F .text 00000004 T1
-
-# GOT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x400160
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x40100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x402000
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: E1@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Number of TLS and multi-GOT entries: 0
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_PIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Global:
- - Name: E1
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
-
-# t1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_PIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
-
-# t2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_PIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
- AddressAlign: 16
- Size: 8
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [SHF_WRITE, SHF_ALLOC]
- AddressAlign: 16
- Size: 4
-
- - Name: .gnu_extab
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC]
- AddressAlign: 4
- Size: 16
-
- - Name: .rel.gnu_extab
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .gnu_extab
- Relocations:
- - Offset: 1
- Symbol: T1
- Type: R_MIPS_EH
- - Offset: 8
- Symbol: L1
- Type: R_MIPS_EH
- - Offset: 12
- Symbol: E1
- Type: R_MIPS_EH
-
- - Name: .eh_frame_entry
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC]
- AddressAlign: 4
- Content: "0000000100000001"
-
- - Name: .rel.eh_frame_entry
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .eh_frame_entry
- Relocations:
- - Offset: 0
- Symbol: .text
- Type: R_MIPS_PC32
- - Offset: 4
- Symbol: .gnu_extab
- Type: R_MIPS_PC32
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .gnu_extab
- Type: STT_SECTION
- Section: .gnu_extab
- - Name: L1
- Type: STT_OBJECT
- Section: .data
- Value: 0
- Size: 4
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 8
- - Name: E1
- - Name: T1
-...
diff --git a/test/old-elf/Mips/rel-eh-02.test b/test/old-elf/Mips/rel-eh-02.test
deleted file mode 100644
index e78c967ed301..000000000000
--- a/test/old-elf/Mips/rel-eh-02.test
+++ /dev/null
@@ -1,130 +0,0 @@
-# Conditions:
-# a) Linking a non-shared executable file.
-# b) Relocations' targets are symbols defined in the shared object.
-# Check:
-# a) The R_MIPS_REL32 relocation is not created for any symbols.
-# b) The R_MIPS_COPY relocation is created for the D1 symbol.
-# c) No entries in the dynamic symbols table has the STO_MIPS_PLT flag.
-#
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-readobj -dt -r %t.exe | FileCheck -check-prefix=PLT-SYM %s
-
-# PLT-SYM: Relocations [
-# PLT-SYM-NEXT: Section (5) .rel.dyn {
-# PLT-SYM-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY D1 0x0
-# PLT-SYM-NEXT: }
-
-# PLT-SYM: DynamicSymbols [
-# PLT-SYM-NOT: Other: 8
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 4
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
- - Name: D1
- Section: .data
- Type: STT_OBJECT
- Value: 0
- Size: 4
-
-# o.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_WRITE, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_26
- - Offset: 4
- Symbol: D1
- Type: R_MIPS_PC32
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_EH
- - Offset: 4
- Symbol: T2
- Type: R_MIPS_EH
- - Offset: 8
- Symbol: D1
- Type: R_MIPS_EH
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 8
- - Name: T1
- Type: STT_FUNC
- - Name: T2
- Type: STT_FUNC
- - Name: D0
- Section: .data
- Type: STT_OBJECT
- Value: 0x0
- Size: 8
- - Name: D1
- Type: STT_OBJECT
-...
diff --git a/test/old-elf/Mips/rel-eh-03.test b/test/old-elf/Mips/rel-eh-03.test
deleted file mode 100644
index 63ed74cd56f8..000000000000
--- a/test/old-elf/Mips/rel-eh-03.test
+++ /dev/null
@@ -1,128 +0,0 @@
-# Check R_MIPS_EH relocation handling in case of -pcrel-eh-reloc option.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 \
-# RUN: -pcrel-eh-reloc -o %t.exe %t1.o %t2.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck -check-prefix=RAW %s
-
-# RAW: Contents of section .gnu_extab:
-# RAW-NEXT: 400148 00e7ffff ff000000 b01e0000 00000000
-# ^ 0x400130 + 0 - 0x400149 = 0xffffffe7
-# ^ 0x402000 + 0 - 0x400150 = 0x1eb0
-# E1 GOT entry = 0xffff8020 = -32736 ^
-# RAW: Contents of section .got:
-# RAW-NEXT: 401000 00000000 00000080
-
-# RAW: SYMBOL TABLE:
-# RAW: 00402000 l .data 00000004 L1
-# RAW: 00400130 g F .text 00000004 T1
-
-# t1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_PIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
-
-# t2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_CPIC, EF_MIPS_PIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
- AddressAlign: 16
- Size: 8
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [SHF_WRITE, SHF_ALLOC]
- AddressAlign: 16
- Size: 4
-
- - Name: .gnu_extab
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC]
- AddressAlign: 4
- Size: 16
-
- - Name: .rel.gnu_extab
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .gnu_extab
- Relocations:
- - Offset: 1
- Symbol: T1
- Type: R_MIPS_EH
- - Offset: 8
- Symbol: L1
- Type: R_MIPS_EH
-
- - Name: .eh_frame_entry
- Type: SHT_PROGBITS
- Flags: [SHF_ALLOC]
- AddressAlign: 4
- Content: "0000000100000001"
-
- - Name: .rel.eh_frame_entry
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .eh_frame_entry
- Relocations:
- - Offset: 0
- Symbol: .text
- Type: R_MIPS_PC32
- - Offset: 4
- Symbol: .gnu_extab
- Type: R_MIPS_PC32
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .gnu_extab
- Type: STT_SECTION
- Section: .gnu_extab
- - Name: L1
- Type: STT_OBJECT
- Section: .data
- Value: 0
- Size: 4
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 8
- - Name: T1
-...
diff --git a/test/old-elf/Mips/rel-got-hilo-01.test b/test/old-elf/Mips/rel-got-hilo-01.test
deleted file mode 100644
index c73d8765cbd5..000000000000
--- a/test/old-elf/Mips/rel-got-hilo-01.test
+++ /dev/null
@@ -1,109 +0,0 @@
-# Check handling of R_MIPS_GOT_HI16 / R_MIPS_GOT_LO16 relocations.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t1.so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2.so %t2.so.o %t1.so
-# RUN: llvm-objdump -s -t %t2.so | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -mips-plt-got %t2.so | FileCheck -check-prefix=GOT %s
-
-# RAW: Contents of section .text:
-# RAW-NEXT: 0110 00000000 18800000 00000000 1c800000
-# ^ -32744 ^ -32740
-# RAW-NEXT: 0120 00000000
-
-# RAW: SYMBOL TABLE:
-# RAW: 00000120 l F .text 00000004 T1
-
-# GOT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x120
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# t1.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 4
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
-
-# t2.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 20
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_GOT_HI16
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_GOT_LO16
- - Offset: 8
- Symbol: T2
- Type: R_MIPS_GOT_HI16
- - Offset: 12
- Symbol: T2
- Type: R_MIPS_GOT_LO16
-
-Symbols:
- Local:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 16
- Size: 4
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 16
- - Name: T2
-...
diff --git a/test/old-elf/Mips/rel-got-hilo-micro.test b/test/old-elf/Mips/rel-got-hilo-micro.test
deleted file mode 100644
index 39dd1848f92e..000000000000
--- a/test/old-elf/Mips/rel-got-hilo-micro.test
+++ /dev/null
@@ -1,154 +0,0 @@
-# Check handling of R_MICROMIPS_GOT_HI16 / R_MICROMIPS_GOT_LO16 relocations.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t1.so %t1.so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.so.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t2.so %t2.so.o %t1.so
-# RUN: llvm-objdump -s -t %t2.so | FileCheck -check-prefix=RAW %s
-# RUN: llvm-readobj -mips-plt-got %t2.so | FileCheck -check-prefix=GOT %s
-
-# RAW: Contents of section .text:
-# RAW-NEXT: 0130 00000000 00001880 00000000 00002080
-# ^ -32744 ^ -32736
-# RAW-NEXT: 0140 00000000 00001c80 00000000 00002480
-# ^ -32740 ^ -32732
-# RAW-NEXT: 0150 00000000 00000000
-
-# RAW: SYMBOL TABLE:
-# RAW: 00000150 l F .text 00000004 T1
-# RAW: 00000154 l F .text 00000004 M1
-
-# GOT: Local entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1008
-# GOT-NEXT: Access: -32744
-# GOT-NEXT: Initial: 0x150
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x100C
-# GOT-NEXT: Access: -32740
-# GOT-NEXT: Initial: 0x155
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1010
-# GOT-NEXT: Access: -32736
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: T2@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x1014
-# GOT-NEXT: Access: -32732
-# GOT-NEXT: Initial: 0x0
-# GOT-NEXT: Value: 0x0
-# GOT-NEXT: Type: Function (0x2)
-# GOT-NEXT: Section: Undefined (0x0)
-# GOT-NEXT: Name: M2@ (7)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-
-# t1.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-Symbols:
- Global:
- - Name: T2
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: M2
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
-
-# t2.so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 40
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MICROMIPS_GOT_HI16
- - Offset: 4
- Symbol: T1
- Type: R_MICROMIPS_GOT_LO16
- - Offset: 8
- Symbol: T2
- Type: R_MICROMIPS_GOT_HI16
- - Offset: 12
- Symbol: T2
- Type: R_MICROMIPS_GOT_LO16
- - Offset: 16
- Symbol: M1
- Type: R_MICROMIPS_GOT_HI16
- - Offset: 20
- Symbol: M1
- Type: R_MICROMIPS_GOT_LO16
- - Offset: 24
- Symbol: M2
- Type: R_MICROMIPS_GOT_HI16
- - Offset: 28
- Symbol: M2
- Type: R_MICROMIPS_GOT_LO16
-
-Symbols:
- Local:
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 32
- Size: 4
- - Name: M1
- Section: .text
- Type: STT_FUNC
- Value: 36
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 32
- Other: [STO_MIPS_MICROMIPS]
- - Name: T2
- - Name: M2
-...
diff --git a/test/old-elf/Mips/rel-gprel16-micro-overflow.test b/test/old-elf/Mips/rel-gprel16-micro-overflow.test
deleted file mode 100644
index 7b023aecba41..000000000000
--- a/test/old-elf/Mips/rel-gprel16-micro-overflow.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# Check R_MICROMIPS_GPREL16 relocation overflow handling.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}} reference from +0 to L0+0 of type 136 (R_MICROMIPS_GPREL16)
-# CHECK: Relocation out of range in file {{.*}} reference from +4 to G0+0 of type 136 (R_MICROMIPS_GPREL16)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Type: SHT_PROGBITS
- Name: .text
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
-- Type: SHT_PROGBITS
- Name: .rodata
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Size: 8
-
-- Type: SHT_REL
- Name: .rel.rodata
- Link: .symtab
- Info: .rodata
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: L0
- Type: R_MICROMIPS_GPREL16
- - Offset: 4
- Symbol: G0
- Type: R_MICROMIPS_GPREL16
-
-Symbols:
- Local:
- - Name: L0
- Section: .text
- Value: 0
- Size: 4
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
- Global:
- - Name: G0
- Section: .text
- Value: 4
- Size: 4
diff --git a/test/old-elf/Mips/rel-gprel16-micro.test b/test/old-elf/Mips/rel-gprel16-micro.test
deleted file mode 100644
index c0119a51e484..000000000000
--- a/test/old-elf/Mips/rel-gprel16-micro.test
+++ /dev/null
@@ -1,78 +0,0 @@
-# Check R_MICROMIPS_GPREL16 relocation handling.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=SEC %s
-
-# SYM: Name: L0
-# SYM-NEXT: Value: 0x104
-# SYM-NEXT: Size: 4
-
-# SYM: Name: G0
-# SYM-NEXT: Value: 0x108
-# SYM-NEXT: Size: 4
-
-# SYM: Name: _gp
-# SYM-NEXT: Value: 0x8FF0
-# SYM-NEXT: Size: 0
-
-# SEC: Contents of section .rodata:
-# SEC-NEXT: 010c 00001071 000017f1
-# ^ 0x104 (L0) + 0x10000 (GP0) - 0x8ff0 (_gp) - 4 = 0x7110
-# ^ 0x108 (G0) - 0x8ff0 (_gp) + 0x7fff = 0xf117
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Type: SHT_PROGBITS
- Name: .text
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
-- Type: SHT_PROGBITS
- Name: .rodata
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: 0000fcff0000ff7f
-
-- Type: SHT_REL
- Name: .rel.rodata
- Link: .symtab
- Info: .rodata
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: L0
- Type: R_MICROMIPS_GPREL16
- - Offset: 4
- Symbol: G0
- Type: R_MICROMIPS_GPREL16
-
-- Type: SHT_MIPS_REGINFO
- Name: .reginfo
- Flags: [ SHF_ALLOC ]
- AddressAlign: 1
- Content: 000000000000000000000000000000000000000000000100
-
-Symbols:
- Local:
- - Name: L0
- Section: .text
- Value: 0
- Size: 4
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
- Global:
- - Name: G0
- Section: .text
- Value: 4
- Size: 4
diff --git a/test/old-elf/Mips/rel-gprel16-overflow.test b/test/old-elf/Mips/rel-gprel16-overflow.test
deleted file mode 100644
index 2943b5d200f4..000000000000
--- a/test/old-elf/Mips/rel-gprel16-overflow.test
+++ /dev/null
@@ -1,48 +0,0 @@
-# Check R_MIPS_GPREL16 relocation overflow handling.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}} reference from +0 to T1+-32768 of type 7 (R_MIPS_GPREL16)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Type: SHT_PROGBITS
- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 4
-
-- Type: SHT_PROGBITS
- Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: 00800000
-
-- Type: SHT_REL
- Name: .rel.rodata
- Type: SHT_REL
- Link: .symtab
- Info: .rodata
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_GPREL16
-
-Symbols:
- Global:
- - Name: T1
- Section: .text
- Value: 0
- Size: 4
diff --git a/test/old-elf/Mips/rel-gprel16.test b/test/old-elf/Mips/rel-gprel16.test
deleted file mode 100644
index d7e8a1a92598..000000000000
--- a/test/old-elf/Mips/rel-gprel16.test
+++ /dev/null
@@ -1,104 +0,0 @@
-# Check R_MIPS_GPREL16 relocation handling.
-#
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel -e G1 -shared -o %t.so %t-obj
-# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=SEC %s
-
-# SYM: Name: L1
-# SYM-NEXT: Value: 0x104
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Local (0x0)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x5)
-
-# SYM: Name: G1
-# SYM-NEXT: Value: 0x108
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x5)
-
-# SYM: Name: _gp
-# SYM-NEXT: Value: 0x8FF0
-# SYM-NEXT: Size: 0
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Object (0x1)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: Absolute (0xFFF1)
-
-# 0x6110 == 0xfffc (addend) + 0x0104 (L1) + 0xf000 (GP0) - 0x8ff0 (_gp)
-# SEC: Contents of section .rodata:
-# SEC-NEXT: 010c 10610008 00000000 00000000 00000000
-
-!ELF
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
-- Type: SHT_PROGBITS
- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
-
-- Type: SHT_REL
- Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0
- Symbol: .rodata
- Type: R_MIPS_GOT16
- - Offset: 4
- Symbol: .rodata
- Type: R_MIPS_LO16
-
-- Type: SHT_PROGBITS
- Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x04
- Content: fcff0008000000000000000000000000
-
-- Type: SHT_REL
- Name: .rel.rodata
- Type: SHT_REL
- Link: .symtab
- Info: .rodata
- AddressAlign: 0x04
- Relocations:
- - Offset: 0
- Symbol: L1
- Type: R_MIPS_GPREL16
-
-- Type: SHT_MIPS_REGINFO
- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x01
- Content: 000000000000000000000000000000000000000000f00000
-
-Symbols:
- Local:
- - Name: L1
- Section: .text
- Value: 0x00
- Size: 0x04
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
- Global:
- - Name: G1
- Section: .text
- Value: 0x04
- Size: 0x04
diff --git a/test/old-elf/Mips/rel-gprel32-64.test b/test/old-elf/Mips/rel-gprel32-64.test
deleted file mode 100644
index 15498a693e4d..000000000000
--- a/test/old-elf/Mips/rel-gprel32-64.test
+++ /dev/null
@@ -1,84 +0,0 @@
-# Check R_MIPS_GPREL32/R_MIPS_64 relocations handling.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t.o
-# RUN: llvm-readobj -r %t.exe | FileCheck --check-prefix=REL-EXE %s
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-# RUN: llvm-nm %t.exe | FileCheck --check-prefix=SYM %s
-
-# REL-EXE: Relocations [
-# REL-EXE-NEXT: ]
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 1200001d0 f871ffff ffffffff f871ffff f871ffff
-# CHECK-NEXT: 1200001e0 f871ffff ffffffff 00000000 00000000
-
-# SYM: 00000001200001e8 t LT1
-# SYM: 0000000120001000 N _GLOBAL_OFFSET_TABLE_
-
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t.o
-# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=REL-SO %s
-
-# REL-SO: Relocations [
-# REL-SO-NEXT: ]
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 32
-
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 8
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: LT1
- Type: R_MIPS_GPREL16
- Type2: R_MIPS_64
- Type3: R_MIPS_NONE
- - Offset: 0x08
- Symbol: LT1
- Type: R_MIPS_GPREL16
- Type2: R_MIPS_64
- Type3: R_MIPS_NONE
- - Offset: 0x0C
- Symbol: LT1
- Type: R_MIPS_GPREL32
- Type2: R_MIPS_64
- Type3: R_MIPS_NONE
- - Offset: 0x10
- Symbol: LT1
- Type: R_MIPS_GPREL32
- Type2: R_MIPS_64
- Type3: R_MIPS_NONE
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: LT1
- Type: STT_FUNC
- Section: .text
- Value: 0x18
- Size: 0x8
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0x0
- Size: 0x18
-...
diff --git a/test/old-elf/Mips/rel-gprel32.test b/test/old-elf/Mips/rel-gprel32.test
deleted file mode 100644
index 14ec8cebcabd..000000000000
--- a/test/old-elf/Mips/rel-gprel32.test
+++ /dev/null
@@ -1,84 +0,0 @@
-# Check R_MIPS_GPREL32 relocation handling.
-#
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel -o %t-exe %t-obj
-# RUN: llvm-readobj -symbols %t-exe | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t-exe | FileCheck -check-prefix=SEC %s
-
-# SYM: Name: $L1
-# SYM-NEXT: Value: 0x400160
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Local (0x0)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x6)
-#
-# SYM: Name: _gp
-# SYM-NEXT: Value: 0x408FF0
-# SYM-NEXT: Size: 0
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Object (0x1)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: Absolute (0xFFF1)
-
-# 0x08ff7153 == 0x8000001 (addend) + 0x400140 ($L1) +
-# 0x1000002 (GP0) - 0x408FF0 (_gp)
-# SEC: Contents of section .rodata:
-# SEC-NEXT: 400170 7371ff08 00000000 00000000 00000000
-
-!ELF
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
-- Type: SHT_PROGBITS
- Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: 00000000000000000000000000000000
-
-- Type: SHT_PROGBITS
- Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x04
- Content: 01000008000000000000000000000000
-
-- Type: SHT_REL
- Name: .rel.rodata
- Type: SHT_REL
- Link: .symtab
- Info: .rodata
- AddressAlign: 0x04
- Relocations:
- - Offset: 0
- Symbol: $L1
- Type: R_MIPS_GPREL32
-
-- Type: SHT_MIPS_REGINFO
- Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x01
- Content: 000000000000000000000000000000000000000002000001
-
-Symbols:
- Local:
- - Name: $L1
- Section: .text
- Value: 0x00
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
- Global:
- - Name: __start
- Section: .text
- Type: STT_FUNC
- Value: 0x04
- Size: 12
- - Name: _gp_disp
diff --git a/test/old-elf/Mips/rel-gprel7-micro-overflow.test b/test/old-elf/Mips/rel-gprel7-micro-overflow.test
deleted file mode 100644
index 5609786aa04a..000000000000
--- a/test/old-elf/Mips/rel-gprel7-micro-overflow.test
+++ /dev/null
@@ -1,48 +0,0 @@
-# Check R_MICROMIPS_GPREL7_S2 relocation overflow handling.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}} reference from +0 to L0+-4 of type 172 (R_MICROMIPS_GPREL7_S2)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Type: SHT_PROGBITS
- Name: .text
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 4
-
-- Type: SHT_PROGBITS
- Name: .rodata
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: 7f000000
-
-- Type: SHT_REL
- Name: .rel.rodata
- Link: .symtab
- Info: .rodata
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: L0
- Type: R_MICROMIPS_GPREL7_S2
-
-Symbols:
- Local:
- - Name: L0
- Section: .text
- Value: 0
- Size: 4
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
diff --git a/test/old-elf/Mips/rel-gprel7-micro.test b/test/old-elf/Mips/rel-gprel7-micro.test
deleted file mode 100644
index b7790d9d169c..000000000000
--- a/test/old-elf/Mips/rel-gprel7-micro.test
+++ /dev/null
@@ -1,65 +0,0 @@
-# Check R_MICROMIPS_GPREL7_S2 relocation handling.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=SEC %s
-
-# SYM: Name: L0
-# SYM-NEXT: Value: 0xF0
-# SYM-NEXT: Size: 4
-
-# SYM: Name: _gp
-# SYM-NEXT: Value: 0x8FF0
-# SYM-NEXT: Size: 0
-
-# SEC: Contents of section .rodata:
-# SEC-NEXT: 0f4 3b000000
-# ^ 0xf0 (L0) + 0x8ff0 (GP0) - 0x8ff0 (_gp) - 4 = 0xec >> 2
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
-- Type: SHT_PROGBITS
- Name: .text
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 4
-
-- Type: SHT_PROGBITS
- Name: .rodata
- Flags: [ SHF_ALLOC ]
- AddressAlign: 4
- Content: 7f000000
-
-- Type: SHT_REL
- Name: .rel.rodata
- Link: .symtab
- Info: .rodata
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: L0
- Type: R_MICROMIPS_GPREL7_S2
-
-- Type: SHT_MIPS_REGINFO
- Name: .reginfo
- Flags: [ SHF_ALLOC ]
- AddressAlign: 1
- Content: 0000000000000000000000000000000000000000f08f0000
-
-Symbols:
- Local:
- - Name: L0
- Section: .text
- Value: 0
- Size: 4
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
diff --git a/test/old-elf/Mips/rel-hi0-lo16-micro.test b/test/old-elf/Mips/rel-hi0-lo16-micro.test
deleted file mode 100644
index 82f62954b992..000000000000
--- a/test/old-elf/Mips/rel-hi0-lo16-micro.test
+++ /dev/null
@@ -1,58 +0,0 @@
-# Check handling of R_MICROMIPS_HI0_LO16 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400130 00000420
-# ^ 0x402000 + 0x4 = 0x402004
-
-# CHECK: 00402000 g .data 00000004 D0
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Content: "00000400"
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: D0
- Type: R_MICROMIPS_HI0_LO16
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_WRITE ]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
- - Name: D0
- Type: STT_OBJECT
- Section: .data
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/rel-high-01.test b/test/old-elf/Mips/rel-high-01.test
deleted file mode 100644
index 613fedbe31db..000000000000
--- a/test/old-elf/Mips/rel-high-01.test
+++ /dev/null
@@ -1,25 +0,0 @@
-# REQUIRES: mips
-
-# Check handling R_MIPS_HIGHER / R_MIPS_HIGHEST relocations.
-
-# RUN: llvm-mc -arch=mips64el -filetype=obj -o=%t.o %s
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: T0:
-# CHECK-NEXT: 120000250: 01 00 62 64 daddiu $2, $3, 1
-# CHECK-NEXT: 120000254: 00 00 62 64 daddiu $2, $3, 0
-#
-# CHECK: T1:
-# CHECK-NEXT: 120000258: 00 00 00 00 nop
-
- .text
- .globl T0
-T0:
- daddiu $2, $3, %higher(T1)
- daddiu $2, $3, %highest(T1)
-
- .globl T1
-T1:
- nop
diff --git a/test/old-elf/Mips/rel-high-02.test b/test/old-elf/Mips/rel-high-02.test
deleted file mode 100644
index 7a40a617a680..000000000000
--- a/test/old-elf/Mips/rel-high-02.test
+++ /dev/null
@@ -1,25 +0,0 @@
-# REQUIRES: mips
-
-# Check handling R_MICROMIPS_HIGHER / R_MICROMIPS_HIGHEST relocations.
-
-# RUN: llvm-mc -arch=mips64el -filetype=obj -o=%t.o %s
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: T0:
-# CHECK-NEXT: 120000250: 01 00 62 64 daddiu $2, $3, 1
-# CHECK-NEXT: 120000254: 00 00 62 64 daddiu $2, $3, 0
-#
-# CHECK: T1:
-# CHECK-NEXT: 120000258: 00 00 00 00 nop
-
- .text
- .globl T0
-T0:
- daddiu $2, $3, %higher(T1+0x0000800100000000)
- daddiu $2, $3, %highest(T1+0x4001000000000000)
-
- .globl T1
-T1:
- nop
diff --git a/test/old-elf/Mips/rel-jalr-01.test b/test/old-elf/Mips/rel-jalr-01.test
deleted file mode 100644
index 3c519056e1a9..000000000000
--- a/test/old-elf/Mips/rel-jalr-01.test
+++ /dev/null
@@ -1,101 +0,0 @@
-# REQUIRES: mips
-
-# Check handling of the R_MIPS_JALR relocation.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mipsel -o %t.exe %t2.o %t.so
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# CHECK: __start:
-# CHECK-NEXT: {{[0-9a-f]+}}: 05 00 11 04 bal 24
-# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
-# CHECK-NEXT: {{[0-9a-f]+}}: 04 00 00 10 b 20
-# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
-# CHECK-NEXT: {{[0-9a-f]+}}: 09 f8 20 03 jalr $25
-# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
-
-# t1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Global:
- - Name: T3
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
-
-# t2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Content: "09f8200300000000080020030000000009f82003000000000000000000000000"
-# ^ jalr T1 ^ j T2 ^ jalr T3
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_JALR
- - Offset: 8
- Symbol: T2
- Type: R_MIPS_JALR
- - Offset: 16
- Symbol: T3
- Type: R_MIPS_JALR
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 16
- Size: 0
-
-Symbols:
- Local:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 24
- Size: 4
- Global:
- - Name: __start
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 24
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Value: 28
- Size: 4
- - Name: T3
-...
diff --git a/test/old-elf/Mips/rel-jalr-02.test b/test/old-elf/Mips/rel-jalr-02.test
deleted file mode 100644
index e9c74c4c3300..000000000000
--- a/test/old-elf/Mips/rel-jalr-02.test
+++ /dev/null
@@ -1,68 +0,0 @@
-# REQUIRES: mips
-
-# Check R_MIPS_JALR relocations do not affect the code
-# in case of relocatable targets.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t.o
-# RUN: llvm-objdump -d %t.so | FileCheck %s
-
-# CHECK: __start:
-# CHECK-NEXT: {{[0-9a-f]+}}: 09 f8 20 03 jalr $25
-# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
-# CHECK-NEXT: {{[0-9a-f]+}}: 08 00 20 03 jr $25
-# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Content: "09f820030000000008002003000000000000000000000000"
-# ^ jalr ^ jr ^ T1 ^ T2
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_JALR
- - Offset: 8
- Symbol: T2
- Type: R_MIPS_JALR
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 16
- Size: 0
-
-Symbols:
- Global:
- - Name: __start
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 16
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 16
- Size: 4
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Value: 20
- Size: 4
-...
diff --git a/test/old-elf/Mips/rel-lit-micro.test b/test/old-elf/Mips/rel-lit-micro.test
deleted file mode 100644
index 783b24f83813..000000000000
--- a/test/old-elf/Mips/rel-lit-micro.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_MICROMIPS_LITERAL relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400130 00000f10
-# ^ 0x402000 + 0x7fff - 0x408ff0 = 0x100f
-
-# CHECK: 00402000 g .data 00000004 D0
-# CHECK: 00408ff0 g *ABS* 00000000 _gp_disp
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
- EF_MIPS_ARCH_32, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Content: "0000ff7f"
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: D0
- Type: R_MICROMIPS_LITERAL
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_WRITE ]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
- - Name: D0
- Type: STT_OBJECT
- Section: .data
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/rel-lit.test b/test/old-elf/Mips/rel-lit.test
deleted file mode 100644
index 19aa68721691..000000000000
--- a/test/old-elf/Mips/rel-lit.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# Check handling of R_MIPS_LITERAL relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400130 0f100000
-# ^ 0x402000 + 0x7fff - 0x408ff0 = 0x100f
-
-# CHECK: 00402000 g .data 00000004 D0
-# CHECK: 00408ff0 g *ABS* 00000000 _gp_disp
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Content: "ff7f0000"
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: D0
- Type: R_MIPS_LITERAL
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_WRITE ]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
- - Name: D0
- Type: STT_OBJECT
- Section: .data
- Value: 0
- Size: 4
-...
diff --git a/test/old-elf/Mips/rel-pc-hilo.test b/test/old-elf/Mips/rel-pc-hilo.test
deleted file mode 100644
index 6791926762b2..000000000000
--- a/test/old-elf/Mips/rel-pc-hilo.test
+++ /dev/null
@@ -1,70 +0,0 @@
-# Check handling of R_MIPS_PCHI16 / R_MIPS_PCLO16 relocations.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 01000000 02000000 03000000 00000000
-# ^
-# A = 0x10000 - 1 == 0xffff
-# V = (T1 + 0xffff - T0) >> 16 =>
-# V => 0x1000b >> 16 = 1
-# ^
-# A = 0x20000 - 1 == 0x1ffff
-# V = (T1 + 0x1ffff - T0 - 4) >> 16 =>
-# V => 0x20007 >> 16 = 2
-# ^
-# A = 0xffff == -1
-# V = T1 - 1 - T0 - 8 = 3
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9a-f]+}} g F .text 0000000c T0
-# CHECK: {{[0-9a-f]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0100000002000000ffff000000000000"
-# ^ T0
-# ^ A := 0x1 == 0x10000
-# ^ A := 0x2 == 0x20000
-# ^ A := 0xffff == -1
-# ^ T1
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PCHI16
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_PCHI16
- - Offset: 8
- Symbol: T1
- Type: R_MIPS_PCLO16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 12
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 12
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc16-align.test b/test/old-elf/Mips/rel-pc16-align.test
deleted file mode 100644
index 6366a4d67e92..000000000000
--- a/test/old-elf/Mips/rel-pc16-align.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# Check incorrect alignment handling for R_MIPS_PC16 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation not aligned in file {{.*}} reference from T0+0 to T1+0 of type 10 (R_MIPS_PC16)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 6
- Size: 2
diff --git a/test/old-elf/Mips/rel-pc16-overflow.test b/test/old-elf/Mips/rel-pc16-overflow.test
deleted file mode 100644
index 910482ee6154..000000000000
--- a/test/old-elf/Mips/rel-pc16-overflow.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Check R_MIPS_PC16 relocation overflow handling.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}} reference from T0+0 to T1+131068 of type 10 (R_MIPS_PC16)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "ff7f00000000000000000000"
-# ^ T1
-# ^ T0 A := 0x7fff << 2 = 0x1fffc
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc16.test b/test/old-elf/Mips/rel-pc16.test
deleted file mode 100644
index f298afd81cd6..000000000000
--- a/test/old-elf/Mips/rel-pc16.test
+++ /dev/null
@@ -1,53 +0,0 @@
-# Check handling of R_MIPS_PC16 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} feff0000 00000000 00000000
-# ^ V
-# A = -16 =>
-# V = (T1 - 16 - T0) >> 2 = -2
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000008 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "fcff00000000000000000000"
-# ^ T1
-# ^ T0 A := 0xfffc << 2 = -16
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC16
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc18-s3-align.test b/test/old-elf/Mips/rel-pc18-s3-align.test
deleted file mode 100644
index ca2fa18ecaa0..000000000000
--- a/test/old-elf/Mips/rel-pc18-s3-align.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# Check incorrect alignment handling for R_MIPS_PC18_S3 relocation target.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation not aligned in file {{.*}} reference from T1+0 to T1+0 of type 62 (R_MIPS_PC18_S3)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000000000000"
-# ^ T0 ^ T1
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_PC18_S3
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 4
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc18-s3-micro.test b/test/old-elf/Mips/rel-pc18-s3-micro.test
deleted file mode 100644
index fc143a75e569..000000000000
--- a/test/old-elf/Mips/rel-pc18-s3-micro.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# Check handling of R_MICROMIPS_PC18_S3 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 00000000 00000100 00000000 00000000
-# ^ V
-# A = -1 << 3 = -8 =>
-# V = (T1 - 8 - (T0|7)^7) >> 3 =>
-# V => 8 >> 3 = 1 (shuffled)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000010 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "000000000300ffff000000000000000000000000"
-# ^ T1
-# ^ T0 ^ A := 0x3ffff == -1 (shuffled)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 4
- Symbol: T1
- Type: R_MICROMIPS_PC18_S3
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 16
- Other: [STO_MIPS_MICROMIPS]
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 16
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
diff --git a/test/old-elf/Mips/rel-pc18-s3.test b/test/old-elf/Mips/rel-pc18-s3.test
deleted file mode 100644
index d61427448d53..000000000000
--- a/test/old-elf/Mips/rel-pc18-s3.test
+++ /dev/null
@@ -1,54 +0,0 @@
-# Check handling of R_MIPS_PC18_S3 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 00000000 01000000 00000000 00000000
-# ^ V
-# A = -1 << 3 = -8 =>
-# V = (T1 - 8 - (T0|7)^7) >> 3 =>
-# V => 8 >> 3 = 1
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000010 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000ffff0300000000000000000000000000"
-# ^ T1
-# ^ T0 ^ A := 0x3ffff == -1
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 4
- Symbol: T1
- Type: R_MIPS_PC18_S3
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 16
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 16
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc19-s2-align.test b/test/old-elf/Mips/rel-pc19-s2-align.test
deleted file mode 100644
index 19010a445578..000000000000
--- a/test/old-elf/Mips/rel-pc19-s2-align.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# Check incorrect alignment handling for R_MIPS_PC19_S2 relocation target.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation not aligned in file {{.*}} reference from T0+0 to T1+0 of type 63 (R_MIPS_PC19_S2)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000000000000"
-# ^ T0 ^ T1
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC19_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 6
- Size: 2
diff --git a/test/old-elf/Mips/rel-pc19-s2-micro.test b/test/old-elf/Mips/rel-pc19-s2-micro.test
deleted file mode 100644
index d9a930e41d88..000000000000
--- a/test/old-elf/Mips/rel-pc19-s2-micro.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# Check handling of R_MICROMIPS_PC19_S2 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 00000100 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1 (shuffled)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000008 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0700ffff0000000000000000"
-# ^ T1
-# ^ T0 A := 0x7ffff == -1 (shuffled)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MICROMIPS_PC19_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- Other: [STO_MIPS_MICROMIPS]
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
diff --git a/test/old-elf/Mips/rel-pc19-s2.test b/test/old-elf/Mips/rel-pc19-s2.test
deleted file mode 100644
index da21864a1214..000000000000
--- a/test/old-elf/Mips/rel-pc19-s2.test
+++ /dev/null
@@ -1,54 +0,0 @@
-# Check handling of R_MIPS_PC19_S2 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 01000000 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000008 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "ffff07000000000000000000"
-# ^ T1
-# ^ T0 A := 0x7ffff == -1
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC19_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc21-s2-align.test b/test/old-elf/Mips/rel-pc21-s2-align.test
deleted file mode 100644
index a79e1e2a46e0..000000000000
--- a/test/old-elf/Mips/rel-pc21-s2-align.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# Check incorrect alignment handling for R_MIPS_PC21_S2 relocation target.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation not aligned in file {{.*}} reference from T0+0 to T1+0 of type 60 (R_MIPS_PC21_S2)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000000000000"
-# ^ T0 ^ T1
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC21_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 6
- Size: 2
diff --git a/test/old-elf/Mips/rel-pc21-s2-micro.test b/test/old-elf/Mips/rel-pc21-s2-micro.test
deleted file mode 100644
index 4aa0a7de9489..000000000000
--- a/test/old-elf/Mips/rel-pc21-s2-micro.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# Check handling of R_MICROMIPS_PC21_S2 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 00000100 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1 (shuffled)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000008 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "1f00ffff0000000000000000"
-# ^ T1
-# ^ T0 A := 0x1fffff (shuffled)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MICROMIPS_PC21_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- Other: [STO_MIPS_MICROMIPS]
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
diff --git a/test/old-elf/Mips/rel-pc21-s2-overflow.test b/test/old-elf/Mips/rel-pc21-s2-overflow.test
deleted file mode 100644
index ad88e0c14b44..000000000000
--- a/test/old-elf/Mips/rel-pc21-s2-overflow.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Check R_MIPS_PC21_S2 relocation overflow handling.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation out of range in file {{.*}} reference from T0+0 to T1+4194300 of type 60 (R_MIPS_PC21_S2)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "ffff0f000000000000000000"
-# ^ T1
-# ^ T0 A := 0xfffff
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC21_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc21-s2.test b/test/old-elf/Mips/rel-pc21-s2.test
deleted file mode 100644
index c2b58c859af9..000000000000
--- a/test/old-elf/Mips/rel-pc21-s2.test
+++ /dev/null
@@ -1,54 +0,0 @@
-# Check handling of R_MIPS_PC21_S2 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 01000000 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000008 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "ffff1f000000000000000000"
-# ^ T1
-# ^ T0 A := 0x1fffff
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC21_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc26-s2-align.test b/test/old-elf/Mips/rel-pc26-s2-align.test
deleted file mode 100644
index 23e660848365..000000000000
--- a/test/old-elf/Mips/rel-pc26-s2-align.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# Check incorrect alignment handling for R_MIPS_PC26_S2 relocation target.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: Relocation not aligned in file {{.*}} reference from T0+0 to T1+0 of type 61 (R_MIPS_PC26_S2)
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "0000000000000000"
-# ^ T0 ^ T1
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC26_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 4
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 6
- Size: 2
diff --git a/test/old-elf/Mips/rel-pc26-s2-micro.test b/test/old-elf/Mips/rel-pc26-s2-micro.test
deleted file mode 100644
index 193c328be687..000000000000
--- a/test/old-elf/Mips/rel-pc26-s2-micro.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# Check handling of R_MICROMIPS_PC26_S2 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 00000100 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1 (shuffled)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000008 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "ff03ffff0000000000000000"
-# ^ T1
-# ^ T0 A := 0x3ffffff == -1 (shuffled)
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MICROMIPS_PC26_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- Other: [STO_MIPS_MICROMIPS]
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
- Other: [STO_MIPS_MICROMIPS]
diff --git a/test/old-elf/Mips/rel-pc26-s2.test b/test/old-elf/Mips/rel-pc26-s2.test
deleted file mode 100644
index c500f00cb860..000000000000
--- a/test/old-elf/Mips/rel-pc26-s2.test
+++ /dev/null
@@ -1,54 +0,0 @@
-# Check handling of R_MIPS_PC26_S2 relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 01000000 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g F .text 00000008 T0
-# CHECK: {{[0-9A-F]+}} g F .text 00000004 T1
-
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "ffffff030000000000000000"
-# ^ T1
-# ^ T0 A := 0x3ffffff == -1
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_PC26_S2
-
-Symbols:
- Global:
- - Name: T0
- Section: .text
- Type: STT_FUNC
- Value: 0
- Size: 8
- - Name: T1
- Section: .text
- Type: STT_FUNC
- Value: 8
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc32.test b/test/old-elf/Mips/rel-pc32.test
deleted file mode 100644
index 9faa32efec7b..000000000000
--- a/test/old-elf/Mips/rel-pc32.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_MIPS_PC32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: {{[0-9A-F]+}} 00000000 05000080 fdffff7f
-# ^^ data2 + 0x80000001 - data1
-# ^^ data1 + 0x80000001 - data2
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9A-F]+}} g .data 00000004 data1
-# CHECK: {{[0-9A-F]+}} g .data 00000004 data2
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "00000000"
- AddressAlign: 16
- Flags: [SHF_ALLOC]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "000000000100008001000080"
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rel.data
- Type: SHT_REL
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x4
- Symbol: data2
- Type: R_MIPS_PC32
- - Offset: 0x8
- Symbol: data1
- Type: R_MIPS_PC32
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0x0
- Size: 4
- - Name: data1
- Section: .data
- Value: 0x4
- Size: 4
- - Name: data2
- Section: .data
- Value: 0x8
- Size: 4
diff --git a/test/old-elf/Mips/rel-pc7-10-16-23.test b/test/old-elf/Mips/rel-pc7-10-16-23.test
deleted file mode 100644
index 51c4c3a670f1..000000000000
--- a/test/old-elf/Mips/rel-pc7-10-16-23.test
+++ /dev/null
@@ -1,86 +0,0 @@
-# Check handling of R_MICROMIPS_PC7_S1, R_MICROMIPS_PC10_S1,
-# R_MICROMIPS_PC16_S1, and R_MICROMIPS_PC23_S2 relocations.
-
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target mipsel -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: {{[0-9A-F]+}} 00000000 80780500 a240fcff 000c03cc
-# ^^ addiu s1,$pc,20
-# ^^ bnezc v0,400114 <__start+0x4>
-# ^^ b 400126 <L1>
-# CHECK-NEXT: {{[0-9A-F]+}} 000c03ad 00000000 00000000 00000000
-# ^^ bnez v0,40012a <L2>
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9a-f]+}} l F .text 00000002 L0
-# CHECK: {{[0-9a-f]+}} l F .text 00000004 L1
-# CHECK: {{[0-9a-f]+}} l F .text 00000004 L2
-# CHECK: {{[0-9a-f]+}} l F .text 00000002 L3
-# CHECK: {{[0-9a-f]+}} g F .text 00000014 __start
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
- EF_MIPS_MICROMIPS ]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
-# v nop v nop v L0
- Content: "0000000080780100a240f5ff000cfdcf000c7dad000000000000000000000000"
-# ^ PC23 ^ PC16 ^ PC10 ^ PC7 ^ L1 ^ L2 ^ L3
-# 7d << 1 = -6 => L3 + 2 - 6 = L2
-# 3fd << 1 = -6 => L2 + 2 - 6 = L1
-# fff5 << 1 = -22 => L1 + 2 - 22 = __start
-# 1 << 2 = 4 => L0 + 4 - 4 = L0
- AddressAlign: 16
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 4
- Symbol: L0
- Type: R_MICROMIPS_PC23_S2
- - Offset: 8
- Symbol: L1
- Type: R_MICROMIPS_PC16_S1
- - Offset: 14
- Symbol: L2
- Type: R_MICROMIPS_PC10_S1
- - Offset: 18
- Symbol: L3
- Type: R_MICROMIPS_PC7_S1
-
-Symbols:
- Local:
- - Name: L0
- Section: .text
- Value: 20
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: L1
- Section: .text
- Value: 22
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: L2
- Section: .text
- Value: 26
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: L3
- Section: .text
- Value: 30
- Other: [ STO_MIPS_MICROMIPS ]
- Global:
- - Name: __start
- Section: .text
- Type: STT_FUNC
- Value: 0x0
- Size: 32
- Other: [ STO_MIPS_MICROMIPS ]
diff --git a/test/old-elf/Mips/rel-sub-micro.test b/test/old-elf/Mips/rel-sub-micro.test
deleted file mode 100644
index 831a020ce2f9..000000000000
--- a/test/old-elf/Mips/rel-sub-micro.test
+++ /dev/null
@@ -1,62 +0,0 @@
-# Check handling of R_MICROMIPS_SUB relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 120002000 0020cc01 01000000 0020d001 0100ffff
-# ^^ __start - 4 = 0x1200001cc
-# ^^ __start - 0x1000000000000
-# = 0xffff0001200001d0
-# CHECK: SYMBOL TABLE:
-# CHECK: 00000001200001d0 g .rodata 00000008 __start
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64, EF_MIPS_MICROMIPS]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 8
- AddressAlign: 16
- Flags: [SHF_ALLOC]
-
-- Name: .data
- Type: SHT_PROGBITS
- Size: 16
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: __start
- Type: R_MICROMIPS_SUB
- Addend: 4
- - Offset: 8
- Symbol: __start
- Type: R_MICROMIPS_SUB
- Addend: 0x1000000000000
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0
- Size: 8
- - Name: D1
- Section: .data
- Value: 0
- Size: 8
- - Name: D2
- Section: .data
- Value: 8
- Size: 8
diff --git a/test/old-elf/Mips/rel-sub.test b/test/old-elf/Mips/rel-sub.test
deleted file mode 100644
index 5100406fd5d5..000000000000
--- a/test/old-elf/Mips/rel-sub.test
+++ /dev/null
@@ -1,61 +0,0 @@
-# Check handling of R_MIPS_SUB relocation.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -o %t.exe %t.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .data:
-# CHECK-NEXT: 120002000 cf010020 01000000 d0010020 0100ffff ... ....... ....
-# ^^ __start - 1 = 0x1200001cf
-# ^^ __start - 0x1000000000000
-# = 0Xffff0001200001d0
-# CHECK: SYMBOL TABLE:
-# CHECK: 00000001200001d0 g .rodata 00000008 __start
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Size: 0x08
- AddressAlign: 16
- Flags: [SHF_ALLOC]
-- Name: .data
- Type: SHT_PROGBITS
- Size: 0x10
- AddressAlign: 16
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-- Name: .rela.data
- Type: SHT_RELA
- Info: .data
- AddressAlign: 4
- Relocations:
- - Offset: 0x0
- Symbol: __start
- Type: R_MIPS_SUB
- Addend: 1
- - Offset: 0x8
- Symbol: __start
- Type: R_MIPS_SUB
- Addend: 0x1000000000000
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0x0
- Size: 8
- - Name: data1
- Section: .data
- Value: 0x0
- Size: 8
- - Name: data2
- Section: .data
- Value: 0x8
- Size: 8
diff --git a/test/old-elf/Mips/rld_map.test b/test/old-elf/Mips/rld_map.test
deleted file mode 100644
index ee063be1d7fc..000000000000
--- a/test/old-elf/Mips/rld_map.test
+++ /dev/null
@@ -1,42 +0,0 @@
-# REQUIRES: mips
-
-# Check definition of DT_MIPS_RLD_MAP and DT_MIPS_RLD_MAP_REL dynamic tags,
-# .rld_map section, and __RLD_MAP symbol.
-
-# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
-# RUN: lld -flavor old-gnu -target mips %t.o -o %t.exe
-# RUN: llvm-readobj -dynamic-table -s -st %t.exe \
-# RUN: | FileCheck -check-prefix=EXE-DYN %s
-
-# EXE-DYN: Name: .rld_map
-# EXE-DYN-NEXT: Type: SHT_PROGBITS
-# EXE-DYN-NEXT: Flags [
-# EXE-DYN-NEXT: SHF_ALLOC
-# EXE-DYN-NEXT: SHF_WRITE
-# EXE-DYN-NEXT: ]
-# EXE-DYN-NEXT: Address: 0x[[ADDR:[0-9A-F]+]]
-# EXE-DYN: Size: 4
-# EXE-DYN: AddressAlignment: 4
-# EXE-DYN: Symbols [
-# EXE-DYN-NEXT: Symbol {
-# EXE-DYN-NEXT: Name: __RLD_MAP
-# EXE-DYN-NEXT: Value: 0x[[ADDR]]
-# EXE-DYN-NEXT: Size: 4
-# EXE-DYN-NEXT: Binding: Global
-# EXE-DYN-NEXT: Type: Object
-#
-# EXE-DYN: 0x70000016 MIPS_RLD_MAP 0x[[ADDR]]
-# EXE-DYN: 0x70000035 MIPS_RLD_MAP_REL 0x1E48
-
-# RUN: lld -flavor old-gnu -target mips -static %t.o -o %t.exe
-# RUN: llvm-nm -just-symbol-name %t.exe | FileCheck -check-prefix=EXE-STATIC %s
-
-# EXE-STATIC-NOT: __RLD_MAP
-
-# RUN: lld -flavor old-gnu -target mips -shared %t.o -o %t.so
-# RUN: llvm-nm -just-symbol-name %t.so | FileCheck -check-prefix=DYNLIB %s
-
-# DYNLIB-NOT: __RLD_MAP
-
- .globl __start;
-__start:
diff --git a/test/old-elf/Mips/sign-rela.test b/test/old-elf/Mips/sign-rela.test
deleted file mode 100644
index 3e5341f2c230..000000000000
--- a/test/old-elf/Mips/sign-rela.test
+++ /dev/null
@@ -1,54 +0,0 @@
-# Check that relocation addend read from RELA record is not sign-extended.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target mips64el -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: {{[0-9a-f]+}} 01000000 00000000 ........
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 0x20008
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0x20000
- Symbol: __start
- Type: R_MIPS_PC16
- Addend: 0x20000
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 16
- Size: 0
-
-Symbols:
- Local:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
- Global:
- - Name: __start
- Type: STT_FUNC
- Section: .text
- Value: 4
- Size: 0x20004
-...
diff --git a/test/old-elf/Mips/st-other.test b/test/old-elf/Mips/st-other.test
deleted file mode 100644
index 2bb1f8b96e07..000000000000
--- a/test/old-elf/Mips/st-other.test
+++ /dev/null
@@ -1,90 +0,0 @@
-# Check STO_MICROMIPS flag handling. microMIPS symbol records in a dynamic
-# symbol table should not have STO_MICROMIPS flag but their value field
-# must be odd. microMIPS symbol records in a regular symbol table should
-# have the STO_MICROMIPS flag.
-
-# RUN: yaml2obj -format=elf %s > %t-micro.o
-
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-micro.o
-# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck -check-prefix=SO %s
-
-# RUN: lld -flavor old-gnu -target mipsel -e S0 -o %t.exe %t-micro.o
-# RUN: llvm-readobj -symbols %t.exe | FileCheck -check-prefix=EXE-SYM %s
-# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=EXE-DSYM %s
-
-# SO: Symbol {
-# SO: Name: S0@ (1)
-# SO-NEXT: Value: 0x{{[0-9A-F]+}}
-# SO-NEXT: Size: 4
-# SO-NEXT: Binding: Global (0x1)
-# SO-NEXT: Type: Function (0x2)
-# SO-NEXT: Other: 0
-# SO-NEXT: Section: .text (0x4)
-# SO-NEXT: }
-
-# SO: Symbol {
-# SO: Name: S1@ (4)
-# SO-NEXT: Value: 0x{{[0-9A-F]+}}
-# SO-NEXT: Size: 4
-# SO-NEXT: Binding: Global (0x1)
-# SO-NEXT: Type: Function (0x2)
-# SO-NEXT: Other: 0
-# SO-NEXT: Section: .text (0x4)
-# SO-NEXT: }
-
-# EXE-SYM: Symbol {
-# EXE-SYM: Name: S0 (1)
-# EXE-SYM-NEXT: Value: 0x{{[0-9A-F]+}}
-# EXE-SYM-NEXT: Size: 4
-# EXE-SYM-NEXT: Binding: Global (0x1)
-# EXE-SYM-NEXT: Type: Function (0x2)
-# EXE-SYM-NEXT: Other: 0
-# EXE-SYM-NEXT: Section: .text (0x5)
-# EXE-SYM-NEXT: }
-
-# EXE-SYM: Symbol {
-# EXE-SYM: Name: S1 (4)
-# EXE-SYM-NEXT: Value: 0x{{[0-9A-F]+}}
-# EXE-SYM-NEXT: Size: 4
-# EXE-SYM-NEXT: Binding: Global (0x1)
-# EXE-SYM-NEXT: Type: Function (0x2)
-# EXE-SYM-NEXT: Other: 128
-# EXE-SYM-NEXT: Section: .text (0x5)
-# EXE-SYM-NEXT: }
-
-# EXE-DSYM-NOT: Name: S1 (4)
-
-# micro.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
-
-Symbols:
- Global:
- - Name: S0
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- Value: 0x00
- Visibility: STV_DEFAULT
- Other: [ ]
-
- - Name: S1
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- Value: 0x04
- Visibility: STV_DEFAULT
- Other: [ STO_MIPS_MICROMIPS ]
-...
diff --git a/test/old-elf/Mips/static-01.test b/test/old-elf/Mips/static-01.test
deleted file mode 100644
index 77a33469df3f..000000000000
--- a/test/old-elf/Mips/static-01.test
+++ /dev/null
@@ -1,119 +0,0 @@
-# Check handling relocations against _gp/__gnu_local_gp symbols
-# in case of "-static" linking.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -static -o %t.exe %t1.o %t2.o
-# RUN: llvm-nm %t.exe | FileCheck %s
-
-# CHECK: 00401000 N _GLOBAL_OFFSET_TABLE_
-# CHECK: 00408ff0 A __gnu_local_gp
-# CHECK: 00408ff0 A _gp
-# CHECK: 00408ff0 A _gp_disp
-
-# o1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 28
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: .data
- Type: R_MIPS_HI16
- - Offset: 4
- Symbol: .data
- Type: R_MIPS_LO16
- - Offset: 8
- Symbol: T1
- Type: R_MIPS_26
- - Offset: 12
- Symbol: _gp
- Type: R_MIPS_HI16
- - Offset: 16
- Symbol: _gp
- Type: R_MIPS_LO16
- - Offset: 20
- Symbol: __gnu_local_gp
- Type: R_MIPS_HI16
- - Offset: 24
- Symbol: __gnu_local_gp
- Type: R_MIPS_LO16
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 16
- Size: 4
-
- - Name: .pdr
- Type: SHT_PROGBITS
- AddressAlign: 4
- Size: 4
-
- - Name: .rel.pdr
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .pdr
- Relocations:
- - Offset: 0
- Symbol: T0
- Type: R_MIPS_32
-
-Symbols:
- Local:
- - Type: STT_SECTION
- Section: .text
- - Type: STT_SECTION
- Section: .data
- - Type: STT_SECTION
- Section: .pdr
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 28
- - Name: T1
- - Name: _gp
- - Name: __gnu_local_gp
-
-# o2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 20
-...
diff --git a/test/old-elf/Mips/tls-1-micro.test b/test/old-elf/Mips/tls-1-micro.test
deleted file mode 100644
index f47592a5ab7d..000000000000
--- a/test/old-elf/Mips/tls-1-micro.test
+++ /dev/null
@@ -1,65 +0,0 @@
-# Check handling of R_MICROMIPS_TLS_TPREL_HI16 / R_MICROMIPS_TLS_TPREL_LO16
-# relocations.
-
-# RUN: yaml2obj -format=elf -o %t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e L0 -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: {{[0-9A-F]+}} 00000000 00000100 00000380 00000480
-
-!ELF
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Content: '00000100000002000000030000000400'
- - Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: L1
- Type: R_MICROMIPS_TLS_TPREL_HI16
- - Offset: 0x04
- Symbol: L2
- Type: R_MICROMIPS_TLS_TPREL_HI16
- - Offset: 0x08
- Symbol: L2
- Type: R_MICROMIPS_TLS_TPREL_LO16
- - Offset: 0x0C
- Symbol: L1
- Type: R_MICROMIPS_TLS_TPREL_LO16
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Address: 0x1000
- Size: 0x20000
-
-Symbols:
- Global:
- - Name: L0
- Type: STT_FUNC
- Section: .text
- Size: 0x58
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: L1
- Type: STT_TLS
- Section: .tdata
- Value: 0x00
- Size: 0x04
- - Name: L2
- Type: STT_TLS
- Section: .tdata
- Value: 0x10000
- Size: 0x04
diff --git a/test/old-elf/Mips/tls-1.test b/test/old-elf/Mips/tls-1.test
deleted file mode 100644
index c25a06c1dee9..000000000000
--- a/test/old-elf/Mips/tls-1.test
+++ /dev/null
@@ -1,63 +0,0 @@
-# Check handling of R_MIPS_TLS_TPREL_HI16 / R_MIPS_TLS_TPREL_LO16 relocations.
-
-# RUN: yaml2obj -format=elf -o %t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e L0 -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: {{[0-9A-F]+}} 00000000 01000000 03800000 04800000
-
-!ELF
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Content: '01000000020000000300000004000000'
- - Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: L1
- Type: R_MIPS_TLS_TPREL_HI16
- - Offset: 0x04
- Symbol: L2
- Type: R_MIPS_TLS_TPREL_HI16
- - Offset: 0x08
- Symbol: L2
- Type: R_MIPS_TLS_TPREL_LO16
- - Offset: 0x0C
- Symbol: L1
- Type: R_MIPS_TLS_TPREL_LO16
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Address: 0x1000
- Size: 0x20000
-
-Symbols:
- Global:
- - Name: L0
- Type: STT_FUNC
- Section: .text
- Size: 0x58
- - Name: L1
- Type: STT_TLS
- Section: .tdata
- Value: 0x00
- Size: 0x04
- - Name: L2
- Type: STT_TLS
- Section: .tdata
- Value: 0x10000
- Size: 0x04
diff --git a/test/old-elf/Mips/tls-2-64-static.test b/test/old-elf/Mips/tls-2-64-static.test
deleted file mode 100644
index c8c30ea06c60..000000000000
--- a/test/old-elf/Mips/tls-2-64-static.test
+++ /dev/null
@@ -1,71 +0,0 @@
-# Check handling of R_MIPS_TLS_GD relocation in case of -static linking.
-
-# RUN: yaml2obj -format=elf -o %t.o %s
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -static -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 120000120 20800000 30800000
-# ^ -32736 ^ -32720
-# CHECK-NEXT: Contents of section .tdata:
-# CHECK-NEXT: 120001000 00000000 00000000
-# CHECK-NEXT: Contents of section .got:
-# CHECK-NEXT: 120002000 00000000 00000000 00000000 00000080
-# CHECK-NEXT: 120002010 01000000 00000000 0480ffff ffffffff
-# CHECK-NEXT: 120002020 01000000 00000000 0c80ffff ffffffff
-# D1 0x120001000 + 4 - (0x120001000 + 0x8000) = 0xffff8004 => 0480ffff
-# D2 0x120001040 + 8 - (0x120001000 + 0x8000) = 0xffff800c => 0c80ffff
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: D1
- Type: R_MIPS_TLS_GD
- Addend: 4
- - Offset: 4
- Symbol: D2
- Type: R_MIPS_TLS_GD
- Addend: 8
-
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 8
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Value: 0
- Size: 4
- - Name: D2
- Type: STT_TLS
- Section: .tdata
- Value: 4
- Size: 4
-...
diff --git a/test/old-elf/Mips/tls-2-64.test b/test/old-elf/Mips/tls-2-64.test
deleted file mode 100644
index 3a6f6b3bedea..000000000000
--- a/test/old-elf/Mips/tls-2-64.test
+++ /dev/null
@@ -1,69 +0,0 @@
-# Check handling of R_MIPS_TLS_GOTTPREL and R_MIPS_TLS_GD relocations
-# and generation of corresponding dynamic relocations R_MIPS_TLS_TPREL64,
-# R_MIPS_TLS_DTPMOD64 and R_MIPS_TLS_DTPREL64 in case of shared library.
-
-# Create a shared library with thread symbol D1.
-# RUN: yaml2obj -format=elf -o %t-so.o %s
-# RUN: lld -flavor old-gnu -target mips64el -shared -o %t.so %t-so.o
-
-# Check dynamic relocations and GOT in the shared library.
-# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s
-# RUN: llvm-readobj -dynamic-table %t.so | FileCheck -check-prefix=DYN %s
-# RUN: llvm-readobj -dt %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=GOT %s
-
-# REL: Section (4) .rel.dyn {
-# REL-NEXT: 0x2010 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE D1 0x0
-# REL-NEXT: 0x2018 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE D1 0x0
-# REL-NEXT: }
-
-# DYN: 0x000000007000000A MIPS_LOCAL_GOTNO 2
-# DYN: 0x0000000070000013 MIPS_GOTSYM 0x3
-
-# SYM: Name: T1@ (1)
-# SYM: Name: D1@ (4)
-
-# GOT: Contents of section .got:
-# GOT-NEXT: 2000 00000000 00000000 00000000 00000080 ................
-# GOT-NEXT: 2010 00000000 00000000 00000000 00000000 ................
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 4
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: D1
- Type: R_MIPS_TLS_GD
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 4
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Size: 8
-...
diff --git a/test/old-elf/Mips/tls-2-micro.test b/test/old-elf/Mips/tls-2-micro.test
deleted file mode 100644
index 88d8797cd06a..000000000000
--- a/test/old-elf/Mips/tls-2-micro.test
+++ /dev/null
@@ -1,70 +0,0 @@
-# Check handling of R_MICROMIPS_TLS_GOTTPREL and R_MICROMIPS_TLS_GD relocations
-# and generation of corresponding dynamic relocations R_MIPS_TLS_TPREL32,
-# R_MIPS_TLS_DTPMOD32 and R_MIPS_TLS_DTPREL32 in case of shared library.
-
-# Create a shared library with thread symbol D1.
-# RUN: yaml2obj -format=elf -o %t-so.o %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Check dynamic relocations and GOT in the shared library.
-# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s
-# RUN: llvm-readobj -dynamic-table %t.so | FileCheck -check-prefix=DYN %s
-# RUN: llvm-readobj -dt %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=GOT %s
-
-# REL: Section (4) .rel.dyn {
-# REL-NEXT: 0x2008 R_MIPS_TLS_DTPMOD32 D1 0x0
-# REL-NEXT: 0x200C R_MIPS_TLS_DTPREL32 D1 0x0
-# REL-NEXT: }
-
-# DYN: 0x7000000A MIPS_LOCAL_GOTNO 2
-# DYN: 0x70000013 MIPS_GOTSYM 0x3
-
-# SYM: Name: T1@ (1)
-# SYM: Name: D1@ (4)
-
-# GOT: Contents of section .got:
-# GOT-NEXT: 2000 00000000 00000080 00000000 00000000 ................
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MICROMIPS_TLS_GD
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/tls-2-static.test b/test/old-elf/Mips/tls-2-static.test
deleted file mode 100644
index 3ac2122628d6..000000000000
--- a/test/old-elf/Mips/tls-2-static.test
+++ /dev/null
@@ -1,125 +0,0 @@
-# Check handling of R_MIPS_TLS_GD relocation in case of -static linking.
-
-# RUN: yaml2obj -format=elf -docnum 1 -o %t1.o %s
-# RUN: yaml2obj -format=elf -docnum 2 -o %t2.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -static -o %t.exe %t1.o %t2.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 4000b4 18800000 20800000 28800000 30800000
-# ^ -32744 ^ -32736 ^ -32728 ^ -32720
-# CHECK-NEXT: Contents of section .tdata:
-# CHECK-NEXT: 401000 00000000 00000000 00000000 00000000
-# CHECK-NEXT: Contents of section .got:
-# CHECK-NEXT: 402000 00000000 00000080 01000000 0480ffff
-# CHECK-NEXT: 402010 01000000 0c80ffff 01000000 0c80ffff
-# CHECK-NEXT: 402020 01000000 1480ffff
-# D1 0x401000 + 4 - (0x401000 + 0x8000) = 0xffff8004 => 0480ffff
-# D2 0x401004 + 8 - (0x401000 + 0x8000) = 0xffff800c => 0c80ffff
-# D3 0x401008 + 4 - (0x401000 + 0x8000) = 0xffff800c => 0c80ffff
-# D4 0x40100c + 8 - (0x401000 + 0x8000) = 0xffff8014 => 1480ffff
-
-# t1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Content: "0400000008000000"
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: D1
- Type: R_MIPS_TLS_GD
- - Offset: 4
- Symbol: D2
- Type: R_MIPS_TLS_GD
-
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 8
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Value: 0
- Size: 4
- - Name: D2
- Type: STT_TLS
- Section: .tdata
- Value: 4
- Size: 4
-
-# t2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Content: "0400000008000000"
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: D3
- Type: R_MIPS_TLS_GD
- - Offset: 4
- Symbol: D4
- Type: R_MIPS_TLS_GD
-
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 8
- - Name: D3
- Type: STT_TLS
- Section: .tdata
- Value: 0
- Size: 4
- - Name: D4
- Type: STT_TLS
- Section: .tdata
- Value: 4
- Size: 4
-...
diff --git a/test/old-elf/Mips/tls-2.test b/test/old-elf/Mips/tls-2.test
deleted file mode 100644
index de8fc2a70861..000000000000
--- a/test/old-elf/Mips/tls-2.test
+++ /dev/null
@@ -1,69 +0,0 @@
-# Check handling of R_MIPS_TLS_GOTTPREL and R_MIPS_TLS_GD relocations
-# and generation of corresponding dynamic relocations R_MIPS_TLS_TPREL32,
-# R_MIPS_TLS_DTPMOD32 and R_MIPS_TLS_DTPREL32 in case of shared library.
-
-# Create a shared library with thread symbol D1.
-# RUN: yaml2obj -format=elf -o %t-so.o %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Check dynamic relocations and GOT in the shared library.
-# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s
-# RUN: llvm-readobj -dynamic-table %t.so | FileCheck -check-prefix=DYN %s
-# RUN: llvm-readobj -dt %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=GOT %s
-
-# REL: Section (4) .rel.dyn {
-# REL-NEXT: 0x2008 R_MIPS_TLS_DTPMOD32 D1 0x0
-# REL-NEXT: 0x200C R_MIPS_TLS_DTPREL32 D1 0x0
-# REL-NEXT: }
-
-# DYN: 0x7000000A MIPS_LOCAL_GOTNO 2
-# DYN: 0x70000013 MIPS_GOTSYM 0x3
-
-# SYM: Name: T1@ (1)
-# SYM: Name: D1@ (4)
-
-# GOT: Contents of section .got:
-# GOT-NEXT: 2000 00000000 00000080 00000000 00000000 ................
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MIPS_TLS_GD
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/tls-3-64-static.test b/test/old-elf/Mips/tls-3-64-static.test
deleted file mode 100644
index 2183d1fd6833..000000000000
--- a/test/old-elf/Mips/tls-3-64-static.test
+++ /dev/null
@@ -1,70 +0,0 @@
-# Check handling of R_MIPS_TLS_GOTTPREL relocation in case of -static linking.
-
-# RUN: yaml2obj -format=elf -o %t.o %s
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -static -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 120000120 20800000 28800000
-# ^ -32736 ^ -32728
-# CHECK-NEXT: Contents of section .tdata:
-# CHECK-NEXT: 120001000 00000000 00000000
-# CHECK-NEXT: Contents of section .got:
-# CHECK-NEXT: 120002000 00000000 00000000 00000000 00000080
-# CHECK-NEXT: 120002010 0490ffff ffffffff 0c90ffff ffffffff
-# D1 0x120001000 + 4 - (0x120001000 + 0x7000) = 0xffff9004 => 0490ffff
-# D2 0x120001004 + 8 - (0x120001000 + 0x7000) = 0xffff900c => 0c90ffff
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: D1
- Type: R_MIPS_TLS_GOTTPREL
- Addend: 4
- - Offset: 4
- Symbol: D2
- Type: R_MIPS_TLS_GOTTPREL
- Addend: 8
-
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Value: 0
- Size: 4
- - Name: D2
- Type: STT_TLS
- Section: .tdata
- Value: 4
- Size: 4
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 8
-...
diff --git a/test/old-elf/Mips/tls-3-micro.test b/test/old-elf/Mips/tls-3-micro.test
deleted file mode 100644
index 347332e6633e..000000000000
--- a/test/old-elf/Mips/tls-3-micro.test
+++ /dev/null
@@ -1,183 +0,0 @@
-# Check handling of R_MICROMIPS_TLS_GOTTPREL and R_MICROMIPS_TLS_GD relocations
-# and generation of corresponding dynamic relocations R_MIPS_TLS_TPREL32,
-# R_MIPS_TLS_DTPMOD32 and R_MIPS_TLS_DTPREL32 in case of executable linking.
-
-# Create a shared library with thread symbol D1.
-# RUN: yaml2obj -format=elf -docnum 1 -o %t-so.o %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Create executable file linked using two object files and the shared library.
-# The object files defines thread symbols D0 and D2.
-# RUN: yaml2obj -format=elf -docnum 2 -o %t-o1.o %s
-# RUN: yaml2obj -format=elf -docnum 3 -o %t-o2.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o1.o %t-o2.o %t.so
-
-# Check dynamic relocations and GOT in the executable file.
-# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
-# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck -check-prefix=DYN %s
-# RUN: llvm-readobj -dt %t.exe | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=GOT %s
-
-# REL: Section (5) .rel.dyn {
-# REL-NEXT: 0x402008 R_MIPS_TLS_TPREL32 D1 0x0
-# REL-NEXT: 0x40200C R_MIPS_TLS_TPREL32 D2 0x0
-# REL-NEXT: }
-
-# DYN: 0x7000000A MIPS_LOCAL_GOTNO 2
-# DYN: 0x70000013 MIPS_GOTSYM 0x3
-
-# SYM: Name: D2@ (1)
-# SYM: Name: D1@ (4)
-
-# GOT: Contents of section .got:
-# GOT-NEXT: 402000 00000000 00000080 00000000 00000000 ................
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MICROMIPS_TLS_GD
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
-
-# o1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: D2
- Type: R_MICROMIPS_TLS_TPREL_HI16
- - Offset: 0x04
- Symbol: D2
- Type: R_MICROMIPS_TLS_TPREL_LO16
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: D2
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
-
-# o2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x10
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MICROMIPS_TLS_GOTTPREL
- Addend: 0
- - Offset: 0x04
- Symbol: D0
- Type: R_MICROMIPS_TLS_TPREL_HI16
- Addend: 0
- - Offset: 0x08
- Symbol: D0
- Type: R_MICROMIPS_TLS_TPREL_LO16
- Addend: 0
- - Offset: 0x0C
- Symbol: D2
- Type: R_MICROMIPS_TLS_GOTTPREL
- Addend: 0
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: D0
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x10
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: D1
- Type: STT_TLS
- - Name: D2
- Type: STT_TLS
-...
diff --git a/test/old-elf/Mips/tls-3-static.test b/test/old-elf/Mips/tls-3-static.test
deleted file mode 100644
index 5d3a7b8bfd6a..000000000000
--- a/test/old-elf/Mips/tls-3-static.test
+++ /dev/null
@@ -1,67 +0,0 @@
-# Check handling of R_MIPS_TLS_GOTTPREL relocation in case of -static linking.
-
-# RUN: yaml2obj -format=elf -o %t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -static -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 4000b4 18800000 1c800000
-# ^ -32744 ^ -32740
-# CHECK-NEXT: Contents of section .tdata:
-# CHECK-NEXT: 401000 00000000 00000000
-# CHECK-NEXT: Contents of section .got:
-# CHECK-NEXT: 402000 00000000 00000080 0490ffff 0c90ffff
-# D1 0x401000 + 4 - (0x401000 + 0x7000) = 0xffff9004 => 0490ffff
-# D2 0x401004 + 8 - (0x401000 + 0x7000) = 0xffff900c => 0c90ffff
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Content: "0400000008000000"
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0
- Symbol: D1
- Type: R_MIPS_TLS_GOTTPREL
- - Offset: 4
- Symbol: D2
- Type: R_MIPS_TLS_GOTTPREL
-
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Value: 0
- Size: 4
- - Name: D2
- Type: STT_TLS
- Section: .tdata
- Value: 4
- Size: 4
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 8
-...
diff --git a/test/old-elf/Mips/tls-3.test b/test/old-elf/Mips/tls-3.test
deleted file mode 100644
index eb9750fee28d..000000000000
--- a/test/old-elf/Mips/tls-3.test
+++ /dev/null
@@ -1,180 +0,0 @@
-# Check handling of R_MIPS_TLS_GOTTPREL and R_MIPS_TLS_GD relocations
-# and generation of corresponding dynamic relocations R_MIPS_TLS_TPREL32,
-# R_MIPS_TLS_DTPMOD32 and R_MIPS_TLS_DTPREL32 in case of executable linking.
-
-# Create a shared library with thread symbol D1.
-# RUN: yaml2obj -format=elf -docnum 1 -o %t-so.o %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so.o
-
-# Create executable file linked using two object files and the shared library.
-# The object files defines thread symbols D0 and D2.
-# RUN: yaml2obj -format=elf -docnum 2 -o %t-o1.o %s
-# RUN: yaml2obj -format=elf -docnum 3 -o %t-o2.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o1.o %t-o2.o %t.so
-
-# Check dynamic relocations and GOT in the executable file.
-# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
-# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck -check-prefix=DYN %s
-# RUN: llvm-readobj -dt %t.exe | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=GOT %s
-
-# REL: Section (5) .rel.dyn {
-# REL-NEXT: 0x402008 R_MIPS_TLS_TPREL32 D1 0x0
-# REL-NEXT: 0x40200C R_MIPS_TLS_TPREL32 D2 0x0
-# REL-NEXT: }
-
-# DYN: 0x7000000A MIPS_LOCAL_GOTNO 2
-# DYN: 0x70000013 MIPS_GOTSYM 0x3
-
-# SYM: Name: D2@ (1)
-# SYM: Name: D1@ (4)
-
-# GOT: Contents of section .got:
-# GOT-NEXT: 402000 00000000 00000080 00000000 00000000 ................
-
-# so.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MIPS_TLS_GD
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- - Name: D1
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
-
-# o1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: D2
- Type: R_MIPS_TLS_TPREL_HI16
- - Offset: 0x04
- Symbol: D2
- Type: R_MIPS_TLS_TPREL_LO16
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- - Name: D2
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
-
-# o2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x10
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- Info: .text
- AddressAlign: 0x04
- Relocations:
- - Offset: 0x00
- Symbol: D1
- Type: R_MIPS_TLS_GOTTPREL
- Addend: 0
- - Offset: 0x04
- Symbol: D0
- Type: R_MIPS_TLS_TPREL_HI16
- Addend: 0
- - Offset: 0x08
- Symbol: D0
- Type: R_MIPS_TLS_TPREL_LO16
- Addend: 0
- - Offset: 0x0C
- Symbol: D2
- Type: R_MIPS_TLS_GOTTPREL
- Addend: 0
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: D0
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x10
- - Name: D1
- Type: STT_TLS
- - Name: D2
- Type: STT_TLS
-...
diff --git a/test/old-elf/Mips/tls-4-64-static.test b/test/old-elf/Mips/tls-4-64-static.test
deleted file mode 100644
index 3aa37046d36b..000000000000
--- a/test/old-elf/Mips/tls-4-64-static.test
+++ /dev/null
@@ -1,71 +0,0 @@
-# Check handling of R_MIPS_TLS_LDM relocation in case of -static linking.
-
-# RUN: yaml2obj -format=elf -o %t.o %s
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -static -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 120000120 20800000 20800000
-# ^ -32736 ^ -32736
-# CHECK-NEXT: Contents of section .tdata:
-# CHECK-NEXT: 120001000 00000000 00000000
-# CHECK-NEXT: Contents of section .got:
-# CHECK-NEXT: 120002000 00000000 00000000 00000000 00000080
-# CHECK-NEXT: 120002010 01000000 00000000 00000000 00000000
-# ^ R_MIPS_TLS_DTPMOD64
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 8
-
- - Name: .rel.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: L1
- Type: R_MIPS_TLS_LDM
- Addend: 4
- - Offset: 4
- Symbol: L2
- Type: R_MIPS_TLS_LDM
- Addend: 8
-
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Local:
- - Name: L1
- Type: STT_TLS
- Section: .tdata
- Value: 0
- Size: 4
- - Name: L2
- Type: STT_TLS
- Section: .tdata
- Value: 4
- Size: 4
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 8
-...
diff --git a/test/old-elf/Mips/tls-4-micro.test b/test/old-elf/Mips/tls-4-micro.test
deleted file mode 100644
index 23d8e0a1de31..000000000000
--- a/test/old-elf/Mips/tls-4-micro.test
+++ /dev/null
@@ -1,126 +0,0 @@
-# Check handling of R_MICROMIPS_TLS_LDM relocation and generation
-# of corresponding dynamic relocation R_MICROMIPS_TLS_DTPMOD32.
-
-# RUN: yaml2obj -format=elf -docnum 1 -o %t-so1.o %s
-# RUN: yaml2obj -format=elf -docnum 2 -o %t-so2.o %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so1.o %t-so2.o
-
-# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s
-# RUN: llvm-readobj -dynamic-table %t.so | FileCheck -check-prefix=DYN %s
-# RUN: llvm-readobj -dt %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=GOT %s
-
-# REL: Section (4) .rel.dyn {
-# REL-NEXT: 0x2008 R_MIPS_TLS_DTPMOD32 - 0x0
-# REL-NEXT: }
-
-# DYN: 0x7000000A MIPS_LOCAL_GOTNO 2
-# DYN: 0x70000013 MIPS_GOTSYM 0x4
-
-# SYM: Name: @ (0)
-# SYM: Name: T1@ (1)
-# SYM: Name: T2@ (4)
-# SYM: Name: T3@ (7)
-
-# GOT: Contents of section .got:
-# GOT-NEXT: 2000 00000000 00000080 00000000 00000000 ................
-# Two LDM entries --^--------^
-
-# so1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: L01
- Type: R_MICROMIPS_TLS_LDM
- - Offset: 0x04
- Symbol: L01
- Type: R_MICROMIPS_TLS_LDM
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Local:
- - Name: L01
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 0x00
- Size: 0x04
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Value: 0x04
- Size: 0x04
- Other: [ STO_MIPS_MICROMIPS ]
-
-# so2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: L02
- Type: R_MICROMIPS_TLS_LDM
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Local:
- - Name: L02
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
- Global:
- - Name: T3
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- Other: [ STO_MIPS_MICROMIPS ]
-...
diff --git a/test/old-elf/Mips/tls-4-static.test b/test/old-elf/Mips/tls-4-static.test
deleted file mode 100644
index 5fdb11df874b..000000000000
--- a/test/old-elf/Mips/tls-4-static.test
+++ /dev/null
@@ -1,68 +0,0 @@
-# Check handling of R_MIPS_TLS_LDM relocation in case of -static linking.
-
-# RUN: yaml2obj -format=elf -o %t.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -static -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 4000b4 18800000 18800000
-# ^ -32744 ^ -32744
-# CHECK-NEXT: Contents of section .tdata:
-# CHECK-NEXT: 401000 00000000 00000000
-# CHECK-NEXT: Contents of section .got:
-# CHECK-NEXT: 402000 00000000 00000080 01000000 00000000
-# ^ R_MIPS_TLS_DTPMOD32
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Content: "0400000008000000"
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: L1
- Type: R_MIPS_TLS_LDM
- - Offset: 4
- Symbol: L2
- Type: R_MIPS_TLS_LDM
-
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Local:
- - Name: L1
- Type: STT_TLS
- Section: .tdata
- Value: 0
- Size: 4
- - Name: L2
- Type: STT_TLS
- Section: .tdata
- Value: 4
- Size: 4
-
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 8
-...
diff --git a/test/old-elf/Mips/tls-4.test b/test/old-elf/Mips/tls-4.test
deleted file mode 100644
index 95df6d67151f..000000000000
--- a/test/old-elf/Mips/tls-4.test
+++ /dev/null
@@ -1,123 +0,0 @@
-# Check handling of R_MIPS_TLS_LDM relocation and generation of corresponding
-# dynamic relocation R_MIPS_TLS_DTPMOD32.
-
-# RUN: yaml2obj -format=elf -docnum 1 -o %t-so1.o %s
-# RUN: yaml2obj -format=elf -docnum 2 -o %t-so2.o %s
-# RUN: lld -flavor old-gnu -target mipsel -shared -o %t.so %t-so1.o %t-so2.o
-
-# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s
-# RUN: llvm-readobj -dynamic-table %t.so | FileCheck -check-prefix=DYN %s
-# RUN: llvm-readobj -dt %t.so | FileCheck -check-prefix=SYM %s
-# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=GOT %s
-
-# REL: Section (4) .rel.dyn {
-# REL-NEXT: 0x2008 R_MIPS_TLS_DTPMOD32 - 0x0
-# REL-NEXT: }
-
-# DYN: 0x7000000A MIPS_LOCAL_GOTNO 2
-# DYN: 0x70000013 MIPS_GOTSYM 0x4
-
-# SYM: Name: @ (0)
-# SYM: Name: T1@ (1)
-# SYM: Name: T2@ (4)
-# SYM: Name: T3@ (7)
-
-# GOT: Contents of section .got:
-# GOT-NEXT: 2000 00000000 00000080 00000000 00000000 ................
-# Two LDM entries --^--------^
-
-# so1.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: L01
- Type: R_MIPS_TLS_LDM
- - Offset: 0x04
- Symbol: L01
- Type: R_MIPS_TLS_LDM
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Local:
- - Name: L01
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 0x00
- Size: 0x04
- - Name: T2
- Type: STT_FUNC
- Section: .text
- Value: 0x04
- Size: 0x04
-
-# so2.o
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: L02
- Type: R_MIPS_TLS_LDM
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Local:
- - Name: L02
- Type: STT_TLS
- Section: .tdata
- Size: 0x04
- Global:
- - Name: T3
- Type: STT_FUNC
- Section: .text
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/tls-5-64.test b/test/old-elf/Mips/tls-5-64.test
deleted file mode 100644
index 43e6e6c1cf30..000000000000
--- a/test/old-elf/Mips/tls-5-64.test
+++ /dev/null
@@ -1,71 +0,0 @@
-# Check that in case of an executable file linking symbol referred
-# by the R_MIPS_TLS_GD relocation gets an entry in the dynamic symbol table.
-
-# RUN: yaml2obj -format=elf -o %t-o.o %s
-# RUN: lld -flavor old-gnu -target mips64el -e T0 -o %t.exe %t-o.o
-
-# Check dynamic relocations:
-# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
-# Check dynamic symbol table:
-# RUN: llvm-readobj -dt %t.exe | FileCheck -check-prefix=SYM %s
-
-# REL: Relocations [
-# REL-NEXT: Section (5) .rel.dyn {
-# REL-NEXT: 0x120002010 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE T1 0x0
-# REL-NEXT: 0x120002018 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE T1 0x0
-# REL-NEXT: }
-# REL-NEXT: ]
-
-# SYM: Symbol {
-# SYM: Name: T1@ (1)
-# SYM-NEXT: Value: 0x0
-# SYM-NEXT: Size: 8
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: TLS (0x6)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .tdata (0x7)
-# SYM-NEXT: }
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 8
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_TLS_GD
-
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 4
- Size: 8
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 8
- - Name: T1
- Type: STT_TLS
- Section: .tdata
- Value: 0
- Size: 8
-...
diff --git a/test/old-elf/Mips/tls-5-micro.test b/test/old-elf/Mips/tls-5-micro.test
deleted file mode 100644
index 412456417826..000000000000
--- a/test/old-elf/Mips/tls-5-micro.test
+++ /dev/null
@@ -1,70 +0,0 @@
-# Check that in case of an executable file linking symbol referred by
-# the R_MICROMIPS_TLS_GD relocation gets an entry in the dynamic symbol table.
-
-# RUN: yaml2obj -format=elf -o %t-o.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o
-
-# Check dynamic relocations:
-# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
-# Check dynamic symbol table:
-# RUN: llvm-readobj -dt %t.exe | FileCheck -check-prefix=SYM %s
-
-# REL: Relocations [
-# REL-NEXT: Section (5) .rel.dyn {
-# REL-NEXT: 0x402008 R_MIPS_TLS_DTPMOD32 T1 0x0
-# REL-NEXT: 0x40200C R_MIPS_TLS_DTPREL32 T1 0x0
-# REL-NEXT: }
-# REL-NEXT: ]
-
-# SYM: Symbol {
-# SYM: Name: T1@ (1)
-# SYM-NEXT: Value: 0x0
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: TLS (0x6)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .tdata (0x7)
-# SYM-NEXT: }
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MICROMIPS_TLS_GD
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: T1
- Type: STT_TLS
- Section: .tdata
- Value: 0x00
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/tls-5.test b/test/old-elf/Mips/tls-5.test
deleted file mode 100644
index cb71e3ac5f9e..000000000000
--- a/test/old-elf/Mips/tls-5.test
+++ /dev/null
@@ -1,69 +0,0 @@
-# Check that in case of an executable file linking symbol referred
-# by the R_MIPS_TLS_GD relocation gets an entry in the dynamic symbol table.
-
-# RUN: yaml2obj -format=elf -o %t-o.o %s
-# RUN: lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t-o.o
-
-# Check dynamic relocations:
-# RUN: llvm-readobj -r %t.exe | FileCheck -check-prefix=REL %s
-# Check dynamic symbol table:
-# RUN: llvm-readobj -dt %t.exe | FileCheck -check-prefix=SYM %s
-
-# REL: Relocations [
-# REL-NEXT: Section (5) .rel.dyn {
-# REL-NEXT: 0x402008 R_MIPS_TLS_DTPMOD32 T1 0x0
-# REL-NEXT: 0x40200C R_MIPS_TLS_DTPREL32 T1 0x0
-# REL-NEXT: }
-# REL-NEXT: ]
-
-# SYM: Symbol {
-# SYM: Name: T1@ (1)
-# SYM-NEXT: Value: 0x0
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: TLS (0x6)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .tdata (0x7)
-# SYM-NEXT: }
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
- EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x10
- Size: 0x04
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: T1
- Type: R_MIPS_TLS_GD
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 0x04
- - Name: T1
- Type: STT_TLS
- Section: .tdata
- Value: 0x00
- Size: 0x04
-...
diff --git a/test/old-elf/Mips/validate-rel-01.test b/test/old-elf/Mips/validate-rel-01.test
deleted file mode 100644
index 0b8734c5429e..000000000000
--- a/test/old-elf/Mips/validate-rel-01.test
+++ /dev/null
@@ -1,82 +0,0 @@
-# Check that the linker does not accept position-dependent relocations
-# in case of shared library linking.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-hi.o
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so %t-hi.o 2>&1 \
-# RUN: | FileCheck -check-prefix=RHI %s
-
-# RHI: R_MIPS_HI16 (5) relocation cannot be used when making a shared object, recompile {{.*}}validate-rel-01.test.tmp-hi.o with -fPIC
-
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-26.o
-# RUN: not lld -flavor old-gnu -target mipsel -shared -o %t.so %t-26.o 2>&1 \
-# RUN: | FileCheck -check-prefix=R26 %s
-
-# R26: R_MIPS_26 (4) relocation cannot be used when making a shared object, recompile {{.*}}validate-rel-01.test.tmp-26.o with -fPIC
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 4
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T0
- Type: R_MIPS_HI16
- - Offset: 0
- Symbol: T0
- Type: R_MIPS_LO16
-
-Symbols:
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 4
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 4
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: T1
- Type: R_MIPS_26
-
-Symbols:
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 4
-...
diff --git a/test/old-elf/Mips/validate-rel-03.test b/test/old-elf/Mips/validate-rel-03.test
deleted file mode 100644
index baf8516c63b0..000000000000
--- a/test/old-elf/Mips/validate-rel-03.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# Check that the linker does not accept R_MIPS_CALL16 relocation
-# against local symbol.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.o
-# RUN: not lld -flavor old-gnu -target mipsel -e T0 -o %t.exe %t.o 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: R_MIPS_CALL16 (11) relocation cannot be used against local symbol L0 in file {{.*}}validate-rel-03.test.tmp.o
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 16
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 8
- Symbol: T0
- Type: R_MIPS_CALL16
- - Offset: 4
- Symbol: L0
- Type: R_MIPS_CALL16
-
-Symbols:
- Local:
- - Name: L0
- Type: STT_FUNC
- Section: .text
- Value: 0
- Size: 4
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 4
- Size: 4
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Value: 8
- Size: 8
-...
diff --git a/test/old-elf/X86_64/ExampleTarget/triple.test b/test/old-elf/X86_64/ExampleTarget/triple.test
deleted file mode 100644
index aec09eae3a30..000000000000
--- a/test/old-elf/X86_64/ExampleTarget/triple.test
+++ /dev/null
@@ -1,32 +0,0 @@
-# Check that the Example Target is actually used.
-
-# RUN: yaml2obj -format=elf %s -o %t.o
-# RUN: lld -flavor old-gnu -target x86_64-example-freebsd9 %t.o -o %t.exe
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-#
-# CHECK: Type: 0xFF00
-
-# object
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E5B864000000C745FC000000005DC366666666662E0F1F840000000000554889E531C05DC3
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000000
diff --git a/test/old-elf/X86_64/Inputs/constint.c b/test/old-elf/X86_64/Inputs/constint.c
deleted file mode 100644
index 9fc0ebcf6591..000000000000
--- a/test/old-elf/X86_64/Inputs/constint.c
+++ /dev/null
@@ -1 +0,0 @@
-const int b = 20;
diff --git a/test/old-elf/X86_64/Inputs/constint.o b/test/old-elf/X86_64/Inputs/constint.o
deleted file mode 100644
index 8324b73014d0..000000000000
--- a/test/old-elf/X86_64/Inputs/constint.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/debug0.c b/test/old-elf/X86_64/Inputs/debug0.c
deleted file mode 100644
index 1ebe50087383..000000000000
--- a/test/old-elf/X86_64/Inputs/debug0.c
+++ /dev/null
@@ -1,5 +0,0 @@
-int adena();
-
-int main() {
-return adena();
-}
diff --git a/test/old-elf/X86_64/Inputs/debug0.x86-64 b/test/old-elf/X86_64/Inputs/debug0.x86-64
deleted file mode 100644
index 914f5224b9a2..000000000000
--- a/test/old-elf/X86_64/Inputs/debug0.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/debug1.c b/test/old-elf/X86_64/Inputs/debug1.c
deleted file mode 100644
index 281b8a361dbb..000000000000
--- a/test/old-elf/X86_64/Inputs/debug1.c
+++ /dev/null
@@ -1,3 +0,0 @@
-int adena() {
-return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/debug1.x86-64 b/test/old-elf/X86_64/Inputs/debug1.x86-64
deleted file mode 100644
index bfc81458a034..000000000000
--- a/test/old-elf/X86_64/Inputs/debug1.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/externtls.c b/test/old-elf/X86_64/Inputs/externtls.c
deleted file mode 100644
index 499a645a9217..000000000000
--- a/test/old-elf/X86_64/Inputs/externtls.c
+++ /dev/null
@@ -1,6 +0,0 @@
-extern __thread int extern_tls;
-
-int main() {
- extern_tls = 1;
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/externtls.x86-64 b/test/old-elf/X86_64/Inputs/externtls.x86-64
deleted file mode 100644
index 3019aa0ca27c..000000000000
--- a/test/old-elf/X86_64/Inputs/externtls.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/fn.c b/test/old-elf/X86_64/Inputs/fn.c
deleted file mode 100644
index 54939a2426b2..000000000000
--- a/test/old-elf/X86_64/Inputs/fn.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int fn()
-{
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/fn.o b/test/old-elf/X86_64/Inputs/fn.o
deleted file mode 100644
index 4b67d459dfdb..000000000000
--- a/test/old-elf/X86_64/Inputs/fn.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/generaltls-so.o.yaml b/test/old-elf/X86_64/Inputs/generaltls-so.o.yaml
deleted file mode 100644
index 53a7fb6435e9..000000000000
--- a/test/old-elf/X86_64/Inputs/generaltls-so.o.yaml
+++ /dev/null
@@ -1,67 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E566488D3D00000000666648E8000000008B005DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: mynumber
- Type: R_X86_64_TLSGD
- Addend: -4
- - Offset: 0x0000000000000010
- Symbol: __tls_get_addr
- Type: R_X86_64_PLT32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Content: '21000000'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .tdata
- Type: STT_SECTION
- Section: .tdata
- Global:
- - Name: getnumber
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000018
- - Name: mynumber
- Type: STT_TLS
- Section: .tdata
- Size: 0x0000000000000004
- - Name: _GLOBAL_OFFSET_TABLE_
- - Name: __tls_get_addr
-...
diff --git a/test/old-elf/X86_64/Inputs/group/1.c b/test/old-elf/X86_64/Inputs/group/1.c
deleted file mode 100644
index f5e618bc4a85..000000000000
--- a/test/old-elf/X86_64/Inputs/group/1.c
+++ /dev/null
@@ -1,8 +0,0 @@
-int _start() {
- return 0;
-}
-
-int main() {
-fn();
-return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/group/1.o b/test/old-elf/X86_64/Inputs/group/1.o
deleted file mode 100644
index 743518eb0fa3..000000000000
--- a/test/old-elf/X86_64/Inputs/group/1.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/group/fn.c b/test/old-elf/X86_64/Inputs/group/fn.c
deleted file mode 100644
index e443c73a1ee0..000000000000
--- a/test/old-elf/X86_64/Inputs/group/fn.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int fn() {
-fn1();
-return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/group/fn.o b/test/old-elf/X86_64/Inputs/group/fn.o
deleted file mode 100644
index 1134432449cd..000000000000
--- a/test/old-elf/X86_64/Inputs/group/fn.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/group/fn1.c b/test/old-elf/X86_64/Inputs/group/fn1.c
deleted file mode 100644
index cca0df7fd277..000000000000
--- a/test/old-elf/X86_64/Inputs/group/fn1.c
+++ /dev/null
@@ -1,3 +0,0 @@
-int fn1() {
-fn2();
-}
diff --git a/test/old-elf/X86_64/Inputs/group/fn1.o b/test/old-elf/X86_64/Inputs/group/fn1.o
deleted file mode 100644
index 2b02310003db..000000000000
--- a/test/old-elf/X86_64/Inputs/group/fn1.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/group/fn2.c b/test/old-elf/X86_64/Inputs/group/fn2.c
deleted file mode 100644
index a60370ed1e6b..000000000000
--- a/test/old-elf/X86_64/Inputs/group/fn2.c
+++ /dev/null
@@ -1,3 +0,0 @@
-int fn2() {
-return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/group/fn2.o b/test/old-elf/X86_64/Inputs/group/fn2.o
deleted file mode 100644
index fabec849a775..000000000000
--- a/test/old-elf/X86_64/Inputs/group/fn2.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/group/group.sh b/test/old-elf/X86_64/Inputs/group/group.sh
deleted file mode 100755
index 2eba1030160b..000000000000
--- a/test/old-elf/X86_64/Inputs/group/group.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-cat > 1.c << \!
-int _start() {
- return 0;
-}
-
-int main() {
-fn();
-return 0;
-}
-!
-
-cat > fn.c << \!
-int fn() {
-fn1();
-return 0;
-}
-!
-
-cat > fn2.c << \!
-int fn2() {
-return 0;
-}
-!
-
-cat > fn1.c << \!
-int fn1() {
-fn2();
-}
-!
-
-gcc -c 1.c fn.c fn2.c fn1.c
-ar cr libfn.a fn.o fn2.o
-ar cr libfn1.a fn1.o
-lld -flavor gnu -target x86_64 -shared -o libfn2.so fn2.o
-lld -flavor gnu -target x86_64 1.o libfn.a libfn1.a -o x
-lld -flavor gnu -target x86_64 1.o --start-group libfn.a libfn1.a --end-group -o x
-lld -flavor gnu -target x86_64 1.o --start-group fn.o fn2.o fn1.o --end-group -o x
-lld -flavor gnu -target x86_64 1.o --start-group --whole-archive libfn.a --no-whole-archive libfn1.a --end-group -o x
diff --git a/test/old-elf/X86_64/Inputs/group/libfn.a b/test/old-elf/X86_64/Inputs/group/libfn.a
deleted file mode 100644
index c157c3babed9..000000000000
--- a/test/old-elf/X86_64/Inputs/group/libfn.a
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/group/libfn.so b/test/old-elf/X86_64/Inputs/group/libfn.so
deleted file mode 100755
index fcbd11fe5519..000000000000
--- a/test/old-elf/X86_64/Inputs/group/libfn.so
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/group/libfn1.a b/test/old-elf/X86_64/Inputs/group/libfn1.a
deleted file mode 100644
index 69b9c75b5d16..000000000000
--- a/test/old-elf/X86_64/Inputs/group/libfn1.a
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/group/libfn2.so b/test/old-elf/X86_64/Inputs/group/libfn2.so
deleted file mode 100755
index 7ce867373910..000000000000
--- a/test/old-elf/X86_64/Inputs/group/libfn2.so
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/initfini-option.c b/test/old-elf/X86_64/Inputs/initfini-option.c
deleted file mode 100644
index e9a6c08c12ac..000000000000
--- a/test/old-elf/X86_64/Inputs/initfini-option.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-
-void init() {
- printf("%s\n", __FUNCTION__);
-}
-
-void fini() {
- printf("%s\n", __FUNCTION__);
-}
-
-int main() {
-}
-
diff --git a/test/old-elf/X86_64/Inputs/initfini-option.o b/test/old-elf/X86_64/Inputs/initfini-option.o
deleted file mode 100644
index b1ba0557353c..000000000000
--- a/test/old-elf/X86_64/Inputs/initfini-option.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/initfini.c b/test/old-elf/X86_64/Inputs/initfini.c
deleted file mode 100644
index 9427a86b6c9b..000000000000
--- a/test/old-elf/X86_64/Inputs/initfini.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdio.h>
-
-void __attribute__ ((constructor)) constructor() {
- printf("%s\n", __FUNCTION__);
-}
-
-void __attribute__ ((destructor)) destructor() {
- printf("%s\n", __FUNCTION__);
-}
-
-int main() {
- return 0;
-}
-
diff --git a/test/old-elf/X86_64/Inputs/initfini.o b/test/old-elf/X86_64/Inputs/initfini.o
deleted file mode 100644
index f0e55a90b8b6..000000000000
--- a/test/old-elf/X86_64/Inputs/initfini.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/largebss.c b/test/old-elf/X86_64/Inputs/largebss.c
deleted file mode 100644
index 157d01755b6a..000000000000
--- a/test/old-elf/X86_64/Inputs/largebss.c
+++ /dev/null
@@ -1,3 +0,0 @@
-int largebss[1000] = { 0 };
-int largecommon[1000];
-__thread int largetbss[1000] = { 0 };
diff --git a/test/old-elf/X86_64/Inputs/largebss.o b/test/old-elf/X86_64/Inputs/largebss.o
deleted file mode 100644
index 377370ec2db2..000000000000
--- a/test/old-elf/X86_64/Inputs/largebss.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/layoutpass/1.c b/test/old-elf/X86_64/Inputs/layoutpass/1.c
deleted file mode 100644
index fec984503214..000000000000
--- a/test/old-elf/X86_64/Inputs/layoutpass/1.c
+++ /dev/null
@@ -1,8 +0,0 @@
-int main() {
- a();
- return 0;
-}
-
-int b() {
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/layoutpass/1.o b/test/old-elf/X86_64/Inputs/layoutpass/1.o
deleted file mode 100644
index 848a5b3321ac..000000000000
--- a/test/old-elf/X86_64/Inputs/layoutpass/1.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/layoutpass/2.c b/test/old-elf/X86_64/Inputs/layoutpass/2.c
deleted file mode 100644
index fb9dbcc28aa6..000000000000
--- a/test/old-elf/X86_64/Inputs/layoutpass/2.c
+++ /dev/null
@@ -1,7 +0,0 @@
-int a() {
- return 0;
-}
-
-int c() {
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/layoutpass/2.o b/test/old-elf/X86_64/Inputs/layoutpass/2.o
deleted file mode 100644
index 4c5ef8679581..000000000000
--- a/test/old-elf/X86_64/Inputs/layoutpass/2.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/layoutpass/3.c b/test/old-elf/X86_64/Inputs/layoutpass/3.c
deleted file mode 100644
index 054029fe5cfe..000000000000
--- a/test/old-elf/X86_64/Inputs/layoutpass/3.c
+++ /dev/null
@@ -1,3 +0,0 @@
-int d() {
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/layoutpass/3.o b/test/old-elf/X86_64/Inputs/layoutpass/3.o
deleted file mode 100644
index 76ef76e97901..000000000000
--- a/test/old-elf/X86_64/Inputs/layoutpass/3.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/layoutpass/lib2.a b/test/old-elf/X86_64/Inputs/layoutpass/lib2.a
deleted file mode 100644
index 5f076c869817..000000000000
--- a/test/old-elf/X86_64/Inputs/layoutpass/lib2.a
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/libfn.a b/test/old-elf/X86_64/Inputs/libfn.a
deleted file mode 100644
index 380844b0838d..000000000000
--- a/test/old-elf/X86_64/Inputs/libfn.a
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/libfn.so b/test/old-elf/X86_64/Inputs/libfn.so
deleted file mode 100755
index dc02480aa690..000000000000
--- a/test/old-elf/X86_64/Inputs/libfn.so
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/main.c b/test/old-elf/X86_64/Inputs/main.c
deleted file mode 100644
index 0280c9127076..000000000000
--- a/test/old-elf/X86_64/Inputs/main.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int main() {
- fn();
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/main.o b/test/old-elf/X86_64/Inputs/main.o
deleted file mode 100644
index ec8929f4b51d..000000000000
--- a/test/old-elf/X86_64/Inputs/main.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/multi-ovrd.c b/test/old-elf/X86_64/Inputs/multi-ovrd.c
deleted file mode 100644
index cf6c0b6ac361..000000000000
--- a/test/old-elf/X86_64/Inputs/multi-ovrd.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <stdio.h>
-void f(void)
-{
- printf("overridden f!\n");
-}
-
-void g(void)
-{
- printf("overridden g!\n");
-}
diff --git a/test/old-elf/X86_64/Inputs/multi-ovrd.o b/test/old-elf/X86_64/Inputs/multi-ovrd.o
deleted file mode 100644
index e4c4d6037fdd..000000000000
--- a/test/old-elf/X86_64/Inputs/multi-ovrd.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/multi-weak.c b/test/old-elf/X86_64/Inputs/multi-weak.c
deleted file mode 100644
index 10b9160352d9..000000000000
--- a/test/old-elf/X86_64/Inputs/multi-weak.c
+++ /dev/null
@@ -1,20 +0,0 @@
-int fn()
-{
- return 0;
-}
-
-void __attribute__((weak)) f()
-{
- printf("original f..\n");
-}
-
-void __attribute__((weak)) g()
-{
- printf("original f..\n");
-}
-
-int main(void)
-{
- f();
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/multi-weak.o b/test/old-elf/X86_64/Inputs/multi-weak.o
deleted file mode 100644
index d5677b699ac4..000000000000
--- a/test/old-elf/X86_64/Inputs/multi-weak.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/multiweaksyms.o b/test/old-elf/X86_64/Inputs/multiweaksyms.o
deleted file mode 100644
index 5e2e54d66b0d..000000000000
--- a/test/old-elf/X86_64/Inputs/multiweaksyms.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/nmagic.c b/test/old-elf/X86_64/Inputs/nmagic.c
deleted file mode 100644
index 3ad15f0c4971..000000000000
--- a/test/old-elf/X86_64/Inputs/nmagic.c
+++ /dev/null
@@ -1,8 +0,0 @@
-int a = 10;
-__thread int b = 20;
-__thread int c;
-__thread int d;
-
-int main() {
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/nmagic.o b/test/old-elf/X86_64/Inputs/nmagic.o
deleted file mode 100644
index af28e0ada8b3..000000000000
--- a/test/old-elf/X86_64/Inputs/nmagic.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/no-interp-section.c b/test/old-elf/X86_64/Inputs/no-interp-section.c
deleted file mode 100644
index 3981c038ed33..000000000000
--- a/test/old-elf/X86_64/Inputs/no-interp-section.c
+++ /dev/null
@@ -1 +0,0 @@
-int c = 10;
diff --git a/test/old-elf/X86_64/Inputs/no-interp-section.o b/test/old-elf/X86_64/Inputs/no-interp-section.o
deleted file mode 100644
index 063eb3244f22..000000000000
--- a/test/old-elf/X86_64/Inputs/no-interp-section.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/note.o b/test/old-elf/X86_64/Inputs/note.o
deleted file mode 100644
index d86b0cf85d19..000000000000
--- a/test/old-elf/X86_64/Inputs/note.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/note.s b/test/old-elf/X86_64/Inputs/note.s
deleted file mode 100644
index 0a0b03da6bb7..000000000000
--- a/test/old-elf/X86_64/Inputs/note.s
+++ /dev/null
@@ -1,11 +0,0 @@
- .section ".note.ident", "a"
- .p2align 2
- .long 1f - 0f # name size (not including padding)
- .long 3f - 2f # desc size (not including padding)
- .long 0x01234567 # type
-0: .asciz "NaMe" # name
-1: .p2align 2
-2: .long 0x76543210 # desc
- .long 0x89abcdef
-3: .p2align 2
-
diff --git a/test/old-elf/X86_64/Inputs/note_ro_rw.o b/test/old-elf/X86_64/Inputs/note_ro_rw.o
deleted file mode 100644
index 76f2486d2736..000000000000
--- a/test/old-elf/X86_64/Inputs/note_ro_rw.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/note_ro_rw.s b/test/old-elf/X86_64/Inputs/note_ro_rw.s
deleted file mode 100644
index 2a0eff5dfb2b..000000000000
--- a/test/old-elf/X86_64/Inputs/note_ro_rw.s
+++ /dev/null
@@ -1,21 +0,0 @@
- .section ".note.ro", "a"
- .p2align 2
- .long 1f - 0f # name size (not including padding)
- .long 3f - 2f # desc size (not including padding)
- .long 0x01234567 # type
-0: .asciz "NaMe" # name
-1: .p2align 2
-2: .long 0x76543210 # desc
- .long 0x89abcdef
-3: .p2align 2
- .section ".note.rw", "aw"
- .p2align 2
- .long 1f - 0f # name size (not including padding)
- .long 3f - 2f # desc size (not including padding)
- .long 0x01234567 # type
-0: .asciz "NaMe" # name
-1: .p2align 2
-2: .long 0x76543210 # desc
- .long 0x89abcdef
-3: .p2align 2
-
diff --git a/test/old-elf/X86_64/Inputs/ovrd.c b/test/old-elf/X86_64/Inputs/ovrd.c
deleted file mode 100644
index a3d721dac2aa..000000000000
--- a/test/old-elf/X86_64/Inputs/ovrd.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-void f(void)
-{
- printf("overridden f!\n");
-}
-
diff --git a/test/old-elf/X86_64/Inputs/ovrd.o b/test/old-elf/X86_64/Inputs/ovrd.o
deleted file mode 100644
index ea7353d94ed9..000000000000
--- a/test/old-elf/X86_64/Inputs/ovrd.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/rodata.c b/test/old-elf/X86_64/Inputs/rodata.c
deleted file mode 100644
index 01489fe550c8..000000000000
--- a/test/old-elf/X86_64/Inputs/rodata.c
+++ /dev/null
@@ -1,3 +0,0 @@
-const char _nl_default_default_domain[] __attribute__ ((visibility ("hidden"))) = "messages";
-const char *_nl_current_default_domain __attribute__ ((visibility ("hidden"))) = _nl_default_default_domain;
-const char _nl_default_default_dirname[] = "/usr/local";
diff --git a/test/old-elf/X86_64/Inputs/rodata.o b/test/old-elf/X86_64/Inputs/rodata.o
deleted file mode 100644
index 660606cdc9c0..000000000000
--- a/test/old-elf/X86_64/Inputs/rodata.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/rodata.s b/test/old-elf/X86_64/Inputs/rodata.s
deleted file mode 100644
index e1a2eb702736..000000000000
--- a/test/old-elf/X86_64/Inputs/rodata.s
+++ /dev/null
@@ -1,24 +0,0 @@
- .file "x.c"
- .hidden _nl_default_default_domain
- .globl _nl_default_default_domain
- .section .rodata._nl_default_default_domain,"ams",@progbits,1
- .type _nl_default_default_domain, @object
- .size _nl_default_default_domain, 9
-_nl_default_default_domain:
- .string "messages"
- .hidden _nl_current_default_domain
- .globl _nl_current_default_domain
- .section .data._nl_current_default_domain,"aw",@progbits
- .align 8
- .type _nl_current_default_domain, @object
- .size _nl_current_default_domain, 8
-_nl_current_default_domain:
- .quad _nl_default_default_domain
- .globl _nl_default_default_dirname
- .section .rodata._nl_default_default_dirname,"ams",@progbits,1
- .type _nl_default_default_dirname, @object
- .size _nl_default_default_dirname, 11
-_nl_default_default_dirname:
- .string "/usr/local"
- .ident "GCC: (Ubuntu 4.8.1-2ubuntu1~10.04.1) 4.8.1"
- .section .note.GNU-stack,"",@progbits
diff --git a/test/old-elf/X86_64/Inputs/rwint.c b/test/old-elf/X86_64/Inputs/rwint.c
deleted file mode 100644
index d1cf7d62c801..000000000000
--- a/test/old-elf/X86_64/Inputs/rwint.c
+++ /dev/null
@@ -1 +0,0 @@
-int a = 10;
diff --git a/test/old-elf/X86_64/Inputs/rwint.o b/test/old-elf/X86_64/Inputs/rwint.o
deleted file mode 100644
index 9fba51f07add..000000000000
--- a/test/old-elf/X86_64/Inputs/rwint.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/sectionmap.c b/test/old-elf/X86_64/Inputs/sectionmap.c
deleted file mode 100644
index c4f530148949..000000000000
--- a/test/old-elf/X86_64/Inputs/sectionmap.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int foo __attribute__((section(".gcc_except_table.foo"))) = 4;
-const int bar __attribute__((section(".data.rel.local"))) = 2;
-const int baz __attribute__((section(".data.rel.ro"))) = 2;
-const int bak __attribute__((section(".data.xyz"))) = 2;
diff --git a/test/old-elf/X86_64/Inputs/sectionmap.o b/test/old-elf/X86_64/Inputs/sectionmap.o
deleted file mode 100644
index 599cf2cca563..000000000000
--- a/test/old-elf/X86_64/Inputs/sectionmap.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/undefcpp.c b/test/old-elf/X86_64/Inputs/undefcpp.c
deleted file mode 100644
index ce84c2a592b6..000000000000
--- a/test/old-elf/X86_64/Inputs/undefcpp.c
+++ /dev/null
@@ -1 +0,0 @@
-int foo() { return _Z3fooPKc(); }
diff --git a/test/old-elf/X86_64/Inputs/undefcpp.o b/test/old-elf/X86_64/Inputs/undefcpp.o
deleted file mode 100644
index 6b8ebf5b6ab0..000000000000
--- a/test/old-elf/X86_64/Inputs/undefcpp.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/weak-zero-sized.o b/test/old-elf/X86_64/Inputs/weak-zero-sized.o
deleted file mode 100644
index 7c10c6a509ed..000000000000
--- a/test/old-elf/X86_64/Inputs/weak-zero-sized.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/weak.c b/test/old-elf/X86_64/Inputs/weak.c
deleted file mode 100644
index ae07ffc745d8..000000000000
--- a/test/old-elf/X86_64/Inputs/weak.c
+++ /dev/null
@@ -1,14 +0,0 @@
-int fn()
-{
- return 0;
-}
-
-void __attribute__((weak)) f()
-{
- printf("original f..\n");
-}
-int main(void)
-{
- f();
- return 0;
-}
diff --git a/test/old-elf/X86_64/Inputs/weak.o b/test/old-elf/X86_64/Inputs/weak.o
deleted file mode 100644
index 41cc88a0c482..000000000000
--- a/test/old-elf/X86_64/Inputs/weak.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/weak.s b/test/old-elf/X86_64/Inputs/weak.s
deleted file mode 100644
index 64ce779553b6..000000000000
--- a/test/old-elf/X86_64/Inputs/weak.s
+++ /dev/null
@@ -1,21 +0,0 @@
- .file "weak.s"
- .text
- .p2align 4,,15
- .globl test
- .type test, @function
-test:
- ret
- .size test, .-test
- .weak myfn2
- .data
- .align 8
- .type myfn2, @object
- .size myfn2, 8
-myfn2:
- .quad test
- .weak myfn1
- .align 8
- .type myfn1, @object
- .size myfn1, 8
-myfn1:
- .quad test
diff --git a/test/old-elf/X86_64/Inputs/zerosizedsection.o b/test/old-elf/X86_64/Inputs/zerosizedsection.o
deleted file mode 100644
index a0f2f13a307a..000000000000
--- a/test/old-elf/X86_64/Inputs/zerosizedsection.o
+++ /dev/null
Binary files differ
diff --git a/test/old-elf/X86_64/Inputs/zerosizedsection.s b/test/old-elf/X86_64/Inputs/zerosizedsection.s
deleted file mode 100644
index 651ee3aab503..000000000000
--- a/test/old-elf/X86_64/Inputs/zerosizedsection.s
+++ /dev/null
@@ -1,3 +0,0 @@
-.text
-.data
-.word .text
diff --git a/test/old-elf/X86_64/alignoffset.test b/test/old-elf/X86_64/alignoffset.test
deleted file mode 100644
index 53e29211af67..000000000000
--- a/test/old-elf/X86_64/alignoffset.test
+++ /dev/null
@@ -1,118 +0,0 @@
-# Checks that segments are aligned as per ELF spec. The segment virtual address
-# modulo page alignment should be equal to offset modulo page alignment.
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 1 %s -o %t.o
-# RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t.exe -static \
-# RUN: --no-align-segments --rosegment --noinhibit-exec
-# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s
-#
-#CHECK: Offset: 0x15C
-#CHECK: VirtualAddress: 0x40015C
-#CHECK: PhysicalAddress: 0x40015C
-#
-#
-#const int a = 0;
-#int main() {
-# foo();
-# return 0;
-#}
-#
-#int foo() { return 0; }
-
-# object
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E54883EC10C745FC00000000E81C000000B9000000008945F889C84883C4105DC36666662E0F1F840000000000554889E5B8000000005DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '00000000'
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 005562756E747520636C616E672076657273696F6E20332E352E302D73766E3231373330342D317E6578703120286272616E636865732F72656C656173655F33352920286261736564206F6E204C4C564D20332E352E302900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000180000001C000000000000002400000000410E108602430D060000001800000038000000000000000B00000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 0
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 48
-Symbols:
- Local:
- - Name: 1.c
- Type: STT_FILE
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: a
- Type: STT_OBJECT
- Section: .rodata
- Size: 0x0000000000000004
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000030
- Size: 0x000000000000000B
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000024
-...
diff --git a/test/old-elf/X86_64/debug.test b/test/old-elf/X86_64/debug.test
deleted file mode 100644
index 26ba367da574..000000000000
--- a/test/old-elf/X86_64/debug.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# Test that debug info is assigned typeNoAlloc and that the output sections have
-# a virtual address of 0.
-RUN: lld -flavor old-gnu -target x86_64 -e main --output-filetype=yaml \
-RUN: %p/Inputs/debug0.x86-64 %p/Inputs/debug1.x86-64 -o %t
-RUN: FileCheck %s -check-prefix YAML < %t
-
-RUN: lld -flavor old-gnu -target x86_64 -e main %p/Inputs/debug0.x86-64 \
-RUN: %p/Inputs/debug1.x86-64 -o %t1
-RUN: llvm-readobj -sections %t1 | FileCheck %s -check-prefix ELF
-# Verify that non SHF_ALLOC sections are relocated correctly.
-RUN: llvm-objdump -s %t1 | FileCheck %s -check-prefix RELOC
-
-YAML: type: no-alloc
-
-ELF: Section {
-ELF: Name: .debug_info
-ELF: Type: SHT_PROGBITS (0x1)
-ELF: Flags [ (0x0)
-ELF: ]
-ELF: Address: 0x0
-ELF: }
-ELF: Section {
-ELF: Name: .debug_abbrev
-ELF: Type: SHT_PROGBITS (0x1)
-ELF: Flags [ (0x0)
-ELF: ]
-ELF: Address: 0x0
-ELF: }
-ELF: Section {
-ELF: Name: .debug_aranges
-ELF: Type: SHT_PROGBITS (0x1)
-ELF: Flags [ (0x0)
-ELF: ]
-ELF: Address: 0x0
-ELF: }
-ELF: Section {
-ELF: Name: .debug_line
-ELF: Type: SHT_PROGBITS (0x1)
-ELF: Flags [ (0x0)
-ELF: ]
-ELF: Address: 0x0
-ELF: }
-ELF: Section {
-ELF: Name: .debug_str
-ELF: Type: SHT_PROGBITS (0x1)
-ELF: Flags [ (0x0)
-ELF: ]
-ELF: Address: 0x0
-ELF: }
-
-RELOC: Contents of section .debug_info:
-RELOC: 0000 4e000000 04000000 00000801 3a000000 N...........:...
-# ^^ Relocation: ._debug_str + 0x3a
-RELOC: 0010 01780000 00000000 00dc0140 00000000 .x.........@....
-# ^^ Relocation: .debug_str + 0x78
-RELOC: 0020 00100000 00000000 00000000 00028100 ................
-# ^^ Relocation: .debug_str + 0x81
diff --git a/test/old-elf/X86_64/defsym.test b/test/old-elf/X86_64/defsym.test
deleted file mode 100644
index d98abf39d428..000000000000
--- a/test/old-elf/X86_64/defsym.test
+++ /dev/null
@@ -1,22 +0,0 @@
-RUN: lld -flavor old-gnu -target x86_64 --defsym=main=fn --noinhibit-exec \
-RUN: %p/Inputs/fn.o -o %t
-RUN: llvm-readobj -symbols %t | FileCheck %s
-
-CHECK: Symbol {
-CHECK: Name: main (1)
-CHECK: Value: 0x4001E0
-CHECK: Size: 0
-CHECK: Binding: Global (0x1)
-CHECK: Type: Function (0x2)
-CHECK: Other: 0
-CHECK: Section: .text (0x5)
-CHECK: }
-CHECK: Symbol {
-CHECK: Name: fn (6)
-CHECK: Value: 0x4001E0
-CHECK: Size: 6
-CHECK: Binding: Global (0x1)
-CHECK: Type: Function (0x2)
-CHECK: Other: 0
-CHECK: Section: .text (0x5)
-CHECK: }
diff --git a/test/old-elf/X86_64/demangle.test b/test/old-elf/X86_64/demangle.test
deleted file mode 100644
index caae8256d99a..000000000000
--- a/test/old-elf/X86_64/demangle.test
+++ /dev/null
@@ -1,12 +0,0 @@
-# XFAIL: win32
-#
-# Check that the linker is able to demangle strings properly.
-# Once there is a way to add undefined symbols using yaml2obj, the test will be
-# changed.
-
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/undefcpp.o --noinhibit-exec 2>&1 | FileCheck -check-prefix=DEMANGLE %s
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/undefcpp.o --noinhibit-exec --no-demangle 2>&1 | FileCheck -check-prefix=NODEMANGLE %s
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/undefcpp.o --noinhibit-exec --demangle 2>&1 | FileCheck -check-prefix=DEMANGLE %s
-
-#DEMANGLE: undefcpp.o: foo(char const*)
-#NODEMANGLE: undefcpp.o: _Z3fooPKc
diff --git a/test/old-elf/X86_64/dontignorezerosize-sections.test b/test/old-elf/X86_64/dontignorezerosize-sections.test
deleted file mode 100644
index f3042b5508fd..000000000000
--- a/test/old-elf/X86_64/dontignorezerosize-sections.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# This tests that lld is not ignoring zero sized sections
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/zerosizedsection.o \
-RUN: --noinhibit-exec --output-filetype=yaml -o %t
-RUN: FileCheck %s < %t
-
-CHECK: references:
-CHECK: - kind: R_X86_64_16
-CHECK: offset: 0
-CHECK: target: L000
diff --git a/test/old-elf/X86_64/dynamicvars.test b/test/old-elf/X86_64/dynamicvars.test
deleted file mode 100644
index c6f679038320..000000000000
--- a/test/old-elf/X86_64/dynamicvars.test
+++ /dev/null
@@ -1,123 +0,0 @@
-# Tests that the dynamic variables created by the linker are set to the right
-# values.
-
-#RUN: yaml2obj --format elf -docnum 1 %s -o %t.o
-#RUN: lld -flavor old-gnu -target x86_64 -e main %t.o -o %t1 --noinhibit-exec
-#RUN: llvm-readobj -sections -symbols %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-
-#CHECKSYMS: Name: .dynamic
-#CHECKSYMS: Type: SHT_DYNAMIC
-#CHECKSYMS: Address: [[TARGETA:[0xa-fA-f0-9]+]]
-#CHECKSYMS: Name: .got.plt
-#CHECKSYMS: Type: SHT_PROGBITS
-#CHECKSYMS: Address: [[TARGETB:[0xa-fA-f0-9]+]]
-#CHECKSYMS: Name: _DYNAMIC
-#CHECKSYMS: Value: [[TARGETA]]
-#CHECKSYMS: Section: .dynamic
-#CHECKSYMS: Name: _GLOBAL_OFFSET_TABLE_
-#CHECKSYMS: Value: [[TARGETB]]
-#CHECKSYMS: Section: .got.plt
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E54883EC10488B0500000000C745FC00000000C7000A000000E80000000031C98945F889C84883C4105DC36690554889E531C05DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x000000000000000B
- Symbol: a
- Type: R_X86_64_GOTPCREL
- Addend: -4
- - Offset: 0x000000000000001D
- Symbol: foo
- Type: R_X86_64_PLT32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E362E302000
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000180000001C000000000000002E00000000410E108602430D060000001800000038000000000000000800000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 0
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 48
-Symbols:
- Local:
- - Name: 1.c
- Type: STT_FILE
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: a
- Type: STT_OBJECT
- Value: 0x0000000000000004
- Size: 0x0000000000000004
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000030
- Size: 0x0000000000000008
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000002E
- - Name: _GLOBAL_OFFSET_TABLE_
-...
diff --git a/test/old-elf/X86_64/dynlib-nointerp-section.test b/test/old-elf/X86_64/dynlib-nointerp-section.test
deleted file mode 100644
index c23d283d2a6d..000000000000
--- a/test/old-elf/X86_64/dynlib-nointerp-section.test
+++ /dev/null
@@ -1,4 +0,0 @@
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/no-interp-section.o -o %t -shared
-RUN: llvm-objdump -section-headers %t | FileCheck %s
-
-CHECK-NOT: .interp
diff --git a/test/old-elf/X86_64/dynlib-search.test b/test/old-elf/X86_64/dynlib-search.test
deleted file mode 100644
index efd7272fb145..000000000000
--- a/test/old-elf/X86_64/dynlib-search.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# This tests the functionality for finding the shared library libfn.so for ELF
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/main.o -L%p/Inputs/ -lfn -o %t \
-RUN: --noinhibit-exec -t 2> %t1
-RUN: FileCheck %s < %t1
-
-CHECK: {{[\/0-9A-Za-z_]+}}libfn.so
diff --git a/test/old-elf/X86_64/dynsym-weak.test b/test/old-elf/X86_64/dynsym-weak.test
deleted file mode 100644
index 8e1cc9fa8ec9..000000000000
--- a/test/old-elf/X86_64/dynsym-weak.test
+++ /dev/null
@@ -1,118 +0,0 @@
-# Check that a symbol declared as a week in a shared library gets a dynamic
-# symbol table record in an executable file if this executabe file declares the
-# symbol as strong.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t.foo.o
-# RUN: lld -flavor old-gnu -target x86_64 -shared -o %t.so %t.foo.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t.main.o
-#
-# Link executable file with strong symbol. Weak symbol is in the shared lib.
-# RUN: lld -flavor old-gnu -target x86_64 -e main -o %t1.exe %t.main.o %t.so
-# RUN: llvm-readobj -dyn-symbols %t1.exe | FileCheck -check-prefix=EXE %s
-#
-# Link executable file. Strong and weak symbol come from different object files.
-# RUN: lld -flavor old-gnu -target x86_64 -e main -o %t2.exe %t.main.o %t.foo.o
-# RUN: llvm-readobj -dyn-symbols %t2.exe | FileCheck -check-prefix=OBJ %s
-#
-# Link shared library. Weak symbol is in the another shared lib.
-# RUN: lld -flavor old-gnu -target x86_64 -shared -o %t.res.so %t.main.o %t.so
-# RUN: llvm-readobj -dyn-symbols %t.res.so | FileCheck -check-prefix=SO %s
-
-# EXE: Symbol {
-# EXE: Name: flag@ ({{[0-9]+}})
-# EXE-NEXT: Value: 0x{{[0-9A-F]+}}
-# EXE-NEXT: Size: 4
-# EXE-NEXT: Binding: Global (0x1)
-# EXE-NEXT: Type: Object (0x1)
-# EXE-NEXT: Other: 0
-# EXE-NEXT: Section: .data (0x{{[0-9A-F]+}})
-# EXE-NEXT: }
-
-# OBJ-NOT: Name: flag@ ({{[0-9]+}})
-
-# SO: Symbol {
-# SO: Name: flag@ ({{[0-9]+}})
-# SO-NEXT: Value: 0x{{[0-9A-F]+}}
-# SO-NEXT: Size: 4
-# SO-NEXT: Binding: Global (0x1)
-# SO-NEXT: Type: Object (0x1)
-# SO-NEXT: Other: 0
-# SO-NEXT: Section: .data (0x{{[0-9A-F]+}})
-# SO-NEXT: }
-
-# foo.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x08
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: flag
- Type: R_X86_64_GOTPCREL
- Addend: -4
-
-Symbols:
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- Weak:
- - Name: flag
-
-# main.o
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x08
- Info: .text
- Relocations:
- - Offset: 0x00
- Symbol: foo
- Type: R_X86_64_PLT32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x04
- Size: 0x04
-
-Symbols:
- Global:
- - Name: flag
- Type: STT_OBJECT
- Section: .data
- Size: 0x04
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- - Name: foo
-...
diff --git a/test/old-elf/X86_64/extern-tls.test b/test/old-elf/X86_64/extern-tls.test
deleted file mode 100644
index d22b06057a9a..000000000000
--- a/test/old-elf/X86_64/extern-tls.test
+++ /dev/null
@@ -1,16 +0,0 @@
-# This tests verifies that TLS variables have correct offsets
-# when variables the TLS variables are not defined in the program
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/externtls.x86-64 -static \
-RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s -check-prefix=CHECKGOT
-
-# Currently x86_64 relocation pass handles the R_X86_64_GOTTPOFF by
-# creatng R_X86_64_TPOFF64 dynamic ones. For output yaml, this is
-# not changed.
- - name: __got_tls_extern_tls
-CHECKGOT: alignment: 4
-CHECKGOT: section-name: .text
-CHECKGOT: references:
-CHECKGOT: - kind: R_X86_64_GOTTPOFF
-CHECKGOT: offset: 7
-CHECKGOT: target: extern_tls
-CHECKGOT: addend: -4
diff --git a/test/old-elf/X86_64/general-dynamic-tls.test b/test/old-elf/X86_64/general-dynamic-tls.test
deleted file mode 100644
index 12ad1071ae1e..000000000000
--- a/test/old-elf/X86_64/general-dynamic-tls.test
+++ /dev/null
@@ -1,128 +0,0 @@
-# This test exercises a simple general dynamic TLS access model in X86_64.
-#
-# It is composed of two parts: a program and a shared library. The shared
-# library uses TLS, but the program does not.
-#
-# The shared library should import __tls_get_addr, since it uses the general
-# dynamic TLS access mode (see www.akkadia.org/drepper/tls.pdf). Notice that
-# once we support TLS strength reduction, this test should be updated, since
-# this can be converted into a local dynamic TLS model.
-
-# Prepare inputs
-#RUN: yaml2obj -format=elf %p/Inputs/generaltls-so.o.yaml -o=%t.o.so
-#RUN: lld -flavor old-gnu -target x86_64 -shared %t.o.so -o %T/libgeneraltls.so
-#RUN: yaml2obj -format=elf %s -o=%t.o
-
-# Link - (we supply --defsym=__tls_get_addr to avoid the need to link with
-# system libraries)
-#RUN: lld -flavor old-gnu -target x86_64 -e main %t.o -L%T -lgeneraltls -o %t1 \
-#RUN: --defsym=__tls_get_addr=0
-
-# Check
-#RUN: llvm-readobj -dyn-symbols %t1 | FileCheck -check-prefix CHECKPROG %s
-#RUN: llvm-readobj -relocations -dyn-symbols %T/libgeneraltls.so | FileCheck \
-#RUN: -check-prefix CHECKDSO %s
-
-# Test case generated with the following code:
-#
-# DSO: (file %p/Inputs/generaltls-so.o.yaml)
-#
-# __thread int mynumber=33;
-#
-# int getnumber() {
-# return mynumber;
-# }
-#
-# Program: (this file). Note: The printf() relocation was removed to simplify
-# this test and allow us to test this without libc.
-#
-# #include <stdio.h>
-# int getnumber();
-#
-# int main() {
-# printf("getnumber() = %d\n", getnumber());
-# return 0;
-# }
-#
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E54883EC10C745FC00000000B000E80000000048BF000000000000000089C6B000E80000000031F68945F889F04883C4105DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000012
- Symbol: getnumber
- Type: R_X86_64_PC32
- Addend: -4
- - Offset: 0x0000000000000018
- Symbol: .rodata.str1.1
- Type: R_X86_64_64
- Addend: 0
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .rodata.str1.1
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 6765746E756D6265722829203D2025640A00
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .rodata.str1.1
- Type: STT_SECTION
- Section: .rodata.str1.1
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000036
- - Name: getnumber
-
-# Program should import the function defined in the shared library
-#CHECKPROG: getnumber@
-# Program should not import __tls_get_addr, since it does not directly use TLS
-#CHECKPROG-NOT: __tls_get_addr@
-
-# Check for the presence of X86_64 TLS relocations in the shared library
-#CHECKDSO: R_X86_64_DTPMOD64
-#CHECKDSO: R_X86_64_DTPOFF64
-#CHECKDSO: R_X86_64_JUMP_SLOT
-
-# The shared library should import __tls_get_addr, since it uses the general
-# dynamic TLS access mode.
-#CHECKDSO: Name: __tls_get_addr@
-#CHECKDSO-NEXT: Value: 0x0
-#CHECKDSO-NEXT: Size: 0
-#CHECKDSO-NEXT: Binding: Global
-#CHECKDSO-NEXT: Type: None
-#CHECKDSO-NEXT: Other: 0
-#CHECKDSO-NEXT: Section: Undefined
-
diff --git a/test/old-elf/X86_64/imagebase.test b/test/old-elf/X86_64/imagebase.test
deleted file mode 100644
index 7b6f7318d72d..000000000000
--- a/test/old-elf/X86_64/imagebase.test
+++ /dev/null
@@ -1,94 +0,0 @@
-# Checks that segments start at the image address specified.
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 1 %s -o %t.o
-# RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t.exe -static \
-# RUN: --no-align-segments --noinhibit-exec --image-base 0x600000
-# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s
-#
-#CHECK: VirtualAddress: 0x600000
-#CHECK: PhysicalAddress: 0x600000
-#CHECK: VirtualAddress: 0x600178
-#CHECK: PhysicalAddress: 0x600178
-
-# object
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E5B864000000C745FC000000005DC366666666662E0F1F840000000000554889E531C05DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Size: 4
- - Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '64000000'
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000180000001C000000000000001200000000410E108602430D060000001800000038000000000000000800000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 0
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000020
- Size: 0x0000000000000008
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000012
- - Name: myval
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- - Name: val
- Type: STT_OBJECT
- Section: .rodata
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/X86_64/initfini-order.test b/test/old-elf/X86_64/initfini-order.test
deleted file mode 100644
index e6afcf644346..000000000000
--- a/test/old-elf/X86_64/initfini-order.test
+++ /dev/null
@@ -1,10 +0,0 @@
-# This tests the functionality that lld is able to emit
-# init_array/fini_array sections in the right order.
-
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/initfini.o \
-RUN: --noinhibit-exec -o %t
-RUN: llvm-objdump -t -section-headers %t | FileCheck %s
-
-CHECK: {{[0-9]+}} .eh_frame {{[0-9a-z]+}} {{[0-9a-z]+}} DATA
-CHECK: {{[0-9]+}} .init_array {{[0-9a-z]+}} {{[0-9a-z]+}} DATA
-CHECK: {{[0-9]+}} .fini_array {{[0-9a-z]+}} {{[0-9a-z]+}} DATA
diff --git a/test/old-elf/X86_64/initfini.test b/test/old-elf/X86_64/initfini.test
deleted file mode 100644
index 09d2bc129c25..000000000000
--- a/test/old-elf/X86_64/initfini.test
+++ /dev/null
@@ -1,23 +0,0 @@
-# This tests the functionality that lld is able to read
-# init_array/fini_array sections in the input ELF. This
-# corresponds to the the .init_array/.fini_array sections
-# in the output ELF.
-
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/initfini.o \
-RUN: --noinhibit-exec --output-filetype=yaml -o %t
-RUN: FileCheck %s < %t
-
-CHECK: - type: data
-CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECK: section-name: .init_array
-CHECK: references:
-CHECK: - kind: R_X86_64_64
-CHECK: offset: 0
-CHECK: target: constructor
-CHECK: - type: data
-CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECK: section-name: .fini_array
-CHECK: references:
-CHECK: - kind: R_X86_64_64
-CHECK: offset: 0
-CHECK: target: destructor
diff --git a/test/old-elf/X86_64/largebss.test b/test/old-elf/X86_64/largebss.test
deleted file mode 100644
index 722ec1c72bf9..000000000000
--- a/test/old-elf/X86_64/largebss.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# This tests the functionality of handling BSS symbols
-# BSS symbols don't occupy file content and are associated with typeZeroFill
-# Any typeZeroFill content wouldn't have space reserved in the file to store
-# its content
-
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/largebss.o --output-filetype=yaml --noinhibit-exec | FileCheck %s
-
-CHECK: - name: largecommon
-CHECK: scope: global
-CHECK: type: zero-fill
-CHECK: size: 4000
-CHECK: merge: as-tentative
-CHECK: - name: largebss
-CHECK: scope: global
-CHECK: type: zero-fill
-CHECK: size: 4000
-CHECK: - name: largetbss
-CHECK: scope: global
-CHECK: type: thread-zero-fill
-CHECK: size: 4000
diff --git a/test/old-elf/X86_64/layoutpass-order.test b/test/old-elf/X86_64/layoutpass-order.test
deleted file mode 100644
index ec180c970e78..000000000000
--- a/test/old-elf/X86_64/layoutpass-order.test
+++ /dev/null
@@ -1,14 +0,0 @@
-# This test checks that we follow the command line order of layouting
-# symbols in the output file
-
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/layoutpass/1.o \
-RUN: %p/Inputs/layoutpass/lib2.a %p/Inputs/layoutpass/3.o -o %t \
-RUN: --noinhibit-exec -static
-
-RUN: llvm-nm -n %t | FileCheck -check-prefix=SYMBOLSORDER %s
-
-SYMBOLSORDER: {{[A-Fa-f0-9]+}} T main
-SYMBOLSORDER: {{[A-Fa-f0-9]+}} T b
-SYMBOLSORDER: {{[A-Fa-f0-9]+}} T a
-SYMBOLSORDER: {{[A-Fa-f0-9]+}} T c
-SYMBOLSORDER: {{[A-Fa-f0-9]+}} T d
diff --git a/test/old-elf/X86_64/maxpagesize.test b/test/old-elf/X86_64/maxpagesize.test
deleted file mode 100644
index 303bd86eec0b..000000000000
--- a/test/old-elf/X86_64/maxpagesize.test
+++ /dev/null
@@ -1,113 +0,0 @@
-# Checks that segments are aligned as per ELF spec when the user specifies
-# max-page-size option, and the segment alignment is set to the page size
-# specified by the user.
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 1 %s -o %t.o
-# RUN: not lld -flavor old-gnu -target x86_64 %t.o -o %t.exe -static \
-# RUN: --no-align-segments --noinhibit-exec -z max-page-size=0
-# RUN: not lld -flavor old-gnu -target x86_64 %t.o -o %t.exe -static \
-# RUN: --no-align-segments --noinhibit-exec -z max-page-size=0xFF
-# RUN: not lld -flavor old-gnu -target x86_64 %t.o -o %t.exe -static \
-# RUN: --no-align-segments --noinhibit-exec -z max-page-size=0x1010
-# RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t1.exe -static \
-# RUN: --no-align-segments --noinhibit-exec -z max-page-size=0x100000
-# RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t.exe -static \
-# RUN: --no-align-segments --noinhibit-exec -z max-page-size=0x10000
-# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s
-# RUN: llvm-readobj -program-headers %t1.exe | FileCheck %s -check-prefix=CHECKLARGE
-#
-#CHECK: VirtualAddress: 0x400000
-#CHECK: PhysicalAddress: 0x400000
-#CHECK: Alignment: 65536
-#CHECK: VirtualAddress: 0x400178
-#CHECK: PhysicalAddress: 0x400178
-#CHECK: Alignment: 65536
-#CHECKLARGE: VirtualAddress: 0x400000
-#CHECKLARGE: PhysicalAddress: 0x400000
-#CHECKLARGE: Alignment: 1048576
-#CHECKLARGE: VirtualAddress: 0x400178
-#CHECKLARGE: PhysicalAddress: 0x400178
-#CHECKLARGE: Alignment: 1048576
-
-# object
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E5B864000000C745FC000000005DC366666666662E0F1F840000000000554889E531C05DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Size: 4
- - Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '64000000'
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000180000001C000000000000001200000000410E108602430D060000001800000038000000000000000800000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 0
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000020
- Size: 0x0000000000000008
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000012
- - Name: myval
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- - Name: val
- Type: STT_OBJECT
- Section: .rodata
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/X86_64/mergesimilarstrings.test b/test/old-elf/X86_64/mergesimilarstrings.test
deleted file mode 100644
index 2b9b08faa23f..000000000000
--- a/test/old-elf/X86_64/mergesimilarstrings.test
+++ /dev/null
@@ -1,47 +0,0 @@
-# Check that relocations to section that contains strings is properly handled
-# when merging strings is enabled.
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target x86_64 %t.o --noinhibit-exec -o %t1.out
-# RUN: llvm-readobj -sections %t1.out | FileCheck %s
-# RUN: lld -flavor old-gnu -target x86_64 %t.o --noinhibit-exec -o %t2.out --output-filetype=yaml
-# RUN: FileCheck %s -check-prefix=CHECKRELOCS < %t2.out
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Content: 54889e5488d3d00000000e80000000088d3d00000000e800000000b8000000005dc3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x04
- Info: .text
- Relocations:
- - Offset: 0x07
- Symbol: .rodata
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x01
- Content: 48656c6c6f20576f726c6400576f726c6400
-Symbols:
- Global:
- - Name: .rodata
- Section: .rodata
-
-#CHECK: Name: .rodata
-#CHECK: Size: 18
-#CHECKRELOCS: references:
-#CHECKRELOCS: - kind: R_X86_64_PC32
-#CHECKRELOCS: offset: 7
-#CHECKRELOCS: target: .rodata
-#CHECKRELOCS: addend: -4
diff --git a/test/old-elf/X86_64/multi-weak-layout.test b/test/old-elf/X86_64/multi-weak-layout.test
deleted file mode 100644
index 879b4b1b3052..000000000000
--- a/test/old-elf/X86_64/multi-weak-layout.test
+++ /dev/null
@@ -1,52 +0,0 @@
-# Test that we are able to layout multiple weak symbols
-# properly
-
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/multiweaksyms.o \
-RUN: --noinhibit-exec -static --output-filetype=yaml -o %t
-RUN: FileCheck %s -check-prefix=WEAKSYMS < %t
-
-WEAKSYMS: - type: data
-WEAKSYMS: alignment: 8
-WEAKSYMS: references:
-WEAKSYMS: - kind: layout-after
-WEAKSYMS: offset: 0
-WEAKSYMS: target: [[L001:[-a-zA-Z0-9_]+]]
-WEAKSYMS: - name: myfn2
-WEAKSYMS: scope: global
-WEAKSYMS: type: data
-WEAKSYMS: merge: as-weak
-WEAKSYMS: alignment: 8
-WEAKSYMS: references:
-WEAKSYMS: - kind: layout-after
-WEAKSYMS: offset: 0
-WEAKSYMS: target: [[L001]]
-WEAKSYMS: - ref-name: [[L001]]
-WEAKSYMS: scope: global
-WEAKSYMS: type: data
-WEAKSYMS: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-WEAKSYMS: alignment: 8
-WEAKSYMS: references:
-WEAKSYMS: - kind: R_X86_64_64
-WEAKSYMS: offset: 0
-WEAKSYMS: target: test
-WEAKSYMS: - kind: layout-after
-WEAKSYMS: offset: 0
-WEAKSYMS: target: [[L003:[-a-zA-Z0-9_]+]]
-WEAKSYMS: - name: myfn1
-WEAKSYMS: scope: global
-WEAKSYMS: type: data
-WEAKSYMS: merge: as-weak
-WEAKSYMS: alignment: 8
-WEAKSYMS: references:
-WEAKSYMS: - kind: layout-after
-WEAKSYMS: offset: 0
-WEAKSYMS: target: [[L003]]
-WEAKSYMS: - ref-name: [[L003]]
-WEAKSYMS: scope: global
-WEAKSYMS: type: data
-WEAKSYMS: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-WEAKSYMS: alignment: 8
-WEAKSYMS: references:
-WEAKSYMS: - kind: R_X86_64_64
-WEAKSYMS: offset: 0
-WEAKSYMS: target: test
diff --git a/test/old-elf/X86_64/multi-weak-override.test b/test/old-elf/X86_64/multi-weak-override.test
deleted file mode 100644
index 75c86e7e405f..000000000000
--- a/test/old-elf/X86_64/multi-weak-override.test
+++ /dev/null
@@ -1,16 +0,0 @@
-# Test for weak symbol getting overridden
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/multi-weak.o \
-RUN: %p/Inputs/multi-ovrd.o -o %t -e main --noinhibit-exec
-RUN: llvm-nm -n %t | FileCheck -check-prefix=WEAKORDER %s
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/multi-weak.o \
-RUN: %p/Inputs/multi-ovrd.o --output-filetype=yaml -o %t2 --noinhibit-exec
-RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2
-
-WEAKORDER: {{[0-9a-f]+}} T f
-WEAKORDER: {{[0-9a-f]+}} T g
-
-WEAKATOMSORDER: - ref-name: {{[A-Z0-9]+}}
-WEAKATOMSORDER: - ref-name: {{[A-Z0-9]+}}
-WEAKATOMSORDER: - name: f
-WEAKATOMSORDER: - name: g
-
diff --git a/test/old-elf/X86_64/multi-weak-syms-order.test b/test/old-elf/X86_64/multi-weak-syms-order.test
deleted file mode 100644
index a8e21e13f870..000000000000
--- a/test/old-elf/X86_64/multi-weak-syms-order.test
+++ /dev/null
@@ -1,13 +0,0 @@
-# Test for weak symbol getting overridden
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/multi-weak.o -o %t --noinhibit-exec
-RUN: llvm-nm -n %t | FileCheck -check-prefix=WEAKORDER %s
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/multi-weak.o -o %t2 --output-filetype=yaml --noinhibit-exec
-RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2
-
-WEAKORDER: {{[0-9a-f]+}} T fn
-WEAKORDER: {{[0-9a-f]+}} T f
-WEAKORDER: {{[0-9a-f]+}} T g
-WEAKORDER: {{[0-9a-f]+}} T main
-
-WEAKATOMSORDER: - name: f
-WEAKATOMSORDER: - name: g
diff --git a/test/old-elf/X86_64/nmagic.test b/test/old-elf/X86_64/nmagic.test
deleted file mode 100644
index 3ed9228fa787..000000000000
--- a/test/old-elf/X86_64/nmagic.test
+++ /dev/null
@@ -1,91 +0,0 @@
-# This tests verifies functionality of NMAGIC that we create only two segments,
-# PT_LOAD, PT_TLS
-# The data segment should be aligned to a page boundary
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/nmagic.o \
-RUN: --noinhibit-exec -o %t --nmagic -static
-RUN: llvm-readobj -sections %t | FileCheck -check-prefix=NMAGICSECTIONS %s
-RUN: llvm-readobj -program-headers %t | FileCheck -check-prefix=NMAGICPROGRAMHEADERS %s
-
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Index: 0
-NMAGICSECTIONS: Name: (0)
-NMAGICSECTIONS: Type: SHT_NULL (0x0)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .text
-NMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .eh_frame
-NMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .tdata
-NMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .tbss
-NMAGICSECTIONS: Type: SHT_NOBITS (0x8)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .got.plt
-NMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .data
-NMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .bss
-NMAGICSECTIONS: Type: SHT_NOBITS (0x8)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .comment
-NMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .note.GNU-stack
-NMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .shstrtab
-NMAGICSECTIONS: Type: SHT_STRTAB (0x3)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .symtab
-NMAGICSECTIONS: Type: SHT_SYMTAB (0x2)
-NMAGICSECTIONS: }
-NMAGICSECTIONS: Section {
-NMAGICSECTIONS: Name: .strtab
-NMAGICSECTIONS: Type: SHT_STRTAB (0x3)
-NMAGICSECTIONS: }
-
-NMAGICPROGRAMHEADERS: ProgramHeaders [
-NMAGICPROGRAMHEADERS: ProgramHeader {
-NMAGICPROGRAMHEADERS: Type: PT_LOAD (0x1)
-NMAGICPROGRAMHEADERS: Offset: 0x0
-NMAGICPROGRAMHEADERS: VirtualAddress: 0x400000
-NMAGICPROGRAMHEADERS: PhysicalAddress: 0x400000
-NMAGICPROGRAMHEADERS: FileSize: 4108
-NMAGICPROGRAMHEADERS: MemSize: 4108
-NMAGICPROGRAMHEADERS: Flags [ (0x7)
-NMAGICPROGRAMHEADERS: PF_R (0x4)
-NMAGICPROGRAMHEADERS: PF_W (0x2)
-NMAGICPROGRAMHEADERS: PF_X (0x1)
-NMAGICPROGRAMHEADERS: ]
-NMAGICPROGRAMHEADERS: Alignment: 8
-NMAGICPROGRAMHEADERS: }
-NMAGICPROGRAMHEADERS: ProgramHeader {
-NMAGICPROGRAMHEADERS: Type: PT_TLS (0x7)
-NMAGICPROGRAMHEADERS: Offset: 0x1000
-NMAGICPROGRAMHEADERS: VirtualAddress: 0x401000
-NMAGICPROGRAMHEADERS: PhysicalAddress: 0x401000
-NMAGICPROGRAMHEADERS: FileSize: 4
-NMAGICPROGRAMHEADERS: MemSize: 12
-NMAGICPROGRAMHEADERS: Flags [ (0x6)
-NMAGICPROGRAMHEADERS: PF_R (0x4)
-NMAGICPROGRAMHEADERS: PF_W (0x2)
-NMAGICPROGRAMHEADERS: ]
-NMAGICPROGRAMHEADERS: Alignment: 4
-NMAGICPROGRAMHEADERS: }
-NMAGICPROGRAMHEADERS: ]
diff --git a/test/old-elf/X86_64/noalignsegments.test b/test/old-elf/X86_64/noalignsegments.test
deleted file mode 100644
index 4963575b674b..000000000000
--- a/test/old-elf/X86_64/noalignsegments.test
+++ /dev/null
@@ -1,95 +0,0 @@
-# Checks that segments are aligned as per ELF spec than aligning each
-# segment fileoffset / virtual address to a page.
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 1 %s -o %t.o
-# RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t.exe -static \
-# RUN: --no-align-segments --noinhibit-exec
-# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s
-#
-#CHECK: VirtualAddress: 0x400000
-#CHECK: PhysicalAddress: 0x400000
-#CHECK: VirtualAddress: 0x400178
-#CHECK: PhysicalAddress: 0x400178
-
-# object
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E5B864000000C745FC000000005DC366666666662E0F1F840000000000554889E531C05DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Size: 4
- - Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: '64000000'
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000180000001C000000000000001200000000410E108602430D060000001800000038000000000000000800000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 0
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000020
- Size: 0x0000000000000008
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000012
- - Name: myval
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- - Name: val
- Type: STT_OBJECT
- Section: .rodata
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/X86_64/note-sections-ro_plus_rw.test b/test/old-elf/X86_64/note-sections-ro_plus_rw.test
deleted file mode 100644
index b4eafaf277c4..000000000000
--- a/test/old-elf/X86_64/note-sections-ro_plus_rw.test
+++ /dev/null
@@ -1,42 +0,0 @@
-# This tests the functionality that lld is able to recreate the note sections
-# if they appear in the input, it looks like we need to differentiate RO note
-# sections from RW note sections, and each creating a segment of its own
-
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/note_ro_rw.o \
-RUN: --noinhibit-exec -o %t -static
-RUN: llvm-readobj -sections %t | FileCheck -check-prefix=NOTESECTIONS %s
-RUN: llvm-readobj -program-headers %t | FileCheck -check-prefix=NOTESEGMENT %s
-
-NOTESECTIONS: Section {
-NOTESECTIONS: Name: .note.ro (1)
-NOTESECTIONS: Type: SHT_NOTE (0x7)
-NOTESECTIONS: Flags [ (0x2)
-NOTESECTIONS: SHF_ALLOC (0x2)
-NOTESECTIONS: ]
-NOTESECTIONS: AddressAlignment: 4
-NOTESECTIONS: }
-NOTESECTIONS: Section {
-NOTESECTIONS: Name: .note.rw (31)
-NOTESECTIONS: Type: SHT_NOTE (0x7)
-NOTESECTIONS: Flags [ (0x3)
-NOTESECTIONS: SHF_ALLOC (0x2)
-NOTESECTIONS: SHF_WRITE (0x1)
-NOTESECTIONS: ]
-NOTESECTIONS: Size: 28
-NOTESECTIONS: AddressAlignment: 4
-NOTESECTIONS: }
-NOTESEGMENT: ProgramHeader {
-NOTESEGMENT: Type: PT_NOTE (0x4)
-NOTESEGMENT: Flags [ (0x4)
-NOTESEGMENT: PF_R (0x4)
-NOTESEGMENT: ]
-NOTESEGMENT: Alignment: 4
-NOTESEGMENT: }
-NOTESEGMENT: ProgramHeader {
-NOTESEGMENT: Type: PT_NOTE (0x4)
-NOTESEGMENT: Flags [ (0x6)
-NOTESEGMENT: PF_R (0x4)
-NOTESEGMENT: PF_W (0x2)
-NOTESEGMENT: ]
-NOTESEGMENT: Alignment: 4
-NOTESEGMENT: }
diff --git a/test/old-elf/X86_64/note-sections.test b/test/old-elf/X86_64/note-sections.test
deleted file mode 100644
index b831e7e192b4..000000000000
--- a/test/old-elf/X86_64/note-sections.test
+++ /dev/null
@@ -1,23 +0,0 @@
-# This tests the functionality that lld is able to recreate the note sections
-# if they appear in the input
-
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/note.o \
-RUN: --noinhibit-exec -o %t -static
-RUN: llvm-readobj -sections %t | FileCheck -check-prefix=NOTESECTIONS %s
-RUN: llvm-readobj -program-headers %t | FileCheck -check-prefix=NOTESEGMENT %s
-
-
-NOTESECTIONS: Section {
-NOTESECTIONS: Index: 1
-NOTESECTIONS: Name: .note.ident (1)
-NOTESECTIONS: Type: SHT_NOTE (0x7)
-NOTESECTIONS: Size: 28
-NOTESECTIONS: AddressAlignment: 4
-NOTESECTIONS: }
-
-NOTESEGMENT: ProgramHeader {
-NOTESEGMENT: Type: PT_NOTE (0x4)
-NOTESEGMENT: FileSize: 28
-NOTESEGMENT: MemSize: 28
-NOTESEGMENT: Alignment: 4
-NOTESEGMENT: }
diff --git a/test/old-elf/X86_64/omagic.test b/test/old-elf/X86_64/omagic.test
deleted file mode 100644
index fe2633e67a95..000000000000
--- a/test/old-elf/X86_64/omagic.test
+++ /dev/null
@@ -1,237 +0,0 @@
-# This tests verifies functionality of omagic that we create only two segments,
-# PT_LOAD, PT_TLS
-# The data segment should not be aligned to a page boundary
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/nmagic.o \
-RUN: --noinhibit-exec -o %t --omagic -static
-RUN: llvm-readobj -sections %t | FileCheck -check-prefix=OMAGICSECTIONS %s
-RUN: llvm-readobj -program-headers %t | FileCheck -check-prefix=OMAGICPROGRAMHEADERS %s
-
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: (0)
-OMAGICSECTIONS: Type: SHT_NULL (0x0)
-OMAGICSECTIONS: Flags [ (0x0)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x0
-OMAGICSECTIONS: Offset: 0x0
-OMAGICSECTIONS: Size: 0
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 0
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .text
-OMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-OMAGICSECTIONS: Flags [ (0x6)
-OMAGICSECTIONS: SHF_ALLOC (0x2)
-OMAGICSECTIONS: SHF_EXECINSTR (0x4)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x4000E8
-OMAGICSECTIONS: Offset: 0xE8
-OMAGICSECTIONS: Size: 11
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 4
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .eh_frame
-OMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-OMAGICSECTIONS: Flags [ (0x2)
-OMAGICSECTIONS: SHF_ALLOC (0x2)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x4000F8
-OMAGICSECTIONS: Offset: 0xF8
-OMAGICSECTIONS: Size: 56
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 8
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .eh_frame_hdr
-OMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-OMAGICSECTIONS: Flags [ (0x2)
-OMAGICSECTIONS: SHF_ALLOC (0x2)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x400130
-OMAGICSECTIONS: Offset: 0x130
-OMAGICSECTIONS: Size: 8
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 8
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .tdata
-OMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-OMAGICSECTIONS: Flags [ (0x403)
-OMAGICSECTIONS: SHF_ALLOC (0x2)
-OMAGICSECTIONS: SHF_TLS (0x400)
-OMAGICSECTIONS: SHF_WRITE (0x1)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x400138
-OMAGICSECTIONS: Offset: 0x138
-OMAGICSECTIONS: Size: 4
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 4
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .tbss
-OMAGICSECTIONS: Type: SHT_NOBITS (0x8)
-OMAGICSECTIONS: Flags [ (0x403)
-OMAGICSECTIONS: SHF_ALLOC (0x2)
-OMAGICSECTIONS: SHF_TLS (0x400)
-OMAGICSECTIONS: SHF_WRITE (0x1)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x40013C
-OMAGICSECTIONS: Offset: 0x13C
-OMAGICSECTIONS: Size: 8
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 4
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .got.plt
-OMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-OMAGICSECTIONS: Flags [ (0x3)
-OMAGICSECTIONS: SHF_ALLOC (0x2)
-OMAGICSECTIONS: SHF_WRITE (0x1)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x400140
-OMAGICSECTIONS: Offset: 0x140
-OMAGICSECTIONS: Size: 0
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 8
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .data
-OMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-OMAGICSECTIONS: Flags [ (0x3)
-OMAGICSECTIONS: SHF_ALLOC (0x2)
-OMAGICSECTIONS: SHF_WRITE (0x1)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x400140
-OMAGICSECTIONS: Offset: 0x140
-OMAGICSECTIONS: Size: 4
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 4
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .bss
-OMAGICSECTIONS: Type: SHT_NOBITS (0x8)
-OMAGICSECTIONS: Flags [ (0x3)
-OMAGICSECTIONS: SHF_ALLOC (0x2)
-OMAGICSECTIONS: SHF_WRITE (0x1)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x400144
-OMAGICSECTIONS: Offset: 0x144
-OMAGICSECTIONS: Size: 0
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 4
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .comment
-OMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-OMAGICSECTIONS: Flags [ (0x0)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x0
-OMAGICSECTIONS: Offset: 0x144
-OMAGICSECTIONS: Size: 43
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 1
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .note.GNU-stack
-OMAGICSECTIONS: Type: SHT_PROGBITS (0x1)
-OMAGICSECTIONS: Flags [ (0x0)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x0
-OMAGICSECTIONS: Offset: 0x16F
-OMAGICSECTIONS: Size: 0
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 1
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .shstrtab
-OMAGICSECTIONS: Type: SHT_STRTAB (0x3)
-OMAGICSECTIONS: Flags [ (0x0)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x0
-OMAGICSECTIONS: Offset: 0x16F
-OMAGICSECTIONS: Size: 115
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 1
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .symtab
-OMAGICSECTIONS: Type: SHT_SYMTAB (0x2)
-OMAGICSECTIONS: Flags [ (0x0)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x0
-OMAGICSECTIONS: Offset: 0x1E8
-OMAGICSECTIONS: Size: 504
-OMAGICSECTIONS: Link: 13
-OMAGICSECTIONS: Info: 8
-OMAGICSECTIONS: AddressAlignment: 8
-OMAGICSECTIONS: EntrySize: 24
-OMAGICSECTIONS: }
-OMAGICSECTIONS: Section {
-OMAGICSECTIONS: Name: .strtab
-OMAGICSECTIONS: Type: SHT_STRTAB (0x3)
-OMAGICSECTIONS: Flags [ (0x0)
-OMAGICSECTIONS: ]
-OMAGICSECTIONS: Address: 0x0
-OMAGICSECTIONS: Offset: 0x3E0
-OMAGICSECTIONS: Size: 231
-OMAGICSECTIONS: Link: 0
-OMAGICSECTIONS: Info: 0
-OMAGICSECTIONS: AddressAlignment: 1
-OMAGICSECTIONS: EntrySize: 0
-OMAGICSECTIONS: }
-OMAGICSECTIONS: ]
-
-OMAGICPROGRAMHEADERS: ProgramHeaders [
-OMAGICPROGRAMHEADERS: ProgramHeader {
-OMAGICPROGRAMHEADERS: Type: PT_LOAD (0x1)
-OMAGICPROGRAMHEADERS: Offset: 0x0
-OMAGICPROGRAMHEADERS: VirtualAddress: 0x400000
-OMAGICPROGRAMHEADERS: PhysicalAddress: 0x400000
-OMAGICPROGRAMHEADERS: FileSize: 324
-OMAGICPROGRAMHEADERS: MemSize: 324
-OMAGICPROGRAMHEADERS: Flags [ (0x7)
-OMAGICPROGRAMHEADERS: PF_R (0x4)
-OMAGICPROGRAMHEADERS: PF_W (0x2)
-OMAGICPROGRAMHEADERS: PF_X (0x1)
-OMAGICPROGRAMHEADERS: ]
-OMAGICPROGRAMHEADERS: Alignment: 8
-OMAGICPROGRAMHEADERS: }
-OMAGICPROGRAMHEADERS: ProgramHeader {
-OMAGICPROGRAMHEADERS: Type: PT_TLS (0x7)
-OMAGICPROGRAMHEADERS: Offset: 0x138
-OMAGICPROGRAMHEADERS: VirtualAddress: 0x400138
-OMAGICPROGRAMHEADERS: PhysicalAddress: 0x400138
-OMAGICPROGRAMHEADERS: FileSize: 4
-OMAGICPROGRAMHEADERS: MemSize: 12
-OMAGICPROGRAMHEADERS: Flags [ (0x6)
-OMAGICPROGRAMHEADERS: PF_R (0x4)
-OMAGICPROGRAMHEADERS: PF_W (0x2)
-OMAGICPROGRAMHEADERS: ]
-OMAGICPROGRAMHEADERS: Alignment: 4
-OMAGICPROGRAMHEADERS: }
-OMAGICPROGRAMHEADERS: ]
diff --git a/test/old-elf/X86_64/outputsegments.test b/test/old-elf/X86_64/outputsegments.test
deleted file mode 100644
index 1c76b6eb855c..000000000000
--- a/test/old-elf/X86_64/outputsegments.test
+++ /dev/null
@@ -1,188 +0,0 @@
-# Tests that lld does not create separate segment if the input sections are part
-# of the same output section
-
-# Build executable
-# RUN: yaml2obj -format=elf -docnum 1 %s -o %t.o
-# RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t1.exe -static \
-# RUN: --no-align-segments --noinhibit-exec
-# RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t2.exe -static \
-# RUN: --noinhibit-exec
-# RUN: llvm-readobj -program-headers %t1.exe | FileCheck %s -check-prefix=SEGMENTS
-# RUN: llvm-readobj -program-headers %t2.exe | FileCheck %s -check-prefix=SEGMENTS
-#
-#SEGMENTS: VirtualAddress: 0x400000
-#SEGMENTS: PhysicalAddress: 0x400000
-#SEGMENTS: FileSize: 288
-#SEGMENTS: MemSize: 288
-#SEGMENTS: VirtualAddress: 0x404000
-#SEGMENTS: PhysicalAddress: 0x404000
-#SEGMENTS: FileSize: 16608
-#SEGMENTS: MemSize: 16608
-#SEGMENTS: Alignment: 16384
-#
-# object
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .text.foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000002000
- Content: 554889E54883EC1048BF0000000000000000B000E800000000B9000000008945FC89C84883C4105DC3
- - Name: .rela.text.foo
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text.foo
- Relocations:
- - Offset: 0x000000000000000A
- Symbol: .rodata.str1.1
- Type: R_X86_64_64
- Addend: 0
- - Offset: 0x0000000000000015
- Symbol: printf
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .text.bar
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000004000
- Content: 554889E54883EC1048BF0000000000000000B000E800000000B9000000008945FC89C84883C4105DC3
- - Name: .rela.text.bar
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text.bar
- Relocations:
- - Offset: 0x000000000000000A
- Symbol: .rodata.str1.1
- Type: R_X86_64_64
- Addend: 7
- - Offset: 0x0000000000000015
- Symbol: printf
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .text.main
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E54883EC10C745FC00000000E8000000008945F8E8000000008B4DF801C189C84883C4105DC3
- - Name: .rela.text.main
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text.main
- Relocations:
- - Offset: 0x0000000000000010
- Symbol: foo
- Type: R_X86_64_PC32
- Addend: -4
- - Offset: 0x0000000000000018
- Symbol: bar
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .rodata.str1.1
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 48656C6C6F0A00576F726C640A00
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 005562756E747520636C616E672076657273696F6E20332E352E302D73766E3231373330342D317E6578703120286272616E636865732F72656C656173655F33352920286261736564206F6E204C4C564D20332E352E302900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000180000001C000000000000002900000000410E108602430D060000001800000038000000000000002900000000410E108602430D060000001C00000054000000000000002900000000410E108602430D0600000000000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text.foo
- Type: R_X86_64_PC32
- Addend: 0
- - Offset: 0x000000000000003C
- Symbol: .text.bar
- Type: R_X86_64_PC32
- Addend: 0
- - Offset: 0x0000000000000058
- Symbol: .text.main
- Type: R_X86_64_PC32
- Addend: 0
-Symbols:
- Local:
- - Name: 1.c
- Type: STT_FILE
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .text.foo
- Type: STT_SECTION
- Section: .text.foo
- - Name: .text.bar
- Type: STT_SECTION
- Section: .text.bar
- - Name: .text.main
- Type: STT_SECTION
- Section: .text.main
- - Name: .rodata.str1.1
- Type: STT_SECTION
- Section: .rodata.str1.1
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: bar
- Type: STT_FUNC
- Section: .text.bar
- Size: 0x0000000000000029
- - Name: foo
- Type: STT_FUNC
- Section: .text.foo
- Size: 0x0000000000000029
- - Name: main
- Type: STT_FUNC
- Section: .text.main
- Size: 0x0000000000000029
- - Name: printf
-...
diff --git a/test/old-elf/X86_64/reloc_r_x86_64_16.test b/test/old-elf/X86_64/reloc_r_x86_64_16.test
deleted file mode 100644
index 093fbeb4f137..000000000000
--- a/test/old-elf/X86_64/reloc_r_x86_64_16.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Tests that lld can handle relocations of type R_X86_64_16
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t1.o
-#RUN: lld -flavor old-gnu -target x86_64 %t1.o --noinhibit-exec -o %t2.out -static
-#RUN: llvm-objdump -s %t2.out | FileCheck %s
-#CHECK: Contents of section .data:
-#CHECK: 401000 0210
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: '0000'
- - Name: .rela.data
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .data
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: foo
- Type: R_X86_64_16
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: bar
- Type: STT_OBJECT
- Section: .data
- Size: 0x0000000000000008
- - Name: foo
- Type: STT_OBJECT
- Section: .data
- Value: 0x0000000000000002
- Size: 0x0000000000000002
-...
diff --git a/test/old-elf/X86_64/reloc_r_x86_64_pc16.test b/test/old-elf/X86_64/reloc_r_x86_64_pc16.test
deleted file mode 100644
index c6e53ad636e8..000000000000
--- a/test/old-elf/X86_64/reloc_r_x86_64_pc16.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Tests that lld can handle relocations of type R_X86_64_PC16
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t1.o
-#RUN: lld -flavor old-gnu -target x86_64 %t1.o --noinhibit-exec -o %t2.out -static
-#RUN: llvm-objdump -s %t2.out | FileCheck %s
-#CHECK: Contents of section .data:
-#CHECK: 401000 0700
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: '0000'
- - Name: .rela.data
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .data
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: foo
- Type: R_X86_64_PC16
- Addend: 5
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: bar
- Type: STT_OBJECT
- Section: .data
- Size: 0x0000000000000008
- - Name: foo
- Type: STT_OBJECT
- Section: .data
- Value: 0x0000000000000002
- Size: 0x0000000000000002
-...
diff --git a/test/old-elf/X86_64/reloc_r_x86_64_pc64.test b/test/old-elf/X86_64/reloc_r_x86_64_pc64.test
deleted file mode 100644
index a7c5e88965c5..000000000000
--- a/test/old-elf/X86_64/reloc_r_x86_64_pc64.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Tests that lld can handle relocations of type R_X86_64_PC64
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t1.o
-#RUN: lld -flavor old-gnu -target x86_64 %t1.o --noinhibit-exec -o %t2.out -static
-#RUN: llvm-objdump -s %t2.out | FileCheck %s
-#CHECK: Contents of section .data:
-#CHECK: 401000 0a00
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: '0000'
- - Name: .rela.data
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .data
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: foo
- Type: R_X86_64_PC64
- Addend: 8
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: bar
- Type: STT_OBJECT
- Section: .data
- Size: 0x0000000000000008
- - Name: foo
- Type: STT_OBJECT
- Section: .data
- Value: 0x0000000000000002
- Size: 0x0000000000000002
-...
diff --git a/test/old-elf/X86_64/rodata.test b/test/old-elf/X86_64/rodata.test
deleted file mode 100644
index 6f85ac0423fd..000000000000
--- a/test/old-elf/X86_64/rodata.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# This tests that the ordinals for all merge atoms and defined atoms have been
-# set properly
-
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/rodata.o --noinhibit-exec \
-RUN: --merge-strings -static -o %t1
-RUN: llvm-nm -n %t1 | FileCheck %s
-
-CHECK: {{[0-9a-f]+}} R _nl_default_default_domain
-CHECK: {{[0-9a-f]+}} R _nl_default_default_dirname
diff --git a/test/old-elf/X86_64/sectionchoice.test b/test/old-elf/X86_64/sectionchoice.test
deleted file mode 100644
index 7ff838fed98d..000000000000
--- a/test/old-elf/X86_64/sectionchoice.test
+++ /dev/null
@@ -1,7 +0,0 @@
-# This tests that we are able to properly set the sectionChoice for DefinedAtoms
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/zerosizedsection.o \
-RUN: --noinhibit-exec -o %t --output-filetype=yaml
-RUN: FileCheck %s < %t
-
-CHECK-NOT: section-choice: sectionCustomRequired
-
diff --git a/test/old-elf/X86_64/sectionmap.test b/test/old-elf/X86_64/sectionmap.test
deleted file mode 100644
index 5fa04bd87051..000000000000
--- a/test/old-elf/X86_64/sectionmap.test
+++ /dev/null
@@ -1,22 +0,0 @@
-# This tests that we are able to merge the section .gcc_except_table,
-# .data.rel.local, .data.rel.ro, any other sections that belong to .data
-# into appropriate output sections
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/sectionmap.o \
-RUN: --noinhibit-exec -o %t
-RUN: llvm-readobj -sections %t | FileCheck %s -check-prefix=VERIFYSECTIONHEADERS
-
-VERIFYSECTIONHEADERS: Section {
-VERIFYSECTIONHEADERS: Name: .data
-VERIFYSECTIONHEADERS: }
-VERIFYSECTIONHEADERS: Section {
-VERIFYSECTIONHEADERS: Name: .gcc_except_table
-VERIFYSECTIONHEADERS: }
-VERIFYSECTIONHEADERS: Section {
-VERIFYSECTIONHEADERS: Name: .data.rel.local
-VERIFYSECTIONHEADERS: }
-VERIFYSECTIONHEADERS: Section {
-VERIFYSECTIONHEADERS: Name: .data.rel.ro
-VERIFYSECTIONHEADERS: }
-VERIFYSECTIONHEADERS: Section {
-VERIFYSECTIONHEADERS: Name: .bss
-VERIFYSECTIONHEADERS: }
diff --git a/test/old-elf/X86_64/startGroupEndGroup.test b/test/old-elf/X86_64/startGroupEndGroup.test
deleted file mode 100644
index e79e436a6513..000000000000
--- a/test/old-elf/X86_64/startGroupEndGroup.test
+++ /dev/null
@@ -1,48 +0,0 @@
-# This tests functionality of --start-group, --end-group
-
-# This link should fail with unresolve symbol
-RUN: not lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o \
-RUN: %p/Inputs/group/libfn.a %p/Inputs/group/libfn1.a -o x 2> %t.err
-
-# Test group
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o --start-group \
-RUN: %p/Inputs/group/libfn.a %p/Inputs/group/libfn1.a --end-group -o %t1
-
-# Mix object files in group
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o --start-group \
-RUN: %p/Inputs/group/fn.o %p/Inputs/group/fn2.o \
-RUN: %p/Inputs/group/fn1.o --end-group -o %t2
-
-# Mix Whole archive input, the group should not iterate the file libfn.a
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o --start-group \
-RUN: --whole-archive %p/Inputs/group/libfn.a --no-whole-archive \
-RUN: %p/Inputs/group/libfn1.a --end-group -o %t3
-
-# Defined symbols in a shared library.
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o --start-group \
-RUN: %p/Inputs/group/libfn2.so %p/Inputs/group/fn1.o %p/Inputs/group/fn.o \
-RUN: --end-group -o %t4
-
-# Test alias options too, as they are more widely used
-# Test group
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o '-(' \
-RUN: %p/Inputs/group/libfn.a %p/Inputs/group/libfn1.a '-)' -o %t1.alias
-
-# Mix object files in group
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o '-(' \
-RUN: %p/Inputs/group/fn.o %p/Inputs/group/fn2.o \
-RUN: %p/Inputs/group/fn1.o '-)' -o %t2.alias
-
-# Mix Whole archive input, the group should not iterate the file libfn.a
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o '-(' \
-RUN: --whole-archive %p/Inputs/group/libfn.a --no-whole-archive \
-RUN: %p/Inputs/group/libfn1.a '-)' -o %t3.alias
-
-RUN: llvm-nm %t1 | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
-RUN: llvm-nm %t2 | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
-RUN: llvm-nm %t3 | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
-RUN: llvm-nm %t1.alias | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
-RUN: llvm-nm %t2.alias | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
-RUN: llvm-nm %t3.alias | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
-
-RESOLVEDEXTERNAL: {{[0-9a-z]+}} T fn2
diff --git a/test/old-elf/X86_64/startGroupEndGroupWithDynlib.test b/test/old-elf/X86_64/startGroupEndGroupWithDynlib.test
deleted file mode 100644
index 30bfe1530f8e..000000000000
--- a/test/old-elf/X86_64/startGroupEndGroupWithDynlib.test
+++ /dev/null
@@ -1,10 +0,0 @@
-# This tests functionality of --start-group, --end-group with a dynamic library
-
-# Mix dynamic libraries/object files in group
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/group/1.o --start-group \
-RUN: %p/Inputs/group/libfn.so %p/Inputs/group/fn2.o \
-RUN: %p/Inputs/group/fn1.o --end-group -o %t1
-
-RUN: llvm-nm %t1 | FileCheck -check-prefix=RESOLVEDEXTERNAL %s
-
-RESOLVEDEXTERNAL: {{[0-9a-z]+}} T fn2
diff --git a/test/old-elf/X86_64/staticlib-search.test b/test/old-elf/X86_64/staticlib-search.test
deleted file mode 100644
index b84bd299f385..000000000000
--- a/test/old-elf/X86_64/staticlib-search.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# This tests the functionality for finding the static library libfn.a for ELF
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/main.o -L%p/Inputs/ -lfn -o %t \
-RUN: --noinhibit-exec -static -t 2> %t1
-RUN: FileCheck %s < %t1
-
-CHECK: {{[\/0-9A-Za-z_]+}}libfn.a
diff --git a/test/old-elf/X86_64/undef.test b/test/old-elf/X86_64/undef.test
deleted file mode 100644
index f948286a339b..000000000000
--- a/test/old-elf/X86_64/undef.test
+++ /dev/null
@@ -1,18 +0,0 @@
-# This tests the functionality that an undefined symbol thats defined in the
-# commmand line pulls in the required object file from the archive library
-# which is usually the usecase for it
-RUN: lld -flavor old-gnu -target x86_64 -u fn %p/Inputs/libfn.a -o %t --noinhibit-exec
-RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=SYMFROMARCHIVE %s
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/libfn.a -o %t --noinhibit-exec
-RUN: llvm-readobj -symbols %t | FileCheck %s
-
-SYMFROMARCHIVE: Symbol {
-SYMFROMARCHIVE: Name: fn ({{[0-9]+}}
-SYMFROMARCHIVE: Size: 11
-SYMFROMARCHIVE: Binding: Global (0x1)
-SYMFROMARCHIVE: Type: Function (0x2)
-SYMFROMARCHIVE: Other: 0
-SYMFROMARCHIVE: Section: .text
-SYMFROMARCHIVE: }
-
-CHECK-NOT: Name: fn
diff --git a/test/old-elf/X86_64/underscore-end.test b/test/old-elf/X86_64/underscore-end.test
deleted file mode 100644
index 4ca0c94013ea..000000000000
--- a/test/old-elf/X86_64/underscore-end.test
+++ /dev/null
@@ -1,81 +0,0 @@
-# This tests verifies that the value of _end symbol is point to the right value
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/nmagic.o \
-RUN: --noinhibit-exec -o %t --nmagic
-RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=NMAGICABSSYMBOLS %s
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/nmagic.o \
-RUN: --noinhibit-exec -o %t --omagic
-RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=OMAGICABSSYMBOLS %s
-
-NMAGICABSSYMBOLS: Symbol {
-NMAGICABSSYMBOLS: Name: __bss_start ({{[0-9]+}}
-NMAGICABSSYMBOLS: Value: 0x40100C
-NMAGICABSSYMBOLS: Size: 0
-NMAGICABSSYMBOLS: Binding: Global (0x1)
-NMAGICABSSYMBOLS: Type: Object (0x1)
-NMAGICABSSYMBOLS: Other: 0
-NMAGICABSSYMBOLS: Section: Absolute (0xFFF1)
-NMAGICABSSYMBOLS: }
-NMAGICABSSYMBOLS: Symbol {
-NMAGICABSSYMBOLS: Name: __bss_end ({{[0-9]+}}
-NMAGICABSSYMBOLS: Value: 0x40100C
-NMAGICABSSYMBOLS: Size: 0
-NMAGICABSSYMBOLS: Binding: Global (0x1)
-NMAGICABSSYMBOLS: Type: Object (0x1)
-NMAGICABSSYMBOLS: Other: 0
-NMAGICABSSYMBOLS: Section: Absolute (0xFFF1)
-NMAGICABSSYMBOLS: }
-NMAGICABSSYMBOLS: Symbol {
-NMAGICABSSYMBOLS: Name: _end ({{[0-9]+}}
-NMAGICABSSYMBOLS: Value: 0x40100C
-NMAGICABSSYMBOLS: Size: 0
-NMAGICABSSYMBOLS: Binding: Global (0x1)
-NMAGICABSSYMBOLS: Type: Object (0x1)
-NMAGICABSSYMBOLS: Other: 0
-NMAGICABSSYMBOLS: Section: Absolute (0xFFF1)
-NMAGICABSSYMBOLS: }
-NMAGICABSSYMBOLS: Symbol {
-NMAGICABSSYMBOLS: Name: end ({{[0-9]+}}
-NMAGICABSSYMBOLS: Value: 0x40100C
-NMAGICABSSYMBOLS: Size: 0
-NMAGICABSSYMBOLS: Binding: Global (0x1)
-NMAGICABSSYMBOLS: Type: Object (0x1)
-NMAGICABSSYMBOLS: Other: 0
-NMAGICABSSYMBOLS: Section: Absolute (0xFFF1)
-NMAGICABSSYMBOLS: }
-
-OMAGICABSSYMBOLS: Symbol {
-OMAGICABSSYMBOLS: Name: __bss_start ({{[0-9]+}})
-OMAGICABSSYMBOLS: Value: 0x400144
-OMAGICABSSYMBOLS: Size: 0
-OMAGICABSSYMBOLS: Binding: Global (0x1)
-OMAGICABSSYMBOLS: Type: Object (0x1)
-OMAGICABSSYMBOLS: Other: 0
-OMAGICABSSYMBOLS: Section: Absolute (0xFFF1)
-OMAGICABSSYMBOLS: }
-OMAGICABSSYMBOLS: Symbol {
-OMAGICABSSYMBOLS: Name: __bss_end ({{[0-9]+}}
-OMAGICABSSYMBOLS: Value: 0x400144
-OMAGICABSSYMBOLS: Size: 0
-OMAGICABSSYMBOLS: Binding: Global (0x1)
-OMAGICABSSYMBOLS: Type: Object (0x1)
-OMAGICABSSYMBOLS: Other: 0
-OMAGICABSSYMBOLS: Section: Absolute (0xFFF1)
-OMAGICABSSYMBOLS: }
-OMAGICABSSYMBOLS: Symbol {
-OMAGICABSSYMBOLS: Name: _end ({{[0-9]+}}
-OMAGICABSSYMBOLS: Value: 0x400144
-OMAGICABSSYMBOLS: Size: 0
-OMAGICABSSYMBOLS: Binding: Global (0x1)
-OMAGICABSSYMBOLS: Type: Object (0x1)
-OMAGICABSSYMBOLS: Other: 0
-OMAGICABSSYMBOLS: Section: Absolute (0xFFF1)
-OMAGICABSSYMBOLS: }
-OMAGICABSSYMBOLS: Symbol {
-OMAGICABSSYMBOLS: Name: end ({{[0-9]+}}
-OMAGICABSSYMBOLS: Value: 0x400144
-OMAGICABSSYMBOLS: Size: 0
-OMAGICABSSYMBOLS: Binding: Global (0x1)
-OMAGICABSSYMBOLS: Type: Object (0x1)
-OMAGICABSSYMBOLS: Other: 0
-OMAGICABSSYMBOLS: Section: Absolute (0xFFF1)
-OMAGICABSSYMBOLS: }
diff --git a/test/old-elf/X86_64/weak-override.test b/test/old-elf/X86_64/weak-override.test
deleted file mode 100644
index 25cb9d5d687f..000000000000
--- a/test/old-elf/X86_64/weak-override.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Test for weak symbol getting overridden
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/weak.o %p/Inputs/ovrd.o \
-RUN: -o %t --noinhibit-exec
-RUN: llvm-nm %t | FileCheck -check-prefix=WEAKORDER %s
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/weak.o \
-RUN: %p/Inputs/ovrd.o -o %t2 --output-filetype=yaml --noinhibit-exec
-RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2
-
-WEAKORDER: {{[0-9a-c]+}} T f
-
-WEAKATOMSORDER: references:
-WEAKATOMSORDER: - kind: layout-after
-WEAKATOMSORDER: offset: 0
-WEAKATOMSORDER: target: fn
-WEAKATOMSORDER: - name: fn
-WEAKATOMSORDER: references:
-WEAKATOMSORDER: - kind: layout-after
-WEAKATOMSORDER: offset: 0
-WEAKATOMSORDER: target: [[CONSTSTRA:[-a-zA-Z0-9_]+]]
-WEAKATOMSORDER: - ref-name: [[CONSTSTRA]]
-WEAKATOMSORDER: scope: global
-WEAKATOMSORDER: content: [ 55, 48, 89, E5, BF, 00, 00, 00, 00, E8, 00, 00,
-WEAKATOMSORDER: 00, 00, 5D, C3 ]
-WEAKATOMSORDER: references:
-WEAKATOMSORDER: - kind: layout-after
-WEAKATOMSORDER: offset: 0
-WEAKATOMSORDER: target: main
-WEAKATOMSORDER: - name: main
-WEAKATOMSORDER: scope: global
-WEAKATOMSORDER: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, E8, 00, 00,
-WEAKATOMSORDER: 00, 00, B8, 00, 00, 00, 00, 5D, C3 ]
-WEAKATOMSORDER: references:
-WEAKATOMSORDER: - kind: R_X86_64_PC32
-WEAKATOMSORDER: offset: 10
-WEAKATOMSORDER: target: f
-WEAKATOMSORDER: addend: -4
-WEAKATOMSORDER: - ref-name: {{[0-9A-Z]+}}
-WEAKATOMSORDER: references:
-WEAKATOMSORDER: - kind: layout-after
-WEAKATOMSORDER: offset: 0
-WEAKATOMSORDER: target: f
-WEAKATOMSORDER: - name: f
-WEAKATOMSORDER: scope: global
-WEAKATOMSORDER: content: [ 55, 48, 89, E5, BF, 00, 00, 00, 00, E8, 00, 00,
-WEAKATOMSORDER: 00, 00, 5D, C3 ]
diff --git a/test/old-elf/X86_64/weak-zero-sized.test b/test/old-elf/X86_64/weak-zero-sized.test
deleted file mode 100644
index 93e27a355d64..000000000000
--- a/test/old-elf/X86_64/weak-zero-sized.test
+++ /dev/null
@@ -1,26 +0,0 @@
-# Test for zero sized weak atoms, there is only a single weak atom
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/weak-zero-sized.o -o %t \
-RUN: --noinhibit-exec
-RUN: llvm-nm %t | FileCheck -check-prefix=WEAKORDER %s
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/weak-zero-sized.o \
-RUN: --output-filetype=yaml -o %t2 --noinhibit-exec
-RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2
-
-WEAKORDER: 004001a4 T _start
-
-WEAKATOMSORDER: alignment: 4
-WEAKATOMSORDER: - kind: layout-after
-WEAKATOMSORDER: offset: 0
-WEAKATOMSORDER: target: [[TARGETC:[-a-zA-Z0-9_]+]]
-WEAKATOMSORDER: - name: [[TARGETA:[-a-zA-Z0-9_]+]]
-WEAKATOMSORDER: scope: global
-WEAKATOMSORDER: merge: as-weak
-WEAKATOMSORDER: alignment: 4
-WEAKATOMSORDER: references:
-WEAKATOMSORDER: - kind: layout-after
-WEAKATOMSORDER: offset: 0
-WEAKATOMSORDER: target: [[TARGETC]]
-WEAKATOMSORDER: - ref-name: [[TARGETC]]
-WEAKATOMSORDER: scope: global
-WEAKATOMSORDER: content: [ C3 ]
-WEAKATOMSORDER: alignment: 4
diff --git a/test/old-elf/X86_64/weaksym.test b/test/old-elf/X86_64/weaksym.test
deleted file mode 100644
index 9e4f2da9bdba..000000000000
--- a/test/old-elf/X86_64/weaksym.test
+++ /dev/null
@@ -1,77 +0,0 @@
-# Tests that an executable with a weak undefine will put this symbol in the
-# dynamic symbol table if the executable has a dynamic relocation against this
-# symbol.
-
-#RUN: yaml2obj --format elf %s -o %t.o
-#RUN: lld -flavor old-gnu -target x86_64 -e main %t.o -o %t1
-#RUN: llvm-readobj -dt %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-#CHECKSYMS: Name: x@
-#CHECKSYMS-NEXT: Value: 0x0
-#CHECKSYMS-NEXT: Size: 0
-#CHECKSYMS-NEXT: Binding: Weak (0x2)
-#CHECKSYMS-NEXT: Type: None (0x0)
-#CHECKSYMS-NEXT: Other: 0
-#CHECKSYMS-NEXT: Section: Undefined (0x0)
-
-# The object file above corresponds to the following C program compiled with
-# -fPIC:
-# extern int *x __attribute__((weak));
-#
-# int main() {
-# if (x)
-# return 1;
-# return 0;
-# }
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E5488B0500000000C745FC00000000488138000000000F840C000000C745FC01000000E907000000C745FC000000008B45FC5DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000007
- Symbol: x
- Type: R_X86_64_GOTPCREL
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000037
- - Name: _GLOBAL_OFFSET_TABLE_
- Weak:
- - Name: x
diff --git a/test/old-elf/X86_64/yamlinput.test b/test/old-elf/X86_64/yamlinput.test
deleted file mode 100644
index 1c51811eec95..000000000000
--- a/test/old-elf/X86_64/yamlinput.test
+++ /dev/null
@@ -1,166 +0,0 @@
-# This tests the functionality that lld is able to read
-# an input YAML from a previous link
-
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/initfini.o \
-RUN: --noinhibit-exec --output-filetype=yaml -o %t.objtxt
-RUN: lld -flavor old-gnu -target x86_64-linux %t.objtxt \
-RUN: --noinhibit-exec -o %t1
-RUN: llvm-readobj -sections %t1 | FileCheck %s -check-prefix=SECTIONS
-
-SECTIONS: Section {
-SECTIONS: Index: 0
-SECTIONS: Name: (0)
-SECTIONS: Type: SHT_NULL (0x0)
-SECTIONS: Flags [ (0x0)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 1
-SECTIONS: Name: .interp
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x2)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 2
-SECTIONS: Name: .hash
-SECTIONS: Type: SHT_HASH (0x5)
-SECTIONS: Flags [ (0x2)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 3
-SECTIONS: Name: .dynsym
-SECTIONS: Type: SHT_DYNSYM (0xB)
-SECTIONS: Flags [ (0x2)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 4
-SECTIONS: Name: .dynstr
-SECTIONS: Type: SHT_STRTAB (0x3)
-SECTIONS: Flags [ (0x2)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 5
-SECTIONS: Name: .text
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x6)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: SHF_EXECINSTR (0x4)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 6
-SECTIONS: Name: .rodata
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x2)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 7
-SECTIONS: Name: .eh_frame
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x2)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 8
-SECTIONS: Name: .eh_frame_hdr
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 9
-SECTIONS: Name: .init_array
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x3)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: SHF_WRITE (0x1)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 10
-SECTIONS: Name: .fini_array
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x3)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: SHF_WRITE (0x1)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 11
-SECTIONS: Name: .dynamic
-SECTIONS: Type: SHT_DYNAMIC (0x6)
-SECTIONS: Flags [ (0x3)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: SHF_WRITE (0x1)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 12
-SECTIONS: Name: .got.plt
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x3)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: SHF_WRITE (0x1)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 13
-SECTIONS: Name: .data
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x3)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: SHF_WRITE (0x1)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 14
-SECTIONS: Name: .bss
-SECTIONS: Type: SHT_NOBITS (0x8)
-SECTIONS: Flags [ (0x3)
-SECTIONS: SHF_ALLOC (0x2)
-SECTIONS: SHF_WRITE (0x1)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 15
-SECTIONS: Name: .comment
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x0)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 16
-SECTIONS: Name: .note.GNU-stack
-SECTIONS: Type: SHT_PROGBITS (0x1)
-SECTIONS: Flags [ (0x0)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 17
-SECTIONS: Name: .shstrtab
-SECTIONS: Type: SHT_STRTAB (0x3)
-SECTIONS: Flags [ (0x0)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 18
-SECTIONS: Name: .symtab
-SECTIONS: Type: SHT_SYMTAB (0x2)
-SECTIONS: Flags [ (0x0)
-SECTIONS: ]
-SECTIONS: }
-SECTIONS: Section {
-SECTIONS: Index: 19
-SECTIONS: Name: .strtab
-SECTIONS: Type: SHT_STRTAB (0x3)
-SECTIONS: Flags [ (0x0)
-SECTIONS: ]
-SECTIONS: }
diff --git a/test/old-elf/abs-dup.objtxt b/test/old-elf/abs-dup.objtxt
deleted file mode 100644
index c662c9b44b4a..000000000000
--- a/test/old-elf/abs-dup.objtxt
+++ /dev/null
@@ -1,19 +0,0 @@
-# Tests handling an absolute symbol with no name
-# RUN: lld -flavor old-gnu -target x86_64 -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-absolute-atoms:
- - name: abs
- scope: static
- value: 0x10
- - name: ''
- scope: static
- value: 0x15
-
-# CHECK: absolute-atoms:
-# CHECK: - name: abs
-# CHECK: scope: static
-# CHECK: value: 0x0000000000000010
-# CHECK: - name: ''
-# CHECK: scope: static
-# CHECK: value: 0x0000000000000015
diff --git a/test/old-elf/abs.test b/test/old-elf/abs.test
deleted file mode 100644
index f542582bfa85..000000000000
--- a/test/old-elf/abs.test
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Source File:
-# .local absGlobalSymbol
-# .set absLocalSymbol,0xC0000
-# .type absLocalSymbol, @object
-# .globl absGlobalSymbol
-# .set absGlobalSymbol,0xD0000
-# .type absGlobalSymbol, @object
-
-# built using: "gcc -m32"
-#
-RUN: lld -flavor old-gnu -target i386 --output-filetype=yaml -r %p/Inputs/abs-test.i386 | FileCheck -check-prefix=YAML %s
-
-YAML: absolute-atoms:
-YAML: - name: absLocalSymbol
-YAML: value: {{0x[0]+C0000}}
-YAML: - name: absGlobalSymbol
-YAML: scope: global
-YAML: value: {{0x[0]+D0000}}
diff --git a/test/old-elf/allowduplicates.objtxt b/test/old-elf/allowduplicates.objtxt
deleted file mode 100644
index b2f263148b60..000000000000
--- a/test/old-elf/allowduplicates.objtxt
+++ /dev/null
@@ -1,41 +0,0 @@
-# RUN: lld -flavor old-gnu -target x86_64 --allow-multiple-definition %s \
-# RUN: %p/Inputs/allowduplicates.objtxt \
-# RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s
-#
-# RUN: not lld -flavor old-gnu -target x86_64 %s %p/Inputs/allowduplicates.objtxt \
-# RUN: --output-filetype=yaml \
-# RUN: --noinhibit-exec 2>&1 | FileCheck -check-prefix=ERROR %s
-#
-# RUN: lld -flavor old-gnu -target x86_64 -z muldefs %s \
-# RUN: %p/Inputs/allowduplicates.objtxt \
-# RUN: --noinhibit-exec --output-filetype=yaml | FileCheck %s
-
----
-defined-atoms:
- - name: .text
- alignment: 16
- section-choice: custom-required
- section-name: .text
- - name: main
- scope: global
- content: [ B8, 00, 00, 00, 00, C7, 44, 24, FC, 00, 00, 00,
- 00, C3 ]
- alignment: 16
- section-choice: custom-required
- section-name: .text
----
-
-# CHECK: defined-atoms:
-# CHECK: - name: .text
-# CHECK: alignment: 16
-# CHECK: section-choice: custom-required
-# CHECK: section-name: .text
-# CHECK: - name: main
-# CHECK: scope: global
-# CHECK: content: [ B8, 00, 00, 00, 00, C7, 44, 24, FC, 00, 00, 00,
-# CHECK: 00, C3 ]
-# CHECK: alignment: 16
-# CHECK: section-choice: custom-required
-# CHECK: section-name: .text
-
-# ERROR: duplicate symbol error
diff --git a/test/old-elf/archive-elf-forceload.test b/test/old-elf/archive-elf-forceload.test
deleted file mode 100644
index db5ba6cdfaa2..000000000000
--- a/test/old-elf/archive-elf-forceload.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# Tests the functionality of archive libraries reading
-# and resolution
-# Note: The binary files would not be required once we have support to generate
-# binary archives from textual(yaml) input
-#
-# Tests generated using the source files below
-# main file
-# int main()
-# {
-# fn();
-# return 0;
-# }
-#
-# archive file
-# int fn()
-# {
-# return 0;
-# }
-#
-# int fn1()
-# {
-# return 0;
-# }
-# gcc -c main.c fn.c fn1.c
-
-RUN: lld -flavor old-gnu -target x86_64-linux -e main %p/Inputs/mainobj.x86_64 \
-RUN: --whole-archive %p/Inputs/libfnarchive.a --no-whole-archive --output-filetype=yaml \
-RUN: | FileCheck -check-prefix FORCELOAD %s
-
-FORCELOAD: defined-atoms:
-FORCELOAD: - name: fn1
-FORCELOAD: scope: global
-FORCELOAD: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
-FORCELOAD: - name: fn
-FORCELOAD: scope: global
-FORCELOAD: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
-FORCELOAD: absolute-atoms:
-FORCELOAD: - name: main.c
-FORCELOAD: value: 0x0
-FORCELOAD: - name: fn1.c
-FORCELOAD: value: 0x0
-FORCELOAD: - name: fn.c
-FORCELOAD: value: 0x0
diff --git a/test/old-elf/archive-elf.test b/test/old-elf/archive-elf.test
deleted file mode 100644
index 7784eb9279dc..000000000000
--- a/test/old-elf/archive-elf.test
+++ /dev/null
@@ -1,38 +0,0 @@
-# Tests the functionality of archive libraries reading
-# and resolution
-# Note: The binary files would not be required once we have support to generate
-# binary archives from textual(yaml) input
-#
-# Tests generated using the source files below
-# main file
-# int main()
-# {
-# fn();
-# return 0;
-# }
-#
-# archive file
-# int fn()
-# {
-# return 0;
-# }
-#
-# int fn1()
-# {
-# return 0;
-# }
-# gcc -c main.c fn.c fn1.c
-
-RUN: lld -flavor old-gnu -target x86_64-linux --output-filetype=yaml -r \
-RUN: %p/Inputs/mainobj.x86_64 %p/Inputs/libfnarchive.a | \
-RUN: FileCheck -check-prefix NOFORCELOAD %s
-
-NOFORCELOAD: defined-atoms:
-NOFORCELOAD: - name: fn
-NOFORCELOAD: scope: global
-NOFORCELOAD: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ]
-NOFORCELOAD: absolute-atoms:
-NOFORCELOAD: - name: main.c
-NOFORCELOAD: value: 0x0
-NOFORCELOAD: - name: fn.c
-NOFORCELOAD: value: 0x0
diff --git a/test/old-elf/as-needed.test b/test/old-elf/as-needed.test
deleted file mode 100644
index bcebfbac2f24..000000000000
--- a/test/old-elf/as-needed.test
+++ /dev/null
@@ -1,15 +0,0 @@
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
-RUN: --as-needed %p/Inputs/shared.so-x86-64 %p/Inputs/libifunc.x86-64.so \
-RUN: -o %t1 -e main --allow-shlib-undefined
-RUN: llvm-readobj -dynamic-table %t1 | FileCheck %s -check-prefix AS_NEEDED
-
-AS_NEEDED: NEEDED SharedLibrary (shared.so-x86-64)
-AS_NEEDED-NOT: NEEDED SharedLibrary (libifunc.x86-64.so)
-
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 %p/Inputs/libifunc.x86-64.so \
-RUN: -o %t2 -e main --allow-shlib-undefined
-RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s -check-prefix NO_AS_NEEDED
-
-NO_AS_NEEDED: NEEDED SharedLibrary (shared.so-x86-64)
-NO_AS_NEEDED: NEEDED SharedLibrary (libifunc.x86-64.so)
diff --git a/test/old-elf/branch.test b/test/old-elf/branch.test
deleted file mode 100644
index 116fd0f07c5e..000000000000
--- a/test/old-elf/branch.test
+++ /dev/null
@@ -1,34 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon -static --output-filetype=yaml \
-RUN: %p/Inputs/branch-test.hexagon %p/Inputs/target-test.hexagon --noinhibit-exec | FileCheck %s -check-prefix hexagon-yaml
-RUN: lld -flavor old-gnu -target hexagon -e target -o %t1 \
-RUN: %p/Inputs/branch-test.hexagon %p/Inputs/target-test.hexagon --noinhibit-exec
-RUN: llvm-readobj -h %t1 | FileCheck -check-prefix=hexagon-readobj %s
-
-hexagon-yaml: - name: back
-hexagon-yaml: scope: global
-hexagon-yaml: content: [ 00, C0, 00, 7F, 00, C0, 00, 5A, 00, 00, 00, 00,
-hexagon-yaml: 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 ]
-hexagon-yaml: references:
-hexagon-yaml: - kind:
-hexagon-yaml: offset: 4
-hexagon-yaml: target: target
-
-hexagon-yaml: - name: target
-hexagon-yaml: scope: global
-hexagon-yaml: content: [ 00, C0, 00, 5A ]
-hexagon-yaml: references:
-hexagon-yaml: - kind:
-hexagon-yaml: offset: 0
-hexagon-yaml: target: back
-
-
-hexagon-readobj: ElfHeader {
-hexagon-readobj: Ident {
-hexagon-readobj: Class: 32-bit (0x1)
-hexagon-readobj: DataEncoding: LittleEndian (0x1)
-hexagon-readobj: FileVersion: 1
-hexagon-readobj: OS/ABI: SystemV (0x0)
-hexagon-readobj: ABIVersion: 0
-hexagon-readobj: }
-hexagon-readobj: Type: Executable (0x2)
-hexagon-readobj: Machine: EM_HEXAGON (0xA4)
diff --git a/test/old-elf/check.test b/test/old-elf/check.test
deleted file mode 100644
index 3fc11728e12d..000000000000
--- a/test/old-elf/check.test
+++ /dev/null
@@ -1,39 +0,0 @@
-# This tests the basic functionality of ordering data and functions as they
-# appear in the inputs
-RUN: lld -flavor old-gnu -target i386 -e global_func --noinhibit-exec --output-filetype=yaml \
-RUN: %p/Inputs/object-test.elf-i386 -o %t
-RUN: FileCheck %s -check-prefix ELF-i386 < %t
-RUN: lld -flavor old-gnu -target hexagon -e global_func --noinhibit-exec --output-filetype=yaml \
-RUN: %p/Inputs/object-test.elf-hexagon -o %t1
-RUN: FileCheck %s -check-prefix ELF-hexagon < %t1
-
-ELF-i386: defined-atoms:
-ELF-i386: - name: global_func
-ELF-i386: - name: static_func
-ELF-i386: - name: weak_func
-ELF-i386: - name: hidden_func
-ELF-i386: - name: no_dead_strip
-ELF-i386: - name: no_special_section_func
-ELF-i386: - name: global_variable
-ELF-i386: - name: uninitialized_static_variable
-ELF-i386: - name: special_section_func
-ELF-i386: undefined-atoms:
-ELF-i386: - name: puts
-ELF-i386: absolute-atoms:
-ELF-i386: - name: sample.c
-
-ELF-hexagon: - name: global_func
-ELF-hexagon: - name: static_func
-ELF-hexagon: - name: weak_func
-ELF-hexagon: - name: hidden_func
-ELF-hexagon: - name: no_dead_strip
-ELF-hexagon: - name: no_special_section_func
-ELF-hexagon: - name: global_variable
-ELF-hexagon: - name: uninitialized_static_variable
-ELF-hexagon: - name: special_section_func
-ELF-hexagon: undefined-atoms:
-ELF-hexagon: - name: puts
-ELF-hexagon: absolute-atoms:
-ELF-hexagon: - name: sample.c
-ELF-hexagon: scope: static
-ELF-hexagon: value: 0x0000000000000000
diff --git a/test/old-elf/checkrodata.test b/test/old-elf/checkrodata.test
deleted file mode 100644
index 71304a443b8b..000000000000
--- a/test/old-elf/checkrodata.test
+++ /dev/null
@@ -1,9 +0,0 @@
-
-RUN: lld -flavor old-gnu -target i386 -o %t1 %p/Inputs/rodata-test.i386 --noinhibit-exec
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=i386 %s
-RUN: lld -flavor old-gnu -target hexagon -o %t2 %p/Inputs/rodata-test.hexagon --noinhibit-exec
-RUN: llvm-objdump -section-headers %t2 | FileCheck -check-prefix=hexagon %s
-
-i386: .rodata 00000004 0000000000000114 DATA
-
-hexagon: .rodata 00000004 0000000000000114 DATA
diff --git a/test/old-elf/common.test b/test/old-elf/common.test
deleted file mode 100644
index e337ac399140..000000000000
--- a/test/old-elf/common.test
+++ /dev/null
@@ -1,10 +0,0 @@
-RUN: lld -flavor old-gnu -target x86_64-linux -o %t %p/Inputs/relocs.x86-64 \
-RUN: -e _start -static
-RUN: llvm-readobj -t %t | FileCheck %s
-
-CHECK: Symbol {
-CHECK: Name: i
-CHECK-NEXT: Value:
-CHECK-NEXT: Size:
-CHECK-NEXT: Binding:
-CHECK-NEXT: Type: Object
diff --git a/test/old-elf/consecutive-weak-sym-defs.test b/test/old-elf/consecutive-weak-sym-defs.test
deleted file mode 100644
index 0120aa126551..000000000000
--- a/test/old-elf/consecutive-weak-sym-defs.test
+++ /dev/null
@@ -1,81 +0,0 @@
-#Tests that multiple consecutive weak symbol definitions do not confuse the
-#ELF reader. For example:
-#
-# my_weak_func1:
-# my_weak_func2:
-# my_weak_func3:
-# code
-#
-#If my_weak_func2 is merged to other definition, this should not disturb the
-#definition my_weak_func1 to "code".
-#
-#
-#RUN: yaml2obj -format=elf %p/Inputs/consecutive-weak-defs.o.yaml -o=%t1.o
-#RUN: yaml2obj -format=elf %p/Inputs/main-with-global-def.o.yaml -o=%t2.o
-#RUN: lld -flavor old-gnu -target x86_64 %t1.o %t2.o -e=main -o %t1
-#RUN: obj2yaml %t1 | FileCheck -check-prefix CHECKLAYOUT %s
-#
-# Check that the layout has not been changed:
-#
-#CHECKLAYOUT: Name: .text
-#CHECKLAYOUT-NEXT: Type:
-#CHECKLAYOUT-NEXT: Flags:
-#CHECKLAYOUT-NEXT: Address:
-#CHECKLAYOUT-NEXT: AddressAlign:
-#CHECKLAYOUT-NEXT: Content: 554889E5E8020000005DC3554889E5B8640000005DC3
-# ^~~> my_func ^~~> my_weak_func
-#
-#
-#
-#Our two input files were produced by the following code:
-#
-#Inputs/consecutive-weak-defs.o.yaml (this one is in assembly to allow us to
-# easily define multiple labels)
-#
-# .text
-# .globl my_func
-# .type my_func,@function
-# my_func:
-# pushq %rbp
-# movq %rsp, %rbp
-# callq my_weak_func
-# popq %rbp
-# retq
-# .Ltmp0:
-# .size my_func, .Ltmp0-my_func
-#
-# .text
-# .weak my_weak_func
-# .type my_weak_func,@function
-# .weak my_weak_func2
-# .type my_weak_func2,@function
-# .weak my_weak_func3
-# .type my_weak_func3,@function
-# my_weak_func:
-# my_weak_func2:
-# my_weak_func3:
-# pushq %rbp
-# movq %rsp, %rbp
-# movl $100, %eax
-# popq %rbp
-# retq
-# .Ltmp1:
-# .size my_weak_func, .Ltmp1-my_weak_func
-# .size my_weak_func2, .Ltmp1-my_weak_func2
-# .size my_weak_func3, .Ltmp1-my_weak_func3
-#
-#Inputs/main-with-global-def.o.yaml:
-#
-# int my_func();
-#
-# int my_weak_func2() {
-# return 200;
-# }
-#
-# int main() {
-# return my_func();
-# }
-#
-#-------------------------------------------------------------------------------
-# The net effect is that this program should return 100.
-
diff --git a/test/old-elf/defsym.objtxt b/test/old-elf/defsym.objtxt
deleted file mode 100644
index 7fdc20d4dd93..000000000000
--- a/test/old-elf/defsym.objtxt
+++ /dev/null
@@ -1,31 +0,0 @@
-# RUN: lld -flavor old-gnu -target x86_64 --defsym=foo=0x1234 -r %s \
-# RUN: --output-filetype=yaml | FileCheck -check-prefix=ABS %s
-
-# RUN: lld -flavor old-gnu -target x86_64 --defsym=foo=main -r %s \
-# RUN: --output-filetype=yaml | FileCheck -check-prefix=ALIAS %s
-
-# RUN: lld -flavor old-gnu -target x86_64 --defsym foo=main -r %s \
-# RUN: --output-filetype=yaml | FileCheck -check-prefix=ALIAS %s
-
-defined-atoms:
- - name: main
- scope: global
- content: [ B8, 00, 00, 00, 00, C7, 44, 24, FC, 00, 00, 00, 00, C3 ]
- alignment: 16
- section-choice: custom-required
- section-name: .text
-
-# ABS: absolute-atoms:
-# ABS: - name: foo
-# ABS: scope: global
-# ABS: value: 0x0000000000001234
-
-# ALIAS: defined-atoms:
-# ALIAS: - name: foo
-# ALIAS: scope: global
-# ALIAS: section-choice: custom-required
-# ALIAS: section-name: .text
-# ALIAS: references:
-# ALIAS: - kind: layout-after
-# ALIAS: offset: 0
-# ALIAS: target: main
diff --git a/test/old-elf/discard-all.test b/test/old-elf/discard-all.test
deleted file mode 100644
index 7fca435008ab..000000000000
--- a/test/old-elf/discard-all.test
+++ /dev/null
@@ -1,88 +0,0 @@
-# Test that -x/--discard all works.
-#
-#RUN: yaml2obj -format=elf %s -o=%t.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.o -e=main -x -o %t1
-#RUN: llvm-objdump -t %t1 | FileCheck %s
-
-#CHECK-NOT: 0000000000400210 l F .text 00000009 local
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_FREEBSD
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E54883EC10C745FC00000000E81C000000B9000000008945F889C84883C4105DC36666662E0F1F840000000000554889E58B45FC5DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 004672656542534420636C616E672076657273696F6E20332E342E312028746167732F52454C454153455F33342F646F74312D66696E616C203230383033322920323031343035313200
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000017A5200017810011B0C070890010000180000001C000000000000002400000000410E108602430D060000001800000038000000000000000900000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 48
-Symbols:
- Local:
- - Name: local
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000030
- Size: 0x0000000000000009
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000024
-...
diff --git a/test/old-elf/discard-locals.test b/test/old-elf/discard-locals.test
deleted file mode 100644
index d1a0918949ad..000000000000
--- a/test/old-elf/discard-locals.test
+++ /dev/null
@@ -1,65 +0,0 @@
-# Test that -X/--discard-locals works.
-#
-#RUN: yaml2obj -format=elf %s -o=%t.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.o -shared -X -o %t1
-#RUN: llvm-objdump -t %t1 | FileCheck %s
-
-#CHECK-NOT: 0000000000400121 l .rodata 00000000 .Lsym8
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_FREEBSD
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 00000000F20F100D00000000C3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .rodata.str1.1
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000008
- Symbol: .Lsym8
- Type: R_X86_64_PC32
- Addend: -4
-Symbols:
- Local:
- - Name: .Lsym8
- Section: .rodata.str1.1
- - Name: test
- Section: .text
- Value: 0x000000000000000C
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .rodata.str1.1
- Type: STT_SECTION
- Section: .rodata.str1.1
-...
diff --git a/test/old-elf/dynamic-segorder.test b/test/old-elf/dynamic-segorder.test
deleted file mode 100644
index e9143d83f0f6..000000000000
--- a/test/old-elf/dynamic-segorder.test
+++ /dev/null
@@ -1,17 +0,0 @@
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined \
-RUN: --defsym=__tls_get_addr=0
-RUN: llvm-objdump -p %t | FileCheck %s
-
-CHECK: PHDR
-CHECK: flags r-x
-CHECK: INTERP
-CHECK: flags r--
-CHECK: LOAD
-CHECK: flags r-x
-CHECK: LOAD
-CHECK: flags rw-
-CHECK: DYNAMIC
-CHECK: flags rw-
-CHECK: TLS
-CHECK: flags rw-
diff --git a/test/old-elf/dynamic-undef.test b/test/old-elf/dynamic-undef.test
deleted file mode 100644
index fc661684b19b..000000000000
--- a/test/old-elf/dynamic-undef.test
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# This test creates a executable and tests the options that are used to
-# to create an executable and a shared library
-#
-# This test will fail because there are unresolved symbols from the shared
-# library and we are passing --no-allow-shlib-undefined
-RUN: not lld -flavor old-gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 -o %t -e main --no-allow-shlib-undefined 2> %t1
-RUN: FileCheck -check-prefix=EXEC %s < %t1
-# This test will pass because of --allow-shlib-undefined
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined \
-RUN: --defsym=__tls_get_addr=0
-# This test will pass becase --allow-shlib-undefined is the default.
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 -o %t -e main \
-RUN: --defsym=__tls_get_addr=0
-# Building shared libraries should not fail when there is a undefined symbol.
-# Test creation of shared library, this should pass because we are using
-# shared option and by default, dynamic library wouldn't create undefined atoms
-# from the input shared library
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 -o %t.usenoundefines -e main -shared
-RUN: llvm-readobj -symbols %t.usenoundefines | FileCheck %s -check-prefix=SHLIB-NOUNDEF
-# Test creation of shared library, this should fail because we are using
-# shared option setting the options to use the shared library undefines to
-# create undefined atoms from the input shared library
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 -o %t.useundefines -e main -shared \
-RUN: --use-shlib-undefines --no-allow-shlib-undefined 2> %t2
-RUN: llvm-readobj -symbols %t.useundefines | FileCheck -check-prefix=SHLIB-UNDEF-SYMBOLS %s
-
-EXEC: Undefined symbol: {{.+[\\/]}}shared.so-x86-64: puts
-SHLIB: Undefined symbol: {{.+[\\/]}}shared.so-x86-64: puts
-EXEC-NOT: Undefined symbol: {{.+[\\/]}}shared.so-x86-64: weakfoo
-SHLIB-NOT: Undefined symbol: {{.+[\\/]}}shared.so-x86-64: weakfoo
-SHLIB-NOUNDEF-NOT: Name: puts
-SHLIB-UNDEF-SYMBOLS: Name: puts
diff --git a/test/old-elf/dynamic.test b/test/old-elf/dynamic.test
deleted file mode 100644
index 2b548a7aaf5e..000000000000
--- a/test/old-elf/dynamic.test
+++ /dev/null
@@ -1,80 +0,0 @@
-# Checks functionality of dynamic executables
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined \
-RUN: -rpath /l1:/l2 -rpath /l3
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 --output-filetype=yaml -o %t2 --allow-shlib-undefined \
-RUN: --noinhibit-exec
-RUN: llvm-objdump -p %t >> %t2
-RUN: llvm-readobj -s -dyn-symbols -dynamic-table %t >> %t2
-RUN: FileCheck %s < %t2
-
-CHECK: name: main
-CHECK: kind: R_X86_64_PC32
-CHECK: offset: 18
-CHECK: target: [[PLTNAME:[-a-zA-Z0-9_]+]]
-
-CHECK: name: [[PLTNAME]]
-CHECK: type: stub
-
-CHECK: type: got
-CHECK: references:
-CHECK: kind: R_X86_64_JUMP_SLOT
-
-CHECK: shared-library-atoms:
-CHECK: name: foo
-CHECK: load-name: shared.so-x86-64
-
-CHECK: PHDR off 0x{{0+}}40
-CHECK: INTERP
-CHECK: flags r--
-
-CHECK: Section {
-CHECK: Name: .hash
-CHECK-NEXT: Type: SHT_HASH
-CHECK-NEXT: Flags [
-CHECK-NEXT: SHF_ALLOC
-CHECK-NEXT: ]
-CHECK-NEXT: Address:
-CHECK-NEXT: Offset:
-CHECK-NEXT: Size: 32
-CHECK-NEXT: Link:
-CHECK-NEXT: Info:
-CHECK-NEXT: AddressAlignment: 8
-CHECK-NEXT: EntrySize:
-CHECK-NEXT: }
-
-CHECK: DynamicSymbols [
-CHECK: Symbol {
-CHECK: Name: foo
-CHECK-NEXT: Value: 0
-CHECK-NEXT: Size:
-CHECK-NEXT: Binding: Global
-CHECK-NEXT: Type: Function
-CHECK: }
-CHECK: Symbol {
-CHECK: Name: i
-CHECK-NEXT: Value: 0
-CHECK-NEXT: Size:
-CHECK-NEXT: Binding: Global
-CHECK-NEXT: Type: Object
-CHECK: }
-
-CHECK: DynamicSection [ (15 entries)
-CHECK: Tag Type Name/Value
-CHECK: 0x0000000000000004 HASH
-CHECK: 0x0000000000000005 STRTAB
-CHECK: 0x0000000000000006 SYMTAB
-CHECK: 0x000000000000000A STRSZ
-CHECK: 0x000000000000000B SYMENT 24
-CHECK: 0x0000000000000007 RELA
-CHECK: 0x0000000000000008 RELASZ 24
-CHECK: 0x0000000000000009 RELAENT 24
-CHECK: 0x0000000000000002 PLTRELSZ 24
-CHECK: 0x0000000000000003 PLTGOT
-CHECK: 0x0000000000000014 PLTREL RELA
-CHECK: 0x0000000000000017 JMPREL
-CHECK: 0x0000000000000001 NEEDED SharedLibrary (shared.so-x86-64)
-CHECK: 0x000000000000000F RPATH /l1:/l2:/l3
-CHECK: 0x0000000000000000 NULL 0x0
-CHECK: ]
diff --git a/test/old-elf/eh_frame_hdr.test b/test/old-elf/eh_frame_hdr.test
deleted file mode 100644
index 74383b8dbc5b..000000000000
--- a/test/old-elf/eh_frame_hdr.test
+++ /dev/null
@@ -1,30 +0,0 @@
-#RUN: yaml2obj -format=elf %s > %t
-#RUN: lld -flavor old-gnu -target x86_64-linux %t --noinhibit-exec \
-#RUN: -o %t1
-#RUN: llvm-objdump -s %t1 | FileCheck %s
-
-!ELF
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-
-Sections:
-- Name: .eh_frame
- Type: SHT_PROGBITS
- Content: "00"
- AddressAlign: 8
- Flags: [SHF_ALLOC]
-
-Symbols:
- Local:
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
-
-# CHECK: Contents of section .eh_frame:
-# CHECK-NEXT: 4001e0 00
-# CHECK-NEXT: Contents of section .eh_frame_hdr:
-# CHECK-NEXT: 4001e8 011bffff f4ffffff
-# ^ 0x4001e0 - 0x4001e8 - 4 = 0xfffffff4
diff --git a/test/old-elf/entry.objtxt b/test/old-elf/entry.objtxt
deleted file mode 100644
index 6590d139c417..000000000000
--- a/test/old-elf/entry.objtxt
+++ /dev/null
@@ -1,58 +0,0 @@
-# Tests entry point handling
-#
-# Test generated using the source file below:
-#
-# int main()
-# {
-# return 0;
-# }
-#
-
-# RUN: lld -flavor old-gnu -target x86_64 %s -e _entrypoint --noinhibit-exec -o %t1
-# RUN: llvm-nm -n %t1 | FileCheck %s
-#
-# CHECK: U _entrypoint
-# CHECK: 004001e0 T main
-# CHECK: 00401000 D _DYNAMIC
-# CHECK: 00401060 A _end
-# CHECK: 00401060 A end
-
-defined-atoms:
- - name: .text
- alignment: 16
- section-choice: custom-required
- section-name: .text
- - name: main
- scope: global
- content: [ B8, 00, 00, 00, 00, C7, 44, 24, FC, 00, 00, 00,
- 00, C3 ]
- alignment: 16
- section-choice: custom-required
- section-name: .text
- - name: .data
- type: data
- alignment: 4
- section-choice: custom-required
- section-name: .data
- - name: .bss
- type: zero-fill
- alignment: 4
- section-choice: custom-required
- section-name: .bss
- - name: .note.GNU-stack
- section-choice: custom-required
- section-name: .note.GNU-stack
- permissions: r--
- - name: .eh_frame
- content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
- 01, 78, 10, 01, 1B, 0C, 07, 08, 90, 01, 00, 00,
- 14, 00, 00, 00, 1C, 00, 00, 00, 00, 00, 00, 00,
- 0E, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 ]
- alignment: 8
- section-choice: custom-required
- section-name: .eh_frame
- permissions: r--
- references:
- - kind: R_X86_64_PC32
- offset: 32
- target: .text
diff --git a/test/old-elf/export-dynamic.test b/test/old-elf/export-dynamic.test
deleted file mode 100644
index b88961597ea0..000000000000
--- a/test/old-elf/export-dynamic.test
+++ /dev/null
@@ -1,98 +0,0 @@
-# Tests the --export-dynamic (-E) flag. When creating a dynamic executable and
-# receiving this flag, the linker should export all globally visible symbols in
-# its dynamic symbol table.
-
-#RUN: yaml2obj -format=elf %s -o=%t.o
-#RUN: lld -flavor old-gnu -target x86_64 -E %t.o -e=main -o %t1
-#RUN: llvm-readobj -dt %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-#CHECKSYMS: myfunc1@
-#CHECKSYMS: main@
-#CHECKSYMS: myvar1@
-
-# The object file below was generated with the following code:
-#
-# (command line clang -c prog.c -o prog.o)
-#
-# int myvar1 = 22;
-#
-# static int mysecretvar = 11;
-#
-# int myfunc1() {
-# return 23;
-# }
-#
-# static int mysecretfunc() {
-# return 42;
-# }
-#
-# int main() {
-# return mysecretfunc() + mysecretvar;
-# }
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E5B8170000005DC30F1F440000554889E54883EC10C745FC00000000E81C000000030425000000004883C4105DC36666666666662E0F1F840000000000554889E5B82A0000005DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000027
- Symbol: .data
- Type: R_X86_64_32S
- Addend: 4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: 160000000B000000
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: mysecretfunc
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000040
- Size: 0x000000000000000B
- - Name: mysecretvar
- Type: STT_OBJECT
- Section: .data
- Value: 0x0000000000000004
- Size: 0x0000000000000004
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000010
- Size: 0x0000000000000021
- - Name: myfunc1
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000000B
- - Name: myvar1
- Type: STT_OBJECT
- Section: .data
- Size: 0x0000000000000004
diff --git a/test/old-elf/filenotfound.test b/test/old-elf/filenotfound.test
deleted file mode 100644
index 5020e9cf9b74..000000000000
--- a/test/old-elf/filenotfound.test
+++ /dev/null
@@ -1,3 +0,0 @@
-# Check that a file that cannot be found results in a proper error message
-RUN: not lld -flavor old-gnu -target x86_64 %p/Inputs/nofile.o 2>&1 | FileCheck %s
-#CHECK: lld: cannot find file {{.+[\\/]}}nofile.o
diff --git a/test/old-elf/gnulinkonce/gnulinkonce-report-discarded-reference.test b/test/old-elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
deleted file mode 100644
index c05a06fab32b..000000000000
--- a/test/old-elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
+++ /dev/null
@@ -1,145 +0,0 @@
-# Tests that the linker is able to read .gnu.linkonce sections and link them
-# appropriately. The testcase has been created by using the following source
-# code.
-# TODO: This test should produce a discarded reference error message which it
-# does not currently.
-# linkoncea.s
-# .section .gnu.linkonce.d.dummy,"aw"
-#bar:
-# .long 0
-# linkonceb.s
-# .section .gnu.linkonce.d.dummy,"aw"
-#foo:
-# .long 0
-# .section .blah, "aw"
-# .long foo
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
-#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor old-gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
-#RUN: --noinhibit-exec -o %t2.out
-#RUN: FileCheck %s -check-prefix=CHECKGNULINKONCE < %t2.out.yaml
-#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGNULINKONCESECTIONS
-#CHECKGNULINKONCE: - name: .gnu.linkonce.d.dummy
-#CHECKGNULINKONCE: scope: global
-#CHECKGNULINKONCE: type: gnu-linkonce
-#CHECKGNULINKONCE: section-choice: custom-required
-#CHECKGNULINKONCE: section-name: .gnu.linkonce.d.dummy
-#CHECKGNULINKONCE: permissions: rw-
-#CHECKGNULINKONCE: references:
-#CHECKGNULINKONCE: - kind: group-child
-#CHECKGNULINKONCE: offset: 0
-#CHECKGNULINKONCE: target: bar
-#CHECKGNULINKONCESECTIONS: Section {
-#CHECKGNULINKONCESECTIONS: Name: .gnu.linkonce.d.dummy
-#CHECKGNULINKONCESECTIONS: Type: SHT_PROGBITS
-#CHECKGNULINKONCESECTIONS: Flags [ (0x3)
-#CHECKGNULINKONCESECTIONS: SHF_ALLOC (0x2)
-#CHECKGNULINKONCESECTIONS: SHF_WRITE (0x1)
-#CHECKGNULINKONCESECTIONS: ]
-#CHECKGNULINKONCESECTIONS: Size: 4
-#CHECKGNULINKONCESECTIONS: }
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .gnu.linkonce.d.dummy
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: '00000000'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .gnu.linkonce.d.dummy
- Type: STT_SECTION
- Section: .gnu.linkonce.d.dummy
- - Name: bar
- Section: .gnu.linkonce.d.dummy
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .gnu.linkonce.d.dummy
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: '00000000'
- - Name: .blah
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: '00000000'
- - Name: .rela.blah
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .blah
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: foo
- Type: R_X86_64_32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .gnu.linkonce.d.dummy
- Type: STT_SECTION
- Section: .gnu.linkonce.d.dummy
- - Name: foo
- Section: .gnu.linkonce.d.dummy
- - Name: .blah
- Type: STT_SECTION
- Section: .blah
-...
diff --git a/test/old-elf/gnulinkonce/gnulinkonce-report-undef.test b/test/old-elf/gnulinkonce/gnulinkonce-report-undef.test
deleted file mode 100644
index f91123f0efad..000000000000
--- a/test/old-elf/gnulinkonce/gnulinkonce-report-undef.test
+++ /dev/null
@@ -1,127 +0,0 @@
-# Tests that the linker is able to read .gnu.linkonce sections and link them
-# appropriately. The testcase has been created by using the following source
-# code. This test checks that the linker produces an undefined error.
-# linkoncea.s
-# .section .gnu.linkonce.d.dummy,"aw"
-#bar:
-# .long 0
-# linkonceb.s
-# .section .gnu.linkonce.d.dummy,"aw"
-# .global foo
-#foo:
-# .long 0
-# .section .blah, "aw"
-# .long foo
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o
-#RUN: not lld -flavor old-gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
-#RUN: --output-filetype=yaml -o %t2.out.yaml 2>&1 | FileCheck \
-#RUN: -check-prefix=UNDEFS %s
-#RUN: not lld -flavor old-gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
-#RUN: -o %t2.out 2>&1 | FileCheck -check-prefix=UNDEFS %s
-#UNDEFS: Undefined symbol: {{.*}} foo
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .gnu.linkonce.d.dummy
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: '00000000'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .gnu.linkonce.d.dummy
- Type: STT_SECTION
- Section: .gnu.linkonce.d.dummy
- - Name: bar
- Section: .gnu.linkonce.d.dummy
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .gnu.linkonce.d.dummy
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: '00000000'
- - Name: .blah
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: '00000000'
- - Name: .rela.blah
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .blah
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: foo
- Type: R_X86_64_32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .gnu.linkonce.d.dummy
- Type: STT_SECTION
- Section: .gnu.linkonce.d.dummy
- - Name: .blah
- Type: STT_SECTION
- Section: .blah
- Global:
- - Name: foo
- Section: .gnu.linkonce.d.dummy
-...
diff --git a/test/old-elf/gnulinkonce/gnulinkonce.test b/test/old-elf/gnulinkonce/gnulinkonce.test
deleted file mode 100644
index eacd41d6ded5..000000000000
--- a/test/old-elf/gnulinkonce/gnulinkonce.test
+++ /dev/null
@@ -1,149 +0,0 @@
-# Tests that the linker is able to read .gnu.linkonce sections and link them
-# appropriately. The testcase has been created by using the following source
-# code
-# linkonce1a.s
-# ------------
-# .section .gnu.linkonce.d.dummy,"aw"
-#bar:
-# .long 0
-# linkonce1b.s
-# ------------
-# .globl main
-# .globl start
-# .globl _start
-# .globl __start
-# .text
-#main:
-#start:
-#_start:
-#__start:
-# .long 0
-#
-# .section .gnu.linkonce.d.dummy,"aw"
-#foo:
-# .long 0
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
-#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor old-gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
-#RUN: --noinhibit-exec -o %t2.out
-#RUN: FileCheck %s -check-prefix=CHECKGNULINKONCE < %t2.out.yaml
-#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGNULINKONCESECTIONS
-#CHECKGNULINKONCE: - name: .gnu.linkonce.d.dummy
-#CHECKGNULINKONCE: scope: global
-#CHECKGNULINKONCE: type: gnu-linkonce
-#CHECKGNULINKONCE: section-choice: custom-required
-#CHECKGNULINKONCE: section-name: .gnu.linkonce.d.dummy
-#CHECKGNULINKONCE: permissions: rw-
-#CHECKGNULINKONCE: references:
-#CHECKGNULINKONCE: - kind: group-child
-#CHECKGNULINKONCE: offset: 0
-#CHECKGNULINKONCE: target: bar
-#CHECKGNULINKONCE: - kind: group-child
-#CHECKGNULINKONCE: offset: 0
-#CHECKGNULINKONCESECTIONS: Section {
-#CHECKGNULINKONCESECTIONS: Name: .gnu.linkonce.d.dummy
-#CHECKGNULINKONCESECTIONS: Type: SHT_PROGBITS
-#CHECKGNULINKONCESECTIONS: Flags [ (0x3)
-#CHECKGNULINKONCESECTIONS: SHF_ALLOC (0x2)
-#CHECKGNULINKONCESECTIONS: SHF_WRITE (0x1)
-#CHECKGNULINKONCESECTIONS: ]
-#CHECKGNULINKONCESECTIONS: Size: 4
-#CHECKGNULINKONCESECTIONS: }
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .gnu.linkonce.d.dummy
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: '00000000'
-Symbols:
- Local:
- - Name: bar
- Section: .gnu.linkonce.d.dummy
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .gnu.linkonce.d.dummy
- Type: STT_SECTION
- Section: .gnu.linkonce.d.dummy
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: '00000000'
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .gnu.linkonce.d.dummy
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: '00000000'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .gnu.linkonce.d.dummy
- Type: STT_SECTION
- Section: .gnu.linkonce.d.dummy
- - Name: foo
- Section: .gnu.linkonce.d.dummy
- Global:
- - Name: main
- Section: .text
- - Name: start
- Section: .text
- - Name: _start
- Section: .text
- - Name: __start
- Section: .text
-...
diff --git a/test/old-elf/gotpcrel.test b/test/old-elf/gotpcrel.test
deleted file mode 100644
index b8695f1aedfb..000000000000
--- a/test/old-elf/gotpcrel.test
+++ /dev/null
@@ -1,21 +0,0 @@
-# This test checks that GOTPCREL entries are being handled properly
-RUN: lld -flavor old-gnu -target x86_64-linux -static -e main --output-filetype=yaml \
-RUN: --noinhibit-exec %p/Inputs/gotpcrel.x86-64 \
-RUN: | FileCheck %s -check-prefix=YAML
-
-YAML: name: main
-YAML: references:
-YAML: kind: R_X86_64_GOTPCREL
-YAML: offset: 3
-YAML: target: [[NULLGOT:[a-zA-Z0-9_]+]]
-YAML: kind: R_X86_64_GOTPCREL
-YAML: offset: 10
-YAML: target: [[MAINGOT:[a-zA-Z0-9_]+]]
-
-YAML: name: [[NULLGOT]]
-YAML: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-YAML-NOT: references:
-
-YAML: name: [[MAINGOT]]
-YAML: kind: R_X86_64_64
-YAML: target: main
diff --git a/test/old-elf/gottpoff.test b/test/old-elf/gottpoff.test
deleted file mode 100644
index 969874e538a5..000000000000
--- a/test/old-elf/gottpoff.test
+++ /dev/null
@@ -1,119 +0,0 @@
-# Test that GOTTPOFF reloc generates an outstanding R_X86_64_TPOFF64
-# to be processed at startup time.
-# Reference: Ulrich Drepper's "ELF Handling for Thread-Local storage"
-
-#RUN: yaml2obj -format=elf %s -o %t.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t -e=main --defsym=__tls_get_addr=0
-#RUN: llvm-readobj -r %t | FileCheck %s
-#
-#CHECK: Section (5) .rela.dyn {
-#CHECK: 0x401098 R_X86_64_TPOFF64 tls2 0x0
-#CHECK: }
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_FREEBSD
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: E819000000640304250000000064030425000000006403042500000000C3488B0500000000648B00C3488D3D00000000E800000000488D8000000000C3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000009
- Symbol: tls1
- Type: R_X86_64_TPOFF32
- - Offset: 0x0000000000000011
- Symbol: tls0
- Type: R_X86_64_TPOFF32
- - Offset: 0x0000000000000019
- Symbol: tls2
- Type: R_X86_64_TPOFF32
- - Offset: 0x0000000000000021
- Symbol: tls2
- Type: R_X86_64_GOTTPOFF
- Addend: -4
- - Offset: 0x000000000000002C
- Symbol: tls0
- Type: R_X86_64_TLSLD
- Addend: -4
- - Offset: 0x0000000000000031
- Symbol: __tls_get_addr
- Type: R_X86_64_PLT32
- Addend: -4
- - Offset: 0x0000000000000038
- Symbol: tls0
- Type: R_X86_64_DTPOFF32
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Size: 8
- - Name: .tbss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Content: '01000000'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .tbss
- Type: STT_SECTION
- Section: .tbss
- - Name: .tdata
- Type: STT_SECTION
- Section: .tdata
- Global:
- - Name: GOTTPOFF
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000001E
- - Name: TLSLD
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000029
- - Name: main
- Type: STT_FUNC
- Section: .text
- - Name: tls0
- Type: STT_TLS
- Section: .tbss
- Size: 0x0000000000000004
- - Name: tls1
- Type: STT_TLS
- Section: .tbss
- Value: 0x0000000000000004
- Size: 0x0000000000000004
- - Name: tls2
- Type: STT_TLS
- Section: .tdata
- Size: 0x0000000000000004
- - Name: _GLOBAL_OFFSET_TABLE_
- - Name: __tls_get_addr
-...
diff --git a/test/old-elf/group-cmd-search.test b/test/old-elf/group-cmd-search.test
deleted file mode 100644
index 1d7f5ee43367..000000000000
--- a/test/old-elf/group-cmd-search.test
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- XFAIL: win32
-
- This test does not pass on Windows because a path starting with
- "/" is not considered as an absolute path. (It needs a drive
- letter.)
-*/
-
-/*
- In general the linker scripts's GROUP command works like a pair
- of command line options --start-group/--end-group. But there is
- a difference in the files look up algorithm.
-
- The --start-group/--end-group commands use a trivial approach:
- a) If the path has '-l' prefix, add 'lib' prefix and '.a'/'.so'
- suffix and search the path through library search directories.
- b) Otherwise, use the path 'as-is'.
-
- The GROUP command implements more compicated approach:
- a) If the path has '-l' prefix, add 'lib' prefix and '.a'/'.so'
- suffix and search the path through library search directories.
- b) If the path does not have '-l' prefix, and sysroot is configured,
- and the path starts with the / character, and the script being
- processed is located inside the sysroot, search the path under
- the sysroot. Otherwise, try to open the path in the current
- directory. If it is not found, search through library search
- directories.
-*/
-
-/*
- This link should finish successfully. The --start-group/--end-group
- contains an existing absolute path to the file.
-
-RUN: lld -flavor old-gnu -target x86_64 -shared \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: --start-group %p/Inputs/shared.so-x86-64 --end-group -o %t1
-*/
-
-/*
- This link should fail with unknown input file format error.
- There is no shared.so-x86-64 file in the current directory.
-
-RUN: not \
-RUN: lld -flavor old-gnu -target x86_64 -shared \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: --start-group shared.so-x86-64 --end-group -o %t2
-*/
-
-/*
- This link should fail with unknown input file format error.
- The absolute path /shared.so-x86-64 does not exist and the linker
- should not attempt to search it under the sysroot directory.
-
-RUN: not \
-RUN: lld -flavor old-gnu -target x86_64 -shared --sysroot=%p/Inputs \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: --start-group /shared.so-x86-64 --end-group -o %t3
-*/
-
-/*
- This link should finish successfully. The group-cmd-search-1.ls
- script contains "GROUP ( shared.so-x86-64 )" command and the linker
- has to search shared.so-x86-64 through the library search paths.
-
-RUN: lld -flavor old-gnu -target x86_64 -shared \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/group-cmd-search-1.ls -o %t4
-*/
-
-/*
- This link should fail with unknown input file format error.
- The group-cmd-search-2.ls script contains GROUP command with
- a non-existing absolute path but there is no --sysroot argument.
-
-RUN: not \
-RUN: lld -flavor old-gnu -target x86_64 -shared \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/group-cmd-search-2.ls -o %t5
-*/
-
-/*
- This link should finish successfully. The group-cmd-search-2.ls
- script contains GROUP command with an absolute path and the sysroot
- directory is provided. The linker has to search the absolute path
- under the sysroot directory.
-
-RUN: lld -flavor old-gnu -target x86_64 -shared --sysroot=%p/Inputs \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/group-cmd-search-2.ls -o %t6
-*/
-
-/*
- This link should finish successfully. The group-cmd-search-2.ls
- script contains GROUP command with an absolute path and the sysroot
- directory is provided. The linker has to search the absolute path
- under the sysroot directory.
-
-RUN: lld -flavor old-gnu -target x86_64 -shared --sysroot=%p/Inputs/../Inputs \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/group-cmd-search-2.ls -o %t6
-*/
-
-/*
- This link should finish successfully. The group-cmd-search-3.ls
- script contains GROUP command with two elements. The first one
- has a -l:<path> form and should be found by iterating through
- lib dirs and searching the 'path' name exactly. The second element
- has a -l<lib name> form and should be found by constructing a full
- library name lib<lib name>.a and iterating through lib dirs.
-
-RUN: lld -flavor old-gnu -target x86_64 -shared \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/group-cmd-search-3.ls -o %t8
-*/
-
-/*
- This link should fail with unknown input file format error.
- The linker script from this file contains GROUP with an absolute
- path which can be found under provided sysroot directory.
- But the linker script itself is not under the sysroot.
-
-RUN: not \
-RUN: lld -flavor old-gnu -target x86_64 -shared --sysroot=%p/Inputs \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: %s -o %t7
-*/
-
-/*
-RUN: lld -flavor old-gnu -target x86_64 -shared \
-RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
-RUN: -l:group-cmd-search-1.ls -o %t9
-*/
-
-GROUP ( /shared.so-x86-64 )
diff --git a/test/old-elf/hexagon-quickdata-sort.test b/test/old-elf/hexagon-quickdata-sort.test
deleted file mode 100644
index 98488b75ceb7..000000000000
--- a/test/old-elf/hexagon-quickdata-sort.test
+++ /dev/null
@@ -1,12 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon %p/Inputs/quickdata-sort-test.o.elf-hexagon -o %t1 --noinhibit-exec
-RUN: llvm-nm -n %t1 | FileCheck %s -check-prefix=quickdataSort
-
-quickdataSort: 00002000 D A1
-quickdataSort: 00002001 D AA1
-quickdataSort: 00002002 D B1
-quickdataSort: 00002004 D BB1
-quickdataSort: 00002008 D C1
-quickdataSort: 0000200c D CC1
-quickdataSort: 00002010 D D1
-quickdataSort: 00002018 D DD1
-
diff --git a/test/old-elf/hexagon-quickdata-sortcommon.test b/test/old-elf/hexagon-quickdata-sortcommon.test
deleted file mode 100644
index d4d7d6a617e6..000000000000
--- a/test/old-elf/hexagon-quickdata-sortcommon.test
+++ /dev/null
@@ -1,16 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon -o %t1 --noinhibit-exec \
-RUN: %p/Inputs/quickdata-sortcommon-test.o.elf-hexagon
-RUN: llvm-nm -n %t1 | FileCheck %s -check-prefix=quickdataSortCommon
-
-quickdataSortCommon: 00002000 D A1
-quickdataSortCommon: 00002001 D AA1
-quickdataSortCommon: 00002002 D AAA1
-quickdataSortCommon: 00002004 D B1
-quickdataSortCommon: 00002006 D BB1
-quickdataSortCommon: 00002008 D BBB1
-quickdataSortCommon: 0000200c D C1
-quickdataSortCommon: 00002010 D CC1
-quickdataSortCommon: 00002014 D CCC1
-quickdataSortCommon: 00002018 D D1
-quickdataSortCommon: 00002020 D DD1
-quickdataSortCommon: 00002028 D DDD1
diff --git a/test/old-elf/ifunc.test b/test/old-elf/ifunc.test
deleted file mode 100644
index 0aa317a24e6f..000000000000
--- a/test/old-elf/ifunc.test
+++ /dev/null
@@ -1,69 +0,0 @@
-# REQUIRES: x86
-
-# This test checks that IRELATIVE relocations are created for symbols that
-# need relocation even for static links.
-RUN: lld -flavor old-gnu -target x86_64-linux --output-filetype=yaml -r \
-RUN: %p/Inputs/ifunc.x86-64 | FileCheck %s
-
-RUN: lld -flavor old-gnu -target x86_64-linux --output-filetype=yaml --noinhibit-exec \
-RUN: %p/Inputs/ifunc.x86-64 %p/Inputs/ifunc.cpp.x86-64 \
-RUN: | FileCheck %s --check-prefix=PLT
-
-RUN: lld -flavor old-gnu -target x86_64-linux -o %t %p/Inputs/ifunc.x86-64 \
-RUN: -e main -static %p/Inputs/ifunc.cpp.x86-64
-RUN: llvm-objdump -d -s %t| FileCheck %s --check-prefix=BIN
-RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELATIVEADDEND
-
-# Test that STT_GNU_IFUNC symbols have type Code in SharedLibraryAtom.
-RUN: lld -flavor old-gnu -target x86_64-linux --output-filetype=yaml \
-RUN: --noinhibit-exec %p/Inputs/ifunc.cpp.x86-64 -L%p/Inputs -lifunc.x86-64 \
-RUN: | FileCheck %s --check-prefix=SHARED
-
-PLT: defined-atoms:
-
-PLT: name: plt
-PLT: scope: global
-PLT: references:
-PLT: kind: R_X86_64_PC32
-PLT: target: [[PLTNAME:[-a-zA-Z0-9_]+]]
-
-PLT: name: main
-PLT: scope: global
-PLT: references:
-PLT: kind: R_X86_64_PC32
-PLT: target: [[PLTNAME]]
-
-// Make sure the target of main's relocation is a stub with a PC32 relocation.
-// This relocation is to the got atom, but you can't really write that check in
-// FileCheck.
-PLT: name:
-PLT: type: stub
-PLT: references
-PLT: kind: R_X86_64_PC32
-
-// Make sure there's a got entry with a IRELATIVE relocation.
-PLT: type: got
-PLT: references:
-PLT: kind: R_X86_64_IRELATIVE
-PLT: target: hey
-
-CHECK: name: hey
-CHECK: scope: global
-CHECK: type: resolver
-
-
-// This is a horribly brittle test. We need a way to do arithmetic on captured
-// variables.
-BIN: {{[0-9a-f]+}}: ff 25 {{[0-9a-f]+}} {{[0-9a-f]+}} 00 00 jmpq *{{[0-9]+}}(%rip)
-BIN: .got.plt:
-BIN-NEXT: {{[0-9a-f]+}} 00000000 00000000
-
-RELATIVEADDEND: Relocations [
-RELATIVEADDEND-NEXT: Section (1) .rela.plt {
-RELATIVEADDEND-NEXT: 0x401000 R_X86_64_IRELATIVE - 0x400110
-RELATIVEADDEND-NEXT: }
-RELATIVEADDEND-NEXT: ]
-
-SHARED: shared-library-atoms
-SHARED: name: hey
-SHARED-NOT: data
diff --git a/test/old-elf/ignore-unknownoption.test b/test/old-elf/ignore-unknownoption.test
deleted file mode 100644
index aa03a2eb4e73..000000000000
--- a/test/old-elf/ignore-unknownoption.test
+++ /dev/null
@@ -1,5 +0,0 @@
-# This test tests that lld is able to print unknown options that are not
-# recognized.
-RUN: not lld -flavor old-gnu -target x86_64 --gc-sections 2> %t
-RUN: FileCheck %s < %t
-CHECK: warning: ignoring unknown argument: --gc-sections
diff --git a/test/old-elf/init_array-order.test b/test/old-elf/init_array-order.test
deleted file mode 100644
index 2b8bcb65c3e4..000000000000
--- a/test/old-elf/init_array-order.test
+++ /dev/null
@@ -1,67 +0,0 @@
-#RUN: yaml2obj -format=elf %s > %t
-#RUN: lld -flavor old-gnu -target x86_64-linux %t --noinhibit-exec \
-#RUN: -o %t1.out
-#RUN: llvm-objdump -s %t1.out | FileCheck %s
-
-!ELF
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: "1100000000000000"
- AddressAlign: 8
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .init_array.2
- Type: SHT_INIT_ARRAY
- Content: "0200000000000000"
- AddressAlign: 8
- Flags: [SHF_ALLOC]
-- Name: .init_array.3
- Type: SHT_INIT_ARRAY
- Content: "0300000000000000"
- AddressAlign: 8
- Flags: [SHF_ALLOC]
-- Name: .init_array
- Type: SHT_INIT_ARRAY
- Content: "9900000000000000"
- AddressAlign: 8
- Flags: [SHF_ALLOC]
-- Name: .data
- Type: SHT_PROGBITS
- Content: "2200000000000000"
- AddressAlign: 8
- Flags: [SHF_ALLOC, SHF_WRITE]
-- Name: .init_array.1
- Type: SHT_INIT_ARRAY
- Content: "0100000000000000"
- AddressAlign: 8
- Flags: [SHF_ALLOC]
-
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .init_array.3
- Type: STT_SECTION
- Section: .init_array.3
- - Name: .init_array.2
- Type: STT_SECTION
- Section: .init_array.2
- - Name: .init_array.1
- Type: STT_SECTION
- Section: .init_array.1
- - Name: .init_array
- Type: STT_SECTION
- Section: .init_array
-
-#CHECK: {{[0xa-f0-9]+}} 01000000 00000000 02000000 00000000
-#CHECK: {{[0xa-f0-9]+}} 03000000 00000000 99000000 00000000
diff --git a/test/old-elf/init_array.test b/test/old-elf/init_array.test
deleted file mode 100644
index f7f48445621e..000000000000
--- a/test/old-elf/init_array.test
+++ /dev/null
@@ -1,127 +0,0 @@
-# Test .init_array.
-# Generated from the following C code:
-#
-# static void
-# init () {}
-#
-# static void (*const init_array []) ()
-# __attribute__ ((used, section (".init_array"), aligned (sizeof (void *))))
-# = { init };
-#
-# int
-# main() { return (0); }
-#
-# Note: both STT_OBJECT and STT_SECTION for .init_array are commented in yaml
-# declaration to check if lld correct adds the object's .init_array when the
-# section has no symbol (some compilers may create object with this behavior,
-# specially for C++ global constructors).
-
-#RUN: yaml2obj -format=elf %s -o=%t.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.o -o %t -e=main
-#RUN: llvm-objdump -t -section-headers %t | FileCheck %s
-
-#CHECK: .init_array {{[0-9]+}} [[ADDR:[0-9]+]]
-#CHECK: [[ADDR]] l *ABS* {{[0-9]+}} .hidden __init_array_start
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_FREEBSD
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E5B800000000C745FC000000005DC366666666662E0F1F840000000000554889E55DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .init_array
- Type: SHT_INIT_ARRAY
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: '0000000000000000'
- - Name: .rela.init_array
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .init_array
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: .text
- Type: R_X86_64_64
- Addend: 32
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 004672656542534420636C616E672076657273696F6E20332E342E312028746167732F52454C454153455F33342F646F74312D66696E616C203230383033322920323031343035313200
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000017A5200017810011B0C070890010000180000001C000000000000001200000000410E108602430D060000001800000038000000000000000600000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 32
-Symbols:
- Local:
- - Name: init
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000020
- Size: 0x0000000000000006
-# - Name: init_array
-# Type: STT_OBJECT
-# Section: .init_array
-# Size: 0x0000000000000008
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
-# - Name: .init_array
-# Type: STT_SECTION
-# Section: .init_array
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000012
-...
diff --git a/test/old-elf/initfini-options.test-1.test b/test/old-elf/initfini-options.test-1.test
deleted file mode 100644
index f8571a637197..000000000000
--- a/test/old-elf/initfini-options.test-1.test
+++ /dev/null
@@ -1,33 +0,0 @@
-# Check that if there are no -init/-fini options and _init/_fini symbols
-# are undefined the linker does not emit DT_INIT/DT_FINI tags.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target x86_64 -shared --noinhibit-exec -o %t.so %t.o
-# RUN: llvm-readobj -dynamic-table %t.so | FileCheck %s
-
-# CHECK-NOT: 0x000000000000000C INIT 0x{{[0-9A-F]+}}
-# CHECK-NOT: 0x000000000000000D FINI 0x{{[0-9A-F]+}}
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x08
-
-Symbols:
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Size: 0x08
- - Name: _init
- - Name: _fini
-...
diff --git a/test/old-elf/initfini-options.test-2.test b/test/old-elf/initfini-options.test-2.test
deleted file mode 100644
index 35361c76d973..000000000000
--- a/test/old-elf/initfini-options.test-2.test
+++ /dev/null
@@ -1,47 +0,0 @@
-# Check that if _init/_fini symbols are defined the linker emits
-# DT_INIT/DT_FINI tags point to these symbols.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target x86_64 -shared -o %t.so %t.o
-# RUN: llvm-readobj -symbols -dynamic-table %t.so | FileCheck %s
-
-# CHECK: Name: _init (8)
-# CHECK-NEXT: Value: {{[0x0-9a-f]+}}
-# CHECK: Name: _fini (14)
-# CHECK-NEXT: Value: {{[0x0-9a-f]+}}
-#
-# CHECK: 0x000000000000000C INIT {{[0x0-9a-f]+}}
-# CHECK: 0x000000000000000D FINI {{[0x0-9a-f]+}}
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x18
-
-Symbols:
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Value: 0x0
- Size: 0x8
- - Name: _init
- Type: STT_FUNC
- Section: .text
- Value: 0x8
- Size: 0x8
- - Name: _fini
- Type: STT_FUNC
- Section: .text
- Value: 0xF
- Size: 0x8
-...
diff --git a/test/old-elf/initfini-options.test-3.test b/test/old-elf/initfini-options.test-3.test
deleted file mode 100644
index 2c9ab3cceb94..000000000000
--- a/test/old-elf/initfini-options.test-3.test
+++ /dev/null
@@ -1,53 +0,0 @@
-# Check that -init/-fini command line options override default function names
-# and the linker uses these name to search symbols and setup DT_INIT/DT_FINI.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor old-gnu -target x86_64 -shared -o %t.so %t.o \
-# RUN: -init _init -init _start -fini _fini -fini _stop
-# RUN: llvm-readobj -symbols -dynamic-table %t.so | FileCheck %s
-
-# CHECK: Name: _start (1)
-# CHECK-NEXT: Value: {{[0x0-9a-f]+}}
-# CHECK: Name: _stop (8)
-# CHECK-NEXT: Value: {{[0x0-9a-f]+}}
-#
-# CHECK: 0x000000000000000C INIT {{[0x0-9a-f]+}}
-# CHECK: 0x000000000000000D FINI {{[0x0-9a-f]+}}
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x04
- Size: 0x20
-
-Symbols:
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Value: 0x0
- Size: 0x8
- - Name: _stop
- Type: STT_FUNC
- Section: .text
- Value: 0x8
- Size: 0x8
- - Name: _init
- Type: STT_FUNC
- Section: .text
- Value: 0xF
- Size: 0x8
- - Name: _fini
- Type: STT_FUNC
- Section: .text
- Value: 0x18
- Size: 0x8
-...
diff --git a/test/old-elf/librarynotfound.test b/test/old-elf/librarynotfound.test
deleted file mode 100644
index 9b1b8f2cffc4..000000000000
--- a/test/old-elf/librarynotfound.test
+++ /dev/null
@@ -1,5 +0,0 @@
-# Tests the functionality of library not found
-RUN: not lld -flavor old-gnu -lfn 2> %t1
-RUN: FileCheck %s < %t1
-
-CHECK: Unable to find library -lfn
diff --git a/test/old-elf/linker-as-ld.test b/test/old-elf/linker-as-ld.test
deleted file mode 100644
index 8b07ae9d1a71..000000000000
--- a/test/old-elf/linker-as-ld.test
+++ /dev/null
@@ -1,16 +0,0 @@
-REQUIRES: system-linker-elf
-
-RUN: mkdir -p %t.dir && cp `which lld` %t.dir/ld
-RUN: %t.dir/ld -o %t %p/Inputs/relocs.x86-64 \
-RUN: -e _start -static
-RUN: llvm-readobj -t %t | FileCheck %s
-
-# Test linker run as "ld" on elf based system works like gnu linker.
-
-
-CHECK: Symbol {
-CHECK: Name: i
-CHECK-NEXT: Value:
-CHECK-NEXT: Size:
-CHECK-NEXT: Binding:
-CHECK-NEXT: Type: Object
diff --git a/test/old-elf/linkerscript/Inputs/externs.ls b/test/old-elf/linkerscript/Inputs/externs.ls
deleted file mode 100644
index 20fdc0c3f980..000000000000
--- a/test/old-elf/linkerscript/Inputs/externs.ls
+++ /dev/null
@@ -1,3 +0,0 @@
-/* A simple valid linker script used for testing the EXTERN command.
- */
-EXTERN(_foo bar __baz)
diff --git a/test/old-elf/linkerscript/Inputs/invalid.ls b/test/old-elf/linkerscript/Inputs/invalid.ls
deleted file mode 100644
index 894d4bef2732..000000000000
--- a/test/old-elf/linkerscript/Inputs/invalid.ls
+++ /dev/null
@@ -1 +0,0 @@
-GROUP(
diff --git a/test/old-elf/linkerscript/Inputs/prog1.o.yaml b/test/old-elf/linkerscript/Inputs/prog1.o.yaml
deleted file mode 100644
index f450048ab37b..000000000000
--- a/test/old-elf/linkerscript/Inputs/prog1.o.yaml
+++ /dev/null
@@ -1,87 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E5B000E800000000BF01000000BA0E0000004889C6E80000000031C05DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000007
- Symbol: prog2
- Type: R_X86_64_PC32
- Addend: -4
- - Offset: 0x0000000000000019
- Symbol: write
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742036336134646334616430343938646139623934386330383263623735336430353735323938346638292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420623838363135326664656538376564653738613565643965616638663664313839343033616266312900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C0708900100001C0000001C000000000000002100000000410E108602430D0600000000000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000021
- - Name: prog2
- - Name: write
-...
diff --git a/test/old-elf/linkerscript/Inputs/prog2.o.yaml b/test/old-elf/linkerscript/Inputs/prog2.o.yaml
deleted file mode 100644
index 4d1bbd5754ea..000000000000
--- a/test/old-elf/linkerscript/Inputs/prog2.o.yaml
+++ /dev/null
@@ -1,88 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E548B800000000000000005DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000006
- Symbol: .rodata.str1.1
- Type: R_X86_64_64
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .rodata.str1.1
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 48656C6C6F2C20776F726C64210A00
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742036336134646334616430343938646139623934386330383263623735336430353735323938346638292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420623838363135326664656538376564653738613565643965616638663664313839343033616266312900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C0708900100001C0000001C000000000000001000000000410E108602430D0600000000000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .rodata.str1.1
- Type: STT_SECTION
- Section: .rodata.str1.1
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: prog2
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000010
-...
diff --git a/test/old-elf/linkerscript/Inputs/prog3.o.yaml b/test/old-elf/linkerscript/Inputs/prog3.o.yaml
deleted file mode 100644
index 2402be4d42b6..000000000000
--- a/test/old-elf/linkerscript/Inputs/prog3.o.yaml
+++ /dev/null
@@ -1,51 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: B8010000000F05C3E800000000B83C0000000F05C3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000009
- Symbol: main
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: _start
- Section: .text
- Value: 0x0000000000000008
- - Name: write
- Section: .text
- - Name: main
-...
diff --git a/test/old-elf/linkerscript/Inputs/simple-pic.o.yaml b/test/old-elf/linkerscript/Inputs/simple-pic.o.yaml
deleted file mode 100644
index f826034053c3..000000000000
--- a/test/old-elf/linkerscript/Inputs/simple-pic.o.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 4
- Size: 16
-
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 4
- Size: 16
-
-Symbols:
- Local:
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Size: 16
diff --git a/test/old-elf/linkerscript/Inputs/simple.o.yaml b/test/old-elf/linkerscript/Inputs/simple.o.yaml
deleted file mode 100644
index fc9cd4c5f67d..000000000000
--- a/test/old-elf/linkerscript/Inputs/simple.o.yaml
+++ /dev/null
@@ -1,51 +0,0 @@
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: B80100000048C7C70100000048C7C60000000048C7C20E0000000F05C3E8DEFFFFFFB83C0000000F05C3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x000000000000000F
- Symbol: .data
- Type: R_X86_64_32S
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: 48656C6C6F2C20576F726C64210A00
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
-Symbols:
- Local:
- - Name: main
- Section: .text
- - Name: msg
- Section: .data
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: _start
- Section: .text
- Value: 0x000000000000001D
-...
diff --git a/test/old-elf/linkerscript/Inputs/valid.ls b/test/old-elf/linkerscript/Inputs/valid.ls
deleted file mode 100644
index 43593602d3fb..000000000000
--- a/test/old-elf/linkerscript/Inputs/valid.ls
+++ /dev/null
@@ -1,6 +0,0 @@
-/* A simple valid linker script used for testing the -T/--script options.
- *
- * An unresolved symbol named '_entry_point' can be scanned for by the tests
- * to determine that the linker script was processed.
- */
-ENTRY(_entry_point)
diff --git a/test/old-elf/linkerscript/externs.objtxt b/test/old-elf/linkerscript/externs.objtxt
deleted file mode 100644
index d79c56a142c9..000000000000
--- a/test/old-elf/linkerscript/externs.objtxt
+++ /dev/null
@@ -1,21 +0,0 @@
-# Check symbols defined with the EXTERN command are added as undefined
-# symbols.
-
-# RUN: lld -flavor old-gnu -target x86_64 -T %p/Inputs/externs.ls -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-defined-atoms:
- - name: main
- scope: global
- content: [ B8, 00, 00, 00, 00, C7, 44, 24, FC, 00, 00, 00, 00, C3 ]
- alignment: 16
- section-choice: custom-required
- section-name: .text
-
-# CHECK: undefined-atoms:
-# CHECK: - name: _foo
-# CHECK: can-be-null: at-buildtime
-# CHECK: - name: bar
-# CHECK: can-be-null: at-buildtime
-# CHECK: - name: __baz
-# CHECK: can-be-null: at-buildtime
diff --git a/test/old-elf/linkerscript/filename-with-wildcards.test b/test/old-elf/linkerscript/filename-with-wildcards.test
deleted file mode 100644
index 9376d5a5cfb4..000000000000
--- a/test/old-elf/linkerscript/filename-with-wildcards.test
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-Tests a linker script that uses the SECTIONS command with rules containing
-wildcards that matching input object files.
-*/
-
-ENTRY(_start)
-
-SECTIONS
-{
- . = 0x500000;
- .foo : { *p1-wc.o(.text .rodata*) }
- .bar : { *(.text .rodata*) }
-}
-
-/*
-RUN: mkdir -p %T
-RUN: yaml2obj -format=elf %p/Inputs/prog1.o.yaml -o=%T/p1-wc.o
-RUN: yaml2obj -format=elf %p/Inputs/prog2.o.yaml -o=%T/p2-wc.o
-RUN: yaml2obj -format=elf %p/Inputs/prog3.o.yaml -o=%T/p3-wc.o
-RUN: cd %T
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s p1-wc.o p2-wc.o p3-wc.o \
-RUN: -static -o %t1
-RUN: llvm-readobj -s %t1 | FileCheck -check-prefix CHECKSECTIONS %s
-
-CHECKSECTIONS: Index: 1
-CHECKSECTIONS: Name: .foo
-CHECKSECTIONS: Address: 0x500000
-CHECKSECTIONS: Size: 33
-
-CHECKSECTIONS: Index: 2
-CHECKSECTIONS: Name: .bar
-CHECKSECTIONS: Address: 0x500030
-CHECKSECTIONS: Size: 52
-
-RUN: llvm-readobj -symbols %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-CHECKSYMS: Name: main
-CHECKSYMS-NEXT: Value: 0x500000
-
-CHECKSYMS: Name: prog2
-CHECKSYMS-NEXT: Value: 0x500030
-
-CHECKSYMS: Name: write
-CHECKSYMS-NEXT: Value: 0x500040
-
-CHECKSYMS: Name: _start
-CHECKSYMS-NEXT: Value: 0x500048
-*/
diff --git a/test/old-elf/linkerscript/invalid-script-cli-1.test b/test/old-elf/linkerscript/invalid-script-cli-1.test
deleted file mode 100644
index 72d2edebb4d5..000000000000
--- a/test/old-elf/linkerscript/invalid-script-cli-1.test
+++ /dev/null
@@ -1,10 +0,0 @@
-# Check that the -T/--script options issue an error when passed
-# filenames for files that do not exist.
-
-RUN: not lld -flavor old-gnu -target x86_64 -T idonotexist.ls 2> %t.err
-RUN: FileCheck %s < %t.err
-
-RUN: not lld -flavor old-gnu -target x86_64 --script=idonotexist.ls 2> %t.err
-RUN: FileCheck %s < %t.err
-
-CHECK: {{.*}}lld: cannot find file {{.*}}idonotexist.ls
diff --git a/test/old-elf/linkerscript/invalid-script-cli-2.test b/test/old-elf/linkerscript/invalid-script-cli-2.test
deleted file mode 100644
index cc76f0e55a81..000000000000
--- a/test/old-elf/linkerscript/invalid-script-cli-2.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# Check that linker script are *not* picked up with -lscript.ls.
-
-RUN: not lld -flavor old-gnu -target x86_64 -L%p/Inputs/ -lvalid.ls 2> %t.err
-RUN: FileCheck %s < %t.err
-
-CHECK: {{.*}}: Unable to find library -lvalid.ls
diff --git a/test/old-elf/linkerscript/invalid.test b/test/old-elf/linkerscript/invalid.test
deleted file mode 100644
index a00a200225dc..000000000000
--- a/test/old-elf/linkerscript/invalid.test
+++ /dev/null
@@ -1,5 +0,0 @@
-# Check for errors from invalid linker scripts
-RUN: not lld -flavor old-gnu -target x86_64 %p/Inputs/invalid.ls 2> %t.err
-RUN: FileCheck %s < %t.err
-
-CHECK: {{.*}}invalid.ls: Error parsing linker script
diff --git a/test/old-elf/linkerscript/phdrs-all-none.test b/test/old-elf/linkerscript/phdrs-all-none.test
deleted file mode 100644
index 45baf188d8d8..000000000000
--- a/test/old-elf/linkerscript/phdrs-all-none.test
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-Test when all segments are marked as NONE.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix NONE-ALL-PHDRS %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- text PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :NONE
- .data : { *(.data) }
-}
-
-/*
-NONE-ALL-PHDRS: .text {{[0-9a-f]+}} 0000000000000000
-NONE-ALL-PHDRS: .data {{[0-9a-f]+}} 000000000000002c
-*/
diff --git a/test/old-elf/linkerscript/phdrs-custom-none.test b/test/old-elf/linkerscript/phdrs-custom-none.test
deleted file mode 100644
index e3672cf8fd30..000000000000
--- a/test/old-elf/linkerscript/phdrs-custom-none.test
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Test when PHDRS contains custom NONE segment.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix CUSTOM-NONE-SECS %s
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix CUSTOM-NONE-HDRS %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- NONE PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :NONE
- .data : { *(.data) }
-}
-
-/*
-CUSTOM-NONE-SECS: .text {{[0-9a-f]+}} 00000000004000b0
-CUSTOM-NONE-SECS: .data {{[0-9a-f]+}} 00000000004000dc
-
-CUSTOM-NONE-HDRS: ProgramHeader {
-CUSTOM-NONE-HDRS: Type: PT_LOAD (0x1)
-CUSTOM-NONE-HDRS: VirtualAddress: 0x400000
-CUSTOM-NONE-HDRS: Flags [ (0x5)
-CUSTOM-NONE-HDRS: PF_R (0x4)
-CUSTOM-NONE-HDRS: PF_X (0x1)
-CUSTOM-NONE-HDRS: ]
-CUSTOM-NONE-HDRS: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs-default.test b/test/old-elf/linkerscript/phdrs-default.test
deleted file mode 100644
index 8c493d020504..000000000000
--- a/test/old-elf/linkerscript/phdrs-default.test
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-This group of tests checks usage of default headers during linking,
-when PHDRS command is not defined or defined empty in linker scripts.
-
-This test uses a single X86-64 input object, simple.o, created with the
-following X86-64 assembly code:
-
-*** simple.S:
-
-(command line clang -c simple.S -o simple.o)
-
- .text
- main:
- mov $1, %eax
- movq $1, %rdi
- movq $msg, %rsi
- movq $14, %rdx
- syscall
- ret
-
- .globl _start
- _start:
- call main
- mov $60, %eax
- syscall
- ret
-
- .data
- msg: .asciz "Hello, World!\n"
-*/
-
-/*
-Prepare the object file to test on.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-*/
-
-/*
-Test when no linker script passed.
-
-RUN: lld -flavor old-gnu -target x86_64 %t.o -static -o %t1
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix SECTIONS %s
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix HEADERS %s
-
-SECTIONS: .text {{[0-9a-f]+}} 00000000004000b0
-SECTIONS: .data {{[0-9a-f]+}} 0000000000401000
-
-HEADERS: ProgramHeader {
-HEADERS: Type: PT_LOAD (0x1)
-HEADERS: VirtualAddress: 0x400000
-HEADERS: }
-HEADERS: ProgramHeader {
-HEADERS: Type: PT_LOAD (0x1)
-HEADERS: VirtualAddress: 0x401000
-HEADERS: }
-*/
-
-/*
-Test when linker script doesn't contain PHDRS and sections are not assigned to any segments.
-
-RUN: lld -flavor old-gnu -target x86_64 -T %p/phdrs/sections-no-phdrs.script %t.o -static -o %t2
-RUN: llvm-objdump -section-headers %t2 | FileCheck -check-prefix SECTIONS %s
-RUN: llvm-readobj -program-headers %t2 | FileCheck -check-prefix HEADERS %s
-*/
-
-/*
-Test when linker script contains empty PHDRS and sections are not assigned to any segments.
-
-RUN: lld -flavor old-gnu -target x86_64 -T %p/phdrs/sections-empty-phdrs.script %t.o -static -o %t3
-RUN: llvm-objdump -section-headers %t3 | FileCheck -check-prefix SECTIONS %s
-RUN: llvm-readobj -program-headers %t3 | FileCheck -check-prefix HEADERS %s
-*/
-
-/*
-Test when linker script contains empty PHDRS and sections are only assigned to NONE segments
-or not assigned at all.
-NOTE: Segments with the name NONE are ignored in such a case.
-
-RUN: lld -flavor old-gnu -target x86_64 -T %p/phdrs/sections-none-phdrs.script %t.o -static -o %t4
-RUN: llvm-objdump -section-headers %t4 | FileCheck -check-prefix SECTIONS %s
-RUN: llvm-readobj -program-headers %t4 | FileCheck -check-prefix HEADERS %s
-*/
diff --git a/test/old-elf/linkerscript/phdrs-different.test b/test/old-elf/linkerscript/phdrs-different.test
deleted file mode 100644
index 7fe14dd543d1..000000000000
--- a/test/old-elf/linkerscript/phdrs-different.test
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-Test sections put to different segments.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix DIFF-PHDRS-SECS %s
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix DIFF-PHDRS-HDRS %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- text PT_LOAD;
- data PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) } :data
-}
-
-/*
-DIFF-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000e8
-DIFF-PHDRS-SECS: .data {{[0-9a-f]+}} 0000000000401000
-
-DIFF-PHDRS-HDRS: ProgramHeader {
-DIFF-PHDRS-HDRS: Type: PT_LOAD (0x1)
-DIFF-PHDRS-HDRS: VirtualAddress: 0x400000
-DIFF-PHDRS-HDRS: Flags [ (0x5)
-DIFF-PHDRS-HDRS: PF_R (0x4)
-DIFF-PHDRS-HDRS: PF_X (0x1)
-DIFF-PHDRS-HDRS: ]
-DIFF-PHDRS-HDRS: }
-DIFF-PHDRS-HDRS: ProgramHeader {
-DIFF-PHDRS-HDRS: Type: PT_LOAD (0x1)
-DIFF-PHDRS-HDRS: VirtualAddress: 0x401000
-DIFF-PHDRS-HDRS: Flags [ (0x6)
-DIFF-PHDRS-HDRS: PF_R (0x4)
-DIFF-PHDRS-HDRS: PF_W (0x2)
-DIFF-PHDRS-HDRS: ]
-DIFF-PHDRS-HDRS: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs-extra-program.test b/test/old-elf/linkerscript/phdrs-extra-program.test
deleted file mode 100644
index 3bf27dcb1f5a..000000000000
--- a/test/old-elf/linkerscript/phdrs-extra-program.test
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-Test extra program header generates error.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: not lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
-RUN: FileCheck -check-prefix EXTRA-PROGRAM-PHDR %s < %t1-error
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- header PT_PHDR PHDRS;
- header2 PT_PHDR PHDRS;
- text PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :NONE
- .data : { *(.data) }
-}
-
-/*
-EXTRA-PROGRAM-PHDR: Extra program header is found
-*/
diff --git a/test/old-elf/linkerscript/phdrs-flags.test b/test/old-elf/linkerscript/phdrs-flags.test
deleted file mode 100644
index 0fac53e75302..000000000000
--- a/test/old-elf/linkerscript/phdrs-flags.test
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-Test sections put to different segments with FLAGS attribute set.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix FLAGS-PHDRS-SECS %s
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix FLAGS-PHDRS-HDRS %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- text PT_LOAD FLAGS(0x5);
- data PT_LOAD FLAGS(0x7);
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) } :data
-}
-
-/*
-FLAGS-PHDRS-SECS: .text {{[0-9a-f]+}} 0000000000401000
-FLAGS-PHDRS-SECS: .data {{[0-9a-f]+}} 00000000004000e8
-
-FLAGS-PHDRS-HDRS: ProgramHeader {
-FLAGS-PHDRS-HDRS: Type: PT_LOAD (0x1)
-FLAGS-PHDRS-HDRS: VirtualAddress: 0x400000
-FLAGS-PHDRS-HDRS: Flags [ (0x7)
-FLAGS-PHDRS-HDRS: PF_R (0x4)
-FLAGS-PHDRS-HDRS: PF_W (0x2)
-FLAGS-PHDRS-HDRS: PF_X (0x1)
-FLAGS-PHDRS-HDRS: ]
-FLAGS-PHDRS-HDRS: }
-FLAGS-PHDRS-HDRS: ProgramHeader {
-FLAGS-PHDRS-HDRS: Type: PT_LOAD (0x1)
-FLAGS-PHDRS-HDRS: VirtualAddress: 0x401000
-FLAGS-PHDRS-HDRS: Flags [ (0x5)
-FLAGS-PHDRS-HDRS: PF_R (0x4)
-FLAGS-PHDRS-HDRS: PF_X (0x1)
-FLAGS-PHDRS-HDRS: ]
-FLAGS-PHDRS-HDRS: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs-has-program.test b/test/old-elf/linkerscript/phdrs-has-program.test
deleted file mode 100644
index 83fe94c70614..000000000000
--- a/test/old-elf/linkerscript/phdrs-has-program.test
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-Test when program segment is set it's generated.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDR %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- header PT_PHDR FILEHDR PHDRS;
- text PT_LOAD PHDRS;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) }
-}
-
-/*
-PROGRAM-PHDR: ProgramHeader {
-PROGRAM-PHDR: Type: PT_PHDR (0x6)
-PROGRAM-PHDR: VirtualAddress: 0x400040
-PROGRAM-PHDR: Flags [ (0x5)
-PROGRAM-PHDR: PF_R (0x4)
-PROGRAM-PHDR: PF_X (0x1)
-PROGRAM-PHDR: ]
-PROGRAM-PHDR: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs-invalid.test b/test/old-elf/linkerscript/phdrs-invalid.test
deleted file mode 100644
index c1426e8ffa5f..000000000000
--- a/test/old-elf/linkerscript/phdrs-invalid.test
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-This group of tests checks invalid cases of defining and using PHDRS
-command in linker scripts.
-
-This test uses a single X86-64 input object, simple.o, created with the
-following X86-64 assembly code:
-
-*** simple.S:
-
-(command line clang -c simple.S -o simple.o)
-
- .text
- main:
- mov $1, %eax
- movq $1, %rdi
- movq $msg, %rsi
- movq $14, %rdx
- syscall
- ret
-
- .globl _start
- _start:
- call main
- mov $60, %eax
- syscall
- ret
-
- .data
- msg: .asciz "Hello, World!\n"
-*/
-
-/*
-Prepare the object file to test on.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-*/
-
-/*
-Test undefined header used when no PHDRS defined.
-
-RUN: not lld -flavor old-gnu -target x86_64 -T %p/phdrs/undef-no-phdrs.script %t.o -static -o %t1 &> %t1-error
-RUN: FileCheck -check-prefix UNDEF-NO-PHDRS %s < %t1-error
-
-UNDEF-NO-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
-*/
-
-/*
-Test undefined header used when PHDRS is empty.
-
-RUN: not lld -flavor old-gnu -target x86_64 -T %p/phdrs/undef-empty-phdrs.script %t.o -static -o %t2 &> %t2-error
-RUN: FileCheck -check-prefix UNDEF-EMPTY-PHDRS %s < %t2-error
-
-UNDEF-EMPTY-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
-*/
-
-/*
-Test undefined header used when PHDRS contains definitions.
-
-RUN: not lld -flavor old-gnu -target x86_64 -T %p/phdrs/undef-id-phdrs.script %t.o -static -o %t3 &> %t3-error
-RUN: FileCheck -check-prefix UNDEF-ID-PHDRS %s < %t3-error
-
-UNDEF-ID-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
-*/
diff --git a/test/old-elf/linkerscript/phdrs-misplaced-program.test b/test/old-elf/linkerscript/phdrs-misplaced-program.test
deleted file mode 100644
index 0fb669d818c4..000000000000
--- a/test/old-elf/linkerscript/phdrs-misplaced-program.test
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-Test misplaced program header generates error.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: not lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
-RUN: FileCheck -check-prefix MISPLACED-PROGRAM-PHDR %s < %t1-error
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- text PT_LOAD;
- header PT_PHDR PHDRS;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :NONE
- .data : { *(.data) }
-}
-
-/*
-MISPLACED-PROGRAM-PHDR: Program header must precede load segments
-*/
diff --git a/test/old-elf/linkerscript/phdrs-no-program.test b/test/old-elf/linkerscript/phdrs-no-program.test
deleted file mode 100644
index e461d5061019..000000000000
--- a/test/old-elf/linkerscript/phdrs-no-program.test
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-Test when no program segment set it's not generated.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDR %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- text PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) }
-}
-
-/*
-PROGRAM-PHDR-NOT: Type: PT_PHDR (0x6)
-*/
diff --git a/test/old-elf/linkerscript/phdrs-one-none.test b/test/old-elf/linkerscript/phdrs-one-none.test
deleted file mode 100644
index a1c84e59fc60..000000000000
--- a/test/old-elf/linkerscript/phdrs-one-none.test
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Test when one segment is marked as NONE.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix NONE-PHDRS-SECS %s
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix NONE-PHDRS-HDRS %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- text PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) } :NONE
-}
-
-/*
-NONE-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000b0
-NONE-PHDRS-SECS: .data {{[0-9a-f]+}} 0000000000000000
-
-NONE-PHDRS-HDRS: ProgramHeader {
-NONE-PHDRS-HDRS: Type: PT_LOAD (0x1)
-NONE-PHDRS-HDRS: VirtualAddress: 0x400000
-NONE-PHDRS-HDRS: Flags [ (0x5)
-NONE-PHDRS-HDRS: PF_R (0x4)
-NONE-PHDRS-HDRS: PF_X (0x1)
-NONE-PHDRS-HDRS: ]
-NONE-PHDRS-HDRS: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs-program-flags.test b/test/old-elf/linkerscript/phdrs-program-flags.test
deleted file mode 100644
index 2a719a6cb296..000000000000
--- a/test/old-elf/linkerscript/phdrs-program-flags.test
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-Test when program segment contains only FLAGS attribute.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-FLAGS-PHDR %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- header PT_PHDR PHDRS FLAGS(0x7);
- text PT_LOAD FILEHDR PHDRS;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) }
-}
-
-/*
-PROGRAM-FLAGS-PHDR: ProgramHeader {
-PROGRAM-FLAGS-PHDR: Type: PT_PHDR (0x6)
-PROGRAM-FLAGS-PHDR: Flags [ (0x7)
-PROGRAM-FLAGS-PHDR: PF_R (0x4)
-PROGRAM-FLAGS-PHDR: PF_W (0x2)
-PROGRAM-FLAGS-PHDR: PF_X (0x1)
-PROGRAM-FLAGS-PHDR: ]
-PROGRAM-FLAGS-PHDR: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs-program-good-phdrs.test b/test/old-elf/linkerscript/phdrs-program-good-phdrs.test
deleted file mode 100644
index 373facc380ba..000000000000
--- a/test/old-elf/linkerscript/phdrs-program-good-phdrs.test
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-Test when program segment contains only PHDRS attribute.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDRS-PHDR %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- header PT_PHDR PHDRS;
- text PT_LOAD PHDRS;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) }
-}
-
-/*
-PROGRAM-PHDRS-PHDR: ProgramHeader {
-PROGRAM-PHDRS-PHDR: Type: PT_PHDR (0x6)
-PROGRAM-PHDRS-PHDR: VirtualAddress: 0x400040
-PROGRAM-PHDRS-PHDR: MemSize: 168
-PROGRAM-PHDRS-PHDR: Flags [ (0x5)
-PROGRAM-PHDRS-PHDR: PF_R (0x4)
-PROGRAM-PHDRS-PHDR: PF_X (0x1)
-PROGRAM-PHDRS-PHDR: ]
-PROGRAM-PHDRS-PHDR: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs-program-no-phdrs.test b/test/old-elf/linkerscript/phdrs-program-no-phdrs.test
deleted file mode 100644
index 3e639bdb0f43..000000000000
--- a/test/old-elf/linkerscript/phdrs-program-no-phdrs.test
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-Test when program segment doesn't contain PHDRS attribute.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: not lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
-RUN: FileCheck -check-prefix PROGRAM-PHDR-NO-PHDRS %s < %t1-error
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- header PT_PHDR;
- text PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) }
-}
-
-/*
-PROGRAM-PHDR-NO-PHDRS: Program header has invalid PHDRS attribute
-*/
diff --git a/test/old-elf/linkerscript/phdrs-program-wrong-phdrs.test b/test/old-elf/linkerscript/phdrs-program-wrong-phdrs.test
deleted file mode 100644
index c27b23d85876..000000000000
--- a/test/old-elf/linkerscript/phdrs-program-wrong-phdrs.test
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-Test when program segment contains PHDRS attribute not mapped to load segment.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: not lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
-RUN: FileCheck -check-prefix PROGRAM-PHDR-WRONG-PHDRS %s < %t1-error
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- header PT_PHDR PHDRS;
- text PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) }
-}
-
-/*
-PROGRAM-PHDR-WRONG-PHDRS: Program header has invalid PHDRS attribute
-*/
diff --git a/test/old-elf/linkerscript/phdrs-same-flags.test b/test/old-elf/linkerscript/phdrs-same-flags.test
deleted file mode 100644
index e39f61881033..000000000000
--- a/test/old-elf/linkerscript/phdrs-same-flags.test
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-Test sections put to same segment with FLAGS attribute set.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix FLAGS-PHDRS-SECS %s
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix FLAGS-PHDRS-HDRS %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- text PT_LOAD FLAGS(0x4);
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) }
-}
-
-/*
-FLAGS-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000b0
-FLAGS-PHDRS-SECS: .data {{[0-9a-f]+}} 00000000004000dc
-
-FLAGS-PHDRS-HDRS: ProgramHeader {
-FLAGS-PHDRS-HDRS: Type: PT_LOAD (0x1)
-FLAGS-PHDRS-HDRS: VirtualAddress: 0x400000
-FLAGS-PHDRS-HDRS: Flags [ (0x4)
-FLAGS-PHDRS-HDRS: PF_R (0x4)
-FLAGS-PHDRS-HDRS: ]
-FLAGS-PHDRS-HDRS: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs-same.test b/test/old-elf/linkerscript/phdrs-same.test
deleted file mode 100644
index 92b3ad3909c3..000000000000
--- a/test/old-elf/linkerscript/phdrs-same.test
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Test sections put to same segment.
-
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %t.o -static -o %t1
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix SAME-PHDRS-SECS %s
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix SAME-PHDRS-HDRS %s
-*/
-
-ENTRY(_start)
-
-PHDRS
-{
- text PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :text
- .data : { *(.data) }
-}
-
-/*
-SAME-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000b0
-SAME-PHDRS-SECS: .data {{[0-9a-f]+}} 00000000004000dc
-
-SAME-PHDRS-HDRS: ProgramHeader {
-SAME-PHDRS-HDRS: Type: PT_LOAD (0x1)
-SAME-PHDRS-HDRS: VirtualAddress: 0x400000
-SAME-PHDRS-HDRS: Flags [ (0x5)
-SAME-PHDRS-HDRS: PF_R (0x4)
-SAME-PHDRS-HDRS: PF_X (0x1)
-SAME-PHDRS-HDRS: ]
-SAME-PHDRS-HDRS: }
-*/
diff --git a/test/old-elf/linkerscript/phdrs/sections-empty-phdrs.script b/test/old-elf/linkerscript/phdrs/sections-empty-phdrs.script
deleted file mode 100644
index ac30df78d5e1..000000000000
--- a/test/old-elf/linkerscript/phdrs/sections-empty-phdrs.script
+++ /dev/null
@@ -1,11 +0,0 @@
-ENTRY(_start)
-
-PHDRS
-{
-}
-
-SECTIONS
-{
- .text : { *(.text) }
- .data : { *(.data) }
-}
diff --git a/test/old-elf/linkerscript/phdrs/sections-no-phdrs.script b/test/old-elf/linkerscript/phdrs/sections-no-phdrs.script
deleted file mode 100644
index b8848cd3ab0d..000000000000
--- a/test/old-elf/linkerscript/phdrs/sections-no-phdrs.script
+++ /dev/null
@@ -1,7 +0,0 @@
-ENTRY(_start)
-
-SECTIONS
-{
- .text : { *(.text) }
- .data : { *(.data) }
-}
diff --git a/test/old-elf/linkerscript/phdrs/sections-none-phdrs.script b/test/old-elf/linkerscript/phdrs/sections-none-phdrs.script
deleted file mode 100644
index 4b240245d2b2..000000000000
--- a/test/old-elf/linkerscript/phdrs/sections-none-phdrs.script
+++ /dev/null
@@ -1,11 +0,0 @@
-ENTRY(_start)
-
-PHDRS
-{
-}
-
-SECTIONS
-{
- .text : { *(.text) } :NONE
- .data : { *(.data) }
-}
diff --git a/test/old-elf/linkerscript/phdrs/undef-empty-phdrs.script b/test/old-elf/linkerscript/phdrs/undef-empty-phdrs.script
deleted file mode 100644
index f92b452d2346..000000000000
--- a/test/old-elf/linkerscript/phdrs/undef-empty-phdrs.script
+++ /dev/null
@@ -1,11 +0,0 @@
-ENTRY(_start)
-
-PHDRS
-{
-}
-
-SECTIONS
-{
- .text : { *(.text) }
- .data : { *(.data) } :phdr
-}
diff --git a/test/old-elf/linkerscript/phdrs/undef-id-phdrs.script b/test/old-elf/linkerscript/phdrs/undef-id-phdrs.script
deleted file mode 100644
index 8ac56695f00a..000000000000
--- a/test/old-elf/linkerscript/phdrs/undef-id-phdrs.script
+++ /dev/null
@@ -1,12 +0,0 @@
-ENTRY(_start)
-
-PHDRS
-{
- phdr PT_LOAD;
-}
-
-SECTIONS
-{
- .text : { *(.text) } :phdr_wrong
- .data : { *(.data) }
-}
diff --git a/test/old-elf/linkerscript/phdrs/undef-no-phdrs.script b/test/old-elf/linkerscript/phdrs/undef-no-phdrs.script
deleted file mode 100644
index d3ee5bdebe41..000000000000
--- a/test/old-elf/linkerscript/phdrs/undef-no-phdrs.script
+++ /dev/null
@@ -1,7 +0,0 @@
-ENTRY(_start)
-
-SECTIONS
-{
- .text : { *(.text) } :phdr
- .data : { *(.data) }
-}
diff --git a/test/old-elf/linkerscript/sections-order.test b/test/old-elf/linkerscript/sections-order.test
deleted file mode 100644
index 4d23f5eb9d54..000000000000
--- a/test/old-elf/linkerscript/sections-order.test
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-Tests a simple linker script that changes the order of output sections and
-also changes the address of output sections by using simple expressions.
-
-This test uses three X86-64 input objects, prog1.o, prog2.o and prog3.o,
-which were created with the following C or assembly code:
-
-*** prog1.o:
-
-(command line clang -c prog1.c -o prog1.o)
-
-const char *prog2();
-void write(int, const char *, int);
-
-int main() {
- write(1, prog2(), 14);
-}
-
-*** prog2.o:
-
-(command line clang -c prog2.c -o prog2.o)
-
-const char *prog2() {
- return "Hello, world!\n";
-}
-
-*** prog3.o:
-
-(command line clang -c prog3.S -o prog3.o)
-
- .globl write
-write:
- mov $1, %eax
- syscall
- ret
-
- .globl _start
-_start:
- call main
- mov $60, %eax
- syscall
- ret
-
-We use the following linker script for this test:
-*/
-
-ENTRY(_start)
-
-SECTIONS
-{
- . = 0x500000;
- .text : { prog1.o(.text) }
- .mystring : { prog2.o(.rodata.str1.1) }
- . = . + 0x6000;
- .text.2 : {prog3.o(.text) prog2.o(.text) }
-}
-
-/*
-RUN: mkdir -p %T
-RUN: yaml2obj -format=elf %p/Inputs/prog1.o.yaml -o=%T/prog1.o
-RUN: yaml2obj -format=elf %p/Inputs/prog2.o.yaml -o=%T/prog2.o
-RUN: yaml2obj -format=elf %p/Inputs/prog3.o.yaml -o=%T/prog3.o
-RUN: cd %T
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s prog1.o prog2.o prog3.o \
-RUN: -static -o %t1
-RUN: llvm-readobj -s %t1 | FileCheck -check-prefix CHECKSECTIONS %s
-
-CHECKSECTIONS: Index: 1
-CHECKSECTIONS: Name: .text
-CHECKSECTIONS: Address: 0x500000
-CHECKSECTIONS: Size: 33
-
-CHECKSECTIONS: Index: 2
-CHECKSECTIONS: Name: .mystring
-CHECKSECTIONS: Address: 0x500021
-CHECKSECTIONS: Size: 15
-
-CHECKSECTIONS: Index: 3
-CHECKSECTIONS: Name: .text.2
-CHECKSECTIONS: Address: 0x506030
-CHECKSECTIONS: Size: 48
-
-RUN: llvm-readobj -symbols %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-CHECKSYMS: Name: main
-CHECKSYMS-NEXT: Value: 0x500000
-
-CHECKSYMS: Name: write
-CHECKSYMS-NEXT: Value: 0x506030
-
-CHECKSYMS: Name: _start
-CHECKSYMS-NEXT: Value: 0x506038
-
-CHECKSYMS: Name: prog2
-CHECKSYMS-NEXT: Value: 0x506050
-
-RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix CHECKPHDRS %s
-
-CHECKPHDRS: Type: PT_LOAD (0x1)
-CHECKPHDRS: Offset: 0x1000
-CHECKPHDRS-NEXT: VirtualAddress: 0x500000
-CHECKPHDRS-NEXT: PhysicalAddress: 0x500000
-CHECKPHDRS-NEXT: FileSize: 48
-CHECKPHDRS-NEXT: MemSize: 48
-
-CHECKPHDRS: Type: PT_LOAD (0x1)
-CHECKPHDRS: Offset: 0x2030
-CHECKPHDRS-NEXT: VirtualAddress: 0x506030
-CHECKPHDRS-NEXT: PhysicalAddress: 0x506030
-CHECKPHDRS-NEXT: FileSize: 168
-CHECKPHDRS-NEXT: MemSize: 168
-*/
diff --git a/test/old-elf/linkerscript/sections-with-wildcards.test b/test/old-elf/linkerscript/sections-with-wildcards.test
deleted file mode 100644
index a390a2b2d36a..000000000000
--- a/test/old-elf/linkerscript/sections-with-wildcards.test
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-Tests a linker script that uses the SECTIONS command with rules containing
-wildcards and simple SORT directives. It also tests that the linker script
-evaluates the expressions in the same order as the one written in the script
-file.
-
-This test uses three X86-64 input objects, prog1.o, prog2.o and prog3.o,
-which were created with the following C or assembly code:
-
-*** prog1.o:
-
-(command line clang -c prog1.c -o prog1.o)
-
-const char *prog2();
-void write(int, const char *, int);
-
-int main() {
- write(1, prog2(), 14);
-}
-
-*** prog2.o:
-
-(command line clang -c prog2.c -o prog2.o)
-
-const char *prog2() {
- return "Hello, world!\n";
-}
-
-*** prog3.o:
-
-(command line clang -c prog3.S -o prog3.o)
-
- .globl write
-write:
- mov $1, %eax
- syscall
- ret
-
- .globl _start
-_start:
- call main
- mov $60, %eax
- syscall
- ret
-
-We use the following linker script for this test:
-*/
-
-ENTRY(_start)
-
-SECTIONS
-{
- my_start_addr = 0x500000;
- my_symbol = my_start_addr;
- . = my_symbol;
- .foo : { SORT(*)(.text .rodata*) }
-}
-
-/*
-RUN: mkdir -p %T
-RUN: yaml2obj -format=elf %p/Inputs/prog1.o.yaml -o=%T/p1.o
-RUN: yaml2obj -format=elf %p/Inputs/prog2.o.yaml -o=%T/p2.o
-RUN: yaml2obj -format=elf %p/Inputs/prog3.o.yaml -o=%T/p3.o
-RUN: cd %T
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s p1.o p2.o p3.o \
-RUN: -static -o %t1
-RUN: llvm-readobj -s %t1 | FileCheck -check-prefix CHECKSECTIONS %s
-
-CHECKSECTIONS: Index: 1
-CHECKSECTIONS: Name: .foo
-CHECKSECTIONS: Address: 0x500000
-CHECKSECTIONS: Size: 101
-
-RUN: llvm-readobj -symbols %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-CHECKSYMS: Name: main
-CHECKSYMS-NEXT: Value: 0x500000
-
-CHECKSYMS: Name: prog2
-CHECKSYMS-NEXT: Value: 0x500030
-
-CHECKSYMS: Name: write
-CHECKSYMS-NEXT: Value: 0x500050
-
-CHECKSYMS: Name: _start
-CHECKSYMS-NEXT: Value: 0x500058
-*/
diff --git a/test/old-elf/linkerscript/symbol-definition-so.test b/test/old-elf/linkerscript/symbol-definition-so.test
deleted file mode 100644
index 15b22f6f581f..000000000000
--- a/test/old-elf/linkerscript/symbol-definition-so.test
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-We test whether we can define symbols in a linker script and have them exported
-to the output file symbol table. This test is the same as symbol-definition.test
-but make checking in case of shared library linking.
-
-We use the following linker script for this test:
-*/
-
-SECTIONS
-{
- .text : { *(.text) }
- MYSTRING = .;
- .data : { *(.data) }
-}
-
-/*
-RUN: yaml2obj -format=elf %p/Inputs/simple-pic.o.yaml -o=%t.o
-
-RUN: lld -flavor old-gnu -target x86_64 -shared -T %s %t.o -o %t.so
-RUN: llvm-readobj -s -symbols %t.so | FileCheck -check-prefix CHECKSYMS %s
-
-CHECKSYMS: Name: .data
-CHECKSYMS-NEXT: Type: SHT_PROGBITS
-CHECKSYMS-NEXT: Flags [
-CHECKSYMS-NEXT: SHF_ALLOC
-CHECKSYMS-NEXT: SHF_WRITE
-CHECKSYMS-NEXT: ]
-CHECKSYMS-NEXT: Address: 0x401060
-
-CHECKSYMS: Name: MYSTRING
-CHECKSYMS-NEXT: Value: 0x401060
-*/
diff --git a/test/old-elf/linkerscript/symbol-definition.test b/test/old-elf/linkerscript/symbol-definition.test
deleted file mode 100644
index daa3b17e9965..000000000000
--- a/test/old-elf/linkerscript/symbol-definition.test
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-We test whether we can define symbols in a linker script and have them exported
-to the output file symbol table.
-
-This test uses a single X86-64 input object, simple.o, created with the
-following X86-64 assembly code:
-
-*** simple.S:
-
-(command line clang -c simple.S -o simple.o)
-
- .text
- main:
- mov $1, %eax
- movq $1, %rdi
- movq $msg, %rsi
- movq $14, %rdx
- syscall
- ret
-
- .globl _start
- _start:
- call main
- mov $60, %eax
- syscall
- ret
-
- .data
- msg: .asciz "Hello, World!\n"
-
-
-We use the following linker script for this test:
-*/
-
-ENTRY(_start)
-
-SECTIONS
-{
- . = 0x500000;
- .text : { *(.text) }
- MYSTRING = .;
- .data : { *(.data) }
-}
-
-/*
-RUN: mkdir -p %T
-RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%T/simple.o
-
-RUN: lld -flavor old-gnu -target x86_64 -T %s %T/simple.o -static -o %t1
-RUN: llvm-readobj -symbols %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-CHECKSYMS: Name: MYSTRING
-CHECKSYMS-NEXT: Value: 0x501000
-*/
diff --git a/test/old-elf/linkerscript/valid-script-cli.objtxt b/test/old-elf/linkerscript/valid-script-cli.objtxt
deleted file mode 100644
index a7342c41f529..000000000000
--- a/test/old-elf/linkerscript/valid-script-cli.objtxt
+++ /dev/null
@@ -1,23 +0,0 @@
-# Check that the linker script inputs are accepted properly.
-
-# RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/valid.ls -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-# RUN: lld -flavor old-gnu -target x86_64 -T %p/Inputs/valid.ls -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-# RUN: lld -flavor old-gnu -target x86_64 --script=%p/Inputs/valid.ls -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-# RUN: lld -flavor old-gnu -target x86_64 -L%p/Inputs/ -l:valid.ls -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-defined-atoms:
- - name: main
- scope: global
- content: [ B8, 00, 00, 00, 00, C7, 44, 24, FC, 00, 00, 00, 00, C3 ]
- alignment: 16
- section-choice: custom-required
- section-name: .text
-
-# CHECK: _entry_point
diff --git a/test/old-elf/loginputfiles.test b/test/old-elf/loginputfiles.test
deleted file mode 100644
index f1b78558e9c5..000000000000
--- a/test/old-elf/loginputfiles.test
+++ /dev/null
@@ -1,28 +0,0 @@
-# Tests functionality of -t
-#
-# Tests generated using the source files below
-# main file
-# int main()
-# {
-# fn();
-# return 0;
-# }
-#
-# archive file
-# int fn()
-# {
-# return 0;
-# }
-#
-# int fn1()
-# {
-# return 0;
-# }
-# gcc -c main.c fn.c fn1.c
-
-RUN: lld -flavor old-gnu -target x86_64-linux \
-RUN: %p/Inputs/mainobj.x86_64 %p/Inputs/libfnarchive.a -t --noinhibit-exec 2>&1 | \
-RUN: FileCheck -check-prefix INPUTFILES %s
-
-#INPUTFILES: mainobj.x86_64
-#INPUTFILES: libfnarchive.a(fn.o)
diff --git a/test/old-elf/mergeatoms.test b/test/old-elf/mergeatoms.test
deleted file mode 100644
index ec83ac2b8849..000000000000
--- a/test/old-elf/mergeatoms.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# Tests that atoms are merged by testing it with --merge-strings option
-RUN: lld -flavor old-gnu -target x86_64-linux --merge-strings -o %t1 \
-RUN: %p/Inputs/foo.o.x86-64 %p/Inputs/bar.o.x86-64 -e bar1
-RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=mergeAtoms %s
-
-mergeAtoms: 62617200 666f6f00 bar.foo.
diff --git a/test/old-elf/mergeconstants.test b/test/old-elf/mergeconstants.test
deleted file mode 100644
index 719ae8a8b24e..000000000000
--- a/test/old-elf/mergeconstants.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# The test checks for mergeable strings that appear in the object file
-RUN: lld -flavor old-gnu --merge-strings --output-filetype=yaml -target x86_64 \
-RUN: %p/Inputs/constants-merge.x86-64 --noinhibit-exec \
-RUN: | FileCheck -check-prefix=mergeAtoms %s
-
-mergeAtoms: - ref-name: [[CONSTANT:[-a-zA-Z0-9_]+]]
-mergeAtoms: type: constant
-mergeAtoms: content: [ 62, 61, 72, 66, 6F, 6F, 00 ]
-mergeAtoms: merge: by-content
-mergeAtoms: section-choice: custom-required
-mergeAtoms: section-name: .rodata.str1.1
-mergeAtoms: - name: foo
-mergeAtoms: scope: global
-mergeAtoms: type: data
-mergeAtoms: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-mergeAtoms: alignment: 8
-mergeAtoms: references:
-mergeAtoms: - kind: R_X86_64_64
-mergeAtoms: offset: 3
-mergeAtoms: target: [[CONSTANT]]
diff --git a/test/old-elf/mergeglobalatoms.test b/test/old-elf/mergeglobalatoms.test
deleted file mode 100644
index bf8dbf7593f0..000000000000
--- a/test/old-elf/mergeglobalatoms.test
+++ /dev/null
@@ -1,11 +0,0 @@
-# ELF files can have mergeable strings which are global!, treat them as global
-# defined atoms
-RUN: lld -flavor old-gnu --output-filetype=yaml %p/Inputs/globalconst.o.x86-64 \
-RUN: --noinhibit-exec -target x86_64 | FileCheck -check-prefix=globalatoms %s
-
-globalatoms: - name: mystr
-globalatoms: scope: global
-globalatoms: type: constant
-globalatoms: content: [ 66, 6F, 6F, 62, 61, 72, 00 ]
-globalatoms: section-choice: custom-required
-globalatoms: section-name: .rodata.str1.1
diff --git a/test/old-elf/no-unique-section-names.test b/test/old-elf/no-unique-section-names.test
deleted file mode 100644
index 4c5f79588dbe..000000000000
--- a/test/old-elf/no-unique-section-names.test
+++ /dev/null
@@ -1,19 +0,0 @@
-# Check handling object files with non-unique named sections.
-
-RUN: lld -flavor old-gnu -target x86_64-linux -shared -o %t \
-RUN: %p/Inputs/no-unique-section-names.x86-64
-RUN: llvm-objdump -s %p/Inputs/no-unique-section-names.x86-64 %t \
-RUN: | FileCheck %s
-
-CHECK: Contents of section .group:
-CHECK-NEXT: 0000 01000000 08000000
-CHECK-NEXT: Contents of section .text:
-CHECK-NEXT: 0000 [[A1:[0-9a-f]+]] [[A2:[0-9a-f]+]] [[A3:[0-9a-f]+]]
-CHECK-NEXT: Contents of section .group:
-CHECK-NEXT: 0000 01000000 0a000000
-CHECK-NEXT: Contents of section .text:
-CHECK-NEXT: 0000 [[B1:[0-9a-f]+]] [[B2:[0-9a-f]+]] [[B3:[0-9a-f]+]]
-
-CHECK: Contents of section .text:
-CHECK: {{[0-9a-f]+}} [[A1]] [[A2]] [[A3]]
-CHECK-NEXT: {{[0-9a-f]+}} [[B1]] [[B2]] [[B3]]
diff --git a/test/old-elf/note.test b/test/old-elf/note.test
deleted file mode 100644
index aff01c3e5b2a..000000000000
--- a/test/old-elf/note.test
+++ /dev/null
@@ -1,50 +0,0 @@
-# Check that the linker is not ignoring input sections.
-# RUN: yaml2obj -format=elf %s > %t.obj
-# RUN: lld -flavor old-gnu -target x86_64 %t.obj -o %t.exe --noinhibit-exec
-# RUN: llvm-readobj -s %t.exe | FileCheck %s
-
-# CHECK: Section {
-# CHECK: Name: .note
-# CHECK-NEXT: Type: SHT_NOTE
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .note
- Type: SHT_NOTE
- AddressAlign: 0x0000000000000001
- Content: '00'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .note
- Type: STT_SECTION
- Section: .note
-...
diff --git a/test/old-elf/options/dynamic-linker.test b/test/old-elf/options/dynamic-linker.test
deleted file mode 100644
index 6b56f17c677d..000000000000
--- a/test/old-elf/options/dynamic-linker.test
+++ /dev/null
@@ -1,17 +0,0 @@
-# This tests the functionality of specifying dynamic-linker argument in the
-# command line
-RUN: lld -flavor old-gnu -target x86_64 --dynamic-linker="/xyz.so" \
-RUN: %p/../Inputs/foo.o.x86-64 --noinhibit-exec -o %t
-RUN: llvm-objdump -s %t | FileCheck -check-prefix=DYNAMICINTERP1 %s
-RUN: lld -flavor old-gnu -target x86_64 --dynamic-linker="" \
-RUN: %p/../Inputs/foo.o.x86-64 --noinhibit-exec -o %t1
-RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=DYNAMICINTERP2 %s
-RUN: lld -flavor old-gnu -target x86_64 -dynamic-linker /xyz.so \
-RUN: %p/../Inputs/foo.o.x86-64 --noinhibit-exec -o %t2
-RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=DYNAMICINTERP1 %s
-
-DYNAMICINTERP1:Contents of section .interp:
-DYNAMICINTERP1: 400158 2f78797a 2e736f00 /xyz.so.
-DYNAMICINTERP2:Contents of section .interp:
-DYNAMICINTERP2: 400158 00
-
diff --git a/test/old-elf/options/target-specific-args.test b/test/old-elf/options/target-specific-args.test
deleted file mode 100644
index ec5edf0ad62e..000000000000
--- a/test/old-elf/options/target-specific-args.test
+++ /dev/null
@@ -1,5 +0,0 @@
-# Test of target specific options
-# RUN: lld -flavor old-gnu -target x86_64 --target1-rel \
-# RUN: %p/../Inputs/foo.o.x86-64 --noinhibit-exec -o %t 2>&1 | FileCheck %s
-
-# CHECK: warning: ignoring unsupported ARM/ELF specific argument: --target1-rel
diff --git a/test/old-elf/phdr.test b/test/old-elf/phdr.test
deleted file mode 100644
index c8b3664d025f..000000000000
--- a/test/old-elf/phdr.test
+++ /dev/null
@@ -1,99 +0,0 @@
-# This test checks emission for program header for ELF binaries
-RUN: lld -flavor old-gnu -target i386-linux -o %t1 -e main %p/Inputs/phdr.i386 \
-RUN: && llvm-readobj -program-headers %t1 | FileCheck -check-prefix=I386 %s
-RUN: lld -flavor old-gnu -target x86_64-linux -o %t1 -e _start %p/Inputs/relocs.x86-64 -static \
-RUN: && llvm-objdump -p %t1 | FileCheck %s -check-prefix=X86_64
-
-
-I386: ProgramHeaders [
-I386-NEXT: ProgramHeader {
-I386-NEXT: Type: PT_PHDR (0x6)
-I386-NEXT: Offset: 0x34
-I386-NEXT: VirtualAddress: 0x34
-I386-NEXT: PhysicalAddress: 0x34
-I386-NEXT: FileSize: 224
-I386-NEXT: MemSize: 224
-I386-NEXT: Flags [ (0x5)
-I386-NEXT: PF_R (0x4)
-I386-NEXT: PF_X (0x1)
-I386-NEXT: ]
-I386-NEXT: Alignment: 8
-I386-NEXT: }
-I386-NEXT: ProgramHeader {
-I386-NEXT: Type: PT_INTERP (0x3)
-I386-NEXT: Offset: 0x114
-I386-NEXT: VirtualAddress: 0x114
-I386-NEXT: PhysicalAddress: 0x114
-I386-NEXT: FileSize: 28
-I386-NEXT: MemSize: 28
-I386-NEXT: Flags [ (0x4)
-I386-NEXT: PF_R (0x4)
-I386-NEXT: ]
-I386-NEXT: Alignment: 1
-I386-NEXT: }
-I386-NEXT: ProgramHeader {
-I386-NEXT: Type: PT_LOAD (0x1)
-I386-NEXT: Offset: 0x0
-I386-NEXT: VirtualAddress: 0x0
-I386-NEXT: PhysicalAddress: 0x0
-I386-NEXT: FileSize: 556
-I386-NEXT: MemSize: 556
-I386-NEXT: Flags [ (0x5)
-I386-NEXT: PF_R (0x4)
-I386-NEXT: PF_X (0x1)
-I386-NEXT: ]
-I386-NEXT: Alignment: 4096
-I386-NEXT: }
-I386-NEXT: ProgramHeader {
-I386-NEXT: Type: PT_LOAD (0x1)
-I386-NEXT: Offset: 0x1000
-I386-NEXT: VirtualAddress: 0x1000
-I386-NEXT: PhysicalAddress: 0x1000
-I386-NEXT: FileSize: 260
-I386-NEXT: MemSize: 260
-I386-NEXT: Flags [ (0x6)
-I386-NEXT: PF_R (0x4)
-I386-NEXT: PF_W (0x2)
-I386-NEXT: ]
-I386-NEXT: Alignment: 4096
-I386-NEXT: }
-I386-NEXT: ProgramHeader {
-I386-NEXT: Type: PT_LOAD (0x1)
-I386-NEXT: Offset: 0x4000
-I386-NEXT: VirtualAddress: 0x4000
-I386-NEXT: PhysicalAddress: 0x4000
-I386-NEXT: FileSize: 4
-I386-NEXT: MemSize: 8
-I386-NEXT: Flags [ (0x6)
-I386-NEXT: PF_R (0x4)
-I386-NEXT: PF_W (0x2)
-I386-NEXT: ]
-I386-NEXT: Alignment: 16384
-I386-NEXT: }
-I386-NEXT: ProgramHeader {
-I386-NEXT: Type: PT_DYNAMIC (0x2)
-I386-NEXT: Offset: 0x1FC
-I386-NEXT: VirtualAddress: 0x1FC
-I386-NEXT: PhysicalAddress: 0x1FC
-I386-NEXT: FileSize: 48
-I386-NEXT: MemSize: 48
-I386-NEXT: Flags [ (0x4)
-I386-NEXT: PF_R (0x4)
-I386-NEXT: ]
-I386-NEXT: Alignment: 4
-I386-NEXT: }
-I386-NEXT: ProgramHeader {
-I386-NEXT: Type: PT_GNU_EH_FRAME (0x6474E550)
-I386-NEXT: Offset: 0x1F4
-I386-NEXT: VirtualAddress: 0x1F4
-I386-NEXT: PhysicalAddress: 0x1F4
-I386-NEXT: FileSize: 8
-I386-NEXT: MemSize: 8
-I386-NEXT: Flags [ (0x4)
-I386-NEXT: PF_R (0x4)
-I386-NEXT: ]
-I386-NEXT: Alignment: 4
-I386-NEXT: }
-
-X86_64: LOAD off 0x0000000000000000
-X86_64: LOAD off 0x0000000000001000
diff --git a/test/old-elf/quickdata.test b/test/old-elf/quickdata.test
deleted file mode 100644
index 85ad23d0b8e9..000000000000
--- a/test/old-elf/quickdata.test
+++ /dev/null
@@ -1,15 +0,0 @@
-RUN: lld -flavor old-gnu -target hexagon --output-filetype=yaml %p/Inputs/quickdata-test.elf-hexagon \
-RUN: --noinhibit-exec | FileCheck %s -check-prefix hexagon
-
-hexagon: - name: ac1
-hexagon: scope: global
-hexagon: type: zero-fill-quick
-hexagon: size: 1
-hexagon: merge: as-tentative
-hexagon: - name: init
-hexagon: scope: global
-hexagon: type: quick-data
-hexagon: - name: bss1
-hexagon: scope: global
-hexagon: type: zero-fill-quick
-
diff --git a/test/old-elf/reloc.test b/test/old-elf/reloc.test
deleted file mode 100644
index f8cb056e03da..000000000000
--- a/test/old-elf/reloc.test
+++ /dev/null
@@ -1,38 +0,0 @@
-RUN: lld -flavor old-gnu -target i386 --merge-strings -r --output-filetype=yaml \
-RUN: %p/Inputs/reloc-test.elf-i386 | FileCheck %s -check-prefix ELF-i386
-
-ELF-i386: defined-atoms:
-ELF-i386: - ref-name: [[STRNAMEA:[-a-zA-Z0-9_]+]]
-ELF-i386: type: constant
-ELF-i386: content: [ 68, 65, 6C, 6C, 6F, 20, 77, 6F, 72, 6C, 64, 00 ]
-ELF-i386: merge: by-content
-ELF-i386: - ref-name: [[STRNAMEB:[-a-zA-Z0-9_]+]]
-ELF-i386: alignment: 16
-ELF-i386: section-choice: custom-required
-ELF-i386: section-name: .text.startup
-ELF-i386: references:
-ELF-i386: - kind: layout-after
-ELF-i386: offset: 0
-ELF-i386: target: main
-ELF-i386: - name: main
-ELF-i386: scope: global
-ELF-i386: content: [ 55, 89, E5, 83, E4, F0, 83, EC, 10, C7, 04, 24,
-ELF-i386: 00, 00, 00, 00, E8, FC, FF, FF, FF, 31, C0, C9,
-ELF-i386: C3 ]
-ELF-i386: alignment: 16
-ELF-i386: section-choice: custom-required
-ELF-i386: section-name: .text.startup
-ELF-i386: references:
-ELF-i386: - kind: R_386_32
-ELF-i386: offset: 12
-ELF-i386: target: [[STRNAMEA]]
-ELF-i386: - kind: R_386_PC32
-ELF-i386: offset: 17
-ELF-i386: target: puts
-ELF-i386: addend: 252
-ELF-i386: undefined-atoms:
-ELF-i386: - name: puts
-ELF-i386: absolute-atoms:
-ELF-i386: - name: test.c
-ELF-i386: scope: static
-ELF-i386: value: 0x0000000000000000
diff --git a/test/old-elf/responsefile.test b/test/old-elf/responsefile.test
deleted file mode 100644
index 89e9ffd015bd..000000000000
--- a/test/old-elf/responsefile.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# RUN: not lld -flavor old-gnu --abc @%p/Inputs/responsefile --baz >& %t.log
-# RUN: FileCheck %s < %t.log
-
-CHECK: warning: ignoring unknown argument: --abc
-CHECK: warning: ignoring unknown argument: --inresponsefile
-CHECK: warning: ignoring unknown argument: --baz
diff --git a/test/old-elf/rodata.test b/test/old-elf/rodata.test
deleted file mode 100644
index 12d9abb2a194..000000000000
--- a/test/old-elf/rodata.test
+++ /dev/null
@@ -1,5 +0,0 @@
-RUN: lld -flavor old-gnu -target x86_64-linux -o %t %p/Inputs/constdata.x86-64 \
-RUN: -static -e _start
-RUN: llvm-objdump -s %t | FileCheck %s
-
-CHECK: Hellooooooooo
diff --git a/test/old-elf/rosegment.test b/test/old-elf/rosegment.test
deleted file mode 100644
index 675dc3861867..000000000000
--- a/test/old-elf/rosegment.test
+++ /dev/null
@@ -1,26 +0,0 @@
-# Tests that the option --rosegment produces an output file with a separate
-# segment created for read only data.
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/rodata.o -o %t1.elf \
-RUN: --noinhibit-exec
-RUN: lld -flavor old-gnu -target x86_64 %p/Inputs/rodata.o --rosegment -o %t2.elf \
-RUN: --noinhibit-exec
-RUN: llvm-readobj -program-headers %t1.elf | FileCheck %s -check-prefix=NORO-SEGMENT
-RUN: llvm-readobj -program-headers %t2.elf | FileCheck %s -check-prefix=RO-SEGMENT
-
-#NORO-SEGMENT: Type: PT_PHDR
-#NORO-SEGMENT: Type: PT_INTERP
-#NORO-SEGMENT: Type: PT_LOAD
-#NORO-SEGMENT: Type: PT_LOAD
-#NORO-SEGMENT: Type: PT_DYNAMIC
-#NORO-SEGMENT: Type: PT_GNU_EH_FRAME
-
-#RO-SEGMENT: Type: PT_PHDR
-#RO-SEGMENT: Type: PT_INTERP
-#RO-SEGMENT: Type: PT_LOAD
-#RO-SEGMENT: Type: PT_LOAD
-#RO-SEGMENT: Flags [
-#RO-SEGMENT: PF_R (0x4)
-#RO-SEGMENT: ]
-#RO-SEGMENT: Type: PT_LOAD
-#RO-SEGMENT: Type: PT_DYNAMIC
-#RO-SEGMENT: Type: PT_GNU_EH_FRAME
diff --git a/test/old-elf/sectionGroups/sectiongroup-new-members.test b/test/old-elf/sectionGroups/sectiongroup-new-members.test
deleted file mode 100644
index dff1a96b07ee..000000000000
--- a/test/old-elf/sectionGroups/sectiongroup-new-members.test
+++ /dev/null
@@ -1,151 +0,0 @@
-# Checks that the linker picks the first group in the output file when the file
-# have some members dont appear in the first group.
-# 1a.s
-# ------
-#
-# .section .text,"axG",%progbits,foo_group,comdat
-# .weak foo
-#foo:
-# .word 0
-# 1b.s
-# -----
-# .section .text,"axG",%progbits,foo_group,comdat
-# .global foo
-# .global bar
-#foo:
-# .word 0
-#bar:
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.group1a.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.group1b.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.group1a.o %t.group1b.o \
-#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor old-gnu -target x86_64 %t.group1a.o %t.group1b.o \
-#RUN: --noinhibit-exec -o %t2.out
-#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
-#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
-#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
-#CHECKGROUP: - name: foo
-#CHECKGROUP: scope: global
-#CHECKGROUP: merge: as-weak
-#CHECKGROUP: section-name: .text
-#CHECKGROUP: - name: foo_group
-#CHECKGROUP: scope: global
-#CHECKGROUP: type: group-comdat
-#CHECKGROUP: section-choice: custom-required
-#CHECKGROUP: section-name: .group
-#CHECKGROUP: permissions: ---
-#CHECKGROUP: references:
-#CHECKGROUP: - kind: group-child
-#CHECKGROUP: offset: 0
-#CHECKGROUP: target: foo
-#CHECKGROUPSECTIONS: Section {
-#CHECKGROUPSECTIONS: Name: .text
-#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
-#CHECKGROUPSECTIONS: Flags [ (0x6)
-#CHECKGROUPSECTIONS: SHF_ALLOC (0x2)
-#CHECKGROUPSECTIONS: SHF_EXECINSTR (0x4)
-#CHECKGROUPSECTIONS: ]
-#CHECKGROUPSECTIONS: Size: 2
-#CHECKGROUPSECTIONS: AddressAlignment: 1
-#CHECKGROUPSECTIONS: }
-#CHECKSYMBOLS: Name: foo
-#CHECKSYMBOLS: Type: Function
-#CHECKSYMBOLS: Section: .text
-#CHECKSYMBOLS-NOT: Name: bar
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: foo_group
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .text
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '0000'
-Symbols:
- Local:
- - Name: foo_group
- Section: .group
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Weak:
- - Name: foo
- Section: .text
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: foo_group
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .text
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '0000'
-Symbols:
- Local:
- - Name: foo_group
- Section: .group
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: bar
- Section: .text
- Value: 0x0000000000000002
- - Name: foo
- Section: .text
-...
diff --git a/test/old-elf/sectionGroups/sectiongroup-simple.test b/test/old-elf/sectionGroups/sectiongroup-simple.test
deleted file mode 100644
index 57707f84475e..000000000000
--- a/test/old-elf/sectionGroups/sectiongroup-simple.test
+++ /dev/null
@@ -1,144 +0,0 @@
-# Checks that the linker picks the first group in the output file when the file
-# have some members dont appear in the first group.
-# 1a.s
-# ------
-# .section .text,"axG",%progbits,foo_group,comdat
-# .weak foo
-#foo:
-# .word 0
-# 1b.s
-# -----
-# .section .text,"axG",%progbits,foo_group,comdat
-# .global bar
-#bar:
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.group1a.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.group1b.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.group1a.o %t.group1b.o \
-#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor old-gnu -target x86_64 %t.group1a.o %t.group1b.o \
-#RUN: --noinhibit-exec -o %t2.out
-#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
-#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
-#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
-#CHECKGROUP: - name: foo
-#CHECKGROUP: scope: global
-#CHECKGROUP: merge: as-weak
-#CHECKGROUP: section-name: .text
-#CHECKGROUP: - name: foo_group
-#CHECKGROUP: scope: global
-#CHECKGROUP: type: group-comdat
-#CHECKGROUP: section-choice: custom-required
-#CHECKGROUP: section-name: .group
-#CHECKGROUP: permissions: ---
-#CHECKGROUP: references:
-#CHECKGROUP: - kind: group-child
-#CHECKGROUP: offset: 0
-#CHECKGROUP: target: foo
-#CHECKGROUPSECTIONS: Section {
-#CHECKGROUPSECTIONS: Name: .text
-#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
-#CHECKGROUPSECTIONS: Flags [ (0x6)
-#CHECKGROUPSECTIONS: SHF_ALLOC (0x2)
-#CHECKGROUPSECTIONS: SHF_EXECINSTR (0x4)
-#CHECKGROUPSECTIONS: ]
-#CHECKGROUPSECTIONS: Size: 2
-#CHECKGROUPSECTIONS: AddressAlignment: 1
-#CHECKGROUPSECTIONS: }
-#CHECKSYMBOLS: Name: foo
-#CHECKSYMBOLS: Type: Function
-#CHECKSYMBOLS: Section: .text
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: foo_group
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .text
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '0000'
-Symbols:
- Local:
- - Name: foo_group
- Section: .group
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Weak:
- - Name: foo
- Section: .text
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: foo_group
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .text
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
- - Name: foo_group
- Section: .group
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: bar
- Section: .text
-...
diff --git a/test/old-elf/sectionGroups/sectiongroup-undef-member-other.test b/test/old-elf/sectionGroups/sectiongroup-undef-member-other.test
deleted file mode 100644
index 56595e59d8d6..000000000000
--- a/test/old-elf/sectionGroups/sectiongroup-undef-member-other.test
+++ /dev/null
@@ -1,156 +0,0 @@
-# Tests that linker throws an error for an undefined symbol in the section
-# group, which is the same as the signature in the next input file.
-# comdat1.s
-# ------------
-# .section .foo,"axG",@progbits,g1,comdat
-# .word g1
-#comdat2.s
-#-----------
-# .global g1
-# .section .bar,"axG",@progbits,g1,comdat
-#g2:
-# nop
-# .section .car,"axG",@progbits,g1,comdat
-#g3:
-# nop
-#
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.group1a.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.group1b.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.group1a.o %t.group1b.o \
-#RUN: --noinhibit-exec -o %t2.out 2>&1 | FileCheck %s
-#CHECK: Undefined symbol: {{.*}} g1
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - SectionOrType: .rela.foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '0000'
- - Name: .rela.foo
- Type: SHT_RELA
- Flags: [ SHF_GROUP ]
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .foo
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: g1
- Type: R_X86_64_16
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- - Name: .group
- Type: STT_SECTION
- Section: .group
- Global:
- - Name: g1
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .bar
- - SectionOrType: .car
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .bar
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '90'
- - Name: .car
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '90'
-Symbols:
- Local:
- - Name: g2
- Section: .bar
- - Name: g3
- Section: .car
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .bar
- Type: STT_SECTION
- Section: .bar
- - Name: .car
- Type: STT_SECTION
- Section: .car
- - Name: .group
- Type: STT_SECTION
- Section: .group
- Global:
- - Name: g1
- Section: .group
-...
diff --git a/test/old-elf/sectionGroups/sectiongroup-undef-member.test b/test/old-elf/sectionGroups/sectiongroup-undef-member.test
deleted file mode 100644
index 65e9ec7632bf..000000000000
--- a/test/old-elf/sectionGroups/sectiongroup-undef-member.test
+++ /dev/null
@@ -1,142 +0,0 @@
-# Tests that linker throws an error for an undefined symbol in the section
-# group.
-#
-#comdata.s
-#------------
-# .section .foo,"axG",@progbits,g1,comdat
-# .word g1
-#
-#comdatb.s
-#------------
-# .global g1
-# .section .foo,"axG",@progbits,g1,comdat
-#g1:
-# nop
-#
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.group1a.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.group1b.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.group1a.o %t.group1b.o \
-#RUN: --noinhibit-exec -o %t2.out 2>&1 | FileCheck %s
-#CHECK: Undefined symbol: {{.*}} g1
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - SectionOrType: .rela.foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '0000'
- - Name: .rela.foo
- Type: SHT_RELA
- Flags: [ SHF_GROUP ]
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .foo
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: g1
- Type: R_X86_64_16
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- - Name: .group
- Type: STT_SECTION
- Section: .group
- Global:
- - Name: g1
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '90'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- - Name: .group
- Type: STT_SECTION
- Section: .group
- Global:
- - Name: g1
- Section: .foo
-...
diff --git a/test/old-elf/sectionGroups/sectiongroup-with-globalsymbols.test b/test/old-elf/sectionGroups/sectiongroup-with-globalsymbols.test
deleted file mode 100644
index 9f8f80c23605..000000000000
--- a/test/old-elf/sectionGroups/sectiongroup-with-globalsymbols.test
+++ /dev/null
@@ -1,250 +0,0 @@
-# This tests that comdat weak symbol can be overridden by a global symbol.
-# comdat1.s
-#------------------------
-# .weak g1
-# .section .foo,"axG",@progbits,g1,comdat
-#g1:
-# nop
-# .global g2
-#g2:
-# nop
-#!
-#
-#comdat2.s << \!
-#-----------------
-# .global g1
-# .section .foo,"axG",@progbits,g1,comdat
-#g1:
-# nop
-# .global g2
-#g2:
-# nop
-#
-#cat > g1.c << \!
-#int g1() {
-# return 0;
-#}
-#
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.comdat1.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.comdat2.o
-#RUN: yaml2obj -format=elf -docnum 3 %s -o %t.g1.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
-#RUN: %t.g1.o --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor old-gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
-#RUN: %t.g1.o --noinhibit-exec -o %t2.out
-#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
-#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
-#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
-#CHECKGROUP: - name: g2
-#CHECKGROUP: content: [ 90 ]
-#CHECKGROUP: section-choice: custom-required
-#CHECKGROUP: section-name: .foo
-#CHECKGROUP: - name: g1
-#CHECKGROUP: scope: global
-#CHECKGROUP: content: [ 55, 48, 89, E5, 31, C0, 5D, C3 ]
-#CHECKGROUP: alignment: 16
-#CHECKGROUP: section-name: .text
-#CHECKGROUPSECTIONS: Name: .text
-#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
-#CHECKGROUPSECTIONS: Flags [
-#CHECKGROUPSECTIONS: SHF_ALLOC
-#CHECKGROUPSECTIONS: SHF_EXECINSTR
-#CHECKGROUPSECTIONS: ]
-#CHECKGROUPSECTIONS: Size: 8
-#CHECKGROUPSECTIONS: Name: .foo
-#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
-#CHECKGROUPSECTIONS: Flags [
-#CHECKGROUPSECTIONS: SHF_ALLOC
-#CHECKGROUPSECTIONS: SHF_EXECINSTR
-#CHECKGROUPSECTIONS: ]
-#CHECKGROUPSECTIONS: Size: 2
-#CHECKSYMBOLS: Name: g2
-#CHECKSYMBOLS: Section: .foo
-#CHECKSYMBOLS: Name: g1
-#CHECKSYMBOLS: Section: .text
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '9090'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- Global:
- - Name: g2
- Section: .foo
- Value: 0x0000000000000001
- Weak:
- - Name: g1
- Section: .foo
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '9090'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- Global:
- - Name: g1
- Section: .foo
- - Name: g2
- Section: .foo
- Value: 0x0000000000000001
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E531C05DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232393535372920286C6C766D2F7472756E6B203232393536332900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C0708900100001C0000001C000000000000000800000000410E108602430D0600000000000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
-Symbols:
- Local:
- - Name: g1.c
- Type: STT_FILE
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: g1
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000008
-...
diff --git a/test/old-elf/sectionGroups/sectiongroup-with-undef-external-reference.test b/test/old-elf/sectionGroups/sectiongroup-with-undef-external-reference.test
deleted file mode 100644
index 0c5d65ad544f..000000000000
--- a/test/old-elf/sectionGroups/sectiongroup-with-undef-external-reference.test
+++ /dev/null
@@ -1,236 +0,0 @@
-# This tests that comdat undef symbol is overridden by a global symbol.
-# comdat1.s
-#------------------------
-# .global g1
-# .section .foo,"axG",@progbits,g1,comdat
-#g1:
-# .word 5
-#
-#comdat2.s << \!
-#-----------------
-# .global g1
-# .section .foo,"axG",@progbits,g1,comdat
-#g1:
-# nop
-#
-#g1.c
-#-----------
-#extern int g1;
-#int fn() { return g1;}
-#
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.comdat1.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.comdat2.o
-#RUN: yaml2obj -format=elf -docnum 3 %s -o %t.g1.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
-#RUN: %t.g1.o --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor old-gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
-#RUN: %t.g1.o --noinhibit-exec -o %t2.out
-#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
-#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
-#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
-#CHECKGROUP: - name: g1
-#CHECKGROUP: scope: global
-#CHECKGROUP: content: [ 05, 00 ]
-#CHECKGROUP: section-name: .foo
-#CHECKGROUPSECTIONS: Section {
-#CHECKGROUPSECTIONS: Name: .foo
-#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
-#CHECKGROUPSECTIONS: Flags [
-#CHECKGROUPSECTIONS: SHF_ALLOC
-#CHECKGROUPSECTIONS: SHF_EXECINSTR
-#CHECKGROUPSECTIONS: ]
-#CHECKGROUPSECTIONS: Size: 2
-#CHECKGROUPSECTIONS: }
-#CHECKSYMBOLS: Name: g1
-#CHECKSYMBOLS: Section: .foo
-#CHECKSYMBOLS: Name: fn
-#CHECKSYMBOLS: Section: .text
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '0500'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- Global:
- - Name: g1
- Section: .foo
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '90'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- Global:
- - Name: g1
- Section: .foo
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E58B0425000000005DC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000007
- Symbol: g1
- Type: R_X86_64_32S
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232393535372920286C6C766D2F7472756E6B203232393536332900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C0708900100001C0000001C000000000000000D00000000410E108602430D0600000000000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
-Symbols:
- Local:
- - Name: global-g1.c
- Type: STT_FILE
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: fn
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000000D
- - Name: g1
-...
diff --git a/test/old-elf/sectionGroups/sectiongroup-with-undef-signature.test b/test/old-elf/sectionGroups/sectiongroup-with-undef-signature.test
deleted file mode 100644
index 83a69a3828b2..000000000000
--- a/test/old-elf/sectionGroups/sectiongroup-with-undef-signature.test
+++ /dev/null
@@ -1,219 +0,0 @@
-# This tests that comdat undef symbol is overridden by a global symbol.
-# comdat1.s
-#------------------------
-# .section .foo,"axG",@progbits,g1,comdat
-# word g1
-#
-#comdat2.s << \!
-#-----------------
-# .global g1
-# .section .foo,"axG",@progbits,g1,comdat
-#g1:
-# nop
-#
-#global-g1.c
-#-----------
-#int g1=10;
-#
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.comdat1.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.comdat2.o
-#RUN: yaml2obj -format=elf -docnum 3 %s -o %t.g1.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
-#RUN: %t.g1.o --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor old-gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
-#RUN: %t.g1.o --noinhibit-exec -o %t2.out
-#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
-#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
-#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
-#CHECKGROUP: - name: g1
-#CHECKGROUP: scope: global
-#CHECKGROUP: content: [ 0A, 00, 00, 00 ]
-#CHECKGROUP: section-name: .data
-#CHECKGROUPSECTIONS: Name: .foo
-#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
-#CHECKGROUPSECTIONS: Flags [
-#CHECKGROUPSECTIONS: SHF_ALLOC
-#CHECKGROUPSECTIONS: SHF_EXECINSTR
-#CHECKGROUPSECTIONS: ]
-#CHECKGROUPSECTIONS: Size: 2
-#CHECKGROUPSECTIONS: Name: .data
-#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
-#CHECKGROUPSECTIONS: Flags [
-#CHECKGROUPSECTIONS: SHF_ALLOC
-#CHECKGROUPSECTIONS: SHF_WRITE
-#CHECKGROUPSECTIONS: ]
-#CHECKGROUPSECTIONS: Size: 4
-#CHECKSYMBOLS: Name: g1
-#CHECKSYMBOLS: Section: .data
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - SectionOrType: .rela.foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '0000'
- - Name: .rela.foo
- Type: SHT_RELA
- Flags: [ SHF_GROUP ]
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .foo
- Relocations:
- - Offset: 0x0000000000000000
- Symbol: g1
- Type: R_X86_64_16
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- Global:
- - Name: g1
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .group
- Type: SHT_GROUP
- Link: .symtab
- AddressAlign: 0x0000000000000004
- Info: g1
- Members:
- - SectionOrType: GRP_COMDAT
- - SectionOrType: .foo
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .foo
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
- AddressAlign: 0x0000000000000001
- Content: '90'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .foo
- Type: STT_SECTION
- Section: .foo
- Global:
- - Name: g1
- Section: .foo
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: 0A000000
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232393535372920286C6C766D2F7472756E6B203232393536332900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
-Symbols:
- Local:
- - Name: global-g1.c
- Type: STT_FILE
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- Global:
- - Name: g1
- Type: STT_OBJECT
- Section: .data
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/sections.test b/test/old-elf/sections.test
deleted file mode 100644
index f36cad619186..000000000000
--- a/test/old-elf/sections.test
+++ /dev/null
@@ -1,142 +0,0 @@
-# This test checks if sections are created properly in the output that appear in
-# the input
-RUN: lld -flavor old-gnu -target i386 -o %t1 %p/Inputs/section-test.i386 \
-RUN: -static -e baz
-RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=OBJDUMP %s
-RUN: llvm-readobj -h -s -t %t1 | FileCheck -check-prefix=READOBJ %s
-
-OBJDUMP: 0 00000000 0000000000000000
-OBJDUMP: 1 .text 0000000a 0000000000000074 TEXT DATA
-OBJDUMP: 2 .data 00000004 0000000000001000 DATA
-OBJDUMP: 3 .special 00000004 0000000000001004 DATA
-OBJDUMP: 4 .anotherspecial 00000004 0000000000001008 DATA
-OBJDUMP: 5 .bss 00000004 000000000000100c BSS
-OBJDUMP: 6 .shstrtab {{[0-9a-f]+}} 0000000000000000
-OBJDUMP: 7 .symtab {{[0-9a-f]+}} 0000000000000000
-OBJDUMP: 8 .strtab {{[0-9a-f]+}} 0000000000000000
-
-READOBJ: Format: ELF32-i386
-READOBJ: Arch: i386
-READOBJ: AddressSize: 32bit
-READOBJ: ElfHeader {
-READOBJ: Ident {
-READOBJ: DataEncoding: LittleEndian (0x1)
-READOBJ: }
-READOBJ: Machine: EM_386
-READOBJ: }
-
-READOBJ: Sections [
-READOBJ: Section {
-READOBJ: Index: 0
-READOBJ: Name: (0)
-READOBJ: Type: SHT_NULL
-READOBJ: Flags [ (0x0)
-READOBJ: ]
-READOBJ: Address: 0x0
-READOBJ: Size: 0
-READOBJ: }
-READOBJ: Section {
-READOBJ: Index: 1
-READOBJ: Name: .text
-READOBJ: Type: SHT_PROGBITS
-READOBJ: Flags [ (0x6)
-READOBJ: SHF_ALLOC
-READOBJ: SHF_EXECINSTR
-READOBJ: ]
-READOBJ: Address: 0x74
-READOBJ: Size: 10
-READOBJ: AddressAlignment: 4
-READOBJ: }
-READOBJ: Section {
-READOBJ: Index: 2
-READOBJ: Name: .data
-READOBJ: Type: SHT_PROGBITS
-READOBJ: Flags [ (0x3)
-READOBJ: SHF_ALLOC
-READOBJ: SHF_WRITE
-READOBJ: ]
-READOBJ: Address: 0x1000
-READOBJ: Size: 4
-READOBJ: AddressAlignment: 4
-READOBJ: }
-READOBJ: Section {
-READOBJ: Index: 3
-READOBJ: Name: .special
-READOBJ: Type: SHT_PROGBITS
-READOBJ: Flags [ (0x3)
-READOBJ: SHF_ALLOC
-READOBJ: SHF_WRITE
-READOBJ: ]
-READOBJ: Address: 0x1004
-READOBJ: Size: 4
-READOBJ: }
-READOBJ: Section {
-READOBJ: Index: 4
-READOBJ: Name: .anotherspecial
-READOBJ: Type: SHT_PROGBITS
-READOBJ: Flags [ (0x3)
-READOBJ: SHF_ALLOC
-READOBJ: SHF_WRITE
-READOBJ: ]
-READOBJ: Address: 0x1008
-READOBJ: Size: 4
-READOBJ: }
-READOBJ: Section {
-READOBJ: Index: 5
-READOBJ: Name: .bss
-READOBJ: Type: SHT_NOBITS
-READOBJ: Flags [ (0x3)
-READOBJ: SHF_ALLOC
-READOBJ: SHF_WRITE
-READOBJ: ]
-READOBJ: Address: 0x100C
-READOBJ: Size: 4
-READOBJ: }
-READOBJ: Section {
-READOBJ: Index: 6
-READOBJ: Name: .shstrtab
-READOBJ: Type: SHT_STRTAB
-READOBJ: Flags [ (0x0)
-READOBJ: ]
-READOBJ: Address: 0x0
-READOBJ: Link: 0
-READOBJ: AddressAlignment: 1
-READOBJ: }
-READOBJ: Section {
-READOBJ: Index: 7
-READOBJ: Name: .symtab
-READOBJ: Type: SHT_SYMTAB
-READOBJ: Flags [ (0x0)
-READOBJ: ]
-READOBJ: Address: 0x0
-READOBJ: Link: 8
-READOBJ: AddressAlignment: 4
-READOBJ: EntrySize: 16
-READOBJ: }
-READOBJ: Section {
-READOBJ: Index: 8
-READOBJ: Name: .strtab
-READOBJ: Type: SHT_STRTAB
-READOBJ: Flags [ (0x0)
-READOBJ: ]
-READOBJ: Address: 0x0
-READOBJ: }
-READOBJ: ]
-
-READOBJ: Symbols [
-READOBJ: Symbol {
-READOBJ: Name: baz
-READOBJ: Value: 0x74
-READOBJ: Size: 10
-READOBJ: Binding: Global
-READOBJ: Type: Function
-READOBJ: Section: .text
-READOBJ: }
-READOBJ: Symbol {
-READOBJ: Name: y
-READOBJ: Value: 0x1004
-READOBJ: Size: 4
-READOBJ: Binding: Global
-READOBJ: Type: Object
-READOBJ: Section: .special
-READOBJ: }
diff --git a/test/old-elf/sh_addralign.test b/test/old-elf/sh_addralign.test
deleted file mode 100644
index 97ddd5f1030a..000000000000
--- a/test/old-elf/sh_addralign.test
+++ /dev/null
@@ -1,37 +0,0 @@
-# Check handling of section alignment.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor old-gnu -target arm64 -o %t-exe %t-obj
-# RUN: llvm-objdump -h %t-exe | FileCheck %s
-
-# CHECK: 8 .data 00000000 0000000000402000 DATA
-
-!ELF
-FileHeader: !FileHeader
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_AARCH64
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
- Content: ''
- AddressAlign: 0
- Flags: [SHF_ALLOC, SHF_EXECINSTR]
-- Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 1
- Size: 0x1000
-- Name: .data
- Type: SHT_PROGBITS
- Content: ''
- AddressAlign: 4096
- Flags: [SHF_ALLOC, SHF_WRITE]
-
-Symbols:
- Global:
- - Name: _start
- Section: .text
- Value: 0x0
- Size: 4
diff --git a/test/old-elf/shndx.test b/test/old-elf/shndx.test
deleted file mode 100644
index c86fa3349b5f..000000000000
--- a/test/old-elf/shndx.test
+++ /dev/null
@@ -1,18 +0,0 @@
-Test that we can handle shndx. The test file has a shndx despite having only
-a few sections. One might consider it invalid, but it has a clear interpretation
-and avoids needing 65K sections to test the corresponding code path.
-
-RUN: lld -target x86_64-pc-linux -flavor old-gnu %p/Inputs/shndx.o-x86_64 -o %t.so -shared
-RUN: llvm-readobj -s -t %t.so | FileCheck %s
-
-CHECK: Name: .text
-CHECK-NEXT: Type: SHT_PROGBITS (0x1)
-CHECK-NEXT: Flags [ (0x6)
-CHECK-NEXT: SHF_ALLOC (0x2)
-CHECK-NEXT: SHF_EXECINSTR (0x4)
-CHECK-NEXT: ]
-CHECK-NEXT: Address: [[ADDR:.*]]
-
-// CHECK: Symbol {
-// CHECK: Name: foo
-// CHECK-NEXT: Value: [[ADDR]]
diff --git a/test/old-elf/soname.test b/test/old-elf/soname.test
deleted file mode 100644
index b4dce9746d48..000000000000
--- a/test/old-elf/soname.test
+++ /dev/null
@@ -1,6 +0,0 @@
-RUN: lld -flavor old-gnu -shared -target i386 -e main %p/Inputs/writersyms.o \
-RUN: -o %t -soname libtest.so
-RUN: llvm-readobj -dynamic-table %t | FileCheck %s
-
-CHECK: LoadName: libtest.so
-CHECK: 0x0000000E SONAME LibrarySoname (libtest.so)
diff --git a/test/old-elf/start-stop-sym.test b/test/old-elf/start-stop-sym.test
deleted file mode 100644
index 62c16a91ee69..000000000000
--- a/test/old-elf/start-stop-sym.test
+++ /dev/null
@@ -1,108 +0,0 @@
-# Check __start_XXX and __stop_XXX symbols handling where XXX
-# is a section name which can be represented as a C identifier.
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
-# RUN: lld -flavor old-gnu -target mipsel -static -e T0 -o %t.exe %t1.o %t2.o
-# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400080 a0004000 b4004000 00000000 00000000
-# ^ start of _csec section
-# ^ end of _csec section
-# CHECK-NEXT: 400090 a0004000 b4004000
-# CHECK-NEXT: Contents of section _csec:
-# CHECK-NEXT: 4000a0 00000000 00000000 00000000 00000000
-# CHECK-NEXT: 4000b0 00000000
-
-# CHECK: 004000a0 g *ABS* 00000000 __start__csec
-# CHECK: 004000b4 g *ABS* 00000000 __stop__csec
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 8
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: __start__csec
- Type: R_MIPS_32
- - Offset: 4
- Symbol: __stop__csec
- Type: R_MIPS_32
-
- - Name: _csec
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Weak:
- - Name: __start__csec
- - Name: __stop__csec
- Global:
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Size: 8
-
----
-FileHeader:
- Class: ELFCLASS32
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_MIPS
- Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
-
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 16
- Size: 8
-
- - Name: .rel.text
- Type: SHT_REL
- Link: .symtab
- AddressAlign: 4
- Info: .text
- Relocations:
- - Offset: 0
- Symbol: __start__csec
- Type: R_MIPS_32
- - Offset: 4
- Symbol: __stop__csec
- Type: R_MIPS_32
-
- - Name: _csec
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 16
- Size: 4
-
-Symbols:
- Weak:
- - Name: __start__csec
- - Name: __stop__csec
- Global:
- - Name: T1
- Type: STT_FUNC
- Section: .text
- Size: 8
-...
diff --git a/test/old-elf/strip-all.test b/test/old-elf/strip-all.test
deleted file mode 100644
index faf30349ec84..000000000000
--- a/test/old-elf/strip-all.test
+++ /dev/null
@@ -1,108 +0,0 @@
-# Tests the --strip-all (-s) flag.
-# We expect that .symtab and .strtab are stripped from the final executable.
-#
-# The following code was used to generate the object.
-# $ clang -c blah.c -o blah
-#
-# void
-# callMeMaybe(int *v)
-# {
-# *v += 1;
-# }
-#
-# int
-# main(void)
-# {
-#
-# int blah = 42;
-# callMeMaybe(&blah);
-# }
-
-#RUN: yaml2obj -format=elf %s -o=%t.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.o -e=main --strip-all -o %t1
-#RUN: llvm-objdump -section-headers %t1 | FileCheck %s
-
-#CHECK: 14 .shstrtab 0000007d 0000000000000000
-#CHECK-NOT: 15 .symtab 00000198 0000000000000000
-#CHECK-NOT: 16 .strtab 000000e4 0000000000000000
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_FREEBSD
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E548897DF8488B7DF88B07050100000089075DC3660F1F840000000000554889E54883EC10488D7DFCC745FC2A000000E8C8FFFFFFB8000000004883C4105DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 004672656542534420636C616E672076657273696F6E20332E342E312028746167732F52454C454153455F33342F646F74312D66696E616C203230383033322920323031343035313200
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000017A5200017810011B0C070890010000180000001C000000000000001700000000410E108602430D060000001800000038000000000000002300000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: callMeMaybe
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000017
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000020
- Size: 0x0000000000000023
-...
diff --git a/test/old-elf/stripped-empty.test b/test/old-elf/stripped-empty.test
deleted file mode 100644
index ddf3b3899d10..000000000000
--- a/test/old-elf/stripped-empty.test
+++ /dev/null
@@ -1,4 +0,0 @@
-RUN: lld -flavor old-gnu -shared -o test.so \
-RUN: -target x86_64 %p/Inputs/stripped-empty.x86_64
-
-test that we handle files without a symbol table.
diff --git a/test/old-elf/symbols.test b/test/old-elf/symbols.test
deleted file mode 100644
index bcf399e86eb8..000000000000
--- a/test/old-elf/symbols.test
+++ /dev/null
@@ -1,33 +0,0 @@
-# Tests the functionality of archive libraries reading
-# and resolution
-# Note: The binary files would not be required once we have support to generate
-# binary archives from textual(yaml) input
-#
-# Tests generated using the source files below
-# main file
-#
-#extern int __bss_start __attribute__ ((weak));
-#int a;
-#int main()
-#{
-# return 0;
-#}
-#
-
-RUN: lld -flavor old-gnu -target i386 -e main %p/Inputs/writersyms.o -o %t1
-RUN: llvm-nm -n %t1 | FileCheck -check-prefix CHECKSYMS %s
-RUN: lld -flavor old-gnu -shared -target i386 -e main %p/Inputs/writersyms.o -o %t1
-RUN: llvm-nm -n %t1 | FileCheck -check-prefix CHECKSHAREDSYMS %s
-
-CHECKSYMS: {{[0-9a-f]+}} a 1.c
-CHECKSYMS: {{[0-9a-f]+}} T main
-CHECKSYMS: {{[0-9a-f]+}} A __bss_start
-CHECKSYMS: {{[0-9a-f]+}} B a
-CHECKSYMS: {{[0-9a-f]+}} A __bss_end
-CHECKSYMS: {{[0-9a-f]+}} A _end
-CHECKSYMS: {{[0-9a-f]+}} A end
-
-CHECKSHAREDSYMS: {{[0-9a-f]+}} a 1.c
-CHECKSHAREDSYMS: {{[0-9a-f]+}} T main
-CHECKSHAREDSYMS: {{[0-9a-f]+}} B a
-CHECKSHAREDSYMS: {{[0-9a-f]+}} A _end
diff --git a/test/old-elf/tls-tbss-size.test b/test/old-elf/tls-tbss-size.test
deleted file mode 100644
index a7fd86cb7b43..000000000000
--- a/test/old-elf/tls-tbss-size.test
+++ /dev/null
@@ -1,176 +0,0 @@
-# This test verify if external TLS non initialized variables (tbss) are
-# accounted in TBSS segment size
-
-# The input file 'test/elf/Inputs/tls-tbss-size.yaml' declares:
-#
-# __thread int t0;
-# __thread int t1;
-# __thread int t2;
-# __thread int t3;
-#
-# And the 'test/elf/tls-tbss-size.test' defines:
-#
-# __thread int t4;
-# __thread int t5;
-# __thread int t6;
-# __thread int t7;
-#
-# __thread int t8 = 3;
-# __thread int t9 = 4;
-# __thread int t10 = 5;
-# __thread int t11 = 6;
-
-#RUN: yaml2obj -format=elf -o=%t-t1.o %p/Inputs/tls-tbss-size.yaml
-#RUN: yaml2obj -format=elf -o=%t-t0.o %s
-#RUN: lld -flavor old-gnu -target x86_64-linux --noinhibit-exec -o %t.exe %t-t0.o %t-t1.o
-#RUN: llvm-readobj --sections %t.exe | FileCheck %s
-
-#CHECK: Sections [
-#CHECK: Section {
-#CHECK: Index: 9
-#CHECK: Name: .tdata (71)
-#CHECK: Size: 16
-#CHECK: }
-#CHECK: Section {
-#CHECK: Index: 10
-#CHECK: Name: .tbss (78)
-#CHECK: Size: 32
-#CHECK: }
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 488B050000000064C70001000000488B050000000064C70002000000488B050000000064C70003000000488B050000000064C7000400000064C70425000000000500000064C70425000000000600000064C70425000000000700000064C70425000000000800000031C0C3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000003
- Symbol: t0
- Type: R_X86_64_GOTTPOFF
- Addend: -4
- - Offset: 0x0000000000000011
- Symbol: t1
- Type: R_X86_64_GOTTPOFF
- Addend: -4
- - Offset: 0x000000000000001F
- Symbol: t2
- Type: R_X86_64_GOTTPOFF
- Addend: -4
- - Offset: 0x000000000000002D
- Symbol: t3
- Type: R_X86_64_GOTTPOFF
- Addend: -4
- - Offset: 0x000000000000003C
- Symbol: t4
- Type: R_X86_64_TPOFF32
- - Offset: 0x0000000000000048
- Symbol: t5
- Type: R_X86_64_TPOFF32
- - Offset: 0x0000000000000054
- Symbol: t6
- Type: R_X86_64_TPOFF32
- - Offset: 0x0000000000000060
- Symbol: t7
- Type: R_X86_64_TPOFF32
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .tdata
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Content: '03000000040000000500000006000000'
- - Name: .tbss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Size: 16
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000017A5200017810011B0C070890010000140000001C000000000000006B0000000000000000000000
-Symbols:
- Local:
- - Name: .tbss
- Type: STT_TLS
- Section: .tbss
- - Name: .tdata
- Type: STT_TLS
- Section: .tdata
- - Type: STT_SECTION
- Section: .text
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000006B
- - Name: t0
- Type: STT_TLS
- - Name: t1
- Type: STT_TLS
- - Name: t10
- Type: STT_TLS
- Section: .tdata
- Value: 0x0000000000000008
- Size: 0x0000000000000004
- - Name: t11
- Type: STT_TLS
- Section: .tdata
- Value: 0x000000000000000C
- Size: 0x0000000000000004
- - Name: t2
- Type: STT_TLS
- - Name: t3
- Type: STT_TLS
- - Name: t4
- Type: STT_TLS
- Section: .tbss
- Size: 0x0000000000000004
- - Name: t5
- Type: STT_TLS
- Section: .tbss
- Value: 0x0000000000000004
- Size: 0x0000000000000004
- - Name: t6
- Type: STT_TLS
- Section: .tbss
- Value: 0x0000000000000008
- Size: 0x0000000000000004
- - Name: t7
- Type: STT_TLS
- Section: .tbss
- Value: 0x000000000000000C
- Size: 0x0000000000000004
- - Name: t8
- Type: STT_TLS
- Section: .tdata
- Size: 0x0000000000000004
- - Name: t9
- Type: STT_TLS
- Section: .tdata
- Value: 0x0000000000000004
- Size: 0x0000000000000004
-...
diff --git a/test/old-elf/tls.test b/test/old-elf/tls.test
deleted file mode 100644
index 6fb33941a88c..000000000000
--- a/test/old-elf/tls.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# REQUIRES: x86
-
-# This tests verifies that TLS variables have correct offsets
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/tls.x86-64 -static \
-RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s -check-prefix=YAML
-
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/tls.x86-64 -o %t \
-RUN: --noinhibit-exec -e main -static && llvm-objdump -d %t | FileCheck %s
-
-// Verify that the TLS accesses have the correct offsets.
-
-YAML: name: main
-YAML: references:
-YAML: kind: R_X86_64_TPOFF32
-YAML: offset: 9
-YAML: target: tls1
-YAML: kind: R_X86_64_TPOFF32
-YAML: offset: 17
-YAML: target: tls0
-YAML: kind: R_X86_64_TPOFF32
-YAML: offset: 25
-YAML: target: tls2
-
-YAML: name: GOTTPOFF
-YAML: kind: R_X86_64_GOTTPOFF
-YAML: target: [[GOTNAME:[a-zA-Z0-9_]+]]
-
-YAML: type: got
-YAML: references:
-YAML: kind: R_X86_64_TPOFF64
-YAML: target: tls2
-
-// main
-CHECK: addl %fs:-4
-CHECK: addl %fs:-8
-CHECK: addl %fs:-12
-
-// GOTTPOFF
-CHECK: movq {{[0-9]+}}(%rip)
-
-// TLSLD
-CHECK: movq %fs:0, %rax
-CHECK: leaq -8(%rax), %rax
diff --git a/test/old-elf/tlsAddr.test b/test/old-elf/tlsAddr.test
deleted file mode 100644
index bcb089c504ed..000000000000
--- a/test/old-elf/tlsAddr.test
+++ /dev/null
@@ -1,7 +0,0 @@
-# This tests verifies that TLS variables have correct offsets
-# and that TBSS doesn't occupy memory
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/tlsAddr.x86-64 -static \
-RUN: -o %t --noinhibit-exec
-RUN: llvm-objdump -section-headers %t | FileCheck -check-prefix=CHECKADDR %s
-
-CHECKADDR: {{[0-9]+}} .data 00000000 0000000000401008 DATA
diff --git a/test/old-elf/undef-from-dso-to-main.test b/test/old-elf/undef-from-dso-to-main.test
deleted file mode 100644
index c19a0197061e..000000000000
--- a/test/old-elf/undef-from-dso-to-main.test
+++ /dev/null
@@ -1,52 +0,0 @@
-# Tests that a reference from a DSO to a regular object
-# forces the final executable to export the symbol.
-
-#RUN: yaml2obj -format=elf %p/Inputs/undef2-so.o.yaml -o=%t.o.so
-#RUN: lld -flavor old-gnu -target x86_64 -shared %t.o.so -o %T/libundef2.so
-#RUN: yaml2obj -format=elf %s -o=%t.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.o -L%T -lundef2 -o %t1
-#RUN: llvm-readobj -dyn-symbols %t1 | FileCheck -check-prefix CHECKSYMS %s
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000001
- Content: C3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Size: 4
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Global:
- - Name: myexportedsymbol
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- - Name: _start
- Section: .text
- Size: 0x0000000000000001
-
-#CHECKSYMS: myexportedsymbol
diff --git a/test/old-elf/undef-from-main-dso.test b/test/old-elf/undef-from-main-dso.test
deleted file mode 100644
index 8722a55f672c..000000000000
--- a/test/old-elf/undef-from-main-dso.test
+++ /dev/null
@@ -1,43 +0,0 @@
-RUN: lld -flavor old-gnu -target x86_64 -e main -o %t -L%p/Inputs \
-RUN: %p/Inputs/undef.o -lundef
-RUN: llvm-readobj -relocations -symbols -dyn-symbols %t | FileCheck %s
-
-RUN: lld -flavor old-gnu -target x86_64 -e main -o %t -L%p/Inputs \
-RUN: %p/Inputs/undef-pc32.o -lundef
-RUN: llvm-readobj -relocations -symbols -dyn-symbols %t | FileCheck %s
-
-# DSO source code:
-# int x[2] = { 1, 2 };
-#
-# Main binary source code:
-#
-# extern int x[2];
-#
-# int main(void)
-# {
-# x[0] = 2;
-# }
-#
-
-CHECK: Relocations [
-CHECK-NEXT: Section ({{[0-9]+}}) .rela.dyn {
-CHECK-NEXT: 0x{{[1-9A-F][0-9A-F]*}} R_X86_64_COPY x 0x0
-CHECK-NEXT: }
-CHECK-NEXT: ]
-
-CHECK: Name: x ({{[0-9]+}}
-CHECK-NEXT: Value: 0x{{[1-9A-F][0-9A-F]*}}
-CHECK-NEXT: Size: 8
-CHECK-NEXT: Binding: Global (0x1)
-CHECK-NEXT: Type: Object (0x1)
-CHECK-NEXT: Other: 0
-CHECK-NEXT: Section: .bss
-
-CHECK: Name: x@ ({{[0-9]+}}
-CHECK-NEXT: Value: 0x{{[1-9A-F][0-9A-F]*}}
-CHECK-NEXT: Size: 8
-CHECK-NEXT: Binding: Global (0x1)
-CHECK-NEXT: Type: Object (0x1)
-CHECK-NEXT: Other: 0
-CHECK-NEXT: Section: .bss
-
diff --git a/test/old-elf/weaksym.test b/test/old-elf/weaksym.test
deleted file mode 100644
index 59d997edc64c..000000000000
--- a/test/old-elf/weaksym.test
+++ /dev/null
@@ -1,7 +0,0 @@
-# Tests that a weak reference remains a weak reference,
-# even if a shared library defines the symbol weak as well.
-
-RUN: lld -flavor old-gnu -target x86_64 -shared %p/Inputs/weaksym.o -L%p/Inputs -lweaksym -o %t1
-RUN: llvm-nm -n %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-CHECKSYMS: w weaksym
diff --git a/test/old-elf/wrap.test b/test/old-elf/wrap.test
deleted file mode 100644
index 427764970be8..000000000000
--- a/test/old-elf/wrap.test
+++ /dev/null
@@ -1,276 +0,0 @@
-# This tests the functionality of using the --wrap option.
-# The test case is extracted by compiling and linking the following code.
-#
-#cat > main.c << \!
-#int main() {
-# foo();
-# return 0;
-#}
-#!
-#
-#cat > wrapfoo.c << \!
-#int __wrap_foo() {
-# __real_foo();
-# return 0;
-#}
-#!
-#
-#cat > realfoo.c << \!
-#int foo() {
-# return 0;
-#}
-#!
-#
-#clang main.c wrapfoo.c realfoo.c -Xlinker --wrap -Xlinker foo
-#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.main.o
-#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.wrapfoo.o
-#RUN: yaml2obj -format=elf -docnum 3 %s -o %t.realfoo.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.main.o %t.wrapfoo.o %t.realfoo.o \
-#RUN: --wrap foo --wrap foo --noinhibit-exec --output-filetype=yaml -o %t2.out
-#RUN: lld -flavor old-gnu -target x86_64 %t.main.o %t.wrapfoo.o \
-#RUN: --wrap foo --wrap foo --noinhibit-exec --output-filetype=yaml -o %t2.out.undef 2>&1 | \
-#RUN: FileCheck %s -check-prefix=CHECKUNDEF
-#CHECKWRAP: - name: main
-#CHECKWRAP: references:
-#CHECKWRAP: - kind: R_X86_64_PC32
-#CHECKWRAP: target: __wrap_foo
-#CHECKWRAP: - name: __wrap_foo
-#CHECKWRAP: references:
-#CHECKWRAP: - kind: R_X86_64_PC32
-#CHECKWRAP: target: foo
-#CHECKUNDEF: Undefined symbol: {{.*}}main.o: foo
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 5031C0E80000000031C05AC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: foo
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232383733392920286C6C766D2F7472756E6B203232383734382900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000140000001C000000000000000C00000000410E1000000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000000C
- - Name: foo
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 5031C0E80000000031C05AC3
- - Name: .rela.text
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .text
- Relocations:
- - Offset: 0x0000000000000004
- Symbol: __real_foo
- Type: R_X86_64_PC32
- Addend: -4
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232383733392920286C6C766D2F7472756E6B203232383734382900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000140000001C000000000000000C00000000410E1000000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: __wrap_foo
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000000C
- - Name: __real_foo
-...
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 31C0C3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232383733392920286C6C766D2F7472756E6B203232383734382900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000037A5200017810011B0C070890010000140000001C00000000000000030000000000000000000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: foo
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000003
-...
diff --git a/test/old-elf/x86-64-dynamic-relocs.test b/test/old-elf/x86-64-dynamic-relocs.test
deleted file mode 100644
index c5572d0aa3a3..000000000000
--- a/test/old-elf/x86-64-dynamic-relocs.test
+++ /dev/null
@@ -1,26 +0,0 @@
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/relocs-dynamic.x86-64 \
-RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s
-
-path: <linker-internal>
-defined-atoms:
- - name: main
- scope: global
- content: [ E8, 00, 00, 00, 00, C3 ]
- alignment: 16
- section-choice: custom-required
- section-name: .text
- references:
- - kind: R_X86_64_PLT32
- offset: 1
- target: foo
- addend: -4
- - name: foo
- scope: global
- content: [ C3 ]
- alignment: 6 mod 16
- section-choice: custom-required
- section-name: .text
-
-# Don't generate a PLT/GOT entry for a PLT32 relocation to a non-shared symbol.
-CHECK-NOT: got
-CHECK-NOT: stub
diff --git a/test/old-elf/x86-64-dynamic.test b/test/old-elf/x86-64-dynamic.test
deleted file mode 100644
index d957e6ee85ee..000000000000
--- a/test/old-elf/x86-64-dynamic.test
+++ /dev/null
@@ -1,79 +0,0 @@
-# Checks that linking an object file with a shared object creates the necessary
-# PLT/GOT Entries
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 --output-filetype=yaml -o %t1 --noinhibit-exec
-RUN: FileCheck %s < %t1
-
-RUN: lld -flavor old-gnu -target x86_64-linux %p/Inputs/use-shared-32s.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 --output-filetype=yaml --noinhibit-exec \
-RUN: | FileCheck %s --check-prefix=32S
-
-CHECK: - name: main
-CHECK: scope: global
-CHECK: references:
-CHECK: - kind: R_X86_64_PC32
-CHECK: offset: 18
-CHECK: target: [[PLTNAME:[-a-zA-Z0-9_]+]]
-CHECK: addend: -4
-CHECK: - kind: R_X86_64_GOTPCREL
-CHECK: offset: 25
-CHECK: target: [[GOTNAME:[-a-zA-Z0-9_]+]]
-CHECK: addend: -4
-
- - name: .PLT0
-CHECK: type: stub
-CHECK: content: [ FF, 35, 00, 00, 00, 00, FF, 25, 00, 00, 00, 00,
-CHECK: 90, 90, 90, 90 ]
-CHECK: alignment: 16
-CHECK: section-choice: custom-required
-CHECK: section-name: .plt
-CHECK: references:
-CHECK: - kind: R_X86_64_PC32
-CHECK: offset: 2
- target: __got0
-CHECK: addend: -4
-CHECK: - kind: R_X86_64_PC32
-CHECK: offset: 8
- target: __got1
-CHECK: addend: -4
- - name: [[PLTNAME]]
-CHECK: type: stub
-CHECK: content: [ FF, 25, 00, 00, 00, 00, 68, 00, 00, 00, 00, E9,
-CHECK: 00, 00, 00, 00 ]
-CHECK: alignment: 16
-CHECK: section-choice: custom-required
-CHECK: section-name: .plt
-CHECK: references:
-CHECK: - kind: R_X86_64_PC32
-CHECK: offset: 2
- target: __got_foo
-CHECK: addend: -4
-CHECK: - kind: LLD_R_X86_64_GOTRELINDEX
-CHECK: offset: 7
- target: __got_foo
-CHECK: - kind: R_X86_64_PC32
-CHECK: offset: 12
- target: .PLT0
-CHECK: addend: -4
-
-// Don't check the GOT and PLT names as they are only present in assert builds.
-CHECK: type: got
-CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECK: section-choice: custom-required
-CHECK: section-name: .got
-CHECK: permissions: rw-
-CHECK: references:
-CHECK: - kind: R_X86_64_GLOB_DAT
-CHECK: offset: 0
-CHECK: target: i
-
-CHECK:shared-library-atoms:
-CHECK: - name: foo
-CHECK: load-name: shared.so-x86-64
-
-32S: name: main
-32S: kind: R_X86_64_PC32
-32S: target: func
-32S: kind: R_X86_64_32S
-32S: kind: R_X86_64_PC32
-32S: type: stub
diff --git a/test/old-elf/x86.test b/test/old-elf/x86.test
deleted file mode 100644
index 3bc4a6963a50..000000000000
--- a/test/old-elf/x86.test
+++ /dev/null
@@ -1,38 +0,0 @@
-# Source for input file: reloc-xb.x86
-# xb.S:
-# .section .text, "ax", @progbits
-# .align 0x4
-# .globl _start
-# _start:
-# .globl back
-# back:
-# call target
-#
-# Source for input file: reloc-xt.x86
-# xt.S:
-# .section .text, "ax", @progbits
-#
-# .globl target
-# target:
-# call back
-#
-# Assembled with: "as --32"
-
-RUN: lld -flavor old-gnu -target i386 -e back --output-filetype=yaml %p/Inputs/reloc-xb.x86 %p/Inputs/reloc-xt.x86 | FileCheck %s -check-prefix x86-yaml
-
-x86-yaml: - name: back
-x86-yaml: scope: global
-x86-yaml: content: [ E8, FC, FF, FF, FF ]
-x86-yaml: references:
-x86-yaml: - kind: R_386_PC32
-x86-yaml: offset: 1
-x86-yaml: target: target
-
-x86-yaml: - name: target
-x86-yaml: scope: global
-x86-yaml: content: [ E8, FC, FF, FF, FF ]
-x86-yaml: references:
-x86-yaml: - kind: R_386_PC32
-x86-yaml: offset: 1
-x86-yaml: target: back
-
diff --git a/test/old-elf/x86_64-kinds.test b/test/old-elf/x86_64-kinds.test
deleted file mode 100644
index 111cea53bf0c..000000000000
--- a/test/old-elf/x86_64-kinds.test
+++ /dev/null
@@ -1,23 +0,0 @@
-REQUIRES: x86
-
-RUN: lld -flavor old-gnu -target x86_64-linux -o %t1 %p/Inputs/relocs.x86-64 \
-RUN: -e _start -static
-RUN: llvm-objdump -d %t1 | FileCheck %s -check-prefix=RELOCS
-
-RUN: lld -flavor old-gnu -target x86_64-linux --output-filetype=yaml -e _start -static \
-RUN: %p/Inputs/relocs.x86-64 | FileCheck %s -check-prefix=X86_64
-
-RELOCS: ELF64-x86-64
-
-// R_X86_64_32S
-RELOCS: c7 04 25
-RELOCS-NOT: 00 00 00 00
-RELOCS: 05 00 00 00 movl
-
-// R_X86_64_PC32
-RELOCS: e8
-RELOCS-NOT: 00 00 00 00
-RELOCS: callq
-
-X86_64: R_X86_64_32S
-X86_64: R_X86_64_PC32
diff --git a/test/old-elf/zoption_dtflags.test b/test/old-elf/zoption_dtflags.test
deleted file mode 100644
index 274981bb1360..000000000000
--- a/test/old-elf/zoption_dtflags.test
+++ /dev/null
@@ -1,89 +0,0 @@
-# Test that -z {origin, now} options work.
-#
-#RUN: yaml2obj -format=elf %s -o=%t.o
-#RUN: lld -flavor old-gnu -target x86_64 %t.o -e=main -z now -z origin -o %t1
-#RUN: llvm-readobj -dynamic-table %t1 | FileCheck %s
-#
-#CHECK: 0x000000000000001E FLAGS ORIGIN BIND_NOW
-#CHECK: 0x000000006FFFFFFB FLAGS_1 NOW ORIGIN
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_FREEBSD
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000010
- Content: 554889E54883EC10C745FC00000000E81C000000B9000000008945F889C84883C4105DC36666662E0F1F840000000000554889E58B45FC5DC3
- - Name: .data
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- AddressAlign: 0x0000000000000004
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 004672656542534420636C616E672076657273696F6E20332E342E312028746167732F52454C454153455F33342F646F74312D66696E616C203230383033322920323031343035313200
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x0000000000000008
- Content: 1400000000000000017A5200017810011B0C070890010000180000001C000000000000002400000000410E108602430D060000001800000038000000000000000900000000410E108602430D06000000
- - Name: .rela.eh_frame
- Type: SHT_RELA
- Link: .symtab
- AddressAlign: 0x0000000000000008
- Info: .eh_frame
- Relocations:
- - Offset: 0x0000000000000020
- Symbol: .text
- Type: R_X86_64_PC32
- - Offset: 0x000000000000003C
- Symbol: .text
- Type: R_X86_64_PC32
- Addend: 48
-Symbols:
- Local:
- - Name: local
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000030
- Size: 0x0000000000000009
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .note.GNU-stack
- Type: STT_SECTION
- Section: .note.GNU-stack
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x0000000000000024
-...
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
deleted file mode 100644
index 1151404441b4..000000000000
--- a/tools/CMakeLists.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-add_subdirectory(linker-script-test)
-add_subdirectory(lld)
diff --git a/tools/linker-script-test/CMakeLists.txt b/tools/linker-script-test/CMakeLists.txt
deleted file mode 100644
index 2492f10aa80c..000000000000
--- a/tools/linker-script-test/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-add_llvm_executable(linker-script-test
- linker-script-test.cpp
- )
-
-target_link_libraries(linker-script-test
- LLVMSupport
- lldReaderWriter
- )
diff --git a/tools/linker-script-test/linker-script-test.cpp b/tools/linker-script-test/linker-script-test.cpp
deleted file mode 100644
index 027ecb36c382..000000000000
--- a/tools/linker-script-test/linker-script-test.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- utils/linker-script-test/linker-script-test.cpp --------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Tool for testing linker script parsing.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/ReaderWriter/LinkerScript.h"
-
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
-
-using namespace llvm;
-using namespace lld;
-using namespace script;
-
-int main(int argc, const char **argv) {
- llvm::sys::PrintStackTraceOnErrorSignal();
- llvm::PrettyStackTraceProgram X(argc, argv);
-
- {
- ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
- MemoryBuffer::getFileOrSTDIN(argv[1]);
- if (std::error_code ec = mb.getError()) {
- llvm::errs() << ec.message() << "\n";
- return 1;
- }
- Lexer l(std::move(mb.get()));
- Token tok;
- while (true) {
- l.lex(tok);
- tok.dump(llvm::outs());
- if (tok._kind == Token::eof || tok._kind == Token::unknown)
- break;
- }
- }
- {
- ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
- MemoryBuffer::getFileOrSTDIN(argv[1]);
- if (std::error_code ec = mb.getError()) {
- llvm::errs() << ec.message() << "\n";
- return 1;
- }
- Parser p(std::move(mb.get()));
- if (!p.parse()) {
- LinkerScript *ls = p.get();
- ls->dump(llvm::outs());
- }
- }
-}
diff --git a/tools/lld/CMakeLists.txt b/tools/lld/CMakeLists.txt
index 5a0736e4c1e9..5951da6496c5 100644
--- a/tools/lld/CMakeLists.txt
+++ b/tools/lld/CMakeLists.txt
@@ -5,6 +5,7 @@ add_llvm_executable(lld
target_link_libraries(lld
lldDriver
lldCOFF
+ lldELF
LLVMSupport
)
diff --git a/tools/lld/TODO.txt b/tools/lld/TODO.txt
deleted file mode 100644
index 20f8db0fcf10..000000000000
--- a/tools/lld/TODO.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-tools/lld
-~~~~~~~~~
diff --git a/tools/lld/lld.cpp b/tools/lld/lld.cpp
index eb0903660dbd..8805e02e8c48 100644
--- a/tools/lld/lld.cpp
+++ b/tools/lld/lld.cpp
@@ -6,32 +6,110 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// This is the entry point to the lld driver. This is a thin wrapper which
-/// dispatches to the given platform specific driver.
-///
+//
+// This is the entry point to the lld driver. This is a thin wrapper which
+// dispatches to the given platform specific driver.
+//
+// If there is -flavor option, it is dispatched according to the arguments.
+// If the flavor parameter is not present, then it is dispatched according
+// to argv[0].
+//
//===----------------------------------------------------------------------===//
-#include "lld/Core/LLVM.h"
#include "lld/Driver/Driver.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
using namespace lld;
+using namespace llvm;
+using namespace llvm::sys;
+
+enum Flavor {
+ Invalid,
+ Gnu, // -flavor gnu
+ WinLink, // -flavor link
+ Darwin, // -flavor darwin
+};
+
+LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) {
+ errs() << S << "\n";
+ exit(1);
+}
+
+static Flavor getFlavor(StringRef S) {
+ return StringSwitch<Flavor>(S)
+ .Case("ld", Gnu)
+ .Case("ld.lld", Gnu)
+ .Case("gnu", Gnu)
+ .Case("link", WinLink)
+ .Case("darwin", Darwin)
+ .Default(Invalid);
+}
+
+static Flavor parseProgname(StringRef Progname) {
+#if __APPLE__
+ // Use Darwin driver for "ld" on Darwin.
+ if (Progname == "ld")
+ return Darwin;
+#endif
+#if LLVM_ON_UNIX
+ // Use GNU driver for "ld" on other Unix-like system.
+ if (Progname == "ld")
+ return Gnu;
+#endif
+
+ // Progname may be something like "lld-gnu". Parse it.
+ SmallVector<StringRef, 3> V;
+ Progname.split(V, "-");
+ for (StringRef S : V)
+ if (Flavor F = getFlavor(S))
+ return F;
+ return Invalid;
+}
+
+static Flavor parseFlavor(std::vector<const char *> &V) {
+ // Parse -flavor option.
+ if (V.size() > 1 && V[1] == StringRef("-flavor")) {
+ if (V.size() <= 2)
+ die("missing arg value for '-flavor'");
+ Flavor F = getFlavor(V[2]);
+ if (F == Invalid)
+ die("Unknown flavor: " + StringRef(V[2]));
+ V.erase(V.begin() + 1, V.begin() + 3);
+ return F;
+ }
+
+ // Deduct the flavor from argv[0].
+ StringRef Arg0 = path::filename(V[0]);
+ if (Arg0.endswith_lower(".exe"))
+ Arg0 = Arg0.drop_back(4);
+ return parseProgname(Arg0);
+}
/// Universal linker main(). This linker emulates the gnu, darwin, or
-/// windows linker based on the tool name or if the first argument is
-/// -flavor.
-int main(int argc, const char *argv[]) {
+/// windows linker based on the argv[0] or -flavor option.
+int main(int Argc, const char **Argv) {
// Standard set up, so program fails gracefully.
- llvm::sys::PrintStackTraceOnErrorSignal();
- llvm::PrettyStackTraceProgram stackPrinter(argc, argv);
- llvm::llvm_shutdown_obj shutdown;
+ sys::PrintStackTraceOnErrorSignal(Argv[0]);
+ PrettyStackTraceProgram StackPrinter(Argc, Argv);
+ llvm_shutdown_obj Shutdown;
- return !UniversalDriver::link(
- llvm::MutableArrayRef<const char *>(argv, argc));
+ std::vector<const char *> Args(Argv, Argv + Argc);
+ switch (parseFlavor(Args)) {
+ case Gnu:
+ return !elf::link(Args);
+ case WinLink:
+ return !coff::link(Args);
+ case Darwin:
+ return !mach_o::link(Args);
+ default:
+ die("lld is a generic driver.\n"
+ "Invoke ld.lld (Unix), ld (Mac) or lld-link (Windows) instead.");
+ }
}
diff --git a/unittests/CoreTests/CMakeLists.txt b/unittests/CoreTests/CMakeLists.txt
index aa85617916b4..98405d5c73a1 100644
--- a/unittests/CoreTests/CMakeLists.txt
+++ b/unittests/CoreTests/CMakeLists.txt
@@ -1,4 +1,7 @@
add_lld_unittest(CoreTests
ParallelTest.cpp
- RangeTest.cpp
+ )
+
+target_link_libraries(CoreTests
+ ${PTHREAD_LIB}
)
diff --git a/unittests/CoreTests/RangeTest.cpp b/unittests/CoreTests/RangeTest.cpp
deleted file mode 100644
index 2b2fcd5f7875..000000000000
--- a/unittests/CoreTests/RangeTest.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-//===- lld/unittest/RangeTest.cpp -----------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief range.h unit tests.
-///
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-#include "lld/Core/range.h"
-#include <array>
-#include <assert.h>
-#include <deque>
-#include <forward_list>
-#include <iterator>
-#include <list>
-#include <numeric>
-#include <sstream>
-#include <vector>
-
-template <typename T, typename U> struct AssertTypesSame;
-template <typename T> struct AssertTypesSame<T, T> {};
-#define ASSERT_TYPES_SAME(T, U) AssertTypesSame<T, U>()
-
-struct no_begin {};
-struct member_begin {
- int *begin();
-};
-struct free_begin {};
-int *begin(free_begin);
-
-template <typename T>
-auto type_of_forward(T &&t) -> decltype(std::forward<T>(t)) {
- return std::forward<T>(t);
-}
-
-template <typename To> To implicit_cast(To val) { return val; }
-
-void test_traits() {
- using namespace lld::detail;
- ASSERT_TYPES_SAME(begin_result<no_begin>::type, undefined);
- // This causes clang to segfault.
-#if 0
- ASSERT_TYPES_SAME(
- begin_result<decltype(type_of_forward(member_begin()))>::type, int *);
-#endif
- ASSERT_TYPES_SAME(begin_result<free_begin>::type, int *);
-}
-
-TEST(Range, constructors) {
- std::vector<int> v(5);
- std::iota(v.begin(), v.end(), 0);
- lld::range<std::vector<int>::iterator> r = v;
- EXPECT_EQ(v.begin(), r.begin());
- EXPECT_EQ(v.end(), r.end());
-
- int arr[] = { 1, 2, 3, 4, 5 };
- std::begin(arr);
- lld::range<int *> r2 = arr;
- EXPECT_EQ(5, r2.back());
-}
-
-TEST(Range, conversion_to_pointer_range) {
- std::vector<int> v(5);
- std::iota(v.begin(), v.end(), 0);
- lld::range<int *> r = v;
- EXPECT_EQ(&*v.begin(), r.begin());
- EXPECT_EQ(2, r[2]);
-}
-
-template <typename Iter> void takes_range(lld::range<Iter> r) {
- int expected = 0;
- for (int val : r) {
- EXPECT_EQ(expected++, val);
- }
-}
-
-void takes_ptr_range(lld::range<const int *> r) {
- int expected = 0;
- for (int val : r) {
- EXPECT_EQ(expected++, val);
- }
-}
-
-TEST(Range, passing) {
- using lld::make_range;
- using lld::make_ptr_range;
- std::list<int> l(5);
- std::iota(l.begin(), l.end(), 0);
- takes_range(make_range(l));
- takes_range(make_range(implicit_cast<const std::list<int> &>(l)));
- std::deque<int> d(5);
- std::iota(d.begin(), d.end(), 0);
- takes_range(make_range(d));
- takes_range(make_range(implicit_cast<const std::deque<int> &>(d)));
- std::vector<int> v(5);
- std::iota(v.begin(), v.end(), 0);
- takes_range(make_range(v));
- takes_range(make_range(implicit_cast<const std::vector<int> &>(v)));
- static_assert(
- std::is_same<decltype(make_ptr_range(v)), lld::range<int *>>::value,
- "make_ptr_range should return a range of pointers");
- takes_range(make_ptr_range(v));
- takes_range(make_ptr_range(implicit_cast<const std::vector<int> &>(v)));
- int arr[] = { 0, 1, 2, 3, 4 };
- takes_range(make_range(arr));
- const int carr[] = { 0, 1, 2, 3, 4 };
- takes_range(make_range(carr));
-
- takes_ptr_range(v);
- takes_ptr_range(implicit_cast<const std::vector<int> &>(v));
- takes_ptr_range(arr);
- takes_ptr_range(carr);
-}
-
-TEST(Range, access) {
- std::array<int, 5> a = { { 1, 2, 3, 4, 5 } };
- lld::range<decltype(a.begin())> r = a;
- EXPECT_EQ(4, r[3]);
- EXPECT_EQ(4, r[-2]);
-}
-
-template <bool b> struct CompileAssert;
-template <> struct CompileAssert<true> {};
-
-#if __has_feature(cxx_constexpr)
-constexpr int arr[] = { 1, 2, 3, 4, 5 };
-TEST(Range, constexpr) {
- constexpr lld::range<const int *> r(arr, arr + 5);
- CompileAssert<r.front() == 1>();
- CompileAssert<r.size() == 5>();
- CompileAssert<r[4] == 5>();
-}
-#endif
-
-template <typename Container> void test_slice() {
- Container cont(10);
- std::iota(cont.begin(), cont.end(), 0);
- lld::range<decltype(cont.begin())> r = cont;
-
- // One argument.
- EXPECT_EQ(10, r.slice(0).size());
- EXPECT_EQ(8, r.slice(2).size());
- EXPECT_EQ(2, r.slice(2).front());
- EXPECT_EQ(1, r.slice(-1).size());
- EXPECT_EQ(9, r.slice(-1).front());
-
- // Two positive arguments.
- EXPECT_TRUE(r.slice(5, 2).empty());
- EXPECT_EQ(next(cont.begin(), 5), r.slice(5, 2).begin());
- EXPECT_EQ(1, r.slice(1, 2).size());
- EXPECT_EQ(1, r.slice(1, 2).front());
-
- // Two negative arguments.
- EXPECT_TRUE(r.slice(-2, -5).empty());
- EXPECT_EQ(next(cont.begin(), 8), r.slice(-2, -5).begin());
- EXPECT_EQ(1, r.slice(-2, -1).size());
- EXPECT_EQ(8, r.slice(-2, -1).front());
-
- // Positive start, negative stop.
- EXPECT_EQ(1, r.slice(6, -3).size());
- EXPECT_EQ(6, r.slice(6, -3).front());
- EXPECT_TRUE(r.slice(6, -5).empty());
- EXPECT_EQ(next(cont.begin(), 6), r.slice(6, -5).begin());
-
- // Negative start, positive stop.
- EXPECT_TRUE(r.slice(-3, 6).empty());
- EXPECT_EQ(next(cont.begin(), 7), r.slice(-3, 6).begin());
- EXPECT_EQ(1, r.slice(-5, 6).size());
- EXPECT_EQ(5, r.slice(-5, 6).front());
-}
-
-TEST(Range, slice) {
- // -fsanitize=undefined complains about this, but only if optimizations are
- // enabled.
-#if 0
- test_slice<std::forward_list<int>>();
-#endif
- test_slice<std::list<int>>();
-// This doesn't build with libstdc++ 4.7
-#if 0
- test_slice<std::deque<int>>();
-#endif
-}
-
-// This test is flaky and I've yet to pin down why. Changing between
-// EXPECT_EQ(1, input.front()) and EXPECT_TRUE(input.front() == 1) makes it work
-// with VS 2012 in Debug mode. Clang on Linux seems to fail with -03 and -02 -g
-// -fsanitize=undefined.
-#if 0
-TEST(Range, istream_range) {
- std::istringstream stream("1 2 3 4 5");
- // MSVC interprets input as a function declaration if you don't declare start
- // and instead directly pass std::istream_iterator<int>(stream).
- auto start = std::istream_iterator<int>(stream);
- lld::range<std::istream_iterator<int>> input(
- start, std::istream_iterator<int>());
- EXPECT_TRUE(input.front() == 1);
- input.pop_front();
- EXPECT_TRUE(input.front() == 2);
- input.pop_front(2);
- EXPECT_TRUE(input.front() == 4);
- input.pop_front_upto(7);
- EXPECT_TRUE(input.empty());
-}
-#endif
-
-//! [algorithm using range]
-template <typename T> void partial_sum(T &container) {
- using lld::make_range;
- auto range = make_range(container);
- typename T::value_type sum = 0;
- // One would actually use a range-based for loop
- // in this case, but you get the idea:
- for (; !range.empty(); range.pop_front()) {
- sum += range.front();
- range.front() = sum;
- }
-}
-
-TEST(Range, user1) {
- std::vector<int> v(5, 2);
- partial_sum(v);
- EXPECT_EQ(8, v[3]);
-}
-//! [algorithm using range]
-
-//! [algorithm using ptr_range]
-void my_write(int fd, lld::range<const char *> buffer) {}
-
-TEST(Range, user2) {
- std::string s("Hello world");
- my_write(1, s);
-}
diff --git a/unittests/DriverTests/CMakeLists.txt b/unittests/DriverTests/CMakeLists.txt
index 0378e6164429..91d22ca19d72 100644
--- a/unittests/DriverTests/CMakeLists.txt
+++ b/unittests/DriverTests/CMakeLists.txt
@@ -1,12 +1,8 @@
add_lld_unittest(DriverTests
- UniversalDriverTest.cpp
- GnuLdDriverTest.cpp
DarwinLdDriverTest.cpp
)
target_link_libraries(DriverTests
lldDriver
- lldCOFF
- lldCore
lldMachO
)
diff --git a/unittests/DriverTests/DarwinLdDriverTest.cpp b/unittests/DriverTests/DarwinLdDriverTest.cpp
index e2809c44984d..ea7fcc7eafcb 100644
--- a/unittests/DriverTests/DarwinLdDriverTest.cpp
+++ b/unittests/DriverTests/DarwinLdDriverTest.cpp
@@ -12,23 +12,47 @@
///
//===----------------------------------------------------------------------===//
-#include "DriverTest.h"
+#include "lld/Driver/Driver.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"
#include "llvm/Support/MachO.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
using namespace llvm;
using namespace lld;
+namespace lld {
+namespace mach_o {
+bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx,
+ raw_ostream &diagnostics);
+}
+}
+
namespace {
-class DarwinLdParserTest
- : public ParserTest<DarwinLdDriver, MachOLinkingContext> {
+class DarwinLdParserTest : public testing::Test {
protected:
- const LinkingContext *linkingContext() override { return &_ctx; }
+ int inputFileCount() { return _ctx.getNodes().size(); }
+
+ std::string inputFile(int index) {
+ Node &node = *_ctx.getNodes()[index];
+ if (node.kind() == Node::Kind::File)
+ return cast<FileNode>(&node)->getFile()->path();
+ llvm_unreachable("not handling other types of input files");
+ }
+
+ bool parse(std::vector<const char *> args) {
+ args.insert(args.begin(), "ld");
+ std::string errorMessage;
+ raw_string_ostream os(errorMessage);
+ return mach_o::parse(args, _ctx, os);
+ }
+
+ MachOLinkingContext _ctx;
};
}
TEST_F(DarwinLdParserTest, Basic) {
- EXPECT_TRUE(parse("ld", "foo.o", "bar.o", "-arch", "i386", nullptr));
+ EXPECT_TRUE(parse({"foo.o", "bar.o", "-arch", "i386"}));
EXPECT_FALSE(_ctx.allowRemainingUndefines());
EXPECT_FALSE(_ctx.deadStrip());
EXPECT_EQ(2, inputFileCount());
@@ -37,204 +61,207 @@ TEST_F(DarwinLdParserTest, Basic) {
}
TEST_F(DarwinLdParserTest, Output) {
- EXPECT_TRUE(parse("ld", "-o", "my.out", "foo.o", "-arch", "i386", nullptr));
+ EXPECT_TRUE(parse({"-o", "my.out", "foo.o", "-arch", "i386"}));
EXPECT_EQ("my.out", _ctx.outputPath());
}
TEST_F(DarwinLdParserTest, Dylib) {
- EXPECT_TRUE(parse("ld", "-dylib", "foo.o", "-arch", "i386", nullptr));
+ EXPECT_TRUE(parse({"-dylib", "foo.o", "-arch", "i386"}));
EXPECT_EQ(llvm::MachO::MH_DYLIB, _ctx.outputMachOType());
}
TEST_F(DarwinLdParserTest, Relocatable) {
- EXPECT_TRUE(parse("ld", "-r", "foo.o", "-arch", "i386", nullptr));
+ EXPECT_TRUE(parse({"-r", "foo.o", "-arch", "i386"}));
EXPECT_EQ(llvm::MachO::MH_OBJECT, _ctx.outputMachOType());
}
TEST_F(DarwinLdParserTest, Bundle) {
- EXPECT_TRUE(parse("ld", "-bundle", "foo.o", "-arch", "i386", nullptr));
+ EXPECT_TRUE(parse({"-bundle", "foo.o", "-arch", "i386"}));
EXPECT_EQ(llvm::MachO::MH_BUNDLE, _ctx.outputMachOType());
}
TEST_F(DarwinLdParserTest, Preload) {
- EXPECT_TRUE(parse("ld", "-preload", "foo.o", "-arch", "i386", nullptr));
+ EXPECT_TRUE(parse({"-preload", "foo.o", "-arch", "i386"}));
EXPECT_EQ(llvm::MachO::MH_PRELOAD, _ctx.outputMachOType());
}
TEST_F(DarwinLdParserTest, Static) {
- EXPECT_TRUE(parse("ld", "-static", "foo.o", "-arch", "i386", nullptr));
+ EXPECT_TRUE(parse({"-static", "foo.o", "-arch", "i386"}));
EXPECT_EQ(llvm::MachO::MH_EXECUTE, _ctx.outputMachOType());
}
TEST_F(DarwinLdParserTest, Entry) {
- EXPECT_TRUE(parse("ld", "-e", "entryFunc", "foo.o", "-arch", "i386",nullptr));
+ EXPECT_TRUE(parse({"-e", "entryFunc", "foo.o", "-arch", "i386"}));
EXPECT_EQ("entryFunc", _ctx.entrySymbolName());
}
TEST_F(DarwinLdParserTest, DeadStrip) {
- EXPECT_TRUE(parse("ld", "-arch", "x86_64", "-dead_strip", "foo.o", nullptr));
+ EXPECT_TRUE(parse({"-arch", "x86_64", "-dead_strip", "foo.o"}));
EXPECT_TRUE(_ctx.deadStrip());
}
TEST_F(DarwinLdParserTest, DeadStripRootsExe) {
- EXPECT_TRUE(parse("ld", "-arch", "x86_64", "-dead_strip", "foo.o", nullptr));
+ EXPECT_TRUE(parse({"-arch", "x86_64", "-dead_strip", "foo.o"}));
EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
}
TEST_F(DarwinLdParserTest, DeadStripRootsDylib) {
- EXPECT_TRUE(parse("ld", "-arch", "x86_64", "-dylib", "-dead_strip", "foo.o",
- nullptr));
+ EXPECT_TRUE(parse({"-arch", "x86_64", "-dylib", "-dead_strip", "foo.o"}));
+ EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
+}
+
+TEST_F(DarwinLdParserTest, DeadStripRootsRelocatable) {
+ EXPECT_TRUE(parse({"-arch", "x86_64", "-r", "-dead_strip", "foo.o"}));
+ EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
+}
+
+TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicExe) {
+ EXPECT_TRUE(
+ parse({"-arch", "x86_64", "-dead_strip", "-export_dynamic", "foo.o"}));
EXPECT_TRUE(_ctx.globalsAreDeadStripRoots());
}
+TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicDylib) {
+ EXPECT_TRUE(parse({"-arch", "x86_64", "-dylib", "-dead_strip",
+ "-export_dynamic", "foo.o"}));
+ EXPECT_TRUE(_ctx.globalsAreDeadStripRoots());
+}
+
+TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicRelocatable) {
+ EXPECT_TRUE(parse(
+ {"-arch", "x86_64", "-r", "-dead_strip", "-export_dynamic", "foo.o"}));
+ EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
+}
+
TEST_F(DarwinLdParserTest, Arch) {
- EXPECT_TRUE(parse("ld", "-arch", "x86_64", "foo.o", nullptr));
+ EXPECT_TRUE(parse({"-arch", "x86_64", "foo.o"}));
EXPECT_EQ(MachOLinkingContext::arch_x86_64, _ctx.arch());
EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_X86_64, _ctx.getCPUType());
EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_X86_64_ALL, _ctx.getCPUSubType());
}
TEST_F(DarwinLdParserTest, Arch_x86) {
- EXPECT_TRUE(parse("ld", "-arch", "i386", "foo.o", nullptr));
+ EXPECT_TRUE(parse({"-arch", "i386", "foo.o"}));
EXPECT_EQ(MachOLinkingContext::arch_x86, _ctx.arch());
EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_I386, _ctx.getCPUType());
EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_X86_ALL, _ctx.getCPUSubType());
}
TEST_F(DarwinLdParserTest, Arch_armv6) {
- EXPECT_TRUE(parse("ld", "-arch", "armv6", "foo.o", nullptr));
+ EXPECT_TRUE(parse({"-arch", "armv6", "foo.o"}));
EXPECT_EQ(MachOLinkingContext::arch_armv6, _ctx.arch());
EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V6, _ctx.getCPUSubType());
}
TEST_F(DarwinLdParserTest, Arch_armv7) {
- EXPECT_TRUE(parse("ld", "-arch", "armv7", "foo.o", nullptr));
+ EXPECT_TRUE(parse({"-arch", "armv7", "foo.o"}));
EXPECT_EQ(MachOLinkingContext::arch_armv7, _ctx.arch());
EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V7, _ctx.getCPUSubType());
}
TEST_F(DarwinLdParserTest, Arch_armv7s) {
- EXPECT_TRUE(parse("ld", "-arch", "armv7s", "foo.o", nullptr));
+ EXPECT_TRUE(parse({"-arch", "armv7s", "foo.o"}));
EXPECT_EQ(MachOLinkingContext::arch_armv7s, _ctx.arch());
EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V7S, _ctx.getCPUSubType());
}
TEST_F(DarwinLdParserTest, MinMacOSX10_7) {
- EXPECT_TRUE(parse("ld", "-macosx_version_min", "10.7", "foo.o",
- "-arch", "x86_64", nullptr));
+ EXPECT_TRUE(
+ parse({"-macosx_version_min", "10.7", "foo.o", "-arch", "x86_64"}));
EXPECT_EQ(MachOLinkingContext::OS::macOSX, _ctx.os());
EXPECT_TRUE(_ctx.minOS("10.7", ""));
EXPECT_FALSE(_ctx.minOS("10.8", ""));
}
TEST_F(DarwinLdParserTest, MinMacOSX10_8) {
- EXPECT_TRUE(parse("ld", "-macosx_version_min", "10.8.3", "foo.o",
- "-arch", "x86_64", nullptr));
+ EXPECT_TRUE(
+ parse({"-macosx_version_min", "10.8.3", "foo.o", "-arch", "x86_64"}));
EXPECT_EQ(MachOLinkingContext::OS::macOSX, _ctx.os());
EXPECT_TRUE(_ctx.minOS("10.7", ""));
EXPECT_TRUE(_ctx.minOS("10.8", ""));
}
TEST_F(DarwinLdParserTest, iOS5) {
- EXPECT_TRUE(parse("ld", "-ios_version_min", "5.0", "foo.o",
- "-arch", "armv7", nullptr));
+ EXPECT_TRUE(parse({"-ios_version_min", "5.0", "foo.o", "-arch", "armv7"}));
EXPECT_EQ(MachOLinkingContext::OS::iOS, _ctx.os());
EXPECT_TRUE(_ctx.minOS("", "5.0"));
EXPECT_FALSE(_ctx.minOS("", "6.0"));
}
TEST_F(DarwinLdParserTest, iOS6) {
- EXPECT_TRUE(parse("ld", "-ios_version_min", "6.0", "foo.o", "-arch", "armv7",
- nullptr));
+ EXPECT_TRUE(parse({"-ios_version_min", "6.0", "foo.o", "-arch", "armv7"}));
EXPECT_EQ(MachOLinkingContext::OS::iOS, _ctx.os());
EXPECT_TRUE(_ctx.minOS("", "5.0"));
EXPECT_TRUE(_ctx.minOS("", "6.0"));
}
TEST_F(DarwinLdParserTest, iOS_Simulator5) {
- EXPECT_TRUE(parse("ld", "-ios_simulator_version_min", "5.0", "a.o",
- "-arch", "i386", nullptr));
+ EXPECT_TRUE(
+ parse({"-ios_simulator_version_min", "5.0", "a.o", "-arch", "i386"}));
EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _ctx.os());
EXPECT_TRUE(_ctx.minOS("", "5.0"));
EXPECT_FALSE(_ctx.minOS("", "6.0"));
}
TEST_F(DarwinLdParserTest, iOS_Simulator6) {
- EXPECT_TRUE(parse("ld", "-ios_simulator_version_min", "6.0", "a.o",
- "-arch", "i386", nullptr));
+ EXPECT_TRUE(
+ parse({"-ios_simulator_version_min", "6.0", "a.o", "-arch", "i386"}));
EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _ctx.os());
EXPECT_TRUE(_ctx.minOS("", "5.0"));
EXPECT_TRUE(_ctx.minOS("", "6.0"));
}
TEST_F(DarwinLdParserTest, compatibilityVersion) {
- EXPECT_TRUE(
- parse("ld", "-dylib", "-compatibility_version", "1.2.3", "a.o",
- "-arch", "i386",nullptr));
+ EXPECT_TRUE(parse(
+ {"-dylib", "-compatibility_version", "1.2.3", "a.o", "-arch", "i386"}));
EXPECT_EQ(_ctx.compatibilityVersion(), 0x10203U);
}
TEST_F(DarwinLdParserTest, compatibilityVersionInvalidType) {
- EXPECT_FALSE(parse("ld", "-bundle", "-compatibility_version", "1.2.3", "a.o",
- "-arch", "i386",nullptr));
+ EXPECT_FALSE(parse(
+ {"-bundle", "-compatibility_version", "1.2.3", "a.o", "-arch", "i386"}));
}
TEST_F(DarwinLdParserTest, compatibilityVersionInvalidValue) {
- EXPECT_FALSE(parse("ld", "-bundle", "-compatibility_version", "1,2,3", "a.o",
- "-arch", "i386", nullptr));
+ EXPECT_FALSE(parse(
+ {"-bundle", "-compatibility_version", "1,2,3", "a.o", "-arch", "i386"}));
}
TEST_F(DarwinLdParserTest, currentVersion) {
EXPECT_TRUE(
- parse("ld", "-dylib", "-current_version", "1.2.3", "a.o", "-arch", "i386",
- nullptr));
+ parse({"-dylib", "-current_version", "1.2.3", "a.o", "-arch", "i386"}));
EXPECT_EQ(_ctx.currentVersion(), 0x10203U);
}
TEST_F(DarwinLdParserTest, currentVersionInvalidType) {
EXPECT_FALSE(
- parse("ld", "-bundle", "-current_version", "1.2.3", "a.o",
- "-arch", "i386", nullptr));
+ parse({"-bundle", "-current_version", "1.2.3", "a.o", "-arch", "i386"}));
}
TEST_F(DarwinLdParserTest, currentVersionInvalidValue) {
EXPECT_FALSE(
- parse("ld", "-bundle", "-current_version", "1,2,3", "a.o",
- "-arch", "i386", nullptr));
+ parse({"-bundle", "-current_version", "1,2,3", "a.o", "-arch", "i386"}));
}
TEST_F(DarwinLdParserTest, bundleLoader) {
EXPECT_TRUE(
- parse("ld", "-bundle", "-bundle_loader", "/bin/ls", "a.o",
- "-arch", "i386", nullptr));
+ parse({"-bundle", "-bundle_loader", "/bin/ls", "a.o", "-arch", "i386"}));
EXPECT_EQ(_ctx.bundleLoader(), "/bin/ls");
}
TEST_F(DarwinLdParserTest, bundleLoaderInvalidType) {
- EXPECT_FALSE(parse("ld", "-bundle_loader", "/bin/ls", "a.o", "-arch", "i386",
- nullptr));
+ EXPECT_FALSE(parse({"-bundle_loader", "/bin/ls", "a.o", "-arch", "i386"}));
}
TEST_F(DarwinLdParserTest, deadStrippableDylib) {
EXPECT_TRUE(
- parse("ld", "-dylib", "-mark_dead_strippable_dylib", "a.o",
- "-arch", "i386", nullptr));
+ parse({"-dylib", "-mark_dead_strippable_dylib", "a.o", "-arch", "i386"}));
EXPECT_EQ(true, _ctx.deadStrippableDylib());
}
TEST_F(DarwinLdParserTest, deadStrippableDylibInvalidType) {
- EXPECT_FALSE(parse("ld", "-mark_dead_strippable_dylib", "a.o",
- "-arch", "i386", nullptr));
-}
-
-TEST_F(DarwinLdParserTest, llvmOptions) {
- EXPECT_TRUE(parse("ld", "-mllvm", "-enable-tbaa", "-mllvm", "-enable-misched", "a.o",
- "-arch", "i386", nullptr));
- const std::vector<const char *> &options = _ctx.llvmOptions();
- EXPECT_EQ(options.size(), 2UL);
- EXPECT_EQ(strcmp(options[0],"-enable-tbaa"), 0);
- EXPECT_EQ(strcmp(options[1],"-enable-misched"), 0);
+ EXPECT_FALSE(parse({"-mark_dead_strippable_dylib", "a.o", "-arch", "i386"}));
}
diff --git a/unittests/DriverTests/DriverTest.h b/unittests/DriverTests/DriverTest.h
deleted file mode 100644
index 65af7cac3139..000000000000
--- a/unittests/DriverTests/DriverTest.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- lld/unittest/DriverTest.h ------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Driver/Driver.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-#include <stdarg.h>
-
-namespace {
-
-using namespace llvm;
-using namespace lld;
-
-template<typename D, typename T>
-class ParserTest : public testing::Test {
-protected:
-
- virtual const LinkingContext *linkingContext() = 0;
-
- std::string &errorMessage() { return _errorMessage; }
-
- // Convenience method for getting number of input files.
- int inputFileCount() {
- return linkingContext()->getNodes().size();
- }
-
- // Convenience method for getting i'th input files name.
- std::string inputFile(int index) {
- Node &node = *linkingContext()->getNodes()[index];
- if (node.kind() == Node::Kind::File)
- return cast<FileNode>(&node)->getFile()->path();
- llvm_unreachable("not handling other types of input files");
- }
-
- // For unit tests to call driver with various command lines.
- bool parse(const char *args, ...) {
- // Construct command line options from varargs.
- std::vector<const char *> vec;
- vec.push_back(args);
- va_list ap;
- va_start(ap, args);
- while (const char *arg = va_arg(ap, const char *))
- vec.push_back(arg);
- va_end(ap);
-
- // Call the parser.
- raw_string_ostream os(_errorMessage);
- return D::parse(vec, _ctx, os);
- }
-
- T _ctx;
- std::string _errorMessage;
-};
-
-}
diff --git a/unittests/DriverTests/GnuLdDriverTest.cpp b/unittests/DriverTests/GnuLdDriverTest.cpp
deleted file mode 100644
index 13d20a4411a1..000000000000
--- a/unittests/DriverTests/GnuLdDriverTest.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-//===- lld/unittest/GnuLdDriverTest.cpp -----------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief GNU ld driver tests.
-///
-//===----------------------------------------------------------------------===//
-
-#include "DriverTest.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Support/MemoryBuffer.h"
-
-using namespace llvm;
-using namespace lld;
-
-namespace {
-
-class GnuLdParserTest
- : public ParserTest<GnuLdDriver, std::unique_ptr<ELFLinkingContext>> {
-protected:
- const LinkingContext *linkingContext() override { return _ctx.get(); }
-};
-
-class LinkerScriptTest : public testing::Test {
-protected:
- void SetUp() override {
- llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
- _ctx = GnuLdDriver::createELFLinkingContext(triple);
- }
-
- void parse(StringRef script, bool nostdlib = false) {
- std::unique_ptr<MemoryBuffer> mb = MemoryBuffer::getMemBuffer(
- script, "foo.so");
- std::string s;
- raw_string_ostream out(s);
- std::error_code ec =
- GnuLdDriver::evalLinkerScript(*_ctx, std::move(mb), out, nostdlib);
- EXPECT_FALSE(ec);
- }
-
- std::unique_ptr<ELFLinkingContext> _ctx;
-};
-
-} // anonymous namespace
-
-TEST_F(GnuLdParserTest, Empty) {
- EXPECT_FALSE(parse("ld", nullptr));
- EXPECT_EQ(linkingContext(), nullptr);
- EXPECT_EQ("No input files\n", errorMessage());
-}
-
-// -o
-
-TEST_F(GnuLdParserTest, Output) {
- EXPECT_TRUE(parse("ld", "a.o", "-o", "foo", nullptr));
- EXPECT_EQ("foo", _ctx->outputPath());
-}
-
-TEST_F(GnuLdParserTest, OutputDefault) {
- EXPECT_TRUE(parse("ld", "abc.o", nullptr));
- EXPECT_EQ("a.out", _ctx->outputPath());
-}
-
-// --noinhibit-exec
-
-TEST_F(GnuLdParserTest, NoinhibitExec) {
- EXPECT_TRUE(parse("ld", "a.o", "--noinhibit-exec", nullptr));
- EXPECT_TRUE(_ctx->allowRemainingUndefines());
-}
-
-// --entry
-
-TEST_F(GnuLdParserTest, Entry) {
- EXPECT_TRUE(parse("ld", "a.o", "--entry", "foo", nullptr));
- EXPECT_EQ("foo", _ctx->entrySymbolName());
-}
-
-TEST_F(GnuLdParserTest, EntryShort) {
- EXPECT_TRUE(parse("ld", "a.o", "-e", "foo", nullptr));
- EXPECT_EQ("foo", _ctx->entrySymbolName());
-}
-
-TEST_F(GnuLdParserTest, EntryJoined) {
- EXPECT_TRUE(parse("ld", "a.o", "--entry=foo", nullptr));
- EXPECT_EQ("foo", _ctx->entrySymbolName());
-}
-
-// --export-dynamic
-
-TEST_F(GnuLdParserTest, ExportDynamic) {
- EXPECT_TRUE(parse("ld", "a.o", "--export-dynamic", nullptr));
- EXPECT_TRUE(_ctx->shouldExportDynamic());
-}
-
-TEST_F(GnuLdParserTest, NoExportDynamic) {
- EXPECT_TRUE(parse("ld", "a.o", "--no-export-dynamic", nullptr));
- EXPECT_FALSE(_ctx->shouldExportDynamic());
-}
-
-// --init
-
-TEST_F(GnuLdParserTest, Init) {
- EXPECT_TRUE(parse("ld", "a.o", "-init", "foo", "-init", "bar", nullptr));
- EXPECT_EQ("bar", _ctx->initFunction());
-}
-
-TEST_F(GnuLdParserTest, InitJoined) {
- EXPECT_TRUE(parse("ld", "a.o", "-init=foo", nullptr));
- EXPECT_EQ("foo", _ctx->initFunction());
-}
-
-// --soname
-
-TEST_F(GnuLdParserTest, SOName) {
- EXPECT_TRUE(parse("ld", "a.o", "--soname=foo", nullptr));
- EXPECT_EQ("foo", _ctx->sharedObjectName());
-}
-
-TEST_F(GnuLdParserTest, SONameSingleDash) {
- EXPECT_TRUE(parse("ld", "a.o", "-soname=foo", nullptr));
- EXPECT_EQ("foo", _ctx->sharedObjectName());
-}
-
-TEST_F(GnuLdParserTest, SONameH) {
- EXPECT_TRUE(parse("ld", "a.o", "-h", "foo", nullptr));
- EXPECT_EQ("foo", _ctx->sharedObjectName());
-}
-
-// -rpath
-
-TEST_F(GnuLdParserTest, Rpath) {
- EXPECT_TRUE(parse("ld", "a.o", "-rpath", "foo:bar", nullptr));
- EXPECT_EQ(2, _ctx->getRpathList().size());
- EXPECT_EQ("foo", _ctx->getRpathList()[0]);
- EXPECT_EQ("bar", _ctx->getRpathList()[1]);
-}
-
-TEST_F(GnuLdParserTest, RpathEq) {
- EXPECT_TRUE(parse("ld", "a.o", "-rpath=foo", nullptr));
- EXPECT_EQ(1, _ctx->getRpathList().size());
- EXPECT_EQ("foo", _ctx->getRpathList()[0]);
-}
-
-// --defsym
-
-TEST_F(GnuLdParserTest, DefsymDecimal) {
- EXPECT_TRUE(parse("ld", "a.o", "--defsym=sym=1000", nullptr));
- assert(_ctx.get());
- auto map = _ctx->getAbsoluteSymbols();
- EXPECT_EQ((size_t)1, map.size());
- EXPECT_EQ((uint64_t)1000, map["sym"]);
-}
-
-TEST_F(GnuLdParserTest, DefsymHexadecimal) {
- EXPECT_TRUE(parse("ld", "a.o", "--defsym=sym=0x1000", nullptr));
- auto map = _ctx->getAbsoluteSymbols();
- EXPECT_EQ((size_t)1, map.size());
- EXPECT_EQ((uint64_t)0x1000, map["sym"]);
-}
-
-TEST_F(GnuLdParserTest, DefsymAlias) {
- EXPECT_TRUE(parse("ld", "a.o", "--defsym=sym=abc", nullptr));
- auto map = _ctx->getAliases();
- EXPECT_EQ((size_t)1, map.size());
- EXPECT_EQ("abc", map["sym"]);
-}
-
-TEST_F(GnuLdParserTest, DefsymOctal) {
- EXPECT_TRUE(parse("ld", "a.o", "--defsym=sym=0777", nullptr));
- auto map = _ctx->getAbsoluteSymbols();
- EXPECT_EQ((size_t)1, map.size());
- EXPECT_EQ((uint64_t)0777, map["sym"]);
-}
-
-TEST_F(GnuLdParserTest, DefsymMisssingSymbol) {
- EXPECT_FALSE(parse("ld", "a.o", "--defsym==0", nullptr));
-}
-
-TEST_F(GnuLdParserTest, DefsymMisssingValue) {
- EXPECT_FALSE(parse("ld", "a.o", "--defsym=sym=", nullptr));
-}
-
-// --as-needed
-
-TEST_F(GnuLdParserTest, AsNeeded) {
- EXPECT_TRUE(parse("ld", "a.o", "--as-needed", "b.o", "c.o",
- "--no-as-needed", "d.o", nullptr));
- std::vector<std::unique_ptr<Node>> &nodes = _ctx->getNodes();
- EXPECT_EQ((size_t)4, nodes.size());
- EXPECT_FALSE(cast<FileNode>(nodes[0].get())->asNeeded());
- EXPECT_TRUE(cast<FileNode>(nodes[1].get())->asNeeded());
- EXPECT_TRUE(cast<FileNode>(nodes[2].get())->asNeeded());
- EXPECT_FALSE(cast<FileNode>(nodes[3].get())->asNeeded());
-}
-
-// Emulation
-
-TEST_F(GnuLdParserTest, Emulation) {
- EXPECT_TRUE(parse("mips-linux-gnu-ld", "a.o", "-m", "elf64ltsmip", nullptr));
- EXPECT_EQ(Triple::mips64el, _ctx->getTriple().getArch());
- EXPECT_TRUE(
- parse("mips64el-linux-gnu-ld", "a.o", "-m", "elf32btsmip", nullptr));
- EXPECT_EQ(Triple::mips, _ctx->getTriple().getArch());
- EXPECT_TRUE(
- parse("mipsel-linux-gnu-ld", "a.o", "-m", "elf32btsmipn32", nullptr));
- EXPECT_EQ(Triple::mips, _ctx->getTriple().getArch());
- EXPECT_TRUE(
- parse("mips-linux-gnu-ld", "a.o", "-m", "elf32ltsmipn32", nullptr));
- EXPECT_EQ(Triple::mipsel, _ctx->getTriple().getArch());
-}
-
-// Linker script
-
-TEST_F(LinkerScriptTest, Input) {
- parse("INPUT(/x /y)");
- std::vector<std::unique_ptr<Node>> &nodes = _ctx->getNodes();
- EXPECT_EQ((size_t)2, nodes.size());
- EXPECT_EQ("/x", cast<FileNode>(nodes[0].get())->getFile()->path());
- EXPECT_EQ("/y", cast<FileNode>(nodes[1].get())->getFile()->path());
-}
-
-TEST_F(LinkerScriptTest, Group) {
- parse("GROUP(/x /y)");
- std::vector<std::unique_ptr<Node>> &nodes = _ctx->getNodes();
- EXPECT_EQ((size_t)3, nodes.size());
- EXPECT_EQ("/x", cast<FileNode>(nodes[0].get())->getFile()->path());
- EXPECT_EQ("/y", cast<FileNode>(nodes[1].get())->getFile()->path());
- EXPECT_EQ(2, cast<GroupEnd>(nodes[2].get())->getSize());
-}
-
-TEST_F(LinkerScriptTest, SearchDir) {
- parse("SEARCH_DIR(\"/foo/bar\")");
- std::vector<StringRef> paths = _ctx->getSearchPaths();
- EXPECT_EQ((size_t)1, paths.size());
- EXPECT_EQ("/foo/bar", paths[0]);
-}
-
-TEST_F(LinkerScriptTest, Entry) {
- parse("ENTRY(blah)");
- EXPECT_EQ("blah", _ctx->entrySymbolName());
-}
-
-TEST_F(LinkerScriptTest, Output) {
- parse("OUTPUT(\"/path/to/output\")");
- EXPECT_EQ("/path/to/output", _ctx->outputPath());
-}
-
-// Test that search paths are ignored when nostdlib is set.
-TEST_F(LinkerScriptTest, IgnoreSearchDirNoStdLib) {
- parse("SEARCH_DIR(\"/foo/bar\")", true /*nostdlib*/);
- std::vector<StringRef> paths = _ctx->getSearchPaths();
- EXPECT_EQ((size_t)0, paths.size());
-}
-
-TEST_F(LinkerScriptTest, ExprEval) {
- parse("SECTIONS { symbol = 0x4000 + 0x40; \n"
- ". = (symbol >= 0x4040)? (0x5001 * 2 & 0xFFF0) << 1 : 0}");
-
- EXPECT_EQ((size_t)1, _ctx->linkerScriptSema().getLinkerScripts().size());
-
- script::LinkerScript *ls =
- _ctx->linkerScriptSema().getLinkerScripts()[0]->get();
- EXPECT_EQ((size_t)1, ls->_commands.size());
-
- auto *secs = dyn_cast<const script::Sections>(*ls->_commands.begin());
- EXPECT_TRUE(secs != nullptr);
- EXPECT_EQ(2, secs->end() - secs->begin());
-
- auto command = secs->begin();
- auto *sa1 = dyn_cast<const script::SymbolAssignment>(*command);
- EXPECT_TRUE(sa1 != nullptr);
- EXPECT_EQ(script::SymbolAssignment::Simple, sa1->assignmentKind());
- EXPECT_EQ(script::SymbolAssignment::Default, sa1->assignmentVisibility());
-
- ++command;
- auto *sa2 = dyn_cast<const script::SymbolAssignment>(*command);
- EXPECT_TRUE(sa2 != nullptr);
- EXPECT_EQ(script::SymbolAssignment::Simple, sa2->assignmentKind());
- EXPECT_EQ(script::SymbolAssignment::Default, sa2->assignmentVisibility());
-
- script::Expression::SymbolTableTy mySymbolTable;
- auto ans = sa1->expr()->evalExpr(mySymbolTable);
- EXPECT_FALSE(ans.getError());
- int64_t result = *ans;
- EXPECT_EQ(0x4040, result);
- mySymbolTable[sa1->symbol()] = result;
-
- auto ans2 = sa2->expr()->evalExpr(mySymbolTable);
- EXPECT_FALSE(ans2.getError());
- result = *ans2;
- EXPECT_EQ(0x14000, result);
- EXPECT_EQ(0, sa2->symbol().compare(StringRef(".")));
-}
diff --git a/unittests/DriverTests/UniversalDriverTest.cpp b/unittests/DriverTests/UniversalDriverTest.cpp
deleted file mode 100644
index 0a464d3038c6..000000000000
--- a/unittests/DriverTests/UniversalDriverTest.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- lld/unittest/UniversalDriverTest.cpp -------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Universal driver tests that depend on the value of argv[0].
-///
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-#include "lld/Driver/Driver.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace lld;
-
-TEST(UniversalDriver, flavor) {
- const char *args[] = {"ld", "-flavor", "old-gnu"};
-
- std::string diags;
- raw_string_ostream os(diags);
- UniversalDriver::link(args, os);
- EXPECT_EQ(os.str().find("failed to determine driver flavor"),
- std::string::npos);
- EXPECT_NE(os.str().find("No input files"),
- std::string::npos);
-}
diff --git a/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp b/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp
index 6827a732fbd8..a3c445a93619 100644
--- a/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp
+++ b/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp
@@ -9,13 +9,17 @@
#include "gtest/gtest.h"
#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MachO.h"
-#include <assert.h>
-#include <vector>
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <cstdint>
+#include <memory>
using llvm::StringRef;
using llvm::MemoryBuffer;
-using llvm::ErrorOr;
using namespace lld::mach_o::normalized;
using namespace llvm::MachO;
@@ -24,7 +28,7 @@ static std::unique_ptr<NormalizedFile>
fromBinary(const uint8_t bytes[], unsigned length, StringRef archStr) {
StringRef sr((const char*)bytes, length);
std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(sr, "", false));
- ErrorOr<std::unique_ptr<NormalizedFile>> r =
+ llvm::Expected<std::unique_ptr<NormalizedFile>> r =
lld::mach_o::normalized::readBinary(
mb, lld::MachOLinkingContext::archFromName(archStr));
EXPECT_FALSE(!r);
@@ -75,7 +79,6 @@ TEST(BinaryReaderTest, empty_obj_x86_64) {
EXPECT_TRUE(f->undefinedSymbols.empty());
}
-
TEST(BinaryReaderTest, empty_obj_x86) {
FILEBYTES = {
0xce, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x00,
@@ -107,7 +110,6 @@ TEST(BinaryReaderTest, empty_obj_x86) {
EXPECT_TRUE(f->undefinedSymbols.empty());
}
-
TEST(BinaryReaderTest, empty_obj_ppc) {
FILEBYTES = {
0xfe, 0xed, 0xfa, 0xce, 0x00, 0x00, 0x00, 0x12,
@@ -139,7 +141,6 @@ TEST(BinaryReaderTest, empty_obj_ppc) {
EXPECT_TRUE(f->undefinedSymbols.empty());
}
-
TEST(BinaryReaderTest, empty_obj_armv7) {
FILEBYTES = {
0xce, 0xfa, 0xed, 0xfe, 0x0c, 0x00, 0x00, 0x00,
@@ -326,7 +327,6 @@ TEST(BinaryReaderTest, hello_obj_x86_64) {
EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
}
-
TEST(BinaryReaderTest, hello_obj_x86) {
FILEBYTES = {
0xCE, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x00,
@@ -458,7 +458,6 @@ TEST(BinaryReaderTest, hello_obj_x86) {
EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
}
-
TEST(BinaryReaderTest, hello_obj_armv7) {
FILEBYTES = {
0xCE, 0xFA, 0xED, 0xFE, 0x0C, 0x00, 0x00, 0x00,
@@ -600,7 +599,6 @@ TEST(BinaryReaderTest, hello_obj_armv7) {
EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
}
-
TEST(BinaryReaderTest, hello_obj_ppc) {
FILEBYTES = {
0xFE, 0xED, 0xFA, 0xCE, 0x00, 0x00, 0x00, 0x12,
@@ -743,6 +741,9 @@ TEST(BinaryReaderTest, hello_obj_ppc) {
EXPECT_EQ(printfLabel.type, N_UNDF);
EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
- writeBinary(*f, "/tmp/foo.o");
-
+ auto ec = writeBinary(*f, "/tmp/foo.o");
+ // FIXME: We want to do EXPECT_FALSE(ec) but that fails on some Windows bots,
+ // probably due to /tmp not being available.
+ // For now just consume the error without checking it.
+ consumeError(std::move(ec));
}
diff --git a/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp b/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
index 87c527233cb1..f44950a8d5ab 100644
--- a/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
+++ b/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
@@ -35,7 +35,7 @@ static void fromBinary(StringRef path, std::unique_ptr<MemoryBuffer> &mb,
EXPECT_FALSE(ec);
mb = std::move(mbOrErr.get());
- ErrorOr<std::unique_ptr<NormalizedFile>> r =
+ llvm::Expected<std::unique_ptr<NormalizedFile>> r =
lld::mach_o::normalized::readBinary(
mb, lld::MachOLinkingContext::archFromName(archStr));
EXPECT_FALSE(!r);
@@ -148,8 +148,8 @@ TEST(BinaryWriterTest, obj_relocs_x86_64) {
std::error_code ec =
llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
EXPECT_FALSE(ec);
- ec = writeBinary(f, tmpFl);
- EXPECT_FALSE(ec);
+ llvm::Error ec2 = writeBinary(f, tmpFl);
+ EXPECT_FALSE(ec2);
}
std::unique_ptr<MemoryBuffer> bufferOwner;
@@ -260,8 +260,8 @@ TEST(BinaryWriterTest, obj_relocs_x86) {
std::error_code ec =
llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
EXPECT_FALSE(ec);
- ec = writeBinary(f, tmpFl);
- EXPECT_FALSE(ec);
+ llvm::Error ec2 = writeBinary(f, tmpFl);
+ EXPECT_FALSE(ec2);
}
std::unique_ptr<MemoryBuffer> bufferOwner;
std::unique_ptr<NormalizedFile> f2;
@@ -378,8 +378,8 @@ TEST(BinaryWriterTest, obj_relocs_armv7) {
std::error_code ec =
llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
EXPECT_FALSE(ec);
- ec = writeBinary(f, tmpFl);
- EXPECT_FALSE(ec);
+ llvm::Error ec2 = writeBinary(f, tmpFl);
+ EXPECT_FALSE(ec2);
}
std::unique_ptr<MemoryBuffer> bufferOwner;
std::unique_ptr<NormalizedFile> f2;
@@ -534,8 +534,8 @@ TEST(BinaryWriterTest, obj_relocs_ppc) {
std::error_code ec =
llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
EXPECT_FALSE(ec);
- ec = writeBinary(f, tmpFl);
- EXPECT_FALSE(ec);
+ llvm::Error ec2 = writeBinary(f, tmpFl);
+ EXPECT_FALSE(ec2);
}
std::unique_ptr<MemoryBuffer> bufferOwner;
std::unique_ptr<NormalizedFile> f2;
diff --git a/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp b/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp
index 7def86c87929..8205ea97520a 100644
--- a/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp
+++ b/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp
@@ -9,11 +9,17 @@
#include "gtest/gtest.h"
#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
+#include "lld/Core/Atom.h"
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MachO.h"
-#include <assert.h>
-#include <vector>
-
-using llvm::ErrorOr;
+#include "llvm/Support/YAMLTraits.h"
+#include <cstdint>
+#include <memory>
using namespace lld::mach_o::normalized;
using namespace llvm::MachO;
@@ -21,7 +27,7 @@ using namespace llvm::MachO;
TEST(ToAtomsTest, empty_obj_x86_64) {
NormalizedFile f;
f.arch = lld::MachOLinkingContext::arch_x86_64;
- ErrorOr<std::unique_ptr<const lld::File>> atom_f =
+ llvm::Expected<std::unique_ptr<const lld::File>> atom_f =
normalizedToAtoms(f, "", false);
EXPECT_FALSE(!atom_f);
EXPECT_EQ(0U, (*atom_f)->defined().size());
@@ -61,7 +67,7 @@ TEST(ToAtomsTest, basic_obj_x86_64) {
bazSymbol.value = 3;
f.localSymbols.push_back(bazSymbol);
- ErrorOr<std::unique_ptr<const lld::File>> atom_f =
+ llvm::Expected<std::unique_ptr<const lld::File>> atom_f =
normalizedToAtoms(f, "", false);
EXPECT_FALSE(!atom_f);
const lld::File &file = **atom_f;
diff --git a/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp b/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
index d13e360b41a5..e41b7ecd801c 100644
--- a/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
+++ b/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
@@ -9,22 +9,27 @@
#include "gtest/gtest.h"
#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MachO.h"
-#include <assert.h>
-#include <vector>
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <memory>
+#include <system_error>
+#include <string>
using llvm::StringRef;
using llvm::MemoryBuffer;
-using llvm::ErrorOr;
using lld::mach_o::normalized::NormalizedFile;
using lld::mach_o::normalized::Symbol;
using lld::mach_o::normalized::Section;
using lld::mach_o::normalized::Relocation;
-
static std::unique_ptr<NormalizedFile> fromYAML(StringRef str) {
std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(str));
- ErrorOr<std::unique_ptr<NormalizedFile>> r
+ llvm::Expected<std::unique_ptr<NormalizedFile>> r
= lld::mach_o::normalized::readYaml(mb);
EXPECT_FALSE(!r);
return std::move(*r);
@@ -36,7 +41,6 @@ static void toYAML(const NormalizedFile &f, std::string &out) {
EXPECT_TRUE(!ec);
}
-
// ppc is no longer supported, but it is here to test endianness handling.
TEST(ObjectFileYAML, empty_ppc) {
std::unique_ptr<NormalizedFile> f = fromYAML(
@@ -134,7 +138,6 @@ TEST(ObjectFileYAML, empty_armv7s) {
EXPECT_TRUE(f->undefinedSymbols.empty());
}
-
TEST(ObjectFileYAML, roundTrip) {
std::string intermediate;
{
@@ -157,7 +160,6 @@ TEST(ObjectFileYAML, roundTrip) {
}
}
-
TEST(ObjectFileYAML, oneSymbol) {
std::unique_ptr<NormalizedFile> f = fromYAML(
"---\n"
@@ -186,7 +188,6 @@ TEST(ObjectFileYAML, oneSymbol) {
EXPECT_EQ((uint64_t)sym.value, 0x100ULL);
}
-
TEST(ObjectFileYAML, oneSection) {
std::unique_ptr<NormalizedFile> f = fromYAML(
"---\n"
@@ -220,7 +221,6 @@ TEST(ObjectFileYAML, oneSection) {
EXPECT_EQ((int)(sect.content[1]), 0x90);
}
-
TEST(ObjectFileYAML, hello_x86_64) {
std::unique_ptr<NormalizedFile> f = fromYAML(
"---\n"
@@ -349,7 +349,6 @@ TEST(ObjectFileYAML, hello_x86_64) {
EXPECT_EQ((uint64_t)sym3.value, 0x0ULL);
}
-
TEST(ObjectFileYAML, hello_x86) {
std::unique_ptr<NormalizedFile> f = fromYAML(
"---\n"
@@ -607,8 +606,6 @@ TEST(ObjectFileYAML, hello_armv6) {
EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
}
-
-
TEST(ObjectFileYAML, hello_armv7) {
std::unique_ptr<NormalizedFile> f = fromYAML(
"---\n"